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
[] = {
92 SECU_GetString(int16 error_number
)
95 static char errString
[80];
96 sprintf(errString
, "Unknown error string (%d)", error_number
);
101 SECU_PrintErrMsg(FILE *out
, int level
, char *progName
, char *msg
, ...)
104 PRErrorCode err
= PORT_GetError();
105 const char * errString
= SECU_Strerror(err
);
109 SECU_Indent(out
, level
);
110 fprintf(out
, "%s: ", progName
);
111 vfprintf(out
, msg
, args
);
112 if (errString
!= NULL
&& PORT_Strlen(errString
) > 0)
113 fprintf(out
, ": %s\n", errString
);
115 fprintf(out
, ": error %d\n", (int)err
);
121 SECU_PrintError(char *progName
, char *msg
, ...)
124 PRErrorCode err
= PORT_GetError();
125 const char * errString
= SECU_Strerror(err
);
129 fprintf(stderr
, "%s: ", progName
);
130 vfprintf(stderr
, msg
, args
);
131 if (errString
!= NULL
&& PORT_Strlen(errString
) > 0)
132 fprintf(stderr
, ": %s\n", errString
);
134 fprintf(stderr
, ": error %d\n", (int)err
);
140 SECU_PrintSystemError(char *progName
, char *msg
, ...)
145 fprintf(stderr
, "%s: ", progName
);
146 vfprintf(stderr
, msg
, args
);
147 #if defined(_WIN32_WCE)
148 fprintf(stderr
, ": %d\n", PR_GetOSError());
150 fprintf(stderr
, ": %s\n", strerror(errno
));
156 secu_ClearPassword(char *p
)
159 PORT_Memset(p
, 0, PORT_Strlen(p
));
165 SECU_GetPasswordString(void *arg
, char *prompt
)
169 FILE *input
, *output
;
172 input
= fopen(consoleName
, "r");
174 fprintf(stderr
, "Error opening input terminal for read\n");
178 output
= fopen(consoleName
, "w");
179 if (output
== NULL
) {
180 fprintf(stderr
, "Error opening output terminal for write\n");
184 p
= SEC_GetPassword (input
, output
, prompt
, SEC_BlindCheckPassword
);
193 /* Win32 version of above. opening the console may fail
194 on windows95, and certainly isn't necessary.. */
198 p
= SEC_GetPassword (stdin
, stdout
, prompt
, SEC_BlindCheckPassword
);
206 * p a s s w o r d _ h a r d c o d e
208 * A function to use the password passed in the -f(pwfile) argument
209 * of the command line.
210 * After use once, null it out otherwise PKCS11 calls us forever.?
214 SECU_FilePasswd(PK11SlotInfo
*slot
, PRBool retry
, void *arg
)
216 unsigned char phrase
[200];
226 return 0; /* no good retrying - the files contents will be the same */
229 fd
= PR_Open(pwFile
, PR_RDONLY
, 0);
231 fprintf(stderr
, "No password file \"%s\" exists.\n", pwFile
);
235 nb
= PR_Read(fd
, phrase
, sizeof(phrase
));
238 /* handle the Windows EOL case */
240 while (phrase
[i
] != '\r' && phrase
[i
] != '\n' && i
< nb
) i
++;
243 fprintf(stderr
,"password file contains no data\n");
246 return (char*) PORT_Strdup((char*)phrase
);
250 SECU_GetModulePassword(PK11SlotInfo
*slot
, PRBool retry
, void *arg
)
253 secuPWData
*pwdata
= (secuPWData
*)arg
;
254 secuPWData pwnull
= { PW_NONE
, 0 };
255 secuPWData pwxtrn
= { PW_EXTERNAL
, "external" };
261 if (PK11_ProtectedAuthenticationPath(slot
)) {
264 if (retry
&& pwdata
->source
!= PW_NONE
) {
265 PR_fprintf(PR_STDERR
, "Incorrect password/PIN entered.\n");
269 switch (pwdata
->source
) {
271 sprintf(prompt
, "Enter Password or Pin for \"%s\":",
272 PK11_GetTokenName(slot
));
273 return SECU_GetPasswordString(NULL
, prompt
);
275 /* Instead of opening and closing the file every time, get the pw
276 * once, then keep it in memory (duh).
278 pw
= SECU_FilePasswd(slot
, retry
, pwdata
->data
);
279 pwdata
->source
= PW_PLAINTEXT
;
280 pwdata
->data
= PL_strdup(pw
);
281 /* it's already been dup'ed */
285 "Press Enter, then enter PIN for \"%s\" on external device.\n",
286 PK11_GetTokenName(slot
));
287 (void) SECU_GetPasswordString(NULL
, prompt
);
290 return PL_strdup(pwdata
->data
);
295 PR_fprintf(PR_STDERR
, "Password check failed: No password found.\n");
300 secu_InitSlotPassword(PK11SlotInfo
*slot
, PRBool retry
, void *arg
)
304 FILE *input
, *output
;
305 secuPWData
*pwdata
= arg
;
307 if (pwdata
->source
== PW_FROMFILE
) {
308 return SECU_FilePasswd(slot
, retry
, pwdata
->data
);
310 if (pwdata
->source
== PW_PLAINTEXT
) {
311 return PL_strdup(pwdata
->data
);
314 /* PW_NONE - get it from tty */
319 input
= fopen(consoleName
, "r");
322 PR_fprintf(PR_STDERR
, "Error opening input terminal for read\n");
326 /* we have no password, so initialize database with one */
327 PR_fprintf(PR_STDERR
,
328 "Enter a password which will be used to encrypt your keys.\n"
329 "The password should be at least 8 characters long,\n"
330 "and should contain at least one non-alphabetic character.\n\n");
332 output
= fopen(consoleName
, "w");
333 if (output
== NULL
) {
334 PR_fprintf(PR_STDERR
, "Error opening output terminal for write\n");
342 p0
= SEC_GetPassword(input
, output
, "Enter new password: ",
343 SEC_BlindCheckPassword
);
347 p1
= SEC_GetPassword(input
, output
, "Re-enter password: ",
348 SEC_BlindCheckPassword
);
349 if (p0
&& p1
&& !PORT_Strcmp(p0
, p1
)) {
352 PR_fprintf(PR_STDERR
, "Passwords do not match. Try again.\n");
355 /* clear out the duplicate password string */
356 secu_ClearPassword(p1
);
365 SECU_ChangePW(PK11SlotInfo
*slot
, char *passwd
, char *pwFile
)
367 return SECU_ChangePW2(slot
, passwd
, 0, pwFile
, 0);
371 SECU_ChangePW2(PK11SlotInfo
*slot
, char *oldPass
, char *newPass
,
372 char *oldPwFile
, char *newPwFile
)
375 secuPWData pwdata
, newpwdata
;
376 char *oldpw
= NULL
, *newpw
= NULL
;
379 pwdata
.source
= PW_PLAINTEXT
;
380 pwdata
.data
= oldPass
;
381 } else if (oldPwFile
) {
382 pwdata
.source
= PW_FROMFILE
;
383 pwdata
.data
= oldPwFile
;
385 pwdata
.source
= PW_NONE
;
390 newpwdata
.source
= PW_PLAINTEXT
;
391 newpwdata
.data
= newPass
;
392 } else if (newPwFile
) {
393 newpwdata
.source
= PW_FROMFILE
;
394 newpwdata
.data
= newPwFile
;
396 newpwdata
.source
= PW_NONE
;
397 newpwdata
.data
= NULL
;
400 if (PK11_NeedUserInit(slot
)) {
401 newpw
= secu_InitSlotPassword(slot
, PR_FALSE
, &pwdata
);
402 rv
= PK11_InitPin(slot
, (char*)NULL
, newpw
);
407 oldpw
= SECU_GetModulePassword(slot
, PR_FALSE
, &pwdata
);
409 if (PK11_CheckUserPassword(slot
, oldpw
) != SECSuccess
) {
410 if (pwdata
.source
== PW_NONE
) {
411 PR_fprintf(PR_STDERR
, "Invalid password. Try again.\n");
413 PR_fprintf(PR_STDERR
, "Invalid password.\n");
414 PORT_Memset(oldpw
, 0, PL_strlen(oldpw
));
424 newpw
= secu_InitSlotPassword(slot
, PR_FALSE
, &newpwdata
);
426 if (PK11_ChangePW(slot
, oldpw
, newpw
) != SECSuccess
) {
427 PR_fprintf(PR_STDERR
, "Failed to change password.\n");
431 PORT_Memset(oldpw
, 0, PL_strlen(oldpw
));
434 PR_fprintf(PR_STDOUT
, "Password changed successfully.\n");
437 PORT_Memset(newpw
, 0, PL_strlen(newpw
));
449 SECU_DefaultSSLDir(void)
452 static char sslDir
[1000];
454 dir
= PR_GetEnv("SSL_DIR");
458 sprintf(sslDir
, "%s", dir
);
460 if (sslDir
[strlen(sslDir
)-1] == '/')
461 sslDir
[strlen(sslDir
)-1] = 0;
467 SECU_AppendFilenameToDir(char *dir
, char *filename
)
469 static char path
[1000];
471 if (dir
[strlen(dir
)-1] == '/')
472 sprintf(path
, "%s%s", dir
, filename
);
474 sprintf(path
, "%s/%s", dir
, filename
);
479 SECU_ConfigDirectory(const char* base
)
481 static PRBool initted
= PR_FALSE
;
482 const char *dir
= ".netscape";
484 static char buf
[1000];
486 if (initted
) return buf
;
489 if (base
== NULL
|| *base
== 0) {
490 home
= PR_GetEnv("HOME");
491 if (!home
) home
= "";
493 if (*home
&& home
[strlen(home
) - 1] == '/')
494 sprintf (buf
, "%.900s%s", home
, dir
);
496 sprintf (buf
, "%.900s/%s", home
, dir
);
498 sprintf(buf
, "%.900s", base
);
499 if (buf
[strlen(buf
) - 1] == '/')
500 buf
[strlen(buf
) - 1] = 0;
508 /*Turn off SSL for now */
509 /* This gets called by SSL when server wants our cert & key */
511 SECU_GetClientAuthData(void *arg
, PRFileDesc
*fd
,
512 struct CERTDistNamesStr
*caNames
,
513 struct CERTCertificateStr
**pRetCert
,
514 struct SECKEYPrivateKeyStr
**pRetKey
)
516 SECKEYPrivateKey
*key
;
517 CERTCertificate
*cert
;
521 fprintf(stderr
, "no key/cert name specified for client auth\n");
524 cert
= PK11_FindCertFromNickname(arg
, NULL
);
525 errsave
= PORT_GetError();
527 if (errsave
== SEC_ERROR_BAD_PASSWORD
)
528 fprintf(stderr
, "Bad password\n");
529 else if (errsave
> 0)
530 fprintf(stderr
, "Unable to read cert (error %d)\n", errsave
);
531 else if (errsave
== SEC_ERROR_BAD_DATABASE
)
532 fprintf(stderr
, "Unable to get cert from database (%d)\n", errsave
);
534 fprintf(stderr
, "SECKEY_FindKeyByName: internal error %d\n", errsave
);
538 key
= PK11_FindKeyByAnyCert(arg
,NULL
);
540 fprintf(stderr
, "Unable to get key (%d)\n", PORT_GetError());
552 secu_StdinToItem(SECItem
*dst
)
554 unsigned char buf
[1000];
556 PRBool notDone
= PR_TRUE
;
562 numBytes
= PR_Read(PR_STDIN
, buf
, sizeof(buf
));
572 unsigned char * p
= dst
->data
;
573 dst
->data
= (unsigned char*)PORT_Realloc(p
, dst
->len
+ numBytes
);
578 dst
->data
= (unsigned char*)PORT_Alloc(numBytes
);
583 PORT_Memcpy(dst
->data
+ dst
->len
, buf
, numBytes
);
584 dst
->len
+= numBytes
;
591 SECU_FileToItem(SECItem
*dst
, PRFileDesc
*src
)
598 return secu_StdinToItem(dst
);
600 prStatus
= PR_GetOpenFileInfo(src
, &info
);
602 if (prStatus
!= PR_SUCCESS
) {
603 PORT_SetError(SEC_ERROR_IO
);
607 /* XXX workaround for 3.1, not all utils zero dst before sending */
609 if (!SECITEM_AllocItem(NULL
, dst
, info
.size
))
612 numBytes
= PR_Read(src
, dst
->data
, info
.size
);
613 if (numBytes
!= info
.size
) {
614 PORT_SetError(SEC_ERROR_IO
);
620 SECITEM_FreeItem(dst
, PR_FALSE
);
626 SECU_TextFileToItem(SECItem
*dst
, PRFileDesc
*src
)
634 return secu_StdinToItem(dst
);
636 prStatus
= PR_GetOpenFileInfo(src
, &info
);
638 if (prStatus
!= PR_SUCCESS
) {
639 PORT_SetError(SEC_ERROR_IO
);
643 buf
= (unsigned char*)PORT_Alloc(info
.size
);
647 numBytes
= PR_Read(src
, buf
, info
.size
);
648 if (numBytes
!= info
.size
) {
649 PORT_SetError(SEC_ERROR_IO
);
653 if (buf
[numBytes
-1] == '\n') numBytes
--;
655 if (buf
[numBytes
-1] == '\r') numBytes
--;
658 /* XXX workaround for 3.1, not all utils zero dst before sending */
660 if (!SECITEM_AllocItem(NULL
, dst
, numBytes
))
663 memcpy(dst
->data
, buf
, numBytes
);
673 SECU_ReadDERFromFile(SECItem
*der
, PRFileDesc
*inFile
, PRBool ascii
)
677 /* First convert ascii to binary */
681 /* Read in ascii data */
682 rv
= SECU_FileToItem(&filedata
, inFile
);
683 asc
= (char *)filedata
.data
;
685 fprintf(stderr
, "unable to read data from input file\n");
689 /* check for headers and trailers and remove them */
690 if ((body
= strstr(asc
, "-----BEGIN")) != NULL
) {
691 char *trailer
= NULL
;
693 body
= PORT_Strchr(body
, '\n');
695 body
= PORT_Strchr(asc
, '\r'); /* maybe this is a MAC file */
697 trailer
= strstr(++body
, "-----END");
698 if (trailer
!= NULL
) {
701 fprintf(stderr
, "input has header but no trailer\n");
702 PORT_Free(filedata
.data
);
709 /* Convert to binary */
710 rv
= ATOB_ConvertAsciiToItem(der
, body
);
712 fprintf(stderr
, "error converting ascii to binary (%s)\n",
713 SECU_Strerror(PORT_GetError()));
714 PORT_Free(filedata
.data
);
718 PORT_Free(filedata
.data
);
720 /* Read in binary der */
721 rv
= SECU_FileToItem(der
, inFile
);
723 fprintf(stderr
, "error converting der (%s)\n",
724 SECU_Strerror(PORT_GetError()));
731 #define INDENT_MULT 4
733 SECU_Indent(FILE *out
, int level
)
737 for (i
= 0; i
< level
; i
++) {
742 static void secu_Newline(FILE *out
)
748 SECU_PrintAsHex(FILE *out
, SECItem
*data
, const char *m
, int level
)
752 PRBool isString
= PR_TRUE
;
753 PRBool isWhiteSpace
= PR_TRUE
;
754 PRBool printedHex
= PR_FALSE
;
755 unsigned int limit
= 15;
758 SECU_Indent(out
, level
); fprintf(out
, "%s:\n", m
);
762 SECU_Indent(out
, level
); column
= level
*INDENT_MULT
;
764 fprintf(out
, "(empty)\n");
767 /* take a pass to see if it's all printable. */
768 for (i
= 0; i
< data
->len
; i
++) {
769 unsigned char val
= data
->data
[i
];
770 if (!val
|| !isprint(val
)) {
774 if (isWhiteSpace
&& !isspace(val
)) {
775 isWhiteSpace
= PR_FALSE
;
779 /* Short values, such as bit strings (which are printed with this
780 ** function) often look like strings, but we want to see the bits.
781 ** so this test assures that short values will be printed in hex,
782 ** perhaps in addition to being printed as strings.
783 ** The threshold size (4 bytes) is arbitrary.
785 if (!isString
|| data
->len
<= 4) {
786 for (i
= 0; i
< data
->len
; i
++) {
787 if (i
!= data
->len
- 1) {
788 fprintf(out
, "%02x:", data
->data
[i
]);
791 fprintf(out
, "%02x", data
->data
[i
]);
795 if (column
> 76 || (i
% 16 == limit
)) {
797 SECU_Indent(out
, level
);
798 column
= level
*INDENT_MULT
;
802 printedHex
= PR_TRUE
;
804 if (isString
&& !isWhiteSpace
) {
805 if (printedHex
!= PR_FALSE
) {
807 SECU_Indent(out
, level
); column
= level
*INDENT_MULT
;
809 for (i
= 0; i
< data
->len
; i
++) {
810 unsigned char val
= data
->data
[i
];
813 fprintf(out
,"%c",val
);
820 SECU_Indent(out
, level
); column
= level
*INDENT_MULT
;
825 if (column
!= level
*INDENT_MULT
) {
830 static const char *hex
= "0123456789abcdef";
832 static const char printable
[257] = {
833 "................" /* 0x */
834 "................" /* 1x */
835 " !\"#$%&'()*+,-./" /* 2x */
836 "0123456789:;<=>?" /* 3x */
837 "@ABCDEFGHIJKLMNO" /* 4x */
838 "PQRSTUVWXYZ[\\]^_" /* 5x */
839 "`abcdefghijklmno" /* 6x */
840 "pqrstuvwxyz{|}~." /* 7x */
841 "................" /* 8x */
842 "................" /* 9x */
843 "................" /* ax */
844 "................" /* bx */
845 "................" /* cx */
846 "................" /* dx */
847 "................" /* ex */
848 "................" /* fx */
852 SECU_PrintBuf(FILE *out
, const char *msg
, const void *vp
, int len
)
854 const unsigned char *cp
= (const unsigned char *)vp
;
859 fprintf(out
, "%s [Len: %d]\n", msg
, len
);
860 memset(buf
, ' ', sizeof buf
);
864 unsigned char ch
= *cp
++;
865 *bp
++ = hex
[(ch
>> 4) & 0xf];
866 *bp
++ = hex
[ch
& 0xf];
868 *ap
++ = printable
[ch
];
869 if (ap
- buf
>= 66) {
871 fprintf(out
, " %s\n", buf
);
872 memset(buf
, ' ', sizeof buf
);
879 fprintf(out
, " %s\n", buf
);
884 SECU_StripTagAndLength(SECItem
*i
)
888 if (!i
|| !i
->data
|| i
->len
< 2) { /* must be at least tag and length */
891 start
= ((i
->data
[1] & 0x80) ? (i
->data
[1] & 0x7f) + 2 : 2);
892 if (i
->len
< start
) {
901 /* This expents i->data[0] to be the MSB of the integer.
902 ** if you want to print a DER-encoded integer (with the tag and length)
903 ** call SECU_PrintEncodedInteger();
906 SECU_PrintInteger(FILE *out
, SECItem
*i
, char *m
, int level
)
910 if (!i
|| !i
->len
|| !i
->data
) {
911 SECU_Indent(out
, level
);
913 fprintf(out
, "%s: (null)\n", m
);
915 fprintf(out
, "(null)\n");
917 } else if (i
->len
> 4) {
918 SECU_PrintAsHex(out
, i
, m
, level
);
920 if (i
->type
== siUnsignedInteger
&& *i
->data
& 0x80) {
921 /* Make sure i->data has zero in the highest bite
922 * if i->data is an unsigned integer */
924 char data
[] = {0, 0, 0, 0, 0};
926 PORT_Memcpy(data
+ 1, i
->data
, i
->len
);
927 tmpI
.len
= i
->len
+ 1;
928 tmpI
.data
= (void*)data
;
930 iv
= DER_GetInteger(&tmpI
);
932 iv
= DER_GetInteger(i
);
934 SECU_Indent(out
, level
);
936 fprintf(out
, "%s: %d (0x%x)\n", m
, iv
, iv
);
938 fprintf(out
, "%d (0x%x)\n", iv
, iv
);
944 secu_PrintRawString(FILE *out
, SECItem
*si
, char *m
, int level
)
950 SECU_Indent(out
, level
); fprintf(out
, "%s: ", m
);
951 column
= (level
* INDENT_MULT
) + strlen(m
) + 2;
954 SECU_Indent(out
, level
);
955 column
= level
*INDENT_MULT
;
957 fprintf(out
, "\""); column
++;
959 for (i
= 0; i
< si
->len
; i
++) {
960 unsigned char val
= si
->data
[i
];
963 SECU_Indent(out
, level
); column
= level
*INDENT_MULT
;
966 fprintf(out
,"%c", printable
[val
]); column
++;
969 fprintf(out
, "\""); column
++;
970 if (column
!= level
*INDENT_MULT
|| column
> 76) {
976 SECU_PrintString(FILE *out
, SECItem
*si
, char *m
, int level
)
980 if (SECSuccess
!= SECU_StripTagAndLength(&my
) || !my
.len
)
982 secu_PrintRawString(out
, &my
, m
, level
);
985 /* print an unencoded boolean */
987 secu_PrintBoolean(FILE *out
, SECItem
*i
, const char *m
, int level
)
991 if ( i
->data
&& i
->len
) {
998 SECU_Indent(out
, level
);
999 fprintf(out
, "%s: %s\n", m
, (val
? "True" : "False"));
1003 * Format and print "time". If the tag message "m" is not NULL,
1004 * do indent formatting based on "level" and add a newline afterward;
1005 * otherwise just print the formatted time string only.
1008 secu_PrintTime(FILE *out
, int64 time
, char *m
, int level
)
1010 PRExplodedTime printableTime
;
1013 /* Convert to local time */
1014 PR_ExplodeTime(time
, PR_GMTParameters
, &printableTime
);
1016 timeString
= PORT_Alloc(100);
1017 if (timeString
== NULL
)
1021 SECU_Indent(out
, level
);
1022 fprintf(out
, "%s: ", m
);
1025 PR_FormatTime(timeString
, 100, "%a %b %d %H:%M:%S %Y", &printableTime
);
1026 fprintf(out
, timeString
);
1031 PORT_Free(timeString
);
1035 * Format and print the UTC Time "t". If the tag message "m" is not NULL,
1036 * do indent formatting based on "level" and add a newline afterward;
1037 * otherwise just print the formatted time string only.
1040 SECU_PrintUTCTime(FILE *out
, SECItem
*t
, char *m
, int level
)
1045 rv
= DER_UTCTimeToTime(&time
, t
);
1046 if (rv
!= SECSuccess
)
1049 secu_PrintTime(out
, time
, m
, level
);
1053 * Format and print the Generalized Time "t". If the tag message "m"
1054 * is not NULL, * do indent formatting based on "level" and add a newline
1055 * afterward; otherwise just print the formatted time string only.
1058 SECU_PrintGeneralizedTime(FILE *out
, SECItem
*t
, char *m
, int level
)
1064 rv
= DER_GeneralizedTimeToTime(&time
, t
);
1065 if (rv
!= SECSuccess
)
1068 secu_PrintTime(out
, time
, m
, level
);
1072 * Format and print the UTC or Generalized Time "t". If the tag message
1073 * "m" is not NULL, do indent formatting based on "level" and add a newline
1074 * afterward; otherwise just print the formatted time string only.
1077 SECU_PrintTimeChoice(FILE *out
, SECItem
*t
, char *m
, int level
)
1081 SECU_PrintUTCTime(out
, t
, m
, level
);
1084 case siGeneralizedTime
:
1085 SECU_PrintGeneralizedTime(out
, t
, m
, level
);
1095 /* This prints a SET or SEQUENCE */
1097 SECU_PrintSet(FILE *out
, SECItem
*t
, char *m
, int level
)
1099 int type
= t
->data
[0] & SEC_ASN1_TAGNUM_MASK
;
1100 int constructed
= t
->data
[0] & SEC_ASN1_CONSTRUCTED
;
1105 SECU_PrintAsHex(out
, t
, m
, level
);
1108 if (SECSuccess
!= SECU_StripTagAndLength(&my
))
1111 SECU_Indent(out
, level
);
1113 fprintf(out
, "%s: ", m
);
1116 if (type
== SEC_ASN1_SET
)
1118 else if (type
== SEC_ASN1_SEQUENCE
)
1119 label
= "Sequence ";
1122 fprintf(out
,"%s{\n", label
); /* } */
1124 while (my
.len
>= 2) {
1127 if (tmp
.data
[1] & 0x80) {
1129 unsigned int lenlen
= tmp
.data
[1] & 0x7f;
1130 if (lenlen
> sizeof tmp
.len
)
1133 for (i
=0; i
< lenlen
; i
++) {
1134 tmp
.len
= (tmp
.len
<< 8) | tmp
.data
[2+i
];
1136 tmp
.len
+= lenlen
+ 2;
1138 tmp
.len
= tmp
.data
[1] + 2;
1140 if (tmp
.len
> my
.len
) {
1145 SECU_PrintAny(out
, &tmp
, NULL
, level
+ 1);
1147 SECU_Indent(out
, level
); fprintf(out
, /* { */ "}\n");
1151 secu_PrintContextSpecific(FILE *out
, SECItem
*i
, char *m
, int level
)
1153 int type
= i
->data
[0] & SEC_ASN1_TAGNUM_MASK
;
1154 int constructed
= i
->data
[0] & SEC_ASN1_CONSTRUCTED
;
1160 m2
= PR_smprintf("[%d]", type
);
1162 m2
= PR_smprintf("%s: [%d]", m
, type
);
1164 SECU_PrintSet(out
, i
, m2
, level
);
1165 PR_smprintf_free(m2
);
1170 SECU_Indent(out
, level
);
1172 fprintf(out
, "%s: ", m
);
1174 fprintf(out
,"[%d]\n", type
);
1177 if (SECSuccess
== SECU_StripTagAndLength(&tmp
))
1178 SECU_PrintAsHex(out
, &tmp
, m
, level
+1);
1182 secu_PrintOctetString(FILE *out
, SECItem
*i
, char *m
, int level
)
1185 if (SECSuccess
== SECU_StripTagAndLength(&tmp
))
1186 SECU_PrintAsHex(out
, &tmp
, m
, level
);
1190 secu_PrintBitString(FILE *out
, SECItem
*i
, char *m
, int level
)
1195 if (SECSuccess
!= SECU_StripTagAndLength(&tmp
) || tmp
.len
< 2)
1198 unused_bits
= *tmp
.data
++;
1201 SECU_PrintAsHex(out
, &tmp
, m
, level
);
1203 SECU_Indent(out
, level
+ 1);
1204 fprintf(out
, "(%d least significant bits unused)\n", unused_bits
);
1208 /* in a decoded bit string, the len member is a bit length. */
1210 secu_PrintDecodedBitString(FILE *out
, SECItem
*i
, char *m
, int level
)
1216 unused_bits
= (tmp
.len
& 0x7) ? 8 - (tmp
.len
& 7) : 0;
1217 DER_ConvertBitString(&tmp
); /* convert length to byte length */
1219 SECU_PrintAsHex(out
, &tmp
, m
, level
);
1221 SECU_Indent(out
, level
+ 1);
1222 fprintf(out
, "(%d least significant bits unused)\n", unused_bits
);
1227 /* Print a DER encoded Boolean */
1229 SECU_PrintEncodedBoolean(FILE *out
, SECItem
*i
, char *m
, int level
)
1232 if (SECSuccess
== SECU_StripTagAndLength(&my
))
1233 secu_PrintBoolean(out
, &my
, m
, level
);
1236 /* Print a DER encoded integer */
1238 SECU_PrintEncodedInteger(FILE *out
, SECItem
*i
, char *m
, int level
)
1241 if (SECSuccess
== SECU_StripTagAndLength(&my
))
1242 SECU_PrintInteger(out
, &my
, m
, level
);
1245 /* Print a DER encoded OID */
1247 SECU_PrintEncodedObjectID(FILE *out
, SECItem
*i
, char *m
, int level
)
1250 if (SECSuccess
== SECU_StripTagAndLength(&my
))
1251 SECU_PrintObjectID(out
, &my
, m
, level
);
1255 secu_PrintBMPString(FILE *out
, SECItem
*i
, char *m
, int level
)
1260 SECItem tmp
= {0, 0, 0};
1263 if (SECSuccess
!= SECU_StripTagAndLength(&my
))
1267 len
= (int)(my
.len
/ 2);
1268 tmp
.data
= (unsigned char *)PORT_Alloc(len
);
1272 for (s
= my
.data
, d
= tmp
.data
; len
> 0; len
--) {
1273 PRUint32 bmpChar
= (s
[0] << 8) | s
[1]; s
+= 2;
1274 if (!isprint(bmpChar
))
1276 *d
++ = (unsigned char)bmpChar
;
1278 secu_PrintRawString(out
, &tmp
, m
, level
);
1279 PORT_Free(tmp
.data
);
1283 SECU_PrintAsHex(out
, i
, m
, level
);
1285 PORT_Free(tmp
.data
);
1289 secu_PrintUniversalString(FILE *out
, SECItem
*i
, char *m
, int level
)
1294 SECItem tmp
= {0, 0, 0};
1297 if (SECSuccess
!= SECU_StripTagAndLength(&my
))
1301 len
= (int)(my
.len
/ 4);
1302 tmp
.data
= (unsigned char *)PORT_Alloc(len
);
1306 for (s
= my
.data
, d
= tmp
.data
; len
> 0; len
--) {
1307 PRUint32 bmpChar
= (s
[0] << 24) | (s
[1] << 16) | (s
[2] << 8) | s
[3];
1309 if (!isprint(bmpChar
))
1311 *d
++ = (unsigned char)bmpChar
;
1313 secu_PrintRawString(out
, &tmp
, m
, level
);
1314 PORT_Free(tmp
.data
);
1318 SECU_PrintAsHex(out
, i
, m
, level
);
1320 PORT_Free(tmp
.data
);
1324 secu_PrintUniversal(FILE *out
, SECItem
*i
, char *m
, int level
)
1326 switch (i
->data
[0] & SEC_ASN1_TAGNUM_MASK
) {
1327 case SEC_ASN1_ENUMERATED
:
1328 case SEC_ASN1_INTEGER
:
1329 SECU_PrintEncodedInteger(out
, i
, m
, level
);
1331 case SEC_ASN1_OBJECT_ID
:
1332 SECU_PrintEncodedObjectID(out
, i
, m
, level
);
1334 case SEC_ASN1_BOOLEAN
:
1335 SECU_PrintEncodedBoolean(out
, i
, m
, level
);
1337 case SEC_ASN1_UTF8_STRING
:
1338 case SEC_ASN1_PRINTABLE_STRING
:
1339 case SEC_ASN1_VISIBLE_STRING
:
1340 case SEC_ASN1_IA5_STRING
:
1341 case SEC_ASN1_T61_STRING
:
1342 SECU_PrintString(out
, i
, m
, level
);
1344 case SEC_ASN1_GENERALIZED_TIME
:
1345 SECU_PrintGeneralizedTime(out
, i
, m
, level
);
1347 case SEC_ASN1_UTC_TIME
:
1348 SECU_PrintUTCTime(out
, i
, m
, level
);
1351 SECU_Indent(out
, level
);
1353 fprintf(out
, "%s: NULL\n", m
);
1355 fprintf(out
, "NULL\n");
1358 case SEC_ASN1_SEQUENCE
:
1359 SECU_PrintSet(out
, i
, m
, level
);
1361 case SEC_ASN1_OCTET_STRING
:
1362 secu_PrintOctetString(out
, i
, m
, level
);
1364 case SEC_ASN1_BIT_STRING
:
1365 secu_PrintBitString(out
, i
, m
, level
);
1367 case SEC_ASN1_BMP_STRING
:
1368 secu_PrintBMPString(out
, i
, m
, level
);
1370 case SEC_ASN1_UNIVERSAL_STRING
:
1371 secu_PrintUniversalString(out
, i
, m
, level
);
1374 SECU_PrintAsHex(out
, i
, m
, level
);
1380 SECU_PrintAny(FILE *out
, SECItem
*i
, char *m
, int level
)
1382 if ( i
&& i
->len
&& i
->data
) {
1383 switch (i
->data
[0] & SEC_ASN1_CLASS_MASK
) {
1384 case SEC_ASN1_CONTEXT_SPECIFIC
:
1385 secu_PrintContextSpecific(out
, i
, m
, level
);
1387 case SEC_ASN1_UNIVERSAL
:
1388 secu_PrintUniversal(out
, i
, m
, level
);
1391 SECU_PrintAsHex(out
, i
, m
, level
);
1398 secu_PrintValidity(FILE *out
, CERTValidity
*v
, char *m
, int level
)
1400 SECU_Indent(out
, level
); fprintf(out
, "%s:\n", m
);
1401 SECU_PrintTimeChoice(out
, &v
->notBefore
, "Not Before", level
+1);
1402 SECU_PrintTimeChoice(out
, &v
->notAfter
, "Not After ", level
+1);
1406 /* This function does NOT expect a DER type and length. */
1408 SECU_PrintObjectID(FILE *out
, SECItem
*oid
, char *m
, int level
)
1410 SECOidData
*oiddata
;
1411 char * oidString
= NULL
;
1413 oiddata
= SECOID_FindOID(oid
);
1414 if (oiddata
!= NULL
) {
1415 const char *name
= oiddata
->desc
;
1416 SECU_Indent(out
, level
);
1418 fprintf(out
, "%s: ", m
);
1419 fprintf(out
, "%s\n", name
);
1420 return oiddata
->offset
;
1422 oidString
= CERT_GetOidString(oid
);
1424 SECU_Indent(out
, level
);
1426 fprintf(out
, "%s: ", m
);
1427 fprintf(out
, "%s\n", oidString
);
1428 PR_smprintf_free(oidString
);
1429 return SEC_OID_UNKNOWN
;
1431 SECU_PrintAsHex(out
, oid
, m
, level
);
1432 return SEC_OID_UNKNOWN
;
1435 typedef struct secuPBEParamsStr
{
1437 SECItem iterationCount
;
1439 SECAlgorithmID cipherAlg
;
1440 SECAlgorithmID kdfAlg
;
1443 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate
);
1445 /* SECOID_PKCS5_PBKDF2 */
1446 const SEC_ASN1Template secuKDF2Params
[] =
1448 { SEC_ASN1_SEQUENCE
, 0, NULL
, sizeof(secuPBEParams
) },
1449 { SEC_ASN1_OCTET_STRING
, offsetof(secuPBEParams
, salt
) },
1450 { SEC_ASN1_INTEGER
, offsetof(secuPBEParams
, iterationCount
) },
1451 { SEC_ASN1_INTEGER
, offsetof(secuPBEParams
, keyLength
) },
1452 { SEC_ASN1_INLINE
| SEC_ASN1_XTRN
, offsetof(secuPBEParams
, kdfAlg
),
1453 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate
) },
1457 /* PKCS5v1 & PKCS12 */
1458 const SEC_ASN1Template secuPBEParamsTemp
[] =
1460 { SEC_ASN1_SEQUENCE
, 0, NULL
, sizeof(secuPBEParams
) },
1461 { SEC_ASN1_OCTET_STRING
, offsetof(secuPBEParams
, salt
) },
1462 { SEC_ASN1_INTEGER
, offsetof(secuPBEParams
, iterationCount
) },
1466 /* SEC_OID_PKCS5_PBES2, SEC_OID_PKCS5_PBMAC1 */
1467 const SEC_ASN1Template secuPBEV2Params
[] =
1469 { SEC_ASN1_SEQUENCE
, 0, NULL
, sizeof(secuPBEParams
)},
1470 { SEC_ASN1_INLINE
| SEC_ASN1_XTRN
, offsetof(secuPBEParams
, kdfAlg
),
1471 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate
) },
1472 { SEC_ASN1_INLINE
| SEC_ASN1_XTRN
, offsetof(secuPBEParams
, cipherAlg
),
1473 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate
) },
1478 secu_PrintKDF2Params(FILE *out
, SECItem
*value
, char *m
, int level
)
1480 PRArenaPool
*pool
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
1482 secuPBEParams param
;
1485 SECU_Indent(out
, level
);
1486 fprintf (out
, "%s:\n", m
);
1490 SECU_Indent(out
, level
);
1491 fprintf(out
, "Out of memory\n");
1495 PORT_Memset(¶m
, 0, sizeof param
);
1496 rv
= SEC_QuickDERDecodeItem(pool
, ¶m
, secuKDF2Params
, value
);
1497 if (rv
== SECSuccess
) {
1498 SECU_PrintAsHex(out
, ¶m
.salt
, "Salt", level
+1);
1499 SECU_PrintInteger(out
, ¶m
.iterationCount
, "Iteration Count",
1501 SECU_PrintInteger(out
, ¶m
.keyLength
, "Key Length", level
+1);
1502 SECU_PrintAlgorithmID(out
, ¶m
.kdfAlg
, "KDF algorithm", level
+1);
1504 PORT_FreeArena(pool
, PR_FALSE
);
1508 secu_PrintPKCS5V2Params(FILE *out
, SECItem
*value
, char *m
, int level
)
1510 PRArenaPool
*pool
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
1512 secuPBEParams param
;
1515 SECU_Indent(out
, level
);
1516 fprintf (out
, "%s:\n", m
);
1520 SECU_Indent(out
, level
);
1521 fprintf(out
, "Out of memory\n");
1525 PORT_Memset(¶m
, 0, sizeof param
);
1526 rv
= SEC_QuickDERDecodeItem(pool
, ¶m
, secuPBEV2Params
, value
);
1527 if (rv
== SECSuccess
) {
1528 SECU_PrintAlgorithmID(out
, ¶m
.kdfAlg
, "KDF", level
+1);
1529 SECU_PrintAlgorithmID(out
, ¶m
.cipherAlg
, "Cipher", level
+1);
1531 PORT_FreeArena(pool
, PR_FALSE
);
1535 secu_PrintPBEParams(FILE *out
, SECItem
*value
, char *m
, int level
)
1537 PRArenaPool
*pool
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
1539 secuPBEParams param
;
1542 SECU_Indent(out
, level
);
1543 fprintf (out
, "%s:\n", m
);
1547 SECU_Indent(out
, level
);
1548 fprintf(out
, "Out of memory\n");
1552 PORT_Memset(¶m
, 0, sizeof(secuPBEParams
));
1553 rv
= SEC_QuickDERDecodeItem(pool
, ¶m
, secuPBEParamsTemp
, value
);
1554 if (rv
== SECSuccess
) {
1555 SECU_PrintAsHex(out
, ¶m
.salt
, "Salt", level
+1);
1556 SECU_PrintInteger(out
, ¶m
.iterationCount
, "Iteration Count",
1559 PORT_FreeArena(pool
, PR_FALSE
);
1562 /* This function does NOT expect a DER type and length. */
1564 SECU_PrintAlgorithmID(FILE *out
, SECAlgorithmID
*a
, char *m
, int level
)
1567 SECU_PrintObjectID(out
, &a
->algorithm
, m
, level
);
1569 algtag
= SECOID_GetAlgorithmTag(a
);
1570 if (SEC_PKCS5IsAlgorithmPBEAlgTag(algtag
)) {
1572 case SEC_OID_PKCS5_PBKDF2
:
1573 secu_PrintKDF2Params(out
, &a
->parameters
, "Parameters", level
+1);
1575 case SEC_OID_PKCS5_PBES2
:
1576 secu_PrintPKCS5V2Params(out
, &a
->parameters
, "Encryption", level
+1);
1578 case SEC_OID_PKCS5_PBMAC1
:
1579 secu_PrintPKCS5V2Params(out
, &a
->parameters
, "MAC", level
+1);
1582 secu_PrintPBEParams(out
, &a
->parameters
, "Parameters", level
+1);
1589 if (a
->parameters
.len
== 0
1590 || (a
->parameters
.len
== 2
1591 && PORT_Memcmp(a
->parameters
.data
, "\005\000", 2) == 0)) {
1592 /* No arguments or NULL argument */
1594 /* Print args to algorithm */
1595 SECU_PrintAsHex(out
, &a
->parameters
, "Args", level
+1);
1600 secu_PrintAttribute(FILE *out
, SEC_PKCS7Attribute
*attr
, char *m
, int level
)
1607 SECU_Indent(out
, level
); fprintf(out
, "%s:\n", m
);
1611 * Should make this smarter; look at the type field and then decode
1612 * and print the value(s) appropriately!
1614 SECU_PrintObjectID(out
, &(attr
->type
), "Type", level
+1);
1615 if (attr
->values
!= NULL
) {
1617 while ((value
= attr
->values
[i
++]) != NULL
) {
1618 sprintf(om
, "Value (%d)%s", i
, attr
->encoded
? " (encoded)" : "");
1619 if (attr
->encoded
|| attr
->typeTag
== NULL
) {
1620 SECU_PrintAny(out
, value
, om
, level
+1);
1622 switch (attr
->typeTag
->offset
) {
1624 SECU_PrintAsHex(out
, value
, om
, level
+1);
1626 case SEC_OID_PKCS9_CONTENT_TYPE
:
1627 SECU_PrintObjectID(out
, value
, om
, level
+1);
1629 case SEC_OID_PKCS9_SIGNING_TIME
:
1630 SECU_PrintTimeChoice(out
, value
, om
, level
+1);
1639 secu_PrintRSAPublicKey(FILE *out
, SECKEYPublicKey
*pk
, char *m
, int level
)
1642 SECU_Indent(out
, level
); fprintf(out
, "%s:\n", m
);
1643 SECU_PrintInteger(out
, &pk
->u
.rsa
.modulus
, "Modulus", level
+1);
1644 SECU_PrintInteger(out
, &pk
->u
.rsa
.publicExponent
, "Exponent", level
+1);
1645 if (pk
->u
.rsa
.publicExponent
.len
== 1 &&
1646 pk
->u
.rsa
.publicExponent
.data
[0] == 1) {
1647 SECU_Indent(out
, level
+1); fprintf(out
, "Error: INVALID RSA KEY!\n");
1652 secu_PrintDSAPublicKey(FILE *out
, SECKEYPublicKey
*pk
, char *m
, int level
)
1654 SECU_Indent(out
, level
); fprintf(out
, "%s:\n", m
);
1655 SECU_PrintInteger(out
, &pk
->u
.dsa
.params
.prime
, "Prime", level
+1);
1656 SECU_PrintInteger(out
, &pk
->u
.dsa
.params
.subPrime
, "Subprime", level
+1);
1657 SECU_PrintInteger(out
, &pk
->u
.dsa
.params
.base
, "Base", level
+1);
1658 SECU_PrintInteger(out
, &pk
->u
.dsa
.publicValue
, "PublicValue", level
+1);
1661 #ifdef NSS_ENABLE_ECC
1663 secu_PrintECPublicKey(FILE *out
, SECKEYPublicKey
*pk
, char *m
, int level
)
1665 SECItem curveOID
= { siBuffer
, NULL
, 0};
1667 SECU_Indent(out
, level
); fprintf(out
, "%s:\n", m
);
1668 SECU_PrintInteger(out
, &pk
->u
.ec
.publicValue
, "PublicValue", level
+1);
1669 /* For named curves, the DEREncodedParams field contains an
1670 * ASN Object ID (0x06 is SEC_ASN1_OBJECT_ID).
1672 if ((pk
->u
.ec
.DEREncodedParams
.len
> 2) &&
1673 (pk
->u
.ec
.DEREncodedParams
.data
[0] == 0x06)) {
1674 curveOID
.len
= pk
->u
.ec
.DEREncodedParams
.data
[1];
1675 curveOID
.data
= pk
->u
.ec
.DEREncodedParams
.data
+ 2;
1676 SECU_PrintObjectID(out
, &curveOID
, "Curve", level
+1);
1679 #endif /* NSS_ENABLE_ECC */
1682 secu_PrintSubjectPublicKeyInfo(FILE *out
, PRArenaPool
*arena
,
1683 CERTSubjectPublicKeyInfo
*i
, char *msg
, int level
)
1685 SECKEYPublicKey
*pk
;
1687 SECU_Indent(out
, level
); fprintf(out
, "%s:\n", msg
);
1688 SECU_PrintAlgorithmID(out
, &i
->algorithm
, "Public Key Algorithm", level
+1);
1690 pk
= SECKEY_ExtractPublicKey(i
);
1692 switch (pk
->keyType
) {
1694 secu_PrintRSAPublicKey(out
, pk
, "RSA Public Key", level
+1);
1698 secu_PrintDSAPublicKey(out
, pk
, "DSA Public Key", level
+1);
1701 #ifdef NSS_ENABLE_ECC
1703 secu_PrintECPublicKey(out
, pk
, "EC Public Key", level
+1);
1710 SECU_Indent(out
, level
);
1711 fprintf(out
, "unable to format this SPKI algorithm type\n");
1714 SECU_Indent(out
, level
);
1715 fprintf(out
, "unknown SPKI algorithm type\n");
1718 PORT_FreeArena(pk
->arena
, PR_FALSE
);
1720 SECU_PrintErrMsg(out
, level
, "Error", "Parsing public key");
1722 if (i
->subjectPublicKey
.data
) {
1723 SECU_PrintAny(out
, &i
->subjectPublicKey
, "Raw", level
);
1729 secu_PrintX509InvalidDate(FILE *out
, SECItem
*value
, char *msg
, int level
)
1731 SECItem decodedValue
;
1734 char *formattedTime
= NULL
;
1736 decodedValue
.data
= NULL
;
1737 rv
= SEC_ASN1DecodeItem (NULL
, &decodedValue
,
1738 SEC_ASN1_GET(SEC_GeneralizedTimeTemplate
),
1740 if (rv
== SECSuccess
) {
1741 rv
= DER_GeneralizedTimeToTime(&invalidTime
, &decodedValue
);
1742 if (rv
== SECSuccess
) {
1743 formattedTime
= CERT_GenTime2FormattedAscii
1744 (invalidTime
, "%a %b %d %H:%M:%S %Y");
1745 SECU_Indent(out
, level
+1);
1746 fprintf (out
, "%s: %s\n", msg
, formattedTime
);
1747 PORT_Free (formattedTime
);
1750 PORT_Free (decodedValue
.data
);
1755 PrintExtKeyUsageExtension (FILE *out
, SECItem
*value
, char *msg
, int level
)
1757 CERTOidSequence
*os
;
1760 os
= CERT_DecodeOidSequence(value
);
1761 if( (CERTOidSequence
*)NULL
== os
) {
1765 for( op
= os
->oids
; *op
; op
++ ) {
1766 SECU_PrintObjectID(out
, *op
, msg
, level
+ 1);
1768 CERT_DestroyOidSequence(os
);
1773 secu_PrintBasicConstraints(FILE *out
, SECItem
*value
, char *msg
, int level
) {
1774 CERTBasicConstraints constraints
;
1777 SECU_Indent(out
, level
);
1779 fprintf(out
,"%s: ",msg
);
1781 rv
= CERT_DecodeBasicConstraintValue(&constraints
,value
);
1782 if (rv
== SECSuccess
&& constraints
.isCA
) {
1783 if (constraints
.pathLenConstraint
>= 0) {
1784 fprintf(out
,"Is a CA with a maximum path length of %d.\n",
1785 constraints
.pathLenConstraint
);
1787 fprintf(out
,"Is a CA with no maximum path length.\n");
1790 fprintf(out
,"Is not a CA.\n");
1795 static const char * const nsTypeBits
[] = {
1806 /* NSCertType is merely a bit string whose bits are displayed symbolically */
1808 secu_PrintNSCertType(FILE *out
, SECItem
*value
, char *msg
, int level
)
1814 SECItem my
= *value
;
1816 if ((my
.data
[0] != SEC_ASN1_BIT_STRING
) ||
1817 SECSuccess
!= SECU_StripTagAndLength(&my
)) {
1818 SECU_PrintAny(out
, value
, "Data", level
);
1822 unused
= (my
.len
== 2) ? (my
.data
[0] & 0x0f) : 0;
1823 NS_Type
= my
.data
[1] & (0xff << unused
);
1826 SECU_Indent(out
, level
);
1828 fprintf(out
,"%s: ",msg
);
1830 fprintf(out
,"Netscape Certificate Type: ");
1832 for (i
=0; i
< 8; i
++) {
1833 if ( (0x80 >> i
) & NS_Type
) {
1834 fprintf(out
, "%c%s", (found
? ',' : '<'), nsTypeBits
[i
]);
1838 fprintf(out
, (found
? ">\n" : "none\n"));
1842 static const char * const usageBits
[] = {
1843 "Digital Signature", /* 0x80 */
1844 "Non-Repudiation", /* 0x40 */
1845 "Key Encipherment", /* 0x20 */
1846 "Data Encipherment", /* 0x10 */
1847 "Key Agreement", /* 0x08 */
1848 "Certificate Signing", /* 0x04 */
1849 "CRL Signing", /* 0x02 */
1850 "Encipher Only", /* 0x01 */
1851 "Decipher Only", /* 0x0080 */
1855 /* X509KeyUsage is merely a bit string whose bits are displayed symbolically */
1857 secu_PrintX509KeyUsage(FILE *out
, SECItem
*value
, char *msg
, int level
)
1863 SECItem my
= *value
;
1865 if ((my
.data
[0] != SEC_ASN1_BIT_STRING
) ||
1866 SECSuccess
!= SECU_StripTagAndLength(&my
)) {
1867 SECU_PrintAny(out
, value
, "Data", level
);
1871 unused
= (my
.len
>= 2) ? (my
.data
[0] & 0x0f) : 0;
1872 usage
= (my
.len
== 2) ? (my
.data
[1] & (0xff << unused
)) << 8
1873 : (my
.data
[1] << 8) |
1874 (my
.data
[2] & (0xff << unused
));
1876 SECU_Indent(out
, level
);
1877 fprintf(out
, "Usages: ");
1878 for (i
=0; usageBits
[i
]; i
++) {
1879 if ( (0x8000 >> i
) & usage
) {
1881 SECU_Indent(out
, level
+ 2);
1882 fprintf(out
, "%s\n", usageBits
[i
]);
1887 fprintf(out
, "(none)\n");
1892 secu_PrintIPAddress(FILE *out
, SECItem
*value
, char *msg
, int level
)
1898 memset(&addr
, 0, sizeof addr
);
1899 if (value
->len
== 4) {
1900 addr
.inet
.family
= PR_AF_INET
;
1901 memcpy(&addr
.inet
.ip
, value
->data
, value
->len
);
1902 } else if (value
->len
== 16) {
1903 addr
.ipv6
.family
= PR_AF_INET6
;
1904 memcpy(addr
.ipv6
.ip
.pr_s6_addr
, value
->data
, value
->len
);
1905 if (PR_IsNetAddrType(&addr
, PR_IpAddrV4Mapped
)) {
1906 /* convert to IPv4. */
1907 addr
.inet
.family
= PR_AF_INET
;
1908 memcpy(&addr
.inet
.ip
, &addr
.ipv6
.ip
.pr_s6_addr
[12], 4);
1909 memset(&addr
.inet
.pad
[0], 0, sizeof addr
.inet
.pad
);
1915 st
= PR_NetAddrToString(&addr
, addrBuf
, sizeof addrBuf
);
1916 if (st
== PR_SUCCESS
) {
1917 SECU_Indent(out
, level
);
1918 fprintf(out
, "%s: %s\n", msg
, addrBuf
);
1921 SECU_PrintAsHex(out
, value
, msg
, level
);
1927 secu_PrintGeneralName(FILE *out
, CERTGeneralName
*gname
, char *msg
, int level
)
1930 if (msg
&& msg
[0]) {
1931 SECU_Indent(out
, level
++); fprintf(out
, "%s: \n", msg
);
1933 switch (gname
->type
) {
1934 case certOtherName
:
1935 SECU_PrintAny( out
, &gname
->name
.OthName
.name
, "Other Name", level
);
1936 SECU_PrintObjectID(out
, &gname
->name
.OthName
.oid
, "OID", level
+1);
1938 case certDirectoryName
:
1939 SECU_PrintName(out
, &gname
->name
.directoryName
, "Directory Name", level
);
1941 case certRFC822Name
:
1942 secu_PrintRawString( out
, &gname
->name
.other
, "RFC822 Name", level
);
1945 secu_PrintRawString( out
, &gname
->name
.other
, "DNS name", level
);
1948 secu_PrintRawString( out
, &gname
->name
.other
, "URI", level
);
1950 case certIPAddress
:
1951 secu_PrintIPAddress(out
, &gname
->name
.other
, "IP Address", level
);
1953 case certRegisterID
:
1954 SECU_PrintObjectID( out
, &gname
->name
.other
, "Registered ID", level
);
1956 case certX400Address
:
1957 SECU_PrintAny( out
, &gname
->name
.other
, "X400 Address", level
);
1959 case certEDIPartyName
:
1960 SECU_PrintAny( out
, &gname
->name
.other
, "EDI Party", level
);
1963 PR_snprintf(label
, sizeof label
, "unknown type [%d]",
1964 (int)gname
->type
- 1);
1965 SECU_PrintAsHex(out
, &gname
->name
.other
, label
, level
);
1971 secu_PrintGeneralNames(FILE *out
, CERTGeneralName
*gname
, char *msg
, int level
)
1973 CERTGeneralName
*name
= gname
;
1975 secu_PrintGeneralName(out
, name
, msg
, level
);
1976 name
= CERT_GetNextGeneralName(name
);
1977 } while (name
&& name
!= gname
);
1982 secu_PrintAuthKeyIDExtension(FILE *out
, SECItem
*value
, char *msg
, int level
)
1984 CERTAuthKeyID
*kid
= NULL
;
1985 PLArenaPool
*pool
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
1988 SECU_PrintError("Error", "Allocating new ArenaPool");
1991 kid
= CERT_DecodeAuthKeyID(pool
, value
);
1993 SECU_PrintErrMsg(out
, level
, "Error", "Parsing extension");
1994 SECU_PrintAny(out
, value
, "Data", level
);
1996 int keyIDPresent
= (kid
->keyID
.data
&& kid
->keyID
.len
);
1997 int issuerPresent
= kid
->authCertIssuer
!= NULL
;
1998 int snPresent
= (kid
->authCertSerialNumber
.data
&&
1999 kid
->authCertSerialNumber
.len
);
2001 if ((keyIDPresent
&& !issuerPresent
&& !snPresent
) ||
2002 (!keyIDPresent
&& issuerPresent
&& snPresent
)) {
2005 SECU_Indent(out
, level
);
2007 "Error: KeyID OR (Issuer AND Serial) must be present, not both.\n");
2010 SECU_PrintAsHex(out
, &kid
->keyID
, "Key ID", level
);
2012 secu_PrintGeneralName(out
, kid
->authCertIssuer
, "Issuer", level
);
2014 SECU_PrintInteger(out
, &kid
->authCertSerialNumber
,
2015 "Serial Number", level
);
2017 PORT_FreeArena(pool
, PR_FALSE
);
2022 secu_PrintAltNameExtension(FILE *out
, SECItem
*value
, char *msg
, int level
)
2024 CERTGeneralName
* nameList
;
2025 CERTGeneralName
* current
;
2026 PLArenaPool
* pool
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
2029 SECU_PrintError("Error", "Allocating new ArenaPool");
2032 nameList
= current
= CERT_DecodeAltNameExtension(pool
, value
);
2034 if (PORT_GetError() == SEC_ERROR_EXTENSION_NOT_FOUND
) {
2035 /* Decoder found empty sequence, which is invalid. */
2036 PORT_SetError(SEC_ERROR_EXTENSION_VALUE_INVALID
);
2038 SECU_PrintErrMsg(out
, level
, "Error", "Parsing extension");
2039 SECU_PrintAny(out
, value
, "Data", level
);
2042 secu_PrintGeneralName(out
, current
, msg
, level
);
2043 current
= CERT_GetNextGeneralName(current
);
2044 } while (current
!= nameList
);
2046 PORT_FreeArena(pool
, PR_FALSE
);
2050 secu_PrintCRLDistPtsExtension(FILE *out
, SECItem
*value
, char *msg
, int level
)
2052 CERTCrlDistributionPoints
* dPoints
;
2053 PLArenaPool
* pool
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
2056 SECU_PrintError("Error", "Allocating new ArenaPool");
2059 dPoints
= CERT_DecodeCRLDistributionPoints(pool
, value
);
2060 if (dPoints
&& dPoints
->distPoints
&& dPoints
->distPoints
[0]) {
2061 CRLDistributionPoint
** pPoints
= dPoints
->distPoints
;
2062 CRLDistributionPoint
* pPoint
;
2063 while (NULL
!= (pPoint
= *pPoints
++)) {
2064 if (pPoint
->distPointType
== generalName
&&
2065 pPoint
->distPoint
.fullName
!= NULL
) {
2066 secu_PrintGeneralNames(out
, pPoint
->distPoint
.fullName
, NULL
,
2069 } else if (pPoint
->distPointType
== relativeDistinguishedName
) {
2070 /* print the relative name */
2072 } else if (pPoint
->derDistPoint
.data
) {
2073 SECU_PrintAny(out
, &pPoint
->derDistPoint
, "Point", level
);
2075 if (pPoint
->reasons
.data
) {
2076 secu_PrintDecodedBitString(out
, &pPoint
->reasons
, "Reasons",
2079 if (pPoint
->crlIssuer
) {
2080 secu_PrintGeneralName(out
, pPoint
->crlIssuer
, "Issuer", level
);
2084 SECU_PrintErrMsg(out
, level
, "Error", "Parsing extension");
2085 SECU_PrintAny(out
, value
, "Data", level
);
2087 PORT_FreeArena(pool
, PR_FALSE
);
2092 secu_PrintNameConstraintSubtree(FILE *out
, CERTNameConstraint
*value
,
2093 char *msg
, int level
)
2095 CERTNameConstraint
*head
= value
;
2096 SECU_Indent(out
, level
); fprintf(out
, "%s Subtree:\n", msg
);
2099 secu_PrintGeneralName(out
, &value
->name
, NULL
, level
);
2100 if (value
->min
.data
)
2101 SECU_PrintInteger(out
, &value
->min
, "Minimum", level
+1);
2102 if (value
->max
.data
)
2103 SECU_PrintInteger(out
, &value
->max
, "Maximum", level
+1);
2104 value
= CERT_GetNextNameConstraint(value
);
2105 } while (value
!= head
);
2109 secu_PrintNameConstraintsExtension(FILE *out
, SECItem
*value
, char *msg
, int level
)
2111 CERTNameConstraints
* cnstrnts
;
2112 PLArenaPool
* pool
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
2115 SECU_PrintError("Error", "Allocating new ArenaPool");
2118 cnstrnts
= CERT_DecodeNameConstraintsExtension(pool
, value
);
2120 SECU_PrintErrMsg(out
, level
, "Error", "Parsing extension");
2121 SECU_PrintAny(out
, value
, "Raw", level
);
2123 if (cnstrnts
->permited
)
2124 secu_PrintNameConstraintSubtree(out
, cnstrnts
->permited
,
2125 "Permitted", level
);
2126 if (cnstrnts
->excluded
)
2127 secu_PrintNameConstraintSubtree(out
, cnstrnts
->excluded
,
2130 PORT_FreeArena(pool
, PR_FALSE
);
2135 secu_PrintAuthorityInfoAcess(FILE *out
, SECItem
*value
, char *msg
, int level
)
2137 CERTAuthInfoAccess
**infos
= NULL
;
2138 PLArenaPool
* pool
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
2141 SECU_PrintError("Error", "Allocating new ArenaPool");
2144 infos
= CERT_DecodeAuthInfoAccessExtension(pool
, value
);
2146 SECU_PrintErrMsg(out
, level
, "Error", "Parsing extension");
2147 SECU_PrintAny(out
, value
, "Raw", level
);
2149 CERTAuthInfoAccess
*info
;
2150 while (NULL
!= (info
= *infos
++)) {
2151 if (info
->method
.data
) {
2152 SECU_PrintObjectID(out
, &info
->method
, "Method", level
);
2154 SECU_Indent(out
,level
);
2155 fprintf(out
, "Error: missing method\n");
2157 if (info
->location
) {
2158 secu_PrintGeneralName(out
, info
->location
, "Location", level
);
2160 SECU_PrintAny(out
, &info
->derLocation
, "Location", level
);
2164 PORT_FreeArena(pool
, PR_FALSE
);
2169 SECU_PrintExtensions(FILE *out
, CERTCertExtension
**extensions
,
2170 char *msg
, int level
)
2176 SECU_Indent(out
, level
++); fprintf(out
, "%s:\n", msg
);
2179 while ( *extensions
) {
2182 tmpitem
= &(*extensions
)->id
;
2183 SECU_PrintObjectID(out
, tmpitem
, "Name", level
);
2185 tmpitem
= &(*extensions
)->critical
;
2186 if ( tmpitem
->len
) {
2187 secu_PrintBoolean(out
, tmpitem
, "Critical", level
);
2190 oidTag
= SECOID_FindOIDTag (&((*extensions
)->id
));
2191 tmpitem
= &((*extensions
)->value
);
2194 case SEC_OID_X509_INVALID_DATE
:
2195 case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_TIME
:
2196 secu_PrintX509InvalidDate(out
, tmpitem
, "Date", level
);
2198 case SEC_OID_X509_CERTIFICATE_POLICIES
:
2199 SECU_PrintPolicy(out
, tmpitem
, "Data", level
);
2201 case SEC_OID_NS_CERT_EXT_BASE_URL
:
2202 case SEC_OID_NS_CERT_EXT_REVOCATION_URL
:
2203 case SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL
:
2204 case SEC_OID_NS_CERT_EXT_CA_CRL_URL
:
2205 case SEC_OID_NS_CERT_EXT_CA_CERT_URL
:
2206 case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL
:
2207 case SEC_OID_NS_CERT_EXT_CA_POLICY_URL
:
2208 case SEC_OID_NS_CERT_EXT_HOMEPAGE_URL
:
2209 case SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL
:
2210 case SEC_OID_OCSP_RESPONDER
:
2211 SECU_PrintString(out
,tmpitem
, "URL", level
);
2213 case SEC_OID_NS_CERT_EXT_COMMENT
:
2214 SECU_PrintString(out
,tmpitem
, "Comment", level
);
2216 case SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME
:
2217 SECU_PrintString(out
,tmpitem
, "ServerName", level
);
2219 case SEC_OID_NS_CERT_EXT_CERT_TYPE
:
2220 secu_PrintNSCertType(out
,tmpitem
,"Data",level
);
2222 case SEC_OID_X509_BASIC_CONSTRAINTS
:
2223 secu_PrintBasicConstraints(out
,tmpitem
,"Data",level
);
2225 case SEC_OID_X509_EXT_KEY_USAGE
:
2226 PrintExtKeyUsageExtension(out
, tmpitem
, NULL
, level
);
2228 case SEC_OID_X509_KEY_USAGE
:
2229 secu_PrintX509KeyUsage(out
, tmpitem
, NULL
, level
);
2231 case SEC_OID_X509_AUTH_KEY_ID
:
2232 secu_PrintAuthKeyIDExtension(out
, tmpitem
, NULL
, level
);
2234 case SEC_OID_X509_SUBJECT_ALT_NAME
:
2235 case SEC_OID_X509_ISSUER_ALT_NAME
:
2236 secu_PrintAltNameExtension(out
, tmpitem
, NULL
, level
);
2238 case SEC_OID_X509_CRL_DIST_POINTS
:
2239 secu_PrintCRLDistPtsExtension(out
, tmpitem
, NULL
, level
);
2241 case SEC_OID_X509_PRIVATE_KEY_USAGE_PERIOD
:
2242 SECU_PrintPrivKeyUsagePeriodExtension(out
, tmpitem
, NULL
,
2245 case SEC_OID_X509_NAME_CONSTRAINTS
:
2246 secu_PrintNameConstraintsExtension(out
, tmpitem
, NULL
, level
);
2248 case SEC_OID_X509_AUTH_INFO_ACCESS
:
2249 secu_PrintAuthorityInfoAcess(out
, tmpitem
, NULL
, level
);
2252 case SEC_OID_X509_CRL_NUMBER
:
2253 case SEC_OID_X509_REASON_CODE
:
2256 case SEC_OID_PKIX_OCSP
:
2257 case SEC_OID_PKIX_OCSP_BASIC_RESPONSE
:
2258 case SEC_OID_PKIX_OCSP_NONCE
:
2259 case SEC_OID_PKIX_OCSP_CRL
:
2260 case SEC_OID_PKIX_OCSP_RESPONSE
:
2261 case SEC_OID_PKIX_OCSP_NO_CHECK
:
2262 case SEC_OID_PKIX_OCSP_ARCHIVE_CUTOFF
:
2263 case SEC_OID_PKIX_OCSP_SERVICE_LOCATOR
:
2264 case SEC_OID_PKIX_REGCTRL_REGTOKEN
:
2265 case SEC_OID_PKIX_REGCTRL_AUTHENTICATOR
:
2266 case SEC_OID_PKIX_REGCTRL_PKIPUBINFO
:
2267 case SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS
:
2268 case SEC_OID_PKIX_REGCTRL_OLD_CERT_ID
:
2269 case SEC_OID_PKIX_REGCTRL_PROTOCOL_ENC_KEY
:
2270 case SEC_OID_PKIX_REGINFO_UTF8_PAIRS
:
2271 case SEC_OID_PKIX_REGINFO_CERT_REQUEST
:
2273 /* Netscape extension OIDs. */
2274 case SEC_OID_NS_CERT_EXT_NETSCAPE_OK
:
2275 case SEC_OID_NS_CERT_EXT_ISSUER_LOGO
:
2276 case SEC_OID_NS_CERT_EXT_SUBJECT_LOGO
:
2277 case SEC_OID_NS_CERT_EXT_ENTITY_LOGO
:
2278 case SEC_OID_NS_CERT_EXT_USER_PICTURE
:
2280 /* x.509 v3 Extensions */
2281 case SEC_OID_X509_SUBJECT_DIRECTORY_ATTR
:
2282 case SEC_OID_X509_SUBJECT_KEY_ID
:
2283 case SEC_OID_X509_POLICY_MAPPINGS
:
2284 case SEC_OID_X509_POLICY_CONSTRAINTS
:
2288 SECU_PrintAny(out
, tmpitem
, "Data", level
);
2300 SECU_PrintName(FILE *out
, CERTName
*name
, char *msg
, int level
)
2306 str
= nameStr
= CERT_NameToAscii(name
);
2308 str
= "!Invalid AVA!";
2310 my
.data
= (unsigned char *)str
;
2311 my
.len
= PORT_Strlen(str
);
2313 secu_PrintRawString(out
, &my
, msg
, level
);
2315 SECU_Indent(out
, level
); fprintf(out
, "%s: ", msg
);
2323 printflags(char *trusts
, unsigned int flags
)
2325 if (flags
& CERTDB_VALID_CA
)
2326 if (!(flags
& CERTDB_TRUSTED_CA
) &&
2327 !(flags
& CERTDB_TRUSTED_CLIENT_CA
))
2328 PORT_Strcat(trusts
, "c");
2329 if (flags
& CERTDB_VALID_PEER
)
2330 if (!(flags
& CERTDB_TRUSTED
))
2331 PORT_Strcat(trusts
, "p");
2332 if (flags
& CERTDB_TRUSTED_CA
)
2333 PORT_Strcat(trusts
, "C");
2334 if (flags
& CERTDB_TRUSTED_CLIENT_CA
)
2335 PORT_Strcat(trusts
, "T");
2336 if (flags
& CERTDB_TRUSTED
)
2337 PORT_Strcat(trusts
, "P");
2338 if (flags
& CERTDB_USER
)
2339 PORT_Strcat(trusts
, "u");
2340 if (flags
& CERTDB_SEND_WARN
)
2341 PORT_Strcat(trusts
, "w");
2342 if (flags
& CERTDB_INVISIBLE_CA
)
2343 PORT_Strcat(trusts
, "I");
2344 if (flags
& CERTDB_GOVT_APPROVED_CA
)
2345 PORT_Strcat(trusts
, "G");
2349 /* callback for listing certs through pkcs11 */
2351 SECU_PrintCertNickname(CERTCertListNode
*node
, void *data
)
2353 CERTCertTrust
*trust
;
2354 CERTCertificate
* cert
;
2361 PORT_Memset (trusts
, 0, sizeof (trusts
));
2364 name
= node
->appData
;
2365 if (!name
|| !name
[0]) {
2366 name
= cert
->nickname
;
2368 if (!name
|| !name
[0]) {
2369 name
= cert
->emailAddr
;
2371 if (!name
|| !name
[0]) {
2375 trust
= cert
->trust
;
2377 printflags(trusts
, trust
->sslFlags
);
2378 PORT_Strcat(trusts
, ",");
2379 printflags(trusts
, trust
->emailFlags
);
2380 PORT_Strcat(trusts
, ",");
2381 printflags(trusts
, trust
->objectSigningFlags
);
2383 PORT_Memcpy(trusts
,",,",3);
2385 fprintf(out
, "%-60s %-5s\n", name
, trusts
);
2387 return (SECSuccess
);
2391 SECU_DecodeAndPrintExtensions(FILE *out
, SECItem
*any
, char *m
, int level
)
2393 CERTCertExtension
**extensions
= NULL
;
2394 PRArenaPool
*arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
2398 return SEC_ERROR_NO_MEMORY
;
2400 rv
= SEC_QuickDERDecodeItem(arena
, &extensions
,
2401 SEC_ASN1_GET(CERT_SequenceOfCertExtensionTemplate
), any
);
2403 SECU_PrintExtensions(out
, extensions
, m
, level
);
2405 SECU_PrintAny(out
, any
, m
, level
);
2406 PORT_FreeArena(arena
, PR_FALSE
);
2410 /* print a decoded SET OF or SEQUENCE OF Extensions */
2412 SECU_PrintSetOfExtensions(FILE *out
, SECItem
**any
, char *m
, int level
)
2416 SECU_Indent(out
, level
++); fprintf(out
, "%s:\n", m
);
2418 while (any
&& any
[0]) {
2419 rv
|= SECU_DecodeAndPrintExtensions(out
, any
[0], "", level
);
2425 /* print a decoded SET OF or SEQUENCE OF "ANY" */
2427 SECU_PrintSetOfAny(FILE *out
, SECItem
**any
, char *m
, int level
)
2431 SECU_Indent(out
, level
++); fprintf(out
, "%s:\n", m
);
2433 while (any
&& any
[0]) {
2434 SECU_PrintAny(out
, any
[0], "", level
);
2441 SECU_PrintCertAttribute(FILE *out
, CERTAttribute
*attr
, char *m
, int level
)
2445 tag
= SECU_PrintObjectID(out
, &attr
->attrType
, "Attribute Type", level
);
2446 if (tag
== SEC_OID_PKCS9_EXTENSION_REQUEST
) {
2447 rv
= SECU_PrintSetOfExtensions(out
, attr
->attrValue
, "Extensions", level
);
2449 rv
= SECU_PrintSetOfAny(out
, attr
->attrValue
, "Attribute Values", level
);
2455 SECU_PrintCertAttributes(FILE *out
, CERTAttribute
**attrs
, char *m
, int level
)
2459 rv
|= SECU_PrintCertAttribute(out
, attrs
[0], m
, level
+1);
2465 int /* sometimes a PRErrorCode, other times a SECStatus. Sigh. */
2466 SECU_PrintCertificateRequest(FILE *out
, SECItem
*der
, char *m
, int level
)
2468 PRArenaPool
*arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
2469 CERTCertificateRequest
*cr
;
2470 int rv
= SEC_ERROR_NO_MEMORY
;
2475 /* Decode certificate request */
2476 cr
= PORT_ArenaZNew(arena
, CERTCertificateRequest
);
2480 rv
= SEC_QuickDERDecodeItem(arena
, cr
,
2481 SEC_ASN1_GET(CERT_CertificateRequestTemplate
), der
);
2485 /* Pretty print it out */
2486 SECU_Indent(out
, level
); fprintf(out
, "%s:\n", m
);
2487 SECU_PrintInteger(out
, &cr
->version
, "Version", level
+1);
2488 SECU_PrintName(out
, &cr
->subject
, "Subject", level
+1);
2489 secu_PrintSubjectPublicKeyInfo(out
, arena
, &cr
->subjectPublicKeyInfo
,
2490 "Subject Public Key Info", level
+1);
2492 SECU_PrintCertAttributes(out
, cr
->attributes
, "Attributes", level
+1);
2495 PORT_FreeArena(arena
, PR_FALSE
);
2500 SECU_PrintCertificate(FILE *out
, SECItem
*der
, char *m
, int level
)
2502 PRArenaPool
*arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
2504 int rv
= SEC_ERROR_NO_MEMORY
;
2510 /* Decode certificate */
2511 c
= PORT_ArenaZNew(arena
, CERTCertificate
);
2515 rv
= SEC_ASN1DecodeItem(arena
, c
,
2516 SEC_ASN1_GET(CERT_CertificateTemplate
), der
);
2518 SECU_Indent(out
, level
);
2519 SECU_PrintErrMsg(out
, level
, "Error", "Parsing extension");
2520 SECU_PrintAny(out
, der
, "Raw", level
);
2523 /* Pretty print it out */
2524 SECU_Indent(out
, level
); fprintf(out
, "%s:\n", m
);
2525 iv
= c
->version
.len
? DER_GetInteger(&c
->version
) : 0; /* version is optional */
2526 SECU_Indent(out
, level
+1); fprintf(out
, "%s: %d (0x%x)\n", "Version", iv
+ 1, iv
);
2528 SECU_PrintInteger(out
, &c
->serialNumber
, "Serial Number", level
+1);
2529 SECU_PrintAlgorithmID(out
, &c
->signature
, "Signature Algorithm", level
+1);
2530 SECU_PrintName(out
, &c
->issuer
, "Issuer", level
+1);
2531 secu_PrintValidity(out
, &c
->validity
, "Validity", level
+1);
2532 SECU_PrintName(out
, &c
->subject
, "Subject", level
+1);
2533 secu_PrintSubjectPublicKeyInfo(out
, arena
, &c
->subjectPublicKeyInfo
,
2534 "Subject Public Key Info", level
+1);
2535 if (c
->issuerID
.data
)
2536 secu_PrintDecodedBitString(out
, &c
->issuerID
, "Issuer Unique ID", level
+1);
2537 if (c
->subjectID
.data
)
2538 secu_PrintDecodedBitString(out
, &c
->subjectID
, "Subject Unique ID", level
+1);
2539 SECU_PrintExtensions(out
, c
->extensions
, "Signed Extensions", level
+1);
2541 PORT_FreeArena(arena
, PR_FALSE
);
2546 SECU_PrintRSAPublicKey(FILE *out
, SECItem
*der
, char *m
, int level
)
2548 PRArenaPool
*arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
2549 SECKEYPublicKey key
;
2550 int rv
= SEC_ERROR_NO_MEMORY
;
2555 PORT_Memset(&key
, 0, sizeof(key
));
2556 rv
= SEC_ASN1DecodeItem(arena
, &key
,
2557 SEC_ASN1_GET(SECKEY_RSAPublicKeyTemplate
), der
);
2559 /* Pretty print it out */
2560 secu_PrintRSAPublicKey(out
, &key
, m
, level
);
2563 PORT_FreeArena(arena
, PR_FALSE
);
2568 SECU_PrintSubjectPublicKeyInfo(FILE *out
, SECItem
*der
, char *m
, int level
)
2570 PRArenaPool
*arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
2571 int rv
= SEC_ERROR_NO_MEMORY
;
2572 CERTSubjectPublicKeyInfo spki
;
2577 PORT_Memset(&spki
, 0, sizeof spki
);
2578 rv
= SEC_ASN1DecodeItem(arena
, &spki
,
2579 SEC_ASN1_GET(CERT_SubjectPublicKeyInfoTemplate
),
2583 SECU_Indent(out
, level
); fprintf(out
, "%s:\n", m
);
2585 secu_PrintSubjectPublicKeyInfo(out
, arena
, &spki
,
2586 "Subject Public Key Info", level
+1);
2589 PORT_FreeArena(arena
, PR_FALSE
);
2593 #ifdef HAVE_EPV_TEMPLATE
2595 SECU_PrintPrivateKey(FILE *out
, SECItem
*der
, char *m
, int level
)
2597 PRArenaPool
*arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
2598 SECKEYEncryptedPrivateKeyInfo key
;
2599 int rv
= SEC_ERROR_NO_MEMORY
;
2604 PORT_Memset(&key
, 0, sizeof(key
));
2605 rv
= SEC_ASN1DecodeItem(arena
, &key
,
2606 SEC_ASN1_GET(SECKEY_EncryptedPrivateKeyInfoTemplate
), der
);
2610 /* Pretty print it out */
2611 SECU_Indent(out
, level
); fprintf(out
, "%s:\n", m
);
2612 SECU_PrintAlgorithmID(out
, &key
.algorithm
, "Encryption Algorithm",
2614 SECU_PrintAsHex(out
, &key
.encryptedData
, "Encrypted Data", level
+1);
2616 PORT_FreeArena(arena
, PR_TRUE
);
2622 SECU_PrintFingerprints(FILE *out
, SECItem
*derCert
, char *m
, int level
)
2624 unsigned char fingerprint
[20];
2626 int err
= PORT_GetError();
2630 /* print MD5 fingerprint */
2631 memset(fingerprint
, 0, sizeof fingerprint
);
2632 rv
= PK11_HashBuf(SEC_OID_MD5
,fingerprint
, derCert
->data
, derCert
->len
);
2633 fpItem
.data
= fingerprint
;
2634 fpItem
.len
= MD5_LENGTH
;
2635 fpStr
= CERT_Hexify(&fpItem
, 1);
2636 SECU_Indent(out
, level
); fprintf(out
, "%s (MD5):\n", m
);
2637 SECU_Indent(out
, level
+1); fprintf(out
, "%s\n", fpStr
);
2640 if (rv
!= SECSuccess
&& !err
)
2641 err
= PORT_GetError();
2643 /* print SHA1 fingerprint */
2644 memset(fingerprint
, 0, sizeof fingerprint
);
2645 rv
= PK11_HashBuf(SEC_OID_SHA1
,fingerprint
, derCert
->data
, derCert
->len
);
2646 fpItem
.data
= fingerprint
;
2647 fpItem
.len
= SHA1_LENGTH
;
2648 fpStr
= CERT_Hexify(&fpItem
, 1);
2649 SECU_Indent(out
, level
); fprintf(out
, "%s (SHA1):\n", m
);
2650 SECU_Indent(out
, level
+1); fprintf(out
, "%s\n", fpStr
);
2656 if (err
|| rv
!= SECSuccess
)
2666 /* forward declaration */
2668 secu_PrintPKCS7ContentInfo(FILE *, SEC_PKCS7ContentInfo
*, char *, int);
2671 ** secu_PrintPKCS7EncContent
2672 ** Prints a SEC_PKCS7EncryptedContentInfo (without decrypting it)
2675 secu_PrintPKCS7EncContent(FILE *out
, SEC_PKCS7EncryptedContentInfo
*src
,
2678 if (src
->contentTypeTag
== NULL
)
2679 src
->contentTypeTag
= SECOID_FindOID(&(src
->contentType
));
2681 SECU_Indent(out
, level
);
2682 fprintf(out
, "%s:\n", m
);
2683 SECU_Indent(out
, level
+ 1);
2684 fprintf(out
, "Content Type: %s\n",
2685 (src
->contentTypeTag
!= NULL
) ? src
->contentTypeTag
->desc
2687 SECU_PrintAlgorithmID(out
, &(src
->contentEncAlg
),
2688 "Content Encryption Algorithm", level
+1);
2689 SECU_PrintAsHex(out
, &(src
->encContent
),
2690 "Encrypted Content", level
+1);
2694 ** secu_PrintRecipientInfo
2695 ** Prints a PKCS7RecipientInfo type
2698 secu_PrintRecipientInfo(FILE *out
, SEC_PKCS7RecipientInfo
*info
, char *m
,
2701 SECU_Indent(out
, level
); fprintf(out
, "%s:\n", m
);
2702 SECU_PrintInteger(out
, &(info
->version
), "Version", level
+ 1);
2704 SECU_PrintName(out
, &(info
->issuerAndSN
->issuer
), "Issuer",
2706 SECU_PrintInteger(out
, &(info
->issuerAndSN
->serialNumber
),
2707 "Serial Number", level
+ 1);
2709 /* Parse and display encrypted key */
2710 SECU_PrintAlgorithmID(out
, &(info
->keyEncAlg
),
2711 "Key Encryption Algorithm", level
+ 1);
2712 SECU_PrintAsHex(out
, &(info
->encKey
), "Encrypted Key", level
+ 1);
2716 ** secu_PrintSignerInfo
2717 ** Prints a PKCS7SingerInfo type
2720 secu_PrintSignerInfo(FILE *out
, SEC_PKCS7SignerInfo
*info
, char *m
, int level
)
2722 SEC_PKCS7Attribute
*attr
;
2726 SECU_Indent(out
, level
); fprintf(out
, "%s:\n", m
);
2727 SECU_PrintInteger(out
, &(info
->version
), "Version", level
+ 1);
2729 SECU_PrintName(out
, &(info
->issuerAndSN
->issuer
), "Issuer",
2731 SECU_PrintInteger(out
, &(info
->issuerAndSN
->serialNumber
),
2732 "Serial Number", level
+ 1);
2734 SECU_PrintAlgorithmID(out
, &(info
->digestAlg
), "Digest Algorithm",
2737 if (info
->authAttr
!= NULL
) {
2738 SECU_Indent(out
, level
+ 1);
2739 fprintf(out
, "Authenticated Attributes:\n");
2741 while ((attr
= info
->authAttr
[iv
++]) != NULL
) {
2742 sprintf(om
, "Attribute (%d)", iv
);
2743 secu_PrintAttribute(out
, attr
, om
, level
+ 2);
2747 /* Parse and display signature */
2748 SECU_PrintAlgorithmID(out
, &(info
->digestEncAlg
),
2749 "Digest Encryption Algorithm", level
+ 1);
2750 SECU_PrintAsHex(out
, &(info
->encDigest
), "Encrypted Digest", level
+ 1);
2752 if (info
->unAuthAttr
!= NULL
) {
2753 SECU_Indent(out
, level
+ 1);
2754 fprintf(out
, "Unauthenticated Attributes:\n");
2756 while ((attr
= info
->unAuthAttr
[iv
++]) != NULL
) {
2757 sprintf(om
, "Attribute (%x)", iv
);
2758 secu_PrintAttribute(out
, attr
, om
, level
+ 2);
2763 /* callers of this function must make sure that the CERTSignedCrl
2764 from which they are extracting the CERTCrl has been fully-decoded.
2765 Otherwise it will not have the entries even though the CRL may have
2769 SECU_PrintCRLInfo(FILE *out
, CERTCrl
*crl
, char *m
, int level
)
2771 CERTCrlEntry
*entry
;
2775 SECU_Indent(out
, level
); fprintf(out
, "%s:\n", m
);
2776 /* version is optional */
2777 iv
= crl
->version
.len
? DER_GetInteger(&crl
->version
) : 0;
2778 SECU_Indent(out
, level
+1);
2779 fprintf(out
, "%s: %d (0x%x)\n", "Version", iv
+ 1, iv
);
2780 SECU_PrintAlgorithmID(out
, &(crl
->signatureAlg
), "Signature Algorithm",
2782 SECU_PrintName(out
, &(crl
->name
), "Issuer", level
+ 1);
2783 SECU_PrintTimeChoice(out
, &(crl
->lastUpdate
), "This Update", level
+ 1);
2784 if (crl
->nextUpdate
.data
&& crl
->nextUpdate
.len
) /* is optional */
2785 SECU_PrintTimeChoice(out
, &(crl
->nextUpdate
), "Next Update", level
+ 1);
2787 if (crl
->entries
!= NULL
) {
2789 while ((entry
= crl
->entries
[iv
++]) != NULL
) {
2790 sprintf(om
, "Entry (%x):\n", iv
);
2791 SECU_Indent(out
, level
+ 1); fprintf(out
, om
);
2792 SECU_PrintInteger(out
, &(entry
->serialNumber
), "Serial Number",
2794 SECU_PrintTimeChoice(out
, &(entry
->revocationDate
),
2795 "Revocation Date", level
+ 2);
2796 SECU_PrintExtensions(out
, entry
->extensions
,
2797 "Entry Extensions", level
+ 2);
2800 SECU_PrintExtensions(out
, crl
->extensions
, "CRL Extensions", level
+ 1);
2804 ** secu_PrintPKCS7Signed
2805 ** Pretty print a PKCS7 signed data type (up to version 1).
2808 secu_PrintPKCS7Signed(FILE *out
, SEC_PKCS7SignedData
*src
,
2809 const char *m
, int level
)
2811 SECAlgorithmID
*digAlg
; /* digest algorithms */
2812 SECItem
*aCert
; /* certificate */
2813 CERTSignedCrl
*aCrl
; /* certificate revocation list */
2814 SEC_PKCS7SignerInfo
*sigInfo
; /* signer information */
2818 SECU_Indent(out
, level
); fprintf(out
, "%s:\n", m
);
2819 SECU_PrintInteger(out
, &(src
->version
), "Version", level
+ 1);
2821 /* Parse and list digest algorithms (if any) */
2822 if (src
->digestAlgorithms
!= NULL
) {
2823 SECU_Indent(out
, level
+ 1); fprintf(out
, "Digest Algorithm List:\n");
2825 while ((digAlg
= src
->digestAlgorithms
[iv
++]) != NULL
) {
2826 sprintf(om
, "Digest Algorithm (%x)", iv
);
2827 SECU_PrintAlgorithmID(out
, digAlg
, om
, level
+ 2);
2831 /* Now for the content */
2832 rv
= secu_PrintPKCS7ContentInfo(out
, &(src
->contentInfo
),
2833 "Content Information", level
+ 1);
2837 /* Parse and list certificates (if any) */
2838 if (src
->rawCerts
!= NULL
) {
2839 SECU_Indent(out
, level
+ 1); fprintf(out
, "Certificate List:\n");
2841 while ((aCert
= src
->rawCerts
[iv
++]) != NULL
) {
2842 sprintf(om
, "Certificate (%x)", iv
);
2843 rv
= SECU_PrintSignedData(out
, aCert
, om
, level
+ 2,
2844 SECU_PrintCertificate
);
2850 /* Parse and list CRL's (if any) */
2851 if (src
->crls
!= NULL
) {
2852 SECU_Indent(out
, level
+ 1);
2853 fprintf(out
, "Signed Revocation Lists:\n");
2855 while ((aCrl
= src
->crls
[iv
++]) != NULL
) {
2856 sprintf(om
, "Signed Revocation List (%x)", iv
);
2857 SECU_Indent(out
, level
+ 2); fprintf(out
, "%s:\n", om
);
2858 SECU_PrintAlgorithmID(out
, &aCrl
->signatureWrap
.signatureAlgorithm
,
2859 "Signature Algorithm", level
+3);
2860 DER_ConvertBitString(&aCrl
->signatureWrap
.signature
);
2861 SECU_PrintAsHex(out
, &aCrl
->signatureWrap
.signature
, "Signature",
2863 SECU_PrintCRLInfo(out
, &aCrl
->crl
, "Certificate Revocation List",
2868 /* Parse and list signatures (if any) */
2869 if (src
->signerInfos
!= NULL
) {
2870 SECU_Indent(out
, level
+ 1);
2871 fprintf(out
, "Signer Information List:\n");
2873 while ((sigInfo
= src
->signerInfos
[iv
++]) != NULL
) {
2874 sprintf(om
, "Signer Information (%x)", iv
);
2875 secu_PrintSignerInfo(out
, sigInfo
, om
, level
+ 2);
2883 ** secu_PrintPKCS7Enveloped
2884 ** Pretty print a PKCS7 enveloped data type (up to version 1).
2887 secu_PrintPKCS7Enveloped(FILE *out
, SEC_PKCS7EnvelopedData
*src
,
2888 const char *m
, int level
)
2890 SEC_PKCS7RecipientInfo
*recInfo
; /* pointer for signer information */
2894 SECU_Indent(out
, level
); fprintf(out
, "%s:\n", m
);
2895 SECU_PrintInteger(out
, &(src
->version
), "Version", level
+ 1);
2897 /* Parse and list recipients (this is not optional) */
2898 if (src
->recipientInfos
!= NULL
) {
2899 SECU_Indent(out
, level
+ 1);
2900 fprintf(out
, "Recipient Information List:\n");
2902 while ((recInfo
= src
->recipientInfos
[iv
++]) != NULL
) {
2903 sprintf(om
, "Recipient Information (%x)", iv
);
2904 secu_PrintRecipientInfo(out
, recInfo
, om
, level
+ 2);
2908 secu_PrintPKCS7EncContent(out
, &src
->encContentInfo
,
2909 "Encrypted Content Information", level
+ 1);
2913 ** secu_PrintPKCS7SignedEnveloped
2914 ** Pretty print a PKCS7 singed and enveloped data type (up to version 1).
2917 secu_PrintPKCS7SignedAndEnveloped(FILE *out
,
2918 SEC_PKCS7SignedAndEnvelopedData
*src
,
2919 const char *m
, int level
)
2921 SECAlgorithmID
*digAlg
; /* pointer for digest algorithms */
2922 SECItem
*aCert
; /* pointer for certificate */
2923 CERTSignedCrl
*aCrl
; /* pointer for certificate revocation list */
2924 SEC_PKCS7SignerInfo
*sigInfo
; /* pointer for signer information */
2925 SEC_PKCS7RecipientInfo
*recInfo
; /* pointer for recipient information */
2929 SECU_Indent(out
, level
); fprintf(out
, "%s:\n", m
);
2930 SECU_PrintInteger(out
, &(src
->version
), "Version", level
+ 1);
2932 /* Parse and list recipients (this is not optional) */
2933 if (src
->recipientInfos
!= NULL
) {
2934 SECU_Indent(out
, level
+ 1);
2935 fprintf(out
, "Recipient Information List:\n");
2937 while ((recInfo
= src
->recipientInfos
[iv
++]) != NULL
) {
2938 sprintf(om
, "Recipient Information (%x)", iv
);
2939 secu_PrintRecipientInfo(out
, recInfo
, om
, level
+ 2);
2943 /* Parse and list digest algorithms (if any) */
2944 if (src
->digestAlgorithms
!= NULL
) {
2945 SECU_Indent(out
, level
+ 1); fprintf(out
, "Digest Algorithm List:\n");
2947 while ((digAlg
= src
->digestAlgorithms
[iv
++]) != NULL
) {
2948 sprintf(om
, "Digest Algorithm (%x)", iv
);
2949 SECU_PrintAlgorithmID(out
, digAlg
, om
, level
+ 2);
2953 secu_PrintPKCS7EncContent(out
, &src
->encContentInfo
,
2954 "Encrypted Content Information", level
+ 1);
2956 /* Parse and list certificates (if any) */
2957 if (src
->rawCerts
!= NULL
) {
2958 SECU_Indent(out
, level
+ 1); fprintf(out
, "Certificate List:\n");
2960 while ((aCert
= src
->rawCerts
[iv
++]) != NULL
) {
2961 sprintf(om
, "Certificate (%x)", iv
);
2962 rv
= SECU_PrintSignedData(out
, aCert
, om
, level
+ 2,
2963 SECU_PrintCertificate
);
2969 /* Parse and list CRL's (if any) */
2970 if (src
->crls
!= NULL
) {
2971 SECU_Indent(out
, level
+ 1);
2972 fprintf(out
, "Signed Revocation Lists:\n");
2974 while ((aCrl
= src
->crls
[iv
++]) != NULL
) {
2975 sprintf(om
, "Signed Revocation List (%x)", iv
);
2976 SECU_Indent(out
, level
+ 2); fprintf(out
, "%s:\n", om
);
2977 SECU_PrintAlgorithmID(out
, &aCrl
->signatureWrap
.signatureAlgorithm
,
2978 "Signature Algorithm", level
+3);
2979 DER_ConvertBitString(&aCrl
->signatureWrap
.signature
);
2980 SECU_PrintAsHex(out
, &aCrl
->signatureWrap
.signature
, "Signature",
2982 SECU_PrintCRLInfo(out
, &aCrl
->crl
, "Certificate Revocation List",
2987 /* Parse and list signatures (if any) */
2988 if (src
->signerInfos
!= NULL
) {
2989 SECU_Indent(out
, level
+ 1);
2990 fprintf(out
, "Signer Information List:\n");
2992 while ((sigInfo
= src
->signerInfos
[iv
++]) != NULL
) {
2993 sprintf(om
, "Signer Information (%x)", iv
);
2994 secu_PrintSignerInfo(out
, sigInfo
, om
, level
+ 2);
3002 SECU_PrintCrl (FILE *out
, SECItem
*der
, char *m
, int level
)
3004 PRArenaPool
*arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
3006 int rv
= SEC_ERROR_NO_MEMORY
;
3012 c
= PORT_ArenaZNew(arena
, CERTCrl
);
3016 rv
= SEC_QuickDERDecodeItem(arena
, c
, SEC_ASN1_GET(CERT_CrlTemplate
), der
);
3017 if (rv
!= SECSuccess
)
3019 SECU_PrintCRLInfo (out
, c
, m
, level
);
3021 PORT_FreeArena (arena
, PR_FALSE
);
3027 ** secu_PrintPKCS7Encrypted
3028 ** Pretty print a PKCS7 encrypted data type (up to version 1).
3031 secu_PrintPKCS7Encrypted(FILE *out
, SEC_PKCS7EncryptedData
*src
,
3032 const char *m
, int level
)
3034 SECU_Indent(out
, level
); fprintf(out
, "%s:\n", m
);
3035 SECU_PrintInteger(out
, &(src
->version
), "Version", level
+ 1);
3037 secu_PrintPKCS7EncContent(out
, &src
->encContentInfo
,
3038 "Encrypted Content Information", level
+ 1);
3042 ** secu_PrintPKCS7Digested
3043 ** Pretty print a PKCS7 digested data type (up to version 1).
3046 secu_PrintPKCS7Digested(FILE *out
, SEC_PKCS7DigestedData
*src
,
3047 const char *m
, int level
)
3049 SECU_Indent(out
, level
); fprintf(out
, "%s:\n", m
);
3050 SECU_PrintInteger(out
, &(src
->version
), "Version", level
+ 1);
3052 SECU_PrintAlgorithmID(out
, &src
->digestAlg
, "Digest Algorithm",
3054 secu_PrintPKCS7ContentInfo(out
, &src
->contentInfo
, "Content Information",
3056 SECU_PrintAsHex(out
, &src
->digest
, "Digest", level
+ 1);
3060 ** secu_PrintPKCS7ContentInfo
3061 ** Takes a SEC_PKCS7ContentInfo type and sends the contents to the
3062 ** appropriate function
3065 secu_PrintPKCS7ContentInfo(FILE *out
, SEC_PKCS7ContentInfo
*src
,
3072 SECU_Indent(out
, level
); fprintf(out
, "%s:\n", m
);
3075 if (src
->contentTypeTag
== NULL
)
3076 src
->contentTypeTag
= SECOID_FindOID(&(src
->contentType
));
3078 if (src
->contentTypeTag
== NULL
) {
3080 kind
= SEC_OID_PKCS7_DATA
;
3082 desc
= src
->contentTypeTag
->desc
;
3083 kind
= src
->contentTypeTag
->offset
;
3086 if (src
->content
.data
== NULL
) {
3087 SECU_Indent(out
, level
); fprintf(out
, "%s:\n", desc
);
3089 SECU_Indent(out
, level
); fprintf(out
, "<no content>\n");
3095 case SEC_OID_PKCS7_SIGNED_DATA
: /* Signed Data */
3096 rv
= secu_PrintPKCS7Signed(out
, src
->content
.signedData
, desc
, level
);
3099 case SEC_OID_PKCS7_ENVELOPED_DATA
: /* Enveloped Data */
3100 secu_PrintPKCS7Enveloped(out
, src
->content
.envelopedData
, desc
, level
);
3103 case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA
: /* Signed and Enveloped */
3104 rv
= secu_PrintPKCS7SignedAndEnveloped(out
,
3105 src
->content
.signedAndEnvelopedData
,
3109 case SEC_OID_PKCS7_DIGESTED_DATA
: /* Digested Data */
3110 secu_PrintPKCS7Digested(out
, src
->content
.digestedData
, desc
, level
);
3113 case SEC_OID_PKCS7_ENCRYPTED_DATA
: /* Encrypted Data */
3114 secu_PrintPKCS7Encrypted(out
, src
->content
.encryptedData
, desc
, level
);
3118 SECU_PrintAsHex(out
, src
->content
.data
, desc
, level
);
3126 ** SECU_PrintPKCS7ContentInfo
3127 ** Decode and print any major PKCS7 data type (up to version 1).
3130 SECU_PrintPKCS7ContentInfo(FILE *out
, SECItem
*der
, char *m
, int level
)
3132 SEC_PKCS7ContentInfo
*cinfo
;
3135 cinfo
= SEC_PKCS7DecodeItem(der
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
3136 if (cinfo
!= NULL
) {
3137 /* Send it to recursive parsing and printing module */
3138 rv
= secu_PrintPKCS7ContentInfo(out
, cinfo
, m
, level
);
3139 SEC_PKCS7DestroyContentInfo(cinfo
);
3148 ** End of PKCS7 functions
3152 printFlags(FILE *out
, unsigned int flags
, int level
)
3154 if ( flags
& CERTDB_VALID_PEER
) {
3155 SECU_Indent(out
, level
); fprintf(out
, "Valid Peer\n");
3157 if ( flags
& CERTDB_TRUSTED
) {
3158 SECU_Indent(out
, level
); fprintf(out
, "Trusted\n");
3160 if ( flags
& CERTDB_SEND_WARN
) {
3161 SECU_Indent(out
, level
); fprintf(out
, "Warn When Sending\n");
3163 if ( flags
& CERTDB_VALID_CA
) {
3164 SECU_Indent(out
, level
); fprintf(out
, "Valid CA\n");
3166 if ( flags
& CERTDB_TRUSTED_CA
) {
3167 SECU_Indent(out
, level
); fprintf(out
, "Trusted CA\n");
3169 if ( flags
& CERTDB_NS_TRUSTED_CA
) {
3170 SECU_Indent(out
, level
); fprintf(out
, "Netscape Trusted CA\n");
3172 if ( flags
& CERTDB_USER
) {
3173 SECU_Indent(out
, level
); fprintf(out
, "User\n");
3175 if ( flags
& CERTDB_TRUSTED_CLIENT_CA
) {
3176 SECU_Indent(out
, level
); fprintf(out
, "Trusted Client CA\n");
3178 if ( flags
& CERTDB_GOVT_APPROVED_CA
) {
3179 SECU_Indent(out
, level
); fprintf(out
, "Step-up\n");
3184 SECU_PrintTrustFlags(FILE *out
, CERTCertTrust
*trust
, char *m
, int level
)
3186 SECU_Indent(out
, level
); fprintf(out
, "%s:\n", m
);
3187 SECU_Indent(out
, level
+1); fprintf(out
, "SSL Flags:\n");
3188 printFlags(out
, trust
->sslFlags
, level
+2);
3189 SECU_Indent(out
, level
+1); fprintf(out
, "Email Flags:\n");
3190 printFlags(out
, trust
->emailFlags
, level
+2);
3191 SECU_Indent(out
, level
+1); fprintf(out
, "Object Signing Flags:\n");
3192 printFlags(out
, trust
->objectSigningFlags
, level
+2);
3195 int SECU_PrintSignedData(FILE *out
, SECItem
*der
, char *m
,
3196 int level
, SECU_PPFunc inner
)
3198 PRArenaPool
*arena
= PORT_NewArena(DER_DEFAULT_CHUNKSIZE
);
3200 int rv
= SEC_ERROR_NO_MEMORY
;
3205 /* Strip off the signature */
3206 sd
= PORT_ArenaZNew(arena
, CERTSignedData
);
3210 rv
= SEC_ASN1DecodeItem(arena
, sd
, SEC_ASN1_GET(CERT_SignedDataTemplate
),
3215 SECU_Indent(out
, level
); fprintf(out
, "%s:\n", m
);
3216 rv
= (*inner
)(out
, &sd
->data
, "Data", level
+1);
3218 SECU_PrintAlgorithmID(out
, &sd
->signatureAlgorithm
, "Signature Algorithm",
3220 DER_ConvertBitString(&sd
->signature
);
3221 SECU_PrintAsHex(out
, &sd
->signature
, "Signature", level
+1);
3222 SECU_PrintFingerprints(out
, der
, "Fingerprint", level
+1);
3224 PORT_FreeArena(arena
, PR_FALSE
);
3230 SEC_PrintCertificateAndTrust(CERTCertificate
*cert
,
3232 CERTCertTrust
*trust
)
3237 data
.data
= cert
->derCert
.data
;
3238 data
.len
= cert
->derCert
.len
;
3240 rv
= SECU_PrintSignedData(stdout
, &data
, label
, 0,
3241 SECU_PrintCertificate
);
3246 SECU_PrintTrustFlags(stdout
, trust
,
3247 "Certificate Trust Flags", 1);
3248 } else if (cert
->trust
) {
3249 SECU_PrintTrustFlags(stdout
, cert
->trust
,
3250 "Certificate Trust Flags", 1);
3260 SECU_ParseCommandLine(int argc
, char **argv
, char *progName
,
3261 const secuCommand
*cmd
)
3264 PLOptState
*optstate
;
3267 PLLongOpt
*longopts
= NULL
;
3269 int lcmd
= 0, lopt
= 0;
3271 optstring
= (char *)PORT_Alloc(cmd
->numCommands
+ 2*cmd
->numOptions
);
3272 if (optstring
== NULL
)
3276 for (i
=0; i
<cmd
->numCommands
; i
++) {
3277 if (cmd
->commands
[i
].flag
) /* single character option ? */
3278 optstring
[j
++] = cmd
->commands
[i
].flag
;
3279 if (cmd
->commands
[i
].longform
)
3282 for (i
=0; i
<cmd
->numOptions
; i
++) {
3283 if (cmd
->options
[i
].flag
) {
3284 optstring
[j
++] = cmd
->options
[i
].flag
;
3285 if (cmd
->options
[i
].needsArg
)
3286 optstring
[j
++] = ':';
3288 if (cmd
->options
[i
].longform
)
3292 optstring
[j
] = '\0';
3294 if (lcmd
+ lopt
> 0) {
3295 longopts
= PORT_NewArray(PLLongOpt
, lcmd
+lopt
+1);
3297 PORT_Free(optstring
);
3302 for (i
=0; j
<lcmd
&& i
<cmd
->numCommands
; i
++) {
3303 if (cmd
->commands
[i
].longform
) {
3304 longopts
[j
].longOptName
= cmd
->commands
[i
].longform
;
3305 longopts
[j
].longOption
= 0;
3306 longopts
[j
++].valueRequired
= cmd
->commands
[i
].needsArg
;
3310 for (i
=0; j
<lopt
&& i
<cmd
->numOptions
; i
++) {
3311 if (cmd
->options
[i
].longform
) {
3312 longopts
[j
].longOptName
= cmd
->options
[i
].longform
;
3313 longopts
[j
].longOption
= 0;
3314 longopts
[j
++].valueRequired
= cmd
->options
[i
].needsArg
;
3317 longopts
[j
].longOptName
= NULL
;
3320 optstate
= PL_CreateLongOptState(argc
, argv
, optstring
, longopts
);
3322 PORT_Free(optstring
);
3323 PORT_Free(longopts
);
3326 /* Parse command line arguments */
3327 while ((status
= PL_GetNextOpt(optstate
)) == PL_OPT_OK
) {
3328 const char *optstatelong
;
3329 char option
= optstate
->option
;
3331 /* positional parameter, single-char option or long opt? */
3332 if (optstate
->longOptIndex
== -1) {
3333 /* not a long opt */
3335 continue; /* it's a positional parameter */
3340 option
= '\377'; /* force unequal with all flags */
3341 optstatelong
= longopts
[optstate
->longOptIndex
].longOptName
;
3346 for (i
=0; i
<cmd
->numCommands
; i
++) {
3347 if (cmd
->commands
[i
].flag
== option
||
3348 cmd
->commands
[i
].longform
== optstatelong
) {
3349 cmd
->commands
[i
].activated
= PR_TRUE
;
3350 if (optstate
->value
) {
3351 cmd
->commands
[i
].arg
= (char *)optstate
->value
;
3361 for (i
=0; i
<cmd
->numOptions
; i
++) {
3362 if (cmd
->options
[i
].flag
== option
||
3363 cmd
->options
[i
].longform
== optstatelong
) {
3364 cmd
->options
[i
].activated
= PR_TRUE
;
3365 if (optstate
->value
) {
3366 cmd
->options
[i
].arg
= (char *)optstate
->value
;
3367 } else if (cmd
->options
[i
].needsArg
) {
3368 status
= PL_OPT_BAD
;
3377 status
= PL_OPT_BAD
;
3383 PL_DestroyOptState(optstate
);
3384 PORT_Free(optstring
);
3386 PORT_Free(longopts
);
3387 if (status
== PL_OPT_BAD
)
3393 SECU_GetOptionArg(const secuCommand
*cmd
, int optionNum
)
3395 if (optionNum
< 0 || optionNum
>= cmd
->numOptions
)
3397 if (cmd
->options
[optionNum
].activated
)
3398 return PL_strdup(cmd
->options
[optionNum
].arg
);
3403 static char SECUErrorBuf
[64];
3406 SECU_ErrorStringRaw(int16 err
)
3409 SECUErrorBuf
[0] = '\0';
3410 else if (err
== SEC_ERROR_BAD_DATA
)
3411 sprintf(SECUErrorBuf
, "Bad data");
3412 else if (err
== SEC_ERROR_BAD_DATABASE
)
3413 sprintf(SECUErrorBuf
, "Problem with database");
3414 else if (err
== SEC_ERROR_BAD_DER
)
3415 sprintf(SECUErrorBuf
, "Problem with DER");
3416 else if (err
== SEC_ERROR_BAD_KEY
)
3417 sprintf(SECUErrorBuf
, "Problem with key");
3418 else if (err
== SEC_ERROR_BAD_PASSWORD
)
3419 sprintf(SECUErrorBuf
, "Incorrect password");
3420 else if (err
== SEC_ERROR_BAD_SIGNATURE
)
3421 sprintf(SECUErrorBuf
, "Bad signature");
3422 else if (err
== SEC_ERROR_EXPIRED_CERTIFICATE
)
3423 sprintf(SECUErrorBuf
, "Expired certificate");
3424 else if (err
== SEC_ERROR_EXTENSION_VALUE_INVALID
)
3425 sprintf(SECUErrorBuf
, "Invalid extension value");
3426 else if (err
== SEC_ERROR_INPUT_LEN
)
3427 sprintf(SECUErrorBuf
, "Problem with input length");
3428 else if (err
== SEC_ERROR_INVALID_ALGORITHM
)
3429 sprintf(SECUErrorBuf
, "Invalid algorithm");
3430 else if (err
== SEC_ERROR_INVALID_ARGS
)
3431 sprintf(SECUErrorBuf
, "Invalid arguments");
3432 else if (err
== SEC_ERROR_INVALID_AVA
)
3433 sprintf(SECUErrorBuf
, "Invalid AVA");
3434 else if (err
== SEC_ERROR_INVALID_TIME
)
3435 sprintf(SECUErrorBuf
, "Invalid time");
3436 else if (err
== SEC_ERROR_IO
)
3437 sprintf(SECUErrorBuf
, "Security I/O error");
3438 else if (err
== SEC_ERROR_LIBRARY_FAILURE
)
3439 sprintf(SECUErrorBuf
, "Library failure");
3440 else if (err
== SEC_ERROR_NO_MEMORY
)
3441 sprintf(SECUErrorBuf
, "Out of memory");
3442 else if (err
== SEC_ERROR_OLD_CRL
)
3443 sprintf(SECUErrorBuf
, "CRL is older than the current one");
3444 else if (err
== SEC_ERROR_OUTPUT_LEN
)
3445 sprintf(SECUErrorBuf
, "Problem with output length");
3446 else if (err
== SEC_ERROR_UNKNOWN_ISSUER
)
3447 sprintf(SECUErrorBuf
, "Unknown issuer");
3448 else if (err
== SEC_ERROR_UNTRUSTED_CERT
)
3449 sprintf(SECUErrorBuf
, "Untrusted certificate");
3450 else if (err
== SEC_ERROR_UNTRUSTED_ISSUER
)
3451 sprintf(SECUErrorBuf
, "Untrusted issuer");
3452 else if (err
== SSL_ERROR_BAD_CERTIFICATE
)
3453 sprintf(SECUErrorBuf
, "Bad certificate");
3454 else if (err
== SSL_ERROR_BAD_CLIENT
)
3455 sprintf(SECUErrorBuf
, "Bad client");
3456 else if (err
== SSL_ERROR_BAD_SERVER
)
3457 sprintf(SECUErrorBuf
, "Bad server");
3458 else if (err
== SSL_ERROR_EXPORT_ONLY_SERVER
)
3459 sprintf(SECUErrorBuf
, "Export only server");
3460 else if (err
== SSL_ERROR_NO_CERTIFICATE
)
3461 sprintf(SECUErrorBuf
, "No certificate");
3462 else if (err
== SSL_ERROR_NO_CYPHER_OVERLAP
)
3463 sprintf(SECUErrorBuf
, "No cypher overlap");
3464 else if (err
== SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE
)
3465 sprintf(SECUErrorBuf
, "Unsupported certificate type");
3466 else if (err
== SSL_ERROR_UNSUPPORTED_VERSION
)
3467 sprintf(SECUErrorBuf
, "Unsupported version");
3468 else if (err
== SSL_ERROR_US_ONLY_SERVER
)
3469 sprintf(SECUErrorBuf
, "U.S. only server");
3470 else if (err
== PR_IO_ERROR
)
3471 sprintf(SECUErrorBuf
, "I/O error");
3473 else if (err
== SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE
)
3474 sprintf (SECUErrorBuf
, "Expired Issuer Certificate");
3475 else if (err
== SEC_ERROR_REVOKED_CERTIFICATE
)
3476 sprintf (SECUErrorBuf
, "Revoked certificate");
3477 else if (err
== SEC_ERROR_NO_KEY
)
3478 sprintf (SECUErrorBuf
, "No private key in database for this cert");
3479 else if (err
== SEC_ERROR_CERT_NOT_VALID
)
3480 sprintf (SECUErrorBuf
, "Certificate is not valid");
3481 else if (err
== SEC_ERROR_EXTENSION_NOT_FOUND
)
3482 sprintf (SECUErrorBuf
, "Certificate extension was not found");
3483 else if (err
== SEC_ERROR_EXTENSION_VALUE_INVALID
)
3484 sprintf (SECUErrorBuf
, "Certificate extension value invalid");
3485 else if (err
== SEC_ERROR_CA_CERT_INVALID
)
3486 sprintf (SECUErrorBuf
, "Issuer certificate is invalid");
3487 else if (err
== SEC_ERROR_CERT_USAGES_INVALID
)
3488 sprintf (SECUErrorBuf
, "Certificate usages is invalid");
3489 else if (err
== SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION
)
3490 sprintf (SECUErrorBuf
, "Certificate has unknown critical extension");
3491 else if (err
== SEC_ERROR_PKCS7_BAD_SIGNATURE
)
3492 sprintf (SECUErrorBuf
, "Bad PKCS7 signature");
3493 else if (err
== SEC_ERROR_INADEQUATE_KEY_USAGE
)
3494 sprintf (SECUErrorBuf
, "Certificate not approved for this operation");
3495 else if (err
== SEC_ERROR_INADEQUATE_CERT_TYPE
)
3496 sprintf (SECUErrorBuf
, "Certificate not approved for this operation");
3498 return SECUErrorBuf
;
3502 SECU_ErrorString(int16 err
)
3507 SECU_ErrorStringRaw (err
);
3509 if (*SECUErrorBuf
== 0) {
3510 error_string
= SECU_GetString(err
);
3511 if (error_string
== NULL
|| *error_string
== '\0')
3512 sprintf(SECUErrorBuf
, "No error string found for %d.", err
);
3514 return error_string
;
3517 return SECUErrorBuf
;
3522 SECU_PrintPRandOSError(char *progName
)
3525 PRInt32 errLen
= PR_GetErrorTextLength();
3526 if (errLen
> 0 && errLen
< sizeof buffer
) {
3527 PR_GetErrorText(buffer
);
3529 SECU_PrintError(progName
, "function failed");
3530 if (errLen
> 0 && errLen
< sizeof buffer
) {
3531 PR_fprintf(PR_STDERR
, "\t%s\n", buffer
);
3537 bestCertName(CERTCertificate
*cert
) {
3538 if (cert
->nickname
) {
3539 return cert
->nickname
;
3541 if (cert
->emailAddr
&& cert
->emailAddr
[0]) {
3542 return cert
->emailAddr
;
3544 return cert
->subjectName
;
3548 SECU_printCertProblemsOnDate(FILE *outfile
, CERTCertDBHandle
*handle
,
3549 CERTCertificate
*cert
, PRBool checksig
,
3550 SECCertificateUsage certUsage
, void *pinArg
, PRBool verbose
,
3554 CERTVerifyLogNode
*node
;
3556 PRErrorCode err
= PORT_GetError();
3558 log
.arena
= PORT_NewArena(512);
3559 log
.head
= log
.tail
= NULL
;
3561 CERT_VerifyCertificate(handle
, cert
, checksig
, certUsage
, datetime
, pinArg
, &log
, NULL
);
3563 SECU_displayVerifyLog(outfile
, &log
, verbose
);
3565 for (node
= log
.head
; node
; node
= node
->next
) {
3567 CERT_DestroyCertificate(node
->cert
);
3569 PORT_FreeArena(log
.arena
, PR_FALSE
);
3571 PORT_SetError(err
); /* restore original error code */
3575 SECU_displayVerifyLog(FILE *outfile
, CERTVerifyLog
*log
,
3578 CERTVerifyLogNode
*node
= NULL
;
3579 unsigned int depth
= (unsigned int)-1;
3580 unsigned int flags
= 0;
3581 char * errstr
= NULL
;
3583 if (log
->count
> 0) {
3584 fprintf(outfile
,"PROBLEM WITH THE CERT CHAIN:\n");
3585 for (node
= log
->head
; node
; node
= node
->next
) {
3586 if (depth
!= node
->depth
) {
3587 depth
= node
->depth
;
3588 fprintf(outfile
,"CERT %d. %s %s:\n", depth
,
3589 bestCertName(node
->cert
),
3590 depth
? "[Certificate Authority]": "");
3592 const char * emailAddr
;
3593 emailAddr
= CERT_GetFirstEmailAddress(node
->cert
);
3595 fprintf(outfile
,"Email Address(es): ");
3597 fprintf(outfile
, "%s\n", emailAddr
);
3598 emailAddr
= CERT_GetNextEmailAddress(node
->cert
,
3600 } while (emailAddr
);
3604 fprintf(outfile
," ERROR %ld: %s\n", node
->error
,
3605 SECU_Strerror(node
->error
));
3607 switch (node
->error
) {
3608 case SEC_ERROR_INADEQUATE_KEY_USAGE
:
3609 flags
= (unsigned int)node
->arg
;
3611 case KU_DIGITAL_SIGNATURE
:
3612 errstr
= "Cert cannot sign.";
3614 case KU_KEY_ENCIPHERMENT
:
3615 errstr
= "Cert cannot encrypt.";
3617 case KU_KEY_CERT_SIGN
:
3618 errstr
= "Cert cannot sign other certs.";
3621 errstr
= "[unknown usage].";
3624 case SEC_ERROR_INADEQUATE_CERT_TYPE
:
3625 flags
= (unsigned int)node
->arg
;
3627 case NS_CERT_TYPE_SSL_CLIENT
:
3628 case NS_CERT_TYPE_SSL_SERVER
:
3629 errstr
= "Cert cannot be used for SSL.";
3631 case NS_CERT_TYPE_SSL_CA
:
3632 errstr
= "Cert cannot be used as an SSL CA.";
3634 case NS_CERT_TYPE_EMAIL
:
3635 errstr
= "Cert cannot be used for SMIME.";
3637 case NS_CERT_TYPE_EMAIL_CA
:
3638 errstr
= "Cert cannot be used as an SMIME CA.";
3640 case NS_CERT_TYPE_OBJECT_SIGNING
:
3641 errstr
= "Cert cannot be used for object signing.";
3643 case NS_CERT_TYPE_OBJECT_SIGNING_CA
:
3644 errstr
= "Cert cannot be used as an object signing CA.";
3647 errstr
= "[unknown usage].";
3650 case SEC_ERROR_UNKNOWN_ISSUER
:
3651 case SEC_ERROR_UNTRUSTED_ISSUER
:
3652 case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE
:
3653 errstr
= node
->cert
->issuerName
;
3659 fprintf(stderr
," %s\n",errstr
);
3666 SECU_printCertProblems(FILE *outfile
, CERTCertDBHandle
*handle
,
3667 CERTCertificate
*cert
, PRBool checksig
,
3668 SECCertificateUsage certUsage
, void *pinArg
, PRBool verbose
)
3670 SECU_printCertProblemsOnDate(outfile
, handle
, cert
, checksig
,
3671 certUsage
, pinArg
, verbose
, PR_Now());
3675 SECU_StringToSignatureAlgTag(const char *alg
)
3677 SECOidTag hashAlgTag
= SEC_OID_UNKNOWN
;
3680 if (!PL_strcmp(alg
, "MD2")) {
3681 hashAlgTag
= SEC_OID_MD2
;
3682 } else if (!PL_strcmp(alg
, "MD4")) {
3683 hashAlgTag
= SEC_OID_MD4
;
3684 } else if (!PL_strcmp(alg
, "MD5")) {
3685 hashAlgTag
= SEC_OID_MD5
;
3686 } else if (!PL_strcmp(alg
, "SHA1")) {
3687 hashAlgTag
= SEC_OID_SHA1
;
3688 } else if (!PL_strcmp(alg
, "SHA256")) {
3689 hashAlgTag
= SEC_OID_SHA256
;
3690 } else if (!PL_strcmp(alg
, "SHA384")) {
3691 hashAlgTag
= SEC_OID_SHA384
;
3692 } else if (!PL_strcmp(alg
, "SHA512")) {
3693 hashAlgTag
= SEC_OID_SHA512
;
3701 SECU_StoreCRL(PK11SlotInfo
*slot
, SECItem
*derCrl
, PRFileDesc
*outFile
,
3702 PRBool ascii
, char *url
)
3704 PORT_Assert(derCrl
!= NULL
);
3706 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
3710 if (outFile
!= NULL
) {
3712 PR_fprintf(outFile
, "%s\n%s\n%s\n", NS_CRL_HEADER
,
3713 BTOA_DataToAscii(derCrl
->data
, derCrl
->len
),
3716 if (PR_Write(outFile
, derCrl
->data
, derCrl
->len
) != derCrl
->len
) {
3722 CERTSignedCrl
*newCrl
= PK11_ImportCRL(slot
, derCrl
, url
,
3723 SEC_CRL_TYPE
, NULL
, 0, NULL
, 0);
3724 if (newCrl
!= NULL
) {
3725 SEC_DestroyCrl(newCrl
);
3730 if (!outFile
&& !slot
) {
3731 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
3738 SECU_SignAndEncodeCRL(CERTCertificate
*issuer
, CERTSignedCrl
*signCrl
,
3739 SECOidTag hashAlgTag
, SignAndEncodeFuncExitStat
*resCode
)
3742 SECKEYPrivateKey
*caPrivateKey
= NULL
;
3748 PORT_Assert(issuer
!= NULL
&& signCrl
!= NULL
);
3749 if (!issuer
|| !signCrl
) {
3750 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
3754 arena
= signCrl
->arena
;
3756 caPrivateKey
= PK11_FindKeyByAnyCert(issuer
, NULL
);
3757 if (caPrivateKey
== NULL
) {
3758 *resCode
= noKeyFound
;
3762 algID
= SEC_GetSignatureAlgorithmOidTag(caPrivateKey
->keyType
, hashAlgTag
);
3763 if (algID
== SEC_OID_UNKNOWN
) {
3764 *resCode
= noSignatureMatch
;
3769 if (!signCrl
->crl
.signatureAlg
.parameters
.data
) {
3770 rv
= SECOID_SetAlgorithmID(arena
, &signCrl
->crl
.signatureAlg
, algID
, 0);
3771 if (rv
!= SECSuccess
) {
3772 *resCode
= failToEncode
;
3779 dummy
= SEC_ASN1EncodeItem(arena
, &der
, &signCrl
->crl
,
3780 SEC_ASN1_GET(CERT_CrlTemplate
));
3782 *resCode
= failToEncode
;
3787 rv
= SECU_DerSignDataCRL(arena
, &signCrl
->signatureWrap
,
3788 der
.data
, der
.len
, caPrivateKey
, algID
);
3789 if (rv
!= SECSuccess
) {
3790 *resCode
= failToSign
;
3794 signCrl
->derCrl
= PORT_ArenaZNew(arena
, SECItem
);
3795 if (signCrl
->derCrl
== NULL
) {
3797 PORT_SetError(SEC_ERROR_NO_MEMORY
);
3802 signCrl
->derCrl
->len
= 0;
3803 signCrl
->derCrl
->data
= NULL
;
3804 dummy
= SEC_ASN1EncodeItem (arena
, signCrl
->derCrl
, signCrl
,
3805 SEC_ASN1_GET(CERT_SignedCrlTemplate
));
3807 *resCode
= failToEncode
;
3814 SECKEY_DestroyPrivateKey(caPrivateKey
);
3822 SECU_CopyCRL(PRArenaPool
*destArena
, CERTCrl
*destCrl
, CERTCrl
*srcCrl
)
3825 SECStatus rv
= SECSuccess
;
3828 PORT_Assert(destArena
&& srcCrl
&& destCrl
);
3829 if (!destArena
|| !srcCrl
|| !destCrl
) {
3830 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
3836 dummy
= SEC_ASN1EncodeItem (destArena
, &der
, srcCrl
,
3837 SEC_ASN1_GET(CERT_CrlTemplate
));
3842 rv
= SEC_QuickDERDecodeItem(destArena
, destCrl
,
3843 SEC_ASN1_GET(CERT_CrlTemplate
), &der
);
3844 if (rv
!= SECSuccess
) {
3848 destCrl
->arena
= destArena
;
3854 SECU_DerSignDataCRL(PRArenaPool
*arena
, CERTSignedData
*sd
,
3855 unsigned char *buf
, int len
, SECKEYPrivateKey
*pk
,
3863 /* XXX We should probably have some asserts here to make sure the key type
3867 /* Sign input buffer */
3868 rv
= SEC_SignData(&it
, buf
, len
, pk
, algID
);
3871 /* Fill out SignedData object */
3872 PORT_Memset(sd
, 0, sizeof(sd
));
3873 sd
->data
.data
= buf
;
3875 sd
->signature
.data
= it
.data
;
3876 sd
->signature
.len
= it
.len
<< 3; /* convert to bit string */
3877 if (!sd
->signatureAlgorithm
.parameters
.data
) {
3878 rv
= SECOID_SetAlgorithmID(arena
, &sd
->signatureAlgorithm
, algID
, 0);
3891 /* we need access to the private function cert_FindExtension for this code to work */
3894 SECU_FindCRLAuthKeyIDExten (PRArenaPool
*arena
, CERTSignedCrl
*scrl
)
3896 SECItem encodedExtenValue
;
3902 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
3908 encodedExtenValue
.data
= NULL
;
3909 encodedExtenValue
.len
= 0;
3911 rv
= cert_FindExtension(crl
->extensions
, SEC_OID_X509_AUTH_KEY_ID
,
3912 &encodedExtenValue
);
3913 if ( rv
!= SECSuccess
) {
3917 ret
= CERT_DecodeAuthKeyID (arena
, &encodedExtenValue
);
3919 PORT_Free(encodedExtenValue
.data
);
3920 encodedExtenValue
.data
= NULL
;
3928 * Find the issuer of a Crl. Use the authorityKeyID if it exists.
3931 SECU_FindCrlIssuer(CERTCertDBHandle
*dbhandle
, SECItem
* subject
,
3932 CERTAuthKeyID
* authorityKeyID
, PRTime validTime
)
3934 CERTCertificate
*issuerCert
= NULL
;
3935 CERTCertList
*certList
= NULL
;
3938 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
3943 CERT_CreateSubjectCertList(NULL
, dbhandle
, subject
,
3944 validTime
, PR_TRUE
);
3946 CERTCertListNode
*node
= CERT_LIST_HEAD(certList
);
3948 /* XXX and authoritykeyid in the future */
3949 while ( ! CERT_LIST_END(node
, certList
) ) {
3950 CERTCertificate
*cert
= node
->cert
;
3951 /* check cert CERTCertTrust data is allocated, check cert
3952 usage extension, check that cert has pkey in db. Select
3953 the first (newest) user cert */
3955 CERT_CheckCertUsage(cert
, KU_CRL_SIGN
) == SECSuccess
&&
3956 CERT_IsUserCert(cert
)) {
3958 issuerCert
= CERT_DupCertificate(cert
);
3961 node
= CERT_LIST_NEXT(node
);
3963 CERT_DestroyCertList(certList
);
3969 /* Encodes and adds extensions to the CRL or CRL entries. */
3971 SECU_EncodeAndAddExtensionValue(PRArenaPool
*arena
, void *extHandle
,
3972 void *value
, PRBool criticality
, int extenType
,
3973 EXTEN_EXT_VALUE_ENCODER EncodeValueFn
)
3975 SECItem encodedValue
;
3978 encodedValue
.data
= NULL
;
3979 encodedValue
.len
= 0;
3981 rv
= (*EncodeValueFn
)(arena
, value
, &encodedValue
);
3982 if (rv
!= SECSuccess
)
3985 rv
= CERT_AddExtension(extHandle
, extenType
, &encodedValue
,
3986 criticality
, PR_TRUE
);
3987 if (rv
!= SECSuccess
)
3994 /* Caller ensures that dst is at least item->len*2+1 bytes long */
3996 SECU_SECItemToHex(const SECItem
* item
, char * dst
)
3998 if (dst
&& item
&& item
->data
) {
3999 unsigned char * src
= item
->data
;
4000 unsigned int len
= item
->len
;
4001 for (; len
> 0; --len
, dst
+= 2) {
4002 sprintf(dst
, "%02x", *src
++);
4008 static unsigned char nibble(char c
) {
4009 c
= PORT_Tolower(c
);
4010 return ( c
>= '0' && c
<= '9') ? c
- '0' :
4011 ( c
>= 'a' && c
<= 'f') ? c
- 'a' +10 : -1;
4015 SECU_SECItemHexStringToBinary(SECItem
* srcdest
)
4020 PORT_SetError(SEC_ERROR_INVALID_ARGS
);
4023 if (srcdest
->len
< 4 || (srcdest
->len
% 2) ) {
4024 /* too short to convert, or even number of characters */
4025 PORT_SetError(SEC_ERROR_BAD_DATA
);
4028 if (PORT_Strncasecmp((const char*)srcdest
->data
, "0x", 2)) {
4030 PORT_SetError(SEC_ERROR_BAD_DATA
);
4034 /* 1st pass to check for hex characters */
4035 for (i
=2; i
<srcdest
->len
; i
++) {
4036 char c
= PORT_Tolower(srcdest
->data
[i
]);
4037 if (! ( ( c
>= '0' && c
<= '9') ||
4038 ( c
>= 'a' && c
<= 'f')
4040 PORT_SetError(SEC_ERROR_BAD_DATA
);
4045 /* 2nd pass to convert */
4046 for (i
=2; i
<srcdest
->len
; i
+=2) {
4047 srcdest
->data
[(i
-2)/2] = (nibble(srcdest
->data
[i
]) << 4) +
4048 nibble(srcdest
->data
[i
+1]);