~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/security/nss/lib/softoken/lowcert.c

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * The contents of this file are subject to the Mozilla Public
 
3
 * License Version 1.1 (the "License"); you may not use this file
 
4
 * except in compliance with the License. You may obtain a copy of
 
5
 * the License at http://www.mozilla.org/MPL/
 
6
 * 
 
7
 * Software distributed under the License is distributed on an "AS
 
8
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 
9
 * implied. See the License for the specific language governing
 
10
 * rights and limitations under the License.
 
11
 * 
 
12
 * The Original Code is the Netscape security libraries.
 
13
 * 
 
14
 * The Initial Developer of the Original Code is Netscape
 
15
 * Communications Corporation.  Portions created by Netscape are 
 
16
 * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
 
17
 * Rights Reserved.
 
18
 * 
 
19
 * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003
 
20
 * Sun Microsystems, Inc. All Rights Reserved.
 
21
 *
 
22
 * Contributor(s):
 
23
 *      Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
 
24
 * 
 
25
 * Alternatively, the contents of this file may be used under the
 
26
 * terms of the GNU General Public License Version 2 or later (the
 
27
 * "GPL"), in which case the provisions of the GPL are applicable 
 
28
 * instead of those above.  If you wish to allow use of your 
 
29
 * version of this file only under the terms of the GPL and not to
 
30
 * allow others to use your version of this file under the MPL,
 
31
 * indicate your decision by deleting the provisions above and
 
32
 * replace them with the notice and other provisions required by
 
33
 * the GPL.  If you do not delete the provisions above, a recipient
 
34
 * may use your version of this file under either the MPL or the
 
35
 * GPL.
 
36
 */
 
37
 
 
38
/*
 
39
 * Certificate handling code
 
40
 *
 
41
 * $Id: lowcert.c,v 1.17 2004/01/07 23:07:24 jpierre%netscape.com Exp $
 
42
 */
 
43
 
 
44
#include "seccomon.h"
 
45
#include "secder.h"
 
46
#include "nssilock.h"
 
47
#include "prmon.h"
 
48
#include "prtime.h"
 
49
#include "lowkeyi.h"
 
50
#include "pcert.h"
 
51
#include "secasn1.h"
 
52
#include "secoid.h"
 
53
 
 
54
#ifdef NSS_ENABLE_ECC
 
55
extern SECStatus EC_FillParams(PRArenaPool *arena, 
 
56
                               const SECItem *encodedParams,
 
57
                               ECParams *params);
 
58
#endif
 
59
 
 
60
static const SEC_ASN1Template nsslowcert_SubjectPublicKeyInfoTemplate[] = {
 
61
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWCERTSubjectPublicKeyInfo) },
 
62
    { SEC_ASN1_INLINE, offsetof(NSSLOWCERTSubjectPublicKeyInfo,algorithm),
 
63
          SECOID_AlgorithmIDTemplate },
 
64
    { SEC_ASN1_BIT_STRING,
 
65
          offsetof(NSSLOWCERTSubjectPublicKeyInfo,subjectPublicKey), },
 
66
    { 0, }
 
67
};
 
68
 
 
69
static const SEC_ASN1Template nsslowcert_RSAPublicKeyTemplate[] = {
 
70
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPublicKey) },
 
71
    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.rsa.modulus), },
 
72
    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.rsa.publicExponent), },
 
73
    { 0, }
 
74
};
 
75
static const SEC_ASN1Template nsslowcert_DSAPublicKeyTemplate[] = {
 
76
    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.dsa.publicValue), },
 
77
    { 0, }
 
78
};
 
79
static const SEC_ASN1Template nsslowcert_DHPublicKeyTemplate[] = {
 
80
    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.dh.publicValue), },
 
81
    { 0, }
 
82
};
 
83
 
 
84
/*
 
85
 * See bugzilla bug 125359
 
86
 * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
 
87
 * all of the templates above that en/decode into integers must be converted
 
88
 * from ASN.1's signed integer type.  This is done by marking either the
 
89
 * source or destination (encoding or decoding, respectively) type as
 
90
 * siUnsignedInteger.
 
91
 */
 
