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 ** secutil.c - various functions used by security stuff
6 **
7 */
8
9 #include "prtypes.h"
10 #include "prtime.h"
11 #include "prlong.h"
12 #include "prerror.h"
13 #include "prprf.h"
14 #include "plgetopt.h"
15 #include "prenv.h"
16 #include "prnetdb.h"
17
18 #include "cryptohi.h"
19 #include "secutil.h"
20 #include "secpkcs7.h"
21 #include "secpkcs5.h"
22 #include <stdarg.h>
23 #include <sys/stat.h>
24 #include <errno.h>
25
26 #ifdef XP_UNIX
27 #include <unistd.h>
28 #endif
29
30 /* for SEC_TraverseNames */
31 #include "cert.h"
32 #include "certt.h"
33 #include "certdb.h"
34
35 /* #include "secmod.h" */
36 #include "pk11func.h"
37 #include "secoid.h"
38
39 static char consoleName[] = {
40 #ifdef XP_UNIX
41 "/dev/tty"
42 #else
43 #ifdef XP_OS2
44 "\\DEV\\CON"
45 #else
46 "CON:"
47 #endif
48 #endif
49 };
50
51 #include "nssutil.h"
52 #include "ssl.h"
53 #include "sslproto.h"
54
55 static PRBool utf8DisplayEnabled = PR_FALSE;
56
57 void
SECU_EnableUtf8Display(PRBool enable)58 SECU_EnableUtf8Display(PRBool enable)
59 {
60 utf8DisplayEnabled = enable;
61 }
62
63 PRBool
SECU_GetUtf8DisplayEnabled(void)64 SECU_GetUtf8DisplayEnabled(void)
65 {
66 return utf8DisplayEnabled;
67 }
68
69 static void
secu_ClearPassword(char * p)70 secu_ClearPassword(char *p)
71 {
72 if (p) {
73 PORT_Memset(p, 0, PORT_Strlen(p));
74 PORT_Free(p);
75 }
76 }
77
78 char *
SECU_GetPasswordString(void * arg,char * prompt)79 SECU_GetPasswordString(void *arg, char *prompt)
80 {
81 #ifndef _WINDOWS
82 char *p = NULL;
83 FILE *input, *output;
84
85 /* open terminal */
86 input = fopen(consoleName, "r");
87 if (input == NULL) {
88 fprintf(stderr, "Error opening input terminal for read\n");
89 return NULL;
90 }
91
92 output = fopen(consoleName, "w");
93 if (output == NULL) {
94 fprintf(stderr, "Error opening output terminal for write\n");
95 fclose(input);
96 return NULL;
97 }
98
99 p = SEC_GetPassword(input, output, prompt, SEC_BlindCheckPassword);
100
101 fclose(input);
102 fclose(output);
103
104 return p;
105
106 #else
107 /* Win32 version of above. opening the console may fail
108 on windows95, and certainly isn't necessary.. */
109
110 char *p = NULL;
111
112 p = SEC_GetPassword(stdin, stdout, prompt, SEC_BlindCheckPassword);
113 return p;
114
115 #endif
116 }
117
118 /*
119 * p a s s w o r d _ h a r d c o d e
120 *
121 * A function to use the password passed in the -f(pwfile) argument
122 * of the command line.
123 * After use once, null it out otherwise PKCS11 calls us forever.?
124 *
125 */
126 char *
SECU_FilePasswd(PK11SlotInfo * slot,PRBool retry,void * arg)127 SECU_FilePasswd(PK11SlotInfo *slot, PRBool retry, void *arg)
128 {
129 char *phrases, *phrase;
130 PRFileDesc *fd;
131 PRInt32 nb;
132 char *pwFile = arg;
133 int i;
134 const long maxPwdFileSize = 4096;
135 char *tokenName = NULL;
136 int tokenLen = 0;
137
138 if (!pwFile)
139 return 0;
140
141 if (retry) {
142 return 0; /* no good retrying - the files contents will be the same */
143 }
144
145 phrases = PORT_ZAlloc(maxPwdFileSize);
146
147 if (!phrases) {
148 return 0; /* out of memory */
149 }
150
151 fd = PR_Open(pwFile, PR_RDONLY, 0);
152 if (!fd) {
153 fprintf(stderr, "No password file \"%s\" exists.\n", pwFile);
154 PORT_Free(phrases);
155 return NULL;
156 }
157
158 nb = PR_Read(fd, phrases, maxPwdFileSize);
159
160 PR_Close(fd);
161
162 if (nb == 0) {
163 fprintf(stderr, "password file contains no data\n");
164 PORT_Free(phrases);
165 return NULL;
166 }
167
168 if (slot) {
169 tokenName = PK11_GetTokenName(slot);
170 if (tokenName) {
171 tokenLen = PORT_Strlen(tokenName);
172 }
173 }
174 i = 0;
175 do {
176 int startphrase = i;
177 int phraseLen;
178
179 /* handle the Windows EOL case */
180 while (phrases[i] != '\r' && phrases[i] != '\n' && i < nb)
181 i++;
182 /* terminate passphrase */
183 phrases[i++] = '\0';
184 /* clean up any EOL before the start of the next passphrase */
185 while ((i < nb) && (phrases[i] == '\r' || phrases[i] == '\n')) {
186 phrases[i++] = '\0';
187 }
188 /* now analyze the current passphrase */
189 phrase = &phrases[startphrase];
190 if (!tokenName)
191 break;
192 if (PORT_Strncmp(phrase, tokenName, tokenLen))
193 continue;
194 phraseLen = PORT_Strlen(phrase);
195 if (phraseLen < (tokenLen + 1))
196 continue;
197 if (phrase[tokenLen] != ':')
198 continue;
199 phrase = &phrase[tokenLen + 1];
200 break;
201
202 } while (i < nb);
203
204 phrase = PORT_Strdup((char *)phrase);
205 PORT_Free(phrases);
206 return phrase;
207 }
208
209 char *
SECU_GetModulePassword(PK11SlotInfo * slot,PRBool retry,void * arg)210 SECU_GetModulePassword(PK11SlotInfo *slot, PRBool retry, void *arg)
211 {
212 char prompt[255];
213 secuPWData *pwdata = (secuPWData *)arg;
214 secuPWData pwnull = { PW_NONE, 0 };
215 secuPWData pwxtrn = { PW_EXTERNAL, "external" };
216
217 if (pwdata == NULL)
218 pwdata = &pwnull;
219
220 if (PK11_ProtectedAuthenticationPath(slot)) {
221 pwdata = &pwxtrn;
222 }
223 if (retry && pwdata->source != PW_NONE) {
224 PR_fprintf(PR_STDERR, "Incorrect password/PIN entered.\n");
225 return NULL;
226 }
227
228 switch (pwdata->source) {
229 case PW_NONE:
230 sprintf(prompt, "Enter Password or Pin for \"%s\":",
231 PK11_GetTokenName(slot));
232 return SECU_GetPasswordString(NULL, prompt);
233 case PW_FROMFILE:
234 return SECU_FilePasswd(slot, retry, pwdata->data);
235 case PW_EXTERNAL:
236 sprintf(prompt,
237 "Press Enter, then enter PIN for \"%s\" on external device.\n",
238 PK11_GetTokenName(slot));
239 (void)SECU_GetPasswordString(NULL, prompt);
240 /* Fall Through */
241 case PW_PLAINTEXT:
242 return PL_strdup(pwdata->data);
243 default:
244 break;
245 }
246
247 PR_fprintf(PR_STDERR, "Password check failed: No password found.\n");
248 return NULL;
249 }
250
251 char *
secu_InitSlotPassword(PK11SlotInfo * slot,PRBool retry,void * arg)252 secu_InitSlotPassword(PK11SlotInfo *slot, PRBool retry, void *arg)
253 {
254 char *p0 = NULL;
255 char *p1 = NULL;
256 FILE *input, *output;
257 secuPWData *pwdata = arg;
258
259 if (pwdata->source == PW_FROMFILE) {
260 return SECU_FilePasswd(slot, retry, pwdata->data);
261 }
262 if (pwdata->source == PW_PLAINTEXT) {
263 return PL_strdup(pwdata->data);
264 }
265
266 /* PW_NONE - get it from tty */
267 /* open terminal */
268 #ifdef _WINDOWS
269 input = stdin;
270 #else
271 input = fopen(consoleName, "r");
272 #endif
273 if (input == NULL) {
274 PR_fprintf(PR_STDERR, "Error opening input terminal for read\n");
275 return NULL;
276 }
277
278 /* we have no password, so initialize database with one */
279 PR_fprintf(PR_STDERR,
280 "Enter a password which will be used to encrypt your keys.\n"
281 "The password should be at least 8 characters long,\n"
282 "and should contain at least one non-alphabetic character.\n\n");
283
284 output = fopen(consoleName, "w");
285 if (output == NULL) {
286 PR_fprintf(PR_STDERR, "Error opening output terminal for write\n");
287 #ifndef _WINDOWS
288 fclose(input);
289 #endif
290 return NULL;
291 }
292
293 for (;;) {
294 if (p0)
295 PORT_Free(p0);
296 p0 = SEC_GetPassword(input, output, "Enter new password: ",
297 SEC_BlindCheckPassword);
298
299 if (p1)
300 PORT_Free(p1);
301 p1 = SEC_GetPassword(input, output, "Re-enter password: ",
302 SEC_BlindCheckPassword);
303 if (p0 && p1 && !PORT_Strcmp(p0, p1)) {
304 break;
305 }
306 PR_fprintf(PR_STDERR, "Passwords do not match. Try again.\n");
307 }
308
309 /* clear out the duplicate password string */
310 secu_ClearPassword(p1);
311
312 fclose(input);
313 fclose(output);
314
315 return p0;
316 }
317
318 SECStatus
SECU_ChangePW(PK11SlotInfo * slot,char * passwd,char * pwFile)319 SECU_ChangePW(PK11SlotInfo *slot, char *passwd, char *pwFile)
320 {
321 return SECU_ChangePW2(slot, passwd, 0, pwFile, 0);
322 }
323
324 SECStatus
SECU_ChangePW2(PK11SlotInfo * slot,char * oldPass,char * newPass,char * oldPwFile,char * newPwFile)325 SECU_ChangePW2(PK11SlotInfo *slot, char *oldPass, char *newPass,
326 char *oldPwFile, char *newPwFile)
327 {
328 SECStatus rv;
329 secuPWData pwdata, newpwdata;
330 char *oldpw = NULL, *newpw = NULL;
331
332 if (oldPass) {
333 pwdata.source = PW_PLAINTEXT;
334 pwdata.data = oldPass;
335 } else if (oldPwFile) {
336 pwdata.source = PW_FROMFILE;
337 pwdata.data = oldPwFile;
338 } else {
339 pwdata.source = PW_NONE;
340 pwdata.data = NULL;
341 }
342
343 if (newPass) {
344 newpwdata.source = PW_PLAINTEXT;
345 newpwdata.data = newPass;
346 } else if (newPwFile) {
347 newpwdata.source = PW_FROMFILE;
348 newpwdata.data = newPwFile;
349 } else {
350 newpwdata.source = PW_NONE;
351 newpwdata.data = NULL;
352 }
353
354 if (PK11_NeedUserInit(slot)) {
355 newpw = secu_InitSlotPassword(slot, PR_FALSE, &pwdata);
356 rv = PK11_InitPin(slot, (char *)NULL, newpw);
357 goto done;
358 }
359
360 for (;;) {
361 oldpw = SECU_GetModulePassword(slot, PR_FALSE, &pwdata);
362
363 if (PK11_CheckUserPassword(slot, oldpw) != SECSuccess) {
364 if (pwdata.source == PW_NONE) {
365 PR_fprintf(PR_STDERR, "Invalid password. Try again.\n");
366 } else {
367 PR_fprintf(PR_STDERR, "Invalid password.\n");
368 PORT_Memset(oldpw, 0, PL_strlen(oldpw));
369 PORT_Free(oldpw);
370 rv = SECFailure;
371 goto done;
372 }
373 } else
374 break;
375
376 PORT_Free(oldpw);
377 }
378
379 newpw = secu_InitSlotPassword(slot, PR_FALSE, &newpwdata);
380
381 rv = PK11_ChangePW(slot, oldpw, newpw);
382 if (rv != SECSuccess) {
383 PR_fprintf(PR_STDERR, "Failed to change password.\n");
384 } else {
385 PR_fprintf(PR_STDOUT, "Password changed successfully.\n");
386 }
387
388 PORT_Memset(oldpw, 0, PL_strlen(oldpw));
389 PORT_Free(oldpw);
390
391 done:
392 if (newpw) {
393 PORT_Memset(newpw, 0, PL_strlen(newpw));
394 PORT_Free(newpw);
395 }
396 return rv;
397 }
398
399 struct matchobj {
400 SECItem index;
401 char *nname;
402 PRBool found;
403 };
404
405 char *
SECU_DefaultSSLDir(void)406 SECU_DefaultSSLDir(void)
407 {
408 char *dir;
409 static char sslDir[1000];
410
411 dir = PR_GetEnvSecure("SSL_DIR");
412 if (!dir)
413 return NULL;
414
415 if (strlen(dir) >= PR_ARRAY_SIZE(sslDir)) {
416 return NULL;
417 }
418 sprintf(sslDir, "%s", dir);
419
420 if (sslDir[strlen(sslDir) - 1] == '/')
421 sslDir[strlen(sslDir) - 1] = 0;
422
423 return sslDir;
424 }
425
426 char *
SECU_AppendFilenameToDir(char * dir,char * filename)427 SECU_AppendFilenameToDir(char *dir, char *filename)
428 {
429 static char path[1000];
430
431 if (dir[strlen(dir) - 1] == '/')
432 sprintf(path, "%s%s", dir, filename);
433 else
434 sprintf(path, "%s/%s", dir, filename);
435 return path;
436 }
437
438 char *
SECU_ConfigDirectory(const char * base)439 SECU_ConfigDirectory(const char *base)
440 {
441 static PRBool initted = PR_FALSE;
442 const char *dir = ".netscape";
443 char *home;
444 static char buf[1000];
445
446 if (initted)
447 return buf;
448
449 if (base == NULL || *base == 0) {
450 home = PR_GetEnvSecure("HOME");
451 if (!home)
452 home = "";
453
454 if (*home && home[strlen(home) - 1] == '/')
455 sprintf(buf, "%.900s%s", home, dir);
456 else
457 sprintf(buf, "%.900s/%s", home, dir);
458 } else {
459 sprintf(buf, "%.900s", base);
460 if (buf[strlen(buf) - 1] == '/')
461 buf[strlen(buf) - 1] = 0;
462 }
463
464 initted = PR_TRUE;
465 return buf;
466 }
467
468 /*Turn off SSL for now */
469 /* This gets called by SSL when server wants our cert & key */
470 int
SECU_GetClientAuthData(void * arg,PRFileDesc * fd,struct CERTDistNamesStr * caNames,struct CERTCertificateStr ** pRetCert,struct SECKEYPrivateKeyStr ** pRetKey)471 SECU_GetClientAuthData(void *arg, PRFileDesc *fd,
472 struct CERTDistNamesStr *caNames,
473 struct CERTCertificateStr **pRetCert,
474 struct SECKEYPrivateKeyStr **pRetKey)
475 {
476 SECKEYPrivateKey *key;
477 CERTCertificate *cert;
478 int errsave;
479
480 if (arg == NULL) {
481 fprintf(stderr, "no key/cert name specified for client auth\n");
482 return -1;
483 }
484 cert = PK11_FindCertFromNickname(arg, NULL);
485 errsave = PORT_GetError();
486 if (!cert) {
487 if (errsave == SEC_ERROR_BAD_PASSWORD)
488 fprintf(stderr, "Bad password\n");
489 else if (errsave > 0)
490 fprintf(stderr, "Unable to read cert (error %d)\n", errsave);
491 else if (errsave == SEC_ERROR_BAD_DATABASE)
492 fprintf(stderr, "Unable to get cert from database (%d)\n", errsave);
493 else
494 fprintf(stderr, "SECKEY_FindKeyByName: internal error %d\n", errsave);
495 return -1;
496 }
497
498 key = PK11_FindKeyByAnyCert(arg, NULL);
499 if (!key) {
500 fprintf(stderr, "Unable to get key (%d)\n", PORT_GetError());
501 return -1;
502 }
503
504 *pRetCert = cert;
505 *pRetKey = key;
506
507 return 0;
508 }
509
510 SECStatus
SECU_ReadDERFromFile(SECItem * der,PRFileDesc * inFile,PRBool ascii,PRBool warnOnPrivateKeyInAsciiFile)511 SECU_ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii,
512 PRBool warnOnPrivateKeyInAsciiFile)
513 {
514 SECStatus rv;
515 if (ascii) {
516 /* First convert ascii to binary */
517 SECItem filedata;
518 char *asc, *body;
519
520 /* Read in ascii data */
521 rv = SECU_FileToItem(&filedata, inFile);
522 if (rv != SECSuccess)
523 return rv;
524 asc = (char *)filedata.data;
525 if (!asc) {
526 fprintf(stderr, "unable to read data from input file\n");
527 return SECFailure;
528 }
529
530 if (warnOnPrivateKeyInAsciiFile && strstr(asc, "PRIVATE KEY")) {
531 fprintf(stderr, "Warning: ignoring private key. Consider to use "
532 "pk12util.\n");
533 }
534
535 /* check for headers and trailers and remove them */
536 if ((body = strstr(asc, "-----BEGIN")) != NULL) {
537 char *trailer = NULL;
538 asc = body;
539 body = PORT_Strchr(body, '\n');
540 if (!body)
541 body = PORT_Strchr(asc, '\r'); /* maybe this is a MAC file */
542 if (body)
543 trailer = strstr(++body, "-----END");
544 if (trailer != NULL) {
545 *trailer = '\0';
546 } else {
547 fprintf(stderr, "input has header but no trailer\n");
548 PORT_Free(filedata.data);
549 return SECFailure;
550 }
551 } else {
552 /* need one additional byte for zero terminator */
553 rv = SECITEM_ReallocItemV2(NULL, &filedata, filedata.len + 1);
554 if (rv != SECSuccess) {
555 PORT_Free(filedata.data);
556 return rv;
557 }
558 body = (char *)filedata.data;
559 body[filedata.len - 1] = '\0';
560 }
561
562 /* Convert to binary */
563 rv = ATOB_ConvertAsciiToItem(der, body);
564 if (rv != SECSuccess) {
565 fprintf(stderr, "error converting ascii to binary (%s)\n",
566 SECU_Strerror(PORT_GetError()));
567 PORT_Free(filedata.data);
568 return SECFailure;
569 }
570
571 PORT_Free(filedata.data);
572 } else {
573 /* Read in binary der */
574 rv = SECU_FileToItem(der, inFile);
575 if (rv != SECSuccess) {
576 fprintf(stderr, "error converting der (%s)\n",
577 SECU_Strerror(PORT_GetError()));
578 return SECFailure;
579 }
580 }
581 return SECSuccess;
582 }
583
584 #define INDENT_MULT 4
585
586 SECStatus
SECU_StripTagAndLength(SECItem * i)587 SECU_StripTagAndLength(SECItem *i)
588 {
589 unsigned int start;
590
591 if (!i || !i->data || i->len < 2) { /* must be at least tag and length */
592 return SECFailure;
593 }
594 start = ((i->data[1] & 0x80) ? (i->data[1] & 0x7f) + 2 : 2);
595 if (i->len < start) {
596 return SECFailure;
597 }
598 i->data += start;
599 i->len -= start;
600 return SECSuccess;
601 }
602
603 static void
secu_PrintRawStringQuotesOptional(FILE * out,SECItem * si,const char * m,int level,PRBool quotes)604 secu_PrintRawStringQuotesOptional(FILE *out, SECItem *si, const char *m,
605 int level, PRBool quotes)
606 {
607 int column;
608 unsigned int i;
609
610 if (m) {
611 SECU_Indent(out, level);
612 fprintf(out, "%s: ", m);
613 column = (level * INDENT_MULT) + strlen(m) + 2;
614 level++;
615 } else {
616 SECU_Indent(out, level);
617 column = level * INDENT_MULT;
618 }
619 if (quotes) {
620 fprintf(out, "\"");
621 column++;
622 }
623
624 for (i = 0; i < si->len; i++) {
625 unsigned char val = si->data[i];
626 unsigned char c;
627 if (SECU_GetWrapEnabled() && column > 76) {
628 SECU_Newline(out);
629 SECU_Indent(out, level);
630 column = level * INDENT_MULT;
631 }
632
633 if (utf8DisplayEnabled) {
634 if (val < 32)
635 c = '.';
636 else
637 c = val;
638 } else {
639 c = printable[val];
640 }
641 fprintf(out, "%c", c);
642 column++;
643 }
644
645 if (quotes) {
646 fprintf(out, "\"");
647 column++;
648 }
649 if (SECU_GetWrapEnabled() &&
650 (column != level * INDENT_MULT || column > 76)) {
651 SECU_Newline(out);
652 }
653 }
654
655 static void
secu_PrintRawString(FILE * out,SECItem * si,const char * m,int level)656 secu_PrintRawString(FILE *out, SECItem *si, const char *m, int level)
657 {
658 secu_PrintRawStringQuotesOptional(out, si, m, level, PR_TRUE);
659 }
660
661 void
SECU_PrintString(FILE * out,const SECItem * si,const char * m,int level)662 SECU_PrintString(FILE *out, const SECItem *si, const char *m, int level)
663 {
664 SECItem my = *si;
665
666 if (SECSuccess != SECU_StripTagAndLength(&my) || !my.len)
667 return;
668 secu_PrintRawString(out, &my, m, level);
669 }
670
671 /* print an unencoded boolean */
672 static void
secu_PrintBoolean(FILE * out,SECItem * i,const char * m,int level)673 secu_PrintBoolean(FILE *out, SECItem *i, const char *m, int level)
674 {
675 int val = 0;
676
677 if (i->data && i->len) {
678 val = i->data[0];
679 }
680
681 if (!m) {
682 m = "Boolean";
683 }
684 SECU_Indent(out, level);
685 fprintf(out, "%s: %s\n", m, (val ? "True" : "False"));
686 }
687
688 /*
689 * Format and print "time". If the tag message "m" is not NULL,
690 * do indent formatting based on "level" and add a newline afterward;
691 * otherwise just print the formatted time string only.
692 */
693 static void
secu_PrintTime(FILE * out,const PRTime time,const char * m,int level)694 secu_PrintTime(FILE *out, const PRTime time, const char *m, int level)
695 {
696 PRExplodedTime printableTime;
697 char *timeString;
698
699 /* Convert to local time */
700 PR_ExplodeTime(time, PR_GMTParameters, &printableTime);
701
702 timeString = PORT_Alloc(256);
703 if (timeString == NULL)
704 return;
705
706 if (m != NULL) {
707 SECU_Indent(out, level);
708 fprintf(out, "%s: ", m);
709 }
710
711 if (PR_FormatTime(timeString, 256, "%a %b %d %H:%M:%S %Y", &printableTime)) {
712 fputs(timeString, out);
713 }
714
715 if (m != NULL)
716 fprintf(out, "\n");
717
718 PORT_Free(timeString);
719 }
720
721 /*
722 * Format and print the UTC Time "t". If the tag message "m" is not NULL,
723 * do indent formatting based on "level" and add a newline afterward;
724 * otherwise just print the formatted time string only.
725 */
726 void
SECU_PrintUTCTime(FILE * out,const SECItem * t,const char * m,int level)727 SECU_PrintUTCTime(FILE *out, const SECItem *t, const char *m, int level)
728 {
729 PRTime time;
730 SECStatus rv;
731
732 rv = DER_UTCTimeToTime(&time, t);
733 if (rv != SECSuccess)
734 return;
735
736 secu_PrintTime(out, time, m, level);
737 }
738
739 /*
740 * Format and print the Generalized Time "t". If the tag message "m"
741 * is not NULL, * do indent formatting based on "level" and add a newline
742 * afterward; otherwise just print the formatted time string only.
743 */
744 void
SECU_PrintGeneralizedTime(FILE * out,const SECItem * t,const char * m,int level)745 SECU_PrintGeneralizedTime(FILE *out, const SECItem *t, const char *m, int level)
746 {
747 PRTime time;
748 SECStatus rv;
749
750 rv = DER_GeneralizedTimeToTime(&time, t);
751 if (rv != SECSuccess)
752 return;
753
754 secu_PrintTime(out, time, m, level);
755 }
756
757 /*
758 * Format and print the UTC or Generalized Time "t". If the tag message
759 * "m" is not NULL, do indent formatting based on "level" and add a newline
760 * afterward; otherwise just print the formatted time string only.
761 */
762 void
SECU_PrintTimeChoice(FILE * out,const SECItem * t,const char * m,int level)763 SECU_PrintTimeChoice(FILE *out, const SECItem *t, const char *m, int level)
764 {
765 switch (t->type) {
766 case siUTCTime:
767 SECU_PrintUTCTime(out, t, m, level);
768 break;
769
770 case siGeneralizedTime:
771 SECU_PrintGeneralizedTime(out, t, m, level);
772 break;
773
774 default:
775 PORT_Assert(0);
776 break;
777 }
778 }
779
780 /* This prints a SET or SEQUENCE */
781 static void
SECU_PrintSet(FILE * out,const SECItem * t,const char * m,int level)782 SECU_PrintSet(FILE *out, const SECItem *t, const char *m, int level)
783 {
784 int type = t->data[0] & SEC_ASN1_TAGNUM_MASK;
785 int constructed = t->data[0] & SEC_ASN1_CONSTRUCTED;
786 const char *label;
787 SECItem my = *t;
788
789 if (!constructed) {
790 SECU_PrintAsHex(out, t, m, level);
791 return;
792 }
793 if (SECSuccess != SECU_StripTagAndLength(&my))
794 return;
795
796 SECU_Indent(out, level);
797 if (m) {
798 fprintf(out, "%s: ", m);
799 }
800
801 if (type == SEC_ASN1_SET)
802 label = "Set ";
803 else if (type == SEC_ASN1_SEQUENCE)
804 label = "Sequence ";
805 else
806 label = "";
807 fprintf(out, "%s{\n", label); /* } */
808
809 while (my.len >= 2) {
810 SECItem tmp = my;
811
812 if (tmp.data[1] & 0x80) {
813 unsigned int i;
814 unsigned int lenlen = tmp.data[1] & 0x7f;
815 if (lenlen > sizeof tmp.len)
816 break;
817 tmp.len = 0;
818 for (i = 0; i < lenlen; i++) {
819 tmp.len = (tmp.len << 8) | tmp.data[2 + i];
820 }
821 tmp.len += lenlen + 2;
822 } else {
823 tmp.len = tmp.data[1] + 2;
824 }
825 if (tmp.len > my.len) {
826 tmp.len = my.len;
827 }
828 my.data += tmp.len;
829 my.len -= tmp.len;
830 SECU_PrintAny(out, &tmp, NULL, level + 1);
831 }
832 SECU_Indent(out, level);
833 fprintf(out, /* { */ "}\n");
834 }
835
836 static void
secu_PrintContextSpecific(FILE * out,const SECItem * i,const char * m,int level)837 secu_PrintContextSpecific(FILE *out, const SECItem *i, const char *m, int level)
838 {
839 int type = i->data[0] & SEC_ASN1_TAGNUM_MASK;
840 int constructed = i->data[0] & SEC_ASN1_CONSTRUCTED;
841 SECItem tmp;
842
843 if (constructed) {
844 char *m2;
845 if (!m)
846 m2 = PR_smprintf("[%d]", type);
847 else
848 m2 = PR_smprintf("%s: [%d]", m, type);
849 if (m2) {
850 SECU_PrintSet(out, i, m2, level);
851 PR_smprintf_free(m2);
852 }
853 return;
854 }
855
856 SECU_Indent(out, level);
857 if (m) {
858 fprintf(out, "%s: ", m);
859 }
860 fprintf(out, "[%d]\n", type);
861
862 tmp = *i;
863 if (SECSuccess == SECU_StripTagAndLength(&tmp))
864 SECU_PrintAsHex(out, &tmp, m, level + 1);
865 }
866
867 static void
secu_PrintOctetString(FILE * out,const SECItem * i,const char * m,int level)868 secu_PrintOctetString(FILE *out, const SECItem *i, const char *m, int level)
869 {
870 SECItem tmp = *i;
871 if (SECSuccess == SECU_StripTagAndLength(&tmp))
872 SECU_PrintAsHex(out, &tmp, m, level);
873 }
874
875 static void
secu_PrintBitString(FILE * out,const SECItem * i,const char * m,int level)876 secu_PrintBitString(FILE *out, const SECItem *i, const char *m, int level)
877 {
878 int unused_bits;
879 SECItem tmp = *i;
880
881 if (SECSuccess != SECU_StripTagAndLength(&tmp) || tmp.len < 2)
882 return;
883
884 unused_bits = *tmp.data++;
885 tmp.len--;
886
887 SECU_PrintAsHex(out, &tmp, m, level);
888 if (unused_bits) {
889 SECU_Indent(out, level + 1);
890 fprintf(out, "(%d least significant bits unused)\n", unused_bits);
891 }
892 }
893
894 /* in a decoded bit string, the len member is a bit length. */
895 static void
secu_PrintDecodedBitString(FILE * out,const SECItem * i,const char * m,int level)896 secu_PrintDecodedBitString(FILE *out, const SECItem *i, const char *m, int level)
897 {
898 int unused_bits;
899 SECItem tmp = *i;
900
901 unused_bits = (tmp.len & 0x7) ? 8 - (tmp.len & 7) : 0;
902 DER_ConvertBitString(&tmp); /* convert length to byte length */
903
904 SECU_PrintAsHex(out, &tmp, m, level);
905 if (unused_bits) {
906 SECU_Indent(out, level + 1);
907 fprintf(out, "(%d least significant bits unused)\n", unused_bits);
908 }
909 }
910
911 /* Print a DER encoded Boolean */
912 void
SECU_PrintEncodedBoolean(FILE * out,const SECItem * i,const char * m,int level)913 SECU_PrintEncodedBoolean(FILE *out, const SECItem *i, const char *m, int level)
914 {
915 SECItem my = *i;
916 if (SECSuccess == SECU_StripTagAndLength(&my))
917 secu_PrintBoolean(out, &my, m, level);
918 }
919
920 /* Print a DER encoded integer */
921 void
SECU_PrintEncodedInteger(FILE * out,const SECItem * i,const char * m,int level)922 SECU_PrintEncodedInteger(FILE *out, const SECItem *i, const char *m, int level)
923 {
924 SECItem my = *i;
925 if (SECSuccess == SECU_StripTagAndLength(&my))
926 SECU_PrintInteger(out, &my, m, level);
927 }
928
929 /* Print a DER encoded OID */
930 void
SECU_PrintEncodedObjectID(FILE * out,const SECItem * i,const char * m,int level)931 SECU_PrintEncodedObjectID(FILE *out, const SECItem *i, const char *m, int level)
932 {
933 SECItem my = *i;
934 if (SECSuccess == SECU_StripTagAndLength(&my))
935 SECU_PrintObjectID(out, &my, m, level);
936 }
937
938 static void
secu_PrintBMPString(FILE * out,const SECItem * i,const char * m,int level)939 secu_PrintBMPString(FILE *out, const SECItem *i, const char *m, int level)
940 {
941 unsigned char *s;
942 unsigned char *d;
943 int len;
944 SECItem tmp = { 0, 0, 0 };
945 SECItem my = *i;
946
947 if (SECSuccess != SECU_StripTagAndLength(&my))
948 goto loser;
949 if (my.len % 2)
950 goto loser;
951 len = (int)(my.len / 2);
952 tmp.data = (unsigned char *)PORT_Alloc(len);
953 if (!tmp.data)
954 goto loser;
955 tmp.len = len;
956 for (s = my.data, d = tmp.data; len > 0; len--) {
957 PRUint32 bmpChar = (s[0] << 8) | s[1];
958 s += 2;
959 if (!isprint(bmpChar))
960 goto loser;
961 *d++ = (unsigned char)bmpChar;
962 }
963 secu_PrintRawString(out, &tmp, m, level);
964 PORT_Free(tmp.data);
965 return;
966
967 loser:
968 SECU_PrintAsHex(out, i, m, level);
969 if (tmp.data)
970 PORT_Free(tmp.data);
971 }
972
973 static void
secu_PrintUniversalString(FILE * out,const SECItem * i,const char * m,int level)974 secu_PrintUniversalString(FILE *out, const SECItem *i, const char *m, int level)
975 {
976 unsigned char *s;
977 unsigned char *d;
978 int len;
979 SECItem tmp = { 0, 0, 0 };
980 SECItem my = *i;
981
982 if (SECSuccess != SECU_StripTagAndLength(&my))
983 goto loser;
984 if (my.len % 4)
985 goto loser;
986 len = (int)(my.len / 4);
987 tmp.data = (unsigned char *)PORT_Alloc(len);
988 if (!tmp.data)
989 goto loser;
990 tmp.len = len;
991 for (s = my.data, d = tmp.data; len > 0; len--) {
992 PRUint32 bmpChar = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
993 s += 4;
994 if (!isprint(bmpChar))
995 goto loser;
996 *d++ = (unsigned char)bmpChar;
997 }
998 secu_PrintRawString(out, &tmp, m, level);
999 PORT_Free(tmp.data);
1000 return;
1001
1002 loser:
1003 SECU_PrintAsHex(out, i, m, level);
1004 if (tmp.data)
1005 PORT_Free(tmp.data);
1006 }
1007
1008 static void
secu_PrintUniversal(FILE * out,const SECItem * i,const char * m,int level)1009 secu_PrintUniversal(FILE *out, const SECItem *i, const char *m, int level)
1010 {
1011 switch (i->data[0] & SEC_ASN1_TAGNUM_MASK) {
1012 case SEC_ASN1_ENUMERATED:
1013 case SEC_ASN1_INTEGER:
1014 SECU_PrintEncodedInteger(out, i, m, level);
1015 break;
1016 case SEC_ASN1_OBJECT_ID:
1017 SECU_PrintEncodedObjectID(out, i, m, level);
1018 break;
1019 case SEC_ASN1_BOOLEAN:
1020 SECU_PrintEncodedBoolean(out, i, m, level);
1021 break;
1022 case SEC_ASN1_UTF8_STRING:
1023 case SEC_ASN1_PRINTABLE_STRING:
1024 case SEC_ASN1_VISIBLE_STRING:
1025 case SEC_ASN1_IA5_STRING:
1026 case SEC_ASN1_T61_STRING:
1027 SECU_PrintString(out, i, m, level);
1028 break;
1029 case SEC_ASN1_GENERALIZED_TIME:
1030 SECU_PrintGeneralizedTime(out, i, m, level);
1031 break;
1032 case SEC_ASN1_UTC_TIME:
1033 SECU_PrintUTCTime(out, i, m, level);
1034 break;
1035 case SEC_ASN1_NULL:
1036 SECU_Indent(out, level);
1037 if (m && m[0])
1038 fprintf(out, "%s: NULL\n", m);
1039 else
1040 fprintf(out, "NULL\n");
1041 break;
1042 case SEC_ASN1_SET:
1043 case SEC_ASN1_SEQUENCE:
1044 SECU_PrintSet(out, i, m, level);
1045 break;
1046 case SEC_ASN1_OCTET_STRING:
1047 secu_PrintOctetString(out, i, m, level);
1048 break;
1049 case SEC_ASN1_BIT_STRING:
1050 secu_PrintBitString(out, i, m, level);
1051 break;
1052 case SEC_ASN1_BMP_STRING:
1053 secu_PrintBMPString(out, i, m, level);
1054 break;
1055 case SEC_ASN1_UNIVERSAL_STRING:
1056 secu_PrintUniversalString(out, i, m, level);
1057 break;
1058 default:
1059 SECU_PrintAsHex(out, i, m, level);
1060 break;
1061 }
1062 }
1063
1064 void
SECU_PrintAny(FILE * out,const SECItem * i,const char * m,int level)1065 SECU_PrintAny(FILE *out, const SECItem *i, const char *m, int level)
1066 {
1067 if (i && i->len && i->data) {
1068 switch (i->data[0] & SEC_ASN1_CLASS_MASK) {
1069 case SEC_ASN1_CONTEXT_SPECIFIC:
1070 secu_PrintContextSpecific(out, i, m, level);
1071 break;
1072 case SEC_ASN1_UNIVERSAL:
1073 secu_PrintUniversal(out, i, m, level);
1074 break;
1075 default:
1076 SECU_PrintAsHex(out, i, m, level);
1077 break;
1078 }
1079 }
1080 }
1081
1082 static int
secu_PrintValidity(FILE * out,CERTValidity * v,char * m,int level)1083 secu_PrintValidity(FILE *out, CERTValidity *v, char *m, int level)
1084 {
1085 SECU_Indent(out, level);
1086 fprintf(out, "%s:\n", m);
1087 SECU_PrintTimeChoice(out, &v->notBefore, "Not Before", level + 1);
1088 SECU_PrintTimeChoice(out, &v->notAfter, "Not After ", level + 1);
1089 return 0;
1090 }
1091
1092 /* This function does NOT expect a DER type and length. */
1093 SECOidTag
SECU_PrintObjectID(FILE * out,const SECItem * oid,const char * m,int level)1094 SECU_PrintObjectID(FILE *out, const SECItem *oid, const char *m, int level)
1095 {
1096 SECOidData *oiddata;
1097 char *oidString = NULL;
1098
1099 oiddata = SECOID_FindOID(oid);
1100 if (oiddata != NULL) {
1101 const char *name = oiddata->desc;
1102 SECU_Indent(out, level);
1103 if (m != NULL)
1104 fprintf(out, "%s: ", m);
1105 fprintf(out, "%s\n", name);
1106 return oiddata->offset;
1107 }
1108 oidString = CERT_GetOidString(oid);
1109 if (oidString) {
1110 SECU_Indent(out, level);
1111 if (m != NULL)
1112 fprintf(out, "%s: ", m);
1113 fprintf(out, "%s\n", oidString);
1114 PR_smprintf_free(oidString);
1115 return SEC_OID_UNKNOWN;
1116 }
1117 SECU_PrintAsHex(out, oid, m, level);
1118 return SEC_OID_UNKNOWN;
1119 }
1120
1121 typedef struct secuPBEParamsStr {
1122 SECItem salt;
1123 SECItem iterationCount;
1124 SECItem keyLength;
1125 SECAlgorithmID cipherAlg;
1126 SECAlgorithmID kdfAlg;
1127 } secuPBEParams;
1128
1129 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
1130
1131 /* SECOID_PKCS5_PBKDF2 */
1132 const SEC_ASN1Template secuKDF2Params[] =
1133 {
1134 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(secuPBEParams) },
1135 { SEC_ASN1_OCTET_STRING, offsetof(secuPBEParams, salt) },
1136 { SEC_ASN1_INTEGER, offsetof(secuPBEParams, iterationCount) },
1137 { SEC_ASN1_INTEGER, offsetof(secuPBEParams, keyLength) },
1138 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(secuPBEParams, kdfAlg),
1139 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
1140 { 0 }
1141 };
1142
1143 /* PKCS5v1 & PKCS12 */
1144 const SEC_ASN1Template secuPBEParamsTemp[] =
1145 {
1146 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(secuPBEParams) },
1147 { SEC_ASN1_OCTET_STRING, offsetof(secuPBEParams, salt) },
1148 { SEC_ASN1_INTEGER, offsetof(secuPBEParams, iterationCount) },
1149 { 0 }
1150 };
1151
1152 /* SEC_OID_PKCS5_PBES2, SEC_OID_PKCS5_PBMAC1 */
1153 const SEC_ASN1Template secuPBEV2Params[] =
1154 {
1155 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(secuPBEParams) },
1156 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(secuPBEParams, kdfAlg),
1157 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
1158 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(secuPBEParams, cipherAlg),
1159 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
1160 { 0 }
1161 };
1162
1163 void
secu_PrintRSAPSSParams(FILE * out,SECItem * value,char * m,int level)1164 secu_PrintRSAPSSParams(FILE *out, SECItem *value, char *m, int level)
1165 {
1166 PLArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1167 SECStatus rv;
1168 SECKEYRSAPSSParams param;
1169 SECAlgorithmID maskHashAlg;
1170
1171 if (m) {
1172 SECU_Indent(out, level);
1173 fprintf(out, "%s:\n", m);
1174 }
1175
1176 if (!pool) {
1177 SECU_Indent(out, level);
1178 fprintf(out, "Out of memory\n");
1179 return;
1180 }
1181
1182 PORT_Memset(¶m, 0, sizeof param);
1183
1184 rv = SEC_QuickDERDecodeItem(pool, ¶m,
1185 SEC_ASN1_GET(SECKEY_RSAPSSParamsTemplate),
1186 value);
1187 if (rv == SECSuccess) {
1188 if (!param.hashAlg) {
1189 SECU_Indent(out, level + 1);
1190 fprintf(out, "Hash algorithm: default, SHA-1\n");
1191 } else {
1192 SECU_PrintObjectID(out, ¶m.hashAlg->algorithm,
1193 "Hash algorithm", level + 1);
1194 }
1195 if (!param.maskAlg) {
1196 SECU_Indent(out, level + 1);
1197 fprintf(out, "Mask algorithm: default, MGF1\n");
1198 SECU_Indent(out, level + 1);
1199 fprintf(out, "Mask hash algorithm: default, SHA-1\n");
1200 } else {
1201 SECU_PrintObjectID(out, ¶m.maskAlg->algorithm,
1202 "Mask algorithm", level + 1);
1203 rv = SEC_QuickDERDecodeItem(pool, &maskHashAlg,
1204 SEC_ASN1_GET(SECOID_AlgorithmIDTemplate),
1205 ¶m.maskAlg->parameters);
1206 if (rv == SECSuccess) {
1207 SECU_PrintObjectID(out, &maskHashAlg.algorithm,
1208 "Mask hash algorithm", level + 1);
1209 } else {
1210 SECU_Indent(out, level + 1);
1211 fprintf(out, "Invalid mask generation algorithm parameters\n");
1212 }
1213 }
1214 if (!param.saltLength.data) {
1215 SECU_Indent(out, level + 1);
1216 fprintf(out, "Salt length: default, %i (0x%2X)\n", 20, 20);
1217 } else {
1218 SECU_PrintInteger(out, ¶m.saltLength, "Salt Length", level + 1);
1219 }
1220 } else {
1221 SECU_Indent(out, level + 1);
1222 fprintf(out, "Invalid RSA-PSS parameters\n");
1223 }
1224 PORT_FreeArena(pool, PR_FALSE);
1225 }
1226
1227 void
secu_PrintKDF2Params(FILE * out,SECItem * value,char * m,int level)1228 secu_PrintKDF2Params(FILE *out, SECItem *value, char *m, int level)
1229 {
1230 PLArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1231 SECStatus rv;
1232 secuPBEParams param;
1233
1234 if (m) {
1235 SECU_Indent(out, level);
1236 fprintf(out, "%s:\n", m);
1237 }
1238
1239 if (!pool) {
1240 SECU_Indent(out, level);
1241 fprintf(out, "Out of memory\n");
1242 return;
1243 }
1244
1245 PORT_Memset(¶m, 0, sizeof param);
1246 rv = SEC_QuickDERDecodeItem(pool, ¶m, secuKDF2Params, value);
1247 if (rv == SECSuccess) {
1248 SECU_PrintAsHex(out, ¶m.salt, "Salt", level + 1);
1249 SECU_PrintInteger(out, ¶m.iterationCount, "Iteration Count",
1250 level + 1);
1251 SECU_PrintInteger(out, ¶m.keyLength, "Key Length", level + 1);
1252 SECU_PrintAlgorithmID(out, ¶m.kdfAlg, "KDF algorithm", level + 1);
1253 }
1254 PORT_FreeArena(pool, PR_FALSE);
1255 }
1256
1257 void
secu_PrintPKCS5V2Params(FILE * out,SECItem * value,char * m,int level)1258 secu_PrintPKCS5V2Params(FILE *out, SECItem *value, char *m, int level)
1259 {
1260 PLArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1261 SECStatus rv;
1262 secuPBEParams param;
1263
1264 if (m) {
1265 SECU_Indent(out, level);
1266 fprintf(out, "%s:\n", m);
1267 }
1268
1269 if (!pool) {
1270 SECU_Indent(out, level);
1271 fprintf(out, "Out of memory\n");
1272 return;
1273 }
1274
1275 PORT_Memset(¶m, 0, sizeof param);
1276 rv = SEC_QuickDERDecodeItem(pool, ¶m, secuPBEV2Params, value);
1277 if (rv == SECSuccess) {
1278 SECU_PrintAlgorithmID(out, ¶m.kdfAlg, "KDF", level + 1);
1279 SECU_PrintAlgorithmID(out, ¶m.cipherAlg, "Cipher", level + 1);
1280 }
1281 PORT_FreeArena(pool, PR_FALSE);
1282 }
1283
1284 void
secu_PrintPBEParams(FILE * out,SECItem * value,char * m,int level)1285 secu_PrintPBEParams(FILE *out, SECItem *value, char *m, int level)
1286 {
1287 PLArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1288 SECStatus rv;
1289 secuPBEParams param;
1290
1291 if (m) {
1292 SECU_Indent(out, level);
1293 fprintf(out, "%s:\n", m);
1294 }
1295
1296 if (!pool) {
1297 SECU_Indent(out, level);
1298 fprintf(out, "Out of memory\n");
1299 return;
1300 }
1301
1302 PORT_Memset(¶m, 0, sizeof(secuPBEParams));
1303 rv = SEC_QuickDERDecodeItem(pool, ¶m, secuPBEParamsTemp, value);
1304 if (rv == SECSuccess) {
1305 SECU_PrintAsHex(out, ¶m.salt, "Salt", level + 1);
1306 SECU_PrintInteger(out, ¶m.iterationCount, "Iteration Count",
1307 level + 1);
1308 }
1309 PORT_FreeArena(pool, PR_FALSE);
1310 }
1311
1312 /* This function does NOT expect a DER type and length. */
1313 void
SECU_PrintAlgorithmID(FILE * out,SECAlgorithmID * a,char * m,int level)1314 SECU_PrintAlgorithmID(FILE *out, SECAlgorithmID *a, char *m, int level)
1315 {
1316 SECOidTag algtag;
1317 SECU_PrintObjectID(out, &a->algorithm, m, level);
1318
1319 algtag = SECOID_GetAlgorithmTag(a);
1320 if (SEC_PKCS5IsAlgorithmPBEAlgTag(algtag)) {
1321 switch (algtag) {
1322 case SEC_OID_PKCS5_PBKDF2:
1323 secu_PrintKDF2Params(out, &a->parameters, "Parameters", level + 1);
1324 break;
1325 case SEC_OID_PKCS5_PBES2:
1326 secu_PrintPKCS5V2Params(out, &a->parameters, "Encryption", level + 1);
1327 break;
1328 case SEC_OID_PKCS5_PBMAC1:
1329 secu_PrintPKCS5V2Params(out, &a->parameters, "MAC", level + 1);
1330 break;
1331 default:
1332 secu_PrintPBEParams(out, &a->parameters, "Parameters", level + 1);
1333 break;
1334 }
1335 return;
1336 }
1337
1338 if (algtag == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
1339 secu_PrintRSAPSSParams(out, &a->parameters, "Parameters", level + 1);
1340 return;
1341 }
1342
1343 if (a->parameters.len == 0 ||
1344 (a->parameters.len == 2 &&
1345 PORT_Memcmp(a->parameters.data, "\005\000", 2) == 0)) {
1346 /* No arguments or NULL argument */
1347 } else {
1348 /* Print args to algorithm */
1349 SECU_PrintAsHex(out, &a->parameters, "Args", level + 1);
1350 }
1351 }
1352
1353 static void
secu_PrintAttribute(FILE * out,SEC_PKCS7Attribute * attr,char * m,int level)1354 secu_PrintAttribute(FILE *out, SEC_PKCS7Attribute *attr, char *m, int level)
1355 {
1356 SECItem *value;
1357 int i;
1358 char om[100];
1359
1360 if (m) {
1361 SECU_Indent(out, level);
1362 fprintf(out, "%s:\n", m);
1363 }
1364
1365 /*
1366 * Should make this smarter; look at the type field and then decode
1367 * and print the value(s) appropriately!
1368 */
1369 SECU_PrintObjectID(out, &(attr->type), "Type", level + 1);
1370 if (attr->values != NULL) {
1371 i = 0;
1372 while ((value = attr->values[i++]) != NULL) {
1373 sprintf(om, "Value (%d)%s", i, attr->encoded ? " (encoded)" : "");
1374 if (attr->encoded || attr->typeTag == NULL) {
1375 SECU_PrintAny(out, value, om, level + 1);
1376 } else {
1377 switch (attr->typeTag->offset) {
1378 default:
1379 SECU_PrintAsHex(out, value, om, level + 1);
1380 break;
1381 case SEC_OID_PKCS9_CONTENT_TYPE:
1382 SECU_PrintObjectID(out, value, om, level + 1);
1383 break;
1384 case SEC_OID_PKCS9_SIGNING_TIME:
1385 SECU_PrintTimeChoice(out, value, om, level + 1);
1386 break;
1387 }
1388 }
1389 }
1390 }
1391 }
1392
1393 #ifndef NSS_DISABLE_ECC
1394 static void
secu_PrintECPublicKey(FILE * out,SECKEYPublicKey * pk,char * m,int level)1395 secu_PrintECPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level)
1396 {
1397 SECItem curveOID = { siBuffer, NULL, 0 };
1398
1399 SECU_Indent(out, level);
1400 fprintf(out, "%s:\n", m);
1401 SECU_PrintInteger(out, &pk->u.ec.publicValue, "PublicValue", level + 1);
1402 /* For named curves, the DEREncodedParams field contains an
1403 * ASN Object ID (0x06 is SEC_ASN1_OBJECT_ID).
1404 */
1405 if ((pk->u.ec.DEREncodedParams.len > 2) &&
1406 (pk->u.ec.DEREncodedParams.data[0] == 0x06)) {
1407 curveOID.len = pk->u.ec.DEREncodedParams.data[1];
1408 curveOID.data = pk->u.ec.DEREncodedParams.data + 2;
1409 SECU_PrintObjectID(out, &curveOID, "Curve", level + 1);
1410 }
1411 }
1412 #endif /* NSS_DISABLE_ECC */
1413
1414 void
SECU_PrintRSAPublicKey(FILE * out,SECKEYPublicKey * pk,char * m,int level)1415 SECU_PrintRSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level)
1416 {
1417 SECU_Indent(out, level);
1418 fprintf(out, "%s:\n", m);
1419 SECU_PrintInteger(out, &pk->u.rsa.modulus, "Modulus", level + 1);
1420 SECU_PrintInteger(out, &pk->u.rsa.publicExponent, "Exponent", level + 1);
1421 if (pk->u.rsa.publicExponent.len == 1 &&
1422 pk->u.rsa.publicExponent.data[0] == 1) {
1423 SECU_Indent(out, level + 1);
1424 fprintf(out, "Error: INVALID RSA KEY!\n");
1425 }
1426 }
1427
1428 void
SECU_PrintDSAPublicKey(FILE * out,SECKEYPublicKey * pk,char * m,int level)1429 SECU_PrintDSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level)
1430 {
1431 SECU_Indent(out, level);
1432 fprintf(out, "%s:\n", m);
1433 SECU_PrintInteger(out, &pk->u.dsa.params.prime, "Prime", level + 1);
1434 SECU_PrintInteger(out, &pk->u.dsa.params.subPrime, "Subprime", level + 1);
1435 SECU_PrintInteger(out, &pk->u.dsa.params.base, "Base", level + 1);
1436 SECU_PrintInteger(out, &pk->u.dsa.publicValue, "PublicValue", level + 1);
1437 }
1438
1439 static void
secu_PrintSubjectPublicKeyInfo(FILE * out,PLArenaPool * arena,CERTSubjectPublicKeyInfo * i,char * msg,int level)1440 secu_PrintSubjectPublicKeyInfo(FILE *out, PLArenaPool *arena,
1441 CERTSubjectPublicKeyInfo *i, char *msg, int level)
1442 {
1443 SECKEYPublicKey *pk;
1444
1445 SECU_Indent(out, level);
1446 fprintf(out, "%s:\n", msg);
1447 SECU_PrintAlgorithmID(out, &i->algorithm, "Public Key Algorithm", level + 1);
1448
1449 pk = SECKEY_ExtractPublicKey(i);
1450 if (pk) {
1451 switch (pk->keyType) {
1452 case rsaKey:
1453 SECU_PrintRSAPublicKey(out, pk, "RSA Public Key", level + 1);
1454 break;
1455
1456 case dsaKey:
1457 SECU_PrintDSAPublicKey(out, pk, "DSA Public Key", level + 1);
1458 break;
1459
1460 #ifndef NSS_DISABLE_ECC
1461 case ecKey:
1462 secu_PrintECPublicKey(out, pk, "EC Public Key", level + 1);
1463 break;
1464 #endif
1465
1466 case dhKey:
1467 case fortezzaKey:
1468 case keaKey:
1469 SECU_Indent(out, level);
1470 fprintf(out, "unable to format this SPKI algorithm type\n");
1471 goto loser;
1472 default:
1473 SECU_Indent(out, level);
1474 fprintf(out, "unknown SPKI algorithm type\n");
1475 goto loser;
1476 }
1477 PORT_FreeArena(pk->arena, PR_FALSE);
1478 } else {
1479 SECU_PrintErrMsg(out, level, "Error", "Parsing public key");
1480 loser:
1481 if (i->subjectPublicKey.data) {
1482 SECU_PrintAny(out, &i->subjectPublicKey, "Raw", level);
1483 }
1484 }
1485 }
1486
1487 static void
printStringWithoutCRLF(FILE * out,const char * str)1488 printStringWithoutCRLF(FILE *out, const char *str)
1489 {
1490 const char *c = str;
1491 while (*c) {
1492 if (*c != '\r' && *c != '\n') {
1493 fputc(*c, out);
1494 }
1495 ++c;
1496 }
1497 }
1498
1499 int
SECU_PrintDumpDerIssuerAndSerial(FILE * out,SECItem * der,char * m,int level)1500 SECU_PrintDumpDerIssuerAndSerial(FILE *out, SECItem *der, char *m,
1501 int level)
1502 {
1503 PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1504 CERTCertificate *c;
1505 int rv = SEC_ERROR_NO_MEMORY;
1506 char *derIssuerB64;
1507 char *derSerialB64;
1508
1509 if (!arena)
1510 return rv;
1511
1512 /* Decode certificate */
1513 c = PORT_ArenaZNew(arena, CERTCertificate);
1514 if (!c)
1515 goto loser;
1516 c->arena = arena;
1517 rv = SEC_ASN1DecodeItem(arena, c,
1518 SEC_ASN1_GET(CERT_CertificateTemplate), der);
1519 if (rv) {
1520 SECU_PrintErrMsg(out, 0, "Error", "Parsing extension");
1521 goto loser;
1522 }
1523
1524 SECU_PrintName(out, &c->subject, "Subject", 0);
1525 if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
1526 SECU_Newline(out);
1527 SECU_PrintName(out, &c->issuer, "Issuer", 0);
1528 if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
1529 SECU_Newline(out);
1530 SECU_PrintInteger(out, &c->serialNumber, "Serial Number", 0);
1531
1532 derIssuerB64 = BTOA_ConvertItemToAscii(&c->derIssuer);
1533 derSerialB64 = BTOA_ConvertItemToAscii(&c->serialNumber);
1534
1535 fprintf(out, "Issuer DER Base64:\n");
1536 if (SECU_GetWrapEnabled()) {
1537 fprintf(out, "%s\n", derIssuerB64);
1538 } else {
1539 printStringWithoutCRLF(out, derIssuerB64);
1540 fputs("\n", out);
1541 }
1542
1543 fprintf(out, "Serial DER Base64:\n");
1544 if (SECU_GetWrapEnabled()) {
1545 fprintf(out, "%s\n", derSerialB64);
1546 } else {
1547 printStringWithoutCRLF(out, derSerialB64);
1548 fputs("\n", out);
1549 }
1550
1551 PORT_Free(derIssuerB64);
1552 PORT_Free(derSerialB64);
1553
1554 fprintf(out, "Serial DER as C source: \n{ %d, \"", c->serialNumber.len);
1555
1556 {
1557 unsigned int i;
1558 for (i = 0; i < c->serialNumber.len; ++i) {
1559 unsigned char *chardata = (unsigned char *)(c->serialNumber.data);
1560 unsigned char c = *(chardata + i);
1561
1562 fprintf(out, "\\x%02x", c);
1563 }
1564 fprintf(out, "\" }\n");
1565 }
1566
1567 loser:
1568 PORT_FreeArena(arena, PR_FALSE);
1569 return rv;
1570 }
1571
1572 static SECStatus
secu_PrintX509InvalidDate(FILE * out,SECItem * value,char * msg,int level)1573 secu_PrintX509InvalidDate(FILE *out, SECItem *value, char *msg, int level)
1574 {
1575 SECItem decodedValue;
1576 SECStatus rv;
1577 PRTime invalidTime;
1578 char *formattedTime = NULL;
1579
1580 decodedValue.data = NULL;
1581 rv = SEC_ASN1DecodeItem(NULL, &decodedValue,
1582 SEC_ASN1_GET(SEC_GeneralizedTimeTemplate),
1583 value);
1584 if (rv == SECSuccess) {
1585 rv = DER_GeneralizedTimeToTime(&invalidTime, &decodedValue);
1586 if (rv == SECSuccess) {
1587 formattedTime = CERT_GenTime2FormattedAscii(invalidTime, "%a %b %d %H:%M:%S %Y");
1588 SECU_Indent(out, level + 1);
1589 fprintf(out, "%s: %s\n", msg, formattedTime);
1590 PORT_Free(formattedTime);
1591 }
1592 }
1593 PORT_Free(decodedValue.data);
1594 return (rv);
1595 }
1596
1597 static SECStatus
PrintExtKeyUsageExtension(FILE * out,SECItem * value,char * msg,int level)1598 PrintExtKeyUsageExtension(FILE *out, SECItem *value, char *msg, int level)
1599 {
1600 CERTOidSequence *os;
1601 SECItem **op;
1602
1603 os = CERT_DecodeOidSequence(value);
1604 if ((CERTOidSequence *)NULL == os) {
1605 return SECFailure;
1606 }
1607
1608 for (op = os->oids; *op; op++) {
1609 SECU_PrintObjectID(out, *op, msg, level + 1);
1610 }
1611 CERT_DestroyOidSequence(os);
1612 return SECSuccess;
1613 }
1614
1615 static SECStatus
secu_PrintBasicConstraints(FILE * out,SECItem * value,char * msg,int level)1616 secu_PrintBasicConstraints(FILE *out, SECItem *value, char *msg, int level)
1617 {
1618 CERTBasicConstraints constraints;
1619 SECStatus rv;
1620
1621 SECU_Indent(out, level);
1622 if (msg) {
1623 fprintf(out, "%s: ", msg);
1624 }
1625 rv = CERT_DecodeBasicConstraintValue(&constraints, value);
1626 if (rv == SECSuccess && constraints.isCA) {
1627 if (constraints.pathLenConstraint >= 0) {
1628 fprintf(out, "Is a CA with a maximum path length of %d.\n",
1629 constraints.pathLenConstraint);
1630 } else {
1631 fprintf(out, "Is a CA with no maximum path length.\n");
1632 }
1633 } else {
1634 fprintf(out, "Is not a CA.\n");
1635 }
1636 return SECSuccess;
1637 }
1638
1639 static const char *const nsTypeBits[] = {
1640 "SSL Client",
1641 "SSL Server",
1642 "S/MIME",
1643 "Object Signing",
1644 "Reserved",
1645 "SSL CA",
1646 "S/MIME CA",
1647 "ObjectSigning CA"
1648 };
1649
1650 /* NSCertType is merely a bit string whose bits are displayed symbolically */
1651 static SECStatus
secu_PrintNSCertType(FILE * out,SECItem * value,char * msg,int level)1652 secu_PrintNSCertType(FILE *out, SECItem *value, char *msg, int level)
1653 {
1654 int unused;
1655 int NS_Type;
1656 int i;
1657 int found = 0;
1658 SECItem my = *value;
1659
1660 if ((my.data[0] != SEC_ASN1_BIT_STRING) ||
1661 SECSuccess != SECU_StripTagAndLength(&my)) {
1662 SECU_PrintAny(out, value, "Data", level);
1663 return SECSuccess;
1664 }
1665
1666 unused = (my.len == 2) ? (my.data[0] & 0x0f) : 0;
1667 NS_Type = my.data[1] & (0xff << unused);
1668
1669 SECU_Indent(out, level);
1670 if (msg) {
1671 fprintf(out, "%s: ", msg);
1672 } else {
1673 fprintf(out, "Netscape Certificate Type: ");
1674 }
1675 for (i = 0; i < 8; i++) {
1676 if ((0x80 >> i) & NS_Type) {
1677 fprintf(out, "%c%s", (found ? ',' : '<'), nsTypeBits[i]);
1678 found = 1;
1679 }
1680 }
1681 fprintf(out, (found ? ">\n" : "none\n"));
1682 return SECSuccess;
1683 }
1684
1685 static const char *const usageBits[] = {
1686 "Digital Signature", /* 0x80 */
1687 "Non-Repudiation", /* 0x40 */
1688 "Key Encipherment", /* 0x20 */
1689 "Data Encipherment", /* 0x10 */
1690 "Key Agreement", /* 0x08 */
1691 "Certificate Signing", /* 0x04 */
1692 "CRL Signing", /* 0x02 */
1693 "Encipher Only", /* 0x01 */
1694 "Decipher Only", /* 0x0080 */
1695 NULL
1696 };
1697
1698 /* X509KeyUsage is merely a bit string whose bits are displayed symbolically */
1699 static void
secu_PrintX509KeyUsage(FILE * out,SECItem * value,char * msg,int level)1700 secu_PrintX509KeyUsage(FILE *out, SECItem *value, char *msg, int level)
1701 {
1702 int unused;
1703 int usage;
1704 int i;
1705 int found = 0;
1706 SECItem my = *value;
1707
1708 if ((my.data[0] != SEC_ASN1_BIT_STRING) ||
1709 SECSuccess != SECU_StripTagAndLength(&my)) {
1710 SECU_PrintAny(out, value, "Data", level);
1711 return;
1712 }
1713
1714 unused = (my.len >= 2) ? (my.data[0] & 0x0f) : 0;
1715 usage = (my.len == 2) ? (my.data[1] & (0xff << unused)) << 8
1716 : (my.data[1] << 8) |
1717 (my.data[2] & (0xff << unused));
1718
1719 SECU_Indent(out, level);
1720 fprintf(out, "Usages: ");
1721 for (i = 0; usageBits[i]; i++) {
1722 if ((0x8000 >> i) & usage) {
1723 if (found)
1724 SECU_Indent(out, level + 2);
1725 fprintf(out, "%s\n", usageBits[i]);
1726 found = 1;
1727 }
1728 }
1729 if (!found) {
1730 fprintf(out, "(none)\n");
1731 }
1732 }
1733
1734 static void
secu_PrintIPAddress(FILE * out,SECItem * value,char * msg,int level)1735 secu_PrintIPAddress(FILE *out, SECItem *value, char *msg, int level)
1736 {
1737 PRStatus st;
1738 PRNetAddr addr;
1739 char addrBuf[80];
1740
1741 memset(&addr, 0, sizeof addr);
1742 if (value->len == 4) {
1743 addr.inet.family = PR_AF_INET;
1744 memcpy(&addr.inet.ip, value->data, value->len);
1745 } else if (value->len == 16) {
1746 addr.ipv6.family = PR_AF_INET6;
1747 memcpy(addr.ipv6.ip.pr_s6_addr, value->data, value->len);
1748 if (PR_IsNetAddrType(&addr, PR_IpAddrV4Mapped)) {
1749 /* convert to IPv4. */
1750 addr.inet.family = PR_AF_INET;
1751 memcpy(&addr.inet.ip, &addr.ipv6.ip.pr_s6_addr[12], 4);
1752 memset(&addr.inet.pad[0], 0, sizeof addr.inet.pad);
1753 }
1754 } else {
1755 goto loser;
1756 }
1757
1758 st = PR_NetAddrToString(&addr, addrBuf, sizeof addrBuf);
1759 if (st == PR_SUCCESS) {
1760 SECU_Indent(out, level);
1761 fprintf(out, "%s: %s\n", msg, addrBuf);
1762 } else {
1763 loser:
1764 SECU_PrintAsHex(out, value, msg, level);
1765 }
1766 }
1767
1768 static void
secu_PrintGeneralName(FILE * out,CERTGeneralName * gname,char * msg,int level)1769 secu_PrintGeneralName(FILE *out, CERTGeneralName *gname, char *msg, int level)
1770 {
1771 char label[40];
1772 if (msg && msg[0]) {
1773 SECU_Indent(out, level++);
1774 fprintf(out, "%s: \n", msg);
1775 }
1776 switch (gname->type) {
1777 case certOtherName:
1778 SECU_PrintAny(out, &gname->name.OthName.name, "Other Name", level);
1779 SECU_PrintObjectID(out, &gname->name.OthName.oid, "OID", level + 1);
1780 break;
1781 case certDirectoryName:
1782 SECU_PrintName(out, &gname->name.directoryName, "Directory Name", level);
1783 break;
1784 case certRFC822Name:
1785 secu_PrintRawString(out, &gname->name.other, "RFC822 Name", level);
1786 break;
1787 case certDNSName:
1788 secu_PrintRawString(out, &gname->name.other, "DNS name", level);
1789 break;
1790 case certURI:
1791 secu_PrintRawString(out, &gname->name.other, "URI", level);
1792 break;
1793 case certIPAddress:
1794 secu_PrintIPAddress(out, &gname->name.other, "IP Address", level);
1795 break;
1796 case certRegisterID:
1797 SECU_PrintObjectID(out, &gname->name.other, "Registered ID", level);
1798 break;
1799 case certX400Address:
1800 SECU_PrintAny(out, &gname->name.other, "X400 Address", level);
1801 break;
1802 case certEDIPartyName:
1803 SECU_PrintAny(out, &gname->name.other, "EDI Party", level);
1804 break;
1805 default:
1806 PR_snprintf(label, sizeof label, "unknown type [%d]",
1807 (int)gname->type - 1);
1808 SECU_PrintAsHex(out, &gname->name.other, label, level);
1809 break;
1810 }
1811 }
1812
1813 static void
secu_PrintGeneralNames(FILE * out,CERTGeneralName * gname,char * msg,int level)1814 secu_PrintGeneralNames(FILE *out, CERTGeneralName *gname, char *msg, int level)
1815 {
1816 CERTGeneralName *name = gname;
1817 do {
1818 secu_PrintGeneralName(out, name, msg, level);
1819 name = CERT_GetNextGeneralName(name);
1820 } while (name && name != gname);
1821 }
1822
1823 static void
secu_PrintAuthKeyIDExtension(FILE * out,SECItem * value,char * msg,int level)1824 secu_PrintAuthKeyIDExtension(FILE *out, SECItem *value, char *msg, int level)
1825 {
1826 CERTAuthKeyID *kid = NULL;
1827 PLArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1828
1829 if (!pool) {
1830 SECU_PrintError("Error", "Allocating new ArenaPool");
1831 return;
1832 }
1833 kid = CERT_DecodeAuthKeyID(pool, value);
1834 if (!kid) {
1835 SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
1836 SECU_PrintAny(out, value, "Data", level);
1837 } else {
1838 int keyIDPresent = (kid->keyID.data && kid->keyID.len);
1839 int issuerPresent = kid->authCertIssuer != NULL;
1840 int snPresent = (kid->authCertSerialNumber.data &&
1841 kid->authCertSerialNumber.len);
1842
1843 if (keyIDPresent)
1844 SECU_PrintAsHex(out, &kid->keyID, "Key ID", level);
1845 if (issuerPresent)
1846 secu_PrintGeneralName(out, kid->authCertIssuer, "Issuer", level);
1847 if (snPresent)
1848 SECU_PrintInteger(out, &kid->authCertSerialNumber,
1849 "Serial Number", level);
1850 }
1851 PORT_FreeArena(pool, PR_FALSE);
1852 }
1853
1854 static void
secu_PrintAltNameExtension(FILE * out,SECItem * value,char * msg,int level)1855 secu_PrintAltNameExtension(FILE *out, SECItem *value, char *msg, int level)
1856 {
1857 CERTGeneralName *nameList;
1858 CERTGeneralName *current;
1859 PLArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1860
1861 if (!pool) {
1862 SECU_PrintError("Error", "Allocating new ArenaPool");
1863 return;
1864 }
1865 nameList = current = CERT_DecodeAltNameExtension(pool, value);
1866 if (!current) {
1867 if (PORT_GetError() == SEC_ERROR_EXTENSION_NOT_FOUND) {
1868 /* Decoder found empty sequence, which is invalid. */
1869 PORT_SetError(SEC_ERROR_EXTENSION_VALUE_INVALID);
1870 }
1871 SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
1872 SECU_PrintAny(out, value, "Data", level);
1873 } else {
1874 do {
1875 secu_PrintGeneralName(out, current, msg, level);
1876 current = CERT_GetNextGeneralName(current);
1877 } while (current != nameList);
1878 }
1879 PORT_FreeArena(pool, PR_FALSE);
1880 }
1881
1882 static void
secu_PrintCRLDistPtsExtension(FILE * out,SECItem * value,char * msg,int level)1883 secu_PrintCRLDistPtsExtension(FILE *out, SECItem *value, char *msg, int level)
1884 {
1885 CERTCrlDistributionPoints *dPoints;
1886 PLArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1887
1888 if (!pool) {
1889 SECU_PrintError("Error", "Allocating new ArenaPool");
1890 return;
1891 }
1892 dPoints = CERT_DecodeCRLDistributionPoints(pool, value);
1893 if (dPoints && dPoints->distPoints && dPoints->distPoints[0]) {
1894 CRLDistributionPoint **pPoints = dPoints->distPoints;
1895 CRLDistributionPoint *pPoint;
1896 while (NULL != (pPoint = *pPoints++)) {
1897 SECU_Indent(out, level);
1898 fputs("Distribution point:\n", out);
1899 if (pPoint->distPointType == generalName &&
1900 pPoint->distPoint.fullName != NULL) {
1901 secu_PrintGeneralNames(out, pPoint->distPoint.fullName, NULL,
1902 level + 1);
1903 } else if (pPoint->distPointType == relativeDistinguishedName &&
1904 pPoint->distPoint.relativeName.avas) {
1905 SECU_PrintRDN(out, &pPoint->distPoint.relativeName, "RDN",
1906 level + 1);
1907 } else if (pPoint->derDistPoint.data) {
1908 SECU_PrintAny(out, &pPoint->derDistPoint, "Point", level + 1);
1909 }
1910 if (pPoint->reasons.data) {
1911 secu_PrintDecodedBitString(out, &pPoint->reasons, "Reasons",
1912 level + 1);
1913 }
1914 if (pPoint->crlIssuer) {
1915 secu_PrintGeneralName(out, pPoint->crlIssuer, "CRL issuer",
1916 level + 1);
1917 }
1918 }
1919 } else {
1920 SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
1921 SECU_PrintAny(out, value, "Data", level);
1922 }
1923 PORT_FreeArena(pool, PR_FALSE);
1924 }
1925
1926 static void
secu_PrintNameConstraintSubtree(FILE * out,CERTNameConstraint * value,char * msg,int level)1927 secu_PrintNameConstraintSubtree(FILE *out, CERTNameConstraint *value,
1928 char *msg, int level)
1929 {
1930 CERTNameConstraint *head = value;
1931 SECU_Indent(out, level);
1932 fprintf(out, "%s Subtree:\n", msg);
1933 level++;
1934 do {
1935 secu_PrintGeneralName(out, &value->name, NULL, level);
1936 if (value->min.data)
1937 SECU_PrintInteger(out, &value->min, "Minimum", level + 1);
1938 if (value->max.data)
1939 SECU_PrintInteger(out, &value->max, "Maximum", level + 1);
1940 value = CERT_GetNextNameConstraint(value);
1941 } while (value != head);
1942 }
1943
1944 static void
secu_PrintNameConstraintsExtension(FILE * out,SECItem * value,char * msg,int level)1945 secu_PrintNameConstraintsExtension(FILE *out, SECItem *value, char *msg, int level)
1946 {
1947 CERTNameConstraints *cnstrnts;
1948 PLArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1949
1950 if (!pool) {
1951 SECU_PrintError("Error", "Allocating new ArenaPool");
1952 return;
1953 }
1954 cnstrnts = CERT_DecodeNameConstraintsExtension(pool, value);
1955 if (!cnstrnts) {
1956 SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
1957 SECU_PrintAny(out, value, "Raw", level);
1958 } else {
1959 if (cnstrnts->permited)
1960 secu_PrintNameConstraintSubtree(out, cnstrnts->permited,
1961 "Permitted", level);
1962 if (cnstrnts->excluded)
1963 secu_PrintNameConstraintSubtree(out, cnstrnts->excluded,
1964 "Excluded", level);
1965 }
1966 PORT_FreeArena(pool, PR_FALSE);
1967 }
1968
1969 static void
secu_PrintAuthorityInfoAcess(FILE * out,SECItem * value,char * msg,int level)1970 secu_PrintAuthorityInfoAcess(FILE *out, SECItem *value, char *msg, int level)
1971 {
1972 CERTAuthInfoAccess **infos = NULL;
1973 PLArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1974
1975 if (!pool) {
1976 SECU_PrintError("Error", "Allocating new ArenaPool");
1977 return;
1978 }
1979 infos = CERT_DecodeAuthInfoAccessExtension(pool, value);
1980 if (!infos) {
1981 SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
1982 SECU_PrintAny(out, value, "Raw", level);
1983 } else {
1984 CERTAuthInfoAccess *info;
1985 while (NULL != (info = *infos++)) {
1986 if (info->method.data) {
1987 SECU_PrintObjectID(out, &info->method, "Method", level);
1988 } else {
1989 SECU_Indent(out, level);
1990 fprintf(out, "Error: missing method\n");
1991 }
1992 if (info->location) {
1993 secu_PrintGeneralName(out, info->location, "Location", level);
1994 } else {
1995 SECU_PrintAny(out, &info->derLocation, "Location", level);
1996 }
1997 }
1998 }
1999 PORT_FreeArena(pool, PR_FALSE);
2000 }
2001
2002 void
SECU_PrintExtensions(FILE * out,CERTCertExtension ** extensions,char * msg,int level)2003 SECU_PrintExtensions(FILE *out, CERTCertExtension **extensions,
2004 char *msg, int level)
2005 {
2006 SECOidTag oidTag;
2007
2008 if (extensions) {
2009 if (msg && *msg) {
2010 SECU_Indent(out, level++);
2011 fprintf(out, "%s:\n", msg);
2012 }
2013
2014 while (*extensions) {
2015 SECItem *tmpitem;
2016
2017 tmpitem = &(*extensions)->id;
2018 SECU_PrintObjectID(out, tmpitem, "Name", level);
2019
2020 tmpitem = &(*extensions)->critical;
2021 if (tmpitem->len) {
2022 secu_PrintBoolean(out, tmpitem, "Critical", level);
2023 }
2024
2025 oidTag = SECOID_FindOIDTag(&((*extensions)->id));
2026 tmpitem = &((*extensions)->value);
2027
2028 switch (oidTag) {
2029 case SEC_OID_X509_INVALID_DATE:
2030 case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_TIME:
2031 secu_PrintX509InvalidDate(out, tmpitem, "Date", level);
2032 break;
2033 case SEC_OID_X509_CERTIFICATE_POLICIES:
2034 SECU_PrintPolicy(out, tmpitem, "Data", level);
2035 break;
2036 case SEC_OID_NS_CERT_EXT_BASE_URL:
2037 case SEC_OID_NS_CERT_EXT_REVOCATION_URL:
2038 case SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL:
2039 case SEC_OID_NS_CERT_EXT_CA_CRL_URL:
2040 case SEC_OID_NS_CERT_EXT_CA_CERT_URL:
2041 case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL:
2042 case SEC_OID_NS_CERT_EXT_CA_POLICY_URL:
2043 case SEC_OID_NS_CERT_EXT_HOMEPAGE_URL:
2044 case SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL:
2045 case SEC_OID_OCSP_RESPONDER:
2046 SECU_PrintString(out, tmpitem, "URL", level);
2047 break;
2048 case SEC_OID_NS_CERT_EXT_COMMENT:
2049 SECU_PrintString(out, tmpitem, "Comment", level);
2050 break;
2051 case SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME:
2052 SECU_PrintString(out, tmpitem, "ServerName", level);
2053 break;
2054 case SEC_OID_NS_CERT_EXT_CERT_TYPE:
2055 secu_PrintNSCertType(out, tmpitem, "Data", level);
2056 break;
2057 case SEC_OID_X509_BASIC_CONSTRAINTS:
2058 secu_PrintBasicConstraints(out, tmpitem, "Data", level);
2059 break;
2060 case SEC_OID_X509_EXT_KEY_USAGE:
2061 PrintExtKeyUsageExtension(out, tmpitem, NULL, level);
2062 break;
2063 case SEC_OID_X509_KEY_USAGE:
2064 secu_PrintX509KeyUsage(out, tmpitem, NULL, level);
2065 break;
2066 case SEC_OID_X509_AUTH_KEY_ID:
2067 secu_PrintAuthKeyIDExtension(out, tmpitem, NULL, level);
2068 break;
2069 case SEC_OID_X509_SUBJECT_ALT_NAME:
2070 case SEC_OID_X509_ISSUER_ALT_NAME:
2071 secu_PrintAltNameExtension(out, tmpitem, NULL, level);
2072 break;
2073 case SEC_OID_X509_CRL_DIST_POINTS:
2074 secu_PrintCRLDistPtsExtension(out, tmpitem, NULL, level);
2075 break;
2076 case SEC_OID_X509_PRIVATE_KEY_USAGE_PERIOD:
2077 SECU_PrintPrivKeyUsagePeriodExtension(out, tmpitem, NULL,
2078 level);
2079 break;
2080 case SEC_OID_X509_NAME_CONSTRAINTS:
2081 secu_PrintNameConstraintsExtension(out, tmpitem, NULL, level);
2082 break;
2083 case SEC_OID_X509_AUTH_INFO_ACCESS:
2084 secu_PrintAuthorityInfoAcess(out, tmpitem, NULL, level);
2085 break;
2086
2087 case SEC_OID_X509_CRL_NUMBER:
2088 case SEC_OID_X509_REASON_CODE:
2089
2090 /* PKIX OIDs */
2091 case SEC_OID_PKIX_OCSP:
2092 case SEC_OID_PKIX_OCSP_BASIC_RESPONSE:
2093 case SEC_OID_PKIX_OCSP_NONCE:
2094 case SEC_OID_PKIX_OCSP_CRL:
2095 case SEC_OID_PKIX_OCSP_RESPONSE:
2096 case SEC_OID_PKIX_OCSP_NO_CHECK:
2097 case SEC_OID_PKIX_OCSP_ARCHIVE_CUTOFF:
2098 case SEC_OID_PKIX_OCSP_SERVICE_LOCATOR:
2099 case SEC_OID_PKIX_REGCTRL_REGTOKEN:
2100 case SEC_OID_PKIX_REGCTRL_AUTHENTICATOR:
2101 case SEC_OID_PKIX_REGCTRL_PKIPUBINFO:
2102 case SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS:
2103 case SEC_OID_PKIX_REGCTRL_OLD_CERT_ID:
2104 case SEC_OID_PKIX_REGCTRL_PROTOCOL_ENC_KEY:
2105 case SEC_OID_PKIX_REGINFO_UTF8_PAIRS:
2106 case SEC_OID_PKIX_REGINFO_CERT_REQUEST:
2107
2108 /* Netscape extension OIDs. */
2109 case SEC_OID_NS_CERT_EXT_NETSCAPE_OK:
2110 case SEC_OID_NS_CERT_EXT_ISSUER_LOGO:
2111 case SEC_OID_NS_CERT_EXT_SUBJECT_LOGO:
2112 case SEC_OID_NS_CERT_EXT_ENTITY_LOGO:
2113 case SEC_OID_NS_CERT_EXT_USER_PICTURE:
2114
2115 /* x.509 v3 Extensions */
2116 case SEC_OID_X509_SUBJECT_DIRECTORY_ATTR:
2117 case SEC_OID_X509_SUBJECT_KEY_ID:
2118 case SEC_OID_X509_POLICY_MAPPINGS:
2119 case SEC_OID_X509_POLICY_CONSTRAINTS:
2120
2121 default:
2122 SECU_PrintAny(out, tmpitem, "Data", level);
2123 break;
2124 }
2125
2126 SECU_Newline(out);
2127 extensions++;
2128 }
2129 }
2130 }
2131
2132 /* An RDN is a subset of a DirectoryName, and we already know how to
2133 * print those, so make a directory name out of the RDN, and print it.
2134 */
2135 void
SECU_PrintRDN(FILE * out,CERTRDN * rdn,const char * msg,int level)2136 SECU_PrintRDN(FILE *out, CERTRDN *rdn, const char *msg, int level)
2137 {
2138 CERTName name;
2139 CERTRDN *rdns[2];
2140
2141 name.arena = NULL;
2142 name.rdns = rdns;
2143 rdns[0] = rdn;
2144 rdns[1] = NULL;
2145 SECU_PrintName(out, &name, msg, level);
2146 }
2147
2148 void
SECU_PrintNameQuotesOptional(FILE * out,CERTName * name,const char * msg,int level,PRBool quotes)2149 SECU_PrintNameQuotesOptional(FILE *out, CERTName *name, const char *msg,
2150 int level, PRBool quotes)
2151 {
2152 char *nameStr = NULL;
2153 char *str;
2154 SECItem my;
2155
2156 if (!name) {
2157 PORT_SetError(SEC_ERROR_INVALID_ARGS);
2158 return;
2159 }
2160 if (!name->rdns || !name->rdns[0]) {
2161 str = "(empty)";
2162 } else {
2163 str = nameStr = CERT_NameToAscii(name);
2164 }
2165 if (!str) {
2166 str = "!Invalid AVA!";
2167 }
2168 my.data = (unsigned char *)str;
2169 my.len = PORT_Strlen(str);
2170 #if 1
2171 secu_PrintRawStringQuotesOptional(out, &my, msg, level, quotes);
2172 #else
2173 SECU_Indent(out, level);
2174 fprintf(out, "%s: ", msg);
2175 fprintf(out, str);
2176 SECU_Newline(out);
2177 #endif
2178 PORT_Free(nameStr);
2179 }
2180
2181 void
SECU_PrintName(FILE * out,CERTName * name,const char * msg,int level)2182 SECU_PrintName(FILE *out, CERTName *name, const char *msg, int level)
2183 {
2184 SECU_PrintNameQuotesOptional(out, name, msg, level, PR_TRUE);
2185 }
2186
2187 void
printflags(char * trusts,unsigned int flags)2188 printflags(char *trusts, unsigned int flags)
2189 {
2190 if (flags & CERTDB_VALID_CA)
2191 if (!(flags & CERTDB_TRUSTED_CA) &&
2192 !(flags & CERTDB_TRUSTED_CLIENT_CA))
2193 PORT_Strcat(trusts, "c");
2194 if (flags & CERTDB_TERMINAL_RECORD)
2195 if (!(flags & CERTDB_TRUSTED))
2196 PORT_Strcat(trusts, "p");
2197 if (flags & CERTDB_TRUSTED_CA)
2198 PORT_Strcat(trusts, "C");
2199 if (flags & CERTDB_TRUSTED_CLIENT_CA)
2200 PORT_Strcat(trusts, "T");
2201 if (flags & CERTDB_TRUSTED)
2202 PORT_Strcat(trusts, "P");
2203 if (flags & CERTDB_USER)
2204 PORT_Strcat(trusts, "u");
2205 if (flags & CERTDB_SEND_WARN)
2206 PORT_Strcat(trusts, "w");
2207 if (flags & CERTDB_INVISIBLE_CA)
2208 PORT_Strcat(trusts, "I");
2209 if (flags & CERTDB_GOVT_APPROVED_CA)
2210 PORT_Strcat(trusts, "G");
2211 return;
2212 }
2213
2214 /* callback for listing certs through pkcs11 */
2215 SECStatus
SECU_PrintCertNickname(CERTCertListNode * node,void * data)2216 SECU_PrintCertNickname(CERTCertListNode *node, void *data)
2217 {
2218 CERTCertTrust trust;
2219 CERTCertificate *cert;
2220 FILE *out;
2221 char trusts[30];
2222 char *name;
2223
2224 cert = node->cert;
2225
2226 PORT_Memset(trusts, 0, sizeof(trusts));
2227 out = (FILE *)data;
2228
2229 name = node->appData;
2230 if (!name || !name[0]) {
2231 name = cert->nickname;
2232 }
2233 if (!name || !name[0]) {
2234 name = cert->emailAddr;
2235 }
2236 if (!name || !name[0]) {
2237 name = "(NULL)";
2238 }
2239
2240 if (CERT_GetCertTrust(cert, &trust) == SECSuccess) {
2241 printflags(trusts, trust.sslFlags);
2242 PORT_Strcat(trusts, ",");
2243 printflags(trusts, trust.emailFlags);
2244 PORT_Strcat(trusts, ",");
2245 printflags(trusts, trust.objectSigningFlags);
2246 } else {
2247 PORT_Memcpy(trusts, ",,", 3);
2248 }
2249 fprintf(out, "%-60s %-5s\n", name, trusts);
2250
2251 return (SECSuccess);
2252 }
2253
2254 int
SECU_DecodeAndPrintExtensions(FILE * out,SECItem * any,char * m,int level)2255 SECU_DecodeAndPrintExtensions(FILE *out, SECItem *any, char *m, int level)
2256 {
2257 CERTCertExtension **extensions = NULL;
2258 PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2259 int rv = 0;
2260
2261 if (!arena)
2262 return SEC_ERROR_NO_MEMORY;
2263
2264 rv = SEC_QuickDERDecodeItem(arena, &extensions,
2265 SEC_ASN1_GET(CERT_SequenceOfCertExtensionTemplate), any);
2266 if (!rv)
2267 SECU_PrintExtensions(out, extensions, m, level);
2268 else
2269 SECU_PrintAny(out, any, m, level);
2270 PORT_FreeArena(arena, PR_FALSE);
2271 return rv;
2272 }
2273
2274 /* print a decoded SET OF or SEQUENCE OF Extensions */
2275 int
SECU_PrintSetOfExtensions(FILE * out,SECItem ** any,char * m,int level)2276 SECU_PrintSetOfExtensions(FILE *out, SECItem **any, char *m, int level)
2277 {
2278 int rv = 0;
2279 if (m && *m) {
2280 SECU_Indent(out, level++);
2281 fprintf(out, "%s:\n", m);
2282 }
2283 while (any && any[0]) {
2284 rv |= SECU_DecodeAndPrintExtensions(out, any[0], "", level);
2285 any++;
2286 }
2287 return rv;
2288 }
2289
2290 /* print a decoded SET OF or SEQUENCE OF "ANY" */
2291 int
SECU_PrintSetOfAny(FILE * out,SECItem ** any,char * m,int level)2292 SECU_PrintSetOfAny(FILE *out, SECItem **any, char *m, int level)
2293 {
2294 int rv = 0;
2295 if (m && *m) {
2296 SECU_Indent(out, level++);
2297 fprintf(out, "%s:\n", m);
2298 }
2299 while (any && any[0]) {
2300 SECU_PrintAny(out, any[0], "", level);
2301 any++;
2302 }
2303 return rv;
2304 }
2305
2306 int
SECU_PrintCertAttribute(FILE * out,CERTAttribute * attr,char * m,int level)2307 SECU_PrintCertAttribute(FILE *out, CERTAttribute *attr, char *m, int level)
2308 {
2309 int rv = 0;
2310 SECOidTag tag;
2311 tag = SECU_PrintObjectID(out, &attr->attrType, "Attribute Type", level);
2312 if (tag == SEC_OID_PKCS9_EXTENSION_REQUEST) {
2313 rv = SECU_PrintSetOfExtensions(out, attr->attrValue, "Extensions", level);
2314 } else {
2315 rv = SECU_PrintSetOfAny(out, attr->attrValue, "Attribute Values", level);
2316 }
2317 return rv;
2318 }
2319
2320 int
SECU_PrintCertAttributes(FILE * out,CERTAttribute ** attrs,char * m,int level)2321 SECU_PrintCertAttributes(FILE *out, CERTAttribute **attrs, char *m, int level)
2322 {
2323 int rv = 0;
2324 while (attrs[0]) {
2325 rv |= SECU_PrintCertAttribute(out, attrs[0], m, level + 1);
2326 attrs++;
2327 }
2328 return rv;
2329 }
2330
2331 int /* sometimes a PRErrorCode, other times a SECStatus. Sigh. */
SECU_PrintCertificateRequest(FILE * out,SECItem * der,char * m,int level)2332 SECU_PrintCertificateRequest(FILE *out, SECItem *der, char *m, int level)
2333 {
2334 PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2335 CERTCertificateRequest *cr;
2336 int rv = SEC_ERROR_NO_MEMORY;
2337
2338 if (!arena)
2339 return rv;
2340
2341 /* Decode certificate request */
2342 cr = PORT_ArenaZNew(arena, CERTCertificateRequest);
2343 if (!cr)
2344 goto loser;
2345 cr->arena = arena;
2346 rv = SEC_QuickDERDecodeItem(arena, cr,
2347 SEC_ASN1_GET(CERT_CertificateRequestTemplate), der);
2348 if (rv)
2349 goto loser;
2350
2351 /* Pretty print it out */
2352 SECU_Indent(out, level);
2353 fprintf(out, "%s:\n", m);
2354 SECU_PrintInteger(out, &cr->version, "Version", level + 1);
2355 SECU_PrintName(out, &cr->subject, "Subject", level + 1);
2356 if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
2357 SECU_Newline(out);
2358 secu_PrintSubjectPublicKeyInfo(out, arena, &cr->subjectPublicKeyInfo,
2359 "Subject Public Key Info", level + 1);
2360 if (cr->attributes)
2361 SECU_PrintCertAttributes(out, cr->attributes, "Attributes", level + 1);
2362 rv = 0;
2363 loser:
2364 PORT_FreeArena(arena, PR_FALSE);
2365 return rv;
2366 }
2367
2368 int
SECU_PrintCertificate(FILE * out,const SECItem * der,const char * m,int level)2369 SECU_PrintCertificate(FILE *out, const SECItem *der, const char *m, int level)
2370 {
2371 PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2372 CERTCertificate *c;
2373 int rv = SEC_ERROR_NO_MEMORY;
2374 int iv;
2375
2376 if (!arena)
2377 return rv;
2378
2379 /* Decode certificate */
2380 c = PORT_ArenaZNew(arena, CERTCertificate);
2381 if (!c)
2382 goto loser;
2383 c->arena = arena;
2384 rv = SEC_ASN1DecodeItem(arena, c,
2385 SEC_ASN1_GET(CERT_CertificateTemplate), der);
2386 if (rv) {
2387 SECU_Indent(out, level);
2388 SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
2389 SECU_PrintAny(out, der, "Raw", level);
2390 goto loser;
2391 }
2392 /* Pretty print it out */
2393 SECU_Indent(out, level);
2394 fprintf(out, "%s:\n", m);
2395 iv = c->version.len ? DER_GetInteger(&c->version) : 0; /* version is optional */
2396 SECU_Indent(out, level + 1);
2397 fprintf(out, "%s: %d (0x%x)\n", "Version", iv + 1, iv);
2398
2399 SECU_PrintInteger(out, &c->serialNumber, "Serial Number", level + 1);
2400 SECU_PrintAlgorithmID(out, &c->signature, "Signature Algorithm", level + 1);
2401 SECU_PrintName(out, &c->issuer, "Issuer", level + 1);
2402 if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
2403 SECU_Newline(out);
2404 secu_PrintValidity(out, &c->validity, "Validity", level + 1);
2405 SECU_PrintName(out, &c->subject, "Subject", level + 1);
2406 if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
2407 SECU_Newline(out);
2408 secu_PrintSubjectPublicKeyInfo(out, arena, &c->subjectPublicKeyInfo,
2409 "Subject Public Key Info", level + 1);
2410 if (c->issuerID.data)
2411 secu_PrintDecodedBitString(out, &c->issuerID, "Issuer Unique ID", level + 1);
2412 if (c->subjectID.data)
2413 secu_PrintDecodedBitString(out, &c->subjectID, "Subject Unique ID", level + 1);
2414 SECU_PrintExtensions(out, c->extensions, "Signed Extensions", level + 1);
2415 loser:
2416 PORT_FreeArena(arena, PR_FALSE);
2417 return rv;
2418 }
2419
2420 int
SECU_PrintCertificateBasicInfo(FILE * out,const SECItem * der,const char * m,int level)2421 SECU_PrintCertificateBasicInfo(FILE *out, const SECItem *der, const char *m, int level)
2422 {
2423 PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2424 CERTCertificate *c;
2425 int rv = SEC_ERROR_NO_MEMORY;
2426
2427 if (!arena)
2428 return rv;
2429
2430 /* Decode certificate */
2431 c = PORT_ArenaZNew(arena, CERTCertificate);
2432 if (!c)
2433 goto loser;
2434 c->arena = arena;
2435 rv = SEC_ASN1DecodeItem(arena, c,
2436 SEC_ASN1_GET(CERT_CertificateTemplate), der);
2437 if (rv) {
2438 SECU_Indent(out, level);
2439 SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
2440 SECU_PrintAny(out, der, "Raw", level);
2441 goto loser;
2442 }
2443 /* Pretty print it out */
2444 SECU_Indent(out, level);
2445 fprintf(out, "%s:\n", m);
2446 SECU_PrintInteger(out, &c->serialNumber, "Serial Number", level + 1);
2447 SECU_PrintAlgorithmID(out, &c->signature, "Signature Algorithm", level + 1);
2448 SECU_PrintName(out, &c->issuer, "Issuer", level + 1);
2449 if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
2450 SECU_Newline(out);
2451 secu_PrintValidity(out, &c->validity, "Validity", level + 1);
2452 SECU_PrintName(out, &c->subject, "Subject", level + 1);
2453 if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
2454 SECU_Newline(out);
2455 loser:
2456 PORT_FreeArena(arena, PR_FALSE);
2457 return rv;
2458 }
2459
2460 int
SECU_PrintSubjectPublicKeyInfo(FILE * out,SECItem * der,char * m,int level)2461 SECU_PrintSubjectPublicKeyInfo(FILE *out, SECItem *der, char *m, int level)
2462 {
2463 PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2464 int rv = SEC_ERROR_NO_MEMORY;
2465 CERTSubjectPublicKeyInfo spki;
2466
2467 if (!arena)
2468 return rv;
2469
2470 PORT_Memset(&spki, 0, sizeof spki);
2471 rv = SEC_ASN1DecodeItem(arena, &spki,
2472 SEC_ASN1_GET(CERT_SubjectPublicKeyInfoTemplate),
2473 der);
2474 if (!rv) {
2475 if (m && *m) {
2476 SECU_Indent(out, level);
2477 fprintf(out, "%s:\n", m);
2478 }
2479 secu_PrintSubjectPublicKeyInfo(out, arena, &spki,
2480 "Subject Public Key Info", level + 1);
2481 }
2482
2483 PORT_FreeArena(arena, PR_FALSE);
2484 return rv;
2485 }
2486
2487 #ifdef HAVE_EPV_TEMPLATE
2488 int
SECU_PrintPrivateKey(FILE * out,SECItem * der,char * m,int level)2489 SECU_PrintPrivateKey(FILE *out, SECItem *der, char *m, int level)
2490 {
2491 PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2492 SECKEYEncryptedPrivateKeyInfo key;
2493 int rv = SEC_ERROR_NO_MEMORY;
2494
2495 if (!arena)
2496 return rv;
2497
2498 PORT_Memset(&key, 0, sizeof(key));
2499 rv = SEC_ASN1DecodeItem(arena, &key,
2500 SEC_ASN1_GET(SECKEY_EncryptedPrivateKeyInfoTemplate), der);
2501 if (rv)
2502 goto loser;
2503
2504 /* Pretty print it out */
2505 SECU_Indent(out, level);
2506 fprintf(out, "%s:\n", m);
2507 SECU_PrintAlgorithmID(out, &key.algorithm, "Encryption Algorithm",
2508 level + 1);
2509 SECU_PrintAsHex(out, &key.encryptedData, "Encrypted Data", level + 1);
2510 loser:
2511 PORT_FreeArena(arena, PR_TRUE);
2512 return rv;
2513 }
2514 #endif
2515
2516 int
SECU_PrintFingerprints(FILE * out,SECItem * derCert,char * m,int level)2517 SECU_PrintFingerprints(FILE *out, SECItem *derCert, char *m, int level)
2518 {
2519 unsigned char fingerprint[SHA256_LENGTH];
2520 char *fpStr = NULL;
2521 int err = PORT_GetError();
2522 SECStatus rv;
2523 SECItem fpItem;
2524
2525 /* Print SHA-256 fingerprint */
2526 memset(fingerprint, 0, sizeof fingerprint);
2527 rv = PK11_HashBuf(SEC_OID_SHA256, fingerprint, derCert->data, derCert->len);
2528 fpItem.data = fingerprint;
2529 fpItem.len = SHA256_LENGTH;
2530 fpStr = CERT_Hexify(&fpItem, 1);
2531 SECU_Indent(out, level);
2532 fprintf(out, "%s (SHA-256):", m);
2533 if (SECU_GetWrapEnabled()) {
2534 fprintf(out, "\n");
2535 SECU_Indent(out, level + 1);
2536 } else {
2537 fprintf(out, " ");
2538 }
2539 fprintf(out, "%s\n", fpStr);
2540 PORT_Free(fpStr);
2541 fpStr = NULL;
2542 if (rv != SECSuccess && !err)
2543 err = PORT_GetError();
2544
2545 /* print SHA1 fingerprint */
2546 memset(fingerprint, 0, sizeof fingerprint);
2547 rv = PK11_HashBuf(SEC_OID_SHA1, fingerprint, derCert->data, derCert->len);
2548 fpItem.data = fingerprint;
2549 fpItem.len = SHA1_LENGTH;
2550 fpStr = CERT_Hexify(&fpItem, 1);
2551 SECU_Indent(out, level);
2552 fprintf(out, "%s (SHA1):", m);
2553 if (SECU_GetWrapEnabled()) {
2554 fprintf(out, "\n");
2555 SECU_Indent(out, level + 1);
2556 } else {
2557 fprintf(out, " ");
2558 }
2559 fprintf(out, "%s\n", fpStr);
2560 PORT_Free(fpStr);
2561 if (SECU_GetWrapEnabled())
2562 fprintf(out, "\n");
2563
2564 if (err)
2565 PORT_SetError(err);
2566 if (err || rv != SECSuccess)
2567 return SECFailure;
2568
2569 return 0;
2570 }
2571
2572 /*
2573 ** PKCS7 Support
2574 */
2575
2576 /* forward declaration */
2577 static int
2578 secu_PrintPKCS7ContentInfo(FILE *, SEC_PKCS7ContentInfo *, char *, int);
2579
2580 /*
2581 ** secu_PrintPKCS7EncContent
2582 ** Prints a SEC_PKCS7EncryptedContentInfo (without decrypting it)
2583 */
2584 static void
secu_PrintPKCS7EncContent(FILE * out,SEC_PKCS7EncryptedContentInfo * src,char * m,int level)2585 secu_PrintPKCS7EncContent(FILE *out, SEC_PKCS7EncryptedContentInfo *src,
2586 char *m, int level)
2587 {
2588 if (src->contentTypeTag == NULL)
2589 src->contentTypeTag = SECOID_FindOID(&(src->contentType));
2590
2591 SECU_Indent(out, level);
2592 fprintf(out, "%s:\n", m);
2593 SECU_Indent(out, level + 1);
2594 fprintf(out, "Content Type: %s\n",
2595 (src->contentTypeTag != NULL) ? src->contentTypeTag->desc
2596 : "Unknown");
2597 SECU_PrintAlgorithmID(out, &(src->contentEncAlg),
2598 "Content Encryption Algorithm", level + 1);
2599 SECU_PrintAsHex(out, &(src->encContent),
2600 "Encrypted Content", level + 1);
2601 }
2602
2603 /*
2604 ** secu_PrintRecipientInfo
2605 ** Prints a PKCS7RecipientInfo type
2606 */
2607 static void
secu_PrintRecipientInfo(FILE * out,SEC_PKCS7RecipientInfo * info,char * m,int level)2608 secu_PrintRecipientInfo(FILE *out, SEC_PKCS7RecipientInfo *info, char *m,
2609 int level)
2610 {
2611 SECU_Indent(out, level);
2612 fprintf(out, "%s:\n", m);
2613 SECU_PrintInteger(out, &(info->version), "Version", level + 1);
2614
2615 SECU_PrintName(out, &(info->issuerAndSN->issuer), "Issuer",
2616 level + 1);
2617 SECU_PrintInteger(out, &(info->issuerAndSN->serialNumber),
2618 "Serial Number", level + 1);
2619
2620 /* Parse and display encrypted key */
2621 SECU_PrintAlgorithmID(out, &(info->keyEncAlg),
2622 "Key Encryption Algorithm", level + 1);
2623 SECU_PrintAsHex(out, &(info->encKey), "Encrypted Key", level + 1);
2624 }
2625
2626 /*
2627 ** secu_PrintSignerInfo
2628 ** Prints a PKCS7SingerInfo type
2629 */
2630 static void
secu_PrintSignerInfo(FILE * out,SEC_PKCS7SignerInfo * info,char * m,int level)2631 secu_PrintSignerInfo(FILE *out, SEC_PKCS7SignerInfo *info, char *m, int level)
2632 {
2633 SEC_PKCS7Attribute *attr;
2634 int iv;
2635 char om[100];
2636
2637 SECU_Indent(out, level);
2638 fprintf(out, "%s:\n", m);
2639 SECU_PrintInteger(out, &(info->version), "Version", level + 1);
2640
2641 SECU_PrintName(out, &(info->issuerAndSN->issuer), "Issuer",
2642 level + 1);
2643 SECU_PrintInteger(out, &(info->issuerAndSN->serialNumber),
2644 "Serial Number", level + 1);
2645
2646 SECU_PrintAlgorithmID(out, &(info->digestAlg), "Digest Algorithm",
2647 level + 1);
2648
2649 if (info->authAttr != NULL) {
2650 SECU_Indent(out, level + 1);
2651 fprintf(out, "Authenticated Attributes:\n");
2652 iv = 0;
2653 while ((attr = info->authAttr[iv++]) != NULL) {
2654 sprintf(om, "Attribute (%d)", iv);
2655 secu_PrintAttribute(out, attr, om, level + 2);
2656 }
2657 }
2658
2659 /* Parse and display signature */
2660 SECU_PrintAlgorithmID(out, &(info->digestEncAlg),
2661 "Digest Encryption Algorithm", level + 1);
2662 SECU_PrintAsHex(out, &(info->encDigest), "Encrypted Digest", level + 1);
2663
2664 if (info->unAuthAttr != NULL) {
2665 SECU_Indent(out, level + 1);
2666 fprintf(out, "Unauthenticated Attributes:\n");
2667 iv = 0;
2668 while ((attr = info->unAuthAttr[iv++]) != NULL) {
2669 sprintf(om, "Attribute (%x)", iv);
2670 secu_PrintAttribute(out, attr, om, level + 2);
2671 }
2672 }
2673 }
2674
2675 /* callers of this function must make sure that the CERTSignedCrl
2676 from which they are extracting the CERTCrl has been fully-decoded.
2677 Otherwise it will not have the entries even though the CRL may have
2678 some */
2679
2680 void
SECU_PrintCRLInfo(FILE * out,CERTCrl * crl,char * m,int level)2681 SECU_PrintCRLInfo(FILE *out, CERTCrl *crl, char *m, int level)
2682 {
2683 CERTCrlEntry *entry;
2684 int iv;
2685 char om[100];
2686
2687 SECU_Indent(out, level);
2688 fprintf(out, "%s:\n", m);
2689 /* version is optional */
2690 iv = crl->version.len ? DER_GetInteger(&crl->version) : 0;
2691 SECU_Indent(out, level + 1);
2692 fprintf(out, "%s: %d (0x%x)\n", "Version", iv + 1, iv);
2693 SECU_PrintAlgorithmID(out, &(crl->signatureAlg), "Signature Algorithm",
2694 level + 1);
2695 SECU_PrintName(out, &(crl->name), "Issuer", level + 1);
2696 SECU_PrintTimeChoice(out, &(crl->lastUpdate), "This Update", level + 1);
2697 if (crl->nextUpdate.data && crl->nextUpdate.len) /* is optional */
2698 SECU_PrintTimeChoice(out, &(crl->nextUpdate), "Next Update", level + 1);
2699
2700 if (crl->entries != NULL) {
2701 iv = 0;
2702 while ((entry = crl->entries[iv++]) != NULL) {
2703 sprintf(om, "Entry %d (0x%x):\n", iv, iv);
2704 SECU_Indent(out, level + 1);
2705 fputs(om, out);
2706 SECU_PrintInteger(out, &(entry->serialNumber), "Serial Number",
2707 level + 2);
2708 SECU_PrintTimeChoice(out, &(entry->revocationDate),
2709 "Revocation Date", level + 2);
2710 SECU_PrintExtensions(out, entry->extensions,
2711 "Entry Extensions", level + 2);
2712 }
2713 }
2714 SECU_PrintExtensions(out, crl->extensions, "CRL Extensions", level + 1);
2715 }
2716
2717 /*
2718 ** secu_PrintPKCS7Signed
2719 ** Pretty print a PKCS7 signed data type (up to version 1).
2720 */
2721 static int
secu_PrintPKCS7Signed(FILE * out,SEC_PKCS7SignedData * src,const char * m,int level)2722 secu_PrintPKCS7Signed(FILE *out, SEC_PKCS7SignedData *src,
2723 const char *m, int level)
2724 {
2725 SECAlgorithmID *digAlg; /* digest algorithms */
2726 SECItem *aCert; /* certificate */
2727 CERTSignedCrl *aCrl; /* certificate revocation list */
2728 SEC_PKCS7SignerInfo *sigInfo; /* signer information */
2729 int rv, iv;
2730 char om[100];
2731
2732 SECU_Indent(out, level);
2733 fprintf(out, "%s:\n", m);
2734 SECU_PrintInteger(out, &(src->version), "Version", level + 1);
2735
2736 /* Parse and list digest algorithms (if any) */
2737 if (src->digestAlgorithms != NULL) {
2738 SECU_Indent(out, level + 1);
2739 fprintf(out, "Digest Algorithm List:\n");
2740 iv = 0;
2741 while ((digAlg = src->digestAlgorithms[iv++]) != NULL) {
2742 sprintf(om, "Digest Algorithm (%x)", iv);
2743 SECU_PrintAlgorithmID(out, digAlg, om, level + 2);
2744 }
2745 }
2746
2747 /* Now for the content */
2748 rv = secu_PrintPKCS7ContentInfo(out, &(src->contentInfo),
2749 "Content Information", level + 1);
2750 if (rv != 0)
2751 return rv;
2752
2753 /* Parse and list certificates (if any) */
2754 if (src->rawCerts != NULL) {
2755 SECU_Indent(out, level + 1);
2756 fprintf(out, "Certificate List:\n");
2757 iv = 0;
2758 while ((aCert = src->rawCerts[iv++]) != NULL) {
2759 sprintf(om, "Certificate (%x)", iv);
2760 rv = SECU_PrintSignedData(out, aCert, om, level + 2,
2761 (SECU_PPFunc)SECU_PrintCertificate);
2762 if (rv)
2763 return rv;
2764 }
2765 }
2766
2767 /* Parse and list CRL's (if any) */
2768 if (src->crls != NULL) {
2769 SECU_Indent(out, level + 1);
2770 fprintf(out, "Signed Revocation Lists:\n");
2771 iv = 0;
2772 while ((aCrl = src->crls[iv++]) != NULL) {
2773 sprintf(om, "Signed Revocation List (%x)", iv);
2774 SECU_Indent(out, level + 2);
2775 fprintf(out, "%s:\n", om);
2776 SECU_PrintAlgorithmID(out, &aCrl->signatureWrap.signatureAlgorithm,
2777 "Signature Algorithm", level + 3);
2778 DER_ConvertBitString(&aCrl->signatureWrap.signature);
2779 SECU_PrintAsHex(out, &aCrl->signatureWrap.signature, "Signature",
2780 level + 3);
2781 SECU_PrintCRLInfo(out, &aCrl->crl, "Certificate Revocation List",
2782 level + 3);
2783 }
2784 }
2785
2786 /* Parse and list signatures (if any) */
2787 if (src->signerInfos != NULL) {
2788 SECU_Indent(out, level + 1);
2789 fprintf(out, "Signer Information List:\n");
2790 iv = 0;
2791 while ((sigInfo = src->signerInfos[iv++]) != NULL) {
2792 sprintf(om, "Signer Information (%x)", iv);
2793 secu_PrintSignerInfo(out, sigInfo, om, level + 2);
2794 }
2795 }
2796
2797 return 0;
2798 }
2799
2800 /*
2801 ** secu_PrintPKCS7Enveloped
2802 ** Pretty print a PKCS7 enveloped data type (up to version 1).
2803 */
2804 static void
secu_PrintPKCS7Enveloped(FILE * out,SEC_PKCS7EnvelopedData * src,const char * m,int level)2805 secu_PrintPKCS7Enveloped(FILE *out, SEC_PKCS7EnvelopedData *src,
2806 const char *m, int level)
2807 {
2808 SEC_PKCS7RecipientInfo *recInfo; /* pointer for signer information */
2809 int iv;
2810 char om[100];
2811
2812 SECU_Indent(out, level);
2813 fprintf(out, "%s:\n", m);
2814 SECU_PrintInteger(out, &(src->version), "Version", level + 1);
2815
2816 /* Parse and list recipients (this is not optional) */
2817 if (src->recipientInfos != NULL) {
2818 SECU_Indent(out, level + 1);
2819 fprintf(out, "Recipient Information List:\n");
2820 iv = 0;
2821 while ((recInfo = src->recipientInfos[iv++]) != NULL) {
2822 sprintf(om, "Recipient Information (%x)", iv);
2823 secu_PrintRecipientInfo(out, recInfo, om, level + 2);
2824 }
2825 }
2826
2827 secu_PrintPKCS7EncContent(out, &src->encContentInfo,
2828 "Encrypted Content Information", level + 1);
2829 }
2830
2831 /*
2832 ** secu_PrintPKCS7SignedEnveloped
2833 ** Pretty print a PKCS7 singed and enveloped data type (up to version 1).
2834 */
2835 static int
secu_PrintPKCS7SignedAndEnveloped(FILE * out,SEC_PKCS7SignedAndEnvelopedData * src,const char * m,int level)2836 secu_PrintPKCS7SignedAndEnveloped(FILE *out,
2837 SEC_PKCS7SignedAndEnvelopedData *src,
2838 const char *m, int level)
2839 {
2840 SECAlgorithmID *digAlg; /* pointer for digest algorithms */
2841 SECItem *aCert; /* pointer for certificate */
2842 CERTSignedCrl *aCrl; /* pointer for certificate revocation list */
2843 SEC_PKCS7SignerInfo *sigInfo; /* pointer for signer information */
2844 SEC_PKCS7RecipientInfo *recInfo; /* pointer for recipient information */
2845 int rv, iv;
2846 char om[100];
2847
2848 SECU_Indent(out, level);
2849 fprintf(out, "%s:\n", m);
2850 SECU_PrintInteger(out, &(src->version), "Version", level + 1);
2851
2852 /* Parse and list recipients (this is not optional) */
2853 if (src->recipientInfos != NULL) {
2854 SECU_Indent(out, level + 1);
2855 fprintf(out, "Recipient Information List:\n");
2856 iv = 0;
2857 while ((recInfo = src->recipientInfos[iv++]) != NULL) {
2858 sprintf(om, "Recipient Information (%x)", iv);
2859 secu_PrintRecipientInfo(out, recInfo, om, level + 2);
2860 }
2861 }
2862
2863 /* Parse and list digest algorithms (if any) */
2864 if (src->digestAlgorithms != NULL) {
2865 SECU_Indent(out, level + 1);
2866 fprintf(out, "Digest Algorithm List:\n");
2867 iv = 0;
2868 while ((digAlg = src->digestAlgorithms[iv++]) != NULL) {
2869 sprintf(om, "Digest Algorithm (%x)", iv);
2870 SECU_PrintAlgorithmID(out, digAlg, om, level + 2);
2871 }
2872 }
2873
2874 secu_PrintPKCS7EncContent(out, &src->encContentInfo,
2875 "Encrypted Content Information", level + 1);
2876
2877 /* Parse and list certificates (if any) */
2878 if (src->rawCerts != NULL) {
2879 SECU_Indent(out, level + 1);
2880 fprintf(out, "Certificate List:\n");
2881 iv = 0;
2882 while ((aCert = src->rawCerts[iv++]) != NULL) {
2883 sprintf(om, "Certificate (%x)", iv);
2884 rv = SECU_PrintSignedData(out, aCert, om, level + 2,
2885 (SECU_PPFunc)SECU_PrintCertificate);
2886 if (rv)
2887 return rv;
2888 }
2889 }
2890
2891 /* Parse and list CRL's (if any) */
2892 if (src->crls != NULL) {
2893 SECU_Indent(out, level + 1);
2894 fprintf(out, "Signed Revocation Lists:\n");
2895 iv = 0;
2896 while ((aCrl = src->crls[iv++]) != NULL) {
2897 sprintf(om, "Signed Revocation List (%x)", iv);
2898 SECU_Indent(out, level + 2);
2899 fprintf(out, "%s:\n", om);
2900 SECU_PrintAlgorithmID(out, &aCrl->signatureWrap.signatureAlgorithm,
2901 "Signature Algorithm", level + 3);
2902 DER_ConvertBitString(&aCrl->signatureWrap.signature);
2903 SECU_PrintAsHex(out, &aCrl->signatureWrap.signature, "Signature",
2904 level + 3);
2905 SECU_PrintCRLInfo(out, &aCrl->crl, "Certificate Revocation List",
2906 level + 3);
2907 }
2908 }
2909
2910 /* Parse and list signatures (if any) */
2911 if (src->signerInfos != NULL) {
2912 SECU_Indent(out, level + 1);
2913 fprintf(out, "Signer Information List:\n");
2914 iv = 0;
2915 while ((sigInfo = src->signerInfos[iv++]) != NULL) {
2916 sprintf(om, "Signer Information (%x)", iv);
2917 secu_PrintSignerInfo(out, sigInfo, om, level + 2);
2918 }
2919 }
2920
2921 return 0;
2922 }
2923
2924 int
SECU_PrintCrl(FILE * out,SECItem * der,char * m,int level)2925 SECU_PrintCrl(FILE *out, SECItem *der, char *m, int level)
2926 {
2927 PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2928 CERTCrl *c = NULL;
2929 int rv = SEC_ERROR_NO_MEMORY;
2930
2931 if (!arena)
2932 return rv;
2933 do {
2934 /* Decode CRL */
2935 c = PORT_ArenaZNew(arena, CERTCrl);
2936 if (!c)
2937 break;
2938
2939 rv = SEC_QuickDERDecodeItem(arena, c, SEC_ASN1_GET(CERT_CrlTemplate), der);
2940 if (rv != SECSuccess)
2941 break;
2942 SECU_PrintCRLInfo(out, c, m, level);
2943 } while (0);
2944 PORT_FreeArena(arena, PR_FALSE);
2945 return rv;
2946 }
2947
2948 /*
2949 ** secu_PrintPKCS7Encrypted
2950 ** Pretty print a PKCS7 encrypted data type (up to version 1).
2951 */
2952 static void
secu_PrintPKCS7Encrypted(FILE * out,SEC_PKCS7EncryptedData * src,const char * m,int level)2953 secu_PrintPKCS7Encrypted(FILE *out, SEC_PKCS7EncryptedData *src,
2954 const char *m, int level)
2955 {
2956 SECU_Indent(out, level);
2957 fprintf(out, "%s:\n", m);
2958 SECU_PrintInteger(out, &(src->version), "Version", level + 1);
2959
2960 secu_PrintPKCS7EncContent(out, &src->encContentInfo,
2961 "Encrypted Content Information", level + 1);
2962 }
2963
2964 /*
2965 ** secu_PrintPKCS7Digested
2966 ** Pretty print a PKCS7 digested data type (up to version 1).
2967 */
2968 static void
secu_PrintPKCS7Digested(FILE * out,SEC_PKCS7DigestedData * src,const char * m,int level)2969 secu_PrintPKCS7Digested(FILE *out, SEC_PKCS7DigestedData *src,
2970 const char *m, int level)
2971 {
2972 SECU_Indent(out, level);
2973 fprintf(out, "%s:\n", m);
2974 SECU_PrintInteger(out, &(src->version), "Version", level + 1);
2975
2976 SECU_PrintAlgorithmID(out, &src->digestAlg, "Digest Algorithm",
2977 level + 1);
2978 secu_PrintPKCS7ContentInfo(out, &src->contentInfo, "Content Information",
2979 level + 1);
2980 SECU_PrintAsHex(out, &src->digest, "Digest", level + 1);
2981 }
2982
2983 /*
2984 ** secu_PrintPKCS7ContentInfo
2985 ** Takes a SEC_PKCS7ContentInfo type and sends the contents to the
2986 ** appropriate function
2987 */
2988 static int
secu_PrintPKCS7ContentInfo(FILE * out,SEC_PKCS7ContentInfo * src,char * m,int level)2989 secu_PrintPKCS7ContentInfo(FILE *out, SEC_PKCS7ContentInfo *src,
2990 char *m, int level)
2991 {
2992 const char *desc;
2993 SECOidTag kind;
2994 int rv;
2995
2996 SECU_Indent(out, level);
2997 fprintf(out, "%s:\n", m);
2998 level++;
2999
3000 if (src->contentTypeTag == NULL)
3001 src->contentTypeTag = SECOID_FindOID(&(src->contentType));
3002
3003 if (src->contentTypeTag == NULL) {
3004 desc = "Unknown";
3005 kind = SEC_OID_PKCS7_DATA;
3006 } else {
3007 desc = src->contentTypeTag->desc;
3008 kind = src->contentTypeTag->offset;
3009 }
3010
3011 if (src->content.data == NULL) {
3012 SECU_Indent(out, level);
3013 fprintf(out, "%s:\n", desc);
3014 level++;
3015 SECU_Indent(out, level);
3016 fprintf(out, "<no content>\n");
3017 return 0;
3018 }
3019
3020 rv = 0;
3021 switch (kind) {
3022 case SEC_OID_PKCS7_SIGNED_DATA: /* Signed Data */
3023 rv = secu_PrintPKCS7Signed(out, src->content.signedData, desc, level);
3024 break;
3025
3026 case SEC_OID_PKCS7_ENVELOPED_DATA: /* Enveloped Data */
3027 secu_PrintPKCS7Enveloped(out, src->content.envelopedData, desc, level);
3028 break;
3029
3030 case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: /* Signed and Enveloped */
3031 rv = secu_PrintPKCS7SignedAndEnveloped(out,
3032 src->content.signedAndEnvelopedData,
3033 desc, level);
3034 break;
3035
3036 case SEC_OID_PKCS7_DIGESTED_DATA: /* Digested Data */
3037 secu_PrintPKCS7Digested(out, src->content.digestedData, desc, level);
3038 break;
3039
3040 case SEC_OID_PKCS7_ENCRYPTED_DATA: /* Encrypted Data */
3041 secu_PrintPKCS7Encrypted(out, src->content.encryptedData, desc, level);
3042 break;
3043
3044 default:
3045 SECU_PrintAsHex(out, src->content.data, desc, level);
3046 break;
3047 }
3048
3049 return rv;
3050 }
3051
3052 /*
3053 ** SECU_PrintPKCS7ContentInfo
3054 ** Decode and print any major PKCS7 data type (up to version 1).
3055 */
3056 int
SECU_PrintPKCS7ContentInfo(FILE * out,SECItem * der,char * m,int level)3057 SECU_PrintPKCS7ContentInfo(FILE *out, SECItem *der, char *m, int level)
3058 {
3059 SEC_PKCS7ContentInfo *cinfo;
3060 int rv;
3061
3062 cinfo = SEC_PKCS7DecodeItem(der, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
3063 if (cinfo != NULL) {
3064 /* Send it to recursive parsing and printing module */
3065 rv = secu_PrintPKCS7ContentInfo(out, cinfo, m, level);
3066 SEC_PKCS7DestroyContentInfo(cinfo);
3067 } else {
3068 rv = -1;
3069 }
3070
3071 return rv;
3072 }
3073
3074 /*
3075 ** End of PKCS7 functions
3076 */
3077
3078 void
printFlags(FILE * out,unsigned int flags,int level)3079 printFlags(FILE *out, unsigned int flags, int level)
3080 {
3081 if (flags & CERTDB_TERMINAL_RECORD) {
3082 SECU_Indent(out, level);
3083 fprintf(out, "Terminal Record\n");
3084 }
3085 if (flags & CERTDB_TRUSTED) {
3086 SECU_Indent(out, level);
3087 fprintf(out, "Trusted\n");
3088 }
3089 if (flags & CERTDB_SEND_WARN) {
3090 SECU_Indent(out, level);
3091 fprintf(out, "Warn When Sending\n");
3092 }
3093 if (flags & CERTDB_VALID_CA) {
3094 SECU_Indent(out, level);
3095 fprintf(out, "Valid CA\n");
3096 }
3097 if (flags & CERTDB_TRUSTED_CA) {
3098 SECU_Indent(out, level);
3099 fprintf(out, "Trusted CA\n");
3100 }
3101 if (flags & CERTDB_NS_TRUSTED_CA) {
3102 SECU_Indent(out, level);
3103 fprintf(out, "Netscape Trusted CA\n");
3104 }
3105 if (flags & CERTDB_USER) {
3106 SECU_Indent(out, level);
3107 fprintf(out, "User\n");
3108 }
3109 if (flags & CERTDB_TRUSTED_CLIENT_CA) {
3110 SECU_Indent(out, level);
3111 fprintf(out, "Trusted Client CA\n");
3112 }
3113 if (flags & CERTDB_GOVT_APPROVED_CA) {
3114 SECU_Indent(out, level);
3115 fprintf(out, "Step-up\n");
3116 }
3117 }
3118
3119 void
SECU_PrintTrustFlags(FILE * out,CERTCertTrust * trust,char * m,int level)3120 SECU_PrintTrustFlags(FILE *out, CERTCertTrust *trust, char *m, int level)
3121 {
3122 SECU_Indent(out, level);
3123 fprintf(out, "%s:\n", m);
3124 SECU_Indent(out, level + 1);
3125 fprintf(out, "SSL Flags:\n");
3126 printFlags(out, trust->sslFlags, level + 2);
3127 SECU_Indent(out, level + 1);
3128 fprintf(out, "Email Flags:\n");
3129 printFlags(out, trust->emailFlags, level + 2);
3130 SECU_Indent(out, level + 1);
3131 fprintf(out, "Object Signing Flags:\n");
3132 printFlags(out, trust->objectSigningFlags, level + 2);
3133 }
3134
3135 int
SECU_PrintDERName(FILE * out,SECItem * der,const char * m,int level)3136 SECU_PrintDERName(FILE *out, SECItem *der, const char *m, int level)
3137 {
3138 PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
3139 CERTName *name;
3140 int rv = SEC_ERROR_NO_MEMORY;
3141
3142 if (!arena)
3143 return rv;
3144
3145 name = PORT_ArenaZNew(arena, CERTName);
3146 if (!name)
3147 goto loser;
3148
3149 rv = SEC_ASN1DecodeItem(arena, name, SEC_ASN1_GET(CERT_NameTemplate), der);
3150 if (rv)
3151 goto loser;
3152
3153 SECU_PrintName(out, name, m, level);
3154 if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
3155 SECU_Newline(out);
3156 loser:
3157 PORT_FreeArena(arena, PR_FALSE);
3158 return rv;
3159 }
3160
3161 typedef enum {
3162 noSignature = 0,
3163 withSignature = 1
3164 } SignatureOptionType;
3165
3166 static int
secu_PrintSignedDataSigOpt(FILE * out,SECItem * der,const char * m,int level,SECU_PPFunc inner,SignatureOptionType withSignature)3167 secu_PrintSignedDataSigOpt(FILE *out, SECItem *der, const char *m,
3168 int level, SECU_PPFunc inner,
3169 SignatureOptionType withSignature)
3170 {
3171 PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
3172 CERTSignedData *sd;
3173 int rv = SEC_ERROR_NO_MEMORY;
3174
3175 if (!arena)
3176 return rv;
3177
3178 /* Strip off the signature */
3179 sd = PORT_ArenaZNew(arena, CERTSignedData);
3180 if (!sd)
3181 goto loser;
3182
3183 rv = SEC_ASN1DecodeItem(arena, sd, SEC_ASN1_GET(CERT_SignedDataTemplate),
3184 der);
3185 if (rv)
3186 goto loser;
3187
3188 if (m) {
3189 SECU_Indent(out, level);
3190 fprintf(out, "%s:\n", m);
3191 } else {
3192 level -= 1;
3193 }
3194 rv = (*inner)(out, &sd->data, "Data", level + 1);
3195
3196 if (withSignature) {
3197 SECU_PrintAlgorithmID(out, &sd->signatureAlgorithm, "Signature Algorithm",
3198 level + 1);
3199 DER_ConvertBitString(&sd->signature);
3200 SECU_PrintAsHex(out, &sd->signature, "Signature", level + 1);
3201 }
3202 SECU_PrintFingerprints(out, der, "Fingerprint", level + 1);
3203 loser:
3204 PORT_FreeArena(arena, PR_FALSE);
3205 return rv;
3206 }
3207
3208 int
SECU_PrintSignedData(FILE * out,SECItem * der,const char * m,int level,SECU_PPFunc inner)3209 SECU_PrintSignedData(FILE *out, SECItem *der, const char *m,
3210 int level, SECU_PPFunc inner)
3211 {
3212 return secu_PrintSignedDataSigOpt(out, der, m, level, inner,
3213 withSignature);
3214 }
3215
3216 int
SECU_PrintSignedContent(FILE * out,SECItem * der,char * m,int level,SECU_PPFunc inner)3217 SECU_PrintSignedContent(FILE *out, SECItem *der, char *m,
3218 int level, SECU_PPFunc inner)
3219 {
3220 return secu_PrintSignedDataSigOpt(out, der, m, level, inner,
3221 noSignature);
3222 }
3223
3224 SECStatus
SEC_PrintCertificateAndTrust(CERTCertificate * cert,const char * label,CERTCertTrust * trust)3225 SEC_PrintCertificateAndTrust(CERTCertificate *cert,
3226 const char *label,
3227 CERTCertTrust *trust)
3228 {
3229 SECStatus rv;
3230 SECItem data;
3231 CERTCertTrust certTrust;
3232
3233 data.data = cert->derCert.data;
3234 data.len = cert->derCert.len;
3235
3236 rv = SECU_PrintSignedData(stdout, &data, label, 0,
3237 (SECU_PPFunc)SECU_PrintCertificate);
3238 if (rv) {
3239 return (SECFailure);
3240 }
3241 if (trust) {
3242 SECU_PrintTrustFlags(stdout, trust,
3243 "Certificate Trust Flags", 1);
3244 } else if (CERT_GetCertTrust(cert, &certTrust) == SECSuccess) {
3245 SECU_PrintTrustFlags(stdout, &certTrust,
3246 "Certificate Trust Flags", 1);
3247 }
3248
3249 printf("\n");
3250
3251 return (SECSuccess);
3252 }
3253
3254 static char *
bestCertName(CERTCertificate * cert)3255 bestCertName(CERTCertificate *cert)
3256 {
3257 if (cert->nickname) {
3258 return cert->nickname;
3259 }
3260 if (cert->emailAddr && cert->emailAddr[0]) {
3261 return cert->emailAddr;
3262 }
3263 return cert->subjectName;
3264 }
3265
3266 void
SECU_printCertProblemsOnDate(FILE * outfile,CERTCertDBHandle * handle,CERTCertificate * cert,PRBool checksig,SECCertificateUsage certUsage,void * pinArg,PRBool verbose,PRTime datetime)3267 SECU_printCertProblemsOnDate(FILE *outfile, CERTCertDBHandle *handle,
3268 CERTCertificate *cert, PRBool checksig,
3269 SECCertificateUsage certUsage, void *pinArg, PRBool verbose,
3270 PRTime datetime)
3271 {
3272 CERTVerifyLog log;
3273 CERTVerifyLogNode *node;
3274
3275 PRErrorCode err = PORT_GetError();
3276
3277 log.arena = PORT_NewArena(512);
3278 log.head = log.tail = NULL;
3279 log.count = 0;
3280 CERT_VerifyCertificate(handle, cert, checksig, certUsage, datetime, pinArg, &log, NULL);
3281
3282 SECU_displayVerifyLog(outfile, &log, verbose);
3283
3284 for (node = log.head; node; node = node->next) {
3285 if (node->cert)
3286 CERT_DestroyCertificate(node->cert);
3287 }
3288 PORT_FreeArena(log.arena, PR_FALSE);
3289
3290 PORT_SetError(err); /* restore original error code */
3291 }
3292
3293 void
SECU_displayVerifyLog(FILE * outfile,CERTVerifyLog * log,PRBool verbose)3294 SECU_displayVerifyLog(FILE *outfile, CERTVerifyLog *log,
3295 PRBool verbose)
3296 {
3297 CERTVerifyLogNode *node = NULL;
3298 unsigned int depth = (unsigned int)-1;
3299 unsigned int flags = 0;
3300 char *errstr = NULL;
3301
3302 if (log->count > 0) {
3303 fprintf(outfile, "PROBLEM WITH THE CERT CHAIN:\n");
3304 for (node = log->head; node; node = node->next) {
3305 if (depth != node->depth) {
3306 depth = node->depth;
3307 fprintf(outfile, "CERT %d. %s %s:\n", depth,
3308 bestCertName(node->cert),
3309 depth ? "[Certificate Authority]" : "");
3310 if (verbose) {
3311 const char *emailAddr;
3312 emailAddr = CERT_GetFirstEmailAddress(node->cert);
3313 if (emailAddr) {
3314 fprintf(outfile, "Email Address(es): ");
3315 do {
3316 fprintf(outfile, "%s\n", emailAddr);
3317 emailAddr = CERT_GetNextEmailAddress(node->cert,
3318 emailAddr);
3319 } while (emailAddr);
3320 }
3321 }
3322 }
3323 fprintf(outfile, " ERROR %ld: %s\n", node->error,
3324 SECU_Strerror(node->error));
3325 errstr = NULL;
3326 switch (node->error) {
3327 case SEC_ERROR_INADEQUATE_KEY_USAGE:
3328 flags = (unsigned int)((char *)node->arg - (char *)NULL);
3329 switch (flags) {
3330 case KU_DIGITAL_SIGNATURE:
3331 errstr = "Cert cannot sign.";
3332 break;
3333 case KU_KEY_ENCIPHERMENT:
3334 errstr = "Cert cannot encrypt.";
3335 break;
3336 case KU_KEY_CERT_SIGN:
3337 errstr = "Cert cannot sign other certs.";
3338 break;
3339 default:
3340 errstr = "[unknown usage].";
3341 break;
3342 }
3343 break;
3344 case SEC_ERROR_INADEQUATE_CERT_TYPE:
3345 flags = (unsigned int)((char *)node->arg - (char *)NULL);
3346 switch (flags) {
3347 case NS_CERT_TYPE_SSL_CLIENT:
3348 case NS_CERT_TYPE_SSL_SERVER:
3349 errstr = "Cert cannot be used for SSL.";
3350 break;
3351 case NS_CERT_TYPE_SSL_CA:
3352 errstr = "Cert cannot be used as an SSL CA.";
3353 break;
3354 case NS_CERT_TYPE_EMAIL:
3355 errstr = "Cert cannot be used for SMIME.";
3356 break;
3357 case NS_CERT_TYPE_EMAIL_CA:
3358 errstr = "Cert cannot be used as an SMIME CA.";
3359 break;
3360 case NS_CERT_TYPE_OBJECT_SIGNING:
3361 errstr = "Cert cannot be used for object signing.";
3362 break;
3363 case NS_CERT_TYPE_OBJECT_SIGNING_CA:
3364 errstr = "Cert cannot be used as an object signing CA.";
3365 break;
3366 default:
3367 errstr = "[unknown usage].";
3368 break;
3369 }
3370 break;
3371 case SEC_ERROR_UNKNOWN_ISSUER:
3372 case SEC_ERROR_UNTRUSTED_ISSUER:
3373 case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
3374 errstr = node->cert->issuerName;
3375 break;
3376 default:
3377 break;
3378 }
3379 if (errstr) {
3380 fprintf(stderr, " %s\n", errstr);
3381 }
3382 }
3383 }
3384 }
3385
3386 void
SECU_printCertProblems(FILE * outfile,CERTCertDBHandle * handle,CERTCertificate * cert,PRBool checksig,SECCertificateUsage certUsage,void * pinArg,PRBool verbose)3387 SECU_printCertProblems(FILE *outfile, CERTCertDBHandle *handle,
3388 CERTCertificate *cert, PRBool checksig,
3389 SECCertificateUsage certUsage, void *pinArg, PRBool verbose)
3390 {
3391 SECU_printCertProblemsOnDate(outfile, handle, cert, checksig,
3392 certUsage, pinArg, verbose, PR_Now());
3393 }
3394
3395 SECStatus
SECU_StoreCRL(PK11SlotInfo * slot,SECItem * derCrl,PRFileDesc * outFile,PRBool ascii,char * url)3396 SECU_StoreCRL(PK11SlotInfo *slot, SECItem *derCrl, PRFileDesc *outFile,
3397 PRBool ascii, char *url)
3398 {
3399 PORT_Assert(derCrl != NULL);
3400 if (!derCrl) {
3401 PORT_SetError(SEC_ERROR_INVALID_ARGS);
3402 return SECFailure;
3403 }
3404
3405 if (outFile != NULL) {
3406 if (ascii) {
3407 PR_fprintf(outFile, "%s\n%s\n%s\n", NS_CRL_HEADER,
3408 BTOA_DataToAscii(derCrl->data, derCrl->len),
3409 NS_CRL_TRAILER);
3410 } else {
3411 if (PR_Write(outFile, derCrl->data, derCrl->len) != derCrl->len) {
3412 return SECFailure;
3413 }
3414 }
3415 }
3416 if (slot) {
3417 CERTSignedCrl *newCrl = PK11_ImportCRL(slot, derCrl, url,
3418 SEC_CRL_TYPE, NULL, 0, NULL, 0);
3419 if (newCrl != NULL) {
3420 SEC_DestroyCrl(newCrl);
3421 return SECSuccess;
3422 }
3423 return SECFailure;
3424 }
3425 if (!outFile && !slot) {
3426 PORT_SetError(SEC_ERROR_INVALID_ARGS);
3427 return SECFailure;
3428 }
3429 return SECSuccess;
3430 }
3431
3432 SECStatus
SECU_SignAndEncodeCRL(CERTCertificate * issuer,CERTSignedCrl * signCrl,SECOidTag hashAlgTag,SignAndEncodeFuncExitStat * resCode)3433 SECU_SignAndEncodeCRL(CERTCertificate *issuer, CERTSignedCrl *signCrl,
3434 SECOidTag hashAlgTag, SignAndEncodeFuncExitStat *resCode)
3435 {
3436 SECItem der;
3437 SECKEYPrivateKey *caPrivateKey = NULL;
3438 SECStatus rv;
3439 PLArenaPool *arena;
3440 SECOidTag algID;
3441 void *dummy;
3442
3443 PORT_Assert(issuer != NULL && signCrl != NULL);
3444 if (!issuer || !signCrl) {
3445 PORT_SetError(SEC_ERROR_INVALID_ARGS);
3446 return SECFailure;
3447 }
3448
3449 arena = signCrl->arena;
3450
3451 caPrivateKey = PK11_FindKeyByAnyCert(issuer, NULL);
3452 if (caPrivateKey == NULL) {
3453 *resCode = noKeyFound;
3454 return SECFailure;
3455 }
3456
3457 algID = SEC_GetSignatureAlgorithmOidTag(caPrivateKey->keyType, hashAlgTag);
3458 if (algID == SEC_OID_UNKNOWN) {
3459 *resCode = noSignatureMatch;
3460 rv = SECFailure;
3461 goto done;
3462 }
3463
3464 if (!signCrl->crl.signatureAlg.parameters.data) {
3465 rv = SECOID_SetAlgorithmID(arena, &signCrl->crl.signatureAlg, algID, 0);
3466 if (rv != SECSuccess) {
3467 *resCode = failToEncode;
3468 goto done;
3469 }
3470 }
3471
3472 der.len = 0;
3473 der.data = NULL;
3474 dummy = SEC_ASN1EncodeItem(arena, &der, &signCrl->crl,
3475 SEC_ASN1_GET(CERT_CrlTemplate));
3476 if (!dummy) {
3477 *resCode = failToEncode;
3478 rv = SECFailure;
3479 goto done;
3480 }
3481
3482 rv = SECU_DerSignDataCRL(arena, &signCrl->signatureWrap,
3483 der.data, der.len, caPrivateKey, algID);
3484 if (rv != SECSuccess) {
3485 *resCode = failToSign;
3486 goto done;
3487 }
3488
3489 signCrl->derCrl = PORT_ArenaZNew(arena, SECItem);
3490 if (signCrl->derCrl == NULL) {
3491 *resCode = noMem;
3492 PORT_SetError(SEC_ERROR_NO_MEMORY);
3493 rv = SECFailure;
3494 goto done;
3495 }
3496
3497 signCrl->derCrl->len = 0;
3498 signCrl->derCrl->data = NULL;
3499 dummy = SEC_ASN1EncodeItem(arena, signCrl->derCrl, signCrl,
3500 SEC_ASN1_GET(CERT_SignedCrlTemplate));
3501 if (!dummy) {
3502 *resCode = failToEncode;
3503 rv = SECFailure;
3504 goto done;
3505 }
3506
3507 done:
3508 SECKEY_DestroyPrivateKey(caPrivateKey);
3509 return rv;
3510 }
3511
3512 SECStatus
SECU_CopyCRL(PLArenaPool * destArena,CERTCrl * destCrl,CERTCrl * srcCrl)3513 SECU_CopyCRL(PLArenaPool *destArena, CERTCrl *destCrl, CERTCrl *srcCrl)
3514 {
3515 void *dummy;
3516 SECStatus rv = SECSuccess;
3517 SECItem der;
3518
3519 PORT_Assert(destArena && srcCrl && destCrl);
3520 if (!destArena || !srcCrl || !destCrl) {
3521 PORT_SetError(SEC_ERROR_INVALID_ARGS);
3522 return SECFailure;
3523 }
3524
3525 der.len = 0;
3526 der.data = NULL;
3527 dummy = SEC_ASN1EncodeItem(destArena, &der, srcCrl,
3528 SEC_ASN1_GET(CERT_CrlTemplate));
3529 if (!dummy) {
3530 return SECFailure;
3531 }
3532
3533 rv = SEC_QuickDERDecodeItem(destArena, destCrl,
3534 SEC_ASN1_GET(CERT_CrlTemplate), &der);
3535 if (rv != SECSuccess) {
3536 return SECFailure;
3537 }
3538
3539 destCrl->arena = destArena;
3540
3541 return rv;
3542 }
3543
3544 SECStatus
SECU_DerSignDataCRL(PLArenaPool * arena,CERTSignedData * sd,unsigned char * buf,int len,SECKEYPrivateKey * pk,SECOidTag algID)3545 SECU_DerSignDataCRL(PLArenaPool *arena, CERTSignedData *sd,
3546 unsigned char *buf, int len, SECKEYPrivateKey *pk,
3547 SECOidTag algID)
3548 {
3549 SECItem it;
3550 SECStatus rv;
3551
3552 it.data = 0;
3553
3554 /* XXX We should probably have some asserts here to make sure the key type
3555 * and algID match
3556 */
3557
3558 /* Sign input buffer */
3559 rv = SEC_SignData(&it, buf, len, pk, algID);
3560 if (rv != SECSuccess) {
3561 goto loser;
3562 }
3563
3564 /* Fill out SignedData object */
3565 PORT_Memset(sd, 0, sizeof(*sd));
3566 sd->data.data = buf;
3567 sd->data.len = len;
3568 rv = SECITEM_CopyItem(arena, &sd->signature, &it);
3569 if (rv != SECSuccess) {
3570 goto loser;
3571 }
3572
3573 sd->signature.len <<= 3; /* convert to bit string */
3574 rv = SECOID_SetAlgorithmID(arena, &sd->signatureAlgorithm, algID, 0);
3575 if (rv != SECSuccess) {
3576 goto loser;
3577 }
3578
3579 loser:
3580 PORT_Free(it.data);
3581 return rv;
3582 }
3583
3584 #if 0
3585
3586 /* we need access to the private function cert_FindExtension for this code to work */
3587
3588 CERTAuthKeyID *
3589 SECU_FindCRLAuthKeyIDExten (PLArenaPool *arena, CERTSignedCrl *scrl)
3590 {
3591 SECItem encodedExtenValue;
3592 SECStatus rv;
3593 CERTAuthKeyID *ret;
3594 CERTCrl* crl;
3595
3596 if (!scrl) {
3597 PORT_SetError(SEC_ERROR_INVALID_ARGS);
3598 return NULL;
3599 }
3600
3601 crl = &scrl->crl;
3602
3603 encodedExtenValue.data = NULL;
3604 encodedExtenValue.len = 0;
3605
3606 rv = cert_FindExtension(crl->extensions, SEC_OID_X509_AUTH_KEY_ID,
3607 &encodedExtenValue);
3608 if ( rv != SECSuccess ) {
3609 return (NULL);
3610 }
3611
3612 ret = CERT_DecodeAuthKeyID (arena, &encodedExtenValue);
3613
3614 PORT_Free(encodedExtenValue.data);
3615 encodedExtenValue.data = NULL;
3616
3617 return(ret);
3618 }
3619
3620 #endif
3621
3622 /*
3623 * Find the issuer of a Crl. Use the authorityKeyID if it exists.
3624 */
3625 CERTCertificate *
SECU_FindCrlIssuer(CERTCertDBHandle * dbhandle,SECItem * subject,CERTAuthKeyID * authorityKeyID,PRTime validTime)3626 SECU_FindCrlIssuer(CERTCertDBHandle *dbhandle, SECItem *subject,
3627 CERTAuthKeyID *authorityKeyID, PRTime validTime)
3628 {
3629 CERTCertificate *issuerCert = NULL;
3630 CERTCertList *certList = NULL;
3631 CERTCertTrust trust;
3632
3633 if (!subject) {
3634 PORT_SetError(SEC_ERROR_INVALID_ARGS);
3635 return NULL;
3636 }
3637
3638 certList =
3639 CERT_CreateSubjectCertList(NULL, dbhandle, subject,
3640 validTime, PR_TRUE);
3641 if (certList) {
3642 CERTCertListNode *node = CERT_LIST_HEAD(certList);
3643
3644 /* XXX and authoritykeyid in the future */
3645 while (!CERT_LIST_END(node, certList)) {
3646 CERTCertificate *cert = node->cert;
3647 /* check cert CERTCertTrust data is allocated, check cert
3648 usage extension, check that cert has pkey in db. Select
3649 the first (newest) user cert */
3650 if (CERT_GetCertTrust(cert, &trust) == SECSuccess &&
3651 CERT_CheckCertUsage(cert, KU_CRL_SIGN) == SECSuccess &&
3652 CERT_IsUserCert(cert)) {
3653
3654 issuerCert = CERT_DupCertificate(cert);
3655 break;
3656 }
3657 node = CERT_LIST_NEXT(node);
3658 }
3659 CERT_DestroyCertList(certList);
3660 }
3661 return (issuerCert);
3662 }
3663
3664 /* Encodes and adds extensions to the CRL or CRL entries. */
3665 SECStatus
SECU_EncodeAndAddExtensionValue(PLArenaPool * arena,void * extHandle,void * value,PRBool criticality,int extenType,EXTEN_EXT_VALUE_ENCODER EncodeValueFn)3666 SECU_EncodeAndAddExtensionValue(PLArenaPool *arena, void *extHandle,
3667 void *value, PRBool criticality, int extenType,
3668 EXTEN_EXT_VALUE_ENCODER EncodeValueFn)
3669 {
3670 SECItem encodedValue;
3671 SECStatus rv;
3672
3673 encodedValue.data = NULL;
3674 encodedValue.len = 0;
3675 do {
3676 rv = (*EncodeValueFn)(arena, value, &encodedValue);
3677 if (rv != SECSuccess)
3678 break;
3679
3680 rv = CERT_AddExtension(extHandle, extenType, &encodedValue,
3681 criticality, PR_TRUE);
3682 if (rv != SECSuccess)
3683 break;
3684 } while (0);
3685
3686 return (rv);
3687 }
3688
3689 CERTCertificate *
SECU_FindCertByNicknameOrFilename(CERTCertDBHandle * handle,char * name,PRBool ascii,void * pwarg)3690 SECU_FindCertByNicknameOrFilename(CERTCertDBHandle *handle,
3691 char *name, PRBool ascii,
3692 void *pwarg)
3693 {
3694 CERTCertificate *the_cert;
3695 the_cert = CERT_FindCertByNicknameOrEmailAddr(handle, name);
3696 if (the_cert) {
3697 return the_cert;
3698 }
3699 the_cert = PK11_FindCertFromNickname(name, pwarg);
3700 if (!the_cert) {
3701 /* Don't have a cert with name "name" in the DB. Try to
3702 * open a file with such name and get the cert from there.*/
3703 SECStatus rv;
3704 SECItem item = { 0, NULL, 0 };
3705 PRFileDesc *fd = PR_Open(name, PR_RDONLY, 0777);
3706 if (!fd) {
3707 return NULL;
3708 }
3709 rv = SECU_ReadDERFromFile(&item, fd, ascii, PR_FALSE);
3710 PR_Close(fd);
3711 if (rv != SECSuccess || !item.len) {
3712 PORT_Free(item.data);
3713 return NULL;
3714 }
3715 the_cert = CERT_NewTempCertificate(handle, &item,
3716 NULL /* nickname */,
3717 PR_FALSE /* isPerm */,
3718 PR_TRUE /* copyDER */);
3719 PORT_Free(item.data);
3720 }
3721 return the_cert;
3722 }
3723
3724 /* Convert a SSL/TLS protocol version string into the respective numeric value
3725 * defined by the SSL_LIBRARY_VERSION_* constants,
3726 * while accepting a flexible set of case-insensitive identifiers.
3727 *
3728 * Caller must specify bufLen, allowing the function to operate on substrings.
3729 */
3730 static SECStatus
SECU_GetSSLVersionFromName(const char * buf,size_t bufLen,PRUint16 * version)3731 SECU_GetSSLVersionFromName(const char *buf, size_t bufLen, PRUint16 *version)
3732 {
3733 if (!buf || !version) {
3734 PORT_SetError(SEC_ERROR_INVALID_ARGS);
3735 return SECFailure;
3736 }
3737
3738 if (!PL_strncasecmp(buf, "ssl3", bufLen)) {
3739 *version = SSL_LIBRARY_VERSION_3_0;
3740 return SECSuccess;
3741 }
3742 if (!PL_strncasecmp(buf, "tls1.0", bufLen)) {
3743 *version = SSL_LIBRARY_VERSION_TLS_1_0;
3744 return SECSuccess;
3745 }
3746 if (!PL_strncasecmp(buf, "tls1.1", bufLen)) {
3747 *version = SSL_LIBRARY_VERSION_TLS_1_1;
3748 return SECSuccess;
3749 }
3750 if (!PL_strncasecmp(buf, "tls1.2", bufLen)) {
3751 *version = SSL_LIBRARY_VERSION_TLS_1_2;
3752 return SECSuccess;
3753 }
3754
3755 if (!PL_strncasecmp(buf, "tls1.3", bufLen)) {
3756 *version = SSL_LIBRARY_VERSION_TLS_1_3;
3757 return SECSuccess;
3758 }
3759
3760 PORT_SetError(SEC_ERROR_INVALID_ARGS);
3761 return SECFailure;
3762 }
3763
3764 SECStatus
SECU_ParseSSLVersionRangeString(const char * input,const SSLVersionRange defaultVersionRange,SSLVersionRange * vrange)3765 SECU_ParseSSLVersionRangeString(const char *input,
3766 const SSLVersionRange defaultVersionRange,
3767 SSLVersionRange *vrange)
3768 {
3769 const char *colonPos;
3770 size_t colonIndex;
3771 const char *maxStr;
3772
3773 if (!input || !vrange) {
3774 PORT_SetError(SEC_ERROR_INVALID_ARGS);
3775 return SECFailure;
3776 }
3777
3778 // We don't support SSL2 any longer.
3779 if (defaultVersionRange.min < SSL_LIBRARY_VERSION_3_0 ||
3780 defaultVersionRange.max < SSL_LIBRARY_VERSION_3_0) {
3781 PORT_SetError(SEC_ERROR_INVALID_ARGS);
3782 return SECFailure;
3783 }
3784
3785 if (!strcmp(input, ":")) {
3786 /* special value, use default */
3787 *vrange = defaultVersionRange;
3788 return SECSuccess;
3789 }
3790
3791 colonPos = strchr(input, ':');
3792 if (!colonPos) {
3793 PORT_SetError(SEC_ERROR_INVALID_ARGS);
3794 return SECFailure;
3795 }
3796
3797 colonIndex = colonPos - input;
3798 maxStr = colonPos + 1;
3799
3800 if (!colonIndex) {
3801 /* colon was first character, min version is empty */
3802 vrange->min = defaultVersionRange.min;
3803 } else {
3804 PRUint16 version;
3805 /* colonIndex is equivalent to the length of the min version substring */
3806 if (SECU_GetSSLVersionFromName(input, colonIndex, &version) != SECSuccess) {
3807 PORT_SetError(SEC_ERROR_INVALID_ARGS);
3808 return SECFailure;
3809 }
3810
3811 vrange->min = version;
3812 }
3813
3814 if (!*maxStr) {
3815 vrange->max = defaultVersionRange.max;
3816 } else {
3817 PRUint16 version;
3818 /* if max version is empty, then maxStr points to the string terminator */
3819 if (SECU_GetSSLVersionFromName(maxStr, strlen(maxStr), &version) !=
3820 SECSuccess) {
3821 PORT_SetError(SEC_ERROR_INVALID_ARGS);
3822 return SECFailure;
3823 }
3824
3825 vrange->max = version;
3826 }
3827
3828 if (vrange->min > vrange->max) {
3829 PORT_SetError(SEC_ERROR_INVALID_ARGS);
3830 return SECFailure;
3831 }
3832
3833 return SECSuccess;
3834 }
3835
3836 SECItem *
SECU_HexString2SECItem(PLArenaPool * arena,SECItem * item,const char * str)3837 SECU_HexString2SECItem(PLArenaPool *arena, SECItem *item, const char *str)
3838 {
3839 int i = 0;
3840 int byteval = 0;
3841 int tmp = PORT_Strlen(str);
3842
3843 PORT_Assert(arena);
3844 PORT_Assert(item);
3845
3846 if ((tmp % 2) != 0) {
3847 PORT_SetError(SEC_ERROR_INVALID_ARGS);
3848 return NULL;
3849 }
3850
3851 item = SECITEM_AllocItem(arena, item, tmp / 2);
3852 if (item == NULL) {
3853 return NULL;
3854 }
3855
3856 while (str[i]) {
3857 if ((str[i] >= '0') && (str[i] <= '9')) {
3858 tmp = str[i] - '0';
3859 } else if ((str[i] >= 'a') && (str[i] <= 'f')) {
3860 tmp = str[i] - 'a' + 10;
3861 } else if ((str[i] >= 'A') && (str[i] <= 'F')) {
3862 tmp = str[i] - 'A' + 10;
3863 } else {
3864 /* item is in arena and gets freed by the caller */
3865 return NULL;
3866 }
3867
3868 byteval = byteval * 16 + tmp;
3869 if ((i % 2) != 0) {
3870 item->data[i / 2] = byteval;
3871 byteval = 0;
3872 }
3873 i++;
3874 }
3875
3876 return item;
3877 }
3878