security/nss/lib/crmf/cmmfchal.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: C; tab-width: 8 -*-*/
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "cmmf.h"
     7 #include "cmmfi.h"
     8 #include "sechash.h"
     9 #include "genname.h"
    10 #include "pk11func.h"
    11 #include "cert.h"
    12 #include "secitem.h"
    13 #include "secmod.h"
    14 #include "keyhi.h"
    16 static int
    17 cmmf_create_witness_and_challenge(PLArenaPool     *poolp,
    18 				  CMMFChallenge   *challenge,
    19 				  long             inRandom,
    20 				  SECItem         *senderDER,
    21 				  SECKEYPublicKey *inPubKey,
    22 				  void            *passwdArg)
    23 {
    24     SECItem       *encodedRandNum;
    25     SECItem        encodedRandStr = {siBuffer, NULL, 0};
    26     SECItem       *dummy;
    27     unsigned char *randHash, *senderHash, *encChal=NULL;
    28     unsigned       modulusLen = 0;
    29     SECStatus      rv = SECFailure;
    30     CMMFRand       randStr= { {siBuffer, NULL, 0}, {siBuffer, NULL, 0}};
    31     PK11SlotInfo  *slot;
    32     PK11SymKey    *symKey = NULL;
    33     CK_OBJECT_HANDLE id;
    34     CERTSubjectPublicKeyInfo *spki = NULL;
    37     encodedRandNum = SEC_ASN1EncodeInteger(poolp, &challenge->randomNumber,
    38 					   inRandom);
    39     encodedRandNum = &challenge->randomNumber;
    40     randHash   = PORT_ArenaNewArray(poolp, unsigned char, SHA1_LENGTH);
    41     senderHash = PORT_ArenaNewArray(poolp, unsigned char, SHA1_LENGTH);
    42     if (randHash == NULL) {
    43         goto loser;
    44     }
    45     rv = PK11_HashBuf(SEC_OID_SHA1, randHash, encodedRandNum->data, 
    46 		      (PRUint32)encodedRandNum->len);
    47     if (rv != SECSuccess) {
    48         goto loser;
    49     }
    50     rv = PK11_HashBuf(SEC_OID_SHA1, senderHash, senderDER->data,
    51 		      (PRUint32)senderDER->len);
    52     if (rv != SECSuccess) {
    53         goto loser;
    54     }
    55     challenge->witness.data = randHash;
    56     challenge->witness.len  = SHA1_LENGTH;
    58     randStr.integer    = *encodedRandNum;
    59     randStr.senderHash.data = senderHash;
    60     randStr.senderHash.len  = SHA1_LENGTH;
    61     dummy = SEC_ASN1EncodeItem(NULL, &encodedRandStr, &randStr, 
    62 			       CMMFRandTemplate);
    63     if (dummy != &encodedRandStr) {
    64         rv = SECFailure;
    65         goto loser;
    66     }
    67     /* XXXX Now I have to encrypt encodedRandStr and stash it away. */
    68     modulusLen = SECKEY_PublicKeyStrength(inPubKey);
    69     encChal = PORT_ArenaNewArray(poolp, unsigned char, modulusLen);
    70     if (encChal == NULL) {
    71         rv = SECFailure;
    72         goto loser;
    73     }
    74     slot =PK11_GetBestSlotWithAttributes(CKM_RSA_PKCS, CKF_WRAP, 0, passwdArg);
    75     if (slot == NULL) {
    76         rv = SECFailure;
    77         goto loser;
    78     }
    79     id = PK11_ImportPublicKey(slot, inPubKey, PR_FALSE);
    80     /* In order to properly encrypt the data, we import as a symmetric
    81      * key, and then wrap that key.  That in essence encrypts the data.
    82      * This is the method recommended in the PK11 world in order
    83      * to prevent threading issues as well as breaking any other semantics
    84      * the PK11 libraries depend on.
    85      */
    86     symKey = PK11_ImportSymKey(slot, CKM_RSA_PKCS, PK11_OriginGenerated,
    87 			       CKA_VALUE, &encodedRandStr, passwdArg);
    88     if (symKey == NULL) {
    89         rv = SECFailure;
    90 	goto loser;
    91     }
    92     challenge->challenge.data = encChal;
    93     challenge->challenge.len  = modulusLen;
    94     rv = PK11_PubWrapSymKey(CKM_RSA_PKCS, inPubKey, symKey, 
    95 			    &challenge->challenge);
    96     PK11_FreeSlot(slot);
    97     if (rv != SECSuccess) {
    98 	goto loser;
    99     }
   100     rv = SECITEM_CopyItem(poolp, &challenge->senderDER, senderDER);
   101     crmf_get_public_value(inPubKey, &challenge->key);
   102     /* Fall through */
   103  loser:
   104     if (spki != NULL) {
   105         SECKEY_DestroySubjectPublicKeyInfo(spki);
   106     }
   107     if (encodedRandStr.data != NULL) {
   108         PORT_Free(encodedRandStr.data);
   109     }
   110     if (encodedRandNum != NULL) {
   111         SECITEM_FreeItem(encodedRandNum, PR_TRUE);
   112     }
   113     if (symKey != NULL) {
   114         PK11_FreeSymKey(symKey);
   115     }
   116     return rv;
   117 }
   119 static SECStatus
   120 cmmf_create_first_challenge(CMMFPOPODecKeyChallContent *challContent, 
   121 			    long                        inRandom, 
   122 			    SECItem                    *senderDER, 
   123 			    SECKEYPublicKey            *inPubKey,
   124 			    void                       *passwdArg)
   125 {
   126     SECOidData     *oidData;
   127     CMMFChallenge  *challenge;
   128     SECAlgorithmID *algId;
   129     PLArenaPool    *poolp;
   130     SECStatus       rv;
   132     oidData = SECOID_FindOIDByTag(SEC_OID_SHA1);
   133     if (oidData == NULL) {
   134         return SECFailure;
   135     }
   136     poolp = challContent->poolp;
   137     challenge = PORT_ArenaZNew(poolp, CMMFChallenge);
   138     if (challenge == NULL) {
   139         return SECFailure;
   140     }
   141     algId = challenge->owf = PORT_ArenaZNew(poolp, SECAlgorithmID);
   142     if (algId == NULL) {
   143         return SECFailure;
   144     }
   145     rv = SECITEM_CopyItem(poolp, &algId->algorithm, &oidData->oid);
   146     if (rv != SECSuccess) {
   147         return SECFailure;
   148     }
   149     rv = cmmf_create_witness_and_challenge(poolp, challenge, inRandom, 
   150 					   senderDER, inPubKey, passwdArg);
   151     challContent->challenges[0] = (rv == SECSuccess) ? challenge : NULL;
   152     challContent->numChallenges++;
   153     return rv ;
   154 }
   156 CMMFPOPODecKeyChallContent*
   157 CMMF_CreatePOPODecKeyChallContent (void)
   158 {
   159     PLArenaPool *poolp;
   160     CMMFPOPODecKeyChallContent *challContent;
   162     poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
   163     if (poolp == NULL) {
   164         return NULL;
   165     }
   166     challContent = PORT_ArenaZNew(poolp, CMMFPOPODecKeyChallContent);
   167     if (challContent == NULL) {
   168         PORT_FreeArena(poolp, PR_FALSE);
   169 	return NULL;
   170     }
   171     challContent->poolp = poolp;
   172     return challContent;
   173 }
   175 SECStatus
   176 CMMF_POPODecKeyChallContentSetNextChallenge
   177                                     (CMMFPOPODecKeyChallContent *inDecKeyChall,
   178 				     long                        inRandom,
   179 				     CERTGeneralName            *inSender,
   180 				     SECKEYPublicKey            *inPubKey,
   181 				     void                       *passwdArg)
   182 {
   183     CMMFChallenge               *curChallenge;
   184     PLArenaPool                 *genNamePool = NULL, *poolp;
   185     SECStatus                    rv;
   186     SECItem                     *genNameDER;
   187     void                        *mark;
   189     PORT_Assert (inDecKeyChall != NULL &&
   190 		 inSender      != NULL &&
   191 		 inPubKey      != NULL);
   193     if (inDecKeyChall == NULL || 
   194 	inSender      == NULL || inPubKey == NULL) {
   195         return SECFailure;
   196     }
   197     poolp = inDecKeyChall->poolp;
   198     mark = PORT_ArenaMark(poolp);
   200     genNamePool = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
   201     genNameDER = CERT_EncodeGeneralName(inSender, NULL, genNamePool);
   202     if (genNameDER == NULL) {
   203         rv = SECFailure;
   204         goto loser;
   205     }
   206     if (inDecKeyChall->challenges == NULL) {
   207         inDecKeyChall->challenges =
   208 	    PORT_ArenaZNewArray(poolp, CMMFChallenge*,(CMMF_MAX_CHALLENGES+1));
   209 	inDecKeyChall->numAllocated = CMMF_MAX_CHALLENGES;
   210     }
   212     if (inDecKeyChall->numChallenges >= inDecKeyChall->numAllocated) {
   213         rv = SECFailure;
   214         goto loser;
   215     }
   217     if (inDecKeyChall->numChallenges == 0) {
   218         rv = cmmf_create_first_challenge(inDecKeyChall, inRandom, 
   219 					 genNameDER, inPubKey, passwdArg);
   220     } else {
   221         curChallenge = PORT_ArenaZNew(poolp, CMMFChallenge);
   222 	if (curChallenge == NULL) {
   223 	    rv = SECFailure;
   224 	    goto loser;
   225 	}
   226 	rv = cmmf_create_witness_and_challenge(poolp, curChallenge, inRandom, 
   227 					       genNameDER, inPubKey, 
   228 					       passwdArg);
   229 	if (rv == SECSuccess) {
   230 	    inDecKeyChall->challenges[inDecKeyChall->numChallenges] =
   231 	        curChallenge;
   232 	    inDecKeyChall->numChallenges++;
   233 	}
   234     }
   235     if (rv != SECSuccess) {
   236         goto loser;
   237     }
   238     PORT_ArenaUnmark(poolp, mark);
   239     PORT_FreeArena(genNamePool, PR_FALSE);
   240     return SECSuccess;
   242  loser:
   243     PORT_ArenaRelease(poolp, mark);
   244     if (genNamePool != NULL) {
   245         PORT_FreeArena(genNamePool, PR_FALSE);
   246     }
   247     PORT_Assert(rv != SECSuccess);
   248     return rv;
   249 }
   251 SECStatus
   252 CMMF_DestroyPOPODecKeyRespContent(CMMFPOPODecKeyRespContent *inDecKeyResp)
   253 {
   254     PORT_Assert(inDecKeyResp != NULL);
   255     if (inDecKeyResp != NULL && inDecKeyResp->poolp != NULL) {
   256         PORT_FreeArena(inDecKeyResp->poolp, PR_FALSE);
   257     }
   258     return SECSuccess;
   259 }
   261 int 
   262 CMMF_POPODecKeyRespContentGetNumResponses(CMMFPOPODecKeyRespContent *inRespCont)
   263 {
   264     int numResponses = 0;
   266     PORT_Assert(inRespCont != NULL);
   267     if (inRespCont == NULL) {
   268         return 0;
   269     }
   271     while (inRespCont->responses[numResponses] != NULL) {
   272         numResponses ++;
   273     }
   274     return numResponses;
   275 }
   277 SECStatus
   278 CMMF_POPODecKeyRespContentGetResponse (CMMFPOPODecKeyRespContent *inRespCont,
   279 				       int                        inIndex,
   280 				       long                      *inDest)
   281 {
   282     PORT_Assert(inRespCont != NULL);
   284     if (inRespCont == NULL || inIndex < 0 || 
   285 	inIndex >= CMMF_POPODecKeyRespContentGetNumResponses(inRespCont)) {
   286         return SECFailure;
   287     }
   288     *inDest = DER_GetInteger(inRespCont->responses[inIndex]);
   289     return (*inDest == -1) ? SECFailure : SECSuccess;
   290 }

mercurial