92
 
 
93
static void
 
94
prepare_low_rsa_pub_key_for_asn1(NSSLOWKEYPublicKey *pubk)
 
95
{
 
96
    pubk->u.rsa.modulus.type = siUnsignedInteger;
 
97
    pubk->u.rsa.publicExponent.type = siUnsignedInteger;
 
98
}
 
99
 
 
100
static void
 
101
prepare_low_dsa_pub_key_for_asn1(NSSLOWKEYPublicKey *pubk)
 
102
{
 
103
    pubk->u.dsa.publicValue.type = siUnsignedInteger;
 
104
    pubk->u.dsa.params.prime.type = siUnsignedInteger;
 
105
    pubk->u.dsa.params.subPrime.type = siUnsignedInteger;
 
106
    pubk->u.dsa.params.base.type = siUnsignedInteger;
 
107
}
 
108
 
 
109
static void
 
110
prepare_low_dh_pub_key_for_asn1(NSSLOWKEYPublicKey *pubk)
 
111
{
 
112
    pubk->u.dh.prime.type = siUnsignedInteger;
 
113
    pubk->u.dh.base.type = siUnsignedInteger;
 
114
    pubk->u.dh.publicValue.type = siUnsignedInteger;
 
115
}
 
116
 
 
117
/*
 
118
 * Allow use of default cert database, so that apps(such as mozilla) don't
 
119
 * have to pass the handle all over the place.
 
120
 */
 
121
static NSSLOWCERTCertDBHandle *default_pcert_db_handle = 0;
 
122
 
 
123
void
 
124
nsslowcert_SetDefaultCertDB(NSSLOWCERTCertDBHandle *handle)
 
125
{
 
126
    default_pcert_db_handle = handle;
 
127
    
 
128
    return;
 
129
}
 
130
 
 
131
NSSLOWCERTCertDBHandle *
 
132
nsslowcert_GetDefaultCertDB(void)
 
133
{
 
134
    return(default_pcert_db_handle);
 
135
}
 
136
 
 
137
/*
 
138
 * simple cert decoder to avoid the cost of asn1 engine
 
139
 */ 
 
140
static unsigned char *
 
141
nsslowcert_dataStart(unsigned char *buf, unsigned int length, 
 
142
                        unsigned int *data_length, PRBool includeTag,
 
143
                        unsigned char* rettag) {
 
144
    unsigned char tag;
 
145
    unsigned int used_length= 0;
 
146
 
 
147
    tag = buf[used_length++];
 
148
 
 
149
    if (rettag) {
 
150
        *rettag = tag;
 
151
    }
 
152
 
 
153
    /* blow out when we come to the end */
 
154
    if (tag == 0) {
 
155
        return NULL;
 
156
    }
 
157
 
 
158
    *data_length = buf[used_length++];
 
159
 
 
160
    if (*data_length&0x80) {
 
161
        int  len_count = *data_length & 0x7f;
 
162
 
 
163
        *data_length = 0;
 
164
 
 
165
        while (len_count-- > 0) {
 
166
            *data_length = (*data_length << 8) | buf[used_length++];
 
167
        } 
 
168
    }
 
169
 
 
170
    if (*data_length > (length-used_length) ) {
 
171
        *data_length = length-used_length;
 
172
        return NULL;
 
173
    }
 
174
    if (includeTag) *data_length += used_length;
 
175
 
 
176
    return (buf + (includeTag ? 0 : used_length));      
 
177
}
 
178
 
 
179
static void SetTimeType(SECItem* item, unsigned char tagtype)
 
