~ubuntu-branches/ubuntu/lucid/seamonkey/lucid-security

« back to all changes in this revision

Viewing changes to security/nss-fips/lib/crmf/cmmfchal.c

  • Committer: Bazaar Package Importer
  • Author(s): Fabien Tassin
  • Date: 2008-07-29 21:29:02 UTC
  • mfrom: (1.1.4 upstream)
  • Revision ID: james.westby@ubuntu.com-20080729212902-spm9kpvchp9udwbw
Tags: 1.1.11+nobinonly-0ubuntu1
* New security upstream release: 1.1.11 (LP: #218534)
  Fixes USN-602-1, USN-619-1, USN-623-1 and USN-629-1
* Refresh diverged patch:
  - update debian/patches/80_security_build.patch
* Fix FTBFS with missing -lfontconfig
  - add debian/patches/11_fix_ftbfs_with_fontconfig.patch
  - update debian/patches/series
* Build with default gcc (hardy: 4.2, intrepid: 4.3)
  - update debian/rules
  - update debian/control

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8 -*-*/
 
2
/* ***** BEGIN LICENSE BLOCK *****
 
3
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
4
 *
 
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/
 
9
 *
 
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.
 
14
 *
 
15
 * The Original Code is the Netscape security libraries.
 
16
 *
 
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.
 
21
 *
 
22
 * Contributor(s):
 
23
 *
 
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.
 
35
 *
 
36
 * ***** END LICENSE BLOCK ***** */
 
37
 
 
38
#include "cmmf.h"
 
39
#include "cmmfi.h"
 
40
#include "sechash.h"
 
41
#include "genname.h"
 
42
#include "pk11func.h"
 
43
#include "cert.h"
 
44
#include "secitem.h"
 
45
#include "secmod.h"
 
46
#include "keyhi.h"
 
47
 
 
48
static int
 
49
cmmf_create_witness_and_challenge(PRArenaPool     *poolp,
 
50
                                  CMMFChallenge   *challenge,
 
51
                                  long             inRandom,
 
52
                                  SECItem         *senderDER,
 
53
                                  SECKEYPublicKey *inPubKey,
 
54
                                  void            *passwdArg)
 
55
{
 
56
    SECItem       *encodedRandNum;
 
57
    SECItem        encodedRandStr = {siBuffer, NULL, 0};
 
58
    SECItem       *dummy;
 
59
    unsigned char *randHash, *senderHash, *encChal=NULL;
 
60
    unsigned       modulusLen = 0;
 
61
    SECStatus      rv = SECFailure;
 
62
    CMMFRand       randStr= { {siBuffer, NULL, 0}, {siBuffer, NULL, 0}};
 
63
    PK11SlotInfo  *slot;
 
64
    PK11SymKey    *symKey = NULL;
 
65
    CK_OBJECT_HANDLE id;
 
66
    CERTSubjectPublicKeyInfo *spki = NULL;
 
67
 
 
68
    
 
69
    encodedRandNum = SEC_ASN1EncodeInteger(poolp, &challenge->randomNumber,
 
70
                                           inRandom);
 
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) {
 
75
        goto loser;
 
76
    }
 
77
    rv = PK11_HashBuf(SEC_OID_SHA1, randHash, encodedRandNum->data, 
 
78
                      (uint32)encodedRandNum->len);
 
79
    if (rv != SECSuccess) {
 
80
        goto loser;
 
81
    }
 
82
    rv = PK11_HashBuf(SEC_OID_SHA1, senderHash, senderDER->data,
 
83
                      (uint32)senderDER->len);
 
84
    if (rv != SECSuccess) {
 
85
        goto loser;
 
86
    }
 
87
    challenge->witness.data = randHash;
 
88
    challenge->witness.len  = SHA1_LENGTH;
 
89
 
 
90
    randStr.integer    = *encodedRandNum;
 
91
    randStr.senderHash.data = senderHash;
 
92
    randStr.senderHash.len  = SHA1_LENGTH;
 
93
    dummy = SEC_ASN1EncodeItem(NULL, &encodedRandStr, &randStr, 
 
94
                               CMMFRandTemplate);
 
95
    if (dummy != &encodedRandStr) {
 
96
        rv = SECFailure;
 
97
        goto loser;
 
98
    }
 
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) {
 
103
        rv = SECFailure;
 
104
        goto loser;
 
105
    }
 
106
    slot =PK11_GetBestSlot(CKM_RSA_PKCS, passwdArg);
 
107
    if (slot == NULL) {
 
108
        rv = SECFailure;
 
109
        goto loser;
 
110
    }
 
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.
 
117
     */
 
