Bug Summary

File:root/firefox-clang/security/nss/cmd/lib/secutil.c
Warning:line 3814, column 62
Subtraction of a probably non-null pointer and a null pointer may result in undefined behavior

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name secutil.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/security/nss/cmd/lib/lib_sectool -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/security/nss/cmd/lib/lib_sectool -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG -D NSPR20 -D NSS_USE_STATIC_LIBS -D NSS_FIPS_DISABLED -D NSS_NO_INIT_SUPPORT -D NSS_X86_OR_X64 -D NSS_X64 -D NSS_USE_64 -D USE_UTIL_DIRECTLY -D NO_NSPR_10_SUPPORT -D SSL_DISABLE_DEPRECATED_CIPHER_SUITE_NAMES -D LINUX2_1 -D LINUX -D linux -D _DEFAULT_SOURCE -D _BSD_SOURCE -D _POSIX_SOURCE -D SDB_MEASURE_USE_TEMP_DIR -D HAVE_STRERROR -D XP_UNIX -D _REENTRANT -D NSS_DISABLE_DBM -D NSS_DISABLE_LIBPKIX -D NSS_USE_PKCS5_PBKD2_PARAMS2_ONLY -D SOFTOKEN_USE_PKCS5_PBKD2_PARAMS2_ONLY -I /root/firefox-clang/security/nss/cmd/lib -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/security/nss/cmd/lib/lib_sectool -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/private/nss -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -D MOZILLA_CLIENT -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=tautological-type-limit-compare -Wno-range-loop-analysis -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-unknown-warning-option -Wno-character-conversion -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-10-17-231001-351276-1 -x c /root/firefox-clang/security/nss/cmd/lib/secutil.c
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4/*
5** secutil.c - various functions used by security stuff
6**
7*/
8
9#include "prtypes.h"
10#include "prtime.h"
11#include "prlong.h"
12#include "prerror.h"
13#include "prprf.h"
14#include "plgetopt.h"
15#include "prenv.h"
16#include "prnetdb.h"
17
18#include "cryptohi.h"
19#include "secutil.h"
20#include "secpkcs7.h"
21#include "secpkcs5.h"
22#include <stdarg.h>
23#include <stdio.h>
24#include <sys/stat.h>
25#include <errno(*__errno_location ()).h>
26#include <limits.h>
27
28#ifdef XP_UNIX1
29#include <unistd.h>
30#endif
31
32/* for SEC_TraverseNames */
33#include "cert.h"
34#include "certt.h"
35#include "certdb.h"
36
37#include "secmod.h"
38#include "pk11func.h"
39#include "secoid.h"
40
41static char consoleName[] = {
42#ifdef XP_UNIX1
43 "/dev/tty"
44#else
45 "CON:"
46#endif
47};
48
49#include "cert.h"
50#include "nssutil.h"
51#include "ssl.h"
52#include "sslproto.h"
53#include "xconst.h"
54
55#define DEFN_EXTEN_EXT_VALUE_ENCODER(mmm)SECStatus EXTEN_EXT_VALUE_ENCODER_mmm(PLArenaPool *extHandleArena
, void *value, SECItem *encodedValue) { return mmm(extHandleArena
, value, encodedValue); }
\
56 SECStatus EXTEN_EXT_VALUE_ENCODER_##mmm(PLArenaPool *extHandleArena, \
57 void *value, SECItem *encodedValue) \
58 { \
59 return mmm(extHandleArena, value, encodedValue); \
60 }
61
62DEFN_EXTEN_EXT_VALUE_ENCODER(CERT_EncodeAltNameExtension)SECStatus EXTEN_EXT_VALUE_ENCODER_CERT_EncodeAltNameExtension
(PLArenaPool *extHandleArena, void *value, SECItem *encodedValue
) { return CERT_EncodeAltNameExtension(extHandleArena, value,
encodedValue); }
63DEFN_EXTEN_EXT_VALUE_ENCODER(CERT_EncodeAuthKeyID)SECStatus EXTEN_EXT_VALUE_ENCODER_CERT_EncodeAuthKeyID(PLArenaPool
*extHandleArena, void *value, SECItem *encodedValue) { return
CERT_EncodeAuthKeyID(extHandleArena, value, encodedValue); }
64DEFN_EXTEN_EXT_VALUE_ENCODER(CERT_EncodeBasicConstraintValue)SECStatus EXTEN_EXT_VALUE_ENCODER_CERT_EncodeBasicConstraintValue
(PLArenaPool *extHandleArena, void *value, SECItem *encodedValue
) { return CERT_EncodeBasicConstraintValue(extHandleArena, value
, encodedValue); }
65DEFN_EXTEN_EXT_VALUE_ENCODER(CERT_EncodeCRLDistributionPoints)SECStatus EXTEN_EXT_VALUE_ENCODER_CERT_EncodeCRLDistributionPoints
(PLArenaPool *extHandleArena, void *value, SECItem *encodedValue
) { return CERT_EncodeCRLDistributionPoints(extHandleArena, value
, encodedValue); }
66DEFN_EXTEN_EXT_VALUE_ENCODER(CERT_EncodeCertPoliciesExtension)SECStatus EXTEN_EXT_VALUE_ENCODER_CERT_EncodeCertPoliciesExtension
(PLArenaPool *extHandleArena, void *value, SECItem *encodedValue
) { return CERT_EncodeCertPoliciesExtension(extHandleArena, value
, encodedValue); }
67DEFN_EXTEN_EXT_VALUE_ENCODER(CERT_EncodeInfoAccessExtension)SECStatus EXTEN_EXT_VALUE_ENCODER_CERT_EncodeInfoAccessExtension
(PLArenaPool *extHandleArena, void *value, SECItem *encodedValue
) { return CERT_EncodeInfoAccessExtension(extHandleArena, value
, encodedValue); }
68DEFN_EXTEN_EXT_VALUE_ENCODER(CERT_EncodeInhibitAnyExtension)SECStatus EXTEN_EXT_VALUE_ENCODER_CERT_EncodeInhibitAnyExtension
(PLArenaPool *extHandleArena, void *value, SECItem *encodedValue
) { return CERT_EncodeInhibitAnyExtension(extHandleArena, value
, encodedValue); }
69DEFN_EXTEN_EXT_VALUE_ENCODER(CERT_EncodeNameConstraintsExtension)SECStatus EXTEN_EXT_VALUE_ENCODER_CERT_EncodeNameConstraintsExtension
(PLArenaPool *extHandleArena, void *value, SECItem *encodedValue
) { return CERT_EncodeNameConstraintsExtension(extHandleArena
, value, encodedValue); }
70DEFN_EXTEN_EXT_VALUE_ENCODER(CERT_EncodePolicyConstraintsExtension)SECStatus EXTEN_EXT_VALUE_ENCODER_CERT_EncodePolicyConstraintsExtension
(PLArenaPool *extHandleArena, void *value, SECItem *encodedValue
) { return CERT_EncodePolicyConstraintsExtension(extHandleArena
, value, encodedValue); }
71DEFN_EXTEN_EXT_VALUE_ENCODER(CERT_EncodePolicyMappingExtension)SECStatus EXTEN_EXT_VALUE_ENCODER_CERT_EncodePolicyMappingExtension
(PLArenaPool *extHandleArena, void *value, SECItem *encodedValue
) { return CERT_EncodePolicyMappingExtension(extHandleArena, value
, encodedValue); }
72DEFN_EXTEN_EXT_VALUE_ENCODER(CERT_EncodeSubjectKeyID)SECStatus EXTEN_EXT_VALUE_ENCODER_CERT_EncodeSubjectKeyID(PLArenaPool
*extHandleArena, void *value, SECItem *encodedValue) { return
CERT_EncodeSubjectKeyID(extHandleArena, value, encodedValue)
; }
73
74static PRBool utf8DisplayEnabled = PR_FALSE0;
75
76/* The minimum password/pin length (in Unicode characters) in FIPS mode,
77 * defined in lib/softoken/pkcs11i.h. */
78#define FIPS_MIN_PIN7 7
79
80void
81SECU_EnableUtf8Display(PRBool enable)
82{
83 utf8DisplayEnabled = enable;
84}
85
86PRBool
87SECU_GetUtf8DisplayEnabled(void)
88{
89 return utf8DisplayEnabled;
90}
91
92static void
93secu_ClearPassword(char *p)
94{
95 if (p) {
96 PORT_Memsetmemset(p, 0, PORT_Strlen(p)strlen(p));
97 PORT_FreePORT_Free_Util(p);
98 }
99}
100
101char *
102SECU_GetPasswordString(void *arg, char *prompt)
103{
104#ifndef _WINDOWS
105 char *p = NULL((void*)0);
106 FILE *input, *output;
107
108 /* open terminal */
109 input = fopen(consoleName, "r");
110 if (input == NULL((void*)0)) {
111 fprintf(stderrstderr, "Error opening input terminal for read\n");
112 return NULL((void*)0);
113 }
114
115 output = fopen(consoleName, "w");
116 if (output == NULL((void*)0)) {
117 fprintf(stderrstderr, "Error opening output terminal for write\n");
118 fclose(input);
119 return NULL((void*)0);
120 }
121
122 p = SEC_GetPassword(input, output, prompt, SEC_BlindCheckPassword);
123
124 fclose(input);
125 fclose(output);
126
127 return p;
128
129#else
130 /* Win32 version of above. opening the console may fail
131 on windows95, and certainly isn't necessary.. */
132
133 char *p = NULL((void*)0);
134
135 p = SEC_GetPassword(stdinstdin, stdoutstdout, prompt, SEC_BlindCheckPassword);
136 return p;
137
138#endif
139}
140
141/*
142 * p a s s w o r d _ h a r d c o d e
143 *
144 * A function to use the password passed in the -f(pwfile) argument
145 * of the command line.
146 * After use once, null it out otherwise PKCS11 calls us forever.?
147 *
148 */
149char *
150SECU_FilePasswd(PK11SlotInfo *slot, PRBool retry, void *arg)
151{
152 char *phrases, *phrase;
153 PRFileDesc *fd;
154 PRInt32 nb;
155 char *pwFile = arg;
156 int i;
157 const long maxPwdFileSize = 4096;
158 char *tokenName = NULL((void*)0);
159 int tokenLen = 0;
160
161 if (!pwFile)
162 return 0;
163
164 if (retry) {
165 return 0; /* no good retrying - the files contents will be the same */
166 }
167
168 phrases = PORT_ZAllocPORT_ZAlloc_Util(maxPwdFileSize);
169
170 if (!phrases) {
171 return 0; /* out of memory */
172 }
173
174 fd = PR_Open(pwFile, PR_RDONLY0x01, 0);
175 if (!fd) {
176 fprintf(stderrstderr, "No password file \"%s\" exists.\n", pwFile);
177 PORT_FreePORT_Free_Util(phrases);
178 return NULL((void*)0);
179 }
180
181 nb = PR_Read(fd, phrases, maxPwdFileSize);
182
183 PR_Close(fd);
184
185 if (nb == 0) {
186 fprintf(stderrstderr, "password file contains no data\n");
187 PORT_FreePORT_Free_Util(phrases);
188 return NULL((void*)0);
189 }
190
191 if (slot) {
192 tokenName = PK11_GetTokenName(slot);
193 if (tokenName) {
194 tokenLen = PORT_Strlen(tokenName)strlen(tokenName);
195 }
196 }
197 i = 0;
198 do {
199 int startphrase = i;
200 int phraseLen;
201
202 /* handle the Windows EOL case */
203 while (phrases[i] != '\r' && phrases[i] != '\n' && i < nb)
204 i++;
205 /* terminate passphrase */
206 phrases[i++] = '\0';
207 /* clean up any EOL before the start of the next passphrase */
208 while ((i < nb) && (phrases[i] == '\r' || phrases[i] == '\n')) {
209 phrases[i++] = '\0';
210 }
211 /* now analyze the current passphrase */
212 phrase = &phrases[startphrase];
213 if (!tokenName)
214 break;
215 if (PORT_Strncmpstrncmp(phrase, tokenName, tokenLen))
216 continue;
217 phraseLen = PORT_Strlen(phrase)strlen(phrase);
218 if (phraseLen < (tokenLen + 1))
219 continue;
220 if (phrase[tokenLen] != ':')
221 continue;
222 phrase = &phrase[tokenLen + 1];
223 break;
224
225 } while (i < nb);
226
227 phrase = PORT_StrdupPORT_Strdup_Util((char *)phrase);
228 PORT_FreePORT_Free_Util(phrases);
229 return phrase;
230}
231
232char *
233SECU_GetModulePassword(PK11SlotInfo *slot, PRBool retry, void *arg)
234{
235 char prompt[255];
236 secuPWData *pwdata = (secuPWData *)arg;
237 secuPWData pwnull = { PW_NONE, 0 };
238 secuPWData pwxtrn = { PW_EXTERNAL, "external" };
239
240 if (pwdata == NULL((void*)0))
241 pwdata = &pwnull;
242
243 if (PK11_ProtectedAuthenticationPath(slot)) {
244 pwdata = &pwxtrn;
245 }
246 if (retry && pwdata->source != PW_NONE) {
247 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "Incorrect password/PIN entered.\n");
248 return NULL((void*)0);
249 }
250
251 switch (pwdata->source) {
252 case PW_NONE:
253 snprintf(prompt, sizeof(prompt), "Enter Password or Pin for \"%s\":",
254 PK11_GetTokenName(slot));
255 return SECU_GetPasswordString(NULL((void*)0), prompt);
256 case PW_FROMFILE:
257 return SECU_FilePasswd(slot, retry, pwdata->data);
258 case PW_EXTERNAL:
259 snprintf(prompt, sizeof(prompt),
260 "Press Enter, then enter PIN for \"%s\" on external device.\n",
261 PK11_GetTokenName(slot));
262 char *pw = SECU_GetPasswordString(NULL((void*)0), prompt);
263 PORT_FreePORT_Free_Util(pw);
264 /* Fall Through */
265 case PW_PLAINTEXT:
266 return PL_strdup(pwdata->data);
267 default:
268 break;
269 }
270
271 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "Password check failed: No password found.\n");
272 return NULL((void*)0);
273}
274
275char *
276secu_InitSlotPassword(PK11SlotInfo *slot, PRBool retry, void *arg)
277{
278 char *p0 = NULL((void*)0);
279 char *p1 = NULL((void*)0);
280 FILE *input, *output;
281 secuPWData *pwdata = arg;
282
283 if (pwdata->source == PW_FROMFILE) {
284 return SECU_FilePasswd(slot, retry, pwdata->data);
285 }
286 if (pwdata->source == PW_PLAINTEXT) {
287 return PL_strdup(pwdata->data);
288 }
289
290/* PW_NONE - get it from tty */
291/* open terminal */
292#ifdef _WINDOWS
293 input = stdinstdin;
294#else
295 input = fopen(consoleName, "r");
296#endif
297 if (input == NULL((void*)0)) {
298 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "Error opening input terminal for read\n");
299 return NULL((void*)0);
300 }
301
302 /* we have no password, so initialize database with one */
303 if (PK11_IsFIPS()) {
304 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
305 "Enter a password which will be used to encrypt your keys.\n"
306 "The password should be at least %d characters long,\n"
307 "and should consist of at least three character classes.\n"
308 "The available character classes are: digits (0-9), ASCII\n"
309 "lowercase letters, ASCII uppercase letters, ASCII\n"
310 "non-alphanumeric characters, and non-ASCII characters.\n\n"
311 "If an ASCII uppercase letter appears at the beginning of\n"
312 "the password, it is not counted toward its character class.\n"
313 "Similarly, if a digit appears at the end of the password,\n"
314 "it is not counted toward its character class.\n\n",
315 FIPS_MIN_PIN7);
316 } else {
317 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
318 "Enter a password which will be used to encrypt your keys.\n"
319 "The password should be at least 8 characters long,\n"
320 "and should contain at least one non-alphabetic character.\n\n");
321 }
322
323 output = fopen(consoleName, "w");
324 if (output == NULL((void*)0)) {
325 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "Error opening output terminal for write\n");
326#ifndef _WINDOWS
327 fclose(input);
328#endif
329 return NULL((void*)0);
330 }
331
332 for (;;) {
333 if (p0)
334 PORT_FreePORT_Free_Util(p0);
335 p0 = SEC_GetPassword(input, output, "Enter new password: ",
336 SEC_BlindCheckPassword);
337
338 if (p1)
339 PORT_FreePORT_Free_Util(p1);
340 p1 = SEC_GetPassword(input, output, "Re-enter password: ",
341 SEC_BlindCheckPassword);
342 if (p0 && p1 && !PORT_Strcmpstrcmp(p0, p1)) {
343 break;
344 }
345 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "Passwords do not match. Try again.\n");
346 }
347
348 /* clear out the duplicate password string */
349 secu_ClearPassword(p1);
350
351 fclose(input);
352 fclose(output);
353
354 return p0;
355}
356
357SECStatus
358SECU_ChangePW(PK11SlotInfo *slot, char *passwd, char *pwFile)
359{
360 return SECU_ChangePW2(slot, passwd, 0, pwFile, 0);
361}
362
363SECStatus
364SECU_ChangePW2(PK11SlotInfo *slot, char *oldPass, char *newPass,
365 char *oldPwFile, char *newPwFile)
366{
367 SECStatus rv;
368 secuPWData pwdata, newpwdata;
369 char *oldpw = NULL((void*)0), *newpw = NULL((void*)0);
370
371 if (oldPass) {
372 pwdata.source = PW_PLAINTEXT;
373 pwdata.data = oldPass;
374 } else if (oldPwFile) {
375 pwdata.source = PW_FROMFILE;
376 pwdata.data = oldPwFile;
377 } else {
378 pwdata.source = PW_NONE;
379 pwdata.data = NULL((void*)0);
380 }
381
382 if (newPass) {
383 newpwdata.source = PW_PLAINTEXT;
384 newpwdata.data = newPass;
385 } else if (newPwFile) {
386 newpwdata.source = PW_FROMFILE;
387 newpwdata.data = newPwFile;
388 } else {
389 newpwdata.source = PW_NONE;
390 newpwdata.data = NULL((void*)0);
391 }
392
393 if (PK11_NeedUserInit(slot)) {
394 newpw = secu_InitSlotPassword(slot, PR_FALSE0, &pwdata);
395 rv = PK11_InitPin(slot, (char *)NULL((void*)0), newpw);
396 goto done;
397 }
398
399 for (;;) {
400 oldpw = SECU_GetModulePassword(slot, PR_FALSE0, &pwdata);
401
402 if (PK11_CheckUserPassword(slot, oldpw) != SECSuccess) {
403 if (pwdata.source == PW_NONE) {
404 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "Invalid password. Try again.\n");
405 } else {
406 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "Invalid password.\n");
407 PORT_Memsetmemset(oldpw, 0, PL_strlen(oldpw));
408 PORT_FreePORT_Free_Util(oldpw);
409 rv = SECFailure;
410 goto done;
411 }
412 } else
413 break;
414
415 PORT_FreePORT_Free_Util(oldpw);
416 }
417
418 newpw = secu_InitSlotPassword(slot, PR_FALSE0, &newpwdata);
419
420 rv = PK11_ChangePW(slot, oldpw, newpw);
421 if (rv != SECSuccess) {
422 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "Failed to change password.\n");
423 } else {
424 PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), "Password changed successfully.\n");
425 }
426
427 PORT_Memsetmemset(oldpw, 0, PL_strlen(oldpw));
428 PORT_FreePORT_Free_Util(oldpw);
429
430done:
431 if (newpw) {
432 PORT_Memsetmemset(newpw, 0, PL_strlen(newpw));
433 PORT_FreePORT_Free_Util(newpw);
434 }
435 return rv;
436}
437
438struct matchobj {
439 SECItem index;
440 char *nname;
441 PRBool found;
442};
443
444char *
445SECU_DefaultSSLDir(void)
446{
447 char *dir;
448 static char sslDir[1000];
449
450 dir = PR_GetEnvSecure("SSL_DIR");
451 if (!dir)
452 return NULL((void*)0);
453
454 if (strlen(dir) >= PR_ARRAY_SIZE(sslDir)(sizeof(sslDir) / sizeof((sslDir)[0]))) {
455 return NULL((void*)0);
456 }
457 snprintf(sslDir, sizeof(sslDir), "%s", dir);
458
459 if (sslDir[strlen(sslDir) - 1] == '/')
460 sslDir[strlen(sslDir) - 1] = 0;
461
462 return sslDir;
463}
464
465char *
466SECU_AppendFilenameToDir(char *dir, char *filename)
467{
468 static char path[1000];
469
470 if (dir[strlen(dir) - 1] == '/')
471 snprintf(path, sizeof(path), "%s%s", dir, filename);
472 else
473 snprintf(path, sizeof(path), "%s/%s", dir, filename);
474 return path;
475}
476
477char *
478SECU_ConfigDirectory(const char *base)
479{
480 static PRBool initted = PR_FALSE0;
481 const char *dir = ".netscape";
482 char *home;
483 static char buf[1000];
484
485 if (initted)
486 return buf;
487
488 if (base == NULL((void*)0) || *base == 0) {
489 home = PR_GetEnvSecure("HOME");
490 if (!home)
491 home = "";
492
493 if (*home && home[strlen(home) - 1] == '/')
494 snprintf(buf, sizeof(buf), "%.900s%s", home, dir);
495 else
496 snprintf(buf, sizeof(buf), "%.900s/%s", home, dir);
497 } else {
498 snprintf(buf, sizeof(buf), "%.900s", base);
499 if (buf[strlen(buf) - 1] == '/')
500 buf[strlen(buf) - 1] = 0;
501 }
502
503 initted = PR_TRUE1;
504 return buf;
505}
506
507SECStatus
508SECU_ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii,
509 PRBool warnOnPrivateKeyInAsciiFile)
510{
511 SECStatus rv;
512 if (ascii) {
513 /* First convert ascii to binary */
514 SECItem filedata;
515
516 /* Read in ascii data */
517 rv = SECU_FileToItem(&filedata, inFile);
518 if (rv != SECSuccess)
519 return rv;
520 if (!filedata.data) {
521 fprintf(stderrstderr, "unable to read data from input file\n");
522 return SECFailure;
523 }
524 /* need one additional byte for zero terminator */
525 rv = SECITEM_ReallocItemV2(NULL((void*)0), &filedata, filedata.len + 1);
526 if (rv != SECSuccess) {
527 PORT_FreePORT_Free_Util(filedata.data);
528 return rv;
529 }
530 char *asc = (char *)filedata.data;
531 asc[filedata.len - 1] = '\0';
532
533 if (warnOnPrivateKeyInAsciiFile && strstr(asc, "PRIVATE KEY")) {
534 fprintf(stderrstderr, "Warning: ignoring private key. Consider to use "
535 "pk12util.\n");
536 }
537
538 char *body;
539 /* check for headers and trailers and remove them */
540 if ((body = strstr(asc, "-----BEGIN")) != NULL((void*)0)) {
541 char *trailer = NULL((void*)0);
542 asc = body;
543 body = PORT_Strchrstrchr(body, '\n');
544 if (!body)
545 body = PORT_Strchrstrchr(asc, '\r'); /* maybe this is a MAC file */
546 if (body)
547 trailer = strstr(++body, "-----END");
548 if (trailer != NULL((void*)0)) {
549 *trailer = '\0';
550 } else {
551 fprintf(stderrstderr, "input has header but no trailer\n");
552 PORT_FreePORT_Free_Util(filedata.data);
553 return SECFailure;
554 }
555 } else {
556 body = asc;
557 }
558
559 /* Convert to binary */
560 rv = ATOB_ConvertAsciiToItemATOB_ConvertAsciiToItem_Util(der, body);
561 if (rv != SECSuccess) {
562 fprintf(stderrstderr, "error converting ascii to binary (%s)\n",
563 SECU_Strerror(PORT_GetError())PR_ErrorToString((PORT_GetError_Util()), 0));
564 PORT_FreePORT_Free_Util(filedata.data);
565 return SECFailure;
566 }
567
568 PORT_FreePORT_Free_Util(filedata.data);
569 } else {
570 /* Read in binary der */
571 rv = SECU_FileToItem(der, inFile);
572 if (rv != SECSuccess) {
573 fprintf(stderrstderr, "error converting der (%s)\n",
574 SECU_Strerror(PORT_GetError())PR_ErrorToString((PORT_GetError_Util()), 0));
575 return SECFailure;
576 }
577 }
578 return SECSuccess;
579}
580
581#define INDENT_MULT4 4
582
583/*
584 * remove the tag and length and just leave the bare BER data
585 */
586SECStatus
587SECU_StripTagAndLength(SECItem *i)
588{
589 unsigned int start;
590 PRBool isIndefinite;
591
592 if (!i || !i->data || i->len < 2) { /* must be at least tag and length */
593 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
594 return SECFailure;
595 }
596 isIndefinite = (i->data[1] == 0x80);
597 start = ((i->data[1] & 0x80) ? (i->data[1] & 0x7f) + 2 : 2);
598 if (i->len < start) {
599 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
600 return SECFailure;
601 }
602 i->data += start;
603 i->len -= start;
604 /* we are using indefinite encoding, drop the trailing zero */
605 if (isIndefinite) {
606 if (i->len <= 1) {
607 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
608 return SECFailure;
609 }
610 /* verify tags are zero */
611 if ((i->data[i->len - 1] != 0) || (i->data[i->len - 2] != 0)) {
612 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
613 return SECFailure;
614 }
615 i->len -= 2;
616 }
617
618 return SECSuccess;
619}
620
621/*
622 * Create a new SECItem which points to the current BER tag and length with
623 * all it's data. For indefinite encoding, this will also include the trailing
624 * indefinite markers
625 * The 'in' item is advanced to point to the next BER tag.
626 * You don't want to use this in an actual BER/DER parser as NSS already
627 * has 3 to choose from)
628 */
629SECStatus
630SECU_ExtractBERAndStep(SECItem *in, SECItem *out)
631{
632 if (!in || !in->data || in->len < 2) { /* must be at least tag and length */
633 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
634 return SECFailure;
635 }
636
637 *out = *in;
638
639 /* first handle indefinite encoding */
640 if (out->data[1] == 0x80) {
641 SECItem this = *out;
642 SECItem next;
643 this.data += 2;
644 this.len -= 2;
645 out->len = 2;
646 /* walk through all the entries until we find the '0' */
647 while ((this.len >= 2) && (this.data[0] != 0)) {
648 SECStatus rv = SECU_ExtractBERAndStep(&this, &next);
649 if (rv != SECSuccess) {
650 return rv;
651 }
652 out->len += next.len;
653 }
654 if ((this.len < 2) || ((this.data[0] != 0) && (this.data[1] != 0))) {
655 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
656 return SECFailure;
657 }
658 out->len += 2; /* include the trailing zeros */
659 in->data += out->len;
660 in->len -= out->len;
661 return SECSuccess;
662 }
663
664 /* now handle normal DER encoding */
665 if (out->data[1] & 0x80) {
666 unsigned int i;
667 unsigned int lenlen = out->data[1] & 0x7f;
668 unsigned int len = 0;
669 if (lenlen > sizeof out->len) {
670 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
671 return SECFailure;
672 }
673 for (i = 0; i < lenlen; i++) {
674 len = (len << 8) | out->data[2 + i];
675 }
676 out->len = len + lenlen + 2;
677 } else {
678 out->len = out->data[1] + 2;
679 }
680 if (out->len > in->len) {
681 /* we've ran into a truncated file */
682 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
683 return SECFailure;
684 }
685 in->data += out->len;
686 in->len -= out->len;
687 return SECSuccess;
688}
689
690static void
691secu_PrintRawStringQuotesOptional(FILE *out, SECItem *si, const char *m,
692 int level, PRBool quotes)
693{
694 int column;
695 unsigned int i;
696
697 if (m) {
698 SECU_Indent(out, level);
699 fprintf(out, "%s: ", m);
700 column = (level * INDENT_MULT4) + strlen(m) + 2;
701 level++;
702 } else {
703 SECU_Indent(out, level);
704 column = level * INDENT_MULT4;
705 }
706 if (quotes) {
707 fprintf(out, "\"");
708 column++;
709 }
710
711 for (i = 0; i < si->len; i++) {
712 unsigned char val = si->data[i];
713 unsigned char c;
714 if (SECU_GetWrapEnabled() && column > 76) {
715 SECU_Newline(out);
716 SECU_Indent(out, level);
717 column = level * INDENT_MULT4;
718 }
719
720 if (utf8DisplayEnabled) {
721 if (val < 32)
722 c = '.';
723 else
724 c = val;
725 } else {
726 c = printable[val];
727 }
728 fprintf(out, "%c", c);
729 column++;
730 }
731
732 if (quotes) {
733 fprintf(out, "\"");
734 column++;
735 }
736 if (SECU_GetWrapEnabled() &&
737 (column != level * INDENT_MULT4 || column > 76)) {
738 SECU_Newline(out);
739 }
740}
741
742static void
743secu_PrintRawString(FILE *out, SECItem *si, const char *m, int level)
744{
745 secu_PrintRawStringQuotesOptional(out, si, m, level, PR_TRUE1);
746}
747
748void
749SECU_PrintString(FILE *out, const SECItem *si, const char *m, int level)
750{
751 SECItem my = *si;
752
753 if (SECSuccess != SECU_StripTagAndLength(&my) || !my.len)
754 return;
755 secu_PrintRawString(out, &my, m, level);
756}
757
758/* print an unencoded boolean */
759static void
760secu_PrintBoolean(FILE *out, SECItem *i, const char *m, int level)
761{
762 int val = 0;
763
764 if (i->data && i->len) {
765 val = i->data[0];
766 }
767
768 if (!m) {
769 m = "Boolean";
770 }
771 SECU_Indent(out, level);
772 fprintf(out, "%s: %s\n", m, (val ? "True" : "False"));
773}
774
775/*
776 * Format and print "time". If the tag message "m" is not NULL,
777 * do indent formatting based on "level" and add a newline afterward;
778 * otherwise just print the formatted time string only.
779 */
780static void
781secu_PrintTime(FILE *out, const PRTime time, const char *m, int level)
782{
783 PRExplodedTime printableTime;
784 char *timeString;
785
786 /* Convert to local time */
787 PR_ExplodeTime(time, PR_GMTParameters, &printableTime);
788
789 timeString = PORT_AllocPORT_Alloc_Util(256);
790 if (timeString == NULL((void*)0))
791 return;
792
793 if (m != NULL((void*)0)) {
794 SECU_Indent(out, level);
795 fprintf(out, "%s: ", m);
796 }
797
798 if (PR_FormatTime(timeString, 256, "%a %b %d %H:%M:%S %Y", &printableTime)) {
799 fputs(timeString, out);
800 }
801
802 if (m != NULL((void*)0))
803 fprintf(out, "\n");
804
805 PORT_FreePORT_Free_Util(timeString);
806}
807
808/*
809 * Format and print the UTC Time "t". If the tag message "m" is not NULL,
810 * do indent formatting based on "level" and add a newline afterward;
811 * otherwise just print the formatted time string only.
812 */
813void
814SECU_PrintUTCTime(FILE *out, const SECItem *t, const char *m, int level)
815{
816 PRTime time;
817 SECStatus rv;
818
819 rv = DER_UTCTimeToTimeDER_UTCTimeToTime_Util(&time, t);
820 if (rv != SECSuccess)
821 return;
822
823 secu_PrintTime(out, time, m, level);
824}
825
826/*
827 * Format and print the Generalized Time "t". If the tag message "m"
828 * is not NULL, * do indent formatting based on "level" and add a newline
829 * afterward; otherwise just print the formatted time string only.
830 */
831void
832SECU_PrintGeneralizedTime(FILE *out, const SECItem *t, const char *m, int level)
833{
834 PRTime time;
835 SECStatus rv;
836
837 rv = DER_GeneralizedTimeToTimeDER_GeneralizedTimeToTime_Util(&time, t);
838 if (rv != SECSuccess)
839 return;
840
841 secu_PrintTime(out, time, m, level);
842}
843
844/*
845 * Format and print the UTC or Generalized Time "t". If the tag message
846 * "m" is not NULL, do indent formatting based on "level" and add a newline
847 * afterward; otherwise just print the formatted time string only.
848 */
849void
850SECU_PrintTimeChoice(FILE *out, const SECItem *t, const char *m, int level)
851{
852 switch (t->type) {
853 case siUTCTime:
854 SECU_PrintUTCTime(out, t, m, level);
855 break;
856
857 case siGeneralizedTime:
858 SECU_PrintGeneralizedTime(out, t, m, level);
859 break;
860
861 default:
862 PORT_Assert(0)((0) ? ((void)0) : PR_Assert("0", "/root/firefox-clang/security/nss/cmd/lib/secutil.c"
, 862))
;
863 break;
864 }
865}
866
867/* This prints a SET or SEQUENCE */
868static void
869SECU_PrintSet(FILE *out, const SECItem *t, const char *m, int level)
870{
871 int type = t->data[0] & SEC_ASN1_TAGNUM_MASK0x1f;
872 int constructed = t->data[0] & SEC_ASN1_CONSTRUCTED0x20;
873 const char *label;
874 SECItem my = *t;
875
876 if (!constructed) {
877 SECU_PrintAsHex(out, t, m, level);
878 return;
879 }
880 if (SECSuccess != SECU_StripTagAndLength(&my))
881 return;
882
883 SECU_Indent(out, level);
884 if (m) {
885 fprintf(out, "%s: ", m);
886 }
887
888 if (type == SEC_ASN1_SET0x11)
889 label = "Set ";
890 else if (type == SEC_ASN1_SEQUENCE0x10)
891 label = "Sequence ";
892 else
893 label = "";
894 fprintf(out, "%s{\n", label); /* } */
895
896 while (my.len >= 2) {
897 SECItem tmp;
898 if (SECSuccess != SECU_ExtractBERAndStep(&my, &tmp)) {
899 break;
900 }
901 SECU_PrintAny(out, &tmp, NULL((void*)0), level + 1);
902 }
903 SECU_Indent(out, level);
904 fprintf(out, /* { */ "}\n");
905}
906
907static void
908secu_PrintContextSpecific(FILE *out, const SECItem *i, const char *m, int level)
909{
910 int type = i->data[0] & SEC_ASN1_TAGNUM_MASK0x1f;
911 int constructed = i->data[0] & SEC_ASN1_CONSTRUCTED0x20;
912 SECItem tmp;
913
914 if (constructed) {
915 char *m2;
916 if (!m)
917 m2 = PR_smprintf("[%d]", type);
918 else
919 m2 = PR_smprintf("%s: [%d]", m, type);
920 if (m2) {
921 SECU_PrintSet(out, i, m2, level);
922 PR_smprintf_free(m2);
923 }
924 return;
925 }
926
927 SECU_Indent(out, level);
928 if (m) {
929 fprintf(out, "%s: ", m);
930 }
931 fprintf(out, "[%d]\n", type);
932
933 tmp = *i;
934 if (SECSuccess == SECU_StripTagAndLength(&tmp))
935 SECU_PrintAsHex(out, &tmp, m, level + 1);
936}
937
938static void
939secu_PrintOctetString(FILE *out, const SECItem *i, const char *m, int level)
940{
941 SECItem tmp = *i;
942 if (SECSuccess == SECU_StripTagAndLength(&tmp))
943 SECU_PrintAsHex(out, &tmp, m, level);
944}
945
946static void
947secu_PrintBitString(FILE *out, const SECItem *i, const char *m, int level)
948{
949 int unused_bits;
950 SECItem tmp = *i;
951
952 if (SECSuccess != SECU_StripTagAndLength(&tmp) || tmp.len < 2)
953 return;
954
955 unused_bits = *tmp.data++;
956 tmp.len--;
957
958 SECU_PrintAsHex(out, &tmp, m, level);
959 if (unused_bits) {
960 SECU_Indent(out, level + 1);
961 fprintf(out, "(%d least significant bits unused)\n", unused_bits);
962 }
963}
964
965/* in a decoded bit string, the len member is a bit length. */
966static void
967secu_PrintDecodedBitString(FILE *out, const SECItem *i, const char *m, int level)
968{
969 int unused_bits;
970 SECItem tmp = *i;
971
972 unused_bits = (tmp.len & 0x7) ? 8 - (tmp.len & 7) : 0;
973 DER_ConvertBitString(&tmp){ (&tmp)->len = ((&tmp)->len + 7) >> 3; }; /* convert length to byte length */
974
975 SECU_PrintAsHex(out, &tmp, m, level);
976 if (unused_bits) {
977 SECU_Indent(out, level + 1);
978 fprintf(out, "(%d least significant bits unused)\n", unused_bits);
979 }
980}
981
982/* Print a DER encoded Boolean */
983void
984SECU_PrintEncodedBoolean(FILE *out, const SECItem *i, const char *m, int level)
985{
986 SECItem my = *i;
987 if (SECSuccess == SECU_StripTagAndLength(&my))
988 secu_PrintBoolean(out, &my, m, level);
989}
990
991/* Print a DER encoded integer */
992void
993SECU_PrintEncodedInteger(FILE *out, const SECItem *i, const char *m, int level)
994{
995 SECItem my = *i;
996 if (SECSuccess == SECU_StripTagAndLength(&my))
997 SECU_PrintInteger(out, &my, m, level);
998}
999
1000/* Print a DER encoded OID */
1001SECOidTag
1002SECU_PrintEncodedObjectID(FILE *out, const SECItem *i, const char *m, int level)
1003{
1004 SECItem my = *i;
1005 SECOidTag tag = SEC_OID_UNKNOWN;
1006 if (SECSuccess == SECU_StripTagAndLength(&my))
1007 tag = SECU_PrintObjectID(out, &my, m, level);
1008 return tag;
1009}
1010
1011static void
1012secu_PrintBMPString(FILE *out, const SECItem *i, const char *m, int level)
1013{
1014 unsigned char *s;
1015 unsigned char *d;
1016 int len;
1017 SECItem tmp = { 0, 0, 0 };
1018 SECItem my = *i;
1019
1020 if (SECSuccess != SECU_StripTagAndLength(&my))
1021 goto loser;
1022 if (my.len % 2)
1023 goto loser;
1024 len = (int)(my.len / 2);
1025 tmp.data = (unsigned char *)PORT_AllocPORT_Alloc_Util(len);
1026 if (!tmp.data)
1027 goto loser;
1028 tmp.len = len;
1029 for (s = my.data, d = tmp.data; len > 0; len--) {
1030 PRUint32 bmpChar = (s[0] << 8) | s[1];
1031 s += 2;
1032 if (!isprint(bmpChar)((*__ctype_b_loc ())[(int) ((bmpChar))] & (unsigned short
int) _ISprint)
)
1033 goto loser;
1034 *d++ = (unsigned char)bmpChar;
1035 }
1036 secu_PrintRawString(out, &tmp, m, level);
1037 PORT_FreePORT_Free_Util(tmp.data);
1038 return;
1039
1040loser:
1041 SECU_PrintAsHex(out, i, m, level);
1042 if (tmp.data)
1043 PORT_FreePORT_Free_Util(tmp.data);
1044}
1045
1046static void
1047secu_PrintUniversalString(FILE *out, const SECItem *i, const char *m, int level)
1048{
1049 unsigned char *s;
1050 unsigned char *d;
1051 int len;
1052 SECItem tmp = { 0, 0, 0 };
1053 SECItem my = *i;
1054
1055 if (SECSuccess != SECU_StripTagAndLength(&my))
1056 goto loser;
1057 if (my.len % 4)
1058 goto loser;
1059 len = (int)(my.len / 4);
1060 tmp.data = (unsigned char *)PORT_AllocPORT_Alloc_Util(len);
1061 if (!tmp.data)
1062 goto loser;
1063 tmp.len = len;
1064 for (s = my.data, d = tmp.data; len > 0; len--) {
1065 PRUint32 bmpChar = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
1066 s += 4;
1067 if (!isprint(bmpChar & 0xFF)((*__ctype_b_loc ())[(int) ((bmpChar & 0xFF))] & (unsigned
short int) _ISprint)
)
1068 goto loser;
1069 *d++ = (unsigned char)bmpChar;
1070 }
1071 secu_PrintRawString(out, &tmp, m, level);
1072 PORT_FreePORT_Free_Util(tmp.data);
1073 return;
1074
1075loser:
1076 SECU_PrintAsHex(out, i, m, level);
1077 if (tmp.data)
1078 PORT_FreePORT_Free_Util(tmp.data);
1079}
1080
1081static void
1082secu_PrintUniversal(FILE *out, const SECItem *i, const char *m, int level)
1083{
1084 switch (i->data[0] & SEC_ASN1_TAGNUM_MASK0x1f) {
1085 case SEC_ASN1_ENUMERATED0x0a:
1086 case SEC_ASN1_INTEGER0x02:
1087 SECU_PrintEncodedInteger(out, i, m, level);
1088 break;
1089 case SEC_ASN1_OBJECT_ID0x06:
1090 SECU_PrintEncodedObjectID(out, i, m, level);
1091 break;
1092 case SEC_ASN1_BOOLEAN0x01:
1093 SECU_PrintEncodedBoolean(out, i, m, level);
1094 break;
1095 case SEC_ASN1_UTF8_STRING0x0c:
1096 case SEC_ASN1_PRINTABLE_STRING0x13:
1097 case SEC_ASN1_VISIBLE_STRING0x1a:
1098 case SEC_ASN1_IA5_STRING0x16:
1099 case SEC_ASN1_T61_STRING0x14:
1100 SECU_PrintString(out, i, m, level);
1101 break;
1102 case SEC_ASN1_GENERALIZED_TIME0x18:
1103 SECU_PrintGeneralizedTime(out, i, m, level);
1104 break;
1105 case SEC_ASN1_UTC_TIME0x17:
1106 SECU_PrintUTCTime(out, i, m, level);
1107 break;
1108 case SEC_ASN1_NULL0x05:
1109 SECU_Indent(out, level);
1110 if (m && m[0])
1111 fprintf(out, "%s: NULL\n", m);
1112 else
1113 fprintf(out, "NULL\n");
1114 break;
1115 case SEC_ASN1_SET0x11:
1116 case SEC_ASN1_SEQUENCE0x10:
1117 SECU_PrintSet(out, i, m, level);
1118 break;
1119 case SEC_ASN1_OCTET_STRING0x04:
1120 secu_PrintOctetString(out, i, m, level);
1121 break;
1122 case SEC_ASN1_BIT_STRING0x03:
1123 secu_PrintBitString(out, i, m, level);
1124 break;
1125 case SEC_ASN1_BMP_STRING0x1e:
1126 secu_PrintBMPString(out, i, m, level);
1127 break;
1128 case SEC_ASN1_UNIVERSAL_STRING0x1c:
1129 secu_PrintUniversalString(out, i, m, level);
1130 break;
1131 default:
1132 SECU_PrintAsHex(out, i, m, level);
1133 break;
1134 }
1135}
1136
1137void
1138SECU_PrintAny(FILE *out, const SECItem *i, const char *m, int level)
1139{
1140 if (i && i->len && i->data) {
1141 switch (i->data[0] & SEC_ASN1_CLASS_MASK0xc0) {
1142 case SEC_ASN1_CONTEXT_SPECIFIC0x80:
1143 secu_PrintContextSpecific(out, i, m, level);
1144 break;
1145 case SEC_ASN1_UNIVERSAL0x00:
1146 secu_PrintUniversal(out, i, m, level);
1147 break;
1148 default:
1149 SECU_PrintAsHex(out, i, m, level);
1150 break;
1151 }
1152 }
1153}
1154
1155static int
1156secu_PrintValidity(FILE *out, CERTValidity *v, char *m, int level)
1157{
1158 SECU_Indent(out, level);
1159 fprintf(out, "%s:\n", m);
1160 SECU_PrintTimeChoice(out, &v->notBefore, "Not Before", level + 1);
1161 SECU_PrintTimeChoice(out, &v->notAfter, "Not After ", level + 1);
1162 return 0;
1163}
1164
1165/* This function does NOT expect a DER type and length. */
1166SECOidTag
1167SECU_PrintObjectID(FILE *out, const SECItem *oid, const char *m, int level)
1168{
1169 SECOidData *oiddata;
1170 char *oidString = NULL((void*)0);
1171
1172 oiddata = SECOID_FindOIDSECOID_FindOID_Util(oid);
1173 if (oiddata != NULL((void*)0)) {
1174 const char *name = oiddata->desc;
1175 SECU_Indent(out, level);
1176 if (m != NULL((void*)0))
1177 fprintf(out, "%s: ", m);
1178 fprintf(out, "%s\n", name);
1179 return oiddata->offset;
1180 }
1181 oidString = CERT_GetOidString(oid);
1182 if (oidString) {
1183 SECU_Indent(out, level);
1184 if (m != NULL((void*)0))
1185 fprintf(out, "%s: ", m);
1186 fprintf(out, "%s\n", oidString);
1187 PR_smprintf_free(oidString);
1188 return SEC_OID_UNKNOWN;
1189 }
1190 SECU_PrintAsHex(out, oid, m, level);
1191 return SEC_OID_UNKNOWN;
1192}
1193
1194void
1195SECU_PrintOidTag(FILE *out, SECOidTag tag, const char *m, int level)
1196{
1197 const char *desc = SECOID_FindOIDTagDescriptionSECOID_FindOIDTagDescription_Util(tag);
1198
1199 if (desc == NULL((void*)0)) {
1200 desc = SECOID_FindOIDTagDescriptionSECOID_FindOIDTagDescription_Util(SEC_OID_UNKNOWN);
1201 }
1202 SECU_Indent(out, level);
1203 if (m != NULL((void*)0)) {
1204 fprintf(out, "%s: ", m);
1205 }
1206 fprintf(out, "%s\n", desc);
1207}
1208
1209typedef struct secuPBEParamsStr {
1210 SECItem salt;
1211 SECItem iterationCount;
1212 SECItem keyLength;
1213 SECAlgorithmID cipherAlg;
1214 SECAlgorithmID kdfAlg;
1215} secuPBEParams;
1216
1217SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
1218
1219/* SECOID_PKCS5_PBKDF2 */
1220const SEC_ASN1Template secuKDF2Params[] = {
1221 { SEC_ASN1_SEQUENCE0x10, 0, NULL((void*)0), sizeof(secuPBEParams) },
1222 { SEC_ASN1_OCTET_STRING0x04, offsetof(secuPBEParams, salt)__builtin_offsetof(secuPBEParams, salt) },
1223 { SEC_ASN1_INTEGER0x02, offsetof(secuPBEParams, iterationCount)__builtin_offsetof(secuPBEParams, iterationCount) },
1224 { SEC_ASN1_INTEGER0x02 | SEC_ASN1_OPTIONAL0x00100, offsetof(secuPBEParams, keyLength)__builtin_offsetof(secuPBEParams, keyLength) },
1225 { SEC_ASN1_INLINE0x00800 | SEC_ASN1_XTRN0 | SEC_ASN1_OPTIONAL0x00100, offsetof(secuPBEParams, kdfAlg)__builtin_offsetof(secuPBEParams, kdfAlg),
1226 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate)SECOID_AlgorithmIDTemplate_Util },
1227 { 0 }
1228};
1229
1230/* PKCS5v1 & PKCS12 */
1231const SEC_ASN1Template secuPBEParamsTemp[] = {
1232 { SEC_ASN1_SEQUENCE0x10, 0, NULL((void*)0), sizeof(secuPBEParams) },
1233 { SEC_ASN1_OCTET_STRING0x04, offsetof(secuPBEParams, salt)__builtin_offsetof(secuPBEParams, salt) },
1234 { SEC_ASN1_INTEGER0x02, offsetof(secuPBEParams, iterationCount)__builtin_offsetof(secuPBEParams, iterationCount) },
1235 { 0 }
1236};
1237
1238/* SEC_OID_PKCS5_PBES2, SEC_OID_PKCS5_PBMAC1 */
1239const SEC_ASN1Template secuPBEV2Params[] = {
1240 { SEC_ASN1_SEQUENCE0x10, 0, NULL((void*)0), sizeof(secuPBEParams) },
1241 { SEC_ASN1_INLINE0x00800 | SEC_ASN1_XTRN0, offsetof(secuPBEParams, kdfAlg)__builtin_offsetof(secuPBEParams, kdfAlg),
1242 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate)SECOID_AlgorithmIDTemplate_Util },
1243 { SEC_ASN1_INLINE0x00800 | SEC_ASN1_XTRN0, offsetof(secuPBEParams, cipherAlg)__builtin_offsetof(secuPBEParams, cipherAlg),
1244 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate)SECOID_AlgorithmIDTemplate_Util },
1245 { 0 }
1246};
1247
1248void
1249secu_PrintRSAPSSParams(FILE *out, SECItem *value, char *m, int level)
1250{
1251 PLArenaPool *pool = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
1252 SECStatus rv;
1253 SECKEYRSAPSSParams param;
1254 SECAlgorithmID maskHashAlg;
1255
1256 if (m) {
1257 SECU_Indent(out, level);
1258 fprintf(out, "%s:\n", m);
1259 }
1260
1261 if (!pool) {
1262 SECU_Indent(out, level);
1263 fprintf(out, "Out of memory\n");
1264 return;
1265 }
1266
1267 PORT_Memsetmemset(&param, 0, sizeof param);
1268
1269 rv = SEC_QuickDERDecodeItemSEC_QuickDERDecodeItem_Util(pool, &param,
1270 SEC_ASN1_GET(SECKEY_RSAPSSParamsTemplate)SECKEY_RSAPSSParamsTemplate,
1271 value);
1272 if (rv == SECSuccess) {
1273 if (!param.hashAlg) {
1274 SECU_Indent(out, level + 1);
1275 fprintf(out, "Hash algorithm: default, SHA-1\n");
1276 } else {
1277 SECU_PrintObjectID(out, &param.hashAlg->algorithm,
1278 "Hash algorithm", level + 1);
1279 }
1280 if (!param.maskAlg) {
1281 SECU_Indent(out, level + 1);
1282 fprintf(out, "Mask algorithm: default, MGF1\n");
1283 SECU_Indent(out, level + 1);
1284 fprintf(out, "Mask hash algorithm: default, SHA-1\n");
1285 } else {
1286 SECU_PrintObjectID(out, &param.maskAlg->algorithm,
1287 "Mask algorithm", level + 1);
1288 rv = SEC_QuickDERDecodeItemSEC_QuickDERDecodeItem_Util(pool, &maskHashAlg,
1289 SEC_ASN1_GET(SECOID_AlgorithmIDTemplate)SECOID_AlgorithmIDTemplate_Util,
1290 &param.maskAlg->parameters);
1291 if (rv == SECSuccess) {
1292 SECU_PrintObjectID(out, &maskHashAlg.algorithm,
1293 "Mask hash algorithm", level + 1);
1294 } else {
1295 SECU_Indent(out, level + 1);
1296 fprintf(out, "Invalid mask generation algorithm parameters\n");
1297 }
1298 }
1299 if (!param.saltLength.data) {
1300 SECU_Indent(out, level + 1);
1301 fprintf(out, "Salt length: default, %i (0x%2X)\n", 20, 20);
1302 } else {
1303 SECU_PrintInteger(out, &param.saltLength, "Salt length", level + 1);
1304 }
1305 } else {
1306 SECU_Indent(out, level + 1);
1307 fprintf(out, "Invalid RSA-PSS parameters\n");
1308 }
1309 PORT_FreeArenaPORT_FreeArena_Util(pool, PR_FALSE0);
1310}
1311
1312void
1313secu_PrintKDF2Params(FILE *out, SECItem *value, char *m, int level)
1314{
1315 PLArenaPool *pool = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
1316 SECStatus rv;
1317 secuPBEParams param;
1318
1319 if (m) {
1320 SECU_Indent(out, level);
1321 fprintf(out, "%s:\n", m);
1322 }
1323
1324 if (!pool) {
1325 SECU_Indent(out, level);
1326 fprintf(out, "Out of memory\n");
1327 return;
1328 }
1329
1330 PORT_Memsetmemset(&param, 0, sizeof param);
1331 rv = SEC_QuickDERDecodeItemSEC_QuickDERDecodeItem_Util(pool, &param, secuKDF2Params, value);
1332 if (rv == SECSuccess) {
1333 SECU_PrintAsHex(out, &param.salt, "Salt", level + 1);
1334 SECU_PrintInteger(out, &param.iterationCount, "Iteration Count",
1335 level + 1);
1336 if (param.keyLength.data != NULL((void*)0)) {
1337 SECU_PrintInteger(out, &param.keyLength, "Key Length", level + 1);
1338 }
1339 if (param.kdfAlg.algorithm.data != NULL((void*)0)) {
1340 SECU_PrintAlgorithmID(out, &param.kdfAlg, "KDF algorithm", level + 1);
1341 } else {
1342 SECU_Indent(out, level + 1);
1343 fprintf(out, "Implicit KDF Algorithm: HMAC-SHA-1\n");
1344 }
1345 }
1346 PORT_FreeArenaPORT_FreeArena_Util(pool, PR_FALSE0);
1347}
1348
1349void
1350secu_PrintPKCS5V2Params(FILE *out, SECItem *value, char *m, int level)
1351{
1352 PLArenaPool *pool = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
1353 SECStatus rv;
1354 secuPBEParams param;
1355
1356 if (m) {
1357 SECU_Indent(out, level);
1358 fprintf(out, "%s:\n", m);
1359 }
1360
1361 if (!pool) {
1362 SECU_Indent(out, level);
1363 fprintf(out, "Out of memory\n");
1364 return;
1365 }
1366
1367 PORT_Memsetmemset(&param, 0, sizeof param);
1368 rv = SEC_QuickDERDecodeItemSEC_QuickDERDecodeItem_Util(pool, &param, secuPBEV2Params, value);
1369 if (rv == SECSuccess) {
1370 SECU_PrintAlgorithmID(out, &param.kdfAlg, "KDF", level + 1);
1371 SECU_PrintAlgorithmID(out, &param.cipherAlg, "Cipher", level + 1);
1372 }
1373 PORT_FreeArenaPORT_FreeArena_Util(pool, PR_FALSE0);
1374}
1375
1376void
1377secu_PrintPBEParams(FILE *out, SECItem *value, char *m, int level)
1378{
1379 PLArenaPool *pool = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
1380 SECStatus rv;
1381 secuPBEParams param;
1382
1383 if (m) {
1384 SECU_Indent(out, level);
1385 fprintf(out, "%s:\n", m);
1386 }
1387
1388 if (!pool) {
1389 SECU_Indent(out, level);
1390 fprintf(out, "Out of memory\n");
1391 return;
1392 }
1393
1394 PORT_Memsetmemset(&param, 0, sizeof(secuPBEParams));
1395 rv = SEC_QuickDERDecodeItemSEC_QuickDERDecodeItem_Util(pool, &param, secuPBEParamsTemp, value);
1396 if (rv == SECSuccess) {
1397 SECU_PrintAsHex(out, &param.salt, "Salt", level + 1);
1398 SECU_PrintInteger(out, &param.iterationCount, "Iteration Count",
1399 level + 1);
1400 }
1401 PORT_FreeArenaPORT_FreeArena_Util(pool, PR_FALSE0);
1402}
1403
1404/* This function does NOT expect a DER type and length. */
1405void
1406SECU_PrintAlgorithmID(FILE *out, SECAlgorithmID *a, char *m, int level)
1407{
1408 SECOidTag algtag;
1409 SECU_PrintObjectID(out, &a->algorithm, m, level);
1410
1411 algtag = SECOID_GetAlgorithmTagSECOID_GetAlgorithmTag_Util(a);
1412 if (SEC_PKCS5IsAlgorithmPBEAlgTag(algtag)) {
1413 switch (algtag) {
1414 case SEC_OID_PKCS5_PBKDF2:
1415 secu_PrintKDF2Params(out, &a->parameters, "Parameters", level + 1);
1416 break;
1417 case SEC_OID_PKCS5_PBES2:
1418 secu_PrintPKCS5V2Params(out, &a->parameters, "Encryption", level + 1);
1419 break;
1420 case SEC_OID_PKCS5_PBMAC1:
1421 secu_PrintPKCS5V2Params(out, &a->parameters, "MAC", level + 1);
1422 break;
1423 default:
1424 secu_PrintPBEParams(out, &a->parameters, "Parameters", level + 1);
1425 break;
1426 }
1427 return;
1428 }
1429
1430 if (a->parameters.len == 0 ||
1431 (a->parameters.len == 2 &&
1432 PORT_Memcmpmemcmp(a->parameters.data, "\005\000", 2) == 0)) {
1433 /* No arguments or NULL argument */
1434 } else if (algtag == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
1435 secu_PrintRSAPSSParams(out, &a->parameters, "Parameters", level + 1);
1436 } else {
1437 /* Print args to algorithm */
1438 SECU_PrintAsHex(out, &a->parameters, "Args", level + 1);
1439 }
1440}
1441
1442static void
1443secu_PrintAttribute(FILE *out, SEC_PKCS7Attribute *attr, char *m, int level)
1444{
1445 SECItem *value;
1446 int i;
1447 char om[100];
1448
1449 if (m) {
1450 SECU_Indent(out, level);
1451 fprintf(out, "%s:\n", m);
1452 }
1453
1454 /*
1455 * Should make this smarter; look at the type field and then decode
1456 * and print the value(s) appropriately!
1457 */
1458 SECU_PrintObjectID(out, &(attr->type), "Type", level + 1);
1459 if (attr->values != NULL((void*)0)) {
1460 i = 0;
1461 while ((value = attr->values[i++]) != NULL((void*)0)) {
1462 snprintf(om, sizeof(om), "Value (%d)%s", i, attr->encoded ? " (encoded)" : "");
1463 if (attr->encoded || attr->typeTag == NULL((void*)0)) {
1464 SECU_PrintAny(out, value, om, level + 1);
1465 } else {
1466 switch (attr->typeTag->offset) {
1467 default:
1468 SECU_PrintAsHex(out, value, om, level + 1);
1469 break;
1470 case SEC_OID_PKCS9_CONTENT_TYPE:
1471 SECU_PrintObjectID(out, value, om, level + 1);
1472 break;
1473 case SEC_OID_PKCS9_SIGNING_TIME:
1474 SECU_PrintTimeChoice(out, value, om, level + 1);
1475 break;
1476 }
1477 }
1478 }
1479 }
1480}
1481
1482static void
1483secu_PrintECPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level)
1484{
1485 SECItem curveOID = { siBuffer, NULL((void*)0), 0 };
1486
1487 SECU_Indent(out, level);
1488 fprintf(out, "%s:\n", m);
1489 SECU_PrintInteger(out, &pk->u.ec.publicValue, "PublicValue", level + 1);
1490 /* For named curves, the DEREncodedParams field contains an
1491 * ASN Object ID (0x06 is SEC_ASN1_OBJECT_ID).
1492 */
1493 if ((pk->u.ec.DEREncodedParams.len > 2) &&
1494 (pk->u.ec.DEREncodedParams.data[0] == 0x06)) {
1495 curveOID.len = pk->u.ec.DEREncodedParams.data[1];
1496 curveOID.data = pk->u.ec.DEREncodedParams.data + 2;
1497 curveOID.len = PR_MIN(curveOID.len, pk->u.ec.DEREncodedParams.len - 2)((curveOID.len) < (pk->u.ec.DEREncodedParams.len - 2) ?
(curveOID.len) : (pk->u.ec.DEREncodedParams.len - 2))
;
1498 SECU_PrintObjectID(out, &curveOID, "Curve", level + 1);
1499 }
1500}
1501
1502void
1503SECU_PrintRSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level)
1504{
1505 SECU_Indent(out, level);
1506 fprintf(out, "%s:\n", m);
1507 SECU_PrintInteger(out, &pk->u.rsa.modulus, "Modulus", level + 1);
1508 SECU_PrintInteger(out, &pk->u.rsa.publicExponent, "Exponent", level + 1);
1509 if (pk->u.rsa.publicExponent.len == 1 &&
1510 pk->u.rsa.publicExponent.data[0] == 1) {
1511 SECU_Indent(out, level + 1);
1512 fprintf(out, "Error: INVALID RSA KEY!\n");
1513 }
1514}
1515
1516void
1517SECU_PrintDSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level)
1518{
1519 SECU_Indent(out, level);
1520 fprintf(out, "%s:\n", m);
1521 SECU_PrintInteger(out, &pk->u.dsa.params.prime, "Prime", level + 1);
1522 SECU_PrintInteger(out, &pk->u.dsa.params.subPrime, "Subprime", level + 1);
1523 SECU_PrintInteger(out, &pk->u.dsa.params.base, "Base", level + 1);
1524 SECU_PrintInteger(out, &pk->u.dsa.publicValue, "PublicValue", level + 1);
1525}
1526
1527void
1528SECU_PrintMLDSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level)
1529{
1530
1531 SECU_Indent(out, level);
1532 fprintf(out, "%s:\n", m);
1533
1534 SECU_PrintOidTag(out, pk->u.mldsa.paramSet, "Parameter Set", level + 1);
1535 SECU_PrintInteger(out, &pk->u.mldsa.publicValue, "PublicValue", level + 1);
1536}
1537
1538void
1539SECU_PrintMLKEMPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level)
1540{
1541
1542 SECU_Indent(out, level);
1543 fprintf(out, "%s:\n", m);
1544
1545 switch (pk->u.kyber.params) {
1546 case params_ml_kem512:
1547 SECU_PrintOidTag(out, SEC_OID_ML_KEM_512, "Parameter Set", level + 1);
1548 break;
1549 case params_ml_kem512_test_mode:
1550 SECU_PrintOidTag(out, SEC_OID_ML_KEM_512, "Parameter Set (test mode)",
1551 level + 1);
1552 break;
1553 case params_ml_kem768:
1554 SECU_PrintOidTag(out, SEC_OID_ML_KEM_768, "Parameter Set", level + 1);
1555 break;
1556 case params_ml_kem768_test_mode:
1557 SECU_PrintOidTag(out, SEC_OID_ML_KEM_768, "Parameter Set (test mode)",
1558 level + 1);
1559 break;
1560 case params_ml_kem1024:
1561 SECU_PrintOidTag(out, SEC_OID_ML_KEM_1024, "Parameter Set", level + 1);
1562 break;
1563 case params_ml_kem1024_test_mode:
1564 SECU_PrintOidTag(out, SEC_OID_ML_KEM_1024, "Parameter Set (test mode)",
1565 level + 1);
1566 break;
1567 case params_kyber_invalid:
1568 SECU_Indent(out, level);
1569 fprintf(out, "Parameter Set: Invalid Params\n");
1570 break;
1571 default:
1572 SECU_Indent(out, level);
1573 fprintf(out, "Parameter Set: Invalid Params %d\n", pk->u.kyber.params);
1574 break;
1575 }
1576 SECU_PrintInteger(out, &pk->u.kyber.publicValue, "PublicValue", level + 1);
1577}
1578
1579static void
1580secu_PrintSubjectPublicKeyInfo(FILE *out, PLArenaPool *arena,
1581 CERTSubjectPublicKeyInfo *i, char *msg, int level)
1582{
1583 SECKEYPublicKey *pk;
1584
1585 SECU_Indent(out, level);
1586 fprintf(out, "%s:\n", msg);
1587 SECU_PrintAlgorithmID(out, &i->algorithm, "Public Key Algorithm", level + 1);
1588
1589 pk = SECKEY_ExtractPublicKey(i);
1590 if (pk) {
1591 switch (pk->keyType) {
1592 case rsaKey:
1593 SECU_PrintRSAPublicKey(out, pk, "RSA Public Key", level + 1);
1594 break;
1595
1596 case dsaKey:
1597 SECU_PrintDSAPublicKey(out, pk, "DSA Public Key", level + 1);
1598 break;
1599
1600 case ecKey:
1601 secu_PrintECPublicKey(out, pk, "EC Public Key", level + 1);
1602 break;
1603
1604 case ecMontKey:
1605 secu_PrintECPublicKey(out, pk, "EC Montgomery Public Key", level + 1);
1606 break;
1607
1608 case edKey:
1609 secu_PrintECPublicKey(out, pk, "EC Edwards Public Key", level + 1);
1610 break;
1611
1612 case mldsaKey:
1613 SECU_PrintMLDSAPublicKey(out, pk, "ML-DSA Public Key", level + 1);
1614 break;
1615
1616 case kyberKey:
1617 SECU_PrintMLKEMPublicKey(out, pk, "ML-KEM Public Key", level + 1);
1618 break;
1619
1620 case dhKey:
1621 case fortezzaKey:
1622 case keaKey:
1623 SECU_Indent(out, level);
1624 fprintf(out, "unable to format this SPKI algorithm type\n");
1625 goto loser;
1626 default:
1627 SECU_Indent(out, level);
1628 fprintf(out, "unknown SPKI algorithm type %d\n", pk->keyType);
1629 goto loser;
1630 }
1631 PORT_FreeArenaPORT_FreeArena_Util(pk->arena, PR_FALSE0);
1632 } else {
1633 SECU_PrintErrMsg(out, level, "Error", "Parsing public key");
1634 loser:
1635 if (i->subjectPublicKey.data) {
1636 SECItem tmp = i->subjectPublicKey;
1637 DER_ConvertBitString(&tmp){ (&tmp)->len = ((&tmp)->len + 7) >> 3; };
1638 SECU_PrintAny(out, &tmp, "Raw", level);
1639 }
1640 }
1641}
1642
1643static void
1644printStringWithoutCRLF(FILE *out, const char *str)
1645{
1646 const char *c = str;
1647 while (*c) {
1648 if (*c != '\r' && *c != '\n') {
1649 fputc(*c, out);
1650 }
1651 ++c;
1652 }
1653}
1654
1655int
1656SECU_PrintDumpDerIssuerAndSerial(FILE *out, const SECItem *der, const char *m,
1657 int level)
1658{
1659 PLArenaPool *arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
1660 CERTCertificate *c;
1661 int rv = SEC_ERROR_NO_MEMORY;
1662 char *derIssuerB64;
1663 char *derSerialB64;
1664
1665 if (!arena)
1666 return rv;
1667
1668 /* Decode certificate */
1669 c = PORT_ArenaZNew(arena, CERTCertificate)(CERTCertificate *)PORT_ArenaZAlloc_Util(arena, sizeof(CERTCertificate
))
;
1670 if (!c)
1671 goto loser;
1672 c->arena = arena;
1673 rv = SEC_ASN1DecodeItemSEC_ASN1DecodeItem_Util(arena, c,
1674 SEC_ASN1_GET(CERT_CertificateTemplate)CERT_CertificateTemplate, der);
1675 if (rv) {
1676 SECU_PrintErrMsg(out, 0, "Error", "Parsing extension");
1677 goto loser;
1678 }
1679
1680 SECU_PrintName(out, &c->subject, "Subject", 0);
1681 if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
1682 SECU_Newline(out);
1683 SECU_PrintName(out, &c->issuer, "Issuer", 0);
1684 if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
1685 SECU_Newline(out);
1686 SECU_PrintInteger(out, &c->serialNumber, "Serial Number", 0);
1687
1688 derIssuerB64 = BTOA_ConvertItemToAsciiBTOA_ConvertItemToAscii_Util(&c->derIssuer);
1689 derSerialB64 = BTOA_ConvertItemToAsciiBTOA_ConvertItemToAscii_Util(&c->serialNumber);
1690
1691 fprintf(out, "Issuer DER Base64:\n");
1692 if (SECU_GetWrapEnabled()) {
1693 fprintf(out, "%s\n", derIssuerB64);
1694 } else {
1695 printStringWithoutCRLF(out, derIssuerB64);
1696 fputs("\n", out);
1697 }
1698
1699 fprintf(out, "Serial DER Base64:\n");
1700 if (SECU_GetWrapEnabled()) {
1701 fprintf(out, "%s\n", derSerialB64);
1702 } else {
1703 printStringWithoutCRLF(out, derSerialB64);
1704 fputs("\n", out);
1705 }
1706
1707 PORT_FreePORT_Free_Util(derIssuerB64);
1708 PORT_FreePORT_Free_Util(derSerialB64);
1709
1710 fprintf(out, "Serial DER as C source: \n{ %d, \"", c->serialNumber.len);
1711
1712 {
1713 unsigned int i;
1714 for (i = 0; i < c->serialNumber.len; ++i) {
1715 unsigned char *chardata = (unsigned char *)(c->serialNumber.data);
1716 unsigned char ch = *(chardata + i);
1717
1718 fprintf(out, "\\x%02x", ch);
1719 }
1720 fprintf(out, "\" }\n");
1721 }
1722
1723loser:
1724 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
1725 return rv;
1726}
1727
1728static SECStatus
1729secu_PrintX509InvalidDate(FILE *out, SECItem *value, char *msg, int level)
1730{
1731 SECItem decodedValue;
1732 SECStatus rv;
1733 PRTime invalidTime;
1734 char *formattedTime = NULL((void*)0);
1735
1736 decodedValue.data = NULL((void*)0);
1737 rv = SEC_ASN1DecodeItemSEC_ASN1DecodeItem_Util(NULL((void*)0), &decodedValue,
1738 SEC_ASN1_GET(SEC_GeneralizedTimeTemplate)SEC_GeneralizedTimeTemplate_Util,
1739 value);
1740 if (rv == SECSuccess) {
1741 rv = DER_GeneralizedTimeToTimeDER_GeneralizedTimeToTime_Util(&invalidTime, &decodedValue);
1742 if (rv == SECSuccess) {
1743 formattedTime = CERT_GenTime2FormattedAsciiCERT_GenTime2FormattedAscii_Util(invalidTime, "%a %b %d %H:%M:%S %Y");
1744 SECU_Indent(out, level + 1);
1745 fprintf(out, "%s: %s\n", msg, formattedTime);
1746 PORT_FreePORT_Free_Util(formattedTime);
1747 }
1748 }
1749 PORT_FreePORT_Free_Util(decodedValue.data);
1750 return (rv);
1751}
1752
1753static SECStatus
1754PrintExtKeyUsageExtension(FILE *out, SECItem *value, char *msg, int level)
1755{
1756 CERTOidSequence *os;
1757 SECItem **op;
1758
1759 os = CERT_DecodeOidSequence(value);
1760 if ((CERTOidSequence *)NULL((void*)0) == os) {
1761 return SECFailure;
1762 }
1763
1764 for (op = os->oids; *op; op++) {
1765 SECU_PrintObjectID(out, *op, msg, level + 1);
1766 }
1767 CERT_DestroyOidSequence(os);
1768 return SECSuccess;
1769}
1770
1771static SECStatus
1772secu_PrintBasicConstraints(FILE *out, SECItem *value, char *msg, int level)
1773{
1774 CERTBasicConstraints constraints;
1775 SECStatus rv;
1776
1777 SECU_Indent(out, level);
1778 if (msg) {
1779 fprintf(out, "%s: ", msg);
1780 }
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);
1786 } else {
1787 fprintf(out, "Is a CA with no maximum path length.\n");
1788 }
1789 } else {
1790 fprintf(out, "Is not a CA.\n");
1791 }
1792 return SECSuccess;
1793}
1794
1795static const char *const nsTypeBits[] = {
1796 "SSL Client",
1797 "SSL Server",
1798 "S/MIME",
1799 "Object Signing",
1800 "Reserved",
1801 "SSL CA",
1802 "S/MIME CA",
1803 "ObjectSigning CA"
1804};
1805
1806/* NSCertType is merely a bit string whose bits are displayed symbolically */
1807static SECStatus
1808secu_PrintNSCertType(FILE *out, SECItem *value, char *msg, int level)
1809{
1810 int unused;
1811 int NS_Type;
1812 int i;
1813 int found = 0;
1814 SECItem my = *value;
1815
1816 if ((my.data[0] != SEC_ASN1_BIT_STRING0x03) ||
1817 SECSuccess != SECU_StripTagAndLength(&my)) {
1818 SECU_PrintAny(out, value, "Data", level);
1819 return SECSuccess;
1820 }
1821
1822 unused = (my.len == 2) ? (my.data[0] & 0x0f) : 0;
1823 NS_Type = my.data[1] & (0xff << unused);
1824
1825 SECU_Indent(out, level);
1826 if (msg) {
1827 fprintf(out, "%s: ", msg);
1828 } else {
1829 fprintf(out, "Netscape Certificate Type: ");
1830 }
1831 for (i = 0; i < 8; i++) {
1832 if ((0x80 >> i) & NS_Type) {
1833 fprintf(out, "%c%s", (found ? ',' : '<'), nsTypeBits[i]);
1834 found = 1;
1835 }
1836 }
1837 fprintf(out, (found ? ">\n" : "none\n"));
1838 return SECSuccess;
1839}
1840
1841static const char *const usageBits[] = {
1842 "Digital Signature", /* 0x80 */
1843 "Non-Repudiation", /* 0x40 */
1844 "Key Encipherment", /* 0x20 */
1845 "Data Encipherment", /* 0x10 */
1846 "Key Agreement", /* 0x08 */
1847 "Certificate Signing", /* 0x04 */
1848 "CRL Signing", /* 0x02 */
1849 "Encipher Only", /* 0x01 */
1850 "Decipher Only", /* 0x0080 */
1851 NULL((void*)0)
1852};
1853
1854/* X509KeyUsage is merely a bit string whose bits are displayed symbolically */
1855static void
1856secu_PrintX509KeyUsage(FILE *out, SECItem *value, char *msg, int level)
1857{
1858 int unused;
1859 int usage;
1860 int i;
1861 int found = 0;
1862 SECItem my = *value;
1863
1864 if ((my.data[0] != SEC_ASN1_BIT_STRING0x03) ||
1865 SECSuccess != SECU_StripTagAndLength(&my)) {
1866 SECU_PrintAny(out, value, "Data", level);
1867 return;
1868 }
1869
1870 unused = (my.len >= 2) ? (my.data[0] & 0x0f) : 0;
1871 usage = (my.len == 2) ? (my.data[1] & (0xff << unused)) << 8
1872 : (my.data[1] << 8) |
1873 (my.data[2] & (0xff << unused));
1874
1875 SECU_Indent(out, level);
1876 fprintf(out, "Usages: ");
1877 for (i = 0; usageBits[i]; i++) {
1878 if ((0x8000 >> i) & usage) {
1879 if (found)
1880 SECU_Indent(out, level + 2);
1881 fprintf(out, "%s\n", usageBits[i]);
1882 found = 1;
1883 }
1884 }
1885 if (!found) {
1886 fprintf(out, "(none)\n");
1887 }
1888}
1889
1890static void
1891secu_PrintIPAddress(FILE *out, SECItem *value, char *msg, int level)
1892{
1893 PRStatus st;
1894 PRNetAddr addr;
1895 char addrBuf[80];
1896
1897 memset(&addr, 0, sizeof addr);
1898 if (value->len == 4) {
1899 addr.inet.family = PR_AF_INET2;
1900 memcpy(&addr.inet.ip, value->data, value->len);
1901 } else if (value->len == 16) {
1902 addr.ipv6.family = PR_AF_INET610;
1903 memcpy(addr.ipv6.ip.pr_s6_addr_S6_un._S6_u8, value->data, value->len);
1904 if (PR_IsNetAddrType(&addr, PR_IpAddrV4Mapped)) {
1905 /* convert to IPv4. */
1906 addr.inet.family = PR_AF_INET2;
1907 memcpy(&addr.inet.ip, &addr.ipv6.ip.pr_s6_addr_S6_un._S6_u8[12], 4);
1908 memset(&addr.inet.pad[0], 0, sizeof addr.inet.pad);
1909 }
1910 } else {
1911 goto loser;
1912 }
1913
1914 st = PR_NetAddrToString(&addr, addrBuf, sizeof addrBuf);
1915 if (st == PR_SUCCESS) {
1916 SECU_Indent(out, level);
1917 fprintf(out, "%s: %s\n", msg, addrBuf);
1918 } else {
1919 loser:
1920 SECU_PrintAsHex(out, value, msg, level);
1921 }
1922}
1923
1924static void
1925secu_PrintGeneralName(FILE *out, CERTGeneralName *gname, char *msg, int level)
1926{
1927 char label[40];
1928 if (msg && msg[0]) {
1929 SECU_Indent(out, level++);
1930 fprintf(out, "%s: \n", msg);
1931 }
1932 switch (gname->type) {
1933 case certOtherName:
1934 SECU_PrintAny(out, &gname->name.OthName.name, "Other Name", level);
1935 SECU_PrintObjectID(out, &gname->name.OthName.oid, "OID", level + 1);
1936 break;
1937 case certDirectoryName:
1938 SECU_PrintName(out, &gname->name.directoryName, "Directory Name", level);
1939 break;
1940 case certRFC822Name:
1941 secu_PrintRawString(out, &gname->name.other, "RFC822 Name", level);
1942 break;
1943 case certDNSName:
1944 secu_PrintRawString(out, &gname->name.other, "DNS name", level);
1945 break;
1946 case certURI:
1947 secu_PrintRawString(out, &gname->name.other, "URI", level);
1948 break;
1949 case certIPAddress:
1950 secu_PrintIPAddress(out, &gname->name.other, "IP Address", level);
1951 break;
1952 case certRegisterID:
1953 SECU_PrintObjectID(out, &gname->name.other, "Registered ID", level);
1954 break;
1955 case certX400Address:
1956 SECU_PrintAny(out, &gname->name.other, "X400 Address", level);
1957 break;
1958 case certEDIPartyName:
1959 SECU_PrintAny(out, &gname->name.other, "EDI Party", level);
1960 break;
1961 default:
1962 PR_snprintf(label, sizeof label, "unknown type [%d]",
1963 (int)gname->type - 1);
1964 SECU_PrintAsHex(out, &gname->name.other, label, level);
1965 break;
1966 }
1967}
1968
1969static void
1970secu_PrintGeneralNames(FILE *out, CERTGeneralName *gname, char *msg, int level)
1971{
1972 CERTGeneralName *name = gname;
1973 do {
1974 secu_PrintGeneralName(out, name, msg, level);
1975 name = CERT_GetNextGeneralName(name);
1976 } while (name && name != gname);
1977}
1978
1979static void
1980secu_PrintAuthKeyIDExtension(FILE *out, SECItem *value, char *msg, int level)
1981{
1982 CERTAuthKeyID *kid = NULL((void*)0);
1983 PLArenaPool *pool = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
1984
1985 if (!pool) {
1986 SECU_PrintError("Error", "Allocating new ArenaPool");
1987 return;
1988 }
1989 kid = CERT_DecodeAuthKeyID(pool, value);
1990 if (!kid) {
1991 SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
1992 SECU_PrintAny(out, value, "Data", level);
1993 } else {
1994 int keyIDPresent = (kid->keyID.data && kid->keyID.len);
1995 int issuerPresent = kid->authCertIssuer != NULL((void*)0);
1996 int snPresent = (kid->authCertSerialNumber.data &&
1997 kid->authCertSerialNumber.len);
1998
1999 if (keyIDPresent)
2000 SECU_PrintAsHex(out, &kid->keyID, "Key ID", level);
2001 if (issuerPresent)
2002 secu_PrintGeneralName(out, kid->authCertIssuer, "Issuer", level);
2003 if (snPresent)
2004 SECU_PrintInteger(out, &kid->authCertSerialNumber,
2005 "Serial Number", level);
2006 }
2007 PORT_FreeArenaPORT_FreeArena_Util(pool, PR_FALSE0);
2008}
2009
2010static void
2011secu_PrintAltNameExtension(FILE *out, SECItem *value, char *msg, int level)
2012{
2013 CERTGeneralName *nameList;
2014 CERTGeneralName *current;
2015 PLArenaPool *pool = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
2016
2017 if (!pool) {
2018 SECU_PrintError("Error", "Allocating new ArenaPool");
2019 return;
2020 }
2021 nameList = current = CERT_DecodeAltNameExtension(pool, value);
2022 if (!current) {
2023 if (PORT_GetErrorPORT_GetError_Util() == SEC_ERROR_EXTENSION_NOT_FOUND) {
2024 /* Decoder found empty sequence, which is invalid. */
2025 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_EXTENSION_VALUE_INVALID);
2026 }
2027 SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
2028 SECU_PrintAny(out, value, "Data", level);
2029 } else {
2030 do {
2031 secu_PrintGeneralName(out, current, msg, level);
2032 current = CERT_GetNextGeneralName(current);
2033 } while (current != nameList);
2034 }
2035 PORT_FreeArenaPORT_FreeArena_Util(pool, PR_FALSE0);
2036}
2037
2038static void
2039secu_PrintCRLDistPtsExtension(FILE *out, SECItem *value, char *msg, int level)
2040{
2041 CERTCrlDistributionPoints *dPoints;
2042 PLArenaPool *pool = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
2043
2044 if (!pool) {
2045 SECU_PrintError("Error", "Allocating new ArenaPool");
2046 return;
2047 }
2048 dPoints = CERT_DecodeCRLDistributionPoints(pool, value);
2049 if (dPoints && dPoints->distPoints && dPoints->distPoints[0]) {
2050 CRLDistributionPoint **pPoints = dPoints->distPoints;
2051 CRLDistributionPoint *pPoint;
2052 while (NULL((void*)0) != (pPoint = *pPoints++)) {
2053 SECU_Indent(out, level);
2054 fputs("Distribution point:\n", out);
2055 if (pPoint->distPointType == generalName &&
2056 pPoint->distPoint.fullName != NULL((void*)0)) {
2057 secu_PrintGeneralNames(out, pPoint->distPoint.fullName, NULL((void*)0),
2058 level + 1);
2059 } else if (pPoint->distPointType == relativeDistinguishedName &&
2060 pPoint->distPoint.relativeName.avas) {
2061 SECU_PrintRDN(out, &pPoint->distPoint.relativeName, "RDN",
2062 level + 1);
2063 } else if (pPoint->derDistPoint.data) {
2064 SECU_PrintAny(out, &pPoint->derDistPoint, "Point", level + 1);
2065 }
2066 if (pPoint->reasons.data) {
2067 secu_PrintDecodedBitString(out, &pPoint->reasons, "Reasons",
2068 level + 1);
2069 }
2070 if (pPoint->crlIssuer) {
2071 secu_PrintGeneralName(out, pPoint->crlIssuer, "CRL issuer",
2072 level + 1);
2073 }
2074 }
2075 } else {
2076 SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
2077 SECU_PrintAny(out, value, "Data", level);
2078 }
2079 PORT_FreeArenaPORT_FreeArena_Util(pool, PR_FALSE0);
2080}
2081
2082static void
2083secu_PrintNameConstraintSubtree(FILE *out, CERTNameConstraint *value,
2084 char *msg, int level)
2085{
2086 CERTNameConstraint *head = value;
2087 SECU_Indent(out, level);
2088 fprintf(out, "%s Subtree:\n", msg);
2089 level++;
2090 do {
2091 secu_PrintGeneralName(out, &value->name, NULL((void*)0), level);
2092 if (value->min.data)
2093 SECU_PrintInteger(out, &value->min, "Minimum", level + 1);
2094 if (value->max.data)
2095 SECU_PrintInteger(out, &value->max, "Maximum", level + 1);
2096 value = CERT_GetNextNameConstraint(value);
2097 } while (value != head);
2098}
2099
2100static void
2101secu_PrintNameConstraintsExtension(FILE *out, SECItem *value, char *msg, int level)
2102{
2103 CERTNameConstraints *cnstrnts;
2104 PLArenaPool *pool = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
2105
2106 if (!pool) {
2107 SECU_PrintError("Error", "Allocating new ArenaPool");
2108 return;
2109 }
2110 cnstrnts = CERT_DecodeNameConstraintsExtension(pool, value);
2111 if (!cnstrnts) {
2112 SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
2113 SECU_PrintAny(out, value, "Raw", level);
2114 } else {
2115 if (cnstrnts->permited)
2116 secu_PrintNameConstraintSubtree(out, cnstrnts->permited,
2117 "Permitted", level);
2118 if (cnstrnts->excluded)
2119 secu_PrintNameConstraintSubtree(out, cnstrnts->excluded,
2120 "Excluded", level);
2121 }
2122 PORT_FreeArenaPORT_FreeArena_Util(pool, PR_FALSE0);
2123}
2124
2125static void
2126secu_PrintAuthorityInfoAcess(FILE *out, SECItem *value, char *msg, int level)
2127{
2128 CERTAuthInfoAccess **infos = NULL((void*)0);
2129 PLArenaPool *pool = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
2130
2131 if (!pool) {
2132 SECU_PrintError("Error", "Allocating new ArenaPool");
2133 return;
2134 }
2135 infos = CERT_DecodeAuthInfoAccessExtension(pool, value);
2136 if (!infos) {
2137 SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
2138 SECU_PrintAny(out, value, "Raw", level);
2139 } else {
2140 CERTAuthInfoAccess *info;
2141 while (NULL((void*)0) != (info = *infos++)) {
2142 if (info->method.data) {
2143 SECU_PrintObjectID(out, &info->method, "Method", level);
2144 } else {
2145 SECU_Indent(out, level);
2146 fprintf(out, "Error: missing method\n");
2147 }
2148 if (info->location) {
2149 secu_PrintGeneralName(out, info->location, "Location", level);
2150 } else {
2151 SECU_PrintAny(out, &info->derLocation, "Location", level);
2152 }
2153 }
2154 }
2155 PORT_FreeArenaPORT_FreeArena_Util(pool, PR_FALSE0);
2156}
2157
2158void
2159SECU_PrintExtensions(FILE *out, CERTCertExtension **extensions,
2160 char *msg, int level)
2161{
2162 SECOidTag oidTag;
2163
2164 if (extensions) {
2165 if (msg && *msg) {
2166 SECU_Indent(out, level++);
2167 fprintf(out, "%s:\n", msg);
2168 }
2169
2170 while (*extensions) {
2171 SECItem *tmpitem;
2172
2173 tmpitem = &(*extensions)->id;
2174 SECU_PrintObjectID(out, tmpitem, "Name", level);
2175
2176 tmpitem = &(*extensions)->critical;
2177 if (tmpitem->len) {
2178 secu_PrintBoolean(out, tmpitem, "Critical", level);
2179 }
2180
2181 oidTag = SECOID_FindOIDTagSECOID_FindOIDTag_Util(&((*extensions)->id));
2182 tmpitem = &((*extensions)->value);
2183
2184 switch (oidTag) {
2185 case SEC_OID_X509_INVALID_DATE:
2186 case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_TIME:
2187 secu_PrintX509InvalidDate(out, tmpitem, "Date", level);
2188 break;
2189 case SEC_OID_X509_CERTIFICATE_POLICIES:
2190 SECU_PrintPolicy(out, tmpitem, "Data", level);
2191 break;
2192 case SEC_OID_NS_CERT_EXT_BASE_URL:
2193 case SEC_OID_NS_CERT_EXT_REVOCATION_URL:
2194 case SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL:
2195 case SEC_OID_NS_CERT_EXT_CA_CRL_URL:
2196 case SEC_OID_NS_CERT_EXT_CA_CERT_URL:
2197 case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL:
2198 case SEC_OID_NS_CERT_EXT_CA_POLICY_URL:
2199 case SEC_OID_NS_CERT_EXT_HOMEPAGE_URL:
2200 case SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL:
2201 case SEC_OID_OCSP_RESPONDER:
2202 SECU_PrintString(out, tmpitem, "URL", level);
2203 break;
2204 case SEC_OID_NS_CERT_EXT_COMMENT:
2205 SECU_PrintString(out, tmpitem, "Comment", level);
2206 break;
2207 case SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME:
2208 SECU_PrintString(out, tmpitem, "ServerName", level);
2209 break;
2210 case SEC_OID_NS_CERT_EXT_CERT_TYPE:
2211 secu_PrintNSCertType(out, tmpitem, "Data", level);
2212 break;
2213 case SEC_OID_X509_BASIC_CONSTRAINTS:
2214 secu_PrintBasicConstraints(out, tmpitem, "Data", level);
2215 break;
2216 case SEC_OID_X509_EXT_KEY_USAGE:
2217 PrintExtKeyUsageExtension(out, tmpitem, NULL((void*)0), level);
2218 break;
2219 case SEC_OID_X509_KEY_USAGE:
2220 secu_PrintX509KeyUsage(out, tmpitem, NULL((void*)0), level);
2221 break;
2222 case SEC_OID_X509_AUTH_KEY_ID:
2223 secu_PrintAuthKeyIDExtension(out, tmpitem, NULL((void*)0), level);
2224 break;
2225 case SEC_OID_X509_SUBJECT_ALT_NAME:
2226 case SEC_OID_X509_ISSUER_ALT_NAME:
2227 secu_PrintAltNameExtension(out, tmpitem, NULL((void*)0), level);
2228 break;
2229 case SEC_OID_X509_CRL_DIST_POINTS:
2230 secu_PrintCRLDistPtsExtension(out, tmpitem, NULL((void*)0), level);
2231 break;
2232 case SEC_OID_X509_PRIVATE_KEY_USAGE_PERIOD:
2233 SECU_PrintPrivKeyUsagePeriodExtension(out, tmpitem, NULL((void*)0),
2234 level);
2235 break;
2236 case SEC_OID_X509_NAME_CONSTRAINTS:
2237 secu_PrintNameConstraintsExtension(out, tmpitem, NULL((void*)0), level);
2238 break;
2239 case SEC_OID_X509_AUTH_INFO_ACCESS:
2240 secu_PrintAuthorityInfoAcess(out, tmpitem, NULL((void*)0), level);
2241 break;
2242
2243 case SEC_OID_X509_CRL_NUMBER:
2244 case SEC_OID_X509_REASON_CODE:
2245
2246 /* PKIX OIDs */
2247 case SEC_OID_PKIX_OCSP:
2248 case SEC_OID_PKIX_OCSP_BASIC_RESPONSE:
2249 case SEC_OID_PKIX_OCSP_NONCE:
2250 case SEC_OID_PKIX_OCSP_CRL:
2251 case SEC_OID_PKIX_OCSP_RESPONSE:
2252 case SEC_OID_PKIX_OCSP_NO_CHECK:
2253 case SEC_OID_PKIX_OCSP_ARCHIVE_CUTOFF:
2254 case SEC_OID_PKIX_OCSP_SERVICE_LOCATOR:
2255 case SEC_OID_PKIX_REGCTRL_REGTOKEN:
2256 case SEC_OID_PKIX_REGCTRL_AUTHENTICATOR:
2257 case SEC_OID_PKIX_REGCTRL_PKIPUBINFO:
2258 case SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS:
2259 case SEC_OID_PKIX_REGCTRL_OLD_CERT_ID:
2260 case SEC_OID_PKIX_REGCTRL_PROTOCOL_ENC_KEY:
2261 case SEC_OID_PKIX_REGINFO_UTF8_PAIRS:
2262 case SEC_OID_PKIX_REGINFO_CERT_REQUEST:
2263
2264 /* Netscape extension OIDs. */
2265 case SEC_OID_NS_CERT_EXT_NETSCAPE_OK:
2266 case SEC_OID_NS_CERT_EXT_ISSUER_LOGO:
2267 case SEC_OID_NS_CERT_EXT_SUBJECT_LOGO:
2268 case SEC_OID_NS_CERT_EXT_ENTITY_LOGO:
2269 case SEC_OID_NS_CERT_EXT_USER_PICTURE:
2270
2271 /* x.509 v3 Extensions */
2272 case SEC_OID_X509_SUBJECT_DIRECTORY_ATTR:
2273 case SEC_OID_X509_SUBJECT_KEY_ID:
2274 case SEC_OID_X509_POLICY_MAPPINGS:
2275 case SEC_OID_X509_POLICY_CONSTRAINTS:
2276
2277 default:
2278 SECU_PrintAny(out, tmpitem, "Data", level);
2279 break;
2280 }
2281
2282 SECU_Newline(out);
2283 extensions++;
2284 }
2285 }
2286}
2287
2288/* An RDN is a subset of a DirectoryName, and we already know how to
2289 * print those, so make a directory name out of the RDN, and print it.
2290 */
2291void
2292SECU_PrintRDN(FILE *out, CERTRDN *rdn, const char *msg, int level)
2293{
2294 CERTName name;
2295 CERTRDN *rdns[2];
2296
2297 name.arena = NULL((void*)0);
2298 name.rdns = rdns;
2299 rdns[0] = rdn;
2300 rdns[1] = NULL((void*)0);
2301 SECU_PrintName(out, &name, msg, level);
2302}
2303
2304void
2305SECU_PrintNameQuotesOptional(FILE *out, CERTName *name, const char *msg,
2306 int level, PRBool quotes)
2307{
2308 char *nameStr = NULL((void*)0);
2309 char *str;
2310 SECItem my;
2311
2312 if (!name) {
2313 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
2314 return;
2315 }
2316 if (!name->rdns || !name->rdns[0]) {
2317 str = "(empty)";
2318 } else {
2319 str = nameStr = CERT_NameToAscii(name);
2320 }
2321 if (!str) {
2322 str = "!Invalid AVA!";
2323 }
2324 my.data = (unsigned char *)str;
2325 my.len = PORT_Strlen(str)strlen(str);
2326#if 1
2327 secu_PrintRawStringQuotesOptional(out, &my, msg, level, quotes);
2328#else
2329 SECU_Indent(out, level);
2330 fprintf(out, "%s: ", msg);
2331 fprintf(out, str);
2332 SECU_Newline(out);
2333#endif
2334 PORT_FreePORT_Free_Util(nameStr);
2335}
2336
2337void
2338SECU_PrintName(FILE *out, CERTName *name, const char *msg, int level)
2339{
2340 SECU_PrintNameQuotesOptional(out, name, msg, level, PR_TRUE1);
2341}
2342
2343void
2344printflags(char *trusts, unsigned int flags)
2345{
2346 if (flags & CERTDB_VALID_CA(1u << 3))
2347 if (!(flags & CERTDB_TRUSTED_CA(1u << 4)) &&
2348 !(flags & CERTDB_TRUSTED_CLIENT_CA(1u << 7)))
2349 PORT_Strcatstrcat(trusts, "c");
2350 if (flags & CERTDB_TERMINAL_RECORD(1u << 0))
2351 if (!(flags & CERTDB_TRUSTED(1u << 1)))
2352 PORT_Strcatstrcat(trusts, "p");
2353 if (flags & CERTDB_TRUSTED_CA(1u << 4))
2354 PORT_Strcatstrcat(trusts, "C");
2355 if (flags & CERTDB_TRUSTED_CLIENT_CA(1u << 7))
2356 PORT_Strcatstrcat(trusts, "T");
2357 if (flags & CERTDB_TRUSTED(1u << 1))
2358 PORT_Strcatstrcat(trusts, "P");
2359 if (flags & CERTDB_USER(1u << 6))
2360 PORT_Strcatstrcat(trusts, "u");
2361 if (flags & CERTDB_SEND_WARN(1u << 2))
2362 PORT_Strcatstrcat(trusts, "w");
2363 if (flags & CERTDB_INVISIBLE_CA(1u << 8))
2364 PORT_Strcatstrcat(trusts, "I");
2365 if (flags & CERTDB_GOVT_APPROVED_CA(1u << 9))
2366 PORT_Strcatstrcat(trusts, "G");
2367 return;
2368}
2369
2370/* callback for listing certs through pkcs11 */
2371SECStatus
2372SECU_PrintCertNickname(CERTCertListNode *node, void *data)
2373{
2374 CERTCertTrust trust;
2375 CERTCertificate *cert;
2376 FILE *out;
2377 char trusts[30];
2378 char *name;
2379
2380 cert = node->cert;
2381
2382 PORT_Memsetmemset(trusts, 0, sizeof(trusts));
2383 out = (FILE *)data;
2384
2385 name = node->appData;
2386 if (!name || !name[0]) {
2387 name = cert->nickname;
2388 }
2389 if (!name || !name[0]) {
2390 name = cert->emailAddr;
2391 }
2392 if (!name || !name[0]) {
2393 name = "(NULL)";
2394 }
2395
2396 if (CERT_GetCertTrust(cert, &trust) == SECSuccess) {
2397 printflags(trusts, trust.sslFlags);
2398 PORT_Strcatstrcat(trusts, ",");
2399 printflags(trusts, trust.emailFlags);
2400 PORT_Strcatstrcat(trusts, ",");
2401 printflags(trusts, trust.objectSigningFlags);
2402 } else {
2403 PORT_Memcpymemcpy(trusts, ",,", 3);
2404 }
2405 fprintf(out, "%-60s %-5s\n", name, trusts);
2406
2407 return (SECSuccess);
2408}
2409
2410int
2411SECU_DecodeAndPrintExtensions(FILE *out, SECItem *any, char *m, int level)
2412{
2413 CERTCertExtension **extensions = NULL((void*)0);
2414 PLArenaPool *arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
2415 int rv = 0;
2416
2417 if (!arena)
2418 return SEC_ERROR_NO_MEMORY;
2419
2420 rv = SEC_QuickDERDecodeItemSEC_QuickDERDecodeItem_Util(arena, &extensions,
2421 SEC_ASN1_GET(CERT_SequenceOfCertExtensionTemplate)CERT_SequenceOfCertExtensionTemplate, any);
2422 if (!rv)
2423 SECU_PrintExtensions(out, extensions, m, level);
2424 else
2425 SECU_PrintAny(out, any, m, level);
2426 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
2427 return rv;
2428}
2429
2430/* print a decoded SET OF or SEQUENCE OF Extensions */
2431int
2432SECU_PrintSetOfExtensions(FILE *out, SECItem **any, char *m, int level)
2433{
2434 int rv = 0;
2435 if (m && *m) {
2436 SECU_Indent(out, level++);
2437 fprintf(out, "%s:\n", m);
2438 }
2439 while (any && any[0]) {
2440 rv |= SECU_DecodeAndPrintExtensions(out, any[0], "", level);
2441 any++;
2442 }
2443 return rv;
2444}
2445
2446/* print a decoded SET OF or SEQUENCE OF "ANY" */
2447int
2448SECU_PrintSetOfAny(FILE *out, SECItem **any, char *m, int level)
2449{
2450 int rv = 0;
2451 if (m && *m) {
2452 SECU_Indent(out, level++);
2453 fprintf(out, "%s:\n", m);
2454 }
2455 while (any && any[0]) {
2456 SECU_PrintAny(out, any[0], "", level);
2457 any++;
2458 }
2459 return rv;
2460}
2461
2462int
2463SECU_PrintCertAttribute(FILE *out, CERTAttribute *attr, char *m, int level)
2464{
2465 int rv = 0;
2466 SECOidTag tag;
2467 tag = SECU_PrintObjectID(out, &attr->attrType, "Attribute Type", level);
2468 if (tag == SEC_OID_PKCS9_EXTENSION_REQUEST) {
2469 rv = SECU_PrintSetOfExtensions(out, attr->attrValue, "Extensions", level);
2470 } else {
2471 rv = SECU_PrintSetOfAny(out, attr->attrValue, "Attribute Values", level);
2472 }
2473 return rv;
2474}
2475
2476int
2477SECU_PrintCertAttributes(FILE *out, CERTAttribute **attrs, char *m, int level)
2478{
2479 int rv = 0;
2480 while (attrs[0]) {
2481 rv |= SECU_PrintCertAttribute(out, attrs[0], m, level + 1);
2482 attrs++;
2483 }
2484 return rv;
2485}
2486
2487/* sometimes a PRErrorCode, other times a SECStatus. Sigh. */
2488int
2489SECU_PrintCertificateRequest(FILE *out, const SECItem *der, const char *m, int level)
2490{
2491 PLArenaPool *arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
2492 CERTCertificateRequest *cr;
2493 int rv = SEC_ERROR_NO_MEMORY;
2494
2495 if (!arena)
2496 return rv;
2497
2498 /* Decode certificate request */
2499 cr = PORT_ArenaZNew(arena, CERTCertificateRequest)(CERTCertificateRequest *)PORT_ArenaZAlloc_Util(arena, sizeof
(CERTCertificateRequest))
;
2500 if (!cr)
2501 goto loser;
2502 cr->arena = arena;
2503 rv = SEC_QuickDERDecodeItemSEC_QuickDERDecodeItem_Util(arena, cr,
2504 SEC_ASN1_GET(CERT_CertificateRequestTemplate)CERT_CertificateRequestTemplate, der);
2505 if (rv)
2506 goto loser;
2507
2508 /* Pretty print it out */
2509 SECU_Indent(out, level);
2510 fprintf(out, "%s:\n", m);
2511 SECU_PrintInteger(out, &cr->version, "Version", level + 1);
2512 SECU_PrintName(out, &cr->subject, "Subject", level + 1);
2513 if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
2514 SECU_Newline(out);
2515 secu_PrintSubjectPublicKeyInfo(out, arena, &cr->subjectPublicKeyInfo,
2516 "Subject Public Key Info", level + 1);
2517 if (cr->attributes)
2518 SECU_PrintCertAttributes(out, cr->attributes, "Attributes", level + 1);
2519 rv = 0;
2520loser:
2521 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
2522 return rv;
2523}
2524
2525int
2526SECU_PrintCertificate(FILE *out, const SECItem *der, const char *m, int level)
2527{
2528 PLArenaPool *arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
2529 CERTCertificate *c;
2530 int rv = SEC_ERROR_NO_MEMORY;
2531 int iv;
2532
2533 if (!arena)
2534 return rv;
2535
2536 /* Decode certificate */
2537 c = PORT_ArenaZNew(arena, CERTCertificate)(CERTCertificate *)PORT_ArenaZAlloc_Util(arena, sizeof(CERTCertificate
))
;
2538 if (!c)
2539 goto loser;
2540 c->arena = arena;
2541 rv = SEC_ASN1DecodeItemSEC_ASN1DecodeItem_Util(arena, c,
2542 SEC_ASN1_GET(CERT_CertificateTemplate)CERT_CertificateTemplate, der);
2543 if (rv) {
2544 SECU_Indent(out, level);
2545 SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
2546 SECU_PrintAny(out, der, "Raw", level);
2547 goto loser;
2548 }
2549 /* Pretty print it out */
2550 SECU_Indent(out, level);
2551 fprintf(out, "%s:\n", m);
2552 iv = c->version.len ? DER_GetIntegerDER_GetInteger_Util(&c->version) : 0; /* version is optional */
2553 SECU_Indent(out, level + 1);
2554 fprintf(out, "%s: %d (0x%x)\n", "Version", iv + 1, iv);
2555
2556 SECU_PrintInteger(out, &c->serialNumber, "Serial Number", level + 1);
2557 SECU_PrintAlgorithmID(out, &c->signature, "Signature Algorithm", level + 1);
2558 SECU_PrintName(out, &c->issuer, "Issuer", level + 1);
2559 if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
2560 SECU_Newline(out);
2561 secu_PrintValidity(out, &c->validity, "Validity", level + 1);
2562 SECU_PrintName(out, &c->subject, "Subject", level + 1);
2563 if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
2564 SECU_Newline(out);
2565 secu_PrintSubjectPublicKeyInfo(out, arena, &c->subjectPublicKeyInfo,
2566 "Subject Public Key Info", level + 1);
2567 if (c->issuerID.data)
2568 secu_PrintDecodedBitString(out, &c->issuerID, "Issuer Unique ID", level + 1);
2569 if (c->subjectID.data)
2570 secu_PrintDecodedBitString(out, &c->subjectID, "Subject Unique ID", level + 1);
2571 SECU_PrintExtensions(out, c->extensions, "Signed Extensions", level + 1);
2572loser:
2573 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
2574 return rv;
2575}
2576
2577int
2578SECU_PrintCertificateBasicInfo(FILE *out, const SECItem *der, const char *m, int level)
2579{
2580 PLArenaPool *arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
2581 CERTCertificate *c;
2582 int rv = SEC_ERROR_NO_MEMORY;
2583
2584 if (!arena)
2585 return rv;
2586
2587 /* Decode certificate */
2588 c = PORT_ArenaZNew(arena, CERTCertificate)(CERTCertificate *)PORT_ArenaZAlloc_Util(arena, sizeof(CERTCertificate
))
;
2589 if (!c)
2590 goto loser;
2591 c->arena = arena;
2592 rv = SEC_ASN1DecodeItemSEC_ASN1DecodeItem_Util(arena, c,
2593 SEC_ASN1_GET(CERT_CertificateTemplate)CERT_CertificateTemplate, der);
2594 if (rv) {
2595 SECU_Indent(out, level);
2596 SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
2597 SECU_PrintAny(out, der, "Raw", level);
2598 goto loser;
2599 }
2600 /* Pretty print it out */
2601 SECU_Indent(out, level);
2602 fprintf(out, "%s:\n", m);
2603 SECU_PrintInteger(out, &c->serialNumber, "Serial Number", level + 1);
2604 SECU_PrintAlgorithmID(out, &c->signature, "Signature Algorithm", level + 1);
2605 SECU_PrintName(out, &c->issuer, "Issuer", level + 1);
2606 if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
2607 SECU_Newline(out);
2608 secu_PrintValidity(out, &c->validity, "Validity", level + 1);
2609 SECU_PrintName(out, &c->subject, "Subject", level + 1);
2610 if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
2611 SECU_Newline(out);
2612loser:
2613 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
2614 return rv;
2615}
2616
2617int
2618SECU_PrintSubjectPublicKeyInfo(FILE *out, SECItem *der, char *m, int level)
2619{
2620 PLArenaPool *arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
2621 int rv = SEC_ERROR_NO_MEMORY;
2622 CERTSubjectPublicKeyInfo spki;
2623
2624 if (!arena)
2625 return rv;
2626
2627 PORT_Memsetmemset(&spki, 0, sizeof spki);
2628 rv = SEC_ASN1DecodeItemSEC_ASN1DecodeItem_Util(arena, &spki,
2629 SEC_ASN1_GET(CERT_SubjectPublicKeyInfoTemplate)CERT_SubjectPublicKeyInfoTemplate,
2630 der);
2631 if (!rv) {
2632 if (m && *m) {
2633 SECU_Indent(out, level);
2634 fprintf(out, "%s:\n", m);
2635 }
2636 secu_PrintSubjectPublicKeyInfo(out, arena, &spki,
2637 "Subject Public Key Info", level + 1);
2638 }
2639
2640 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
2641 return rv;
2642}
2643
2644int
2645SECU_PrintPrivateKey(FILE *out, SECItem *der, char *m, int level)
2646{
2647 PLArenaPool *arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
2648 SECKEYEncryptedPrivateKeyInfo key;
2649 int rv = SEC_ERROR_NO_MEMORY;
2650
2651 if (!arena)
2652 return rv;
2653
2654 PORT_Memsetmemset(&key, 0, sizeof(key));
2655 rv = SEC_ASN1DecodeItemSEC_ASN1DecodeItem_Util(arena, &key,
2656 SEC_ASN1_GET(SECKEY_EncryptedPrivateKeyInfoTemplate)SECKEY_EncryptedPrivateKeyInfoTemplate, der);
2657 if (rv)
2658 goto loser;
2659
2660 /* Pretty print it out */
2661 SECU_Indent(out, level);
2662 fprintf(out, "%s:\n", m);
2663 SECU_PrintAlgorithmID(out, &key.algorithm, "Encryption Algorithm",
2664 level + 1);
2665 SECU_PrintAsHex(out, &key.encryptedData, "Encrypted Data", level + 1);
2666loser:
2667 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_TRUE1);
2668 return rv;
2669}
2670
2671int
2672SECU_PrintFingerprints(FILE *out, SECItem *derCert, char *m, int level)
2673{
2674 unsigned char fingerprint[SHA256_LENGTH32];
2675 char *fpStr = NULL((void*)0);
2676 int err = PORT_GetErrorPORT_GetError_Util();
2677 SECStatus rv;
2678 SECItem fpItem;
2679
2680 /* Print SHA-256 fingerprint */
2681 memset(fingerprint, 0, sizeof fingerprint);
2682 rv = PK11_HashBuf(SEC_OID_SHA256, fingerprint, derCert->data, derCert->len);
2683 fpItem.data = fingerprint;
2684 fpItem.len = SHA256_LENGTH32;
2685 fpStr = CERT_Hexify(&fpItem, 1);
2686 SECU_Indent(out, level);
2687 fprintf(out, "%s (SHA-256):", m);
2688 if (SECU_GetWrapEnabled()) {
2689 fprintf(out, "\n");
2690 SECU_Indent(out, level + 1);
2691 } else {
2692 fprintf(out, " ");
2693 }
2694 fprintf(out, "%s\n", fpStr);
2695 PORT_FreePORT_Free_Util(fpStr);
2696 fpStr = NULL((void*)0);
2697 if (rv != SECSuccess && !err)
2698 err = PORT_GetErrorPORT_GetError_Util();
2699
2700 /* print SHA1 fingerprint */
2701 memset(fingerprint, 0, sizeof fingerprint);
2702 rv = PK11_HashBuf(SEC_OID_SHA1, fingerprint, derCert->data, derCert->len);
2703 fpItem.data = fingerprint;
2704 fpItem.len = SHA1_LENGTH20;
2705 fpStr = CERT_Hexify(&fpItem, 1);
2706 SECU_Indent(out, level);
2707 fprintf(out, "%s (SHA1):", m);
2708 if (SECU_GetWrapEnabled()) {
2709 fprintf(out, "\n");
2710 SECU_Indent(out, level + 1);
2711 } else {
2712 fprintf(out, " ");
2713 }
2714 fprintf(out, "%s\n", fpStr);
2715 PORT_FreePORT_Free_Util(fpStr);
2716 if (SECU_GetWrapEnabled())
2717 fprintf(out, "\n");
2718
2719 if (err)
2720 PORT_SetErrorPORT_SetError_Util(err);
2721 if (err || rv != SECSuccess)
2722 return SECFailure;
2723
2724 return 0;
2725}
2726
2727/*
2728** PKCS7 Support
2729*/
2730
2731/* forward declaration */
2732typedef enum {
2733 secuPKCS7Unknown = 0,
2734 secuPKCS7PKCS12AuthSafe,
2735 secuPKCS7PKCS12Safe
2736} secuPKCS7State;
2737
2738static int
2739secu_PrintPKCS7ContentInfo(FILE *, SEC_PKCS7ContentInfo *, secuPKCS7State,
2740 const char *, int);
2741static int
2742secu_PrintDERPKCS7ContentInfo(FILE *, SECItem *, secuPKCS7State,
2743 const char *, int);
2744
2745/*
2746** secu_PrintPKCS7EncContent
2747** Prints a SEC_PKCS7EncryptedContentInfo (without decrypting it)
2748*/
2749static int
2750secu_PrintPKCS7EncContent(FILE *out, SEC_PKCS7EncryptedContentInfo *src,
2751 secuPKCS7State state, const char *m, int level)
2752{
2753 if (src->contentTypeTag == NULL((void*)0))
2754 src->contentTypeTag = SECOID_FindOIDSECOID_FindOID_Util(&(src->contentType));
2755
2756 SECU_Indent(out, level);
2757 fprintf(out, "%s:\n", m);
2758 SECU_Indent(out, level + 1);
2759 fprintf(out, "Content Type: %s\n",
2760 (src->contentTypeTag != NULL((void*)0)) ? src->contentTypeTag->desc
2761 : "Unknown");
2762 SECU_PrintAlgorithmID(out, &(src->contentEncAlg),
2763 "Content Encryption Algorithm", level + 1);
2764 SECU_PrintAsHex(out, &(src->encContent),
2765 "Encrypted Content", level + 1);
2766 return 0;
2767}
2768
2769/*
2770** secu_PrintRecipientInfo
2771** Prints a PKCS7RecipientInfo type
2772*/
2773static void
2774secu_PrintRecipientInfo(FILE *out, SEC_PKCS7RecipientInfo *info,
2775 const char *m, int level)
2776{
2777 SECU_Indent(out, level);
2778 fprintf(out, "%s:\n", m);
2779 SECU_PrintInteger(out, &(info->version), "Version", level + 1);
2780
2781 SECU_PrintName(out, &(info->issuerAndSN->issuer), "Issuer",
2782 level + 1);
2783 SECU_PrintInteger(out, &(info->issuerAndSN->serialNumber),
2784 "Serial Number", level + 1);
2785
2786 /* Parse and display encrypted key */
2787 SECU_PrintAlgorithmID(out, &(info->keyEncAlg),
2788 "Key Encryption Algorithm", level + 1);
2789 SECU_PrintAsHex(out, &(info->encKey), "Encrypted Key", level + 1);
2790}
2791
2792/*
2793** secu_PrintSignerInfo
2794** Prints a PKCS7SingerInfo type
2795*/
2796static void
2797secu_PrintSignerInfo(FILE *out, SEC_PKCS7SignerInfo *info,
2798 const char *m, int level)
2799{
2800 SEC_PKCS7Attribute *attr;
2801 int iv;
2802 char om[100];
2803
2804 SECU_Indent(out, level);
2805 fprintf(out, "%s:\n", m);
2806 SECU_PrintInteger(out, &(info->version), "Version", level + 1);
2807
2808 SECU_PrintName(out, &(info->issuerAndSN->issuer), "Issuer",
2809 level + 1);
2810 SECU_PrintInteger(out, &(info->issuerAndSN->serialNumber),
2811 "Serial Number", level + 1);
2812
2813 SECU_PrintAlgorithmID(out, &(info->digestAlg), "Digest Algorithm",
2814 level + 1);
2815
2816 if (info->authAttr != NULL((void*)0)) {
2817 SECU_Indent(out, level + 1);
2818 fprintf(out, "Authenticated Attributes:\n");
2819 iv = 0;
2820 while ((attr = info->authAttr[iv++]) != NULL((void*)0)) {
2821 snprintf(om, sizeof(om), "Attribute (%d)", iv);
2822 secu_PrintAttribute(out, attr, om, level + 2);
2823 }
2824 }
2825
2826 /* Parse and display signature */
2827 SECU_PrintAlgorithmID(out, &(info->digestEncAlg),
2828 "Digest Encryption Algorithm", level + 1);
2829 SECU_PrintAsHex(out, &(info->encDigest), "Encrypted Digest", level + 1);
2830
2831 if (info->unAuthAttr != NULL((void*)0)) {
2832 SECU_Indent(out, level + 1);
2833 fprintf(out, "Unauthenticated Attributes:\n");
2834 iv = 0;
2835 while ((attr = info->unAuthAttr[iv++]) != NULL((void*)0)) {
2836 snprintf(om, sizeof(om), "Attribute (%x)", iv);
2837 secu_PrintAttribute(out, attr, om, level + 2);
2838 }
2839 }
2840}
2841
2842/* callers of this function must make sure that the CERTSignedCrl
2843 from which they are extracting the CERTCrl has been fully-decoded.
2844 Otherwise it will not have the entries even though the CRL may have
2845 some */
2846
2847void
2848SECU_PrintCRLInfo(FILE *out, CERTCrl *crl, const char *m, int level)
2849{
2850 CERTCrlEntry *entry;
2851 int iv;
2852 char om[100];
2853
2854 SECU_Indent(out, level);
2855 fprintf(out, "%s:\n", m);
2856 /* version is optional */
2857 iv = crl->version.len ? DER_GetIntegerDER_GetInteger_Util(&crl->version) : 0;
2858 SECU_Indent(out, level + 1);
2859 fprintf(out, "%s: %d (0x%x)\n", "Version", iv + 1, iv);
2860 SECU_PrintAlgorithmID(out, &(crl->signatureAlg), "Signature Algorithm",
2861 level + 1);
2862 SECU_PrintName(out, &(crl->name), "Issuer", level + 1);
2863 SECU_PrintTimeChoice(out, &(crl->lastUpdate), "This Update", level + 1);
2864 if (crl->nextUpdate.data && crl->nextUpdate.len) /* is optional */
2865 SECU_PrintTimeChoice(out, &(crl->nextUpdate), "Next Update", level + 1);
2866
2867 if (crl->entries != NULL((void*)0)) {
2868 iv = 0;
2869 while ((entry = crl->entries[iv++]) != NULL((void*)0)) {
2870 snprintf(om, sizeof(om), "Entry %d (0x%x):\n", iv, iv);
2871 SECU_Indent(out, level + 1);
2872 fputs(om, out);
2873 SECU_PrintInteger(out, &(entry->serialNumber), "Serial Number",
2874 level + 2);
2875 SECU_PrintTimeChoice(out, &(entry->revocationDate),
2876 "Revocation Date", level + 2);
2877 SECU_PrintExtensions(out, entry->extensions,
2878 "Entry Extensions", level + 2);
2879 }
2880 }
2881 SECU_PrintExtensions(out, crl->extensions, "CRL Extensions", level + 1);
2882}
2883
2884/*
2885** secu_PrintPKCS7Signed
2886** Pretty print a PKCS7 signed data type (up to version 1).
2887*/
2888static int
2889secu_PrintPKCS7Signed(FILE *out, SEC_PKCS7SignedData *src,
2890 secuPKCS7State state, const char *m, int level)
2891{
2892 SECAlgorithmID *digAlg; /* digest algorithms */
2893 SECItem *aCert; /* certificate */
2894 CERTSignedCrl *aCrl; /* certificate revocation list */
2895 SEC_PKCS7SignerInfo *sigInfo; /* signer information */
2896 int rv, iv;
2897 char om[100];
2898
2899 SECU_Indent(out, level);
2900 fprintf(out, "%s:\n", m);
2901 SECU_PrintInteger(out, &(src->version), "Version", level + 1);
2902
2903 /* Parse and list digest algorithms (if any) */
2904 if (src->digestAlgorithms != NULL((void*)0)) {
2905 SECU_Indent(out, level + 1);
2906 fprintf(out, "Digest Algorithm List:\n");
2907 iv = 0;
2908 while ((digAlg = src->digestAlgorithms[iv++]) != NULL((void*)0)) {
2909 snprintf(om, sizeof(om), "Digest Algorithm (%x)", iv);
2910 SECU_PrintAlgorithmID(out, digAlg, om, level + 2);
2911 }
2912 }
2913
2914 /* Now for the content */
2915 rv = secu_PrintPKCS7ContentInfo(out, &(src->contentInfo),
2916 state, "Content Information", level + 1);
2917 if (rv != 0)
2918 return rv;
2919
2920 /* Parse and list certificates (if any) */
2921 if (src->rawCerts != NULL((void*)0)) {
2922 SECU_Indent(out, level + 1);
2923 fprintf(out, "Certificate List:\n");
2924 iv = 0;
2925 while ((aCert = src->rawCerts[iv++]) != NULL((void*)0)) {
2926 snprintf(om, sizeof(om), "Certificate (%x)", iv);
2927 rv = SECU_PrintSignedData(out, aCert, om, level + 2,
2928 SECU_PrintCertificate);
2929 if (rv)
2930 return rv;
2931 }
2932 }
2933
2934 /* Parse and list CRL's (if any) */
2935 if (src->crls != NULL((void*)0)) {
2936 SECU_Indent(out, level + 1);
2937 fprintf(out, "Signed Revocation Lists:\n");
2938 iv = 0;
2939 while ((aCrl = src->crls[iv++]) != NULL((void*)0)) {
2940 snprintf(om, sizeof(om), "Signed Revocation List (%x)", iv);
2941 SECU_Indent(out, level + 2);
2942 fprintf(out, "%s:\n", om);
2943 SECU_PrintAlgorithmID(out, &aCrl->signatureWrap.signatureAlgorithm,
2944 "Signature Algorithm", level + 3);
2945 DER_ConvertBitString(&aCrl->signatureWrap.signature){ (&aCrl->signatureWrap.signature)->len = ((&aCrl
->signatureWrap.signature)->len + 7) >> 3; }
;
2946 SECU_PrintAsHex(out, &aCrl->signatureWrap.signature, "Signature",
2947 level + 3);
2948 SECU_PrintCRLInfo(out, &aCrl->crl, "Certificate Revocation List",
2949 level + 3);
2950 }
2951 }
2952
2953 /* Parse and list signatures (if any) */
2954 if (src->signerInfos != NULL((void*)0)) {
2955 SECU_Indent(out, level + 1);
2956 fprintf(out, "Signer Information List:\n");
2957 iv = 0;
2958 while ((sigInfo = src->signerInfos[iv++]) != NULL((void*)0)) {
2959 snprintf(om, sizeof(om), "Signer Information (%x)", iv);
2960 secu_PrintSignerInfo(out, sigInfo, om, level + 2);
2961 }
2962 }
2963
2964 return 0;
2965}
2966
2967/*
2968** secu_PrintPKCS7Enveloped
2969** Pretty print a PKCS7 enveloped data type (up to version 1).
2970*/
2971static int
2972secu_PrintPKCS7Enveloped(FILE *out, SEC_PKCS7EnvelopedData *src,
2973 secuPKCS7State state, const char *m, int level)
2974{
2975 SEC_PKCS7RecipientInfo *recInfo; /* pointer for signer information */
2976 int iv;
2977 char om[100];
2978
2979 SECU_Indent(out, level);
2980 fprintf(out, "%s:\n", m);
2981 SECU_PrintInteger(out, &(src->version), "Version", level + 1);
2982
2983 /* Parse and list recipients (this is not optional) */
2984 if (src->recipientInfos != NULL((void*)0)) {
2985 SECU_Indent(out, level + 1);
2986 fprintf(out, "Recipient Information List:\n");
2987 iv = 0;
2988 while ((recInfo = src->recipientInfos[iv++]) != NULL((void*)0)) {
2989 snprintf(om, sizeof(om), "Recipient Information (%x)", iv);
2990 secu_PrintRecipientInfo(out, recInfo, om, level + 2);
2991 }
2992 }
2993
2994 return secu_PrintPKCS7EncContent(out, &src->encContentInfo, state,
2995 "Encrypted Content Information", level + 1);
2996}
2997
2998/*
2999** secu_PrintPKCS7SignedEnveloped
3000** Pretty print a PKCS7 singed and enveloped data type (up to version 1).
3001*/
3002static int
3003secu_PrintPKCS7SignedAndEnveloped(FILE *out,
3004 SEC_PKCS7SignedAndEnvelopedData *src,
3005 secuPKCS7State state, const char *m,
3006 int level)
3007{
3008 SECAlgorithmID *digAlg; /* pointer for digest algorithms */
3009 SECItem *aCert; /* pointer for certificate */
3010 CERTSignedCrl *aCrl; /* pointer for certificate revocation list */
3011 SEC_PKCS7SignerInfo *sigInfo; /* pointer for signer information */
3012 SEC_PKCS7RecipientInfo *recInfo; /* pointer for recipient information */
3013 int rv, iv;
3014 char om[100];
3015
3016 SECU_Indent(out, level);
3017 fprintf(out, "%s:\n", m);
3018 SECU_PrintInteger(out, &(src->version), "Version", level + 1);
3019
3020 /* Parse and list recipients (this is not optional) */
3021 if (src->recipientInfos != NULL((void*)0)) {
3022 SECU_Indent(out, level + 1);
3023 fprintf(out, "Recipient Information List:\n");
3024 iv = 0;
3025 while ((recInfo = src->recipientInfos[iv++]) != NULL((void*)0)) {
3026 snprintf(om, sizeof(om), "Recipient Information (%x)", iv);
3027 secu_PrintRecipientInfo(out, recInfo, om, level + 2);
3028 }
3029 }
3030
3031 /* Parse and list digest algorithms (if any) */
3032 if (src->digestAlgorithms != NULL((void*)0)) {
3033 SECU_Indent(out, level + 1);
3034 fprintf(out, "Digest Algorithm List:\n");
3035 iv = 0;
3036 while ((digAlg = src->digestAlgorithms[iv++]) != NULL((void*)0)) {
3037 snprintf(om, sizeof(om), "Digest Algorithm (%x)", iv);
3038 SECU_PrintAlgorithmID(out, digAlg, om, level + 2);
3039 }
3040 }
3041
3042 rv = secu_PrintPKCS7EncContent(out, &src->encContentInfo, state,
3043 "Encrypted Content Information", level + 1);
3044 if (rv)
3045 return rv;
3046
3047 /* Parse and list certificates (if any) */
3048 if (src->rawCerts != NULL((void*)0)) {
3049 SECU_Indent(out, level + 1);
3050 fprintf(out, "Certificate List:\n");
3051 iv = 0;
3052 while ((aCert = src->rawCerts[iv++]) != NULL((void*)0)) {
3053 snprintf(om, sizeof(om), "Certificate (%x)", iv);
3054 rv = SECU_PrintSignedData(out, aCert, om, level + 2,
3055 SECU_PrintCertificate);
3056 if (rv)
3057 return rv;
3058 }
3059 }
3060
3061 /* Parse and list CRL's (if any) */
3062 if (src->crls != NULL((void*)0)) {
3063 SECU_Indent(out, level + 1);
3064 fprintf(out, "Signed Revocation Lists:\n");
3065 iv = 0;
3066 while ((aCrl = src->crls[iv++]) != NULL((void*)0)) {
3067 snprintf(om, sizeof(om), "Signed Revocation List (%x)", iv);
3068 SECU_Indent(out, level + 2);
3069 fprintf(out, "%s:\n", om);
3070 SECU_PrintAlgorithmID(out, &aCrl->signatureWrap.signatureAlgorithm,
3071 "Signature Algorithm", level + 3);
3072 DER_ConvertBitString(&aCrl->signatureWrap.signature){ (&aCrl->signatureWrap.signature)->len = ((&aCrl
->signatureWrap.signature)->len + 7) >> 3; }
;
3073 SECU_PrintAsHex(out, &aCrl->signatureWrap.signature, "Signature",
3074 level + 3);
3075 SECU_PrintCRLInfo(out, &aCrl->crl, "Certificate Revocation List",
3076 level + 3);
3077 }
3078 }
3079
3080 /* Parse and list signatures (if any) */
3081 if (src->signerInfos != NULL((void*)0)) {
3082 SECU_Indent(out, level + 1);
3083 fprintf(out, "Signer Information List:\n");
3084 iv = 0;
3085 while ((sigInfo = src->signerInfos[iv++]) != NULL((void*)0)) {
3086 snprintf(om, sizeof(om), "Signer Information (%x)", iv);
3087 secu_PrintSignerInfo(out, sigInfo, om, level + 2);
3088 }
3089 }
3090
3091 return 0;
3092}
3093
3094int
3095SECU_PrintCrl(FILE *out, const SECItem *der, const char *m, int level)
3096{
3097 PLArenaPool *arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
3098 CERTCrl *c = NULL((void*)0);
3099 int rv = SEC_ERROR_NO_MEMORY;
3100
3101 if (!arena)
3102 return rv;
3103 do {
3104 /* Decode CRL */
3105 c = PORT_ArenaZNew(arena, CERTCrl)(CERTCrl *)PORT_ArenaZAlloc_Util(arena, sizeof(CERTCrl));
3106 if (!c)
3107 break;
3108
3109 rv = SEC_QuickDERDecodeItemSEC_QuickDERDecodeItem_Util(arena, c, SEC_ASN1_GET(CERT_CrlTemplate)CERT_CrlTemplate, der);
3110 if (rv != SECSuccess)
3111 break;
3112 SECU_PrintCRLInfo(out, c, m, level);
3113 } while (0);
3114 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
3115 return rv;
3116}
3117
3118/*
3119** secu_PrintPKCS7Encrypted
3120** Pretty print a PKCS7 encrypted data type (up to version 1).
3121*/
3122static int
3123secu_PrintPKCS7Encrypted(FILE *out, SEC_PKCS7EncryptedData *src,
3124 secuPKCS7State state, const char *m, int level)
3125{
3126 SECU_Indent(out, level);
3127 fprintf(out, "%s:\n", m);
3128 SECU_PrintInteger(out, &(src->version), "Version", level + 1);
3129
3130 return secu_PrintPKCS7EncContent(out, &src->encContentInfo, state,
3131 "Encrypted Content Information", level + 1);
3132}
3133
3134/*
3135** secu_PrintPKCS7Digested
3136** Pretty print a PKCS7 digested data type (up to version 1).
3137*/
3138static int
3139secu_PrintPKCS7Digested(FILE *out, SEC_PKCS7DigestedData *src,
3140 secuPKCS7State state, const char *m, int level)
3141{
3142 SECU_Indent(out, level);
3143 fprintf(out, "%s:\n", m);
3144 SECU_PrintInteger(out, &(src->version), "Version", level + 1);
3145
3146 SECU_PrintAlgorithmID(out, &src->digestAlg, "Digest Algorithm",
3147 level + 1);
3148 secu_PrintPKCS7ContentInfo(out, &src->contentInfo, state,
3149 "Content Information", level + 1);
3150 SECU_PrintAsHex(out, &src->digest, "Digest", level + 1);
3151 return 0;
3152}
3153
3154static int
3155secu_PrintPKCS12Attributes(FILE *out, SECItem *item, const char *m, int level)
3156{
3157 SECItem my = *item;
3158 SECItem attribute;
3159 SECItem attributeID;
3160 SECItem attributeValues;
3161
3162 if ((my.data[0] != (SEC_ASN1_CONSTRUCTED0x20 | SEC_ASN1_SET0x11)) ||
3163 SECSuccess != SECU_StripTagAndLength(&my)) {
3164 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
3165 return SECFailure;
3166 }
3167 SECU_Indent(out, level);
3168 fprintf(out, "%s:\n", m);
3169 level++;
3170
3171 while (my.len) {
3172 if (SECSuccess != SECU_ExtractBERAndStep(&my, &attribute)) {
3173 return SECFailure;
3174 }
3175 if ((attribute.data[0] != (SEC_ASN1_CONSTRUCTED0x20 | SEC_ASN1_SEQUENCE0x10)) ||
3176 SECSuccess != SECU_StripTagAndLength(&attribute)) {
3177 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
3178 return SECFailure;
3179 }
3180
3181 /* attribute ID */
3182 if (SECSuccess != SECU_ExtractBERAndStep(&attribute, &attributeID)) {
3183 return SECFailure;
3184 }
3185 if ((attributeID.data[0] & SEC_ASN1_TAGNUM_MASK0x1f) != SEC_ASN1_OBJECT_ID0x06) {
3186 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
3187 return SECFailure;
3188 }
3189 SECU_PrintEncodedObjectID(out, &attributeID, "Attribute ID", level);
3190
3191 /* attribute values */
3192 if (!attribute.len) { /* skip if there aren't any */
3193 continue;
3194 }
3195 if (SECSuccess != SECU_ExtractBERAndStep(&attribute, &attributeValues)) {
3196 return SECFailure;
3197 }
3198 if (SECSuccess != SECU_StripTagAndLength(&attributeValues)) {
3199 return SECFailure;
3200 }
3201 while (attributeValues.len) {
3202 SECItem tmp;
3203 if (SECSuccess != SECU_ExtractBERAndStep(&attributeValues, &tmp)) {
3204 return SECFailure;
3205 }
3206 SECU_PrintAny(out, &tmp, NULL((void*)0), level + 1);
3207 }
3208 }
3209 return SECSuccess;
3210}
3211
3212static int
3213secu_PrintPKCS12Bag(FILE *out, SECItem *item, const char *desc, int level)
3214{
3215 SECItem my = *item;
3216 SECItem bagID;
3217 SECItem bagValue;
3218 SECItem bagAttributes;
3219 SECOidTag bagTag;
3220 SECStatus rv;
3221 int i;
3222 char *m;
3223
3224 if ((my.data[0] != (SEC_ASN1_CONSTRUCTED0x20 | SEC_ASN1_SEQUENCE0x10)) ||
3225 SECSuccess != SECU_StripTagAndLength(&my)) {
3226 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
3227 return SECFailure;
3228 }
3229
3230 /* bagId BAG-TYPE.&id ({PKCS12BagSet}) */
3231 if (SECSuccess != SECU_ExtractBERAndStep(&my, &bagID)) {
3232 return SECFailure;
3233 }
3234 if ((bagID.data[0] & SEC_ASN1_TAGNUM_MASK0x1f) != SEC_ASN1_OBJECT_ID0x06) {
3235 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
3236 return SECFailure;
3237 }
3238 m = PR_smprintf("%s ID", desc);
3239 bagTag = SECU_PrintEncodedObjectID(out, &bagID, m ? m : "Bag ID", level);
3240 if (m)
3241 PR_smprintf_free(m);
3242
3243 /* bagValue [0] EXPLICIT BAG-TYPE.&type({PKCS12BagSet}{@bagID}) */
3244 if (SECSuccess != SECU_ExtractBERAndStep(&my, &bagValue)) {
3245 return SECFailure;
3246 }
3247 if ((bagValue.data[0] & (SEC_ASN1_CLASS_MASK0xc0 | SEC_ASN1_TAGNUM_MASK0x1f)) !=
3248 (SEC_ASN1_CONTEXT_SPECIFIC0x80 | 0)) {
3249 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
3250 return SECFailure;
3251 }
3252 if (SECSuccess != SECU_StripTagAndLength(&bagValue)) {
3253 return SECFailure;
3254 }
3255
3256 rv = SECSuccess;
3257 switch (bagTag) {
3258 case SEC_OID_PKCS12_V1_KEY_BAG_ID:
3259 /* Future we need to print out raw private keys. Not a priority since
3260 * p12util can't create files with unencrypted private keys, but
3261 * some tools can and do */
3262 SECU_PrintAny(out, &bagValue, "Private Key", level);
3263 break;
3264 case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID:
3265 rv = SECU_PrintPrivateKey(out, &bagValue,
3266 "Encrypted Private Key", level);
3267 break;
3268 case SEC_OID_PKCS12_V1_CERT_BAG_ID:
3269 rv = secu_PrintPKCS12Bag(out, &bagValue, "Certificate Bag", level + 1);
3270 break;
3271 case SEC_OID_PKCS12_V1_CRL_BAG_ID:
3272 rv = secu_PrintPKCS12Bag(out, &bagValue, "Crl Bag", level + 1);
3273 break;
3274 case SEC_OID_PKCS12_V1_SECRET_BAG_ID:
3275 rv = secu_PrintPKCS12Bag(out, &bagValue, "Secret Bag", level + 1);
3276 break;
3277 /* from recursive call from CRL and certificate Bag */
3278 case SEC_OID_PKCS9_X509_CRL:
3279 case SEC_OID_PKCS9_X509_CERT:
3280 case SEC_OID_PKCS9_SDSI_CERT:
3281 /* unwrap the octect string */
3282 rv = SECU_StripTagAndLength(&bagValue);
3283 if (rv != SECSuccess) {
3284 break;
3285 }
3286 /* fall through */
3287 case SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID:
3288 case SEC_OID_PKCS12_X509_CERT_CRL_BAG:
3289 case SEC_OID_PKCS12_SDSI_CERT_BAG:
3290 if (strcmp(desc, "Crl Bag") == 0) {
3291 rv = SECU_PrintSignedData(out, &bagValue, NULL((void*)0), level + 1,
3292 SECU_PrintCrl);
3293 } else {
3294 rv = SECU_PrintSignedData(out, &bagValue, NULL((void*)0), level + 1,
3295 SECU_PrintCertificate);
3296 }
3297 break;
3298 case SEC_OID_PKCS12_V1_SAFE_CONTENTS_BAG_ID:
3299 for (i = 1; my.len; i++) {
3300 SECItem nextBag;
3301 rv = SECU_ExtractBERAndStep(&bagValue, &nextBag);
3302 if (rv != SECSuccess) {
3303 break;
3304 }
3305 m = PR_smprintf("Nested Bag %d", i);
3306 rv = secu_PrintPKCS12Bag(out, &nextBag,
3307 m ? m : "Nested Bag", level + 1);
3308 if (m)
3309 PR_smprintf_free(m);
3310 if (rv != SECSuccess) {
3311 break;
3312 }
3313 }
3314 break;
3315 default:
3316 m = PR_smprintf("%s Value", desc);
3317 SECU_PrintAny(out, &bagValue, m ? m : "Bag Value", level);
3318 if (m)
3319 PR_smprintf_free(m);
3320 }
3321 if (rv != SECSuccess) {
3322 return rv;
3323 }
3324
3325 /* bagAttributes SET OF PKCS12Attributes OPTIONAL */
3326 if (my.len &&
3327 (my.data[0] == (SEC_ASN1_CONSTRUCTED0x20 | SEC_ASN1_SET0x11))) {
3328 if (SECSuccess != SECU_ExtractBERAndStep(&my, &bagAttributes)) {
3329 return SECFailure;
3330 }
3331 m = PR_smprintf("%s Attributes", desc);
3332 rv = secu_PrintPKCS12Attributes(out, &bagAttributes,
3333 m ? m : "Bag Attributes", level);
3334 if (m)
3335 PR_smprintf_free(m);
3336 }
3337 return rv;
3338}
3339
3340static int
3341secu_PrintPKCS7Data(FILE *out, SECItem *item, secuPKCS7State state,
3342 const char *desc, int level)
3343{
3344 SECItem my = *item;
3345 SECItem nextbag;
3346 int i;
3347 SECStatus rv;
3348
3349 /* walk down each safe */
3350 switch (state) {
3351 case secuPKCS7PKCS12AuthSafe:
3352 if ((my.data[0] != (SEC_ASN1_CONSTRUCTED0x20 | SEC_ASN1_SEQUENCE0x10)) ||
3353 SECSuccess != SECU_StripTagAndLength(&my)) {
3354 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
3355 return SECFailure;
3356 }
3357 for (i = 1; my.len; i++) {
3358 char *m;
3359 if (SECSuccess != SECU_ExtractBERAndStep(&my, &nextbag)) {
3360 return SECFailure;
3361 }
3362 m = PR_smprintf("Safe %d", i);
3363 rv = secu_PrintDERPKCS7ContentInfo(out, &nextbag,
3364 secuPKCS7PKCS12Safe,
3365 m ? m : "Safe", level);
3366 if (m)
3367 PR_smprintf_free(m);
3368 if (rv != SECSuccess) {
3369 return SECFailure;
3370 }
3371 }
3372 return SECSuccess;
3373 case secuPKCS7PKCS12Safe:
3374 if ((my.data[0] != (SEC_ASN1_CONSTRUCTED0x20 | SEC_ASN1_SEQUENCE0x10)) ||
3375 SECSuccess != SECU_StripTagAndLength(&my)) {
3376 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
3377 return SECFailure;
3378 }
3379 for (i = 1; my.len; i++) {
3380 char *m;
3381 if (SECSuccess != SECU_ExtractBERAndStep(&my, &nextbag)) {
3382 return SECFailure;
3383 }
3384 m = PR_smprintf("Bag %d", i);
3385 rv = secu_PrintPKCS12Bag(out, &nextbag,
3386 m ? m : "Bag", level);
3387 if (m)
3388 PR_smprintf_free(m);
3389 if (rv != SECSuccess) {
3390 return SECFailure;
3391 }
3392 }
3393 return SECSuccess;
3394 case secuPKCS7Unknown:
3395 SECU_PrintAsHex(out, item, desc, level);
3396 break;
3397 }
3398 return SECSuccess;
3399}
3400
3401/*
3402** secu_PrintPKCS7ContentInfo
3403** Takes a SEC_PKCS7ContentInfo type and sends the contents to the
3404** appropriate function
3405*/
3406static int
3407secu_PrintPKCS7ContentInfo(FILE *out, SEC_PKCS7ContentInfo *src,
3408 secuPKCS7State state, const char *m, int level)
3409{
3410 const char *desc;
3411 SECOidTag kind;
3412 int rv;
3413
3414 SECU_Indent(out, level);
3415 fprintf(out, "%s:\n", m);
3416 level++;
3417
3418 if (src->contentTypeTag == NULL((void*)0))
3419 src->contentTypeTag = SECOID_FindOIDSECOID_FindOID_Util(&(src->contentType));
3420
3421 if (src->contentTypeTag == NULL((void*)0)) {
3422 desc = "Unknown";
3423 kind = SEC_OID_UNKNOWN;
3424 } else {
3425 desc = src->contentTypeTag->desc;
3426 kind = src->contentTypeTag->offset;
3427 }
3428
3429 if (src->content.data == NULL((void*)0)) {
3430 SECU_Indent(out, level);
3431 fprintf(out, "%s:\n", desc);
3432 level++;
3433 SECU_Indent(out, level);
3434 fprintf(out, "<no content>\n");
3435 return 0;
3436 }
3437
3438 rv = 0;
3439 switch (kind) {
3440 case SEC_OID_PKCS7_SIGNED_DATA: /* Signed Data */
3441 rv = secu_PrintPKCS7Signed(out, src->content.signedData,
3442 state, desc, level);
3443 break;
3444
3445 case SEC_OID_PKCS7_ENVELOPED_DATA: /* Enveloped Data */
3446 rv = secu_PrintPKCS7Enveloped(out, src->content.envelopedData,
3447 state, desc, level);
3448 break;
3449
3450 case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: /* Signed and Enveloped */
3451 rv = secu_PrintPKCS7SignedAndEnveloped(out,
3452 src->content.signedAndEnvelopedData,
3453 state, desc, level);
3454 break;
3455
3456 case SEC_OID_PKCS7_DIGESTED_DATA: /* Digested Data */
3457 rv = secu_PrintPKCS7Digested(out, src->content.digestedData,
3458 state, desc, level);
3459 break;
3460
3461 case SEC_OID_PKCS7_ENCRYPTED_DATA: /* Encrypted Data */
3462 rv = secu_PrintPKCS7Encrypted(out, src->content.encryptedData,
3463 state, desc, level);
3464 break;
3465
3466 case SEC_OID_PKCS7_DATA:
3467 rv = secu_PrintPKCS7Data(out, src->content.data, state, desc, level);
3468 break;
3469
3470 default:
3471 SECU_PrintAsHex(out, src->content.data, desc, level);
3472 break;
3473 }
3474
3475 return rv;
3476}
3477
3478/*
3479** SECU_PrintPKCS7ContentInfo
3480** Decode and print any major PKCS7 data type (up to version 1).
3481*/
3482static int
3483secu_PrintDERPKCS7ContentInfo(FILE *out, SECItem *der, secuPKCS7State state,
3484 const char *m, int level)
3485{
3486 SEC_PKCS7ContentInfo *cinfo;
3487 int rv;
3488
3489 cinfo = SEC_PKCS7DecodeItem(der, NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0), NULL((void*)0));
3490 if (cinfo != NULL((void*)0)) {
3491 /* Send it to recursive parsing and printing module */
3492 rv = secu_PrintPKCS7ContentInfo(out, cinfo, state, m, level);
3493 SEC_PKCS7DestroyContentInfo(cinfo);
3494 } else {
3495 rv = -1;
3496 }
3497
3498 return rv;
3499}
3500
3501int
3502SECU_PrintPKCS7ContentInfo(FILE *out, SECItem *der, char *m, int level)
3503{
3504 return secu_PrintDERPKCS7ContentInfo(out, der, secuPKCS7Unknown, m, level);
3505}
3506
3507/*
3508** End of PKCS7 functions
3509*/
3510
3511void
3512printFlags(FILE *out, unsigned int flags, int level)
3513{
3514 if (flags & CERTDB_TERMINAL_RECORD(1u << 0)) {
3515 SECU_Indent(out, level);
3516 fprintf(out, "Terminal Record\n");
3517 }
3518 if (flags & CERTDB_TRUSTED(1u << 1)) {
3519 SECU_Indent(out, level);
3520 fprintf(out, "Trusted\n");
3521 }
3522 if (flags & CERTDB_SEND_WARN(1u << 2)) {
3523 SECU_Indent(out, level);
3524 fprintf(out, "Warn When Sending\n");
3525 }
3526 if (flags & CERTDB_VALID_CA(1u << 3)) {
3527 SECU_Indent(out, level);
3528 fprintf(out, "Valid CA\n");
3529 }
3530 if (flags & CERTDB_TRUSTED_CA(1u << 4)) {
3531 SECU_Indent(out, level);
3532 fprintf(out, "Trusted CA\n");
3533 }
3534 if (flags & CERTDB_NS_TRUSTED_CA(1u << 5)) {
3535 SECU_Indent(out, level);
3536 fprintf(out, "Netscape Trusted CA\n");
3537 }
3538 if (flags & CERTDB_USER(1u << 6)) {
3539 SECU_Indent(out, level);
3540 fprintf(out, "User\n");
3541 }
3542 if (flags & CERTDB_TRUSTED_CLIENT_CA(1u << 7)) {
3543 SECU_Indent(out, level);
3544 fprintf(out, "Trusted Client CA\n");
3545 }
3546 if (flags & CERTDB_GOVT_APPROVED_CA(1u << 9)) {
3547 SECU_Indent(out, level);
3548 fprintf(out, "Step-up\n");
3549 }
3550}
3551
3552void
3553SECU_PrintTrustFlags(FILE *out, CERTCertTrust *trust, char *m, int level)
3554{
3555 SECU_Indent(out, level);
3556 fprintf(out, "%s:\n", m);
3557 SECU_Indent(out, level + 1);
3558 fprintf(out, "SSL Flags:\n");
3559 printFlags(out, trust->sslFlags, level + 2);
3560 SECU_Indent(out, level + 1);
3561 fprintf(out, "Email Flags:\n");
3562 printFlags(out, trust->emailFlags, level + 2);
3563 SECU_Indent(out, level + 1);
3564 fprintf(out, "Object Signing Flags:\n");
3565 printFlags(out, trust->objectSigningFlags, level + 2);
3566}
3567
3568int
3569SECU_PrintDERName(FILE *out, SECItem *der, const char *m, int level)
3570{
3571 PLArenaPool *arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
3572 CERTName *name;
3573 int rv = SEC_ERROR_NO_MEMORY;
3574
3575 if (!arena)
3576 return rv;
3577
3578 name = PORT_ArenaZNew(arena, CERTName)(CERTName *)PORT_ArenaZAlloc_Util(arena, sizeof(CERTName));
3579 if (!name)
3580 goto loser;
3581
3582 rv = SEC_ASN1DecodeItemSEC_ASN1DecodeItem_Util(arena, name, SEC_ASN1_GET(CERT_NameTemplate)CERT_NameTemplate, der);
3583 if (rv)
3584 goto loser;
3585
3586 SECU_PrintName(out, name, m, level);
3587 if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
3588 SECU_Newline(out);
3589loser:
3590 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
3591 return rv;
3592}
3593
3594typedef enum {
3595 noSignature = 0,
3596 withSignature = 1
3597} SignatureOptionType;
3598
3599static int
3600secu_PrintSignedDataSigOpt(FILE *out, SECItem *der, const char *m,
3601 int level, SECU_PPFunc inner,
3602 SignatureOptionType signatureOption)
3603{
3604 PLArenaPool *arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
3605 CERTSignedData *sd;
3606 int rv = SEC_ERROR_NO_MEMORY;
3607
3608 if (!arena)
3609 return rv;
3610
3611 /* Strip off the signature */
3612 sd = PORT_ArenaZNew(arena, CERTSignedData)(CERTSignedData *)PORT_ArenaZAlloc_Util(arena, sizeof(CERTSignedData
))
;
3613 if (!sd)
3614 goto loser;
3615
3616 rv = SEC_ASN1DecodeItemSEC_ASN1DecodeItem_Util(arena, sd, SEC_ASN1_GET(CERT_SignedDataTemplate)CERT_SignedDataTemplate,
3617 der);
3618 if (rv)
3619 goto loser;
3620
3621 if (m) {
3622 SECU_Indent(out, level);
3623 fprintf(out, "%s:\n", m);
3624 } else {
3625 level -= 1;
3626 }
3627 rv = (*inner)(out, &sd->data, "Data", level + 1);
3628
3629 if (signatureOption == withSignature) {
3630 SECU_PrintAlgorithmID(out, &sd->signatureAlgorithm, "Signature Algorithm",
3631 level + 1);
3632 DER_ConvertBitString(&sd->signature){ (&sd->signature)->len = ((&sd->signature)->
len + 7) >> 3; }
;
3633 SECU_PrintAsHex(out, &sd->signature, "Signature", level + 1);
3634 }
3635 SECU_PrintFingerprints(out, der, "Fingerprint", level + 1);
3636loser:
3637 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
3638 return rv;
3639}
3640
3641int
3642SECU_PrintSignedData(FILE *out, SECItem *der, const char *m,
3643 int level, SECU_PPFunc inner)
3644{
3645 return secu_PrintSignedDataSigOpt(out, der, m, level, inner,
3646 withSignature);
3647}
3648
3649int
3650SECU_PrintSignedContent(FILE *out, SECItem *der, char *m,
3651 int level, SECU_PPFunc inner)
3652{
3653 return secu_PrintSignedDataSigOpt(out, der, m, level, inner,
3654 noSignature);
3655}
3656
3657SECStatus
3658SEC_PrintCertificateAndTrust(CERTCertificate *cert,
3659 const char *label,
3660 CERTCertTrust *trust)
3661{
3662 SECStatus rv;
3663 SECItem data;
3664 CERTCertTrust certTrust;
3665 PK11SlotList *slotList;
3666 PRBool falseAttributeFound = PR_FALSE0;
3667 PRBool trueAttributeFound = PR_FALSE0;
3668 const char *moz_policy_ca_info = NULL((void*)0);
3669
3670 data.data = cert->derCert.data;
3671 data.len = cert->derCert.len;
3672
3673 rv = SECU_PrintSignedData(stdoutstdout, &data, label, 0,
3674 SECU_PrintCertificate);
3675 if (rv) {
3676 return (SECFailure);
3677 }
3678
3679 slotList = PK11_GetAllSlotsForCert(cert, NULL((void*)0));
3680 if (slotList) {
3681 PK11SlotListElement *se = PK11_GetFirstSafe(slotList);
3682 for (; se; se = PK11_GetNextSafe(slotList, se, PR_FALSE0)) {
3683 CK_OBJECT_HANDLE handle = PK11_FindCertInSlot(se->slot, cert, NULL((void*)0));
3684 if (handle != CK_INVALID_HANDLE0) {
3685 PORT_SetErrorPORT_SetError_Util(0);
3686 if (PK11_HasAttributeSet(se->slot, handle,
3687 CKA_NSS_MOZILLA_CA_POLICY((0x80000000UL | 0x4E534350) + 34), PR_FALSE0)) {
3688 trueAttributeFound = PR_TRUE1;
3689 } else if (!PORT_GetErrorPORT_GetError_Util()) {
3690 falseAttributeFound = PR_TRUE1;
3691 }
3692 }
3693 }
3694 PK11_FreeSlotList(slotList);
3695 }
3696
3697 if (trueAttributeFound) {
3698 moz_policy_ca_info = "true (attribute present)";
3699 } else if (falseAttributeFound) {
3700 moz_policy_ca_info = "false (attribute present)";
3701 } else {
3702 moz_policy_ca_info = "false (attribute missing)";
3703 }
3704 SECU_Indent(stdoutstdout, 1);
3705 printf("Mozilla-CA-Policy: %s\n", moz_policy_ca_info);
3706
3707 if (trust) {
3708 SECU_PrintTrustFlags(stdoutstdout, trust,
3709 "Certificate Trust Flags", 1);
3710 } else if (CERT_GetCertTrust(cert, &certTrust) == SECSuccess) {
3711 SECU_PrintTrustFlags(stdoutstdout, &certTrust,
3712 "Certificate Trust Flags", 1);
3713 }
3714
3715 /* The distrust fields are hard-coded in nssckbi and read-only.
3716 * If verifying some cert, with vfychain, for instance, the certificate may
3717 * not have a defined slot if not imported. */
3718 if (cert->slot != NULL((void*)0) && cert->distrust != NULL((void*)0)) {
3719 const unsigned int kDistrustFieldSize = 13;
3720 fprintf(stdoutstdout, "\n");
3721 SECU_Indent(stdoutstdout, 1);
3722 fprintf(stdoutstdout, "%s:\n", "Certificate Distrust Dates");
3723 if (cert->distrust->serverDistrustAfter.len == kDistrustFieldSize) {
3724 SECU_PrintTimeChoice(stdoutstdout,
3725 &cert->distrust->serverDistrustAfter,
3726 "Server Distrust After", 2);
3727 }
3728 if (cert->distrust->emailDistrustAfter.len == kDistrustFieldSize) {
3729 SECU_PrintTimeChoice(stdoutstdout,
3730 &cert->distrust->emailDistrustAfter,
3731 "E-mail Distrust After", 2);
3732 }
3733 }
3734
3735 printf("\n");
3736
3737 return (SECSuccess);
3738}
3739
3740static char *
3741bestCertName(CERTCertificate *cert)
3742{
3743 if (cert->nickname) {
3744 return cert->nickname;
3745 }
3746 if (cert->emailAddr && cert->emailAddr[0]) {
3747 return cert->emailAddr;
3748 }
3749 return cert->subjectName;
3750}
3751
3752void
3753SECU_printCertProblemsOnDate(FILE *outfile, CERTCertDBHandle *handle,
3754 CERTCertificate *cert, PRBool checksig,
3755 SECCertificateUsage certUsage, void *pinArg, PRBool verbose,
3756 PRTime datetime)
3757{
3758 CERTVerifyLog log;
3759 CERTVerifyLogNode *node;
3760
3761 PRErrorCode err = PORT_GetErrorPORT_GetError_Util();
3762
3763 log.arena = PORT_NewArenaPORT_NewArena_Util(512);
3764 log.head = log.tail = NULL((void*)0);
3765 log.count = 0;
3766 CERT_VerifyCertificate(handle, cert, checksig, certUsage, datetime, pinArg, &log, NULL((void*)0));
3767
3768 SECU_displayVerifyLog(outfile, &log, verbose);
2
Calling 'SECU_displayVerifyLog'
3769
3770 for (node = log.head; node; node = node->next) {
3771 if (node->cert)
3772 CERT_DestroyCertificate(node->cert);
3773 }
3774 PORT_FreeArenaPORT_FreeArena_Util(log.arena, PR_FALSE0);
3775
3776 PORT_SetErrorPORT_SetError_Util(err); /* restore original error code */
3777}
3778
3779void
3780SECU_displayVerifyLog(FILE *outfile, CERTVerifyLog *log,
3781 PRBool verbose)
3782{
3783 CERTVerifyLogNode *node = NULL((void*)0);
3784 unsigned int depth = (unsigned int)-1;
3785 unsigned int flags = 0;
3786 char *errstr = NULL((void*)0);
3787
3788 if (log->count > 0) {
3
Assuming field 'count' is > 0
4
Taking true branch
3789 fprintf(outfile, "PROBLEM WITH THE CERT CHAIN:\n");
3790 for (node = log->head; node; node = node->next) {
5
Loop condition is true. Entering loop body
3791 if (depth != node->depth) {
6
Assuming 'depth' is equal to field 'depth'
7
Taking false branch
3792 depth = node->depth;
3793 fprintf(outfile, "CERT %d. %s %s:\n", depth,
3794 bestCertName(node->cert),
3795 depth ? "[Certificate Authority]" : "");
3796 if (verbose) {
3797 const char *emailAddr;
3798 emailAddr = CERT_GetFirstEmailAddress(node->cert);
3799 if (emailAddr) {
3800 fprintf(outfile, "Email Address(es): ");
3801 do {
3802 fprintf(outfile, "%s\n", emailAddr);
3803 emailAddr = CERT_GetNextEmailAddress(node->cert,
3804 emailAddr);
3805 } while (emailAddr);
3806 }
3807 }
3808 }
3809 fprintf(outfile, " ERROR %ld: %s\n", node->error,
3810 SECU_Strerror(node->error)PR_ErrorToString((node->error), 0));
3811 errstr = NULL((void*)0);
3812 switch (node->error) {
8
Control jumps to 'case SEC_ERROR_INADEQUATE_KEY_USAGE:' at line 3813
3813 case SEC_ERROR_INADEQUATE_KEY_USAGE:
3814 flags = (unsigned int)((char *)node->arg - (char *)NULL((void*)0));
9
Subtraction of a probably non-null pointer and a null pointer may result in undefined behavior
3815 switch (flags) {
3816 case KU_DIGITAL_SIGNATURE(0x80):
3817 errstr = "Cert cannot sign.";
3818 break;
3819 case KU_KEY_ENCIPHERMENT(0x20):
3820 errstr = "Cert cannot encrypt.";
3821 break;
3822 case KU_KEY_CERT_SIGN(0x04):
3823 errstr = "Cert cannot sign other certs.";
3824 break;
3825 default:
3826 errstr = "[unknown usage].";
3827 break;
3828 }
3829 break;
3830 case SEC_ERROR_INADEQUATE_CERT_TYPE:
3831 flags = (unsigned int)((char *)node->arg - (char *)NULL((void*)0));
3832 switch (flags) {
3833 case NS_CERT_TYPE_SSL_CLIENT(0x80):
3834 case NS_CERT_TYPE_SSL_SERVER(0x40):
3835 errstr = "Cert cannot be used for SSL.";
3836 break;
3837 case NS_CERT_TYPE_SSL_CA(0x04):
3838 errstr = "Cert cannot be used as an SSL CA.";
3839 break;
3840 case NS_CERT_TYPE_EMAIL(0x20):
3841 errstr = "Cert cannot be used for SMIME.";
3842 break;
3843 case NS_CERT_TYPE_EMAIL_CA(0x02):
3844 errstr = "Cert cannot be used as an SMIME CA.";
3845 break;
3846 case NS_CERT_TYPE_OBJECT_SIGNING(0x10):
3847 errstr = "Cert cannot be used for object signing.";
3848 break;
3849 case NS_CERT_TYPE_OBJECT_SIGNING_CA(0x01):
3850 errstr = "Cert cannot be used as an object signing CA.";
3851 break;
3852 default:
3853 errstr = "[unknown usage].";
3854 break;
3855 }
3856 break;
3857 case SEC_ERROR_UNKNOWN_ISSUER:
3858 case SEC_ERROR_UNTRUSTED_ISSUER:
3859 case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
3860 errstr = node->cert->issuerName;
3861 break;
3862 default:
3863 break;
3864 }
3865 if (errstr) {
3866 fprintf(stderrstderr, " %s\n", errstr);
3867 }
3868 }
3869 }
3870}
3871
3872void
3873SECU_printCertProblems(FILE *outfile, CERTCertDBHandle *handle,
3874 CERTCertificate *cert, PRBool checksig,
3875 SECCertificateUsage certUsage, void *pinArg, PRBool verbose)
3876{
3877 SECU_printCertProblemsOnDate(outfile, handle, cert, checksig,
1
Calling 'SECU_printCertProblemsOnDate'
3878 certUsage, pinArg, verbose, PR_Now());
3879}
3880
3881SECStatus
3882SECU_StoreCRL(PK11SlotInfo *slot, SECItem *derCrl, PRFileDesc *outFile,
3883 PRBool ascii, char *url)
3884{
3885 PORT_Assert(derCrl != NULL)((derCrl != ((void*)0)) ? ((void)0) : PR_Assert("derCrl != NULL"
, "/root/firefox-clang/security/nss/cmd/lib/secutil.c", 3885)
)
;
3886 if (!derCrl) {
3887 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
3888 return SECFailure;
3889 }
3890
3891 if (outFile != NULL((void*)0)) {
3892 if (ascii) {
3893 PR_fprintf(outFile, "%s\n%s\n%s\n", NS_CRL_HEADER"-----BEGIN CRL-----",
3894 BTOA_DataToAsciiBTOA_DataToAscii_Util(derCrl->data, derCrl->len),
3895 NS_CRL_TRAILER"-----END CRL-----");
3896 } else {
3897 if (PR_Write(outFile, derCrl->data, derCrl->len) != derCrl->len) {
3898 return SECFailure;
3899 }
3900 }
3901 }
3902 if (slot) {
3903 CERTSignedCrl *newCrl = PK11_ImportCRL(slot, derCrl, url,
3904 SEC_CRL_TYPE1, NULL((void*)0), 0, NULL((void*)0), 0);
3905 if (newCrl != NULL((void*)0)) {
3906 SEC_DestroyCrl(newCrl);
3907 return SECSuccess;
3908 }
3909 return SECFailure;
3910 }
3911 if (!outFile && !slot) {
3912 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
3913 return SECFailure;
3914 }
3915 return SECSuccess;
3916}
3917
3918SECStatus
3919SECU_SignAndEncodeCRL(CERTCertificate *issuer, CERTSignedCrl *signCrl,
3920 SECOidTag hashAlgTag, SignAndEncodeFuncExitStat *resCode)
3921{
3922 SECItem der;
3923 SECKEYPrivateKey *caPrivateKey = NULL((void*)0);
3924 SECStatus rv;
3925 PLArenaPool *arena;
3926 SECOidTag algID;
3927 void *dummy;
3928
3929 PORT_Assert(issuer != NULL && signCrl != NULL)((issuer != ((void*)0) && signCrl != ((void*)0)) ? ((
void)0) : PR_Assert("issuer != NULL && signCrl != NULL"
, "/root/firefox-clang/security/nss/cmd/lib/secutil.c", 3929)
)
;
3930 if (!issuer || !signCrl) {
3931 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
3932 return SECFailure;
3933 }
3934
3935 arena = signCrl->arena;
3936
3937 caPrivateKey = PK11_FindKeyByAnyCert(issuer, NULL((void*)0));
3938 if (caPrivateKey == NULL((void*)0)) {
3939 *resCode = noKeyFound;
3940 return SECFailure;
3941 }
3942
3943 algID = SEC_GetSignatureAlgorithmOidTagByKey(caPrivateKey, NULL((void*)0), hashAlgTag);
3944 if (algID == SEC_OID_UNKNOWN) {
3945 *resCode = noSignatureMatch;
3946 rv = SECFailure;
3947 goto done;
3948 }
3949
3950 if (!signCrl->crl.signatureAlg.parameters.data) {
3951 rv = SECOID_SetAlgorithmIDSECOID_SetAlgorithmID_Util(arena, &signCrl->crl.signatureAlg, algID, 0);
3952 if (rv != SECSuccess) {
3953 *resCode = failToEncode;
3954 goto done;
3955 }
3956 }
3957
3958 der.len = 0;
3959 der.data = NULL((void*)0);
3960 dummy = SEC_ASN1EncodeItemSEC_ASN1EncodeItem_Util(arena, &der, &signCrl->crl,
3961 SEC_ASN1_GET(CERT_CrlTemplate)CERT_CrlTemplate);
3962 if (!dummy) {
3963 *resCode = failToEncode;
3964 rv = SECFailure;
3965 goto done;
3966 }
3967
3968 rv = SECU_DerSignDataCRL(arena, &signCrl->signatureWrap,
3969 der.data, der.len, caPrivateKey, algID);
3970 if (rv != SECSuccess) {
3971 *resCode = failToSign;
3972 goto done;
3973 }
3974
3975 signCrl->derCrl = PORT_ArenaZNew(arena, SECItem)(SECItem *)PORT_ArenaZAlloc_Util(arena, sizeof(SECItem));
3976 if (signCrl->derCrl == NULL((void*)0)) {
3977 *resCode = noMem;
3978 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_MEMORY);
3979 rv = SECFailure;
3980 goto done;
3981 }
3982
3983 signCrl->derCrl->len = 0;
3984 signCrl->derCrl->data = NULL((void*)0);
3985 dummy = SEC_ASN1EncodeItemSEC_ASN1EncodeItem_Util(arena, signCrl->derCrl, signCrl,
3986 SEC_ASN1_GET(CERT_SignedCrlTemplate)CERT_SignedCrlTemplate);
3987 if (!dummy) {
3988 *resCode = failToEncode;
3989 rv = SECFailure;
3990 goto done;
3991 }
3992
3993done:
3994 SECKEY_DestroyPrivateKey(caPrivateKey);
3995 return rv;
3996}
3997
3998SECStatus
3999SECU_CopyCRL(PLArenaPool *destArena, CERTCrl *destCrl, CERTCrl *srcCrl)
4000{
4001 void *dummy;
4002 SECStatus rv = SECSuccess;
4003 SECItem der;
4004
4005 PORT_Assert(destArena && srcCrl && destCrl)((destArena && srcCrl && destCrl) ? ((void)0)
: PR_Assert("destArena && srcCrl && destCrl"
, "/root/firefox-clang/security/nss/cmd/lib/secutil.c", 4005)
)
;
4006 if (!destArena || !srcCrl || !destCrl) {
4007 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
4008 return SECFailure;
4009 }
4010
4011 der.len = 0;
4012 der.data = NULL((void*)0);
4013 dummy = SEC_ASN1EncodeItemSEC_ASN1EncodeItem_Util(destArena, &der, srcCrl,
4014 SEC_ASN1_GET(CERT_CrlTemplate)CERT_CrlTemplate);
4015 if (!dummy) {
4016 return SECFailure;
4017 }
4018
4019 rv = SEC_QuickDERDecodeItemSEC_QuickDERDecodeItem_Util(destArena, destCrl,
4020 SEC_ASN1_GET(CERT_CrlTemplate)CERT_CrlTemplate, &der);
4021 if (rv != SECSuccess) {
4022 return SECFailure;
4023 }
4024
4025 destCrl->arena = destArena;
4026
4027 return rv;
4028}
4029
4030SECStatus
4031SECU_DerSignDataCRL(PLArenaPool *arena, CERTSignedData *sd,
4032 unsigned char *buf, int len, SECKEYPrivateKey *pk,
4033 SECOidTag algID)
4034{
4035 SECItem it;
4036 SECStatus rv;
4037
4038 it.data = 0;
4039
4040 /* XXX We should probably have some asserts here to make sure the key type
4041 * and algID match
4042 */
4043
4044 /* Sign input buffer */
4045 rv = SEC_SignData(&it, buf, len, pk, algID);
4046 if (rv != SECSuccess) {
4047 goto loser;
4048 }
4049
4050 /* Fill out SignedData object */
4051 PORT_Memsetmemset(sd, 0, sizeof(*sd));
4052 sd->data.data = buf;
4053 sd->data.len = len;
4054 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(arena, &sd->signature, &it);
4055 if (rv != SECSuccess) {
4056 goto loser;
4057 }
4058
4059 sd->signature.len <<= 3; /* convert to bit string */
4060 rv = SECOID_SetAlgorithmIDSECOID_SetAlgorithmID_Util(arena, &sd->signatureAlgorithm, algID, 0);
4061 if (rv != SECSuccess) {
4062 goto loser;
4063 }
4064
4065loser:
4066 PORT_FreePORT_Free_Util(it.data);
4067 return rv;
4068}
4069
4070/*
4071 * Find the issuer of a Crl. Use the authorityKeyID if it exists.
4072 */
4073CERTCertificate *
4074SECU_FindCrlIssuer(CERTCertDBHandle *dbhandle, SECItem *subject,
4075 CERTAuthKeyID *authorityKeyID, PRTime validTime)
4076{
4077 CERTCertificate *issuerCert = NULL((void*)0);
4078 CERTCertList *certList = NULL((void*)0);
4079 CERTCertTrust trust;
4080
4081 if (!subject) {
4082 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
4083 return NULL((void*)0);
4084 }
4085
4086 certList =
4087 CERT_CreateSubjectCertList(NULL((void*)0), dbhandle, subject,
4088 validTime, PR_TRUE1);
4089 if (certList) {
4090 CERTCertListNode *node = CERT_LIST_HEAD(certList)((CERTCertListNode *)(&certList->list)->next);
4091
4092 /* XXX and authoritykeyid in the future */
4093 while (!CERT_LIST_END(node, certList)(((void *)node) == ((void *)&certList->list))) {
4094 CERTCertificate *cert = node->cert;
4095 /* check cert CERTCertTrust data is allocated, check cert
4096 usage extension, check that cert has pkey in db. Select
4097 the first (newest) user cert */
4098 if (CERT_GetCertTrust(cert, &trust) == SECSuccess &&
4099 CERT_CheckCertUsage(cert, KU_CRL_SIGN(0x02)) == SECSuccess &&
4100 CERT_IsUserCert(cert)) {
4101
4102 issuerCert = CERT_DupCertificate(cert);
4103 break;
4104 }
4105 node = CERT_LIST_NEXT(node)((CERTCertListNode *)node->links.next);
4106 }
4107 CERT_DestroyCertList(certList);
4108 }
4109 return (issuerCert);
4110}
4111
4112/* Encodes and adds extensions to the CRL or CRL entries. */
4113SECStatus
4114SECU_EncodeAndAddExtensionValue(PLArenaPool *arena, void *extHandle,
4115 void *value, PRBool criticality, int extenType,
4116 EXTEN_EXT_VALUE_ENCODER EncodeValueFn)
4117{
4118 SECItem encodedValue;
4119 SECStatus rv;
4120
4121 encodedValue.data = NULL((void*)0);
4122 encodedValue.len = 0;
4123 do {
4124 rv = (*EncodeValueFn)(arena, value, &encodedValue);
4125 if (rv != SECSuccess)
4126 break;
4127
4128 rv = CERT_AddExtension(extHandle, extenType, &encodedValue,
4129 criticality, PR_TRUE1);
4130 if (rv != SECSuccess)
4131 break;
4132 } while (0);
4133
4134 return (rv);
4135}
4136
4137CERTCertificate *
4138SECU_FindCertByNicknameOrFilename(CERTCertDBHandle *handle,
4139 char *name, PRBool ascii,
4140 void *pwarg)
4141{
4142 CERTCertificate *the_cert;
4143 the_cert = CERT_FindCertByNicknameOrEmailAddrCX(handle, name, pwarg);
4144 if (the_cert) {
4145 return the_cert;
4146 }
4147 the_cert = PK11_FindCertFromNickname(name, pwarg);
4148 if (!the_cert) {
4149 /* Don't have a cert with name "name" in the DB. Try to
4150 * open a file with such name and get the cert from there.*/
4151 SECStatus rv;
4152 SECItem item = { 0, NULL((void*)0), 0 };
4153 PRFileDesc *fd = PR_Open(name, PR_RDONLY0x01, 0777);
4154 if (!fd) {
4155 return NULL((void*)0);
4156 }
4157 rv = SECU_ReadDERFromFile(&item, fd, ascii, PR_FALSE0);
4158 PR_Close(fd);
4159 if (rv != SECSuccess || !item.len) {
4160 PORT_FreePORT_Free_Util(item.data);
4161 return NULL((void*)0);
4162 }
4163 the_cert = CERT_NewTempCertificate(handle, &item,
4164 NULL((void*)0) /* nickname */,
4165 PR_FALSE0 /* isPerm */,
4166 PR_TRUE1 /* copyDER */);
4167 PORT_FreePORT_Free_Util(item.data);
4168 }
4169 return the_cert;
4170}
4171
4172/* Convert a SSL/TLS protocol version string into the respective numeric value
4173 * defined by the SSL_LIBRARY_VERSION_* constants,
4174 * while accepting a flexible set of case-insensitive identifiers.
4175 *
4176 * Caller must specify bufLen, allowing the function to operate on substrings.
4177 */
4178static SECStatus
4179SECU_GetSSLVersionFromName(const char *buf, size_t bufLen, PRUint16 *version)
4180{
4181 if (!buf || !version) {
4182 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
4183 return SECFailure;
4184 }
4185
4186 if (!PL_strncasecmp(buf, "ssl3", bufLen)) {
4187 *version = SSL_LIBRARY_VERSION_3_00x0300;
4188 return SECSuccess;
4189 }
4190 if (!PL_strncasecmp(buf, "tls1.0", bufLen)) {
4191 *version = SSL_LIBRARY_VERSION_TLS_1_00x0301;
4192 return SECSuccess;
4193 }
4194 if (!PL_strncasecmp(buf, "tls1.1", bufLen)) {
4195 *version = SSL_LIBRARY_VERSION_TLS_1_10x0302;
4196 return SECSuccess;
4197 }
4198 if (!PL_strncasecmp(buf, "tls1.2", bufLen)) {
4199 *version = SSL_LIBRARY_VERSION_TLS_1_20x0303;
4200 return SECSuccess;
4201 }
4202
4203 if (!PL_strncasecmp(buf, "tls1.3", bufLen)) {
4204 *version = SSL_LIBRARY_VERSION_TLS_1_30x0304;
4205 return SECSuccess;
4206 }
4207
4208 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
4209 return SECFailure;
4210}
4211
4212SECStatus
4213SECU_ParseSSLVersionRangeString(const char *input,
4214 const SSLVersionRange defaultVersionRange,
4215 SSLVersionRange *vrange)
4216{
4217 const char *colonPos;
4218 size_t colonIndex;
4219 const char *maxStr;
4220
4221 if (!input || !vrange) {
4222 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
4223 return SECFailure;
4224 }
4225
4226 // We don't support SSL2 any longer.
4227 if (defaultVersionRange.min < SSL_LIBRARY_VERSION_3_00x0300 ||
4228 defaultVersionRange.max < SSL_LIBRARY_VERSION_3_00x0300) {
4229 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
4230 return SECFailure;
4231 }
4232
4233 if (!strcmp(input, ":")) {
4234 /* special value, use default */
4235 *vrange = defaultVersionRange;
4236 return SECSuccess;
4237 }
4238
4239 colonPos = strchr(input, ':');
4240 if (!colonPos) {
4241 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
4242 return SECFailure;
4243 }
4244
4245 colonIndex = colonPos - input;
4246 maxStr = colonPos + 1;
4247
4248 if (!colonIndex) {
4249 /* colon was first character, min version is empty */
4250 vrange->min = defaultVersionRange.min;
4251 } else {
4252 PRUint16 version;
4253 /* colonIndex is equivalent to the length of the min version substring */
4254 if (SECU_GetSSLVersionFromName(input, colonIndex, &version) != SECSuccess) {
4255 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
4256 return SECFailure;
4257 }
4258
4259 vrange->min = version;
4260 }
4261
4262 if (!*maxStr) {
4263 vrange->max = defaultVersionRange.max;
4264 } else {
4265 PRUint16 version;
4266 /* if max version is empty, then maxStr points to the string terminator */
4267 if (SECU_GetSSLVersionFromName(maxStr, strlen(maxStr), &version) !=
4268 SECSuccess) {
4269 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
4270 return SECFailure;
4271 }
4272
4273 vrange->max = version;
4274 }
4275
4276 if (vrange->min > vrange->max) {
4277 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
4278 return SECFailure;
4279 }
4280
4281 return SECSuccess;
4282}
4283
4284#define NAME_AND_LEN(s)sizeof(s) - 1, s sizeof(s) - 1, s
4285static const struct SSLNamedGroupString {
4286 int len;
4287 char *name;
4288 SSLNamedGroup grp;
4289} sslNamedGroupStringArray[] = {
4290 { NAME_AND_LEN("P256")sizeof("P256") - 1, "P256", ssl_grp_ec_secp256r1 },
4291 { NAME_AND_LEN("P384")sizeof("P384") - 1, "P384", ssl_grp_ec_secp384r1 },
4292 { NAME_AND_LEN("P521")sizeof("P521") - 1, "P521", ssl_grp_ec_secp521r1 },
4293 { NAME_AND_LEN("x25519")sizeof("x25519") - 1, "x25519", ssl_grp_ec_curve25519 },
4294 { NAME_AND_LEN("FF2048")sizeof("FF2048") - 1, "FF2048", ssl_grp_ffdhe_2048 },
4295 { NAME_AND_LEN("FF3072")sizeof("FF3072") - 1, "FF3072", ssl_grp_ffdhe_3072 },
4296 { NAME_AND_LEN("FF4096")sizeof("FF4096") - 1, "FF4096", ssl_grp_ffdhe_4096 },
4297 { NAME_AND_LEN("FF6144")sizeof("FF6144") - 1, "FF6144", ssl_grp_ffdhe_6144 },
4298 { NAME_AND_LEN("FF8192")sizeof("FF8192") - 1, "FF8192", ssl_grp_ffdhe_8192 },
4299 { NAME_AND_LEN("x25519mlkem768")sizeof("x25519mlkem768") - 1, "x25519mlkem768", ssl_grp_kem_mlkem768x25519 },
4300 { NAME_AND_LEN("secp256r1mlkem768")sizeof("secp256r1mlkem768") - 1, "secp256r1mlkem768", ssl_grp_kem_secp256r1mlkem768 },
4301 { NAME_AND_LEN("secp384r1mlkem1024")sizeof("secp384r1mlkem1024") - 1, "secp384r1mlkem1024", ssl_grp_kem_secp384r1mlkem1024 },
4302 // keep for compatibility
4303 { NAME_AND_LEN("mlkem768x25519")sizeof("mlkem768x25519") - 1, "mlkem768x25519", ssl_grp_kem_mlkem768x25519 },
4304};
4305
4306static const size_t sslNamedGroupStringLen = PR_ARRAY_SIZE(sslNamedGroupStringArray)(sizeof(sslNamedGroupStringArray) / sizeof((sslNamedGroupStringArray
)[0]))
;
4307
4308static SSLNamedGroup
4309groupNameToNamedGroup(char *name)
4310{
4311 int len = PL_strlen(name);
4312 int i;
4313
4314 for (i = 0; i < sslNamedGroupStringLen; i++) {
4315 const struct SSLNamedGroupString *ngs = &sslNamedGroupStringArray[i];
4316 if (len == ngs->len) {
4317 if (!strncmp(name, ngs->name, len)) {
4318 return ngs->grp;
4319 }
4320 }
4321 }
4322 return ssl_grp_none;
4323}
4324
4325static SECStatus
4326countItems(const char *arg, unsigned int *numItems)
4327{
4328 char *str = PORT_StrdupPORT_Strdup_Util(arg);
4329 if (!str) {
4330 return SECFailure;
4331 }
4332 char *p = strtok(str, ",");
4333 while (p) {
4334 ++(*numItems);
4335 p = strtok(NULL((void*)0), ",");
4336 }
4337 PORT_FreePORT_Free_Util(str);
4338 str = NULL((void*)0);
4339 return SECSuccess;
4340}
4341
4342SECStatus
4343parseGroupList(const char *arg, SSLNamedGroup **enabledGroups,
4344 unsigned int *enabledGroupsCount)
4345{
4346 SSLNamedGroup *groups;
4347 char *str;
4348 char *p;
4349 unsigned int numValues = 0;
4350 unsigned int count = 0;
4351
4352 if (countItems(arg, &numValues) != SECSuccess) {
4353 return SECFailure;
4354 }
4355 groups = PORT_ZNewArray(SSLNamedGroup, numValues)(SSLNamedGroup *)PORT_ZAlloc_Util(sizeof(SSLNamedGroup) * (numValues
))
;
4356 if (!groups) {
4357 return SECFailure;
4358 }
4359
4360 /* Get group names. */
4361 str = PORT_StrdupPORT_Strdup_Util(arg);
4362 if (!str) {
4363 goto done;
4364 }
4365 p = strtok(str, ",");
4366 while (p) {
4367 SSLNamedGroup group = groupNameToNamedGroup(p);
4368 if (group == ssl_grp_none) {
4369 count = 0;
4370 goto done;
4371 }
4372 groups[count++] = group;
4373 p = strtok(NULL((void*)0), ",");
4374 }
4375
4376done:
4377 PORT_FreePORT_Free_Util(str);
4378 if (!count) {
4379 PORT_FreePORT_Free_Util(groups);
4380 return SECFailure;
4381 }
4382
4383 *enabledGroupsCount = count;
4384 *enabledGroups = groups;
4385 return SECSuccess;
4386}
4387
4388const char *
4389SECU_NamedGroupToGroupName(SSLNamedGroup grp)
4390{
4391 int i;
4392 static char unknownBuf[32];
4393
4394 if (grp == ssl_grp_none) {
4395 return "None";
4396 }
4397
4398 for (i = 0; i < sslNamedGroupStringLen; i++) {
4399 const struct SSLNamedGroupString *ngs = &sslNamedGroupStringArray[i];
4400 if (grp == ngs->grp) {
4401 return ngs->name;
4402 }
4403 }
4404 snprintf(unknownBuf, sizeof(unknownBuf), "Unknown %04x\n", grp);
4405
4406 return unknownBuf;
4407}
4408
4409const char *
4410SECU_NamedGroupGetNextName(size_t i)
4411{
4412 if (i >= sslNamedGroupStringLen) {
4413 return NULL((void*)0);
4414 }
4415 return sslNamedGroupStringArray[i].name;
4416}
4417
4418#define MAKE_SCHEME(x){ sizeof("x") - 1, "x", ssl_sig_x } \
4419 { \
4420 sizeof(#x) - 1, #x, ssl_sig_##x \
4421 }
4422static const struct SSLSignatureSchemeString {
4423 int len;
4424 char *name;
4425 SSLSignatureScheme scheme;
4426} sslSignatureSchemeStringArray[] = {
4427 MAKE_SCHEME(rsa_pkcs1_sha1){ sizeof("rsa_pkcs1_sha1") - 1, "rsa_pkcs1_sha1", ssl_sig_rsa_pkcs1_sha1
}
,
4428 MAKE_SCHEME(rsa_pkcs1_sha256){ sizeof("rsa_pkcs1_sha256") - 1, "rsa_pkcs1_sha256", ssl_sig_rsa_pkcs1_sha256
}
,
4429 MAKE_SCHEME(rsa_pkcs1_sha384){ sizeof("rsa_pkcs1_sha384") - 1, "rsa_pkcs1_sha384", ssl_sig_rsa_pkcs1_sha384
}
,
4430 MAKE_SCHEME(rsa_pkcs1_sha512){ sizeof("rsa_pkcs1_sha512") - 1, "rsa_pkcs1_sha512", ssl_sig_rsa_pkcs1_sha512
}
,
4431 MAKE_SCHEME(ecdsa_sha1){ sizeof("ecdsa_sha1") - 1, "ecdsa_sha1", ssl_sig_ecdsa_sha1 },
4432 MAKE_SCHEME(ecdsa_secp256r1_sha256){ sizeof("ecdsa_secp256r1_sha256") - 1, "ecdsa_secp256r1_sha256"
, ssl_sig_ecdsa_secp256r1_sha256 }
,
4433 MAKE_SCHEME(ecdsa_secp384r1_sha384){ sizeof("ecdsa_secp384r1_sha384") - 1, "ecdsa_secp384r1_sha384"
, ssl_sig_ecdsa_secp384r1_sha384 }
,
4434 MAKE_SCHEME(ecdsa_secp521r1_sha512){ sizeof("ecdsa_secp521r1_sha512") - 1, "ecdsa_secp521r1_sha512"
, ssl_sig_ecdsa_secp521r1_sha512 }
,
4435 MAKE_SCHEME(rsa_pss_rsae_sha256){ sizeof("rsa_pss_rsae_sha256") - 1, "rsa_pss_rsae_sha256", ssl_sig_rsa_pss_rsae_sha256
}
,
4436 MAKE_SCHEME(rsa_pss_rsae_sha384){ sizeof("rsa_pss_rsae_sha384") - 1, "rsa_pss_rsae_sha384", ssl_sig_rsa_pss_rsae_sha384
}
,
4437 MAKE_SCHEME(rsa_pss_rsae_sha512){ sizeof("rsa_pss_rsae_sha512") - 1, "rsa_pss_rsae_sha512", ssl_sig_rsa_pss_rsae_sha512
}
,
4438 MAKE_SCHEME(ed25519){ sizeof("ed25519") - 1, "ed25519", ssl_sig_ed25519 },
4439 MAKE_SCHEME(ed448){ sizeof("ed448") - 1, "ed448", ssl_sig_ed448 },
4440 MAKE_SCHEME(rsa_pss_pss_sha256){ sizeof("rsa_pss_pss_sha256") - 1, "rsa_pss_pss_sha256", ssl_sig_rsa_pss_pss_sha256
}
,
4441 MAKE_SCHEME(rsa_pss_pss_sha384){ sizeof("rsa_pss_pss_sha384") - 1, "rsa_pss_pss_sha384", ssl_sig_rsa_pss_pss_sha384
}
,
4442 MAKE_SCHEME(rsa_pss_pss_sha512){ sizeof("rsa_pss_pss_sha512") - 1, "rsa_pss_pss_sha512", ssl_sig_rsa_pss_pss_sha512
}
,
4443 MAKE_SCHEME(dsa_sha1){ sizeof("dsa_sha1") - 1, "dsa_sha1", ssl_sig_dsa_sha1 },
4444 MAKE_SCHEME(dsa_sha256){ sizeof("dsa_sha256") - 1, "dsa_sha256", ssl_sig_dsa_sha256 },
4445 MAKE_SCHEME(dsa_sha384){ sizeof("dsa_sha384") - 1, "dsa_sha384", ssl_sig_dsa_sha384 },
4446 MAKE_SCHEME(dsa_sha512){ sizeof("dsa_sha512") - 1, "dsa_sha512", ssl_sig_dsa_sha512 },
4447 MAKE_SCHEME(mldsa44){ sizeof("mldsa44") - 1, "mldsa44", ssl_sig_mldsa44 },
4448 MAKE_SCHEME(mldsa65){ sizeof("mldsa65") - 1, "mldsa65", ssl_sig_mldsa65 },
4449 MAKE_SCHEME(mldsa87){ sizeof("mldsa87") - 1, "mldsa87", ssl_sig_mldsa87 },
4450};
4451
4452static const size_t sslSignatureSchemeStringLen =
4453 PR_ARRAY_SIZE(sslSignatureSchemeStringArray)(sizeof(sslSignatureSchemeStringArray) / sizeof((sslSignatureSchemeStringArray
)[0]))
;
4454
4455const char *
4456SECU_SignatureSchemeGetNextScheme(size_t i)
4457{
4458 if (i >= sslSignatureSchemeStringLen) {
4459 return NULL((void*)0);
4460 }
4461 return sslSignatureSchemeStringArray[i].name;
4462}
4463
4464const char *
4465SECU_SignatureSchemeName(SSLSignatureScheme scheme)
4466{
4467 int i;
4468 static char unknownBuf[32];
4469
4470 if (scheme == ssl_sig_none) {
4471 return "None";
4472 }
4473
4474 for (i = 0; i < sslSignatureSchemeStringLen; i++) {
4475 const struct SSLSignatureSchemeString *schemp =
4476 &sslSignatureSchemeStringArray[i];
4477 if (scheme == schemp->scheme) {
4478 return schemp->name;
4479 }
4480 }
4481
4482 /* we don't include ssl_sig_rsa_pks1_sha1md5 in our list because we
4483 * don't want to select it from the command line, but if you are using
4484 * ssl3, it's possible for this signataure scheme to pop out, so we
4485 * want output it. The name is the same value tstclnt used for this
4486 * scheme originally */
4487 if (scheme == ssl_sig_rsa_pkcs1_sha1md5) {
4488 return "RSA PKCS#1 SHA1+MD5";
4489 }
4490
4491 snprintf(unknownBuf, sizeof(unknownBuf), "Unknown %04x\n", scheme);
4492
4493 return unknownBuf;
4494}
4495
4496SSLSignatureScheme
4497schemeNameToScheme(const char *name)
4498{
4499 int len = PL_strlen(name);
4500 int i;
4501
4502 for (i = 0; i < sslSignatureSchemeStringLen; i++) {
4503 const struct SSLSignatureSchemeString *schemp =
4504 &sslSignatureSchemeStringArray[i];
4505 if (len == schemp->len) {
4506 if (!strncmp(name, schemp->name, len)) {
4507 return schemp->scheme;
4508 }
4509 }
4510 }
4511 return ssl_sig_none;
4512}
4513
4514SECStatus
4515parseSigSchemeList(const char *arg, const SSLSignatureScheme **enabledSigSchemes,
4516 unsigned int *enabledSigSchemeCount)
4517{
4518 SSLSignatureScheme *schemes;
4519 unsigned int numValues = 0;
4520 unsigned int count = 0;
4521
4522 if (countItems(arg, &numValues) != SECSuccess) {
4523 return SECFailure;
4524 }
4525 schemes = PORT_ZNewArray(SSLSignatureScheme, numValues)(SSLSignatureScheme *)PORT_ZAlloc_Util(sizeof(SSLSignatureScheme
) * (numValues))
;
4526 if (!schemes) {
4527 return SECFailure;
4528 }
4529
4530 /* Get group names. */
4531 char *str = PORT_StrdupPORT_Strdup_Util(arg);
4532 if (!str) {
4533 goto done;
4534 }
4535 char *p = strtok(str, ",");
4536 while (p) {
4537 SSLSignatureScheme scheme = schemeNameToScheme(p);
4538 if (scheme == ssl_sig_none) {
4539 count = 0;
4540 goto done;
4541 }
4542 schemes[count++] = scheme;
4543 p = strtok(NULL((void*)0), ",");
4544 }
4545
4546done:
4547 PORT_FreePORT_Free_Util(str);
4548 if (!count) {
4549 PORT_FreePORT_Free_Util(schemes);
4550 return SECFailure;
4551 }
4552
4553 *enabledSigSchemeCount = count;
4554 *enabledSigSchemes = schemes;
4555 return SECSuccess;
4556}
4557
4558/* Parse the exporter spec in the form: LABEL[:OUTPUT-LENGTH[:CONTEXT]] */
4559static SECStatus
4560parseExporter(const char *arg,
4561 secuExporter *exporter)
4562{
4563 SECStatus rv = SECSuccess;
4564
4565 char *str = PORT_StrdupPORT_Strdup_Util(arg);
4566 if (!str) {
4567 rv = SECFailure;
4568 goto done;
4569 }
4570
4571 char *labelEnd = strchr(str, ':');
4572 if (labelEnd) {
4573 *labelEnd = '\0';
4574 labelEnd++;
4575
4576 /* To extract CONTEXT, first skip OUTPUT-LENGTH */
4577 char *outputEnd = strchr(labelEnd, ':');
4578 if (outputEnd) {
4579 *outputEnd = '\0';
4580 outputEnd++;
4581
4582 exporter->hasContext = PR_TRUE1;
4583 exporter->context.data = (unsigned char *)PORT_StrdupPORT_Strdup_Util(outputEnd);
4584 exporter->context.len = strlen(outputEnd);
4585 if (PORT_StrncasecmpPL_strncasecmp((char *)exporter->context.data, "0x", 2) == 0) {
4586 rv = SECU_SECItemHexStringToBinary(&exporter->context);
4587 if (rv != SECSuccess) {
4588 goto done;
4589 }
4590 }
4591 }
4592 }
4593
4594 if (labelEnd && *labelEnd != '\0') {
4595 long int outputLength = strtol(labelEnd, NULL((void*)0), 10);
4596 if (!(outputLength > 0 && outputLength <= UINT_MAX(2147483647 *2U +1U))) {
4597 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
4598 rv = SECFailure;
4599 goto done;
4600 }
4601 exporter->outputLength = outputLength;
4602 } else {
4603 exporter->outputLength = 20;
4604 }
4605
4606 char *label = PORT_StrdupPORT_Strdup_Util(str);
4607 exporter->label.data = (unsigned char *)label;
4608 exporter->label.len = strlen(label);
4609 if (PORT_StrncasecmpPL_strncasecmp((char *)exporter->label.data, "0x", 2) == 0) {
4610 rv = SECU_SECItemHexStringToBinary(&exporter->label);
4611 if (rv != SECSuccess) {
4612 goto done;
4613 }
4614 }
4615
4616done:
4617 PORT_FreePORT_Free_Util(str);
4618
4619 return rv;
4620}
4621
4622SECStatus
4623parseExporters(const char *arg,
4624 const secuExporter **enabledExporters,
4625 unsigned int *enabledExporterCount)
4626{
4627 secuExporter *exporters;
4628 unsigned int numValues = 0;
4629 unsigned int count = 0;
4630
4631 if (countItems(arg, &numValues) != SECSuccess) {
4632 return SECFailure;
4633 }
4634 exporters = PORT_ZNewArray(secuExporter, numValues)(secuExporter *)PORT_ZAlloc_Util(sizeof(secuExporter) * (numValues
))
;
4635 if (!exporters) {
4636 return SECFailure;
4637 }
4638
4639 /* Get exporter definitions. */
4640 char *str = PORT_StrdupPORT_Strdup_Util(arg);
4641 if (!str) {
4642 goto done;
4643 }
4644 char *p = strtok(str, ",");
4645 while (p) {
4646 SECStatus rv = parseExporter(p, &exporters[count++]);
4647 if (rv != SECSuccess) {
4648 count = 0;
4649 goto done;
4650 }
4651 p = strtok(NULL((void*)0), ",");
4652 }
4653
4654done:
4655 PORT_FreePORT_Free_Util(str);
4656 if (!count) {
4657 PORT_FreePORT_Free_Util(exporters);
4658 return SECFailure;
4659 }
4660
4661 *enabledExporterCount = count;
4662 *enabledExporters = exporters;
4663 return SECSuccess;
4664}
4665
4666static SECStatus
4667exportKeyingMaterial(PRFileDesc *fd, const secuExporter *exporter)
4668{
4669 SECStatus rv = SECSuccess;
4670 unsigned char *out = PORT_AllocPORT_Alloc_Util(exporter->outputLength);
4671
4672 if (!out) {
4673 fprintf(stderrstderr, "Unable to allocate buffer for keying material\n");
4674 return SECFailure;
4675 }
4676 rv = SSL_ExportKeyingMaterial(fd,
4677 (char *)exporter->label.data,
4678 exporter->label.len,
4679 exporter->hasContext,
4680 exporter->context.data,
4681 exporter->context.len,
4682 out,
4683 exporter->outputLength);
4684 if (rv != SECSuccess) {
4685 goto done;
4686 }
4687 fprintf(stdoutstdout, "Exported Keying Material:\n");
4688 secu_PrintRawString(stdoutstdout, (SECItem *)&exporter->label, "Label", 1);
4689 if (exporter->hasContext) {
4690 SECU_PrintAsHex(stdoutstdout, &exporter->context, "Context", 1);
4691 }
4692 SECU_Indent(stdoutstdout, 1);
4693 fprintf(stdoutstdout, "Length: %u\n", exporter->outputLength);
4694 SECItem temp = { siBuffer, out, exporter->outputLength };
4695 SECU_PrintAsHex(stdoutstdout, &temp, "Keying Material", 1);
4696
4697done:
4698 PORT_FreePORT_Free_Util(out);
4699 return rv;
4700}
4701
4702SECStatus
4703exportKeyingMaterials(PRFileDesc *fd,
4704 const secuExporter *exporters,
4705 unsigned int exporterCount)
4706{
4707 unsigned int i;
4708
4709 for (i = 0; i < exporterCount; i++) {
4710 SECStatus rv = exportKeyingMaterial(fd, &exporters[i]);
4711 if (rv != SECSuccess) {
4712 return rv;
4713 }
4714 }
4715
4716 return SECSuccess;
4717}
4718
4719SECStatus
4720readPSK(const char *arg, SECItem *psk, SECItem *label)
4721{
4722 SECStatus rv = SECFailure;
4723 char *str = PORT_StrdupPORT_Strdup_Util(arg);
4724 if (!str) {
4725 goto cleanup;
4726 }
4727
4728 char *pskBytes = strtok(str, ":");
4729 if (!pskBytes) {
4730 goto cleanup;
4731 }
4732 if (PORT_StrncasecmpPL_strncasecmp(pskBytes, "0x", 2) != 0) {
4733 goto cleanup;
4734 }
4735
4736 psk = SECU_HexString2SECItem(NULL((void*)0), psk, &pskBytes[2]);
4737 if (!psk || !psk->data || psk->len != strlen(&str[2]) / 2) {
4738 goto cleanup;
4739 }
4740
4741 SECItem labelItem = { siBuffer, NULL((void*)0), 0 };
4742 char *inLabel = strtok(NULL((void*)0), ":");
4743 if (inLabel) {
4744 labelItem.data = (unsigned char *)PORT_StrdupPORT_Strdup_Util(inLabel);
4745 if (!labelItem.data) {
4746 goto cleanup;
4747 }
4748 labelItem.len = strlen(inLabel);
4749
4750 if (PORT_StrncasecmpPL_strncasecmp(inLabel, "0x", 2) == 0) {
4751 rv = SECU_SECItemHexStringToBinary(&labelItem);
4752 if (rv != SECSuccess) {
4753 SECITEM_FreeItemSECITEM_FreeItem_Util(&labelItem, PR_FALSE0);
4754 goto cleanup;
4755 }
4756 }
4757 rv = SECSuccess;
4758 } else {
4759 PRUint8 defaultLabel[] = { 'C', 'l', 'i', 'e', 'n', 't', '_',
4760 'i', 'd', 'e', 'n', 't', 'i', 't', 'y' };
4761 SECItem src = { siBuffer, defaultLabel, sizeof(defaultLabel) };
4762 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(NULL((void*)0), &labelItem, &src);
4763 }
4764 if (rv == SECSuccess) {
4765 *label = labelItem;
4766 }
4767
4768cleanup:
4769 PORT_FreePORT_Free_Util(str);
4770 return rv;
4771}
4772
4773static SECStatus
4774secu_PrintPKCS12DigestInfo(FILE *out, const SECItem *t, char *m, int level)
4775{
4776 SECItem my = *t;
4777 SECItem rawDigestAlgID;
4778 SECItem digestData;
4779 SECStatus rv;
4780 PLArenaPool *arena;
4781 SECAlgorithmID digestAlgID;
4782 char *mAlgID = NULL((void*)0);
4783 char *mDigest = NULL((void*)0);
4784
4785 /* strip the outer sequence */
4786 if ((my.data[0] != (SEC_ASN1_CONSTRUCTED0x20 | SEC_ASN1_SEQUENCE0x10)) ||
4787 SECSuccess != SECU_StripTagAndLength(&my)) {
4788 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
4789 return SECFailure;
4790 }
4791
4792 /* get the algorithm ID */
4793 if (SECSuccess != SECU_ExtractBERAndStep(&my, &rawDigestAlgID)) {
4794 return SECFailure;
4795 }
4796 arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
4797 if (arena == NULL((void*)0)) {
4798 return SECFailure;
4799 }
4800#define DIGEST_ALGID_STRING"Digest Algorithm ID" "Digest Algorithm ID"
4801 if (m)
4802 mAlgID = PR_smprintf("%s " DIGEST_ALGID_STRING"Digest Algorithm ID", m);
4803 rv = SEC_QuickDERDecodeItemSEC_QuickDERDecodeItem_Util(arena, &digestAlgID,
4804 SEC_ASN1_GET(SECOID_AlgorithmIDTemplate)SECOID_AlgorithmIDTemplate_Util,
4805 &rawDigestAlgID);
4806 if (rv == SECSuccess) {
4807 SECU_PrintAlgorithmID(out, &digestAlgID,
4808 mAlgID ? mAlgID : DIGEST_ALGID_STRING"Digest Algorithm ID", level);
4809 }
4810 if (mAlgID)
4811 PR_smprintf_free(mAlgID);
4812 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
4813 if (rv != SECSuccess) {
4814 return rv;
4815 }
4816
4817 /* get the mac data */
4818 if (SECSuccess != SECU_ExtractBERAndStep(&my, &digestData)) {
4819 return SECFailure;
4820 }
4821 if ((digestData.data[0] & SEC_ASN1_TAGNUM_MASK0x1f) != SEC_ASN1_OCTET_STRING0x04) {
4822 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
4823 return SECFailure;
4824 }
4825#define DIGEST_STRING"Digest" "Digest"
4826 if (m)
4827 mDigest = PR_smprintf("%s " DIGEST_STRING"Digest", m);
4828 secu_PrintOctetString(out, &digestData,
4829 mDigest ? mDigest : DIGEST_STRING"Digest", level);
4830 if (mDigest)
4831 PR_smprintf_free(mDigest);
4832 return SECSuccess;
4833}
4834
4835static SECStatus
4836secu_PrintPKCS12MacData(FILE *out, const SECItem *t, char *m, int level)
4837{
4838 SECItem my = *t;
4839 SECItem hash;
4840 SECItem salt;
4841
4842 if (m) {
4843 SECU_Indent(out, level);
4844 fprintf(out, "%s: \n", m);
4845 level++;
4846 }
4847
4848 /* strip the outer sequence */
4849 if ((my.data[0] != (SEC_ASN1_CONSTRUCTED0x20 | SEC_ASN1_SEQUENCE0x10)) ||
4850 SECSuccess != SECU_StripTagAndLength(&my)) {
4851 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
4852 return SECFailure;
4853 }
4854
4855 if (SECSuccess != SECU_ExtractBERAndStep(&my, &hash)) {
4856 return SECFailure;
4857 }
4858 if (SECSuccess != secu_PrintPKCS12DigestInfo(out, &hash, "Mac", level)) {
4859 return SECFailure;
4860 }
4861
4862 /* handle the salt */
4863 if (SECSuccess != SECU_ExtractBERAndStep(&my, &salt)) {
4864 return SECFailure;
4865 ;
4866 }
4867 if ((salt.data[0] & SEC_ASN1_TAGNUM_MASK0x1f) != SEC_ASN1_OCTET_STRING0x04) {
4868 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
4869 return SECFailure;
4870 }
4871 secu_PrintOctetString(out, &salt, "Mac Salt", level);
4872
4873 if (my.len &&
4874 ((my.data[0] & SEC_ASN1_TAGNUM_MASK0x1f) == SEC_ASN1_INTEGER0x02)) {
4875 SECItem iterator;
4876 if (SECSuccess != SECU_ExtractBERAndStep(&my, &iterator)) {
4877 return SECFailure;
4878 }
4879 SECU_PrintEncodedInteger(out, &iterator, "Iterations", level);
4880 }
4881 return SECSuccess;
4882}
4883
4884SECStatus
4885SECU_PrintPKCS12(FILE *out, const SECItem *t, char *m, int level)
4886{
4887 SECItem my = *t;
4888 SECItem authSafe;
4889 SECItem macData;
4890
4891 SECU_Indent(out, level);
4892 fprintf(out, "%s:\n", m);
4893 level++;
4894
4895 /* strip the outer sequence */
4896 if ((my.data[0] != (SEC_ASN1_CONSTRUCTED0x20 | SEC_ASN1_SEQUENCE0x10)) ||
4897 SECSuccess != SECU_StripTagAndLength(&my)) {
4898 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
4899 return SECFailure;
4900 }
4901 /* print and remove the optional version number */
4902 if (my.len && ((my.data[0] & SEC_ASN1_TAGNUM_MASK0x1f) == SEC_ASN1_INTEGER0x02)) {
4903 SECItem version;
4904
4905 if (SECSuccess != SECU_ExtractBERAndStep(&my, &version)) {
4906 return SECFailure;
4907 }
4908 SECU_PrintEncodedInteger(out, &version, "Version", level);
4909 }
4910
4911 /* print the authSafe */
4912 if (SECSuccess != SECU_ExtractBERAndStep(&my, &authSafe)) {
4913 return SECFailure;
4914 }
4915 if (SECSuccess != secu_PrintDERPKCS7ContentInfo(out, &authSafe,
4916 secuPKCS7PKCS12AuthSafe,
4917 "AuthSafe", level)) {
4918 return SECFailure;
4919 }
4920
4921 /* print the mac data (optional) */
4922 if (!my.len) {
4923 return SECSuccess;
4924 }
4925 if (SECSuccess != SECU_ExtractBERAndStep(&my, &macData)) {
4926 return SECFailure;
4927 }
4928 if (SECSuccess != secu_PrintPKCS12MacData(out, &macData,
4929 "Mac Data", level)) {
4930 return SECFailure;
4931 }
4932
4933 if (my.len) {
4934 fprintf(out, "Unknown extra data found \n");
4935 }
4936 return SECSuccess;
4937}