180
{
 
181
    switch (tagtype) {
 
182
        case SEC_ASN1_UTC_TIME:
 
183
            item->type = siUTCTime;
 
184
            break;
 
185
 
 
186
        case SEC_ASN1_GENERALIZED_TIME:
 
187
            item->type = siGeneralizedTime;
 
188
            break;
 
189
 
 
190
        default:
 
191
            PORT_Assert(0);
 
192
            break;
 
193
    }
 
194
}
 
195
 
 
196
static int
 
197
nsslowcert_GetValidityFields(unsigned char *buf,int buf_length,
 
198
        SECItem *notBefore, SECItem *notAfter)
 
199
{
 
200
    unsigned char tagtype;
 
201
    notBefore->data = nsslowcert_dataStart(buf,buf_length,
 
202
                                                &notBefore->len,PR_FALSE, &tagtype);
 
203
    if (notBefore->data == NULL) return SECFailure;
 
204
    SetTimeType(notBefore, tagtype);
 
205
    buf_length -= (notBefore->data-buf) + notBefore->len;
 
206
    buf = notBefore->data + notBefore->len;
 
207
    notAfter->data = nsslowcert_dataStart(buf,buf_length,
 
208
                                                &notAfter->len,PR_FALSE, &tagtype);
 
209
    if (notAfter->data == NULL) return SECFailure;
 
210
    SetTimeType(notAfter, tagtype);
 
211
    return SECSuccess;
 
212
}
 
213
 
 
214
static int
 
215
nsslowcert_GetCertFields(unsigned char *cert,int cert_length,
 
216
        SECItem *issuer, SECItem *serial, SECItem *derSN, SECItem *subject,
 
217
        SECItem *valid, SECItem *subjkey)
 
218
{
 
219
    unsigned char *buf;
 
220
    unsigned int buf_length;
 
221
    unsigned char *dummy;
 
222
    unsigned int dummylen;
 
223
 
 
224
    /* get past the signature wrap */
 
225
    buf = nsslowcert_dataStart(cert,cert_length,&buf_length,PR_FALSE, NULL);
 
226
    if (buf == NULL) return SECFailure;
 
227
    /* get into the raw cert data */
 
228
    buf = nsslowcert_dataStart(buf,buf_length,&buf_length,PR_FALSE, NULL);
 
229
    if (buf == NULL) return SECFailure;
 
230
    /* skip past any optional version number */
 
231
    if ((buf[0] & 0xa0) == 0xa0) {
 
232
        dummy = nsslowcert_dataStart(buf,buf_length,&dummylen,PR_FALSE, NULL);
 
233
        if (dummy == NULL) return SECFailure;
 
234
        buf_length -= (dummy-buf) + dummylen;
 
235
        buf = dummy + dummylen;
 
236
    }
 
237
    /* serial number */
 
238
    if (derSN) {
 
239
        derSN->data=nsslowcert_dataStart(buf,buf_length,&derSN->len,PR_TRUE, NULL);
 
240
    }
 
241
    serial->data = nsslowcert_dataStart(buf,buf_length,&serial->len,PR_FALSE, NULL);
 
242
    if (serial->data == NULL) return SECFailure;
 
243
    buf_length -= (serial->data-buf) + serial->len;
 
244
    buf = serial->data + serial->len;
 
245
    /* skip the OID */
 
246
    dummy = nsslowcert_dataStart(buf,buf_length,&dummylen,PR_FALSE, NULL);
 
247
    if (dummy == NULL) return SECFailure;
 
248
    buf_length -= (dummy-buf) + dummylen;
 
249
    buf = dummy + dummylen;
 
250
    /* issuer */
 
251
    issuer->data = nsslowcert_dataStart(buf,buf_length,&issuer->len,PR_TRUE, NULL);
 
252
    if (issuer->data == NULL) return SECFailure;
 
253
    buf_length -= (issuer->data-buf) + issuer->len;
 
254
    buf = issuer->data + issuer->len;
 
255
 
 
256
    /* only wanted issuer/SN */
 
257
    if (valid == NULL) {
 
258
        return SECSuccess;
 
259
    }
 
260
    /* validity */
 
261
    valid->data = nsslowcert_dataStart(buf,buf_length,&valid->len,PR_FALSE, NULL);
 
262
    if (valid->data == NULL) return SECFailure;
 
263
    buf_length -= (valid->data-buf) + valid->len;
 
264
    buf = valid->data + valid->len;
 
265
    /*subject */
 
266
    subject->data=nsslowcert_dataStart(buf,buf_length,&subject->len,PR_TRUE, NULL);
 
267
    if (subject->data == NULL) return SECFailure;
 
268
    buf_length -= (subject->data-buf) + subject->len;
 
269
    buf = subject->data + subject->len;
 
270
    /* subject  key info */
 
271
    subjkey->data=nsslowcert_dataStart(buf,buf_length,&subjkey->len,PR_TRUE, NULL);
 
272
    if (subjkey->data == NULL) return SECFailure;
 
273
    buf_length -= (subjkey->data-buf) + subjkey->len;
 
274
    buf = subjkey->data + subjkey->len;
 
275
    return SECSuccess;
 
276
}
 
