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
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.
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 ***** */
49
cmmf_create_witness_and_challenge(PRArenaPool *poolp,
50
CMMFChallenge *challenge,
53
SECKEYPublicKey *inPubKey,
56
SECItem *encodedRandNum;
57
SECItem encodedRandStr = {siBuffer, NULL, 0};
59
unsigned char *randHash, *senderHash, *encChal=NULL;
60
unsigned modulusLen = 0;
61
SECStatus rv = SECFailure;
62
CMMFRand randStr= { {siBuffer, NULL, 0}, {siBuffer, NULL, 0}};
64
PK11SymKey *symKey = NULL;
66
CERTSubjectPublicKeyInfo *spki = NULL;
69
encodedRandNum = SEC_ASN1EncodeInteger(poolp, &challenge->randomNumber,
71
encodedRandNum = &challenge->randomNumber;
72
randHash = PORT_ArenaNewArray(poolp, unsigned char, SHA1_LENGTH);
73
senderHash = PORT_ArenaNewArray(poolp, unsigned char, SHA1_LENGTH);
74
if (randHash == NULL) {
77
rv = PK11_HashBuf(SEC_OID_SHA1, randHash, encodedRandNum->data,
78
(uint32)encodedRandNum->len);
79
if (rv != SECSuccess) {
82
rv = PK11_HashBuf(SEC_OID_SHA1, senderHash, senderDER->data,
83
(uint32)senderDER->len);
84
if (rv != SECSuccess) {
87
challenge->witness.data = randHash;
88
challenge->witness.len = SHA1_LENGTH;
90
randStr.integer = *encodedRandNum;
91
randStr.senderHash.data = senderHash;
92
randStr.senderHash.len = SHA1_LENGTH;
93
dummy = SEC_ASN1EncodeItem(NULL, &encodedRandStr, &randStr,
95
if (dummy != &encodedRandStr) {
99
/* XXXX Now I have to encrypt encodedRandStr and stash it away. */
100
modulusLen = SECKEY_PublicKeyStrength(inPubKey);
101
encChal = PORT_ArenaNewArray(poolp, unsigned char, modulusLen);
102
if (encChal == NULL) {
106
slot =PK11_GetBestSlot(CKM_RSA_PKCS, passwdArg);
111
id = PK11_ImportPublicKey(slot, inPubKey, PR_FALSE);
112
/* In order to properly encrypt the data, we import as a symmetric
113
* key, and then wrap that key. That in essence encrypts the data.
114
* This is the method recommended in the PK11 world in order
115
* to prevent threading issues as well as breaking any other semantics
116
* the PK11 libraries depend on.
118
symKey = PK11_ImportSymKey(slot, CKM_RSA_PKCS, PK11_OriginGenerated,
119
CKA_VALUE, &encodedRandStr, passwdArg);
120
if (symKey == NULL) {
124
challenge->challenge.data = encChal;
125
challenge->challenge.len = modulusLen;
126
rv = PK11_PubWrapSymKey(CKM_RSA_PKCS, inPubKey, symKey,
127
&challenge->challenge);
129
if (rv != SECSuccess) {
132
rv = SECITEM_CopyItem(poolp, &challenge->senderDER, senderDER);
133
crmf_get_public_value(inPubKey, &challenge->key);
137
SECKEY_DestroySubjectPublicKeyInfo(spki);
139
if (encodedRandStr.data != NULL) {
140
PORT_Free(encodedRandStr.data);
142
if (encodedRandNum != NULL) {
143
SECITEM_FreeItem(encodedRandNum, PR_TRUE);
145
if (symKey != NULL) {
146
PK11_FreeSymKey(symKey);
152
cmmf_create_first_challenge(CMMFPOPODecKeyChallContent *challContent,
155
SECKEYPublicKey *inPubKey,
159
CMMFChallenge *challenge;
160
SECAlgorithmID *algId;
164
oidData = SECOID_FindOIDByTag(SEC_OID_SHA1);
165
if (oidData == NULL) {
168
poolp = challContent->poolp;
169
challenge = PORT_ArenaZNew(poolp, CMMFChallenge);
170
if (challenge == NULL) {
173
algId = challenge->owf = PORT_ArenaZNew(poolp, SECAlgorithmID);
177
rv = SECITEM_CopyItem(poolp, &algId->algorithm, &oidData->oid);
178
if (rv != SECSuccess) {
181
rv = cmmf_create_witness_and_challenge(poolp, challenge, inRandom,
182
senderDER, inPubKey, passwdArg);
183
challContent->challenges[0] = (rv == SECSuccess) ? challenge : NULL;
184
challContent->numChallenges++;
188
CMMFPOPODecKeyChallContent*
189
CMMF_CreatePOPODecKeyChallContent (void)
192
CMMFPOPODecKeyChallContent *challContent;
194
poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
198
challContent = PORT_ArenaZNew(poolp, CMMFPOPODecKeyChallContent);
199
if (challContent == NULL) {
200
PORT_FreeArena(poolp, PR_FALSE);
203
challContent->poolp = poolp;
208
CMMF_POPODecKeyChallContentSetNextChallenge
209
(CMMFPOPODecKeyChallContent *inDecKeyChall,
211
CERTGeneralName *inSender,
212
SECKEYPublicKey *inPubKey,
215
CMMFChallenge *curChallenge;
216
PRArenaPool *genNamePool = NULL, *poolp;
221
PORT_Assert (inDecKeyChall != NULL &&
225
if (inDecKeyChall == NULL ||
226
inSender == NULL || inPubKey == NULL) {
229
poolp = inDecKeyChall->poolp;
230
mark = PORT_ArenaMark(poolp);
232
genNamePool = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
233
genNameDER = CERT_EncodeGeneralName(inSender, NULL, genNamePool);
234
if (genNameDER == NULL) {
238
if (inDecKeyChall->challenges == NULL) {
239
inDecKeyChall->challenges =
240
PORT_ArenaZNewArray(poolp, CMMFChallenge*,(CMMF_MAX_CHALLENGES+1));
241
inDecKeyChall->numAllocated = CMMF_MAX_CHALLENGES;
244
if (inDecKeyChall->numChallenges >= inDecKeyChall->numAllocated) {
249
if (inDecKeyChall->numChallenges == 0) {
250
rv = cmmf_create_first_challenge(inDecKeyChall, inRandom,
251
genNameDER, inPubKey, passwdArg);
253
curChallenge = PORT_ArenaZNew(poolp, CMMFChallenge);
254
if (curChallenge == NULL) {
258
rv = cmmf_create_witness_and_challenge(poolp, curChallenge, inRandom,
259
genNameDER, inPubKey,
261
if (rv == SECSuccess) {
262
inDecKeyChall->challenges[inDecKeyChall->numChallenges] =
264
inDecKeyChall->numChallenges++;
267
if (rv != SECSuccess) {
270
PORT_ArenaUnmark(poolp, mark);
271
PORT_FreeArena(genNamePool, PR_FALSE);
275
PORT_ArenaRelease(poolp, mark);
276
if (genNamePool != NULL) {
277
PORT_FreeArena(genNamePool, PR_FALSE);
279
PORT_Assert(rv != SECSuccess);
284
CMMF_DestroyPOPODecKeyRespContent(CMMFPOPODecKeyRespContent *inDecKeyResp)
286
PORT_Assert(inDecKeyResp != NULL);
287
if (inDecKeyResp != NULL && inDecKeyResp->poolp != NULL) {
288
PORT_FreeArena(inDecKeyResp->poolp, PR_FALSE);
294
CMMF_POPODecKeyRespContentGetNumResponses(CMMFPOPODecKeyRespContent *inRespCont)
296
int numResponses = 0;
298
PORT_Assert(inRespCont != NULL);
299
if (inRespCont == NULL) {
303
while (inRespCont->responses[numResponses] != NULL) {
310
CMMF_POPODecKeyRespContentGetResponse (CMMFPOPODecKeyRespContent *inRespCont,
314
PORT_Assert(inRespCont != NULL);
316
if (inRespCont == NULL || inIndex < 0 ||
317
inIndex >= CMMF_POPODecKeyRespContentGetNumResponses(inRespCont)) {
320
*inDest = DER_GetInteger(inRespCont->responses[inIndex]);
321
return (*inDest == -1) ? SECFailure : SECSuccess;