1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/crmf/challcli.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,242 @@ 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 "secitem.h" 1.12 +#include "pk11func.h" 1.13 +#include "secder.h" 1.14 +#include "sechash.h" 1.15 + 1.16 +CMMFPOPODecKeyChallContent* 1.17 +CMMF_CreatePOPODecKeyChallContentFromDER(const char *buf, long len) 1.18 +{ 1.19 + PLArenaPool *poolp; 1.20 + CMMFPOPODecKeyChallContent *challContent; 1.21 + SECStatus rv; 1.22 + 1.23 + poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE); 1.24 + if (poolp == NULL) { 1.25 + return NULL; 1.26 + } 1.27 + challContent = PORT_ArenaZNew(poolp, CMMFPOPODecKeyChallContent); 1.28 + if (challContent == NULL) { 1.29 + goto loser; 1.30 + } 1.31 + challContent->poolp = poolp; 1.32 + rv = SEC_ASN1Decode(poolp, challContent, 1.33 + CMMFPOPODecKeyChallContentTemplate, buf, len); 1.34 + if (rv != SECSuccess) { 1.35 + goto loser; 1.36 + } 1.37 + if (challContent->challenges) { 1.38 + while (challContent->challenges[challContent->numChallenges] != NULL) { 1.39 + challContent->numChallenges++; 1.40 + } 1.41 + challContent->numAllocated = challContent->numChallenges; 1.42 + } 1.43 + return challContent; 1.44 + loser: 1.45 + if (poolp != NULL) { 1.46 + PORT_FreeArena(poolp, PR_FALSE); 1.47 + } 1.48 + return NULL; 1.49 +} 1.50 + 1.51 +int 1.52 +CMMF_POPODecKeyChallContentGetNumChallenges 1.53 + (CMMFPOPODecKeyChallContent *inKeyChallCont) 1.54 +{ 1.55 + PORT_Assert(inKeyChallCont != NULL); 1.56 + if (inKeyChallCont == NULL) { 1.57 + return 0; 1.58 + } 1.59 + return inKeyChallCont->numChallenges; 1.60 +} 1.61 + 1.62 +SECItem* 1.63 +CMMF_POPODecKeyChallContentGetPublicValue 1.64 + (CMMFPOPODecKeyChallContent *inKeyChallCont, 1.65 + int inIndex) 1.66 +{ 1.67 + PORT_Assert(inKeyChallCont != NULL); 1.68 + if (inKeyChallCont == NULL || (inIndex > inKeyChallCont->numChallenges-1)|| 1.69 + inIndex < 0) { 1.70 + return NULL; 1.71 + } 1.72 + return SECITEM_DupItem(&inKeyChallCont->challenges[inIndex]->key); 1.73 +} 1.74 + 1.75 +static SECAlgorithmID* 1.76 +cmmf_get_owf(CMMFPOPODecKeyChallContent *inChalCont, 1.77 + int inIndex) 1.78 +{ 1.79 + int i; 1.80 + 1.81 + for (i=inIndex; i >= 0; i--) { 1.82 + if (inChalCont->challenges[i]->owf != NULL) { 1.83 + return inChalCont->challenges[i]->owf; 1.84 + } 1.85 + } 1.86 + return NULL; 1.87 +} 1.88 + 1.89 +SECStatus 1.90 +CMMF_POPODecKeyChallContDecryptChallenge(CMMFPOPODecKeyChallContent *inChalCont, 1.91 + int inIndex, 1.92 + SECKEYPrivateKey *inPrivKey) 1.93 +{ 1.94 + CMMFChallenge *challenge; 1.95 + SECItem *decryptedRand=NULL; 1.96 + PLArenaPool *poolp = NULL; 1.97 + SECAlgorithmID *owf; 1.98 + SECStatus rv = SECFailure; 1.99 + SECOidTag tag; 1.100 + CMMFRand randStr; 1.101 + SECItem hashItem; 1.102 + unsigned char hash[HASH_LENGTH_MAX]; 1.103 + 1.104 + PORT_Assert(inChalCont != NULL && inPrivKey != NULL); 1.105 + if (inChalCont == NULL || inIndex <0 || inIndex > inChalCont->numChallenges 1.106 + || inPrivKey == NULL){ 1.107 + return SECFailure; 1.108 + } 1.109 + 1.110 + poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE); 1.111 + if (poolp == NULL) { 1.112 + goto loser; 1.113 + } 1.114 + 1.115 + challenge = inChalCont->challenges[inIndex]; 1.116 + decryptedRand = SECITEM_AllocItem(poolp, NULL, challenge->challenge.len); 1.117 + if (decryptedRand == NULL) { 1.118 + goto loser; 1.119 + } 1.120 + rv = PK11_PrivDecryptPKCS1(inPrivKey, decryptedRand->data, 1.121 + &decryptedRand->len, decryptedRand->len, 1.122 + challenge->challenge.data, challenge->challenge.len); 1.123 + if (rv != SECSuccess) { 1.124 + goto loser; 1.125 + } 1.126 + 1.127 + rv = SEC_ASN1DecodeItem(poolp, &randStr, CMMFRandTemplate, 1.128 + decryptedRand); 1.129 + if (rv != SECSuccess) { 1.130 + goto loser; 1.131 + } 1.132 + rv = SECFailure; /* Just so that when we do go to loser, 1.133 + * I won't have to set it again. 1.134 + */ 1.135 + owf = cmmf_get_owf(inChalCont, inIndex); 1.136 + if (owf == NULL) { 1.137 + /* No hashing algorithm came with the challenges. Can't verify */ 1.138 + goto loser; 1.139 + } 1.140 + /* Verify the hashes in the challenge */ 1.141 + tag = SECOID_FindOIDTag(&owf->algorithm); 1.142 + hashItem.len = HASH_ResultLenByOidTag(tag); 1.143 + if (!hashItem.len) 1.144 + goto loser; /* error code has been set */ 1.145 + 1.146 + rv = PK11_HashBuf(tag, hash, randStr.integer.data, randStr.integer.len); 1.147 + if (rv != SECSuccess) { 1.148 + goto loser; 1.149 + } 1.150 + hashItem.data = hash; 1.151 + if (SECITEM_CompareItem(&hashItem, &challenge->witness) != SECEqual) { 1.152 + /* The hash for the data we decrypted doesn't match the hash provided 1.153 + * in the challenge. Bail out. 1.154 + */ 1.155 + PORT_SetError(SEC_ERROR_BAD_DATA); 1.156 + rv = SECFailure; 1.157 + goto loser; 1.158 + } 1.159 + rv = PK11_HashBuf(tag, hash, challenge->senderDER.data, 1.160 + challenge->senderDER.len); 1.161 + if (rv != SECSuccess) { 1.162 + goto loser; 1.163 + } 1.164 + if (SECITEM_CompareItem(&hashItem, &randStr.senderHash) != SECEqual) { 1.165 + /* The hash for the data we decrypted doesn't match the hash provided 1.166 + * in the challenge. Bail out. 1.167 + */ 1.168 + PORT_SetError(SEC_ERROR_BAD_DATA); 1.169 + rv = SECFailure; 1.170 + goto loser; 1.171 + } 1.172 + /* All of the hashes have verified, so we can now store the integer away.*/ 1.173 + rv = SECITEM_CopyItem(inChalCont->poolp, &challenge->randomNumber, 1.174 + &randStr.integer); 1.175 + loser: 1.176 + if (poolp) { 1.177 + PORT_FreeArena(poolp, PR_FALSE); 1.178 + } 1.179 + return rv; 1.180 +} 1.181 + 1.182 +SECStatus 1.183 +CMMF_POPODecKeyChallContentGetRandomNumber 1.184 + (CMMFPOPODecKeyChallContent *inKeyChallCont, 1.185 + int inIndex, 1.186 + long *inDest) 1.187 +{ 1.188 + CMMFChallenge *challenge; 1.189 + 1.190 + PORT_Assert(inKeyChallCont != NULL); 1.191 + if (inKeyChallCont == NULL || inIndex > 0 || inIndex >= 1.192 + inKeyChallCont->numChallenges) { 1.193 + return SECFailure; 1.194 + } 1.195 + challenge = inKeyChallCont->challenges[inIndex]; 1.196 + if (challenge->randomNumber.data == NULL) { 1.197 + /* There is no random number here, nothing to see. */ 1.198 + return SECFailure; 1.199 + } 1.200 + *inDest = DER_GetInteger(&challenge->randomNumber); 1.201 + return (*inDest == -1) ? SECFailure : SECSuccess; 1.202 +} 1.203 + 1.204 +SECStatus 1.205 +CMMF_EncodePOPODecKeyRespContent(long *inDecodedRand, 1.206 + int inNumRand, 1.207 + CRMFEncoderOutputCallback inCallback, 1.208 + void *inArg) 1.209 +{ 1.210 + PLArenaPool *poolp; 1.211 + CMMFPOPODecKeyRespContent *response; 1.212 + SECItem *currItem; 1.213 + SECStatus rv=SECFailure; 1.214 + int i; 1.215 + 1.216 + poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE); 1.217 + if (poolp == NULL) { 1.218 + return SECFailure; 1.219 + } 1.220 + response = PORT_ArenaZNew(poolp, CMMFPOPODecKeyRespContent); 1.221 + if (response == NULL) { 1.222 + goto loser; 1.223 + } 1.224 + response->responses = PORT_ArenaZNewArray(poolp, SECItem*, inNumRand+1); 1.225 + if (response->responses == NULL) { 1.226 + goto loser; 1.227 + } 1.228 + for (i=0; i<inNumRand; i++) { 1.229 + currItem = response->responses[i] = PORT_ArenaZNew(poolp,SECItem); 1.230 + if (currItem == NULL) { 1.231 + goto loser; 1.232 + } 1.233 + currItem = SEC_ASN1EncodeInteger(poolp, currItem, inDecodedRand[i]); 1.234 + if (currItem == NULL) { 1.235 + goto loser; 1.236 + } 1.237 + } 1.238 + rv = cmmf_user_encode(response, inCallback, inArg, 1.239 + CMMFPOPODecKeyRespContentTemplate); 1.240 + loser: 1.241 + if (poolp != NULL) { 1.242 + PORT_FreeArena(poolp, PR_FALSE); 1.243 + } 1.244 + return rv; 1.245 +}