security/nss/lib/crmf/cmmfchal.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/lib/crmf/cmmfchal.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,290 @@
     1.4 +/* -*- Mode: C; tab-width: 8 -*-*/
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "cmmf.h"
    1.10 +#include "cmmfi.h"
    1.11 +#include "sechash.h"
    1.12 +#include "genname.h"
    1.13 +#include "pk11func.h"
    1.14 +#include "cert.h"
    1.15 +#include "secitem.h"
    1.16 +#include "secmod.h"
    1.17 +#include "keyhi.h"
    1.18 +
    1.19 +static int
    1.20 +cmmf_create_witness_and_challenge(PLArenaPool     *poolp,
    1.21 +				  CMMFChallenge   *challenge,
    1.22 +				  long             inRandom,
    1.23 +				  SECItem         *senderDER,
    1.24 +				  SECKEYPublicKey *inPubKey,
    1.25 +				  void            *passwdArg)
    1.26 +{
    1.27 +    SECItem       *encodedRandNum;
    1.28 +    SECItem        encodedRandStr = {siBuffer, NULL, 0};
    1.29 +    SECItem       *dummy;
    1.30 +    unsigned char *randHash, *senderHash, *encChal=NULL;
    1.31 +    unsigned       modulusLen = 0;
    1.32 +    SECStatus      rv = SECFailure;
    1.33 +    CMMFRand       randStr= { {siBuffer, NULL, 0}, {siBuffer, NULL, 0}};
    1.34 +    PK11SlotInfo  *slot;
    1.35 +    PK11SymKey    *symKey = NULL;
    1.36 +    CK_OBJECT_HANDLE id;
    1.37 +    CERTSubjectPublicKeyInfo *spki = NULL;
    1.38 +
    1.39 +    
    1.40 +    encodedRandNum = SEC_ASN1EncodeInteger(poolp, &challenge->randomNumber,
    1.41 +					   inRandom);
    1.42 +    encodedRandNum = &challenge->randomNumber;
    1.43 +    randHash   = PORT_ArenaNewArray(poolp, unsigned char, SHA1_LENGTH);
    1.44 +    senderHash = PORT_ArenaNewArray(poolp, unsigned char, SHA1_LENGTH);
    1.45 +    if (randHash == NULL) {
    1.46 +        goto loser;
    1.47 +    }
    1.48 +    rv = PK11_HashBuf(SEC_OID_SHA1, randHash, encodedRandNum->data, 
    1.49 +		      (PRUint32)encodedRandNum->len);
    1.50 +    if (rv != SECSuccess) {
    1.51 +        goto loser;
    1.52 +    }
    1.53 +    rv = PK11_HashBuf(SEC_OID_SHA1, senderHash, senderDER->data,
    1.54 +		      (PRUint32)senderDER->len);
    1.55 +    if (rv != SECSuccess) {
    1.56 +        goto loser;
    1.57 +    }
    1.58 +    challenge->witness.data = randHash;
    1.59 +    challenge->witness.len  = SHA1_LENGTH;
    1.60 +
    1.61 +    randStr.integer    = *encodedRandNum;
    1.62 +    randStr.senderHash.data = senderHash;
    1.63 +    randStr.senderHash.len  = SHA1_LENGTH;
    1.64 +    dummy = SEC_ASN1EncodeItem(NULL, &encodedRandStr, &randStr, 
    1.65 +			       CMMFRandTemplate);
    1.66 +    if (dummy != &encodedRandStr) {
    1.67 +        rv = SECFailure;
    1.68 +        goto loser;
    1.69 +    }
    1.70 +    /* XXXX Now I have to encrypt encodedRandStr and stash it away. */
    1.71 +    modulusLen = SECKEY_PublicKeyStrength(inPubKey);
    1.72 +    encChal = PORT_ArenaNewArray(poolp, unsigned char, modulusLen);
    1.73 +    if (encChal == NULL) {
    1.74 +        rv = SECFailure;
    1.75 +        goto loser;
    1.76 +    }
    1.77 +    slot =PK11_GetBestSlotWithAttributes(CKM_RSA_PKCS, CKF_WRAP, 0, passwdArg);
    1.78 +    if (slot == NULL) {
    1.79 +        rv = SECFailure;
    1.80 +        goto loser;
    1.81 +    }
    1.82 +    id = PK11_ImportPublicKey(slot, inPubKey, PR_FALSE);
    1.83 +    /* In order to properly encrypt the data, we import as a symmetric
    1.84 +     * key, and then wrap that key.  That in essence encrypts the data.
    1.85 +     * This is the method recommended in the PK11 world in order
    1.86 +     * to prevent threading issues as well as breaking any other semantics
    1.87 +     * the PK11 libraries depend on.
    1.88 +     */
    1.89 +    symKey = PK11_ImportSymKey(slot, CKM_RSA_PKCS, PK11_OriginGenerated,
    1.90 +			       CKA_VALUE, &encodedRandStr, passwdArg);
    1.91 +    if (symKey == NULL) {
    1.92 +        rv = SECFailure;
    1.93 +	goto loser;
    1.94 +    }
    1.95 +    challenge->challenge.data = encChal;
    1.96 +    challenge->challenge.len  = modulusLen;
    1.97 +    rv = PK11_PubWrapSymKey(CKM_RSA_PKCS, inPubKey, symKey, 
    1.98 +			    &challenge->challenge);
    1.99 +    PK11_FreeSlot(slot);
   1.100 +    if (rv != SECSuccess) {
   1.101 +	goto loser;
   1.102 +    }
   1.103 +    rv = SECITEM_CopyItem(poolp, &challenge->senderDER, senderDER);
   1.104 +    crmf_get_public_value(inPubKey, &challenge->key);
   1.105 +    /* Fall through */
   1.106 + loser:
   1.107 +    if (spki != NULL) {
   1.108 +        SECKEY_DestroySubjectPublicKeyInfo(spki);
   1.109 +    }
   1.110 +    if (encodedRandStr.data != NULL) {
   1.111 +        PORT_Free(encodedRandStr.data);
   1.112 +    }
   1.113 +    if (encodedRandNum != NULL) {
   1.114 +        SECITEM_FreeItem(encodedRandNum, PR_TRUE);
   1.115 +    }
   1.116 +    if (symKey != NULL) {
   1.117 +        PK11_FreeSymKey(symKey);
   1.118 +    }
   1.119 +    return rv;
   1.120 +}
   1.121 +
   1.122 +static SECStatus
   1.123 +cmmf_create_first_challenge(CMMFPOPODecKeyChallContent *challContent, 
   1.124 +			    long                        inRandom, 
   1.125 +			    SECItem                    *senderDER, 
   1.126 +			    SECKEYPublicKey            *inPubKey,
   1.127 +			    void                       *passwdArg)
   1.128 +{
   1.129 +    SECOidData     *oidData;
   1.130 +    CMMFChallenge  *challenge;
   1.131 +    SECAlgorithmID *algId;
   1.132 +    PLArenaPool    *poolp;
   1.133 +    SECStatus       rv;
   1.134 +
   1.135 +    oidData = SECOID_FindOIDByTag(SEC_OID_SHA1);
   1.136 +    if (oidData == NULL) {
   1.137 +        return SECFailure;
   1.138 +    }
   1.139 +    poolp = challContent->poolp;
   1.140 +    challenge = PORT_ArenaZNew(poolp, CMMFChallenge);
   1.141 +    if (challenge == NULL) {
   1.142 +        return SECFailure;
   1.143 +    }
   1.144 +    algId = challenge->owf = PORT_ArenaZNew(poolp, SECAlgorithmID);
   1.145 +    if (algId == NULL) {
   1.146 +        return SECFailure;
   1.147 +    }
   1.148 +    rv = SECITEM_CopyItem(poolp, &algId->algorithm, &oidData->oid);
   1.149 +    if (rv != SECSuccess) {
   1.150 +        return SECFailure;
   1.151 +    }
   1.152 +    rv = cmmf_create_witness_and_challenge(poolp, challenge, inRandom, 
   1.153 +					   senderDER, inPubKey, passwdArg);
   1.154 +    challContent->challenges[0] = (rv == SECSuccess) ? challenge : NULL;
   1.155 +    challContent->numChallenges++;
   1.156 +    return rv ;
   1.157 +}
   1.158 +
   1.159 +CMMFPOPODecKeyChallContent*
   1.160 +CMMF_CreatePOPODecKeyChallContent (void)
   1.161 +{
   1.162 +    PLArenaPool *poolp;
   1.163 +    CMMFPOPODecKeyChallContent *challContent;
   1.164 +
   1.165 +    poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
   1.166 +    if (poolp == NULL) {
   1.167 +        return NULL;
   1.168 +    }
   1.169 +    challContent = PORT_ArenaZNew(poolp, CMMFPOPODecKeyChallContent);
   1.170 +    if (challContent == NULL) {
   1.171 +        PORT_FreeArena(poolp, PR_FALSE);
   1.172 +	return NULL;
   1.173 +    }
   1.174 +    challContent->poolp = poolp;
   1.175 +    return challContent;
   1.176 +}
   1.177 +
   1.178 +SECStatus
   1.179 +CMMF_POPODecKeyChallContentSetNextChallenge
   1.180 +                                    (CMMFPOPODecKeyChallContent *inDecKeyChall,
   1.181 +				     long                        inRandom,
   1.182 +				     CERTGeneralName            *inSender,
   1.183 +				     SECKEYPublicKey            *inPubKey,
   1.184 +				     void                       *passwdArg)
   1.185 +{
   1.186 +    CMMFChallenge               *curChallenge;
   1.187 +    PLArenaPool                 *genNamePool = NULL, *poolp;
   1.188 +    SECStatus                    rv;
   1.189 +    SECItem                     *genNameDER;
   1.190 +    void                        *mark;
   1.191 +
   1.192 +    PORT_Assert (inDecKeyChall != NULL &&
   1.193 +		 inSender      != NULL &&
   1.194 +		 inPubKey      != NULL);
   1.195 +
   1.196 +    if (inDecKeyChall == NULL || 
   1.197 +	inSender      == NULL || inPubKey == NULL) {
   1.198 +        return SECFailure;
   1.199 +    }
   1.200 +    poolp = inDecKeyChall->poolp;
   1.201 +    mark = PORT_ArenaMark(poolp);
   1.202 +
   1.203 +    genNamePool = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
   1.204 +    genNameDER = CERT_EncodeGeneralName(inSender, NULL, genNamePool);
   1.205 +    if (genNameDER == NULL) {
   1.206 +        rv = SECFailure;
   1.207 +        goto loser;
   1.208 +    }
   1.209 +    if (inDecKeyChall->challenges == NULL) {
   1.210 +        inDecKeyChall->challenges =
   1.211 +	    PORT_ArenaZNewArray(poolp, CMMFChallenge*,(CMMF_MAX_CHALLENGES+1));
   1.212 +	inDecKeyChall->numAllocated = CMMF_MAX_CHALLENGES;
   1.213 +    }
   1.214 +
   1.215 +    if (inDecKeyChall->numChallenges >= inDecKeyChall->numAllocated) {
   1.216 +        rv = SECFailure;
   1.217 +        goto loser;
   1.218 +    }
   1.219 +
   1.220 +    if (inDecKeyChall->numChallenges == 0) {
   1.221 +        rv = cmmf_create_first_challenge(inDecKeyChall, inRandom, 
   1.222 +					 genNameDER, inPubKey, passwdArg);
   1.223 +    } else {
   1.224 +        curChallenge = PORT_ArenaZNew(poolp, CMMFChallenge);
   1.225 +	if (curChallenge == NULL) {
   1.226 +	    rv = SECFailure;
   1.227 +	    goto loser;
   1.228 +	}
   1.229 +	rv = cmmf_create_witness_and_challenge(poolp, curChallenge, inRandom, 
   1.230 +					       genNameDER, inPubKey, 
   1.231 +					       passwdArg);
   1.232 +	if (rv == SECSuccess) {
   1.233 +	    inDecKeyChall->challenges[inDecKeyChall->numChallenges] =
   1.234 +	        curChallenge;
   1.235 +	    inDecKeyChall->numChallenges++;
   1.236 +	}
   1.237 +    }
   1.238 +    if (rv != SECSuccess) {
   1.239 +        goto loser;
   1.240 +    }
   1.241 +    PORT_ArenaUnmark(poolp, mark);
   1.242 +    PORT_FreeArena(genNamePool, PR_FALSE);
   1.243 +    return SECSuccess;
   1.244 +
   1.245 + loser:
   1.246 +    PORT_ArenaRelease(poolp, mark);
   1.247 +    if (genNamePool != NULL) {
   1.248 +        PORT_FreeArena(genNamePool, PR_FALSE);
   1.249 +    }
   1.250 +    PORT_Assert(rv != SECSuccess);
   1.251 +    return rv;
   1.252 +}
   1.253 +
   1.254 +SECStatus
   1.255 +CMMF_DestroyPOPODecKeyRespContent(CMMFPOPODecKeyRespContent *inDecKeyResp)
   1.256 +{
   1.257 +    PORT_Assert(inDecKeyResp != NULL);
   1.258 +    if (inDecKeyResp != NULL && inDecKeyResp->poolp != NULL) {
   1.259 +        PORT_FreeArena(inDecKeyResp->poolp, PR_FALSE);
   1.260 +    }
   1.261 +    return SECSuccess;
   1.262 +}
   1.263 +
   1.264 +int 
   1.265 +CMMF_POPODecKeyRespContentGetNumResponses(CMMFPOPODecKeyRespContent *inRespCont)
   1.266 +{
   1.267 +    int numResponses = 0;
   1.268 +
   1.269 +    PORT_Assert(inRespCont != NULL);
   1.270 +    if (inRespCont == NULL) {
   1.271 +        return 0;
   1.272 +    }
   1.273 +
   1.274 +    while (inRespCont->responses[numResponses] != NULL) {
   1.275 +        numResponses ++;
   1.276 +    }
   1.277 +    return numResponses;
   1.278 +}
   1.279 +
   1.280 +SECStatus
   1.281 +CMMF_POPODecKeyRespContentGetResponse (CMMFPOPODecKeyRespContent *inRespCont,
   1.282 +				       int                        inIndex,
   1.283 +				       long                      *inDest)
   1.284 +{
   1.285 +    PORT_Assert(inRespCont != NULL);
   1.286 +    
   1.287 +    if (inRespCont == NULL || inIndex < 0 || 
   1.288 +	inIndex >= CMMF_POPODecKeyRespContentGetNumResponses(inRespCont)) {
   1.289 +        return SECFailure;
   1.290 +    }
   1.291 +    *inDest = DER_GetInteger(inRespCont->responses[inIndex]);
   1.292 +    return (*inDest == -1) ? SECFailure : SECSuccess;
   1.293 +}

mercurial