277
 
 
278
SECStatus
 
279
nsslowcert_GetCertTimes(NSSLOWCERTCertificate *c, PRTime *notBefore, PRTime *notAfter)
 
280
{
 
281
    int rv;
 
282
    NSSLOWCERTValidity validity;
 
283
 
 
284
    rv = nsslowcert_GetValidityFields(c->validity.data,c->validity.len,
 
285
                                &validity.notBefore,&validity.notAfter);
 
286
    if (rv != SECSuccess) {
 
287
        return rv;
 
288
    }
 
289
    
 
290
    /* convert DER not-before time */
 
291
    rv = DER_DecodeTimeChoice(notBefore, &validity.notBefore);
 
292
    if (rv) {
 
293
        return(SECFailure);
 
294
    }
 
295
    
 
296
    /* convert DER not-after time */
 
297
    rv = DER_DecodeTimeChoice(notAfter, &validity.notAfter);
 
298
    if (rv) {
 
299
        return(SECFailure);
 
300
    }
 
301
 
 
302
    return(SECSuccess);
 
303
}
 
304
 
 
305
/*
 
306
 * is certa newer than certb?  If one is expired, pick the other one.
 
307
 */
 
308
PRBool
 
309
nsslowcert_IsNewer(NSSLOWCERTCertificate *certa, NSSLOWCERTCertificate *certb)
 
310
{
 
311
    PRTime notBeforeA, notAfterA, notBeforeB, notAfterB, now;
 
312
    SECStatus rv;
 
313
    PRBool newerbefore, newerafter;
 
314
    
 
315
    rv = nsslowcert_GetCertTimes(certa, &notBeforeA, &notAfterA);
 
316
    if ( rv != SECSuccess ) {
 
317
        return(PR_FALSE);
 
318
    }
 
319
    
 
320
    rv = nsslowcert_GetCertTimes(certb, &notBeforeB, &notAfterB);
 
321
    if ( rv != SECSuccess ) {
 
322
        return(PR_TRUE);
 
323
    }
 
324
 
 
325
    newerbefore = PR_FALSE;
 
326
    if ( LL_CMP(notBeforeA, >, notBeforeB) ) {
 
327
        newerbefore = PR_TRUE;
 
328
    }
 
329
 
 
330
    newerafter = PR_FALSE;
 
331
    if ( LL_CMP(notAfterA, >, notAfterB) ) {
 
332
        newerafter = PR_TRUE;
 
333
    }
 
334
    
 
335
    if ( newerbefore && newerafter ) {
 
336
        return(PR_TRUE);
 
337
    }
 
338
    
 
339
    if ( ( !newerbefore ) && ( !newerafter ) ) {
 
340
        return(PR_FALSE);
 
341
    }
 
342
 
 
343
    /* get current time */
 
344
    now = PR_Now();
 
345
 
 
346
    if ( newerbefore ) {
 
347
        /* cert A was issued after cert B, but expires sooner */
 
348
        /* if A is expired, then pick B */
 
349
        if ( LL_CMP(notAfterA, <, now ) ) {
 
350
            return(PR_FALSE);
 
351
        }
 
352
        return(PR_TRUE);
 
353
    } else {
 
354
        /* cert B was issued after cert A, but expires sooner */
 
355
        /* if B is expired, then pick A */
 
356
        if ( LL_CMP(notAfterB, <, now ) ) {
 
357
            return(PR_TRUE);
 
358
        }
 
359
        return(PR_FALSE);
 
360
    }
 
361
}
 
