Bug Summary

File:s/lib/softoken/legacydb/lowcert.c
Warning:line 848, column 13
Value stored to 'rv' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name lowcert.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/lib/softoken/legacydb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/var/lib/jenkins/workspace/nss-scan-build/nss/lib/softoken/legacydb -resource-dir /usr/lib/llvm-18/lib/clang/18 -D HAVE_STRERROR -D LINUX -D linux -D XP_UNIX -D XP_UNIX -D SHLIB_SUFFIX="so" -D SHLIB_PREFIX="lib" -D LG_LIB_NAME="libnssdbm3.so" -D DEBUG -U NDEBUG -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D _REENTRANT -D DEBUG -U NDEBUG -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D _REENTRANT -D NSS_DISABLE_SSE3 -D NSS_NO_INIT_SUPPORT -D USE_UTIL_DIRECTLY -D NO_NSPR_10_SUPPORT -D SSL_DISABLE_DEPRECATED_CIPHER_SUITE_NAMES -I ../../../../dist/Linux4.19_x86_64_gcc_glibc_PTH_64_DBG.OBJ/include -I ../../../../dist/public/nss -I ../../../../dist/private/nss -I ../../../../dist/public/dbm -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -std=c99 -ferror-limit 19 -fgnuc-version=4.2.1 -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-05-18-082241-28900-1 -x c lowcert.c
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
18SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
19
20static const SEC_ASN1Template nsslowcert_SubjectPublicKeyInfoTemplate[] = {
21 { SEC_ASN1_SEQUENCE0x10, 0, NULL((void*)0), sizeof(NSSLOWCERTSubjectPublicKeyInfo) },
22 { SEC_ASN1_INLINE0x00800 | SEC_ASN1_XTRN0,
23 offsetof(NSSLOWCERTSubjectPublicKeyInfo, algorithm)__builtin_offsetof(NSSLOWCERTSubjectPublicKeyInfo, algorithm),
24 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate)SECOID_AlgorithmIDTemplate_Util },
25 { SEC_ASN1_BIT_STRING0x03,
26 offsetof(NSSLOWCERTSubjectPublicKeyInfo, subjectPublicKey)__builtin_offsetof(NSSLOWCERTSubjectPublicKeyInfo, subjectPublicKey
)
},
27 { 0 }
28};
29
30static const SEC_ASN1Template nsslowcert_RSAPublicKeyTemplate[] = {
31 { SEC_ASN1_SEQUENCE0x10, 0, NULL((void*)0), sizeof(NSSLOWKEYPublicKey) },
32 { SEC_ASN1_INTEGER0x02, offsetof(NSSLOWKEYPublicKey, u.rsa.modulus)__builtin_offsetof(NSSLOWKEYPublicKey, u.rsa.modulus) },
33 { SEC_ASN1_INTEGER0x02, offsetof(NSSLOWKEYPublicKey, u.rsa.publicExponent)__builtin_offsetof(NSSLOWKEYPublicKey, u.rsa.publicExponent) },
34 { 0 }
35};
36static const SEC_ASN1Template nsslowcert_DSAPublicKeyTemplate[] = {
37 { SEC_ASN1_INTEGER0x02, offsetof(NSSLOWKEYPublicKey, u.dsa.publicValue)__builtin_offsetof(NSSLOWKEYPublicKey, u.dsa.publicValue) },
38 { 0 }
39};
40static const SEC_ASN1Template nsslowcert_DHPublicKeyTemplate[] = {
41 { SEC_ASN1_INTEGER0x02, offsetof(NSSLOWKEYPublicKey, u.dh.publicValue)__builtin_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
54static void
55prepare_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
61static void
62prepare_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
70static void
71prepare_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 */
81static unsigned char *
82nsslowcert_dataStart(unsigned char *buf, unsigned int length,
83 unsigned int *data_length, PRBool includeTag,
84 unsigned char *rettag)
85{
86 unsigned char tag;
87 unsigned int used_length = 0;
88
89 /* need at least a tag and a 1 byte length */
90 if (length < 2) {
91 return NULL((void*)0);
92 }
93
94 tag = buf[used_length++];
95
96 if (rettag) {
97 *rettag = tag;
98 }
99
100 /* blow out when we come to the end */
101 if (tag == 0) {
102 return NULL((void*)0);
103 }
104
105 *data_length = buf[used_length++];
106
107 if (*data_length & 0x80) {
108 int len_count = *data_length & 0x7f;
109
110 if (len_count + used_length > length) {
111 return NULL((void*)0);
112 }
113
114 *data_length = 0;
115
116 while (len_count-- > 0) {
117 *data_length = (*data_length << 8) | buf[used_length++];
118 }
119 }
120
121 if (*data_length > (length - used_length)) {
122 *data_length = length - used_length;
123 return NULL((void*)0);
124 }
125 if (includeTag)
126 *data_length += used_length;
127
128 return (buf + (includeTag ? 0 : used_length));
129}
130
131static void
132SetTimeType(SECItem *item, unsigned char tagtype)
133{
134 switch (tagtype) {
135 case SEC_ASN1_UTC_TIME0x17:
136 item->type = siUTCTime;
137 break;
138
139 case SEC_ASN1_GENERALIZED_TIME0x18:
140 item->type = siGeneralizedTime;
141 break;
142
143 default:
144 PORT_Assert(0)((0)?((void)0):PR_Assert("0","lowcert.c",144));
145 break;
146 }
147}
148
149static int
150nsslowcert_GetValidityFields(unsigned char *buf, int buf_length,
151 SECItem *notBefore, SECItem *notAfter)
152{
153 unsigned char tagtype;
154 notBefore->data = nsslowcert_dataStart(buf, buf_length,
155 &notBefore->len, PR_FALSE0, &tagtype);
156 if (notBefore->data == NULL((void*)0))
157 return SECFailure;
158 SetTimeType(notBefore, tagtype);
159 buf_length -= (notBefore->data - buf) + notBefore->len;
160 buf = notBefore->data + notBefore->len;
161 notAfter->data = nsslowcert_dataStart(buf, buf_length,
162 &notAfter->len, PR_FALSE0, &tagtype);
163 if (notAfter->data == NULL((void*)0))
164 return SECFailure;
165 SetTimeType(notAfter, tagtype);
166 return SECSuccess;
167}
168
169static int
170nsslowcert_GetCertFields(unsigned char *cert, int cert_length,
171 SECItem *issuer, SECItem *serial, SECItem *derSN, SECItem *subject,
172 SECItem *valid, SECItem *subjkey, SECItem *extensions)
173{
174 unsigned char *buf;
175 unsigned int buf_length;
176 unsigned char *dummy;
177 unsigned int dummylen;
178
179 /* get past the signature wrap */
180 buf = nsslowcert_dataStart(cert, cert_length, &buf_length, PR_FALSE0, NULL((void*)0));
181 if (buf == NULL((void*)0))
182 return SECFailure;
183 /* get into the raw cert data */
184 buf = nsslowcert_dataStart(buf, buf_length, &buf_length, PR_FALSE0, NULL((void*)0));
185 if (buf == NULL((void*)0))
186 return SECFailure;
187 /* skip past any optional version number */
188 if ((buf[0] & 0xa0) == 0xa0) {
189 dummy = nsslowcert_dataStart(buf, buf_length, &dummylen, PR_FALSE0, NULL((void*)0));
190 if (dummy == NULL((void*)0))
191 return SECFailure;
192 buf_length -= (dummy - buf) + dummylen;
193 buf = dummy + dummylen;
194 }
195 /* serial number */
196 if (derSN) {
197 derSN->data = nsslowcert_dataStart(buf, buf_length, &derSN->len, PR_TRUE1, NULL((void*)0));
198 /* derSN->data doesn't need to be checked because if it fails so will
199 * serial->data below. The only difference between the two calls is
200 * whether or not the tags are included in the returned buffer */
201 }
202 serial->data = nsslowcert_dataStart(buf, buf_length, &serial->len, PR_FALSE0, NULL((void*)0));
203 if (serial->data == NULL((void*)0))
204 return SECFailure;
205 buf_length -= (serial->data - buf) + serial->len;
206 buf = serial->data + serial->len;
207 /* skip the OID */
208 dummy = nsslowcert_dataStart(buf, buf_length, &dummylen, PR_FALSE0, NULL((void*)0));
209 if (dummy == NULL((void*)0))
210 return SECFailure;
211 buf_length -= (dummy - buf) + dummylen;
212 buf = dummy + dummylen;
213 /* issuer */
214 issuer->data = nsslowcert_dataStart(buf, buf_length, &issuer->len, PR_TRUE1, NULL((void*)0));
215 if (issuer->data == NULL((void*)0))
216 return SECFailure;
217 buf_length -= (issuer->data - buf) + issuer->len;
218 buf = issuer->data + issuer->len;
219
220 /* only wanted issuer/SN */
221 if (valid == NULL((void*)0)) {
222 return SECSuccess;
223 }
224 /* validity */
225 valid->data = nsslowcert_dataStart(buf, buf_length, &valid->len, PR_FALSE0, NULL((void*)0));
226 if (valid->data == NULL((void*)0))
227 return SECFailure;
228 buf_length -= (valid->data - buf) + valid->len;
229 buf = valid->data + valid->len;
230 /*subject */
231 subject->data = nsslowcert_dataStart(buf, buf_length, &subject->len, PR_TRUE1, NULL((void*)0));
232 if (subject->data == NULL((void*)0))
233 return SECFailure;
234 buf_length -= (subject->data - buf) + subject->len;
235 buf = subject->data + subject->len;
236 /* subject key info */
237 subjkey->data = nsslowcert_dataStart(buf, buf_length, &subjkey->len, PR_TRUE1, NULL((void*)0));
238 if (subjkey->data == NULL((void*)0))
239 return SECFailure;
240 buf_length -= (subjkey->data - buf) + subjkey->len;
241 buf = subjkey->data + subjkey->len;
242
243 extensions->data = NULL((void*)0);
244 extensions->len = 0;
245 while (buf_length > 0) {
246 /* EXTENSIONS */
247 if (buf[0] == 0xa3) {
248 extensions->data = nsslowcert_dataStart(buf, buf_length,
249 &extensions->len, PR_FALSE0, NULL((void*)0));
250 /* if the DER is bad, we should fail. Previously we accepted
251 * bad DER here and treated the extension as missin */
252 if (extensions->data == NULL((void*)0) ||
253 (extensions->data - buf) + extensions->len != buf_length)
254 return SECFailure;
255 buf = extensions->data;
256 buf_length = extensions->len;
257 /* now parse the SEQUENCE holding the extensions. */
258 dummy = nsslowcert_dataStart(buf, buf_length, &dummylen, PR_FALSE0, NULL((void*)0));
259 if (dummy == NULL((void*)0) ||
260 (dummy - buf) + dummylen != buf_length)
261 return SECFailure;
262 buf_length -= (dummy - buf);
263 buf = dummy;
264 /* Now parse the extensions inside this sequence */
265 }
266 dummy = nsslowcert_dataStart(buf, buf_length, &dummylen, PR_FALSE0, NULL((void*)0));
267 if (dummy == NULL((void*)0))
268 return SECFailure;
269 buf_length -= (dummy - buf) + dummylen;
270 buf = dummy + dummylen;
271 }
272 return SECSuccess;
273}
274
275static SECStatus
276nsslowcert_GetCertTimes(NSSLOWCERTCertificate *c, PRTime *notBefore, PRTime *notAfter)
277{
278 int rv;
279 NSSLOWCERTValidity validity;
280
281 rv = nsslowcert_GetValidityFields(c->validity.data, c->validity.len,
282 &validity.notBefore, &validity.notAfter);
283 if (rv != SECSuccess) {
284 return rv;
285 }
286
287 /* convert DER not-before time */
288 rv = DER_DecodeTimeChoiceDER_DecodeTimeChoice_Util(notBefore, &validity.notBefore);
289 if (rv) {
290 return (SECFailure);
291 }
292
293 /* convert DER not-after time */
294 rv = DER_DecodeTimeChoiceDER_DecodeTimeChoice_Util(notAfter, &validity.notAfter);
295 if (rv) {
296 return (SECFailure);
297 }
298
299 return (SECSuccess);
300}
301
302/*
303 * is certa newer than certb? If one is expired, pick the other one.
304 */
305PRBool
306nsslowcert_IsNewer(NSSLOWCERTCertificate *certa, NSSLOWCERTCertificate *certb)
307{
308 PRTime notBeforeA, notAfterA, notBeforeB, notAfterB, now;
309 SECStatus rv;
310 PRBool newerbefore, newerafter;
311
312 rv = nsslowcert_GetCertTimes(certa, &notBeforeA, &notAfterA);
313 if (rv != SECSuccess) {
314 return (PR_FALSE0);
315 }
316
317 rv = nsslowcert_GetCertTimes(certb, &notBeforeB, &notAfterB);
318 if (rv != SECSuccess) {
319 return (PR_TRUE1);
320 }
321
322 newerbefore = PR_FALSE0;
323 if (LL_CMP(notBeforeA, >, notBeforeB)((PRInt64)(notBeforeA) > (PRInt64)(notBeforeB))) {
324 newerbefore = PR_TRUE1;
325 }
326
327 newerafter = PR_FALSE0;
328 if (LL_CMP(notAfterA, >, notAfterB)((PRInt64)(notAfterA) > (PRInt64)(notAfterB))) {
329 newerafter = PR_TRUE1;
330 }
331
332 if (newerbefore && newerafter) {
333 return (PR_TRUE1);
334 }
335
336 if ((!newerbefore) && (!newerafter)) {
337 return (PR_FALSE0);
338 }
339
340 /* get current time */
341 now = PR_Now();
342
343 if (newerbefore) {
344 /* cert A was issued after cert B, but expires sooner */
345 /* if A is expired, then pick B */
346 if (LL_CMP(notAfterA, <, now)((PRInt64)(notAfterA) < (PRInt64)(now))) {
347 return (PR_FALSE0);
348 }
349 return (PR_TRUE1);
350 } else {
351 /* cert B was issued after cert A, but expires sooner */
352 /* if B is expired, then pick A */
353 if (LL_CMP(notAfterB, <, now)((PRInt64)(notAfterB) < (PRInt64)(now))) {
354 return (PR_TRUE1);
355 }
356 return (PR_FALSE0);
357 }
358}
359
360#define SOFT_DEFAULT_CHUNKSIZE2048 2048
361
362static SECStatus
363nsslowcert_KeyFromIssuerAndSN(PLArenaPool *arena,
364 SECItem *issuer, SECItem *sn, SECItem *key)
365{
366 unsigned int len = sn->len + issuer->len;
367
368 if (!arena) {
369 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
370 goto loser;
371 }
372 if (len > NSS_MAX_LEGACY_DB_KEY_SIZE(60 * 1024)) {
373 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INPUT_LEN);
374 goto loser;
375 }
376 key->data = (unsigned char *)PORT_ArenaAllocPORT_ArenaAlloc_Util(arena, len);
377 if (!key->data) {
378 goto loser;
379 }
380
381 key->len = len;
382 /* copy the serialNumber */
383 PORT_Memcpymemcpy(key->data, sn->data, sn->len);
384
385 /* copy the issuer */
386 PORT_Memcpymemcpy(&key->data[sn->len], issuer->data, issuer->len);
387
388 return (SECSuccess);
389
390loser:
391 return (SECFailure);
392}
393
394static SECStatus
395nsslowcert_KeyFromIssuerAndSNStatic(unsigned char *space,
396 int spaceLen, SECItem *issuer, SECItem *sn, SECItem *key)
397{
398 unsigned int len = sn->len + issuer->len;
399
400 key->data = pkcs11_allocStaticData(len, space, spaceLen);
401 if (!key->data) {
402 goto loser;
403 }
404
405 key->len = len;
406 /* copy the serialNumber */
407 PORT_Memcpymemcpy(key->data, sn->data, sn->len);
408
409 /* copy the issuer */
410 PORT_Memcpymemcpy(&key->data[sn->len], issuer->data, issuer->len);
411
412 return (SECSuccess);
413
414loser:
415 return (SECFailure);
416}
417
418static char *
419nsslowcert_EmailName(SECItem *derDN, char *space, unsigned int len)
420{
421 unsigned char *buf;
422 unsigned int buf_length;
423
424 /* unwrap outer sequence */
425 buf = nsslowcert_dataStart(derDN->data, derDN->len, &buf_length, PR_FALSE0, NULL((void*)0));
426 if (buf == NULL((void*)0))
427 return NULL((void*)0);
428
429 /* Walk each RDN */
430 while (buf_length > 0) {
431 unsigned char *rdn;
432 unsigned int rdn_length;
433
434 /* grab next rdn */
435 rdn = nsslowcert_dataStart(buf, buf_length, &rdn_length, PR_FALSE0, NULL((void*)0));
436 if (rdn == NULL((void*)0)) {
437 return NULL((void*)0);
438 }
439 buf_length -= (rdn - buf) + rdn_length;
440 buf = rdn + rdn_length;
441
442 while (rdn_length > 0) {
443 unsigned char *ava;
444 unsigned int ava_length;
445 unsigned char *oid;
446 unsigned int oid_length;
447 unsigned char *name;
448 unsigned int name_length;
449 SECItem oidItem;
450 SECOidTag type;
451
452 /* unwrap the ava */
453 ava = nsslowcert_dataStart(rdn, rdn_length, &ava_length, PR_FALSE0,
454 NULL((void*)0));
455 if (ava == NULL((void*)0))
456 return NULL((void*)0);
457 rdn_length -= (ava - rdn) + ava_length;
458 rdn = ava + ava_length;
459
460 oid = nsslowcert_dataStart(ava, ava_length, &oid_length, PR_FALSE0,
461 NULL((void*)0));
462 if (oid == NULL((void*)0)) {
463 return NULL((void*)0);
464 }
465 ava_length -= (oid - ava) + oid_length;
466 ava = oid + oid_length;
467
468 name = nsslowcert_dataStart(ava, ava_length, &name_length, PR_FALSE0,
469 NULL((void*)0));
470 if (name == NULL((void*)0)) {
471 return NULL((void*)0);
472 }
473 ava_length -= (name - ava) + name_length;
474 ava = name + name_length;
475
476 oidItem.data = oid;
477 oidItem.len = oid_length;
478 type = SECOID_FindOIDTagSECOID_FindOIDTag_Util(&oidItem);
479 if ((type == SEC_OID_PKCS9_EMAIL_ADDRESS) ||
480 (type == SEC_OID_RFC1274_MAIL)) {
481 /* Email is supposed to be IA5String, so no
482 * translation necessary */
483 char *emailAddr;
484 emailAddr = (char *)pkcs11_copyStaticData(name, name_length + 1,
485 (unsigned char *)space, len);
486 if (emailAddr) {
487 emailAddr[name_length] = 0;
488 }
489 return emailAddr;
490 }
491 }
492 }
493 return NULL((void*)0);
494}
495
496static char *
497nsslowcert_EmailAltName(NSSLOWCERTCertificate *cert, char *space,
498 unsigned int len)
499{
500 unsigned char *exts;
501 unsigned int exts_length;
502
503 /* unwrap the sequence */
504 exts = nsslowcert_dataStart(cert->extensions.data, cert->extensions.len,
505 &exts_length, PR_FALSE0, NULL((void*)0));
506 /* loop through extension */
507 while (exts && exts_length > 0) {
508 unsigned char *ext;
509 unsigned int ext_length;
510 unsigned char *oid;
511 unsigned int oid_length;
512 unsigned char *nameList;
513 unsigned int nameList_length;
514 SECItem oidItem;
515 SECOidTag type;
516
517 ext = nsslowcert_dataStart(exts, exts_length, &ext_length,
518 PR_FALSE0, NULL((void*)0));
519 if (ext == NULL((void*)0)) {
520 break;
521 }
522 exts_length -= (ext - exts) + ext_length;
523 exts = ext + ext_length;
524
525 oid = nsslowcert_dataStart(ext, ext_length, &oid_length, PR_FALSE0, NULL((void*)0));
526 if (oid == NULL((void*)0)) {
527 break;
528 }
529 ext_length -= (oid - ext) + oid_length;
530 ext = oid + oid_length;
531 oidItem.data = oid;
532 oidItem.len = oid_length;
533 type = SECOID_FindOIDTagSECOID_FindOIDTag_Util(&oidItem);
534
535 /* get Alt Extension */
536 if (type != SEC_OID_X509_SUBJECT_ALT_NAME) {
537 continue;
538 }
539
540 /* skip passed the critical flag */
541 if (ext[0] == 0x01) { /* BOOLEAN */
542 unsigned char *dummy;
543 unsigned int dummy_length;
544 dummy = nsslowcert_dataStart(ext, ext_length, &dummy_length,
545 PR_FALSE0, NULL((void*)0));
546 if (dummy == NULL((void*)0)) {
547 break;
548 }
549 ext_length -= (dummy - ext) + dummy_length;
550 ext = dummy + dummy_length;
551 }
552
553 /* unwrap the name list */
554 nameList = nsslowcert_dataStart(ext, ext_length, &nameList_length,
555 PR_FALSE0, NULL((void*)0));
556 if (nameList == NULL((void*)0)) {
557 break;
558 }
559 ext_length -= (nameList - ext) + nameList_length;
560 ext = nameList + nameList_length;
561 nameList = nsslowcert_dataStart(nameList, nameList_length,
562 &nameList_length, PR_FALSE0, NULL((void*)0));
563 /* loop through the name list */
564 while (nameList && nameList_length > 0) {
565 unsigned char *thisName;
566 unsigned int thisName_length;
567
568 thisName = nsslowcert_dataStart(nameList, nameList_length,
569 &thisName_length, PR_FALSE0, NULL((void*)0));
570 if (thisName == NULL((void*)0)) {
571 break;
572 }
573 if (nameList[0] == 0xa2) { /* DNS Name */
574 SECItem dn;
575 char *emailAddr;
576
577 dn.data = thisName;
578 dn.len = thisName_length;
579 emailAddr = nsslowcert_EmailName(&dn, space, len);
580 if (emailAddr) {
581 return emailAddr;
582 }
583 }
584 if (nameList[0] == 0x81) { /* RFC 822name */
585 char *emailAddr;
586 emailAddr = (char *)pkcs11_copyStaticData(thisName,
587 thisName_length + 1, (unsigned char *)space, len);
588 if (emailAddr) {
589 emailAddr[thisName_length] = 0;
590 }
591 return emailAddr;
592 }
593 nameList_length -= (thisName - nameList) + thisName_length;
594 nameList = thisName + thisName_length;
595 }
596 break;
597 }
598 return NULL((void*)0);
599}
600
601static char *
602nsslowcert_GetCertificateEmailAddress(NSSLOWCERTCertificate *cert)
603{
604 char *emailAddr = NULL((void*)0);
605 char *str;
606
607 emailAddr = nsslowcert_EmailName(&cert->derSubject, cert->emailAddrSpace,
608 sizeof(cert->emailAddrSpace));
609 /* couldn't find the email address in the DN, check the subject Alt name */
610 if (!emailAddr && cert->extensions.data) {
611 emailAddr = nsslowcert_EmailAltName(cert, cert->emailAddrSpace,
612 sizeof(cert->emailAddrSpace));
613 }
614
615 /* make it lower case */
616 str = emailAddr;
617 while (str && *str) {
618 *str = tolower(*str);
619 str++;
620 }
621 return emailAddr;
622}
623
624/*
625 * take a DER certificate and decode it into a certificate structure
626 */
627NSSLOWCERTCertificate *
628nsslowcert_DecodeDERCertificate(SECItem *derSignedCert, char *nickname)
629{
630 NSSLOWCERTCertificate *cert;
631 int rv;
632
633 /* allocate the certificate structure */
634 cert = nsslowcert_CreateCert();
635
636 if (!cert) {
637 goto loser;
638 }
639
640 /* point to passed in DER data */
641 cert->derCert = *derSignedCert;
642 cert->nickname = NULL((void*)0);
643 cert->certKey.data = NULL((void*)0);
644 cert->referenceCount = 1;
645
646 /* decode the certificate info */
647 rv = nsslowcert_GetCertFields(cert->derCert.data, cert->derCert.len,
648 &cert->derIssuer, &cert->serialNumber, &cert->derSN, &cert->derSubject,
649 &cert->validity, &cert->derSubjKeyInfo, &cert->extensions);
650
651 if (rv != SECSuccess) {
652 goto loser;
653 }
654
655 /* cert->subjectKeyID; x509v3 subject key identifier */
656 cert->subjectKeyID.data = NULL((void*)0);
657 cert->subjectKeyID.len = 0;
658 cert->dbEntry = NULL((void*)0);
659 cert->trust = NULL((void*)0);
660 cert->dbhandle = NULL((void*)0);
661
662 /* generate and save the database key for the cert */
663 rv = nsslowcert_KeyFromIssuerAndSNStatic(cert->certKeySpace,
664 sizeof(cert->certKeySpace), &cert->derIssuer,
665 &cert->serialNumber, &cert->certKey);
666 if (rv) {
667 goto loser;
668 }
669
670 /* set the nickname */
671 if (nickname == NULL((void*)0)) {
672 cert->nickname = NULL((void*)0);
673 } else {
674 /* copy and install the nickname */
675 cert->nickname = pkcs11_copyNickname(nickname, cert->nicknameSpace,
676 sizeof(cert->nicknameSpace));
677 }
678
679#ifdef FIXME
680 /* initialize the subjectKeyID */
681 rv = cert_GetKeyID(cert);
682 if (rv != SECSuccess) {
683 goto loser;
684 }
685#endif
686
687 /* set the email address */
688 cert->emailAddr = nsslowcert_GetCertificateEmailAddress(cert);
689
690 cert->referenceCount = 1;
691
692 return (cert);
693
694loser:
695 if (cert) {
696 nsslowcert_DestroyCertificate(cert);
697 }
698
699 return (0);
700}
701
702char *
703nsslowcert_FixupEmailAddr(char *emailAddr)
704{
705 char *retaddr;
706 char *str;
707
708 if (emailAddr == NULL((void*)0)) {
709 return (NULL((void*)0));
710 }
711
712 /* copy the string */
713 str = retaddr = PORT_StrdupPORT_Strdup_Util(emailAddr);
714 if (str == NULL((void*)0)) {
715 return (NULL((void*)0));
716 }
717
718 /* make it lower case */
719 while (*str) {
720 *str = tolower(*str);
721 str++;
722 }
723
724 return (retaddr);
725}
726
727/*
728 * Generate a database key, based on serial number and issuer, from a
729 * DER certificate.
730 */
731SECStatus
732nsslowcert_KeyFromDERCert(PLArenaPool *arena, SECItem *derCert, SECItem *key)
733{
734 int rv;
735 NSSLOWCERTCertKey certkey;
736
737 PORT_Memsetmemset(&certkey, 0, sizeof(NSSLOWCERTCertKey));
738
739 rv = nsslowcert_GetCertFields(derCert->data, derCert->len,
740 &certkey.derIssuer, &certkey.serialNumber, NULL((void*)0), NULL((void*)0),
741 NULL((void*)0), NULL((void*)0), NULL((void*)0));
742
743 if (rv) {
744 goto loser;
745 }
746
747 return (nsslowcert_KeyFromIssuerAndSN(arena, &certkey.derIssuer,
748 &certkey.serialNumber, key));
749loser:
750 return (SECFailure);
751}
752
753NSSLOWKEYPublicKey *
754nsslowcert_ExtractPublicKey(NSSLOWCERTCertificate *cert)
755{
756 NSSLOWCERTSubjectPublicKeyInfo spki;
757 NSSLOWKEYPublicKey *pubk;
758 SECItem os;
759 SECStatus rv;
760 PLArenaPool *arena;
761 SECOidTag tag;
762 SECItem newDerSubjKeyInfo;
763
764 arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
765 if (arena == NULL((void*)0))
766 return NULL((void*)0);
767
768 pubk = (NSSLOWKEYPublicKey *)
769 PORT_ArenaZAllocPORT_ArenaZAlloc_Util(arena, sizeof(NSSLOWKEYPublicKey));
770 if (pubk == NULL((void*)0)) {
771 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
772 return NULL((void*)0);
773 }
774
775 pubk->arena = arena;
776 PORT_Memsetmemset(&spki, 0, sizeof(spki));
777
778 /* copy the DER into the arena, since Quick DER returns data that points
779 into the DER input, which may get freed by the caller */
780 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(arena, &newDerSubjKeyInfo, &cert->derSubjKeyInfo);
781 if (rv != SECSuccess) {
782 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
783 return NULL((void*)0);
784 }
785
786 /* we haven't bothered decoding the spki struct yet, do it now */
787 rv = SEC_QuickDERDecodeItemSEC_QuickDERDecodeItem_Util(arena, &spki,
788 nsslowcert_SubjectPublicKeyInfoTemplate, &newDerSubjKeyInfo);
789 if (rv != SECSuccess) {
790 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
791 return NULL((void*)0);
792 }
793
794 /* Convert bit string length from bits to bytes */
795 os = spki.subjectPublicKey;
796 DER_ConvertBitString(&os){ (&os)->len = ((&os)->len + 7) >> 3; };
797
798 tag = SECOID_GetAlgorithmTagSECOID_GetAlgorithmTag_Util(&spki.algorithm);
799 switch (tag) {
800 case SEC_OID_X500_RSA_ENCRYPTION:
801 case SEC_OID_PKCS1_RSA_ENCRYPTION:
802 case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
803 pubk->keyType = NSSLOWKEYRSAKey;
804 prepare_low_rsa_pub_key_for_asn1(pubk);
805 rv = SEC_QuickDERDecodeItemSEC_QuickDERDecodeItem_Util(arena, pubk,
806 nsslowcert_RSAPublicKeyTemplate, &os);
807 if (rv == SECSuccess)
808 return pubk;
809 break;
810 case SEC_OID_ANSIX9_DSA_SIGNATURE:
811 pubk->keyType = NSSLOWKEYDSAKey;
812 prepare_low_dsa_pub_key_for_asn1(pubk);
813 rv = SEC_QuickDERDecodeItemSEC_QuickDERDecodeItem_Util(arena, pubk,
814 nsslowcert_DSAPublicKeyTemplate, &os);
815 if (rv == SECSuccess)
816 return pubk;
817 break;
818 case SEC_OID_X942_DIFFIE_HELMAN_KEY:
819 pubk->keyType = NSSLOWKEYDHKey;
820 prepare_low_dh_pub_key_for_asn1(pubk);
821 rv = SEC_QuickDERDecodeItemSEC_QuickDERDecodeItem_Util(arena, pubk,
822 nsslowcert_DHPublicKeyTemplate, &os);
823 if (rv == SECSuccess)
824 return pubk;
825 break;
826 case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
827 pubk->keyType = NSSLOWKEYECKey;
828 /* Since PKCS#11 directly takes the DER encoding of EC params
829 * and public value, we don't need any decoding here.
830 */
831 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(arena, &pubk->u.ec.ecParams.DEREncoding,
832 &spki.algorithm.parameters);
833 if (rv != SECSuccess)
834 break;
835
836 /* Fill out the rest of the ecParams structure
837 * based on the encoded params
838 */
839 if (LGEC_FillParams(arena, &pubk->u.ec.ecParams.DEREncoding,
840 &pubk->u.ec.ecParams) != SECSuccess)
841 break;
842
843 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(arena, &pubk->u.ec.publicValue, &os);
844 if (rv == SECSuccess)
845 return pubk;
846 break;
847 default:
848 rv = SECFailure;
Value stored to 'rv' is never read
849 break;
850 }
851
852 lg_nsslowkey_DestroyPublicKey(pubk);
853 return NULL((void*)0);
854}