security/nss/lib/crmf/challcli.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

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

mercurial