security/nss/lib/crmf/challcli.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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 "secitem.h"
     9 #include "pk11func.h"
    10 #include "secder.h"
    11 #include "sechash.h"
    13 CMMFPOPODecKeyChallContent*
    14 CMMF_CreatePOPODecKeyChallContentFromDER(const char *buf, long len)
    15 {
    16     PLArenaPool                *poolp;
    17     CMMFPOPODecKeyChallContent *challContent;
    18     SECStatus                   rv;
    20     poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
    21     if (poolp == NULL) {
    22         return NULL;
    23     }
    24     challContent = PORT_ArenaZNew(poolp, CMMFPOPODecKeyChallContent);
    25     if (challContent == NULL) {
    26         goto loser;
    27     }
    28     challContent->poolp = poolp;
    29     rv = SEC_ASN1Decode(poolp, challContent, 
    30 			CMMFPOPODecKeyChallContentTemplate, buf, len);
    31     if (rv != SECSuccess) {
    32         goto loser;
    33     }
    34     if (challContent->challenges) {
    35       while (challContent->challenges[challContent->numChallenges] != NULL) {
    36 	  challContent->numChallenges++;
    37       }
    38       challContent->numAllocated = challContent->numChallenges;
    39     }
    40     return challContent;
    41  loser:
    42     if (poolp != NULL) {
    43         PORT_FreeArena(poolp, PR_FALSE);
    44     }
    45     return NULL;
    46 }
    48 int
    49 CMMF_POPODecKeyChallContentGetNumChallenges 
    50                               (CMMFPOPODecKeyChallContent *inKeyChallCont)
    51 {
    52     PORT_Assert(inKeyChallCont != NULL);
    53     if (inKeyChallCont == NULL) {
    54         return 0;
    55     }
    56     return inKeyChallCont->numChallenges;
    57 }
    59 SECItem* 
    60 CMMF_POPODecKeyChallContentGetPublicValue
    61                                    (CMMFPOPODecKeyChallContent *inKeyChallCont,
    62 				    int                         inIndex)
    63 {
    64     PORT_Assert(inKeyChallCont != NULL);
    65     if (inKeyChallCont == NULL || (inIndex > inKeyChallCont->numChallenges-1)||
    66 	inIndex < 0) {
    67         return NULL;
    68     }
    69     return SECITEM_DupItem(&inKeyChallCont->challenges[inIndex]->key);
    70 }
    72 static SECAlgorithmID*
    73 cmmf_get_owf(CMMFPOPODecKeyChallContent *inChalCont, 
    74 	     int                         inIndex)
    75 {
    76    int i;
    78    for (i=inIndex; i >= 0; i--) {
    79        if (inChalCont->challenges[i]->owf != NULL) {
    80 	   return inChalCont->challenges[i]->owf;
    81        }
    82    }
    83    return NULL;
    84 }
    86 SECStatus 
    87 CMMF_POPODecKeyChallContDecryptChallenge(CMMFPOPODecKeyChallContent *inChalCont,
    88 					 int                         inIndex,
    89 					 SECKEYPrivateKey           *inPrivKey)
    90 {
    91     CMMFChallenge  *challenge;
    92     SECItem        *decryptedRand=NULL;
    93     PLArenaPool    *poolp  = NULL;
    94     SECAlgorithmID *owf;
    95     SECStatus       rv     = SECFailure;
    96     SECOidTag       tag;
    97     CMMFRand        randStr;
    98     SECItem         hashItem;
    99     unsigned char   hash[HASH_LENGTH_MAX]; 
   101     PORT_Assert(inChalCont != NULL && inPrivKey != NULL);
   102     if (inChalCont == NULL || inIndex <0 || inIndex > inChalCont->numChallenges
   103 	|| inPrivKey == NULL){
   104         return SECFailure;
   105     }
   107     poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
   108     if (poolp == NULL) {
   109         goto loser;
   110     }
   112     challenge = inChalCont->challenges[inIndex];
   113     decryptedRand = SECITEM_AllocItem(poolp, NULL, challenge->challenge.len);
   114     if (decryptedRand == NULL) {
   115         goto loser;
   116     }
   117     rv = PK11_PrivDecryptPKCS1(inPrivKey, decryptedRand->data, 
   118     			&decryptedRand->len, decryptedRand->len, 
   119 			challenge->challenge.data, challenge->challenge.len);
   120     if (rv != SECSuccess) {
   121         goto loser;
   122     }
   124     rv = SEC_ASN1DecodeItem(poolp, &randStr, CMMFRandTemplate,
   125 			    decryptedRand); 
   126     if (rv != SECSuccess) {
   127         goto loser;
   128     }
   129     rv = SECFailure; /* Just so that when we do go to loser,
   130 		      * I won't have to set it again.
   131 		      */
   132     owf = cmmf_get_owf(inChalCont, inIndex);
   133     if (owf == NULL) {
   134         /* No hashing algorithm came with the challenges.  Can't verify */
   135         goto loser;
   136     }
   137     /* Verify the hashes in the challenge */
   138     tag = SECOID_FindOIDTag(&owf->algorithm);
   139     hashItem.len = HASH_ResultLenByOidTag(tag);
   140     if (!hashItem.len)
   141         goto loser;	/* error code has been set */
   143     rv = PK11_HashBuf(tag, hash, randStr.integer.data, randStr.integer.len);
   144     if (rv != SECSuccess) {
   145         goto loser;
   146     }
   147     hashItem.data = hash;
   148     if (SECITEM_CompareItem(&hashItem, &challenge->witness) != SECEqual) {
   149         /* The hash for the data we decrypted doesn't match the hash provided
   150 	 * in the challenge.  Bail out.
   151 	 */
   152 	PORT_SetError(SEC_ERROR_BAD_DATA);
   153         rv = SECFailure;
   154 	goto loser;
   155     }
   156     rv = PK11_HashBuf(tag, hash, challenge->senderDER.data, 
   157 		      challenge->senderDER.len);
   158     if (rv != SECSuccess) {
   159         goto loser;
   160     }
   161     if (SECITEM_CompareItem(&hashItem, &randStr.senderHash) != SECEqual) {
   162         /* The hash for the data we decrypted doesn't match the hash provided
   163 	 * in the challenge.  Bail out.
   164 	 */
   165 	PORT_SetError(SEC_ERROR_BAD_DATA);
   166         rv = SECFailure;
   167 	goto loser;
   168     }
   169     /* All of the hashes have verified, so we can now store the integer away.*/
   170     rv = SECITEM_CopyItem(inChalCont->poolp, &challenge->randomNumber,
   171 			  &randStr.integer);
   172  loser:
   173     if (poolp) {
   174     	PORT_FreeArena(poolp, PR_FALSE);
   175     }
   176     return rv;
   177 }
   179 SECStatus
   180 CMMF_POPODecKeyChallContentGetRandomNumber
   181                                    (CMMFPOPODecKeyChallContent *inKeyChallCont,
   182 				    int                          inIndex,
   183 				    long                        *inDest)
   184 {
   185     CMMFChallenge *challenge;
   187     PORT_Assert(inKeyChallCont != NULL);
   188     if (inKeyChallCont == NULL || inIndex > 0 || inIndex >= 
   189 	inKeyChallCont->numChallenges) {
   190         return SECFailure;
   191     }
   192     challenge = inKeyChallCont->challenges[inIndex];
   193     if (challenge->randomNumber.data == NULL) {
   194         /* There is no random number here, nothing to see. */
   195         return SECFailure;
   196     }
   197     *inDest = DER_GetInteger(&challenge->randomNumber);
   198     return (*inDest == -1) ? SECFailure : SECSuccess;
   199 }
   201 SECStatus 
   202 CMMF_EncodePOPODecKeyRespContent(long                     *inDecodedRand,
   203 				 int                       inNumRand,
   204 				 CRMFEncoderOutputCallback inCallback,
   205 				 void                     *inArg)
   206 {
   207     PLArenaPool *poolp;
   208     CMMFPOPODecKeyRespContent *response;
   209     SECItem *currItem;
   210     SECStatus rv=SECFailure;
   211     int i;
   213     poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
   214     if (poolp == NULL) {
   215         return SECFailure;
   216     }
   217     response = PORT_ArenaZNew(poolp, CMMFPOPODecKeyRespContent);
   218     if (response == NULL) {
   219         goto loser;
   220     }
   221     response->responses = PORT_ArenaZNewArray(poolp, SECItem*, inNumRand+1);
   222     if (response->responses == NULL) {
   223         goto loser;
   224     }
   225     for (i=0; i<inNumRand; i++) {
   226         currItem = response->responses[i] = PORT_ArenaZNew(poolp,SECItem);
   227 	if (currItem == NULL) {
   228 	    goto loser;
   229 	}
   230 	currItem = SEC_ASN1EncodeInteger(poolp, currItem, inDecodedRand[i]);
   231 	if (currItem == NULL) {
   232 	    goto loser;
   233 	}
   234     }
   235     rv = cmmf_user_encode(response, inCallback, inArg,
   236 			  CMMFPOPODecKeyRespContentTemplate);
   237  loser:
   238     if (poolp != NULL) {
   239         PORT_FreeArena(poolp, PR_FALSE);
   240     }
   241     return rv;
   242 }

mercurial