362
 
 
363
#define SOFT_DEFAULT_CHUNKSIZE 2048
 
364
 
 
365
 
 
366
static SECStatus
 
367
nsslowcert_KeyFromIssuerAndSN(PRArenaPool *arena, SECItem *issuer, SECItem *sn,
 
368
                        SECItem *key)
 
369
{
 
370
    unsigned int len = sn->len + issuer->len;
 
371
 
 
372
 
 
373
    if (arena) {
 
374
        key->data = (unsigned char*)PORT_ArenaAlloc(arena, len);
 
375
    } else {
 
376
        if (len > key->len) {
 
377
            key->data = (unsigned char*)PORT_ArenaAlloc(arena, len);
 
378
        }
 
379
    }
 
380
    if ( !key->data ) {
 
381
        goto loser;
 
382
    }
 
383
 
 
384
    key->len = len;
 
385
    /* copy the serialNumber */
 
386
    PORT_Memcpy(key->data, sn->data, sn->len);
 
387
 
 
388
    /* copy the issuer */
 
389
    PORT_Memcpy(&key->data[sn->len], issuer->data, issuer->len);
 
390
 
 
391
    return(SECSuccess);
 
392
 
 
393
loser:
 
394
    return(SECFailure);
 
395
}
 
396
 
 
397
 
 
398
 
 
399
/*
 
400
 * take a DER certificate and decode it into a certificate structure
 
401
 */
 
402
NSSLOWCERTCertificate *
 
403
nsslowcert_DecodeDERCertificate(SECItem *derSignedCert, char *nickname)
 
404
{
 
405
    NSSLOWCERTCertificate *cert;
 
406
    int rv;
 
407
 
 
408
    /* allocate the certificate structure */
 
409
    cert = nsslowcert_CreateCert();
 
410
    
 
411
    if ( !cert ) {
 
412
        goto loser;
 
413
    }
 
414
    
 
415
        /* point to passed in DER data */
 
416
    cert->derCert = *derSignedCert;
 
417
    cert->nickname = NULL;
 
418
    cert->certKey.data = NULL;
 
419
    cert->referenceCount = 1;
 
420
 
 
421
    /* decode the certificate info */
 
422
    rv = nsslowcert_GetCertFields(cert->derCert.data, cert->derCert.len,
 
423
        &cert->derIssuer, &cert->serialNumber, &cert->derSN, &cert->derSubject,
 
424
        &cert->validity, &cert->derSubjKeyInfo);
 
425
 
 
426
    /* cert->subjectKeyID;       x509v3 subject key identifier */
 
427
    cert->subjectKeyID.data = NULL;
 
428
    cert->subjectKeyID.len = 0;
 
429
    cert->dbEntry = NULL;
 
430
    cert ->trust = NULL;
 
431
 
 
432
    /* generate and save the database key for the cert */
 
433
    cert->certKey.data = cert->certKeySpace;
 
434
    cert->certKey.len = sizeof(cert->certKeySpace);
 
435
    rv = nsslowcert_KeyFromIssuerAndSN(NULL, &cert->derIssuer, 
 
436
                                        &cert->serialNumber, &cert->certKey);
 
437
    if ( rv ) {
 
438
        goto loser;
 
439
    }
 
440
 
 
441
    /* set the nickname */
 
442
    if ( nickname == NULL ) {
 
443
        cert->nickname = NULL;
 
444
    } else {
 
445
        /* copy and install the nickname */
 
446
        cert->nickname = pkcs11_copyNickname(nickname,cert->nicknameSpace,
 
447
                                sizeof(cert->nicknameSpace));
 
448
    }
 
449
 
 
450
#ifdef FIXME
 
451
    /* initialize the subjectKeyID */
 
452
    rv = cert_GetKeyID(cert);
 
453
    if ( rv != SECSuccess ) {
 
454
        goto loser;
 
455
    }
 
456
 
 
457
    /* set the email address */
 
458
    cert->emailAddr = CERT_GetCertificateEmailAddress(cert);
 
459
    
 
460
#endif
 
461
    
 
462
    cert->referenceCount = 1;
 
463
    
 
464
    return(cert);
 
465
    
 
466
loser:
 
467
    if (cert) {
 
468
        nsslowcert_DestroyCertificate(cert);
 
469
    }
 
470
    
 
471
    return(0);
 
472
}
 
