comparison nss/lib/softoken/legacydb/lowcert.c @ 3:150b72113545

Add DBM and legacydb support
author Andre Heinecke <andre.heinecke@intevation.de>
date Tue, 05 Aug 2014 18:32:02 +0200
parents
children
comparison
equal deleted inserted replaced
2:a945361df361 3:150b72113545
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 /*
6 * Certificate handling code
7 */
8
9 #include "seccomon.h"
10 #include "secder.h"
11 #include "nssilock.h"
12 #include "lowkeyi.h"
13 #include "secasn1.h"
14 #include "secoid.h"
15 #include "secerr.h"
16 #include "pcert.h"
17
18 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
19
20 static const SEC_ASN1Template nsslowcert_SubjectPublicKeyInfoTemplate[] = {
21 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWCERTSubjectPublicKeyInfo) },
22 { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
23 offsetof(NSSLOWCERTSubjectPublicKeyInfo,algorithm),
24 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
25 { SEC_ASN1_BIT_STRING,
26 offsetof(NSSLOWCERTSubjectPublicKeyInfo,subjectPublicKey), },
27 { 0, }
28 };
29
30 static const SEC_ASN1Template nsslowcert_RSAPublicKeyTemplate[] = {
31 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPublicKey) },
32 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.rsa.modulus), },
33 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.rsa.publicExponent), },
34 { 0, }
35 };
36 static const SEC_ASN1Template nsslowcert_DSAPublicKeyTemplate[] = {
37 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.dsa.publicValue), },
38 { 0, }
39 };
40 static const SEC_ASN1Template nsslowcert_DHPublicKeyTemplate[] = {
41 { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey,u.dh.publicValue), },
42 { 0, }
43 };
44
45 /*
46 * See bugzilla bug 125359
47 * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
48 * all of the templates above that en/decode into integers must be converted
49 * from ASN.1's signed integer type. This is done by marking either the
50 * source or destination (encoding or decoding, respectively) type as
51 * siUnsignedInteger.
52 */
53
54 static void
55 prepare_low_rsa_pub_key_for_asn1(NSSLOWKEYPublicKey *pubk)
56 {
57 pubk->u.rsa.modulus.type = siUnsignedInteger;
58 pubk->u.rsa.publicExponent.type = siUnsignedInteger;
59 }
60
61 static void
62 prepare_low_dsa_pub_key_for_asn1(NSSLOWKEYPublicKey *pubk)
63 {
64 pubk->u.dsa.publicValue.type = siUnsignedInteger;
65 pubk->u.dsa.params.prime.type = siUnsignedInteger;
66 pubk->u.dsa.params.subPrime.type = siUnsignedInteger;
67 pubk->u.dsa.params.base.type = siUnsignedInteger;
68 }
69
70 static void
71 prepare_low_dh_pub_key_for_asn1(NSSLOWKEYPublicKey *pubk)
72 {
73 pubk->u.dh.prime.type = siUnsignedInteger;
74 pubk->u.dh.base.type = siUnsignedInteger;
75 pubk->u.dh.publicValue.type = siUnsignedInteger;
76 }
77
78 /*
79 * simple cert decoder to avoid the cost of asn1 engine
80 */
81 static unsigned char *
82 nsslowcert_dataStart(unsigned char *buf, unsigned int length,
83 unsigned int *data_length, PRBool includeTag,
84 unsigned char* rettag) {
85 unsigned char tag;
86 unsigned int used_length= 0;
87
88 /* need at least a tag and a 1 byte length */
89 if (length < 2) {
90 return NULL;
91 }
92
93 tag = buf[used_length++];
94
95 if (rettag) {
96 *rettag = tag;
97 }
98
99 /* blow out when we come to the end */
100 if (tag == 0) {
101 return NULL;
102 }
103
104 *data_length = buf[used_length++];
105
106 if (*data_length&0x80) {
107 int len_count = *data_length & 0x7f;
108
109 if (len_count+used_length > length) {
110 return NULL;
111 }
112
113 *data_length = 0;
114
115 while (len_count-- > 0) {
116 *data_length = (*data_length << 8) | buf[used_length++];
117 }
118 }
119
120 if (*data_length > (length-used_length) ) {
121 *data_length = length-used_length;
122 return NULL;
123 }
124 if (includeTag) *data_length += used_length;
125
126 return (buf + (includeTag ? 0 : used_length));
127 }
128
129 static void SetTimeType(SECItem* item, unsigned char tagtype)
130 {
131 switch (tagtype) {
132 case SEC_ASN1_UTC_TIME:
133 item->type = siUTCTime;
134 break;
135
136 case SEC_ASN1_GENERALIZED_TIME:
137 item->type = siGeneralizedTime;
138 break;
139
140 default:
141 PORT_Assert(0);
142 break;
143 }
144 }
145
146 static int
147 nsslowcert_GetValidityFields(unsigned char *buf,int buf_length,
148 SECItem *notBefore, SECItem *notAfter)
149 {
150 unsigned char tagtype;
151 notBefore->data = nsslowcert_dataStart(buf,buf_length,
152 &notBefore->len,PR_FALSE, &tagtype);
153 if (notBefore->data == NULL) return SECFailure;
154 SetTimeType(notBefore, tagtype);
155 buf_length -= (notBefore->data-buf) + notBefore->len;
156 buf = notBefore->data + notBefore->len;
157 notAfter->data = nsslowcert_dataStart(buf,buf_length,
158 &notAfter->len,PR_FALSE, &tagtype);
159 if (notAfter->data == NULL) return SECFailure;
160 SetTimeType(notAfter, tagtype);
161 return SECSuccess;
162 }
163
164 static int
165 nsslowcert_GetCertFields(unsigned char *cert,int cert_length,
166 SECItem *issuer, SECItem *serial, SECItem *derSN, SECItem *subject,
167 SECItem *valid, SECItem *subjkey, SECItem *extensions)
168 {
169 unsigned char *buf;
170 unsigned int buf_length;
171 unsigned char *dummy;
172 unsigned int dummylen;
173
174 /* get past the signature wrap */
175 buf = nsslowcert_dataStart(cert,cert_length,&buf_length,PR_FALSE, NULL);
176 if (buf == NULL) return SECFailure;
177 /* get into the raw cert data */
178 buf = nsslowcert_dataStart(buf,buf_length,&buf_length,PR_FALSE, NULL);
179 if (buf == NULL) return SECFailure;
180 /* skip past any optional version number */
181 if ((buf[0] & 0xa0) == 0xa0) {
182 dummy = nsslowcert_dataStart(buf,buf_length,&dummylen,PR_FALSE, NULL);
183 if (dummy == NULL) return SECFailure;
184 buf_length -= (dummy-buf) + dummylen;
185 buf = dummy + dummylen;
186 }
187 /* serial number */
188 if (derSN) {
189 derSN->data=nsslowcert_dataStart(buf,buf_length,&derSN->len,PR_TRUE, NULL);
190 /* derSN->data doesn't need to be checked because if it fails so will
191 * serial->data below. The only difference between the two calls is
192 * whether or not the tags are included in the returned buffer */
193 }
194 serial->data = nsslowcert_dataStart(buf,buf_length,&serial->len,PR_FALSE, NULL);
195 if (serial->data == NULL) return SECFailure;
196 buf_length -= (serial->data-buf) + serial->len;
197 buf = serial->data + serial->len;
198 /* skip the OID */
199 dummy = nsslowcert_dataStart(buf,buf_length,&dummylen,PR_FALSE, NULL);
200 if (dummy == NULL) return SECFailure;
201 buf_length -= (dummy-buf) + dummylen;
202 buf = dummy + dummylen;
203 /* issuer */
204 issuer->data = nsslowcert_dataStart(buf,buf_length,&issuer->len,PR_TRUE, NULL);
205 if (issuer->data == NULL) return SECFailure;
206 buf_length -= (issuer->data-buf) + issuer->len;
207 buf = issuer->data + issuer->len;
208
209 /* only wanted issuer/SN */
210 if (valid == NULL) {
211 return SECSuccess;
212 }
213 /* validity */
214 valid->data = nsslowcert_dataStart(buf,buf_length,&valid->len,PR_FALSE, NULL);
215 if (valid->data == NULL) return SECFailure;
216 buf_length -= (valid->data-buf) + valid->len;
217 buf = valid->data + valid->len;
218 /*subject */
219 subject->data=nsslowcert_dataStart(buf,buf_length,&subject->len,PR_TRUE, NULL);
220 if (subject->data == NULL) return SECFailure;
221 buf_length -= (subject->data-buf) + subject->len;
222 buf = subject->data + subject->len;
223 /* subject key info */
224 subjkey->data=nsslowcert_dataStart(buf,buf_length,&subjkey->len,PR_TRUE, NULL);
225 if (subjkey->data == NULL) return SECFailure;
226 buf_length -= (subjkey->data-buf) + subjkey->len;
227 buf = subjkey->data + subjkey->len;
228
229 extensions->data = NULL;
230 extensions->len = 0;
231 while (buf_length > 0) {
232 /* EXTENSIONS */
233 if (buf[0] == 0xa3) {
234 extensions->data = nsslowcert_dataStart(buf,buf_length,
235 &extensions->len, PR_FALSE, NULL);
236 /* if the DER is bad, we should fail. Previously we accepted
237 * bad DER here and treated the extension as missin */
238 if (extensions->data == NULL ||
239 (extensions->data - buf) + extensions->len != buf_length)
240 return SECFailure;
241 buf = extensions->data;
242 buf_length = extensions->len;
243 /* now parse the SEQUENCE holding the extensions. */
244 dummy = nsslowcert_dataStart(buf,buf_length,&dummylen,PR_FALSE,NULL);
245 if (dummy == NULL ||
246 (dummy - buf) + dummylen != buf_length)
247 return SECFailure;
248 buf_length -= (dummy - buf);
249 buf = dummy;
250 /* Now parse the extensions inside this sequence */
251 }
252 dummy = nsslowcert_dataStart(buf,buf_length,&dummylen,PR_FALSE,NULL);
253 if (dummy == NULL) return SECFailure;
254 buf_length -= (dummy - buf) + dummylen;
255 buf = dummy + dummylen;
256 }
257 return SECSuccess;
258 }
259
260 static SECStatus
261 nsslowcert_GetCertTimes(NSSLOWCERTCertificate *c, PRTime *notBefore, PRTime *notAfter)
262 {
263 int rv;
264 NSSLOWCERTValidity validity;
265
266 rv = nsslowcert_GetValidityFields(c->validity.data,c->validity.len,
267 &validity.notBefore,&validity.notAfter);
268 if (rv != SECSuccess) {
269 return rv;
270 }
271
272 /* convert DER not-before time */
273 rv = DER_DecodeTimeChoice(notBefore, &validity.notBefore);
274 if (rv) {
275 return(SECFailure);
276 }
277
278 /* convert DER not-after time */
279 rv = DER_DecodeTimeChoice(notAfter, &validity.notAfter);
280 if (rv) {
281 return(SECFailure);
282 }
283
284 return(SECSuccess);
285 }
286
287 /*
288 * is certa newer than certb? If one is expired, pick the other one.
289 */
290 PRBool
291 nsslowcert_IsNewer(NSSLOWCERTCertificate *certa, NSSLOWCERTCertificate *certb)
292 {
293 PRTime notBeforeA, notAfterA, notBeforeB, notAfterB, now;
294 SECStatus rv;
295 PRBool newerbefore, newerafter;
296
297 rv = nsslowcert_GetCertTimes(certa, &notBeforeA, &notAfterA);
298 if ( rv != SECSuccess ) {
299 return(PR_FALSE);
300 }
301
302 rv = nsslowcert_GetCertTimes(certb, &notBeforeB, &notAfterB);
303 if ( rv != SECSuccess ) {
304 return(PR_TRUE);
305 }
306
307 newerbefore = PR_FALSE;
308 if ( LL_CMP(notBeforeA, >, notBeforeB) ) {
309 newerbefore = PR_TRUE;
310 }
311
312 newerafter = PR_FALSE;
313 if ( LL_CMP(notAfterA, >, notAfterB) ) {
314 newerafter = PR_TRUE;
315 }
316
317 if ( newerbefore && newerafter ) {
318 return(PR_TRUE);
319 }
320
321 if ( ( !newerbefore ) && ( !newerafter ) ) {
322 return(PR_FALSE);
323 }
324
325 /* get current time */
326 now = PR_Now();
327
328 if ( newerbefore ) {
329 /* cert A was issued after cert B, but expires sooner */
330 /* if A is expired, then pick B */
331 if ( LL_CMP(notAfterA, <, now ) ) {
332 return(PR_FALSE);
333 }
334 return(PR_TRUE);
335 } else {
336 /* cert B was issued after cert A, but expires sooner */
337 /* if B is expired, then pick A */
338 if ( LL_CMP(notAfterB, <, now ) ) {
339 return(PR_TRUE);
340 }
341 return(PR_FALSE);
342 }
343 }
344
345 #define SOFT_DEFAULT_CHUNKSIZE 2048
346
347 static SECStatus
348 nsslowcert_KeyFromIssuerAndSN(PLArenaPool *arena,
349 SECItem *issuer, SECItem *sn, SECItem *key)
350 {
351 unsigned int len = sn->len + issuer->len;
352
353 if (!arena) {
354 PORT_SetError(SEC_ERROR_INVALID_ARGS);
355 goto loser;
356 }
357 if (len > NSS_MAX_LEGACY_DB_KEY_SIZE) {
358 PORT_SetError(SEC_ERROR_INPUT_LEN);
359 goto loser;
360 }
361 key->data = (unsigned char*)PORT_ArenaAlloc(arena, len);
362 if ( !key->data ) {
363 goto loser;
364 }
365
366 key->len = len;
367 /* copy the serialNumber */
368 PORT_Memcpy(key->data, sn->data, sn->len);
369
370 /* copy the issuer */
371 PORT_Memcpy(&key->data[sn->len], issuer->data, issuer->len);
372
373 return(SECSuccess);
374
375 loser:
376 return(SECFailure);
377 }
378
379 static SECStatus
380 nsslowcert_KeyFromIssuerAndSNStatic(unsigned char *space,
381 int spaceLen, SECItem *issuer, SECItem *sn, SECItem *key)
382 {
383 unsigned int len = sn->len + issuer->len;
384
385 key->data = pkcs11_allocStaticData(len, space, spaceLen);
386 if ( !key->data ) {
387 goto loser;
388 }
389
390 key->len = len;
391 /* copy the serialNumber */
392 PORT_Memcpy(key->data, sn->data, sn->len);
393
394 /* copy the issuer */
395 PORT_Memcpy(&key->data[sn->len], issuer->data, issuer->len);
396
397 return(SECSuccess);
398
399 loser:
400 return(SECFailure);
401 }
402
403
404 static char *
405 nsslowcert_EmailName(SECItem *derDN, char *space, unsigned int len)
406 {
407 unsigned char *buf;
408 unsigned int buf_length;
409
410 /* unwrap outer sequence */
411 buf=nsslowcert_dataStart(derDN->data,derDN->len,&buf_length,PR_FALSE,NULL);
412 if (buf == NULL) return NULL;
413
414 /* Walk each RDN */
415 while (buf_length > 0) {
416 unsigned char *rdn;
417 unsigned int rdn_length;
418
419 /* grab next rdn */
420 rdn=nsslowcert_dataStart(buf, buf_length, &rdn_length, PR_FALSE, NULL);
421 if (rdn == NULL) { return NULL; }
422 buf_length -= (rdn - buf) + rdn_length;
423 buf = rdn+rdn_length;
424
425 while (rdn_length > 0) {
426 unsigned char *ava;
427 unsigned int ava_length;
428 unsigned char *oid;
429 unsigned int oid_length;
430 unsigned char *name;
431 unsigned int name_length;
432 SECItem oidItem;
433 SECOidTag type;
434
435 /* unwrap the ava */
436 ava=nsslowcert_dataStart(rdn, rdn_length, &ava_length, PR_FALSE,
437 NULL);
438 if (ava == NULL) return NULL;
439 rdn_length -= (ava-rdn)+ava_length;
440 rdn = ava + ava_length;
441
442 oid=nsslowcert_dataStart(ava, ava_length, &oid_length, PR_FALSE,
443 NULL);
444 if (oid == NULL) { return NULL; }
445 ava_length -= (oid-ava)+oid_length;
446 ava = oid+oid_length;
447
448 name=nsslowcert_dataStart(ava, ava_length, &name_length, PR_FALSE,
449 NULL);
450 if (oid == NULL) { return NULL; }
451 ava_length -= (name-ava)+name_length;
452 ava = name+name_length;
453
454 oidItem.data = oid;
455 oidItem.len = oid_length;
456 type = SECOID_FindOIDTag(&oidItem);
457 if ((type == SEC_OID_PKCS9_EMAIL_ADDRESS) ||
458 (type == SEC_OID_RFC1274_MAIL)) {
459 /* Email is supposed to be IA5String, so no
460 * translation necessary */
461 char *emailAddr;
462 emailAddr = (char *)pkcs11_copyStaticData(name,name_length+1,
463 (unsigned char *)space,len);
464 if (emailAddr) {
465 emailAddr[name_length] = 0;
466 }
467 return emailAddr;
468 }
469 }
470 }
471 return NULL;
472 }
473
474 static char *
475 nsslowcert_EmailAltName(NSSLOWCERTCertificate *cert, char *space,
476 unsigned int len)
477 {
478 unsigned char *exts;
479 unsigned int exts_length;
480
481 /* unwrap the sequence */
482 exts = nsslowcert_dataStart(cert->extensions.data, cert->extensions.len,
483 &exts_length, PR_FALSE, NULL);
484 /* loop through extension */
485 while (exts && exts_length > 0) {
486 unsigned char * ext;
487 unsigned int ext_length;
488 unsigned char *oid;
489 unsigned int oid_length;
490 unsigned char *nameList;
491 unsigned int nameList_length;
492 SECItem oidItem;
493 SECOidTag type;
494
495 ext = nsslowcert_dataStart(exts, exts_length, &ext_length,
496 PR_FALSE, NULL);
497 if (ext == NULL) { break; }
498 exts_length -= (ext - exts) + ext_length;
499 exts = ext+ext_length;
500
501 oid=nsslowcert_dataStart(ext, ext_length, &oid_length, PR_FALSE, NULL);
502 if (oid == NULL) { break; }
503 ext_length -= (oid - ext) + oid_length;
504 ext = oid+oid_length;
505 oidItem.data = oid;
506 oidItem.len = oid_length;
507 type = SECOID_FindOIDTag(&oidItem);
508
509 /* get Alt Extension */
510 if (type != SEC_OID_X509_SUBJECT_ALT_NAME) {
511 continue;
512 }
513
514 /* skip passed the critical flag */
515 if (ext[0] == 0x01) { /* BOOLEAN */
516 unsigned char *dummy;
517 unsigned int dummy_length;
518 dummy = nsslowcert_dataStart(ext, ext_length, &dummy_length,
519 PR_FALSE, NULL);
520 if (dummy == NULL) { break; }
521 ext_length -= (dummy - ext) + dummy_length;
522 ext = dummy+dummy_length;
523 }
524
525
526 /* unwrap the name list */
527 nameList = nsslowcert_dataStart(ext, ext_length, &nameList_length,
528 PR_FALSE, NULL);
529 if (nameList == NULL) { break; }
530 ext_length -= (nameList - ext) + nameList_length;
531 ext = nameList+nameList_length;
532 nameList = nsslowcert_dataStart(nameList, nameList_length,
533 &nameList_length, PR_FALSE, NULL);
534 /* loop through the name list */
535 while (nameList && nameList_length > 0) {
536 unsigned char *thisName;
537 unsigned int thisName_length;
538
539 thisName = nsslowcert_dataStart(nameList, nameList_length,
540 &thisName_length, PR_FALSE, NULL);
541 if (thisName == NULL) { break; }
542 if (nameList[0] == 0xa2) { /* DNS Name */
543 SECItem dn;
544 char *emailAddr;
545
546 dn.data = thisName;
547 dn.len = thisName_length;
548 emailAddr = nsslowcert_EmailName(&dn, space, len);
549 if (emailAddr) {
550 return emailAddr;
551 }
552 }
553 if (nameList[0] == 0x81) { /* RFC 822name */
554 char *emailAddr;
555 emailAddr = (char *)pkcs11_copyStaticData(thisName,
556 thisName_length+1, (unsigned char *)space,len);
557 if (emailAddr) {
558 emailAddr[thisName_length] = 0;
559 }
560 return emailAddr;
561 }
562 nameList_length -= (thisName-nameList) + thisName_length;
563 nameList = thisName + thisName_length;
564 }
565 break;
566 }
567 return NULL;
568 }
569
570 static char *
571 nsslowcert_GetCertificateEmailAddress(NSSLOWCERTCertificate *cert)
572 {
573 char *emailAddr = NULL;
574 char *str;
575
576 emailAddr = nsslowcert_EmailName(&cert->derSubject,cert->emailAddrSpace,
577 sizeof(cert->emailAddrSpace));
578 /* couldn't find the email address in the DN, check the subject Alt name */
579 if (!emailAddr && cert->extensions.data) {
580 emailAddr = nsslowcert_EmailAltName(cert, cert->emailAddrSpace,
581 sizeof(cert->emailAddrSpace));
582 }
583
584
585 /* make it lower case */
586 str = emailAddr;
587 while ( str && *str ) {
588 *str = tolower( *str );
589 str++;
590 }
591 return emailAddr;
592
593 }
594
595 /*
596 * take a DER certificate and decode it into a certificate structure
597 */
598 NSSLOWCERTCertificate *
599 nsslowcert_DecodeDERCertificate(SECItem *derSignedCert, char *nickname)
600 {
601 NSSLOWCERTCertificate *cert;
602 int rv;
603
604 /* allocate the certificate structure */
605 cert = nsslowcert_CreateCert();
606
607 if ( !cert ) {
608 goto loser;
609 }
610
611 /* point to passed in DER data */
612 cert->derCert = *derSignedCert;
613 cert->nickname = NULL;
614 cert->certKey.data = NULL;
615 cert->referenceCount = 1;
616
617 /* decode the certificate info */
618 rv = nsslowcert_GetCertFields(cert->derCert.data, cert->derCert.len,
619 &cert->derIssuer, &cert->serialNumber, &cert->derSN, &cert->derSubject,
620 &cert->validity, &cert->derSubjKeyInfo, &cert->extensions);
621
622 if (rv != SECSuccess) {
623 goto loser;
624 }
625
626 /* cert->subjectKeyID; x509v3 subject key identifier */
627 cert->subjectKeyID.data = NULL;
628 cert->subjectKeyID.len = 0;
629 cert->dbEntry = NULL;
630 cert ->trust = NULL;
631 cert ->dbhandle = NULL;
632
633 /* generate and save the database key for the cert */
634 rv = nsslowcert_KeyFromIssuerAndSNStatic(cert->certKeySpace,
635 sizeof(cert->certKeySpace), &cert->derIssuer,
636 &cert->serialNumber, &cert->certKey);
637 if ( rv ) {
638 goto loser;
639 }
640
641 /* set the nickname */
642 if ( nickname == NULL ) {
643 cert->nickname = NULL;
644 } else {
645 /* copy and install the nickname */
646 cert->nickname = pkcs11_copyNickname(nickname,cert->nicknameSpace,
647 sizeof(cert->nicknameSpace));
648 }
649
650 #ifdef FIXME
651 /* initialize the subjectKeyID */
652 rv = cert_GetKeyID(cert);
653 if ( rv != SECSuccess ) {
654 goto loser;
655 }
656 #endif
657
658 /* set the email address */
659 cert->emailAddr = nsslowcert_GetCertificateEmailAddress(cert);
660
661
662 cert->referenceCount = 1;
663
664 return(cert);
665
666 loser:
667 if (cert) {
668 nsslowcert_DestroyCertificate(cert);
669 }
670
671 return(0);
672 }
673
674 char *
675 nsslowcert_FixupEmailAddr(char *emailAddr)
676 {
677 char *retaddr;
678 char *str;
679
680 if ( emailAddr == NULL ) {
681 return(NULL);
682 }
683
684 /* copy the string */
685 str = retaddr = PORT_Strdup(emailAddr);
686 if ( str == NULL ) {
687 return(NULL);
688 }
689
690 /* make it lower case */
691 while ( *str ) {
692 *str = tolower( *str );
693 str++;
694 }
695
696 return(retaddr);
697 }
698
699
700 /*
701 * Generate a database key, based on serial number and issuer, from a
702 * DER certificate.
703 */
704 SECStatus
705 nsslowcert_KeyFromDERCert(PLArenaPool *arena, SECItem *derCert, SECItem *key)
706 {
707 int rv;
708 NSSLOWCERTCertKey certkey;
709
710 PORT_Memset(&certkey, 0, sizeof(NSSLOWCERTCertKey));
711
712 rv = nsslowcert_GetCertFields(derCert->data, derCert->len,
713 &certkey.derIssuer, &certkey.serialNumber, NULL, NULL,
714 NULL, NULL, NULL);
715
716 if ( rv ) {
717 goto loser;
718 }
719
720 return(nsslowcert_KeyFromIssuerAndSN(arena, &certkey.derIssuer,
721 &certkey.serialNumber, key));
722 loser:
723 return(SECFailure);
724 }
725
726 NSSLOWKEYPublicKey *
727 nsslowcert_ExtractPublicKey(NSSLOWCERTCertificate *cert)
728 {
729 NSSLOWCERTSubjectPublicKeyInfo spki;
730 NSSLOWKEYPublicKey *pubk;
731 SECItem os;
732 SECStatus rv;
733 PLArenaPool *arena;
734 SECOidTag tag;
735 SECItem newDerSubjKeyInfo;
736
737 arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
738 if (arena == NULL)
739 return NULL;
740
741 pubk = (NSSLOWKEYPublicKey *)
742 PORT_ArenaZAlloc(arena, sizeof(NSSLOWKEYPublicKey));
743 if (pubk == NULL) {
744 PORT_FreeArena (arena, PR_FALSE);
745 return NULL;
746 }
747
748 pubk->arena = arena;
749 PORT_Memset(&spki,0,sizeof(spki));
750
751 /* copy the DER into the arena, since Quick DER returns data that points
752 into the DER input, which may get freed by the caller */
753 rv = SECITEM_CopyItem(arena, &newDerSubjKeyInfo, &cert->derSubjKeyInfo);
754 if ( rv != SECSuccess ) {
755 PORT_FreeArena (arena, PR_FALSE);
756 return NULL;
757 }
758
759 /* we haven't bothered decoding the spki struct yet, do it now */
760 rv = SEC_QuickDERDecodeItem(arena, &spki,
761 nsslowcert_SubjectPublicKeyInfoTemplate, &newDerSubjKeyInfo);
762 if (rv != SECSuccess) {
763 PORT_FreeArena (arena, PR_FALSE);
764 return NULL;
765 }
766
767 /* Convert bit string length from bits to bytes */
768 os = spki.subjectPublicKey;
769 DER_ConvertBitString (&os);
770
771 tag = SECOID_GetAlgorithmTag(&spki.algorithm);
772 switch ( tag ) {
773 case SEC_OID_X500_RSA_ENCRYPTION:
774 case SEC_OID_PKCS1_RSA_ENCRYPTION:
775 pubk->keyType = NSSLOWKEYRSAKey;
776 prepare_low_rsa_pub_key_for_asn1(pubk);
777 rv = SEC_QuickDERDecodeItem(arena, pubk,
778 nsslowcert_RSAPublicKeyTemplate, &os);
779 if (rv == SECSuccess)
780 return pubk;
781 break;
782 case SEC_OID_ANSIX9_DSA_SIGNATURE:
783 pubk->keyType = NSSLOWKEYDSAKey;
784 prepare_low_dsa_pub_key_for_asn1(pubk);
785 rv = SEC_QuickDERDecodeItem(arena, pubk,
786 nsslowcert_DSAPublicKeyTemplate, &os);
787 if (rv == SECSuccess) return pubk;
788 break;
789 case SEC_OID_X942_DIFFIE_HELMAN_KEY:
790 pubk->keyType = NSSLOWKEYDHKey;
791 prepare_low_dh_pub_key_for_asn1(pubk);
792 rv = SEC_QuickDERDecodeItem(arena, pubk,
793 nsslowcert_DHPublicKeyTemplate, &os);
794 if (rv == SECSuccess) return pubk;
795 break;
796 #ifndef NSS_DISABLE_ECC
797 case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
798 pubk->keyType = NSSLOWKEYECKey;
799 /* Since PKCS#11 directly takes the DER encoding of EC params
800 * and public value, we don't need any decoding here.
801 */
802 rv = SECITEM_CopyItem(arena, &pubk->u.ec.ecParams.DEREncoding,
803 &spki.algorithm.parameters);
804 if ( rv != SECSuccess )
805 break;
806
807 /* Fill out the rest of the ecParams structure
808 * based on the encoded params
809 */
810 if (LGEC_FillParams(arena, &pubk->u.ec.ecParams.DEREncoding,
811 &pubk->u.ec.ecParams) != SECSuccess)
812 break;
813
814 rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue, &os);
815 if (rv == SECSuccess) return pubk;
816 break;
817 #endif /* NSS_DISABLE_ECC */
818 default:
819 rv = SECFailure;
820 break;
821 }
822
823 lg_nsslowkey_DestroyPublicKey (pubk);
824 return NULL;
825 }
826
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)