118
    symKey = PK11_ImportSymKey(slot, CKM_RSA_PKCS, PK11_OriginGenerated,
 
119
                               CKA_VALUE, &encodedRandStr, passwdArg);
 
120
    if (symKey == NULL) {
 
121
        rv = SECFailure;
 
122
        goto loser;
 
123
    }
 
124
    challenge->challenge.data = encChal;
 
125
    challenge->challenge.len  = modulusLen;
 
126
    rv = PK11_PubWrapSymKey(CKM_RSA_PKCS, inPubKey, symKey, 
 
127
                            &challenge->challenge);
 
128
    PK11_FreeSlot(slot);
 
129
    if (rv != SECSuccess) {
 
130
        goto loser;
 
131
    }
 
132
    rv = SECITEM_CopyItem(poolp, &challenge->senderDER, senderDER);
 
133
    crmf_get_public_value(inPubKey, &challenge->key);
 
134
    /* Fall through */
 
135
 loser:
 
136
    if (spki != NULL) {
 
137
        SECKEY_DestroySubjectPublicKeyInfo(spki);
 
138
    }
 
139
    if (encodedRandStr.data != NULL) {
 
140
        PORT_Free(encodedRandStr.data);
 
141
    }
 
142
    if (encodedRandNum != NULL) {
 
143
        SECITEM_FreeItem(encodedRandNum, PR_TRUE);
 
144
    }
 
145
    if (symKey != NULL) {
 
146
        PK11_FreeSymKey(symKey);
 
147
    }
 
148
    return rv;
 
149
}
 
150
 
 
151
static SECStatus
 
152
cmmf_create_first_challenge(CMMFPOPODecKeyChallContent *challContent, 
 
153
                            long                        inRandom, 
 
154
                            SECItem                    *senderDER, 
 
155
                            SECKEYPublicKey            *inPubKey,
 
156
                            void                       *passwdArg)
 
157
{
 
158
    SECOidData     *oidData;
 
159
    CMMFChallenge  *challenge;
 
160
    SECAlgorithmID *algId;
 
161
    PRArenaPool    *poolp;
 
162
    SECStatus       rv;
 
163
 
 
164
    oidData = SECOID_FindOIDByTag(SEC_OID_SHA1);
 
165
    if (oidData == NULL) {
 
166
        return SECFailure;
 
167
    }
 
168
    poolp = challContent->poolp;
 
169
    challenge = PORT_ArenaZNew(poolp, CMMFChallenge);
 
170
    if (challenge == NULL) {
 
171
        return SECFailure;
 
172
    }
 
173
    algId = challenge->owf = PORT_ArenaZNew(poolp, SECAlgorithmID);
 
174
    if (algId == NULL) {
 
175
        return SECFailure;
 
176
    }
 
177
    rv = SECITEM_CopyItem(poolp, &algId->algorithm, &oidData->oid);
 
178
    if (rv != SECSuccess) {
 
179
        return SECFailure;
 
180
    }
 
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++;
 
185
    return rv ;
 
186
}
 
187
 
 
188
CMMFPOPODecKeyChallContent*
 
189
CMMF_CreatePOPODecKeyChallContent (void)
 
190
{
 
191
    PRArenaPool *poolp;
 
192
    CMMFPOPODecKeyChallContent *challContent;
 
193
 
 
194
    poolp = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
 
195
    if (poolp == NULL) {
 
196
        return NULL;
 
197
    }
 
198
    challContent = PORT_ArenaZNew(poolp, CMMFPOPODecKeyChallContent);
 
199
    if (challContent == NULL) {
 
200
        PORT_FreeArena(poolp, PR_FALSE);
 
201
        return NULL;
 
202
    }
 
203
    challContent->poolp = poolp;
 
204
    return challContent;
 
205
}
 
206
 
 
207
SECStatus
 
208
CMMF_POPODecKeyChallContentSetNextChallenge
 
209
                                    (CMMFPOPODecKeyChallContent *inDecKeyChall,
 
210
                                     long                        inRandom,
 
211
                                     CERTGeneralName            *inSender,
 
212
                                     SECKEYPublicKey            *inPubKey,
 
213
                                     void                       *passwdArg)
 