473
 
 
474
char *
 
475
nsslowcert_FixupEmailAddr(char *emailAddr)
 
476
{
 
477
    char *retaddr;
 
478
    char *str;
 
479
 
 
480
    if ( emailAddr == NULL ) {
 
481
        return(NULL);
 
482
    }
 
483
    
 
484
    /* copy the string */
 
485
    str = retaddr = PORT_Strdup(emailAddr);
 
486
    if ( str == NULL ) {
 
487
        return(NULL);
 
488
    }
 
489
    
 
490
    /* make it lower case */
 
491
    while ( *str ) {
 
492
        *str = tolower( *str );
 
493
        str++;
 
494
    }
 
495
    
 
496
    return(retaddr);
 
497
}
 
498
 
 
499
 
 
500
/*
 
501
 * Generate a database key, based on serial number and issuer, from a
 
502
 * DER certificate.
 
503
 */
 
504
SECStatus
 
505
nsslowcert_KeyFromDERCert(PRArenaPool *arena, SECItem *derCert, SECItem *key)
 
506
{
 
507
    int rv;
 
508
    NSSLOWCERTCertKey certkey;
 
509
 
 
510
    PORT_Memset(&certkey, 0, sizeof(NSSLOWCERTCertKey));    
 
511
 
 
512
    rv = nsslowcert_GetCertFields(derCert->data, derCert->len,
 
513
        &certkey.derIssuer, &certkey.serialNumber, NULL, NULL, NULL, NULL);
 
514
 
 
515
    if ( rv ) {
 
516
        goto loser;
 
517
    }
 
518
 
 
519
    return(nsslowcert_KeyFromIssuerAndSN(arena, &certkey.derIssuer,
 
520
                                   &certkey.serialNumber, key));
 
521
loser:
 
522
    return(SECFailure);
 
523
}
 
524
 
 
525
NSSLOWKEYPublicKey *
 
526
nsslowcert_ExtractPublicKey(NSSLOWCERTCertificate *cert)
 
