1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
22 * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 ** secutil.c - various functions used by security stuff
56 #if !defined(_WIN32_WCE)
65 /* for SEC_TraverseNames */
70 /* #include "secmod.h" */
74 static char consoleName[] = {
89 static PRBool wrapEnabled = PR_TRUE;
92 SECU_EnableWrap(PRBool enable)
104 SECU_PrintErrMsg(FILE *out, int level, char *progName, char *msg, ...)
107 PRErrorCode err = PORT_GetError();
108 const char * errString = SECU_Strerror(err);
112 SECU_Indent(out, level);
113 fprintf(out, "%s: ", progName);
114 vfprintf(out, msg, args);
115 if (errString != NULL && PORT_Strlen(errString) > 0)
116 fprintf(out, ": %s\n", errString);
118 fprintf(out, ": error %d\n", (int)err);
124 SECU_PrintError(char *progName, char *msg, ...)
127 PRErrorCode err = PORT_GetError();
128 const char * errString = SECU_Strerror(err);
132 fprintf(stderr, "%s: ", progName);
133 vfprintf(stderr, msg, args);
134 if (errString != NULL && PORT_Strlen(errString) > 0)
135 fprintf(stderr, ": %s\n", errString);
137 fprintf(stderr, ": error %d\n", (int)err);
143 SECU_PrintSystemError(char *progName, char *msg, ...)
148 fprintf(stderr, "%s: ", progName);
149 vfprintf(stderr, msg, args);
150 #if defined(_WIN32_WCE)
151 fprintf(stderr, ": %d\n", PR_GetOSError());
153 fprintf(stderr, ": %s\n", strerror(errno));
159 secu_ClearPassword(char *p)
162 PORT_Memset(p, 0, PORT_Strlen(p));
168 SECU_GetPasswordString(void *arg, char *prompt)
172 FILE *input, *output;
175 input = fopen(consoleName, "r");
177 fprintf(stderr, "Error opening input terminal for read\n");
181 output = fopen(consoleName, "w");
182 if (output == NULL) {
183 fprintf(stderr, "Error opening output terminal for write\n");
187 p = SEC_GetPassword (input, output, prompt, SEC_BlindCheckPassword);
196 /* Win32 version of above. opening the console may fail
197 on windows95, and certainly isn't necessary.. */
201 p = SEC_GetPassword (stdin, stdout, prompt, SEC_BlindCheckPassword);
209 * p a s s w o r d _ h a r d c o d e
211 * A function to use the password passed in the -f(pwfile) argument
212 * of the command line.
213 * After use once, null it out otherwise PKCS11 calls us forever.?
217 SECU_FilePasswd(PK11SlotInfo *slot, PRBool retry, void *arg)
219 char* phrases, *phrase;
224 const long maxPwdFileSize = 4096;
225 char* tokenName = NULL;
232 return 0; /* no good retrying - the files contents will be the same */
235 phrases = PORT_ZAlloc(maxPwdFileSize);
238 return 0; /* out of memory */
241 fd = PR_Open(pwFile, PR_RDONLY, 0);
243 fprintf(stderr, "No password file \"%s\" exists.\n", pwFile);
248 nb = PR_Read(fd, phrases, maxPwdFileSize);
253 fprintf(stderr,"password file contains no data\n");
259 tokenName = PK11_GetTokenName(slot);
261 tokenLen = PORT_Strlen(tokenName);
270 /* handle the Windows EOL case */
271 while (phrases[i] != '\r' && phrases[i] != '\n' && i < nb) i++;
272 /* terminate passphrase */
274 /* clean up any EOL before the start of the next passphrase */
275 while ( (i<nb) && (phrases[i] == '\r' || phrases[i] == '\n')) {
278 /* now analyze the current passphrase */
279 phrase = &phrases[startphrase];
282 if (PORT_Strncmp(phrase, tokenName, tokenLen)) continue;
283 phraseLen = PORT_Strlen(phrase);
284 if (phraseLen < (tokenLen+1)) continue;
285 if (phrase[tokenLen] != ':') continue;
286 phrase = &phrase[tokenLen+1];
291 phrase = PORT_Strdup((char*)phrase);
297 SECU_GetModulePassword(PK11SlotInfo *slot, PRBool retry, void *arg)
300 secuPWData *pwdata = (secuPWData *)arg;
301 secuPWData pwnull = { PW_NONE, 0 };
302 secuPWData pwxtrn = { PW_EXTERNAL, "external" };
308 if (PK11_ProtectedAuthenticationPath(slot)) {
311 if (retry && pwdata->source != PW_NONE) {
312 PR_fprintf(PR_STDERR, "Incorrect password/PIN entered.\n");
316 switch (pwdata->source) {
318 sprintf(prompt, "Enter Password or Pin for \"%s\":",
319 PK11_GetTokenName(slot));
320 return SECU_GetPasswordString(NULL, prompt);
322 /* Instead of opening and closing the file every time, get the pw
323 * once, then keep it in memory (duh).
325 pw = SECU_FilePasswd(slot, retry, pwdata->data);
326 pwdata->source = PW_PLAINTEXT;
327 pwdata->data = PL_strdup(pw);
328 /* it's already been dup'ed */
332 "Press Enter, then enter PIN for \"%s\" on external device.\n",
333 PK11_GetTokenName(slot));
334 (void) SECU_GetPasswordString(NULL, prompt);
337 return PL_strdup(pwdata->data);
342 PR_fprintf(PR_STDERR, "Password check failed: No password found.\n");
347 secu_InitSlotPassword(PK11SlotInfo *slot, PRBool retry, void *arg)
351 FILE *input, *output;
352 secuPWData *pwdata = arg;
354 if (pwdata->source == PW_FROMFILE) {
355 return SECU_FilePasswd(slot, retry, pwdata->data);
357 if (pwdata->source == PW_PLAINTEXT) {
358 return PL_strdup(pwdata->data);
361 /* PW_NONE - get it from tty */
366 input = fopen(consoleName, "r");
369 PR_fprintf(PR_STDERR, "Error opening input terminal for read\n");
373 /* we have no password, so initialize database with one */
374 PR_fprintf(PR_STDERR,
375 "Enter a password which will be used to encrypt your keys.\n"
376 "The password should be at least 8 characters long,\n"
377 "and should contain at least one non-alphabetic character.\n\n");
379 output = fopen(consoleName, "w");
380 if (output == NULL) {
381 PR_fprintf(PR_STDERR, "Error opening output terminal for write\n");
389 p0 = SEC_GetPassword(input, output, "Enter new password: ",
390 SEC_BlindCheckPassword);
394 p1 = SEC_GetPassword(input, output, "Re-enter password: ",
395 SEC_BlindCheckPassword);
396 if (p0 && p1 && !PORT_Strcmp(p0, p1)) {
399 PR_fprintf(PR_STDERR, "Passwords do not match. Try again.\n");
402 /* clear out the duplicate password string */
403 secu_ClearPassword(p1);
412 SECU_ChangePW(PK11SlotInfo *slot, char *passwd, char *pwFile)
414 return SECU_ChangePW2(slot, passwd, 0, pwFile, 0);
418 SECU_ChangePW2(PK11SlotInfo *slot, char *oldPass, char *newPass,
419 char *oldPwFile, char *newPwFile)
422 secuPWData pwdata, newpwdata;
423 char *oldpw = NULL, *newpw = NULL;
426 pwdata.source = PW_PLAINTEXT;
427 pwdata.data = oldPass;
428 } else if (oldPwFile) {
429 pwdata.source = PW_FROMFILE;
430 pwdata.data = oldPwFile;
432 pwdata.source = PW_NONE;
437 newpwdata.source = PW_PLAINTEXT;
438 newpwdata.data = newPass;
439 } else if (newPwFile) {
440 newpwdata.source = PW_FROMFILE;
441 newpwdata.data = newPwFile;
443 newpwdata.source = PW_NONE;
444 newpwdata.data = NULL;
447 if (PK11_NeedUserInit(slot)) {
448 newpw = secu_InitSlotPassword(slot, PR_FALSE, &pwdata);
449 rv = PK11_InitPin(slot, (char*)NULL, newpw);
454 oldpw = SECU_GetModulePassword(slot, PR_FALSE, &pwdata);
456 if (PK11_CheckUserPassword(slot, oldpw) != SECSuccess) {
457 if (pwdata.source == PW_NONE) {
458 PR_fprintf(PR_STDERR, "Invalid password. Try again.\n");
460 PR_fprintf(PR_STDERR, "Invalid password.\n");
461 PORT_Memset(oldpw, 0, PL_strlen(oldpw));
471 newpw = secu_InitSlotPassword(slot, PR_FALSE, &newpwdata);
473 if (PK11_ChangePW(slot, oldpw, newpw) != SECSuccess) {
474 PR_fprintf(PR_STDERR, "Failed to change password.\n");
478 PORT_Memset(oldpw, 0, PL_strlen(oldpw));
481 PR_fprintf(PR_STDOUT, "Password changed successfully.\n");
484 PORT_Memset(newpw, 0, PL_strlen(newpw));
496 SECU_DefaultSSLDir(void)
499 static char sslDir[1000];
501 dir = PR_GetEnv("SSL_DIR");
505 sprintf(sslDir, "%s", dir);
507 if (sslDir[strlen(sslDir)-1] == '/')
508 sslDir[strlen(sslDir)-1] = 0;
514 SECU_AppendFilenameToDir(char *dir, char *filename)
516 static char path[1000];
518 if (dir[strlen(dir)-1] == '/')
519 sprintf(path, "%s%s", dir, filename);
521 sprintf(path, "%s/%s", dir, filename);
526 SECU_ConfigDirectory(const char* base)
528 static PRBool initted = PR_FALSE;
529 const char *dir = ".netscape";
531 static char buf[1000];
533 if (initted) return buf;
536 if (base == NULL || *base == 0) {
537 home = PR_GetEnv("HOME");
538 if (!home) home = "";
540 if (*home && home[strlen(home) - 1] == '/')
541 sprintf (buf, "%.900s%s", home, dir);
543 sprintf (buf, "%.900s/%s", home, dir);
545 sprintf(buf, "%.900s", base);
546 if (buf[strlen(buf) - 1] == '/')
547 buf[strlen(buf) - 1] = 0;
555 /*Turn off SSL for now */
556 /* This gets called by SSL when server wants our cert & key */
558 SECU_GetClientAuthData(void *arg, PRFileDesc *fd,
559 struct CERTDistNamesStr *caNames,
560 struct CERTCertificateStr **pRetCert,
561 struct SECKEYPrivateKeyStr **pRetKey)
563 SECKEYPrivateKey *key;
564 CERTCertificate *cert;
568 fprintf(stderr, "no key/cert name specified for client auth\n");
571 cert = PK11_FindCertFromNickname(arg, NULL);
572 errsave = PORT_GetError();
574 if (errsave == SEC_ERROR_BAD_PASSWORD)
575 fprintf(stderr, "Bad password\n");
576 else if (errsave > 0)
577 fprintf(stderr, "Unable to read cert (error %d)\n", errsave);
578 else if (errsave == SEC_ERROR_BAD_DATABASE)
579 fprintf(stderr, "Unable to get cert from database (%d)\n", errsave);
581 fprintf(stderr, "SECKEY_FindKeyByName: internal error %d\n", errsave);
585 key = PK11_FindKeyByAnyCert(arg,NULL);
587 fprintf(stderr, "Unable to get key (%d)\n", PORT_GetError());
599 secu_StdinToItem(SECItem *dst)
601 unsigned char buf[1000];
603 PRBool notDone = PR_TRUE;
609 numBytes = PR_Read(PR_STDIN, buf, sizeof(buf));
619 unsigned char * p = dst->data;
620 dst->data = (unsigned char*)PORT_Realloc(p, dst->len + numBytes);
625 dst->data = (unsigned char*)PORT_Alloc(numBytes);
630 PORT_Memcpy(dst->data + dst->len, buf, numBytes);
631 dst->len += numBytes;
638 SECU_FileToItem(SECItem *dst, PRFileDesc *src)
645 return secu_StdinToItem(dst);
647 prStatus = PR_GetOpenFileInfo(src, &info);
649 if (prStatus != PR_SUCCESS) {
650 PORT_SetError(SEC_ERROR_IO);
654 /* XXX workaround for 3.1, not all utils zero dst before sending */
656 if (!SECITEM_AllocItem(NULL, dst, info.size))
659 numBytes = PR_Read(src, dst->data, info.size);
660 if (numBytes != info.size) {
661 PORT_SetError(SEC_ERROR_IO);
667 SECITEM_FreeItem(dst, PR_FALSE);
673 SECU_TextFileToItem(SECItem *dst, PRFileDesc *src)
681 return secu_StdinToItem(dst);
683 prStatus = PR_GetOpenFileInfo(src, &info);
685 if (prStatus != PR_SUCCESS) {
686 PORT_SetError(SEC_ERROR_IO);
690 buf = (unsigned char*)PORT_Alloc(info.size);
694 numBytes = PR_Read(src, buf, info.size);
695 if (numBytes != info.size) {
696 PORT_SetError(SEC_ERROR_IO);
700 if (buf[numBytes-1] == '\n') numBytes--;
702 if (buf[numBytes-1] == '\r') numBytes--;
705 /* XXX workaround for 3.1, not all utils zero dst before sending */
707 if (!SECITEM_AllocItem(NULL, dst, numBytes))
710 memcpy(dst->data, buf, numBytes);
720 SECU_ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii)
724 /* First convert ascii to binary */
728 /* Read in ascii data */
729 rv = SECU_FileToItem(&filedata, inFile);
730 asc = (char *)filedata.data;
732 fprintf(stderr, "unable to read data from input file\n");
736 /* check for headers and trailers and remove them */
737 if ((body = strstr(asc, "-----BEGIN")) != NULL) {
738 char *trailer = NULL;
740 body = PORT_Strchr(body, '\n');
742 body = PORT_Strchr(asc, '\r'); /* maybe this is a MAC file */
744 trailer = strstr(++body, "-----END");
745 if (trailer != NULL) {
748 fprintf(stderr, "input has header but no trailer\n");
749 PORT_Free(filedata.data);
756 /* Convert to binary */
757 rv = ATOB_ConvertAsciiToItem(der, body);
759 fprintf(stderr, "error converting ascii to binary (%s)\n",
760 SECU_Strerror(PORT_GetError()));
761 PORT_Free(filedata.data);
765 PORT_Free(filedata.data);
767 /* Read in binary der */
768 rv = SECU_FileToItem(der, inFile);
770 fprintf(stderr, "error converting der (%s)\n",
771 SECU_Strerror(PORT_GetError()));
778 #define INDENT_MULT 4
780 SECU_Indent(FILE *out, int level)
784 for (i = 0; i < level; i++) {
789 static void secu_Newline(FILE *out)
795 SECU_PrintAsHex(FILE *out, SECItem *data, const char *m, int level)
799 PRBool isString = PR_TRUE;
800 PRBool isWhiteSpace = PR_TRUE;
801 PRBool printedHex = PR_FALSE;
802 unsigned int limit = 15;
805 SECU_Indent(out, level); fprintf(out, "%s:", m);
812 SECU_Indent(out, level); column = level*INDENT_MULT;
815 fprintf(out, "(empty)\n");
818 /* take a pass to see if it's all printable. */
819 for (i = 0; i < data->len; i++) {
820 unsigned char val = data->data[i];
821 if (!val || !isprint(val)) {
825 if (isWhiteSpace && !isspace(val)) {
826 isWhiteSpace = PR_FALSE;
830 /* Short values, such as bit strings (which are printed with this
831 ** function) often look like strings, but we want to see the bits.
832 ** so this test assures that short values will be printed in hex,
833 ** perhaps in addition to being printed as strings.
834 ** The threshold size (4 bytes) is arbitrary.
836 if (!isString || data->len <= 4) {
837 for (i = 0; i < data->len; i++) {
838 if (i != data->len - 1) {
839 fprintf(out, "%02x:", data->data[i]);
842 fprintf(out, "%02x", data->data[i]);
847 (column > 76 || (i % 16 == limit))) {
849 SECU_Indent(out, level);
850 column = level*INDENT_MULT;
854 printedHex = PR_TRUE;
856 if (isString && !isWhiteSpace) {
857 if (printedHex != PR_FALSE) {
859 SECU_Indent(out, level); column = level*INDENT_MULT;
861 for (i = 0; i < data->len; i++) {
862 unsigned char val = data->data[i];
865 fprintf(out,"%c",val);
870 if (wrapEnabled && column > 76) {
872 SECU_Indent(out, level); column = level*INDENT_MULT;
877 if (column != level*INDENT_MULT) {
882 static const char *hex = "0123456789abcdef";
884 static const char printable[257] = {
885 "................" /* 0x */
886 "................" /* 1x */
887 " !\"#$%&'()*+,-./" /* 2x */
888 "0123456789:;<=>?" /* 3x */
889 "@ABCDEFGHIJKLMNO" /* 4x */
890 "PQRSTUVWXYZ[\\]^_" /* 5x */
891 "`abcdefghijklmno" /* 6x */
892 "pqrstuvwxyz{|}~." /* 7x */
893 "................" /* 8x */
894 "................" /* 9x */
895 "................" /* ax */
896 "................" /* bx */
897 "................" /* cx */
898 "................" /* dx */
899 "................" /* ex */
900 "................" /* fx */
904 SECU_PrintBuf(FILE *out, const char *msg, const void *vp, int len)
906 const unsigned char *cp = (const unsigned char *)vp;
911 fprintf(out, "%s [Len: %d]\n", msg, len);
912 memset(buf, ' ', sizeof buf);
916 unsigned char ch = *cp++;
917 *bp++ = hex[(ch >> 4) & 0xf];
918 *bp++ = hex[ch & 0xf];
920 *ap++ = printable[ch];
921 if (ap - buf >= 66) {
923 fprintf(out, " %s\n", buf);
924 memset(buf, ' ', sizeof buf);
931 fprintf(out, " %s\n", buf);
936 SECU_StripTagAndLength(SECItem *i)
940 if (!i || !i->data || i->len < 2) { /* must be at least tag and length */
943 start = ((i->data[1] & 0x80) ? (i->data[1] & 0x7f) + 2 : 2);
944 if (i->len < start) {
953 /* This expents i->data[0] to be the MSB of the integer.
954 ** if you want to print a DER-encoded integer (with the tag and length)
955 ** call SECU_PrintEncodedInteger();
958 SECU_PrintInteger(FILE *out, SECItem *i, char *m, int level)
962 if (!i || !i->len || !i->data) {
963 SECU_Indent(out, level);
965 fprintf(out, "%s: (null)\n", m);
967 fprintf(out, "(null)\n");
969 } else if (i->len > 4) {
970 SECU_PrintAsHex(out, i, m, level);
972 if (i->type == siUnsignedInteger && *i->data & 0x80) {
973 /* Make sure i->data has zero in the highest bite
974 * if i->data is an unsigned integer */
976 char data[] = {0, 0, 0, 0, 0};
978 PORT_Memcpy(data + 1, i->data, i->len);
979 tmpI.len = i->len + 1;
980 tmpI.data = (void*)data;
982 iv = DER_GetInteger(&tmpI);
984 iv = DER_GetInteger(i);
986 SECU_Indent(out, level);
988 fprintf(out, "%s: %d (0x%x)\n", m, iv, iv);
990 fprintf(out, "%d (0x%x)\n", iv, iv);
996 secu_PrintRawStringQuotesOptional(FILE *out, SECItem *si, const char *m,
997 int level, PRBool quotes)
1003 SECU_Indent(out, level); fprintf(out, "%s: ", m);
1004 column = (level * INDENT_MULT) + strlen(m) + 2;
1007 SECU_Indent(out, level);
1008 column = level*INDENT_MULT;
1011 fprintf(out, "\""); column++;
1014 for (i = 0; i < si->len; i++) {
1015 unsigned char val = si->data[i];
1016 if (wrapEnabled && column > 76) {
1018 SECU_Indent(out, level); column = level*INDENT_MULT;
1021 fprintf(out,"%c", printable[val]); column++;
1025 fprintf(out, "\""); column++;
1028 (column != level*INDENT_MULT || column > 76)) {
1034 secu_PrintRawString(FILE *out, SECItem *si, const char *m, int level)
1036 secu_PrintRawStringQuotesOptional(out, si, m, level, PR_TRUE);
1040 SECU_PrintString(FILE *out, SECItem *si, char *m, int level)
1044 if (SECSuccess != SECU_StripTagAndLength(&my) || !my.len)
1046 secu_PrintRawString(out, &my, m, level);
1049 /* print an unencoded boolean */
1051 secu_PrintBoolean(FILE *out, SECItem *i, const char *m, int level)
1055 if ( i->data && i->len ) {
1062 SECU_Indent(out, level);
1063 fprintf(out, "%s: %s\n", m, (val ? "True" : "False"));
1067 * Format and print "time". If the tag message "m" is not NULL,
1068 * do indent formatting based on "level" and add a newline afterward;
1069 * otherwise just print the formatted time string only.
1072 secu_PrintTime(FILE *out, int64 time, char *m, int level)
1074 PRExplodedTime printableTime;
1077 /* Convert to local time */
1078 PR_ExplodeTime(time, PR_GMTParameters, &printableTime);
1080 timeString = PORT_Alloc(256);
1081 if (timeString == NULL)
1085 SECU_Indent(out, level);
1086 fprintf(out, "%s: ", m);
1089 if (PR_FormatTime(timeString, 256, "%a %b %d %H:%M:%S %Y", &printableTime)) {
1090 fputs(timeString, out);
1096 PORT_Free(timeString);
1100 * Format and print the UTC Time "t". If the tag message "m" is not NULL,
1101 * do indent formatting based on "level" and add a newline afterward;
1102 * otherwise just print the formatted time string only.
1105 SECU_PrintUTCTime(FILE *out, SECItem *t, char *m, int level)
1110 rv = DER_UTCTimeToTime(&time, t);
1111 if (rv != SECSuccess)
1114 secu_PrintTime(out, time, m, level);
1118 * Format and print the Generalized Time "t". If the tag message "m"
1119 * is not NULL, * do indent formatting based on "level" and add a newline
1120 * afterward; otherwise just print the formatted time string only.
1123 SECU_PrintGeneralizedTime(FILE *out, SECItem *t, char *m, int level)
1129 rv = DER_GeneralizedTimeToTime(&time, t);
1130 if (rv != SECSuccess)
1133 secu_PrintTime(out, time, m, level);
1137 * Format and print the UTC or Generalized Time "t". If the tag message
1138 * "m" is not NULL, do indent formatting based on "level" and add a newline
1139 * afterward; otherwise just print the formatted time string only.
1142 SECU_PrintTimeChoice(FILE *out, SECItem *t, char *m, int level)
1146 SECU_PrintUTCTime(out, t, m, level);
1149 case siGeneralizedTime:
1150 SECU_PrintGeneralizedTime(out, t, m, level);
1160 /* This prints a SET or SEQUENCE */
1162 SECU_PrintSet(FILE *out, SECItem *t, char *m, int level)
1164 int type = t->data[0] & SEC_ASN1_TAGNUM_MASK;
1165 int constructed = t->data[0] & SEC_ASN1_CONSTRUCTED;
1170 SECU_PrintAsHex(out, t, m, level);
1173 if (SECSuccess != SECU_StripTagAndLength(&my))
1176 SECU_Indent(out, level);
1178 fprintf(out, "%s: ", m);
1181 if (type == SEC_ASN1_SET)
1183 else if (type == SEC_ASN1_SEQUENCE)
1184 label = "Sequence ";
1187 fprintf(out,"%s{\n", label); /* } */
1189 while (my.len >= 2) {
1192 if (tmp.data[1] & 0x80) {
1194 unsigned int lenlen = tmp.data[1] & 0x7f;
1195 if (lenlen > sizeof tmp.len)
1198 for (i=0; i < lenlen; i++) {
1199 tmp.len = (tmp.len << 8) | tmp.data[2+i];
1201 tmp.len += lenlen + 2;
1203 tmp.len = tmp.data[1] + 2;
1205 if (tmp.len > my.len) {
1210 SECU_PrintAny(out, &tmp, NULL, level + 1);
1212 SECU_Indent(out, level); fprintf(out, /* { */ "}\n");
1216 secu_PrintContextSpecific(FILE *out, SECItem *i, char *m, int level)
1218 int type = i->data[0] & SEC_ASN1_TAGNUM_MASK;
1219 int constructed = i->data[0] & SEC_ASN1_CONSTRUCTED;
1225 m2 = PR_smprintf("[%d]", type);
1227 m2 = PR_smprintf("%s: [%d]", m, type);
1229 SECU_PrintSet(out, i, m2, level);
1230 PR_smprintf_free(m2);
1235 SECU_Indent(out, level);
1237 fprintf(out, "%s: ", m);
1239 fprintf(out,"[%d]\n", type);
1242 if (SECSuccess == SECU_StripTagAndLength(&tmp))
1243 SECU_PrintAsHex(out, &tmp, m, level+1);
1247 secu_PrintOctetString(FILE *out, SECItem *i, char *m, int level)
1250 if (SECSuccess == SECU_StripTagAndLength(&tmp))
1251 SECU_PrintAsHex(out, &tmp, m, level);
1255 secu_PrintBitString(FILE *out, SECItem *i, char *m, int level)
1260 if (SECSuccess != SECU_StripTagAndLength(&tmp) || tmp.len < 2)
1263 unused_bits = *tmp.data++;
1266 SECU_PrintAsHex(out, &tmp, m, level);
1268 SECU_Indent(out, level + 1);
1269 fprintf(out, "(%d least significant bits unused)\n", unused_bits);
1273 /* in a decoded bit string, the len member is a bit length. */
1275 secu_PrintDecodedBitString(FILE *out, SECItem *i, char *m, int level)
1281 unused_bits = (tmp.len & 0x7) ? 8 - (tmp.len & 7) : 0;
1282 DER_ConvertBitString(&tmp); /* convert length to byte length */
1284 SECU_PrintAsHex(out, &tmp, m, level);
1286 SECU_Indent(out, level + 1);
1287 fprintf(out, "(%d least significant bits unused)\n", unused_bits);
1292 /* Print a DER encoded Boolean */
1294 SECU_PrintEncodedBoolean(FILE *out, SECItem *i, char *m, int level)
1297 if (SECSuccess == SECU_StripTagAndLength(&my))
1298 secu_PrintBoolean(out, &my, m, level);
1301 /* Print a DER encoded integer */
1303 SECU_PrintEncodedInteger(FILE *out, SECItem *i, char *m, int level)
1306 if (SECSuccess == SECU_StripTagAndLength(&my))
1307 SECU_PrintInteger(out, &my, m, level);
1310 /* Print a DER encoded OID */
1312 SECU_PrintEncodedObjectID(FILE *out, SECItem *i, char *m, int level)
1315 if (SECSuccess == SECU_StripTagAndLength(&my))
1316 SECU_PrintObjectID(out, &my, m, level);
1320 secu_PrintBMPString(FILE *out, SECItem *i, char *m, int level)
1325 SECItem tmp = {0, 0, 0};
1328 if (SECSuccess != SECU_StripTagAndLength(&my))
1332 len = (int)(my.len / 2);
1333 tmp.data = (unsigned char *)PORT_Alloc(len);
1337 for (s = my.data, d = tmp.data ; len > 0; len--) {
1338 PRUint32 bmpChar = (s[0] << 8) | s[1]; s += 2;
1339 if (!isprint(bmpChar))
1341 *d++ = (unsigned char)bmpChar;
1343 secu_PrintRawString(out, &tmp, m, level);
1344 PORT_Free(tmp.data);
1348 SECU_PrintAsHex(out, i, m, level);
1350 PORT_Free(tmp.data);
1354 secu_PrintUniversalString(FILE *out, SECItem *i, char *m, int level)
1359 SECItem tmp = {0, 0, 0};
1362 if (SECSuccess != SECU_StripTagAndLength(&my))
1366 len = (int)(my.len / 4);
1367 tmp.data = (unsigned char *)PORT_Alloc(len);
1371 for (s = my.data, d = tmp.data ; len > 0; len--) {
1372 PRUint32 bmpChar = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
1374 if (!isprint(bmpChar))
1376 *d++ = (unsigned char)bmpChar;
1378 secu_PrintRawString(out, &tmp, m, level);
1379 PORT_Free(tmp.data);
1383 SECU_PrintAsHex(out, i, m, level);
1385 PORT_Free(tmp.data);
1389 secu_PrintUniversal(FILE *out, SECItem *i, char *m, int level)
1391 switch (i->data[0] & SEC_ASN1_TAGNUM_MASK) {
1392 case SEC_ASN1_ENUMERATED:
1393 case SEC_ASN1_INTEGER:
1394 SECU_PrintEncodedInteger(out, i, m, level);
1396 case SEC_ASN1_OBJECT_ID:
1397 SECU_PrintEncodedObjectID(out, i, m, level);
1399 case SEC_ASN1_BOOLEAN:
1400 SECU_PrintEncodedBoolean(out, i, m, level);
1402 case SEC_ASN1_UTF8_STRING:
1403 case SEC_ASN1_PRINTABLE_STRING:
1404 case SEC_ASN1_VISIBLE_STRING:
1405 case SEC_ASN1_IA5_STRING:
1406 case SEC_ASN1_T61_STRING:
1407 SECU_PrintString(out, i, m, level);
1409 case SEC_ASN1_GENERALIZED_TIME:
1410 SECU_PrintGeneralizedTime(out, i, m, level);
1412 case SEC_ASN1_UTC_TIME:
1413 SECU_PrintUTCTime(out, i, m, level);
1416 SECU_Indent(out, level);
1418 fprintf(out, "%s: NULL\n", m);
1420 fprintf(out, "NULL\n");
1423 case SEC_ASN1_SEQUENCE:
1424 SECU_PrintSet(out, i, m, level);
1426 case SEC_ASN1_OCTET_STRING:
1427 secu_PrintOctetString(out, i, m, level);
1429 case SEC_ASN1_BIT_STRING:
1430 secu_PrintBitString(out, i, m, level);
1432 case SEC_ASN1_BMP_STRING:
1433 secu_PrintBMPString(out, i, m, level);
1435 case SEC_ASN1_UNIVERSAL_STRING:
1436 secu_PrintUniversalString(out, i, m, level);
1439 SECU_PrintAsHex(out, i, m, level);
1445 SECU_PrintAny(FILE *out, SECItem *i, char *m, int level)
1447 if ( i && i->len && i->data ) {
1448 switch (i->data[0] & SEC_ASN1_CLASS_MASK) {
1449 case SEC_ASN1_CONTEXT_SPECIFIC:
1450 secu_PrintContextSpecific(out, i, m, level);
1452 case SEC_ASN1_UNIVERSAL:
1453 secu_PrintUniversal(out, i, m, level);
1456 SECU_PrintAsHex(out, i, m, level);
1463 secu_PrintValidity(FILE *out, CERTValidity *v, char *m, int level)
1465 SECU_Indent(out, level); fprintf(out, "%s:\n", m);
1466 SECU_PrintTimeChoice(out, &v->notBefore, "Not Before", level+1);
1467 SECU_PrintTimeChoice(out, &v->notAfter, "Not After ", level+1);
1471 /* This function does NOT expect a DER type and length. */
1473 SECU_PrintObjectID(FILE *out, SECItem *oid, char *m, int level)
1475 SECOidData *oiddata;
1476 char * oidString = NULL;
1478 oiddata = SECOID_FindOID(oid);
1479 if (oiddata != NULL) {
1480 const char *name = oiddata->desc;
1481 SECU_Indent(out, level);
1483 fprintf(out, "%s: ", m);
1484 fprintf(out, "%s\n", name);
1485 return oiddata->offset;
1487 oidString = CERT_GetOidString(oid);
1489 SECU_Indent(out, level);
1491 fprintf(out, "%s: ", m);
1492 fprintf(out, "%s\n", oidString);
1493 PR_smprintf_free(oidString);
1494 return SEC_OID_UNKNOWN;
1496 SECU_PrintAsHex(out, oid, m, level);
1497 return SEC_OID_UNKNOWN;
1500 typedef struct secuPBEParamsStr {
1502 SECItem iterationCount;
1504 SECAlgorithmID cipherAlg;
1505 SECAlgorithmID kdfAlg;
1508 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate);
1510 /* SECOID_PKCS5_PBKDF2 */
1511 const SEC_ASN1Template secuKDF2Params[] =
1513 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(secuPBEParams) },
1514 { SEC_ASN1_OCTET_STRING, offsetof(secuPBEParams, salt) },
1515 { SEC_ASN1_INTEGER, offsetof(secuPBEParams, iterationCount) },
1516 { SEC_ASN1_INTEGER, offsetof(secuPBEParams, keyLength) },
1517 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(secuPBEParams, kdfAlg),
1518 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
1522 /* PKCS5v1 & PKCS12 */
1523 const SEC_ASN1Template secuPBEParamsTemp[] =
1525 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(secuPBEParams) },
1526 { SEC_ASN1_OCTET_STRING, offsetof(secuPBEParams, salt) },
1527 { SEC_ASN1_INTEGER, offsetof(secuPBEParams, iterationCount) },
1531 /* SEC_OID_PKCS5_PBES2, SEC_OID_PKCS5_PBMAC1 */
1532 const SEC_ASN1Template secuPBEV2Params[] =
1534 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(secuPBEParams)},
1535 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(secuPBEParams, kdfAlg),
1536 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
1537 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(secuPBEParams, cipherAlg),
1538 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
1543 secu_PrintRSAPSSParams(FILE *out, SECItem *value, char *m, int level)
1545 PRArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1547 SECKEYRSAPSSParams param;
1548 SECAlgorithmID maskHashAlg;
1551 SECU_Indent(out, level);
1552 fprintf (out, "%s:\n", m);
1556 SECU_Indent(out, level);
1557 fprintf(out, "Out of memory\n");
1561 PORT_Memset(¶m, 0, sizeof param);
1563 rv = SEC_QuickDERDecodeItem(pool, ¶m,
1564 SEC_ASN1_GET(SECKEY_RSAPSSParamsTemplate),
1566 if (rv == SECSuccess) {
1567 if (!param.hashAlg) {
1568 SECU_Indent(out, level+1);
1569 fprintf(out, "Hash algorithm: default, SHA-1\n");
1571 SECU_PrintObjectID(out, ¶m.hashAlg->algorithm,
1572 "Hash algorithm", level+1);
1574 if (!param.maskAlg) {
1575 SECU_Indent(out, level+1);
1576 fprintf(out, "Mask algorithm: default, MGF1\n");
1577 SECU_Indent(out, level+1);
1578 fprintf(out, "Mask hash algorithm: default, SHA-1\n");
1580 SECU_PrintObjectID(out, ¶m.maskAlg->algorithm,
1581 "Mask algorithm", level+1);
1582 rv = SEC_QuickDERDecodeItem(pool, &maskHashAlg,
1583 SEC_ASN1_GET(SECOID_AlgorithmIDTemplate),
1584 ¶m.maskAlg->parameters);
1585 if (rv == SECSuccess) {
1586 SECU_PrintObjectID(out, &maskHashAlg.algorithm,
1587 "Mask hash algorithm", level+1);
1589 SECU_Indent(out, level+1);
1590 fprintf(out, "Invalid mask generation algorithm parameters\n");
1593 if (!param.saltLength.data) {
1594 SECU_Indent(out, level+1);
1595 fprintf(out, "Salt length: default, %i (0x%2X)\n", 20, 20);
1597 SECU_PrintInteger(out, ¶m.saltLength, "Salt Length", level+1);
1600 SECU_Indent(out, level+1);
1601 fprintf(out, "Invalid RSA-PSS parameters\n");
1603 PORT_FreeArena(pool, PR_FALSE);
1607 secu_PrintKDF2Params(FILE *out, SECItem *value, char *m, int level)
1609 PRArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1611 secuPBEParams param;
1614 SECU_Indent(out, level);
1615 fprintf (out, "%s:\n", m);
1619 SECU_Indent(out, level);
1620 fprintf(out, "Out of memory\n");
1624 PORT_Memset(¶m, 0, sizeof param);
1625 rv = SEC_QuickDERDecodeItem(pool, ¶m, secuKDF2Params, value);
1626 if (rv == SECSuccess) {
1627 SECU_PrintAsHex(out, ¶m.salt, "Salt", level+1);
1628 SECU_PrintInteger(out, ¶m.iterationCount, "Iteration Count",
1630 SECU_PrintInteger(out, ¶m.keyLength, "Key Length", level+1);
1631 SECU_PrintAlgorithmID(out, ¶m.kdfAlg, "KDF algorithm", level+1);
1633 PORT_FreeArena(pool, PR_FALSE);
1637 secu_PrintPKCS5V2Params(FILE *out, SECItem *value, char *m, int level)
1639 PRArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1641 secuPBEParams param;
1644 SECU_Indent(out, level);
1645 fprintf (out, "%s:\n", m);
1649 SECU_Indent(out, level);
1650 fprintf(out, "Out of memory\n");
1654 PORT_Memset(¶m, 0, sizeof param);
1655 rv = SEC_QuickDERDecodeItem(pool, ¶m, secuPBEV2Params, value);
1656 if (rv == SECSuccess) {
1657 SECU_PrintAlgorithmID(out, ¶m.kdfAlg, "KDF", level+1);
1658 SECU_PrintAlgorithmID(out, ¶m.cipherAlg, "Cipher", level+1);
1660 PORT_FreeArena(pool, PR_FALSE);
1664 secu_PrintPBEParams(FILE *out, SECItem *value, char *m, int level)
1666 PRArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
1668 secuPBEParams param;
1671 SECU_Indent(out, level);
1672 fprintf (out, "%s:\n", m);
1676 SECU_Indent(out, level);
1677 fprintf(out, "Out of memory\n");
1681 PORT_Memset(¶m, 0, sizeof(secuPBEParams));
1682 rv = SEC_QuickDERDecodeItem(pool, ¶m, secuPBEParamsTemp, value);
1683 if (rv == SECSuccess) {
1684 SECU_PrintAsHex(out, ¶m.salt, "Salt", level+1);
1685 SECU_PrintInteger(out, ¶m.iterationCount, "Iteration Count",
1688 PORT_FreeArena(pool, PR_FALSE);
1691 /* This function does NOT expect a DER type and length. */
1693 SECU_PrintAlgorithmID(FILE *out, SECAlgorithmID *a, char *m, int level)
1696 SECU_PrintObjectID(out, &a->algorithm, m, level);
1698 algtag = SECOID_GetAlgorithmTag(a);
1699 if (SEC_PKCS5IsAlgorithmPBEAlgTag(algtag)) {
1701 case SEC_OID_PKCS5_PBKDF2:
1702 secu_PrintKDF2Params(out, &a->parameters, "Parameters", level+1);
1704 case SEC_OID_PKCS5_PBES2:
1705 secu_PrintPKCS5V2Params(out, &a->parameters, "Encryption", level+1);
1707 case SEC_OID_PKCS5_PBMAC1:
1708 secu_PrintPKCS5V2Params(out, &a->parameters, "MAC", level+1);
1711 secu_PrintPBEParams(out, &a->parameters, "Parameters", level+1);
1717 if (algtag == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
1718 secu_PrintRSAPSSParams(out, &a->parameters, "Parameters", level+1);
1722 if (a->parameters.len == 0
1723 || (a->parameters.len == 2
1724 && PORT_Memcmp(a->parameters.data, "\005\000", 2) == 0)) {
1725 /* No arguments or NULL argument */
1727 /* Print args to algorithm */
1728 SECU_PrintAsHex(out, &a->parameters, "Args", level+1);
1733 secu_PrintAttribute(FILE *out, SEC_PKCS7Attribute *attr, char *m, int level)
1740 SECU_Indent(out, level); fprintf(out, "%s:\n", m);
1744 * Should make this smarter; look at the type field and then decode
1745 * and print the value(s) appropriately!
1747 SECU_PrintObjectID(out, &(attr->type), "Type", level+1);
1748 if (attr->values != NULL) {
1750 while ((value = attr->values[i++]) != NULL) {
1751 sprintf(om, "Value (%d)%s", i, attr->encoded ? " (encoded)" : "");
1752 if (attr->encoded || attr->typeTag == NULL) {
1753 SECU_PrintAny(out, value, om, level+1);
1755 switch (attr->typeTag->offset) {
1757 SECU_PrintAsHex(out, value, om, level+1);
1759 case SEC_OID_PKCS9_CONTENT_TYPE:
1760 SECU_PrintObjectID(out, value, om, level+1);
1762 case SEC_OID_PKCS9_SIGNING_TIME:
1763 SECU_PrintTimeChoice(out, value, om, level+1);
1772 secu_PrintRSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level)
1775 SECU_Indent(out, level); fprintf(out, "%s:\n", m);
1776 SECU_PrintInteger(out, &pk->u.rsa.modulus, "Modulus", level+1);
1777 SECU_PrintInteger(out, &pk->u.rsa.publicExponent, "Exponent", level+1);
1778 if (pk->u.rsa.publicExponent.len == 1 &&
1779 pk->u.rsa.publicExponent.data[0] == 1) {
1780 SECU_Indent(out, level +1); fprintf(out, "Error: INVALID RSA KEY!\n");
1785 secu_PrintDSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level)
1787 SECU_Indent(out, level); fprintf(out, "%s:\n", m);
1788 SECU_PrintInteger(out, &pk->u.dsa.params.prime, "Prime", level+1);
1789 SECU_PrintInteger(out, &pk->u.dsa.params.subPrime, "Subprime", level+1);
1790 SECU_PrintInteger(out, &pk->u.dsa.params.base, "Base", level+1);
1791 SECU_PrintInteger(out, &pk->u.dsa.publicValue, "PublicValue", level+1);
1794 #ifdef NSS_ENABLE_ECC
1796 secu_PrintECPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level)
1798 SECItem curveOID = { siBuffer, NULL, 0};
1800 SECU_Indent(out, level); fprintf(out, "%s:\n", m);
1801 SECU_PrintInteger(out, &pk->u.ec.publicValue, "PublicValue", level+1);
1802 /* For named curves, the DEREncodedParams field contains an
1803 * ASN Object ID (0x06 is SEC_ASN1_OBJECT_ID).
1805 if ((pk->u.ec.DEREncodedParams.len > 2) &&
1806 (pk->u.ec.DEREncodedParams.data[0] == 0x06)) {
1807 curveOID.len = pk->u.ec.DEREncodedParams.data[1];
1808 curveOID.data = pk->u.ec.DEREncodedParams.data + 2;
1809 SECU_PrintObjectID(out, &curveOID, "Curve", level +1);
1812 #endif /* NSS_ENABLE_ECC */
1815 secu_PrintSubjectPublicKeyInfo(FILE *out, PRArenaPool *arena,
1816 CERTSubjectPublicKeyInfo *i, char *msg, int level)
1818 SECKEYPublicKey *pk;
1820 SECU_Indent(out, level); fprintf(out, "%s:\n", msg);
1821 SECU_PrintAlgorithmID(out, &i->algorithm, "Public Key Algorithm", level+1);
1823 pk = SECKEY_ExtractPublicKey(i);
1825 switch (pk->keyType) {
1827 secu_PrintRSAPublicKey(out, pk, "RSA Public Key", level +1);
1831 secu_PrintDSAPublicKey(out, pk, "DSA Public Key", level +1);
1834 #ifdef NSS_ENABLE_ECC
1836 secu_PrintECPublicKey(out, pk, "EC Public Key", level +1);
1843 SECU_Indent(out, level);
1844 fprintf(out, "unable to format this SPKI algorithm type\n");
1847 SECU_Indent(out, level);
1848 fprintf(out, "unknown SPKI algorithm type\n");
1851 PORT_FreeArena(pk->arena, PR_FALSE);
1853 SECU_PrintErrMsg(out, level, "Error", "Parsing public key");
1855 if (i->subjectPublicKey.data) {
1856 SECU_PrintAny(out, &i->subjectPublicKey, "Raw", level);
1862 secu_PrintX509InvalidDate(FILE *out, SECItem *value, char *msg, int level)
1864 SECItem decodedValue;
1867 char *formattedTime = NULL;
1869 decodedValue.data = NULL;
1870 rv = SEC_ASN1DecodeItem (NULL, &decodedValue,
1871 SEC_ASN1_GET(SEC_GeneralizedTimeTemplate),
1873 if (rv == SECSuccess) {
1874 rv = DER_GeneralizedTimeToTime(&invalidTime, &decodedValue);
1875 if (rv == SECSuccess) {
1876 formattedTime = CERT_GenTime2FormattedAscii
1877 (invalidTime, "%a %b %d %H:%M:%S %Y");
1878 SECU_Indent(out, level +1);
1879 fprintf (out, "%s: %s\n", msg, formattedTime);
1880 PORT_Free (formattedTime);
1883 PORT_Free (decodedValue.data);
1888 PrintExtKeyUsageExtension (FILE *out, SECItem *value, char *msg, int level)
1890 CERTOidSequence *os;
1893 os = CERT_DecodeOidSequence(value);
1894 if( (CERTOidSequence *)NULL == os ) {
1898 for( op = os->oids; *op; op++ ) {
1899 SECU_PrintObjectID(out, *op, msg, level + 1);
1901 CERT_DestroyOidSequence(os);
1906 secu_PrintBasicConstraints(FILE *out, SECItem *value, char *msg, int level) {
1907 CERTBasicConstraints constraints;
1910 SECU_Indent(out, level);
1912 fprintf(out,"%s: ",msg);
1914 rv = CERT_DecodeBasicConstraintValue(&constraints,value);
1915 if (rv == SECSuccess && constraints.isCA) {
1916 if (constraints.pathLenConstraint >= 0) {
1917 fprintf(out,"Is a CA with a maximum path length of %d.\n",
1918 constraints.pathLenConstraint);
1920 fprintf(out,"Is a CA with no maximum path length.\n");
1923 fprintf(out,"Is not a CA.\n");
1928 static const char * const nsTypeBits[] = {
1939 /* NSCertType is merely a bit string whose bits are displayed symbolically */
1941 secu_PrintNSCertType(FILE *out, SECItem *value, char *msg, int level)
1947 SECItem my = *value;
1949 if ((my.data[0] != SEC_ASN1_BIT_STRING) ||
1950 SECSuccess != SECU_StripTagAndLength(&my)) {
1951 SECU_PrintAny(out, value, "Data", level);
1955 unused = (my.len == 2) ? (my.data[0] & 0x0f) : 0;
1956 NS_Type = my.data[1] & (0xff << unused);
1959 SECU_Indent(out, level);
1961 fprintf(out,"%s: ",msg);
1963 fprintf(out,"Netscape Certificate Type: ");
1965 for (i=0; i < 8; i++) {
1966 if ( (0x80 >> i) & NS_Type) {
1967 fprintf(out, "%c%s", (found ? ',' : '<'), nsTypeBits[i]);
1971 fprintf(out, (found ? ">\n" : "none\n"));
1975 static const char * const usageBits[] = {
1976 "Digital Signature", /* 0x80 */
1977 "Non-Repudiation", /* 0x40 */
1978 "Key Encipherment", /* 0x20 */
1979 "Data Encipherment", /* 0x10 */
1980 "Key Agreement", /* 0x08 */
1981 "Certificate Signing", /* 0x04 */
1982 "CRL Signing", /* 0x02 */
1983 "Encipher Only", /* 0x01 */
1984 "Decipher Only", /* 0x0080 */
1988 /* X509KeyUsage is merely a bit string whose bits are displayed symbolically */
1990 secu_PrintX509KeyUsage(FILE *out, SECItem *value, char *msg, int level)
1996 SECItem my = *value;
1998 if ((my.data[0] != SEC_ASN1_BIT_STRING) ||
1999 SECSuccess != SECU_StripTagAndLength(&my)) {
2000 SECU_PrintAny(out, value, "Data", level);
2004 unused = (my.len >= 2) ? (my.data[0] & 0x0f) : 0;
2005 usage = (my.len == 2) ? (my.data[1] & (0xff << unused)) << 8
2006 : (my.data[1] << 8) |
2007 (my.data[2] & (0xff << unused));
2009 SECU_Indent(out, level);
2010 fprintf(out, "Usages: ");
2011 for (i=0; usageBits[i]; i++) {
2012 if ( (0x8000 >> i) & usage) {
2014 SECU_Indent(out, level + 2);
2015 fprintf(out, "%s\n", usageBits[i]);
2020 fprintf(out, "(none)\n");
2025 secu_PrintIPAddress(FILE *out, SECItem *value, char *msg, int level)
2031 memset(&addr, 0, sizeof addr);
2032 if (value->len == 4) {
2033 addr.inet.family = PR_AF_INET;
2034 memcpy(&addr.inet.ip, value->data, value->len);
2035 } else if (value->len == 16) {
2036 addr.ipv6.family = PR_AF_INET6;
2037 memcpy(addr.ipv6.ip.pr_s6_addr, value->data, value->len);
2038 if (PR_IsNetAddrType(&addr, PR_IpAddrV4Mapped)) {
2039 /* convert to IPv4. */
2040 addr.inet.family = PR_AF_INET;
2041 memcpy(&addr.inet.ip, &addr.ipv6.ip.pr_s6_addr[12], 4);
2042 memset(&addr.inet.pad[0], 0, sizeof addr.inet.pad);
2048 st = PR_NetAddrToString(&addr, addrBuf, sizeof addrBuf);
2049 if (st == PR_SUCCESS) {
2050 SECU_Indent(out, level);
2051 fprintf(out, "%s: %s\n", msg, addrBuf);
2054 SECU_PrintAsHex(out, value, msg, level);
2060 secu_PrintGeneralName(FILE *out, CERTGeneralName *gname, char *msg, int level)
2063 if (msg && msg[0]) {
2064 SECU_Indent(out, level++); fprintf(out, "%s: \n", msg);
2066 switch (gname->type) {
2067 case certOtherName :
2068 SECU_PrintAny( out, &gname->name.OthName.name, "Other Name", level);
2069 SECU_PrintObjectID(out, &gname->name.OthName.oid, "OID", level+1);
2071 case certDirectoryName :
2072 SECU_PrintName(out, &gname->name.directoryName, "Directory Name", level);
2074 case certRFC822Name :
2075 secu_PrintRawString( out, &gname->name.other, "RFC822 Name", level);
2078 secu_PrintRawString( out, &gname->name.other, "DNS name", level);
2081 secu_PrintRawString( out, &gname->name.other, "URI", level);
2083 case certIPAddress :
2084 secu_PrintIPAddress(out, &gname->name.other, "IP Address", level);
2086 case certRegisterID :
2087 SECU_PrintObjectID( out, &gname->name.other, "Registered ID", level);
2089 case certX400Address :
2090 SECU_PrintAny( out, &gname->name.other, "X400 Address", level);
2092 case certEDIPartyName :
2093 SECU_PrintAny( out, &gname->name.other, "EDI Party", level);
2096 PR_snprintf(label, sizeof label, "unknown type [%d]",
2097 (int)gname->type - 1);
2098 SECU_PrintAsHex(out, &gname->name.other, label, level);
2104 secu_PrintGeneralNames(FILE *out, CERTGeneralName *gname, char *msg, int level)
2106 CERTGeneralName *name = gname;
2108 secu_PrintGeneralName(out, name, msg, level);
2109 name = CERT_GetNextGeneralName(name);
2110 } while (name && name != gname);
2115 secu_PrintAuthKeyIDExtension(FILE *out, SECItem *value, char *msg, int level)
2117 CERTAuthKeyID *kid = NULL;
2118 PLArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2121 SECU_PrintError("Error", "Allocating new ArenaPool");
2124 kid = CERT_DecodeAuthKeyID(pool, value);
2126 SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
2127 SECU_PrintAny(out, value, "Data", level);
2129 int keyIDPresent = (kid->keyID.data && kid->keyID.len);
2130 int issuerPresent = kid->authCertIssuer != NULL;
2131 int snPresent = (kid->authCertSerialNumber.data &&
2132 kid->authCertSerialNumber.len);
2135 SECU_PrintAsHex(out, &kid->keyID, "Key ID", level);
2137 secu_PrintGeneralName(out, kid->authCertIssuer, "Issuer", level);
2139 SECU_PrintInteger(out, &kid->authCertSerialNumber,
2140 "Serial Number", level);
2142 PORT_FreeArena(pool, PR_FALSE);
2147 secu_PrintAltNameExtension(FILE *out, SECItem *value, char *msg, int level)
2149 CERTGeneralName * nameList;
2150 CERTGeneralName * current;
2151 PLArenaPool * pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2154 SECU_PrintError("Error", "Allocating new ArenaPool");
2157 nameList = current = CERT_DecodeAltNameExtension(pool, value);
2159 if (PORT_GetError() == SEC_ERROR_EXTENSION_NOT_FOUND) {
2160 /* Decoder found empty sequence, which is invalid. */
2161 PORT_SetError(SEC_ERROR_EXTENSION_VALUE_INVALID);
2163 SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
2164 SECU_PrintAny(out, value, "Data", level);
2167 secu_PrintGeneralName(out, current, msg, level);
2168 current = CERT_GetNextGeneralName(current);
2169 } while (current != nameList);
2171 PORT_FreeArena(pool, PR_FALSE);
2175 secu_PrintCRLDistPtsExtension(FILE *out, SECItem *value, char *msg, int level)
2177 CERTCrlDistributionPoints * dPoints;
2178 PLArenaPool * pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2181 SECU_PrintError("Error", "Allocating new ArenaPool");
2184 dPoints = CERT_DecodeCRLDistributionPoints(pool, value);
2185 if (dPoints && dPoints->distPoints && dPoints->distPoints[0]) {
2186 CRLDistributionPoint ** pPoints = dPoints->distPoints;
2187 CRLDistributionPoint * pPoint;
2188 while (NULL != (pPoint = *pPoints++)) {
2189 SECU_Indent(out, level); fputs("Distribution point:\n", out);
2190 if (pPoint->distPointType == generalName &&
2191 pPoint->distPoint.fullName != NULL) {
2192 secu_PrintGeneralNames(out, pPoint->distPoint.fullName, NULL,
2194 } else if (pPoint->distPointType == relativeDistinguishedName &&
2195 pPoint->distPoint.relativeName.avas) {
2196 SECU_PrintRDN(out, &pPoint->distPoint.relativeName, "RDN",
2198 } else if (pPoint->derDistPoint.data) {
2199 SECU_PrintAny(out, &pPoint->derDistPoint, "Point", level + 1);
2201 if (pPoint->reasons.data) {
2202 secu_PrintDecodedBitString(out, &pPoint->reasons, "Reasons",
2205 if (pPoint->crlIssuer) {
2206 secu_PrintGeneralName(out, pPoint->crlIssuer, "CRL issuer",
2211 SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
2212 SECU_PrintAny(out, value, "Data", level);
2214 PORT_FreeArena(pool, PR_FALSE);
2219 secu_PrintNameConstraintSubtree(FILE *out, CERTNameConstraint *value,
2220 char *msg, int level)
2222 CERTNameConstraint *head = value;
2223 SECU_Indent(out, level); fprintf(out, "%s Subtree:\n", msg);
2226 secu_PrintGeneralName(out, &value->name, NULL, level);
2227 if (value->min.data)
2228 SECU_PrintInteger(out, &value->min, "Minimum", level+1);
2229 if (value->max.data)
2230 SECU_PrintInteger(out, &value->max, "Maximum", level+1);
2231 value = CERT_GetNextNameConstraint(value);
2232 } while (value != head);
2236 secu_PrintNameConstraintsExtension(FILE *out, SECItem *value, char *msg, int level)
2238 CERTNameConstraints * cnstrnts;
2239 PLArenaPool * pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2242 SECU_PrintError("Error", "Allocating new ArenaPool");
2245 cnstrnts = CERT_DecodeNameConstraintsExtension(pool, value);
2247 SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
2248 SECU_PrintAny(out, value, "Raw", level);
2250 if (cnstrnts->permited)
2251 secu_PrintNameConstraintSubtree(out, cnstrnts->permited,
2252 "Permitted", level);
2253 if (cnstrnts->excluded)
2254 secu_PrintNameConstraintSubtree(out, cnstrnts->excluded,
2257 PORT_FreeArena(pool, PR_FALSE);
2262 secu_PrintAuthorityInfoAcess(FILE *out, SECItem *value, char *msg, int level)
2264 CERTAuthInfoAccess **infos = NULL;
2265 PLArenaPool * pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2268 SECU_PrintError("Error", "Allocating new ArenaPool");
2271 infos = CERT_DecodeAuthInfoAccessExtension(pool, value);
2273 SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
2274 SECU_PrintAny(out, value, "Raw", level);
2276 CERTAuthInfoAccess *info;
2277 while (NULL != (info = *infos++)) {
2278 if (info->method.data) {
2279 SECU_PrintObjectID(out, &info->method, "Method", level);
2281 SECU_Indent(out,level);
2282 fprintf(out, "Error: missing method\n");
2284 if (info->location) {
2285 secu_PrintGeneralName(out, info->location, "Location", level);
2287 SECU_PrintAny(out, &info->derLocation, "Location", level);
2291 PORT_FreeArena(pool, PR_FALSE);
2296 SECU_PrintExtensions(FILE *out, CERTCertExtension **extensions,
2297 char *msg, int level)
2303 SECU_Indent(out, level++); fprintf(out, "%s:\n", msg);
2306 while ( *extensions ) {
2309 tmpitem = &(*extensions)->id;
2310 SECU_PrintObjectID(out, tmpitem, "Name", level);
2312 tmpitem = &(*extensions)->critical;
2313 if ( tmpitem->len ) {
2314 secu_PrintBoolean(out, tmpitem, "Critical", level);
2317 oidTag = SECOID_FindOIDTag (&((*extensions)->id));
2318 tmpitem = &((*extensions)->value);
2321 case SEC_OID_X509_INVALID_DATE:
2322 case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_TIME:
2323 secu_PrintX509InvalidDate(out, tmpitem, "Date", level );
2325 case SEC_OID_X509_CERTIFICATE_POLICIES:
2326 SECU_PrintPolicy(out, tmpitem, "Data", level );
2328 case SEC_OID_NS_CERT_EXT_BASE_URL:
2329 case SEC_OID_NS_CERT_EXT_REVOCATION_URL:
2330 case SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL:
2331 case SEC_OID_NS_CERT_EXT_CA_CRL_URL:
2332 case SEC_OID_NS_CERT_EXT_CA_CERT_URL:
2333 case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL:
2334 case SEC_OID_NS_CERT_EXT_CA_POLICY_URL:
2335 case SEC_OID_NS_CERT_EXT_HOMEPAGE_URL:
2336 case SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL:
2337 case SEC_OID_OCSP_RESPONDER:
2338 SECU_PrintString(out,tmpitem, "URL", level);
2340 case SEC_OID_NS_CERT_EXT_COMMENT:
2341 SECU_PrintString(out,tmpitem, "Comment", level);
2343 case SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME:
2344 SECU_PrintString(out,tmpitem, "ServerName", level);
2346 case SEC_OID_NS_CERT_EXT_CERT_TYPE:
2347 secu_PrintNSCertType(out,tmpitem,"Data",level);
2349 case SEC_OID_X509_BASIC_CONSTRAINTS:
2350 secu_PrintBasicConstraints(out,tmpitem,"Data",level);
2352 case SEC_OID_X509_EXT_KEY_USAGE:
2353 PrintExtKeyUsageExtension(out, tmpitem, NULL, level);
2355 case SEC_OID_X509_KEY_USAGE:
2356 secu_PrintX509KeyUsage(out, tmpitem, NULL, level );
2358 case SEC_OID_X509_AUTH_KEY_ID:
2359 secu_PrintAuthKeyIDExtension(out, tmpitem, NULL, level );
2361 case SEC_OID_X509_SUBJECT_ALT_NAME:
2362 case SEC_OID_X509_ISSUER_ALT_NAME:
2363 secu_PrintAltNameExtension(out, tmpitem, NULL, level );
2365 case SEC_OID_X509_CRL_DIST_POINTS:
2366 secu_PrintCRLDistPtsExtension(out, tmpitem, NULL, level );
2368 case SEC_OID_X509_PRIVATE_KEY_USAGE_PERIOD:
2369 SECU_PrintPrivKeyUsagePeriodExtension(out, tmpitem, NULL,
2372 case SEC_OID_X509_NAME_CONSTRAINTS:
2373 secu_PrintNameConstraintsExtension(out, tmpitem, NULL, level);
2375 case SEC_OID_X509_AUTH_INFO_ACCESS:
2376 secu_PrintAuthorityInfoAcess(out, tmpitem, NULL, level);
2379 case SEC_OID_X509_CRL_NUMBER:
2380 case SEC_OID_X509_REASON_CODE:
2383 case SEC_OID_PKIX_OCSP:
2384 case SEC_OID_PKIX_OCSP_BASIC_RESPONSE:
2385 case SEC_OID_PKIX_OCSP_NONCE:
2386 case SEC_OID_PKIX_OCSP_CRL:
2387 case SEC_OID_PKIX_OCSP_RESPONSE:
2388 case SEC_OID_PKIX_OCSP_NO_CHECK:
2389 case SEC_OID_PKIX_OCSP_ARCHIVE_CUTOFF:
2390 case SEC_OID_PKIX_OCSP_SERVICE_LOCATOR:
2391 case SEC_OID_PKIX_REGCTRL_REGTOKEN:
2392 case SEC_OID_PKIX_REGCTRL_AUTHENTICATOR:
2393 case SEC_OID_PKIX_REGCTRL_PKIPUBINFO:
2394 case SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS:
2395 case SEC_OID_PKIX_REGCTRL_OLD_CERT_ID:
2396 case SEC_OID_PKIX_REGCTRL_PROTOCOL_ENC_KEY:
2397 case SEC_OID_PKIX_REGINFO_UTF8_PAIRS:
2398 case SEC_OID_PKIX_REGINFO_CERT_REQUEST:
2400 /* Netscape extension OIDs. */
2401 case SEC_OID_NS_CERT_EXT_NETSCAPE_OK:
2402 case SEC_OID_NS_CERT_EXT_ISSUER_LOGO:
2403 case SEC_OID_NS_CERT_EXT_SUBJECT_LOGO:
2404 case SEC_OID_NS_CERT_EXT_ENTITY_LOGO:
2405 case SEC_OID_NS_CERT_EXT_USER_PICTURE:
2407 /* x.509 v3 Extensions */
2408 case SEC_OID_X509_SUBJECT_DIRECTORY_ATTR:
2409 case SEC_OID_X509_SUBJECT_KEY_ID:
2410 case SEC_OID_X509_POLICY_MAPPINGS:
2411 case SEC_OID_X509_POLICY_CONSTRAINTS:
2415 SECU_PrintAny(out, tmpitem, "Data", level);
2425 /* An RDN is a subset of a DirectoryName, and we already know how to
2426 * print those, so make a directory name out of the RDN, and print it.
2429 SECU_PrintRDN(FILE *out, CERTRDN *rdn, const char *msg, int level)
2438 SECU_PrintName(out, &name, msg, level);
2442 SECU_PrintNameQuotesOptional(FILE *out, CERTName *name, const char *msg,
2443 int level, PRBool quotes)
2445 char *nameStr = NULL;
2450 PORT_SetError(SEC_ERROR_INVALID_ARGS);
2453 if (!name->rdns || !name->rdns[0]) {
2456 str = nameStr = CERT_NameToAscii(name);
2459 str = "!Invalid AVA!";
2461 my.data = (unsigned char *)str;
2462 my.len = PORT_Strlen(str);
2464 secu_PrintRawStringQuotesOptional(out, &my, msg, level, quotes);
2466 SECU_Indent(out, level); fprintf(out, "%s: ", msg);
2474 SECU_PrintName(FILE *out, CERTName *name, const char *msg, int level)
2476 SECU_PrintNameQuotesOptional(out, name, msg, level, PR_TRUE);
2480 printflags(char *trusts, unsigned int flags)
2482 if (flags & CERTDB_VALID_CA)
2483 if (!(flags & CERTDB_TRUSTED_CA) &&
2484 !(flags & CERTDB_TRUSTED_CLIENT_CA))
2485 PORT_Strcat(trusts, "c");
2486 if (flags & CERTDB_TERMINAL_RECORD)
2487 if (!(flags & CERTDB_TRUSTED))
2488 PORT_Strcat(trusts, "p");
2489 if (flags & CERTDB_TRUSTED_CA)
2490 PORT_Strcat(trusts, "C");
2491 if (flags & CERTDB_TRUSTED_CLIENT_CA)
2492 PORT_Strcat(trusts, "T");
2493 if (flags & CERTDB_TRUSTED)
2494 PORT_Strcat(trusts, "P");
2495 if (flags & CERTDB_USER)
2496 PORT_Strcat(trusts, "u");
2497 if (flags & CERTDB_SEND_WARN)
2498 PORT_Strcat(trusts, "w");
2499 if (flags & CERTDB_INVISIBLE_CA)
2500 PORT_Strcat(trusts, "I");
2501 if (flags & CERTDB_GOVT_APPROVED_CA)
2502 PORT_Strcat(trusts, "G");
2506 /* callback for listing certs through pkcs11 */
2508 SECU_PrintCertNickname(CERTCertListNode *node, void *data)
2510 CERTCertTrust *trust;
2511 CERTCertificate* cert;
2518 PORT_Memset (trusts, 0, sizeof (trusts));
2521 name = node->appData;
2522 if (!name || !name[0]) {
2523 name = cert->nickname;
2525 if (!name || !name[0]) {
2526 name = cert->emailAddr;
2528 if (!name || !name[0]) {
2532 trust = cert->trust;
2534 printflags(trusts, trust->sslFlags);
2535 PORT_Strcat(trusts, ",");
2536 printflags(trusts, trust->emailFlags);
2537 PORT_Strcat(trusts, ",");
2538 printflags(trusts, trust->objectSigningFlags);
2540 PORT_Memcpy(trusts,",,",3);
2542 fprintf(out, "%-60s %-5s\n", name, trusts);
2544 return (SECSuccess);
2548 SECU_DecodeAndPrintExtensions(FILE *out, SECItem *any, char *m, int level)
2550 CERTCertExtension **extensions = NULL;
2551 PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2555 return SEC_ERROR_NO_MEMORY;
2557 rv = SEC_QuickDERDecodeItem(arena, &extensions,
2558 SEC_ASN1_GET(CERT_SequenceOfCertExtensionTemplate), any);
2560 SECU_PrintExtensions(out, extensions, m, level);
2562 SECU_PrintAny(out, any, m, level);
2563 PORT_FreeArena(arena, PR_FALSE);
2567 /* print a decoded SET OF or SEQUENCE OF Extensions */
2569 SECU_PrintSetOfExtensions(FILE *out, SECItem **any, char *m, int level)
2573 SECU_Indent(out, level++); fprintf(out, "%s:\n", m);
2575 while (any && any[0]) {
2576 rv |= SECU_DecodeAndPrintExtensions(out, any[0], "", level);
2582 /* print a decoded SET OF or SEQUENCE OF "ANY" */
2584 SECU_PrintSetOfAny(FILE *out, SECItem **any, char *m, int level)
2588 SECU_Indent(out, level++); fprintf(out, "%s:\n", m);
2590 while (any && any[0]) {
2591 SECU_PrintAny(out, any[0], "", level);
2598 SECU_PrintCertAttribute(FILE *out, CERTAttribute *attr, char *m, int level)
2602 tag = SECU_PrintObjectID(out, &attr->attrType, "Attribute Type", level);
2603 if (tag == SEC_OID_PKCS9_EXTENSION_REQUEST) {
2604 rv = SECU_PrintSetOfExtensions(out, attr->attrValue, "Extensions", level);
2606 rv = SECU_PrintSetOfAny(out, attr->attrValue, "Attribute Values", level);
2612 SECU_PrintCertAttributes(FILE *out, CERTAttribute **attrs, char *m, int level)
2616 rv |= SECU_PrintCertAttribute(out, attrs[0], m, level+1);
2622 int /* sometimes a PRErrorCode, other times a SECStatus. Sigh. */
2623 SECU_PrintCertificateRequest(FILE *out, SECItem *der, char *m, int level)
2625 PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2626 CERTCertificateRequest *cr;
2627 int rv = SEC_ERROR_NO_MEMORY;
2632 /* Decode certificate request */
2633 cr = PORT_ArenaZNew(arena, CERTCertificateRequest);
2637 rv = SEC_QuickDERDecodeItem(arena, cr,
2638 SEC_ASN1_GET(CERT_CertificateRequestTemplate), der);
2642 /* Pretty print it out */
2643 SECU_Indent(out, level); fprintf(out, "%s:\n", m);
2644 SECU_PrintInteger(out, &cr->version, "Version", level+1);
2645 SECU_PrintName(out, &cr->subject, "Subject", level+1);
2646 secu_PrintSubjectPublicKeyInfo(out, arena, &cr->subjectPublicKeyInfo,
2647 "Subject Public Key Info", level+1);
2649 SECU_PrintCertAttributes(out, cr->attributes, "Attributes", level+1);
2652 PORT_FreeArena(arena, PR_FALSE);
2657 SECU_PrintCertificate(FILE *out, SECItem *der, char *m, int level)
2659 PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2661 int rv = SEC_ERROR_NO_MEMORY;
2667 /* Decode certificate */
2668 c = PORT_ArenaZNew(arena, CERTCertificate);
2672 rv = SEC_ASN1DecodeItem(arena, c,
2673 SEC_ASN1_GET(CERT_CertificateTemplate), der);
2675 SECU_Indent(out, level);
2676 SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
2677 SECU_PrintAny(out, der, "Raw", level);
2680 /* Pretty print it out */
2681 SECU_Indent(out, level); fprintf(out, "%s:\n", m);
2682 iv = c->version.len ? DER_GetInteger(&c->version) : 0; /* version is optional */
2683 SECU_Indent(out, level+1); fprintf(out, "%s: %d (0x%x)\n", "Version", iv + 1, iv);
2685 SECU_PrintInteger(out, &c->serialNumber, "Serial Number", level+1);
2686 SECU_PrintAlgorithmID(out, &c->signature, "Signature Algorithm", level+1);
2687 SECU_PrintName(out, &c->issuer, "Issuer", level+1);
2688 secu_PrintValidity(out, &c->validity, "Validity", level+1);
2689 SECU_PrintName(out, &c->subject, "Subject", level+1);
2690 secu_PrintSubjectPublicKeyInfo(out, arena, &c->subjectPublicKeyInfo,
2691 "Subject Public Key Info", level+1);
2692 if (c->issuerID.data)
2693 secu_PrintDecodedBitString(out, &c->issuerID, "Issuer Unique ID", level+1);
2694 if (c->subjectID.data)
2695 secu_PrintDecodedBitString(out, &c->subjectID, "Subject Unique ID", level+1);
2696 SECU_PrintExtensions(out, c->extensions, "Signed Extensions", level+1);
2698 PORT_FreeArena(arena, PR_FALSE);
2703 SECU_PrintRSAPublicKey(FILE *out, SECItem *der, char *m, int level)
2705 PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2706 SECKEYPublicKey key;
2707 int rv = SEC_ERROR_NO_MEMORY;
2712 PORT_Memset(&key, 0, sizeof(key));
2713 rv = SEC_ASN1DecodeItem(arena, &key,
2714 SEC_ASN1_GET(SECKEY_RSAPublicKeyTemplate), der);
2716 /* Pretty print it out */
2717 secu_PrintRSAPublicKey(out, &key, m, level);
2720 PORT_FreeArena(arena, PR_FALSE);
2725 SECU_PrintSubjectPublicKeyInfo(FILE *out, SECItem *der, char *m, int level)
2727 PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2728 int rv = SEC_ERROR_NO_MEMORY;
2729 CERTSubjectPublicKeyInfo spki;
2734 PORT_Memset(&spki, 0, sizeof spki);
2735 rv = SEC_ASN1DecodeItem(arena, &spki,
2736 SEC_ASN1_GET(CERT_SubjectPublicKeyInfoTemplate),
2740 SECU_Indent(out, level); fprintf(out, "%s:\n", m);
2742 secu_PrintSubjectPublicKeyInfo(out, arena, &spki,
2743 "Subject Public Key Info", level+1);
2746 PORT_FreeArena(arena, PR_FALSE);
2750 #ifdef HAVE_EPV_TEMPLATE
2752 SECU_PrintPrivateKey(FILE *out, SECItem *der, char *m, int level)
2754 PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
2755 SECKEYEncryptedPrivateKeyInfo key;
2756 int rv = SEC_ERROR_NO_MEMORY;
2761 PORT_Memset(&key, 0, sizeof(key));
2762 rv = SEC_ASN1DecodeItem(arena, &key,
2763 SEC_ASN1_GET(SECKEY_EncryptedPrivateKeyInfoTemplate), der);
2767 /* Pretty print it out */
2768 SECU_Indent(out, level); fprintf(out, "%s:\n", m);
2769 SECU_PrintAlgorithmID(out, &key.algorithm, "Encryption Algorithm",
2771 SECU_PrintAsHex(out, &key.encryptedData, "Encrypted Data", level+1);
2773 PORT_FreeArena(arena, PR_TRUE);
2779 SECU_PrintFingerprints(FILE *out, SECItem *derCert, char *m, int level)
2781 unsigned char fingerprint[20];
2783 int err = PORT_GetError();
2787 /* print MD5 fingerprint */
2788 memset(fingerprint, 0, sizeof fingerprint);
2789 rv = PK11_HashBuf(SEC_OID_MD5,fingerprint, derCert->data, derCert->len);
2790 fpItem.data = fingerprint;
2791 fpItem.len = MD5_LENGTH;
2792 fpStr = CERT_Hexify(&fpItem, 1);
2793 SECU_Indent(out, level); fprintf(out, "%s (MD5):", m);
2796 SECU_Indent(out, level+1);
2801 fprintf(out, "%s\n", fpStr);
2804 if (rv != SECSuccess && !err)
2805 err = PORT_GetError();
2807 /* print SHA1 fingerprint */
2808 memset(fingerprint, 0, sizeof fingerprint);
2809 rv = PK11_HashBuf(SEC_OID_SHA1,fingerprint, derCert->data, derCert->len);
2810 fpItem.data = fingerprint;
2811 fpItem.len = SHA1_LENGTH;
2812 fpStr = CERT_Hexify(&fpItem, 1);
2813 SECU_Indent(out, level); fprintf(out, "%s (SHA1):", m);
2816 SECU_Indent(out, level+1);
2821 fprintf(out, "%s\n", fpStr);
2828 if (err || rv != SECSuccess)
2838 /* forward declaration */
2840 secu_PrintPKCS7ContentInfo(FILE *, SEC_PKCS7ContentInfo *, char *, int);
2843 ** secu_PrintPKCS7EncContent
2844 ** Prints a SEC_PKCS7EncryptedContentInfo (without decrypting it)
2847 secu_PrintPKCS7EncContent(FILE *out, SEC_PKCS7EncryptedContentInfo *src,
2850 if (src->contentTypeTag == NULL)
2851 src->contentTypeTag = SECOID_FindOID(&(src->contentType));
2853 SECU_Indent(out, level);
2854 fprintf(out, "%s:\n", m);
2855 SECU_Indent(out, level + 1);
2856 fprintf(out, "Content Type: %s\n",
2857 (src->contentTypeTag != NULL) ? src->contentTypeTag->desc
2859 SECU_PrintAlgorithmID(out, &(src->contentEncAlg),
2860 "Content Encryption Algorithm", level+1);
2861 SECU_PrintAsHex(out, &(src->encContent),
2862 "Encrypted Content", level+1);
2866 ** secu_PrintRecipientInfo
2867 ** Prints a PKCS7RecipientInfo type
2870 secu_PrintRecipientInfo(FILE *out, SEC_PKCS7RecipientInfo *info, char *m,
2873 SECU_Indent(out, level); fprintf(out, "%s:\n", m);
2874 SECU_PrintInteger(out, &(info->version), "Version", level + 1);
2876 SECU_PrintName(out, &(info->issuerAndSN->issuer), "Issuer",
2878 SECU_PrintInteger(out, &(info->issuerAndSN->serialNumber),
2879 "Serial Number", level + 1);
2881 /* Parse and display encrypted key */
2882 SECU_PrintAlgorithmID(out, &(info->keyEncAlg),
2883 "Key Encryption Algorithm", level + 1);
2884 SECU_PrintAsHex(out, &(info->encKey), "Encrypted Key", level + 1);
2888 ** secu_PrintSignerInfo
2889 ** Prints a PKCS7SingerInfo type
2892 secu_PrintSignerInfo(FILE *out, SEC_PKCS7SignerInfo *info, char *m, int level)
2894 SEC_PKCS7Attribute *attr;
2898 SECU_Indent(out, level); fprintf(out, "%s:\n", m);
2899 SECU_PrintInteger(out, &(info->version), "Version", level + 1);
2901 SECU_PrintName(out, &(info->issuerAndSN->issuer), "Issuer",
2903 SECU_PrintInteger(out, &(info->issuerAndSN->serialNumber),
2904 "Serial Number", level + 1);
2906 SECU_PrintAlgorithmID(out, &(info->digestAlg), "Digest Algorithm",
2909 if (info->authAttr != NULL) {
2910 SECU_Indent(out, level + 1);
2911 fprintf(out, "Authenticated Attributes:\n");
2913 while ((attr = info->authAttr[iv++]) != NULL) {
2914 sprintf(om, "Attribute (%d)", iv);
2915 secu_PrintAttribute(out, attr, om, level + 2);
2919 /* Parse and display signature */
2920 SECU_PrintAlgorithmID(out, &(info->digestEncAlg),
2921 "Digest Encryption Algorithm", level + 1);
2922 SECU_PrintAsHex(out, &(info->encDigest), "Encrypted Digest", level + 1);
2924 if (info->unAuthAttr != NULL) {
2925 SECU_Indent(out, level + 1);
2926 fprintf(out, "Unauthenticated Attributes:\n");
2928 while ((attr = info->unAuthAttr[iv++]) != NULL) {
2929 sprintf(om, "Attribute (%x)", iv);
2930 secu_PrintAttribute(out, attr, om, level + 2);
2935 /* callers of this function must make sure that the CERTSignedCrl
2936 from which they are extracting the CERTCrl has been fully-decoded.
2937 Otherwise it will not have the entries even though the CRL may have
2941 SECU_PrintCRLInfo(FILE *out, CERTCrl *crl, char *m, int level)
2943 CERTCrlEntry *entry;
2947 SECU_Indent(out, level); fprintf(out, "%s:\n", m);
2948 /* version is optional */
2949 iv = crl->version.len ? DER_GetInteger(&crl->version) : 0;
2950 SECU_Indent(out, level+1);
2951 fprintf(out, "%s: %d (0x%x)\n", "Version", iv + 1, iv);
2952 SECU_PrintAlgorithmID(out, &(crl->signatureAlg), "Signature Algorithm",
2954 SECU_PrintName(out, &(crl->name), "Issuer", level + 1);
2955 SECU_PrintTimeChoice(out, &(crl->lastUpdate), "This Update", level + 1);
2956 if (crl->nextUpdate.data && crl->nextUpdate.len) /* is optional */
2957 SECU_PrintTimeChoice(out, &(crl->nextUpdate), "Next Update", level + 1);
2959 if (crl->entries != NULL) {
2961 while ((entry = crl->entries[iv++]) != NULL) {
2962 sprintf(om, "Entry %d (0x%x):\n", iv, iv);
2963 SECU_Indent(out, level + 1); fputs(om, out);
2964 SECU_PrintInteger(out, &(entry->serialNumber), "Serial Number",
2966 SECU_PrintTimeChoice(out, &(entry->revocationDate),
2967 "Revocation Date", level + 2);
2968 SECU_PrintExtensions(out, entry->extensions,
2969 "Entry Extensions", level + 2);
2972 SECU_PrintExtensions(out, crl->extensions, "CRL Extensions", level + 1);
2976 ** secu_PrintPKCS7Signed
2977 ** Pretty print a PKCS7 signed data type (up to version 1).
2980 secu_PrintPKCS7Signed(FILE *out, SEC_PKCS7SignedData *src,
2981 const char *m, int level)
2983 SECAlgorithmID *digAlg; /* digest algorithms */
2984 SECItem *aCert; /* certificate */
2985 CERTSignedCrl *aCrl; /* certificate revocation list */
2986 SEC_PKCS7SignerInfo *sigInfo; /* signer information */
2990 SECU_Indent(out, level); fprintf(out, "%s:\n", m);
2991 SECU_PrintInteger(out, &(src->version), "Version", level + 1);
2993 /* Parse and list digest algorithms (if any) */
2994 if (src->digestAlgorithms != NULL) {
2995 SECU_Indent(out, level + 1); fprintf(out, "Digest Algorithm List:\n");
2997 while ((digAlg = src->digestAlgorithms[iv++]) != NULL) {
2998 sprintf(om, "Digest Algorithm (%x)", iv);
2999 SECU_PrintAlgorithmID(out, digAlg, om, level + 2);
3003 /* Now for the content */
3004 rv = secu_PrintPKCS7ContentInfo(out, &(src->contentInfo),
3005 "Content Information", level + 1);
3009 /* Parse and list certificates (if any) */
3010 if (src->rawCerts != NULL) {
3011 SECU_Indent(out, level + 1); fprintf(out, "Certificate List:\n");
3013 while ((aCert = src->rawCerts[iv++]) != NULL) {
3014 sprintf(om, "Certificate (%x)", iv);
3015 rv = SECU_PrintSignedData(out, aCert, om, level + 2,
3016 SECU_PrintCertificate);
3022 /* Parse and list CRL's (if any) */
3023 if (src->crls != NULL) {
3024 SECU_Indent(out, level + 1);
3025 fprintf(out, "Signed Revocation Lists:\n");
3027 while ((aCrl = src->crls[iv++]) != NULL) {
3028 sprintf(om, "Signed Revocation List (%x)", iv);
3029 SECU_Indent(out, level + 2); fprintf(out, "%s:\n", om);
3030 SECU_PrintAlgorithmID(out, &aCrl->signatureWrap.signatureAlgorithm,
3031 "Signature Algorithm", level+3);
3032 DER_ConvertBitString(&aCrl->signatureWrap.signature);
3033 SECU_PrintAsHex(out, &aCrl->signatureWrap.signature, "Signature",
3035 SECU_PrintCRLInfo(out, &aCrl->crl, "Certificate Revocation List",
3040 /* Parse and list signatures (if any) */
3041 if (src->signerInfos != NULL) {
3042 SECU_Indent(out, level + 1);
3043 fprintf(out, "Signer Information List:\n");
3045 while ((sigInfo = src->signerInfos[iv++]) != NULL) {
3046 sprintf(om, "Signer Information (%x)", iv);
3047 secu_PrintSignerInfo(out, sigInfo, om, level + 2);
3055 ** secu_PrintPKCS7Enveloped
3056 ** Pretty print a PKCS7 enveloped data type (up to version 1).
3059 secu_PrintPKCS7Enveloped(FILE *out, SEC_PKCS7EnvelopedData *src,
3060 const char *m, int level)
3062 SEC_PKCS7RecipientInfo *recInfo; /* pointer for signer information */
3066 SECU_Indent(out, level); fprintf(out, "%s:\n", m);
3067 SECU_PrintInteger(out, &(src->version), "Version", level + 1);
3069 /* Parse and list recipients (this is not optional) */
3070 if (src->recipientInfos != NULL) {
3071 SECU_Indent(out, level + 1);
3072 fprintf(out, "Recipient Information List:\n");
3074 while ((recInfo = src->recipientInfos[iv++]) != NULL) {
3075 sprintf(om, "Recipient Information (%x)", iv);
3076 secu_PrintRecipientInfo(out, recInfo, om, level + 2);
3080 secu_PrintPKCS7EncContent(out, &src->encContentInfo,
3081 "Encrypted Content Information", level + 1);
3085 ** secu_PrintPKCS7SignedEnveloped
3086 ** Pretty print a PKCS7 singed and enveloped data type (up to version 1).
3089 secu_PrintPKCS7SignedAndEnveloped(FILE *out,
3090 SEC_PKCS7SignedAndEnvelopedData *src,
3091 const char *m, int level)
3093 SECAlgorithmID *digAlg; /* pointer for digest algorithms */
3094 SECItem *aCert; /* pointer for certificate */
3095 CERTSignedCrl *aCrl; /* pointer for certificate revocation list */
3096 SEC_PKCS7SignerInfo *sigInfo; /* pointer for signer information */
3097 SEC_PKCS7RecipientInfo *recInfo; /* pointer for recipient information */
3101 SECU_Indent(out, level); fprintf(out, "%s:\n", m);
3102 SECU_PrintInteger(out, &(src->version), "Version", level + 1);
3104 /* Parse and list recipients (this is not optional) */
3105 if (src->recipientInfos != NULL) {
3106 SECU_Indent(out, level + 1);
3107 fprintf(out, "Recipient Information List:\n");
3109 while ((recInfo = src->recipientInfos[iv++]) != NULL) {
3110 sprintf(om, "Recipient Information (%x)", iv);
3111 secu_PrintRecipientInfo(out, recInfo, om, level + 2);
3115 /* Parse and list digest algorithms (if any) */
3116 if (src->digestAlgorithms != NULL) {
3117 SECU_Indent(out, level + 1); fprintf(out, "Digest Algorithm List:\n");
3119 while ((digAlg = src->digestAlgorithms[iv++]) != NULL) {
3120 sprintf(om, "Digest Algorithm (%x)", iv);
3121 SECU_PrintAlgorithmID(out, digAlg, om, level + 2);
3125 secu_PrintPKCS7EncContent(out, &src->encContentInfo,
3126 "Encrypted Content Information", level + 1);
3128 /* Parse and list certificates (if any) */
3129 if (src->rawCerts != NULL) {
3130 SECU_Indent(out, level + 1); fprintf(out, "Certificate List:\n");
3132 while ((aCert = src->rawCerts[iv++]) != NULL) {
3133 sprintf(om, "Certificate (%x)", iv);
3134 rv = SECU_PrintSignedData(out, aCert, om, level + 2,
3135 SECU_PrintCertificate);
3141 /* Parse and list CRL's (if any) */
3142 if (src->crls != NULL) {
3143 SECU_Indent(out, level + 1);
3144 fprintf(out, "Signed Revocation Lists:\n");
3146 while ((aCrl = src->crls[iv++]) != NULL) {
3147 sprintf(om, "Signed Revocation List (%x)", iv);
3148 SECU_Indent(out, level + 2); fprintf(out, "%s:\n", om);
3149 SECU_PrintAlgorithmID(out, &aCrl->signatureWrap.signatureAlgorithm,
3150 "Signature Algorithm", level+3);
3151 DER_ConvertBitString(&aCrl->signatureWrap.signature);
3152 SECU_PrintAsHex(out, &aCrl->signatureWrap.signature, "Signature",
3154 SECU_PrintCRLInfo(out, &aCrl->crl, "Certificate Revocation List",
3159 /* Parse and list signatures (if any) */
3160 if (src->signerInfos != NULL) {
3161 SECU_Indent(out, level + 1);
3162 fprintf(out, "Signer Information List:\n");
3164 while ((sigInfo = src->signerInfos[iv++]) != NULL) {
3165 sprintf(om, "Signer Information (%x)", iv);
3166 secu_PrintSignerInfo(out, sigInfo, om, level + 2);
3174 SECU_PrintCrl (FILE *out, SECItem *der, char *m, int level)
3176 PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
3178 int rv = SEC_ERROR_NO_MEMORY;
3184 c = PORT_ArenaZNew(arena, CERTCrl);
3188 rv = SEC_QuickDERDecodeItem(arena, c, SEC_ASN1_GET(CERT_CrlTemplate), der);
3189 if (rv != SECSuccess)
3191 SECU_PrintCRLInfo (out, c, m, level);
3193 PORT_FreeArena (arena, PR_FALSE);
3199 ** secu_PrintPKCS7Encrypted
3200 ** Pretty print a PKCS7 encrypted data type (up to version 1).
3203 secu_PrintPKCS7Encrypted(FILE *out, SEC_PKCS7EncryptedData *src,
3204 const char *m, int level)
3206 SECU_Indent(out, level); fprintf(out, "%s:\n", m);
3207 SECU_PrintInteger(out, &(src->version), "Version", level + 1);
3209 secu_PrintPKCS7EncContent(out, &src->encContentInfo,
3210 "Encrypted Content Information", level + 1);
3214 ** secu_PrintPKCS7Digested
3215 ** Pretty print a PKCS7 digested data type (up to version 1).
3218 secu_PrintPKCS7Digested(FILE *out, SEC_PKCS7DigestedData *src,
3219 const char *m, int level)
3221 SECU_Indent(out, level); fprintf(out, "%s:\n", m);
3222 SECU_PrintInteger(out, &(src->version), "Version", level + 1);
3224 SECU_PrintAlgorithmID(out, &src->digestAlg, "Digest Algorithm",
3226 secu_PrintPKCS7ContentInfo(out, &src->contentInfo, "Content Information",
3228 SECU_PrintAsHex(out, &src->digest, "Digest", level + 1);
3232 ** secu_PrintPKCS7ContentInfo
3233 ** Takes a SEC_PKCS7ContentInfo type and sends the contents to the
3234 ** appropriate function
3237 secu_PrintPKCS7ContentInfo(FILE *out, SEC_PKCS7ContentInfo *src,
3244 SECU_Indent(out, level); fprintf(out, "%s:\n", m);
3247 if (src->contentTypeTag == NULL)
3248 src->contentTypeTag = SECOID_FindOID(&(src->contentType));
3250 if (src->contentTypeTag == NULL) {
3252 kind = SEC_OID_PKCS7_DATA;
3254 desc = src->contentTypeTag->desc;
3255 kind = src->contentTypeTag->offset;
3258 if (src->content.data == NULL) {
3259 SECU_Indent(out, level); fprintf(out, "%s:\n", desc);
3261 SECU_Indent(out, level); fprintf(out, "<no content>\n");
3267 case SEC_OID_PKCS7_SIGNED_DATA: /* Signed Data */
3268 rv = secu_PrintPKCS7Signed(out, src->content.signedData, desc, level);
3271 case SEC_OID_PKCS7_ENVELOPED_DATA: /* Enveloped Data */
3272 secu_PrintPKCS7Enveloped(out, src->content.envelopedData, desc, level);
3275 case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: /* Signed and Enveloped */
3276 rv = secu_PrintPKCS7SignedAndEnveloped(out,
3277 src->content.signedAndEnvelopedData,
3281 case SEC_OID_PKCS7_DIGESTED_DATA: /* Digested Data */
3282 secu_PrintPKCS7Digested(out, src->content.digestedData, desc, level);
3285 case SEC_OID_PKCS7_ENCRYPTED_DATA: /* Encrypted Data */
3286 secu_PrintPKCS7Encrypted(out, src->content.encryptedData, desc, level);
3290 SECU_PrintAsHex(out, src->content.data, desc, level);
3298 ** SECU_PrintPKCS7ContentInfo
3299 ** Decode and print any major PKCS7 data type (up to version 1).
3302 SECU_PrintPKCS7ContentInfo(FILE *out, SECItem *der, char *m, int level)
3304 SEC_PKCS7ContentInfo *cinfo;
3307 cinfo = SEC_PKCS7DecodeItem(der, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
3308 if (cinfo != NULL) {
3309 /* Send it to recursive parsing and printing module */
3310 rv = secu_PrintPKCS7ContentInfo(out, cinfo, m, level);
3311 SEC_PKCS7DestroyContentInfo(cinfo);
3320 ** End of PKCS7 functions
3324 printFlags(FILE *out, unsigned int flags, int level)
3326 if ( flags & CERTDB_TERMINAL_RECORD ) {
3327 SECU_Indent(out, level); fprintf(out, "Terminal Record\n");
3329 if ( flags & CERTDB_TRUSTED ) {
3330 SECU_Indent(out, level); fprintf(out, "Trusted\n");
3332 if ( flags & CERTDB_SEND_WARN ) {
3333 SECU_Indent(out, level); fprintf(out, "Warn When Sending\n");
3335 if ( flags & CERTDB_VALID_CA ) {
3336 SECU_Indent(out, level); fprintf(out, "Valid CA\n");
3338 if ( flags & CERTDB_TRUSTED_CA ) {
3339 SECU_Indent(out, level); fprintf(out, "Trusted CA\n");
3341 if ( flags & CERTDB_NS_TRUSTED_CA ) {
3342 SECU_Indent(out, level); fprintf(out, "Netscape Trusted CA\n");
3344 if ( flags & CERTDB_USER ) {
3345 SECU_Indent(out, level); fprintf(out, "User\n");
3347 if ( flags & CERTDB_TRUSTED_CLIENT_CA ) {
3348 SECU_Indent(out, level); fprintf(out, "Trusted Client CA\n");
3350 if ( flags & CERTDB_GOVT_APPROVED_CA ) {
3351 SECU_Indent(out, level); fprintf(out, "Step-up\n");
3356 SECU_PrintTrustFlags(FILE *out, CERTCertTrust *trust, char *m, int level)
3358 SECU_Indent(out, level); fprintf(out, "%s:\n", m);
3359 SECU_Indent(out, level+1); fprintf(out, "SSL Flags:\n");
3360 printFlags(out, trust->sslFlags, level+2);
3361 SECU_Indent(out, level+1); fprintf(out, "Email Flags:\n");
3362 printFlags(out, trust->emailFlags, level+2);
3363 SECU_Indent(out, level+1); fprintf(out, "Object Signing Flags:\n");
3364 printFlags(out, trust->objectSigningFlags, level+2);
3367 int SECU_PrintDERName(FILE *out, SECItem *der, const char *m, int level)
3369 PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
3371 int rv = SEC_ERROR_NO_MEMORY;
3376 name = PORT_ArenaZNew(arena, CERTName);
3380 rv = SEC_ASN1DecodeItem(arena, name, SEC_ASN1_GET(CERT_NameTemplate), der);
3384 SECU_PrintName(out, name, m, level);
3386 PORT_FreeArena(arena, PR_FALSE);
3390 int SECU_PrintSignedData(FILE *out, SECItem *der, const char *m,
3391 int level, SECU_PPFunc inner)
3393 PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
3395 int rv = SEC_ERROR_NO_MEMORY;
3400 /* Strip off the signature */
3401 sd = PORT_ArenaZNew(arena, CERTSignedData);
3405 rv = SEC_ASN1DecodeItem(arena, sd, SEC_ASN1_GET(CERT_SignedDataTemplate),
3410 SECU_Indent(out, level); fprintf(out, "%s:\n", m);
3411 rv = (*inner)(out, &sd->data, "Data", level+1);
3413 SECU_PrintAlgorithmID(out, &sd->signatureAlgorithm, "Signature Algorithm",
3415 DER_ConvertBitString(&sd->signature);
3416 SECU_PrintAsHex(out, &sd->signature, "Signature", level+1);
3417 SECU_PrintFingerprints(out, der, "Fingerprint", level+1);
3419 PORT_FreeArena(arena, PR_FALSE);
3424 SEC_PrintCertificateAndTrust(CERTCertificate *cert,
3426 CERTCertTrust *trust)
3431 data.data = cert->derCert.data;
3432 data.len = cert->derCert.len;
3434 rv = SECU_PrintSignedData(stdout, &data, label, 0,
3435 SECU_PrintCertificate);
3440 SECU_PrintTrustFlags(stdout, trust,
3441 "Certificate Trust Flags", 1);
3442 } else if (cert->trust) {
3443 SECU_PrintTrustFlags(stdout, cert->trust,
3444 "Certificate Trust Flags", 1);
3452 #if defined(DEBUG) || defined(FORCE_PR_ASSERT)
3453 /* Returns true iff a[i].flag has a duplicate in a[i+1 : count-1] */
3454 static PRBool HasShortDuplicate(int i, secuCommandFlag *a, int count)
3456 char target = a[i].flag;
3459 /* duplicate '\0' flags are okay, they are used with long forms */
3460 for (j = i+1; j < count; j++) {
3461 if (a[j].flag && a[j].flag == target) {
3468 /* Returns true iff a[i].longform has a duplicate in a[i+1 : count-1] */
3469 static PRBool HasLongDuplicate(int i, secuCommandFlag *a, int count)
3472 char *target = a[i].longform;
3477 for (j = i+1; j < count; j++) {
3478 if (a[j].longform && strcmp(a[j].longform, target) == 0) {
3485 /* Returns true iff a has no short or long form duplicates
3487 PRBool HasNoDuplicates(secuCommandFlag *a, int count)
3491 for (i = 0; i < count; i++) {
3492 if (a[i].flag && HasShortDuplicate(i, a, count)) {
3495 if (a[i].longform && HasLongDuplicate(i, a, count)) {
3504 SECU_ParseCommandLine(int argc, char **argv, char *progName,
3505 const secuCommand *cmd)
3508 PLOptState *optstate;
3511 PLLongOpt *longopts = NULL;
3513 int lcmd = 0, lopt = 0;
3515 PR_ASSERT(HasNoDuplicates(cmd->commands, cmd->numCommands));
3516 PR_ASSERT(HasNoDuplicates(cmd->options, cmd->numOptions));
3518 optstring = (char *)PORT_Alloc(cmd->numCommands + 2*cmd->numOptions+1);
3519 if (optstring == NULL)
3523 for (i=0; i<cmd->numCommands; i++) {
3524 if (cmd->commands[i].flag) /* single character option ? */
3525 optstring[j++] = cmd->commands[i].flag;
3526 if (cmd->commands[i].longform)
3529 for (i=0; i<cmd->numOptions; i++) {
3530 if (cmd->options[i].flag) {
3531 optstring[j++] = cmd->options[i].flag;
3532 if (cmd->options[i].needsArg)
3533 optstring[j++] = ':';
3535 if (cmd->options[i].longform)
3539 optstring[j] = '\0';
3541 if (lcmd + lopt > 0) {
3542 longopts = PORT_NewArray(PLLongOpt, lcmd+lopt+1);
3544 PORT_Free(optstring);
3549 for (i=0; j<lcmd && i<cmd->numCommands; i++) {
3550 if (cmd->commands[i].longform) {
3551 longopts[j].longOptName = cmd->commands[i].longform;
3552 longopts[j].longOption = 0;
3553 longopts[j++].valueRequired = cmd->commands[i].needsArg;
3557 for (i=0; j<lopt && i<cmd->numOptions; i++) {
3558 if (cmd->options[i].longform) {
3559 longopts[j].longOptName = cmd->options[i].longform;
3560 longopts[j].longOption = 0;
3561 longopts[j++].valueRequired = cmd->options[i].needsArg;
3564 longopts[j].longOptName = NULL;
3567 optstate = PL_CreateLongOptState(argc, argv, optstring, longopts);
3569 PORT_Free(optstring);
3570 PORT_Free(longopts);
3573 /* Parse command line arguments */
3574 while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
3575 const char *optstatelong;
3576 char option = optstate->option;
3578 /* positional parameter, single-char option or long opt? */
3579 if (optstate->longOptIndex == -1) {
3580 /* not a long opt */
3582 continue; /* it's a positional parameter */
3587 option = '\377'; /* force unequal with all flags */
3588 optstatelong = longopts[optstate->longOptIndex].longOptName;
3593 for (i=0; i<cmd->numCommands; i++) {
3594 if (cmd->commands[i].flag == option ||
3595 cmd->commands[i].longform == optstatelong) {
3596 cmd->commands[i].activated = PR_TRUE;
3597 if (optstate->value) {
3598 cmd->commands[i].arg = (char *)optstate->value;
3608 for (i=0; i<cmd->numOptions; i++) {
3609 if (cmd->options[i].flag == option ||
3610 cmd->options[i].longform == optstatelong) {
3611 cmd->options[i].activated = PR_TRUE;
3612 if (optstate->value) {
3613 cmd->options[i].arg = (char *)optstate->value;
3614 } else if (cmd->options[i].needsArg) {
3615 status = PL_OPT_BAD;
3624 status = PL_OPT_BAD;
3630 PL_DestroyOptState(optstate);
3631 PORT_Free(optstring);
3633 PORT_Free(longopts);
3634 if (status == PL_OPT_BAD)
3640 SECU_GetOptionArg(const secuCommand *cmd, int optionNum)
3642 if (optionNum < 0 || optionNum >= cmd->numOptions)
3644 if (cmd->options[optionNum].activated)
3645 return PL_strdup(cmd->options[optionNum].arg);
3652 SECU_PrintPRandOSError(char *progName)
3655 PRInt32 errLen = PR_GetErrorTextLength();
3656 if (errLen > 0 && errLen < sizeof buffer) {
3657 PR_GetErrorText(buffer);
3659 SECU_PrintError(progName, "function failed");
3660 if (errLen > 0 && errLen < sizeof buffer) {
3661 PR_fprintf(PR_STDERR, "\t%s\n", buffer);
3667 bestCertName(CERTCertificate *cert) {
3668 if (cert->nickname) {
3669 return cert->nickname;
3671 if (cert->emailAddr && cert->emailAddr[0]) {
3672 return cert->emailAddr;
3674 return cert->subjectName;
3678 SECU_printCertProblemsOnDate(FILE *outfile, CERTCertDBHandle *handle,
3679 CERTCertificate *cert, PRBool checksig,
3680 SECCertificateUsage certUsage, void *pinArg, PRBool verbose,
3684 CERTVerifyLogNode *node;
3686 PRErrorCode err = PORT_GetError();
3688 log.arena = PORT_NewArena(512);
3689 log.head = log.tail = NULL;
3691 CERT_VerifyCertificate(handle, cert, checksig, certUsage, datetime, pinArg, &log, NULL);
3693 SECU_displayVerifyLog(outfile, &log, verbose);
3695 for (node = log.head; node; node = node->next) {
3697 CERT_DestroyCertificate(node->cert);
3699 PORT_FreeArena(log.arena, PR_FALSE);
3701 PORT_SetError(err); /* restore original error code */
3705 SECU_displayVerifyLog(FILE *outfile, CERTVerifyLog *log,
3708 CERTVerifyLogNode *node = NULL;
3709 unsigned int depth = (unsigned int)-1;
3710 unsigned int flags = 0;
3711 char * errstr = NULL;
3713 if (log->count > 0) {
3714 fprintf(outfile,"PROBLEM WITH THE CERT CHAIN:\n");
3715 for (node = log->head; node; node = node->next) {
3716 if (depth != node->depth) {
3717 depth = node->depth;
3718 fprintf(outfile,"CERT %d. %s %s:\n", depth,
3719 bestCertName(node->cert),
3720 depth ? "[Certificate Authority]": "");
3722 const char * emailAddr;
3723 emailAddr = CERT_GetFirstEmailAddress(node->cert);
3725 fprintf(outfile,"Email Address(es): ");
3727 fprintf(outfile, "%s\n", emailAddr);
3728 emailAddr = CERT_GetNextEmailAddress(node->cert,
3730 } while (emailAddr);
3734 fprintf(outfile, " ERROR %ld: %s\n", node->error,
3735 SECU_Strerror(node->error));
3737 switch (node->error) {
3738 case SEC_ERROR_INADEQUATE_KEY_USAGE:
3739 flags = (unsigned int)node->arg;
3741 case KU_DIGITAL_SIGNATURE:
3742 errstr = "Cert cannot sign.";
3744 case KU_KEY_ENCIPHERMENT:
3745 errstr = "Cert cannot encrypt.";
3747 case KU_KEY_CERT_SIGN:
3748 errstr = "Cert cannot sign other certs.";
3751 errstr = "[unknown usage].";
3754 case SEC_ERROR_INADEQUATE_CERT_TYPE:
3755 flags = (unsigned int)node->arg;
3757 case NS_CERT_TYPE_SSL_CLIENT:
3758 case NS_CERT_TYPE_SSL_SERVER:
3759 errstr = "Cert cannot be used for SSL.";
3761 case NS_CERT_TYPE_SSL_CA:
3762 errstr = "Cert cannot be used as an SSL CA.";
3764 case NS_CERT_TYPE_EMAIL:
3765 errstr = "Cert cannot be used for SMIME.";
3767 case NS_CERT_TYPE_EMAIL_CA:
3768 errstr = "Cert cannot be used as an SMIME CA.";
3770 case NS_CERT_TYPE_OBJECT_SIGNING:
3771 errstr = "Cert cannot be used for object signing.";
3773 case NS_CERT_TYPE_OBJECT_SIGNING_CA:
3774 errstr = "Cert cannot be used as an object signing CA.";
3777 errstr = "[unknown usage].";
3780 case SEC_ERROR_UNKNOWN_ISSUER:
3781 case SEC_ERROR_UNTRUSTED_ISSUER:
3782 case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
3783 errstr = node->cert->issuerName;
3789 fprintf(stderr," %s\n",errstr);
3796 SECU_printCertProblems(FILE *outfile, CERTCertDBHandle *handle,
3797 CERTCertificate *cert, PRBool checksig,
3798 SECCertificateUsage certUsage, void *pinArg, PRBool verbose)
3800 SECU_printCertProblemsOnDate(outfile, handle, cert, checksig,
3801 certUsage, pinArg, verbose, PR_Now());
3805 SECU_StringToSignatureAlgTag(const char *alg)
3807 SECOidTag hashAlgTag = SEC_OID_UNKNOWN;
3810 if (!PL_strcmp(alg, "MD2")) {
3811 hashAlgTag = SEC_OID_MD2;
3812 } else if (!PL_strcmp(alg, "MD4")) {
3813 hashAlgTag = SEC_OID_MD4;
3814 } else if (!PL_strcmp(alg, "MD5")) {
3815 hashAlgTag = SEC_OID_MD5;
3816 } else if (!PL_strcmp(alg, "SHA1")) {
3817 hashAlgTag = SEC_OID_SHA1;
3818 } else if (!PL_strcmp(alg, "SHA224")) {
3819 hashAlgTag = SEC_OID_SHA224;
3820 } else if (!PL_strcmp(alg, "SHA256")) {
3821 hashAlgTag = SEC_OID_SHA256;
3822 } else if (!PL_strcmp(alg, "SHA384")) {
3823 hashAlgTag = SEC_OID_SHA384;
3824 } else if (!PL_strcmp(alg, "SHA512")) {
3825 hashAlgTag = SEC_OID_SHA512;
3833 SECU_StoreCRL(PK11SlotInfo *slot, SECItem *derCrl, PRFileDesc *outFile,
3834 PRBool ascii, char *url)
3836 PORT_Assert(derCrl != NULL);
3838 PORT_SetError(SEC_ERROR_INVALID_ARGS);
3842 if (outFile != NULL) {
3844 PR_fprintf(outFile, "%s\n%s\n%s\n", NS_CRL_HEADER,
3845 BTOA_DataToAscii(derCrl->data, derCrl->len),
3848 if (PR_Write(outFile, derCrl->data, derCrl->len) != derCrl->len) {
3854 CERTSignedCrl *newCrl = PK11_ImportCRL(slot, derCrl, url,
3855 SEC_CRL_TYPE, NULL, 0, NULL, 0);
3856 if (newCrl != NULL) {
3857 SEC_DestroyCrl(newCrl);
3862 if (!outFile && !slot) {
3863 PORT_SetError(SEC_ERROR_INVALID_ARGS);
3870 SECU_SignAndEncodeCRL(CERTCertificate *issuer, CERTSignedCrl *signCrl,
3871 SECOidTag hashAlgTag, SignAndEncodeFuncExitStat *resCode)
3874 SECKEYPrivateKey *caPrivateKey = NULL;
3880 PORT_Assert(issuer != NULL && signCrl != NULL);
3881 if (!issuer || !signCrl) {
3882 PORT_SetError(SEC_ERROR_INVALID_ARGS);
3886 arena = signCrl->arena;
3888 caPrivateKey = PK11_FindKeyByAnyCert(issuer, NULL);
3889 if (caPrivateKey == NULL) {
3890 *resCode = noKeyFound;
3894 algID = SEC_GetSignatureAlgorithmOidTag(caPrivateKey->keyType, hashAlgTag);
3895 if (algID == SEC_OID_UNKNOWN) {
3896 *resCode = noSignatureMatch;
3901 if (!signCrl->crl.signatureAlg.parameters.data) {
3902 rv = SECOID_SetAlgorithmID(arena, &signCrl->crl.signatureAlg, algID, 0);
3903 if (rv != SECSuccess) {
3904 *resCode = failToEncode;
3911 dummy = SEC_ASN1EncodeItem(arena, &der, &signCrl->crl,
3912 SEC_ASN1_GET(CERT_CrlTemplate));
3914 *resCode = failToEncode;
3919 rv = SECU_DerSignDataCRL(arena, &signCrl->signatureWrap,
3920 der.data, der.len, caPrivateKey, algID);
3921 if (rv != SECSuccess) {
3922 *resCode = failToSign;
3926 signCrl->derCrl = PORT_ArenaZNew(arena, SECItem);
3927 if (signCrl->derCrl == NULL) {
3929 PORT_SetError(SEC_ERROR_NO_MEMORY);
3934 signCrl->derCrl->len = 0;
3935 signCrl->derCrl->data = NULL;
3936 dummy = SEC_ASN1EncodeItem (arena, signCrl->derCrl, signCrl,
3937 SEC_ASN1_GET(CERT_SignedCrlTemplate));
3939 *resCode = failToEncode;
3946 SECKEY_DestroyPrivateKey(caPrivateKey);
3954 SECU_CopyCRL(PRArenaPool *destArena, CERTCrl *destCrl, CERTCrl *srcCrl)
3957 SECStatus rv = SECSuccess;
3960 PORT_Assert(destArena && srcCrl && destCrl);
3961 if (!destArena || !srcCrl || !destCrl) {
3962 PORT_SetError(SEC_ERROR_INVALID_ARGS);
3968 dummy = SEC_ASN1EncodeItem (destArena, &der, srcCrl,
3969 SEC_ASN1_GET(CERT_CrlTemplate));
3974 rv = SEC_QuickDERDecodeItem(destArena, destCrl,
3975 SEC_ASN1_GET(CERT_CrlTemplate), &der);
3976 if (rv != SECSuccess) {
3980 destCrl->arena = destArena;
3986 SECU_DerSignDataCRL(PRArenaPool *arena, CERTSignedData *sd,
3987 unsigned char *buf, int len, SECKEYPrivateKey *pk,
3995 /* XXX We should probably have some asserts here to make sure the key type
3999 /* Sign input buffer */
4000 rv = SEC_SignData(&it, buf, len, pk, algID);
4003 /* Fill out SignedData object */
4004 PORT_Memset(sd, 0, sizeof(*sd));
4005 sd->data.data = buf;
4007 sd->signature.data = it.data;
4008 sd->signature.len = it.len << 3; /* convert to bit string */
4009 rv = SECOID_SetAlgorithmID(arena, &sd->signatureAlgorithm, algID, 0);
4021 /* we need access to the private function cert_FindExtension for this code to work */
4024 SECU_FindCRLAuthKeyIDExten (PRArenaPool *arena, CERTSignedCrl *scrl)
4026 SECItem encodedExtenValue;
4032 PORT_SetError(SEC_ERROR_INVALID_ARGS);
4038 encodedExtenValue.data = NULL;
4039 encodedExtenValue.len = 0;
4041 rv = cert_FindExtension(crl->extensions, SEC_OID_X509_AUTH_KEY_ID,
4042 &encodedExtenValue);
4043 if ( rv != SECSuccess ) {
4047 ret = CERT_DecodeAuthKeyID (arena, &encodedExtenValue);
4049 PORT_Free(encodedExtenValue.data);
4050 encodedExtenValue.data = NULL;
4058 * Find the issuer of a Crl. Use the authorityKeyID if it exists.
4061 SECU_FindCrlIssuer(CERTCertDBHandle *dbhandle, SECItem* subject,
4062 CERTAuthKeyID* authorityKeyID, PRTime validTime)
4064 CERTCertificate *issuerCert = NULL;
4065 CERTCertList *certList = NULL;
4068 PORT_SetError(SEC_ERROR_INVALID_ARGS);
4073 CERT_CreateSubjectCertList(NULL, dbhandle, subject,
4074 validTime, PR_TRUE);
4076 CERTCertListNode *node = CERT_LIST_HEAD(certList);
4078 /* XXX and authoritykeyid in the future */
4079 while ( ! CERT_LIST_END(node, certList) ) {
4080 CERTCertificate *cert = node->cert;
4081 /* check cert CERTCertTrust data is allocated, check cert
4082 usage extension, check that cert has pkey in db. Select
4083 the first (newest) user cert */
4085 CERT_CheckCertUsage(cert, KU_CRL_SIGN) == SECSuccess &&
4086 CERT_IsUserCert(cert)) {
4088 issuerCert = CERT_DupCertificate(cert);
4091 node = CERT_LIST_NEXT(node);
4093 CERT_DestroyCertList(certList);
4099 /* Encodes and adds extensions to the CRL or CRL entries. */
4101 SECU_EncodeAndAddExtensionValue(PRArenaPool *arena, void *extHandle,
4102 void *value, PRBool criticality, int extenType,
4103 EXTEN_EXT_VALUE_ENCODER EncodeValueFn)
4105 SECItem encodedValue;
4108 encodedValue.data = NULL;
4109 encodedValue.len = 0;
4111 rv = (*EncodeValueFn)(arena, value, &encodedValue);
4112 if (rv != SECSuccess)
4115 rv = CERT_AddExtension(extHandle, extenType, &encodedValue,
4116 criticality, PR_TRUE);
4117 if (rv != SECSuccess)
4124 /* Caller ensures that dst is at least item->len*2+1 bytes long */
4126 SECU_SECItemToHex(const SECItem * item, char * dst)
4128 if (dst && item && item->data) {
4129 unsigned char * src = item->data;
4130 unsigned int len = item->len;
4131 for (; len > 0; --len, dst += 2) {
4132 sprintf(dst, "%02x", *src++);
4138 static unsigned char nibble(char c) {
4139 c = PORT_Tolower(c);
4140 return ( c >= '0' && c <= '9') ? c - '0' :
4141 ( c >= 'a' && c <= 'f') ? c - 'a' +10 : -1;
4145 SECU_SECItemHexStringToBinary(SECItem* srcdest)
4150 PORT_SetError(SEC_ERROR_INVALID_ARGS);
4153 if (srcdest->len < 4 || (srcdest->len % 2) ) {
4154 /* too short to convert, or even number of characters */
4155 PORT_SetError(SEC_ERROR_BAD_DATA);
4158 if (PORT_Strncasecmp((const char*)srcdest->data, "0x", 2)) {
4160 PORT_SetError(SEC_ERROR_BAD_DATA);
4164 /* 1st pass to check for hex characters */
4165 for (i=2; i<srcdest->len; i++) {
4166 char c = PORT_Tolower(srcdest->data[i]);
4167 if (! ( ( c >= '0' && c <= '9') ||
4168 ( c >= 'a' && c <= 'f')
4170 PORT_SetError(SEC_ERROR_BAD_DATA);
4175 /* 2nd pass to convert */
4176 for (i=2; i<srcdest->len; i+=2) {
4177 srcdest->data[(i-2)/2] = (nibble(srcdest->data[i]) << 4) +
4178 nibble(srcdest->data[i+1]);
4188 SECU_FindCertByNicknameOrFilename(CERTCertDBHandle *handle,
4189 char *name, PRBool ascii,
4192 CERTCertificate *the_cert;
4193 the_cert = CERT_FindCertByNicknameOrEmailAddr(handle, name);
4197 the_cert = PK11_FindCertFromNickname(name, pwarg);
4199 /* Don't have a cert with name "name" in the DB. Try to
4200 * open a file with such name and get the cert from there.*/
4202 SECItem item = {0, NULL, 0};
4203 PRFileDesc* fd = PR_Open(name, PR_RDONLY, 0777);
4207 rv = SECU_ReadDERFromFile(&item, fd, ascii);
4209 if (rv != SECSuccess || !item.len) {
4210 PORT_Free(item.data);
4213 the_cert = CERT_NewTempCertificate(handle, &item,
4214 NULL /* nickname */,
4215 PR_FALSE /* isPerm */,
4216 PR_TRUE /* copyDER */);
4217 PORT_Free(item.data);