214
{
 
215
    CMMFChallenge               *curChallenge;
 
216
    PRArenaPool                 *genNamePool = NULL, *poolp;
 
217
    SECStatus                    rv;
 
218
    SECItem                     *genNameDER;
 
219
    void                        *mark;
 
220
 
 
221
    PORT_Assert (inDecKeyChall != NULL &&
 
222
                 inSender      != NULL &&
 
223
                 inPubKey      != NULL);
 
224
 
 
225
    if (inDecKeyChall == NULL || 
 
226
        inSender      == NULL || inPubKey == NULL) {
 
227
        return SECFailure;
 
228
    }
 
229
    poolp = inDecKeyChall->poolp;
 
230
    mark = PORT_ArenaMark(poolp);
 
231
 
 
232
    genNamePool = PORT_NewArena(CRMF_DEFAULT_ARENA_SIZE);
 
233
    genNameDER = CERT_EncodeGeneralName(inSender, NULL, genNamePool);
 
234
    if (genNameDER == NULL) {
 
235
        rv = SECFailure;
 
236
        goto loser;
 
237
    }
 
238
    if (inDecKeyChall->challenges == NULL) {
 
239
        inDecKeyChall->challenges =
 
240
            PORT_ArenaZNewArray(poolp, CMMFChallenge*,(CMMF_MAX_CHALLENGES+1));
 
241
        inDecKeyChall->numAllocated = CMMF_MAX_CHALLENGES;
 
242
    }
 
243
 
 
244
    if (inDecKeyChall->numChallenges >= inDecKeyChall->numAllocated) {
 
245
        rv = SECFailure;
 
246
        goto loser;
 
247
    }
 
248
 
 
249
    if (inDecKeyChall->numChallenges == 0) {
 
250
        rv = cmmf_create_first_challenge(inDecKeyChall, inRandom, 
 
251
                                         genNameDER, inPubKey, passwdArg);
 
252
    } else {
 
253
        curChallenge = PORT_ArenaZNew(poolp, CMMFChallenge);
 
254
        if (curChallenge == NULL) {
 
255
            rv = SECFailure;
 
256
            goto loser;
 
257
        }
 
258
        rv = cmmf_create_witness_and_challenge(poolp, curChallenge, inRandom, 
 
259
                                               genNameDER, inPubKey, 
 
260
                                               passwdArg);
 
261
        if (rv == SECSuccess) {
 
262
            inDecKeyChall->challenges[inDecKeyChall->numChallenges] =
 
263
                curChallenge;
 
264
            inDecKeyChall->numChallenges++;
 
265
        }
 
266
    }
 
267
    if (rv != SECSuccess) {
 
268
        goto loser;
 
269
    }
 
270
    PORT_ArenaUnmark(poolp, mark);
 
271
    PORT_FreeArena(genNamePool, PR_FALSE);
 
272
    return SECSuccess;
 
273
 
 
274
 loser:
 
275
    PORT_ArenaRelease(poolp, mark);
 
276
    if (genNamePool != NULL) {
 
277
        PORT_FreeArena(genNamePool, PR_FALSE);
 
278
    }
 
279
    PORT_Assert(rv != SECSuccess);
 
280
    return rv;
 
281
}
 
282
 
 
283
SECStatus
 
284
CMMF_DestroyPOPODecKeyRespContent(CMMFPOPODecKeyRespContent *inDecKeyResp)
 
285
{
 
286
    PORT_Assert(inDecKeyResp != NULL);
 
287
    if (inDecKeyResp != NULL && inDecKeyResp->poolp != NULL) {
 
288
        PORT_FreeArena(inDecKeyResp->poolp, PR_FALSE);
 
289
    }
 
290
    return SECSuccess;
 
291
}
 
292
 
 
293
int 
 
294
CMMF_POPODecKeyRespContentGetNumResponses(CMMFPOPODecKeyRespContent *inRespCont)
 
295
{
 
296
    int numResponses = 0;
 
297
 
 
298
    PORT_Assert(inRespCont != NULL);
 
299
    if (inRespCont == NULL) {
 
300
        return 0;
 
301
    }
 
302
 
 
303
    while (inRespCont->responses[numResponses] != NULL) {
 
304
        numResponses ++;
 
305
    }
 
306
    return numResponses;
 
307
}
 
308
 
 
309
SECStatus
 
310
CMMF_POPODecKeyRespContentGetResponse (CMMFPOPODecKeyRespContent *inRespCont,
 
311
                                       int                        inIndex,
 
312
                                       long                      *inDest)
 
313
{
 
314
    PORT_Assert(inRespCont != NULL);
 
315
    
 
316
    if (inRespCont == NULL || inIndex < 0 || 
 
317
        inIndex >= CMMF_POPODecKeyRespContentGetNumResponses(inRespCont)) {
 
318
        return SECFailure;
 
319
    }
 
320
    *inDest = DER_GetInteger(inRespCont->responses[inIndex]);
 
321
    return (*inDest == -1) ? SECFailure : SECSuccess;
 
322
}