527
{
 
528
    NSSLOWCERTSubjectPublicKeyInfo spki;
 
529
    NSSLOWKEYPublicKey *pubk;
 
530
    SECItem os;
 
531
    SECStatus rv;
 
532
    PRArenaPool *arena;
 
533
    SECOidTag tag;
 
534
    SECItem newDerSubjKeyInfo;
 
535
 
 
536
    arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
 
537
    if (arena == NULL)
 
538
        return NULL;
 
539
 
 
540
    pubk = (NSSLOWKEYPublicKey *) 
 
541
                PORT_ArenaZAlloc(arena, sizeof(NSSLOWKEYPublicKey));
 
542
    if (pubk == NULL) {
 
543
        PORT_FreeArena (arena, PR_FALSE);
 
544
        return NULL;
 
545
    }
 
546
 
 
547
    pubk->arena = arena;
 
548
    PORT_Memset(&spki,0,sizeof(spki));
 
549
 
 
550
    /* copy the DER into the arena, since Quick DER returns data that points
 
551
       into the DER input, which may get freed by the caller */
 
552
    rv = SECITEM_CopyItem(arena, &newDerSubjKeyInfo, &cert->derSubjKeyInfo);
 
553
    if ( rv != SECSuccess ) {
 
554
        PORT_FreeArena (arena, PR_FALSE);
 
555
        return NULL;
 
556
    }
 
557
 
 
558
    /* we haven't bothered decoding the spki struct yet, do it now */
 
559
    rv = SEC_QuickDERDecodeItem(arena, &spki, 
 
560
                nsslowcert_SubjectPublicKeyInfoTemplate, &newDerSubjKeyInfo);
 
561
    if (rv != SECSuccess) {
 
562
        PORT_FreeArena (arena, PR_FALSE);
 
563
        return NULL;
 
564
    }
 
565
 
 
566
    /* Convert bit string length from bits to bytes */
 
567
    os = spki.subjectPublicKey;
 
568
    DER_ConvertBitString (&os);
 
569
 
 
570
    tag = SECOID_GetAlgorithmTag(&spki.algorithm);
 
571
    switch ( tag ) {
 
572
      case SEC_OID_X500_RSA_ENCRYPTION:
 
573
      case SEC_OID_PKCS1_RSA_ENCRYPTION:
 
574
        pubk->keyType = NSSLOWKEYRSAKey;
 
575
        prepare_low_rsa_pub_key_for_asn1(pubk);
 
576
        rv = SEC_QuickDERDecodeItem(arena, pubk, 
 
577
                                nsslowcert_RSAPublicKeyTemplate, &os);
 
578
        if (rv == SECSuccess)
 
579
            return pubk;
 
580
        break;
 
581
      case SEC_OID_ANSIX9_DSA_SIGNATURE:
 
582
        pubk->keyType = NSSLOWKEYDSAKey;
 
583
        prepare_low_dsa_pub_key_for_asn1(pubk);
 
584
        rv = SEC_QuickDERDecodeItem(arena, pubk,
 
585
                                 nsslowcert_DSAPublicKeyTemplate, &os);
 
586
        if (rv == SECSuccess) return pubk;
 
587
        break;
 
588
      case SEC_OID_X942_DIFFIE_HELMAN_KEY:
 
589
        pubk->keyType = NSSLOWKEYDHKey;
 
590
        prepare_low_dh_pub_key_for_asn1(pubk);
 
591
        rv = SEC_QuickDERDecodeItem(arena, pubk,
 
592
                                 nsslowcert_DHPublicKeyTemplate, &os);
 
593
        if (rv == SECSuccess) return pubk;
 
594
        break;
 
595
#ifdef NSS_ENABLE_ECC
 
596
      case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
 
597
        pubk->keyType = NSSLOWKEYECKey;
 
598
        /* Since PKCS#11 directly takes the DER encoding of EC params
 
599
         * and public value, we don't need any decoding here.
 
600
         */
 
601
        rv = SECITEM_CopyItem(arena, &pubk->u.ec.ecParams.DEREncoding, 
 
602
            &spki.algorithm.parameters);
 
603
        if ( rv != SECSuccess )
 
604
            break;      
 
605
 
 
606
        /* Fill out the rest of the ecParams structure 
 
607
         * based on the encoded params
 
608
         */
 
609
        if (EC_FillParams(arena, &pubk->u.ec.ecParams.DEREncoding,
 
610
            &pubk->u.ec.ecParams) != SECSuccess) 
 
611
            break;
 
612
 
 
613
        rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue, &os);
 
614
        if (rv == SECSuccess) return pubk;
 
615
        break;
 
616
#endif /* NSS_ENABLE_ECC */
 
617
      default:
 
618
        rv = SECFailure;
 
619
        break;
 
620
    }
 
621
 
 
622
    nsslowkey_DestroyPublicKey (pubk);
 
623
    return NULL;
 
624
}
 
625