Import from 1.9a8 tarball
[mozilla-nss.git] / security / nss / lib / crmf / challcli.c
bloba567452d533c741ec1408b13e0eda4fcd64de696
1 /* -*- Mode: C; tab-width: 8 -*-*/
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is the Netscape security libraries.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1994-2000
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 #include "cmmf.h"
39 #include "cmmfi.h"
40 #include "secitem.h"
41 #include "pk11func.h"
42 #include "secder.h"
43 #include "sechash.h"
45 CMMFPOPODecKeyChallContent*
46 CMMF_CreatePOPODecKeyChallContentFromDER(const char *buf, long len)
48 PRArenaPool *poolp;
49 CMMFPOPODecKeyChallContent *challContent;
50 SECStatus rv;
52 poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
53 if (poolp == NULL) {
54 return NULL;
56 challContent = PORT_ArenaZNew(poolp, CMMFPOPODecKeyChallContent);
57 if (challContent == NULL) {
58 goto loser;
60 challContent->poolp = poolp;
61 rv = SEC_ASN1Decode(poolp, challContent,
62 CMMFPOPODecKeyChallContentTemplate, buf, len);
63 if (rv != SECSuccess) {
64 goto loser;
66 if (challContent->challenges) {
67 while (challContent->challenges[challContent->numChallenges] != NULL) {
68 challContent->numChallenges++;
70 challContent->numAllocated = challContent->numChallenges;
72 return challContent;
73 loser:
74 if (poolp != NULL) {
75 PORT_FreeArena(poolp, PR_FALSE);
77 return NULL;
80 int
81 CMMF_POPODecKeyChallContentGetNumChallenges
82 (CMMFPOPODecKeyChallContent *inKeyChallCont)
84 PORT_Assert(inKeyChallCont != NULL);
85 if (inKeyChallCont == NULL) {
86 return 0;
88 return inKeyChallCont->numChallenges;
91 SECItem*
92 CMMF_POPODecKeyChallContentGetPublicValue
93 (CMMFPOPODecKeyChallContent *inKeyChallCont,
94 int inIndex)
96 PORT_Assert(inKeyChallCont != NULL);
97 if (inKeyChallCont == NULL || (inIndex > inKeyChallCont->numChallenges-1)||
98 inIndex < 0) {
99 return NULL;
101 return SECITEM_DupItem(&inKeyChallCont->challenges[inIndex]->key);
104 static SECAlgorithmID*
105 cmmf_get_owf(CMMFPOPODecKeyChallContent *inChalCont,
106 int inIndex)
108 int i;
110 for (i=inIndex; i >= 0; i--) {
111 if (inChalCont->challenges[i]->owf != NULL) {
112 return inChalCont->challenges[i]->owf;
115 return NULL;
118 SECStatus
119 CMMF_POPODecKeyChallContDecryptChallenge(CMMFPOPODecKeyChallContent *inChalCont,
120 int inIndex,
121 SECKEYPrivateKey *inPrivKey)
123 CMMFChallenge *challenge;
124 SECItem *decryptedRand=NULL;
125 PRArenaPool *poolp = NULL;
126 SECAlgorithmID *owf;
127 SECStatus rv = SECFailure;
128 SECOidTag tag;
129 CMMFRand randStr;
130 SECItem hashItem;
131 unsigned char hash[HASH_LENGTH_MAX];
133 PORT_Assert(inChalCont != NULL && inPrivKey != NULL);
134 if (inChalCont == NULL || inIndex <0 || inIndex > inChalCont->numChallenges
135 || inPrivKey == NULL){
136 return SECFailure;
139 poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
140 if (poolp == NULL) {
141 goto loser;
144 challenge = inChalCont->challenges[inIndex];
145 decryptedRand = SECITEM_AllocItem(poolp, NULL, challenge->challenge.len);
146 if (decryptedRand == NULL) {
147 goto loser;
149 rv = PK11_PrivDecryptPKCS1(inPrivKey, decryptedRand->data,
150 &decryptedRand->len, decryptedRand->len,
151 challenge->challenge.data, challenge->challenge.len);
152 if (rv != SECSuccess) {
153 goto loser;
156 rv = SEC_ASN1DecodeItem(poolp, &randStr, CMMFRandTemplate,
157 decryptedRand);
158 if (rv != SECSuccess) {
159 goto loser;
161 rv = SECFailure; /* Just so that when we do go to loser,
162 * I won't have to set it again.
164 owf = cmmf_get_owf(inChalCont, inIndex);
165 if (owf == NULL) {
166 /* No hashing algorithm came with the challenges. Can't verify */
167 goto loser;
169 /* Verify the hashes in the challenge */
170 tag = SECOID_FindOIDTag(&owf->algorithm);
171 hashItem.len = HASH_ResultLenByOidTag(tag);
172 if (!hashItem.len)
173 goto loser; /* error code has been set */
175 rv = PK11_HashBuf(tag, hash, randStr.integer.data, randStr.integer.len);
176 if (rv != SECSuccess) {
177 goto loser;
179 hashItem.data = hash;
180 if (SECITEM_CompareItem(&hashItem, &challenge->witness) != SECEqual) {
181 /* The hash for the data we decrypted doesn't match the hash provided
182 * in the challenge. Bail out.
184 PORT_SetError(SEC_ERROR_BAD_DATA);
185 rv = SECFailure;
186 goto loser;
188 rv = PK11_HashBuf(tag, hash, challenge->senderDER.data,
189 challenge->senderDER.len);
190 if (rv != SECSuccess) {
191 goto loser;
193 if (SECITEM_CompareItem(&hashItem, &randStr.senderHash) != SECEqual) {
194 /* The hash for the data we decrypted doesn't match the hash provided
195 * in the challenge. Bail out.
197 PORT_SetError(SEC_ERROR_BAD_DATA);
198 rv = SECFailure;
199 goto loser;
201 /* All of the hashes have verified, so we can now store the integer away.*/
202 rv = SECITEM_CopyItem(inChalCont->poolp, &challenge->randomNumber,
203 &randStr.integer);
204 loser:
205 if (poolp) {
206 PORT_FreeArena(poolp, PR_FALSE);
208 return rv;
211 SECStatus
212 CMMF_POPODecKeyChallContentGetRandomNumber
213 (CMMFPOPODecKeyChallContent *inKeyChallCont,
214 int inIndex,
215 long *inDest)
217 CMMFChallenge *challenge;
219 PORT_Assert(inKeyChallCont != NULL);
220 if (inKeyChallCont == NULL || inIndex > 0 || inIndex >=
221 inKeyChallCont->numChallenges) {
222 return SECFailure;
224 challenge = inKeyChallCont->challenges[inIndex];
225 if (challenge->randomNumber.data == NULL) {
226 /* There is no random number here, nothing to see. */
227 return SECFailure;
229 *inDest = DER_GetInteger(&challenge->randomNumber);
230 return (*inDest == -1) ? SECFailure : SECSuccess;
233 SECStatus
234 CMMF_EncodePOPODecKeyRespContent(long *inDecodedRand,
235 int inNumRand,
236 CRMFEncoderOutputCallback inCallback,
237 void *inArg)
239 PRArenaPool *poolp;
240 CMMFPOPODecKeyRespContent *response;
241 SECItem *currItem;
242 SECStatus rv=SECFailure;
243 int i;
245 poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
246 if (poolp == NULL) {
247 return SECFailure;
249 response = PORT_ArenaZNew(poolp, CMMFPOPODecKeyRespContent);
250 if (response == NULL) {
251 goto loser;
253 response->responses = PORT_ArenaZNewArray(poolp, SECItem*, inNumRand+1);
254 if (response->responses == NULL) {
255 goto loser;
257 for (i=0; i<inNumRand; i++) {
258 currItem = response->responses[i] = PORT_ArenaZNew(poolp,SECItem);
259 if (currItem == NULL) {
260 goto loser;
262 currItem = SEC_ASN1EncodeInteger(poolp, currItem, inDecodedRand[i]);
263 if (currItem == NULL) {
264 goto loser;
267 rv = cmmf_user_encode(response, inCallback, inArg,
268 CMMFPOPODecKeyRespContentTemplate);
269 loser:
270 if (poolp != NULL) {
271 PORT_FreeArena(poolp, PR_FALSE);
273 return rv;