Bug Summary

File:root/firefox-clang/security/nss/cmd/lib/secutil.c
Warning:line 3810, 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-09-01-224014-2642839-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_kyber768_round3:
1547 SECU_Indent(out, level);
1548 fprintf(out, "Parameter Set: KYBER-768-ROUND3\n");
1549 break;
1550 case params_kyber768_round3_test_mode:
1551 SECU_Indent(out, level);
1552 fprintf(out, "Parameter Set (test mode): KYBER-768-ROUND3\n");
1553 break;
1554 case params_ml_kem768:
1555 SECU_PrintOidTag(out, SEC_OID_ML_KEM_768, "Parameter Set", level + 1);
1556 break;
1557 case params_ml_kem768_test_mode:
1558 SECU_PrintOidTag(out, SEC_OID_ML_KEM_768, "Parameter Set (test mode)",
1559 level + 1);
1560 break;
1561 case params_ml_kem1024:
1562 SECU_PrintOidTag(out, SEC_OID_ML_KEM_1024, "Parameter Set", level + 1);
1563 break;
1564 case params_ml_kem1024_test_mode:
1565 SECU_PrintOidTag(out, SEC_OID_ML_KEM_1024, "Parameter Set (test mode)",
1566 level + 1);
1567 break;
1568 case params_ml_kem512:
1569 SECU_PrintOidTag(out, SEC_OID_ML_KEM_512, "Parameter Set", level + 1);
1570 break;
1571 case params_kyber_invalid:
1572 SECU_Indent(out, level);
1573 fprintf(out, "Parameter Set: Invalid Params\n");
1574 break;
1575 default:
1576 SECU_Indent(out, level);
1577 fprintf(out, "Parameter Set: Invalid Params %d\n", pk->u.kyber.params);
1578 break;
1579 }
1580 SECU_PrintInteger(out, &pk->u.kyber.publicValue, "PublicValue", level + 1);
1581}
1582
1583static void
1584secu_PrintSubjectPublicKeyInfo(FILE *out, PLArenaPool *arena,
1585 CERTSubjectPublicKeyInfo *i, char *msg, int level)
1586{
1587 SECKEYPublicKey *pk;
1588
1589 SECU_Indent(out, level);
1590 fprintf(out, "%s:\n", msg);
1591 SECU_PrintAlgorithmID(out, &i->algorithm, "Public Key Algorithm", level + 1);
1592
1593 pk = SECKEY_ExtractPublicKey(i);
1594 if (pk) {
1595 switch (pk->keyType) {
1596 case rsaKey:
1597 SECU_PrintRSAPublicKey(out, pk, "RSA Public Key", level + 1);
1598 break;
1599
1600 case dsaKey:
1601 SECU_PrintDSAPublicKey(out, pk, "DSA Public Key", level + 1);
1602 break;
1603
1604 case ecKey:
1605 secu_PrintECPublicKey(out, pk, "EC Public Key", level + 1);
1606 break;
1607
1608 case mldsaKey:
1609 SECU_PrintMLDSAPublicKey(out, pk, "ML-DSA Public Key", level + 1);
1610 break;
1611
1612 case kyberKey:
1613 SECU_PrintMLKEMPublicKey(out, pk, "ML-KEM Public Key", level + 1);
1614 break;
1615
1616 case dhKey:
1617 case fortezzaKey:
1618 case keaKey:
1619 SECU_Indent(out, level);
1620 fprintf(out, "unable to format this SPKI algorithm type\n");
1621 goto loser;
1622 default:
1623 SECU_Indent(out, level);
1624 fprintf(out, "unknown SPKI algorithm type %d\n", pk->keyType);
1625 goto loser;
1626 }
1627 PORT_FreeArenaPORT_FreeArena_Util(pk->arena, PR_FALSE0);
1628 } else {
1629 SECU_PrintErrMsg(out, level, "Error", "Parsing public key");
1630 loser:
1631 if (i->subjectPublicKey.data) {
1632 SECItem tmp = i->subjectPublicKey;
1633 DER_ConvertBitString(&tmp){ (&tmp)->len = ((&tmp)->len + 7) >> 3; };
1634 SECU_PrintAny(out, &tmp, "Raw", level);
1635 }
1636 }
1637}
1638
1639static void
1640printStringWithoutCRLF(FILE *out, const char *str)
1641{
1642 const char *c = str;
1643 while (*c) {
1644 if (*c != '\r' && *c != '\n') {
1645 fputc(*c, out);
1646 }
1647 ++c;
1648 }
1649}
1650
1651int
1652SECU_PrintDumpDerIssuerAndSerial(FILE *out, const SECItem *der, const char *m,
1653 int level)
1654{
1655 PLArenaPool *arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
1656 CERTCertificate *c;
1657 int rv = SEC_ERROR_NO_MEMORY;
1658 char *derIssuerB64;
1659 char *derSerialB64;
1660
1661 if (!arena)
1662 return rv;
1663
1664 /* Decode certificate */
1665 c = PORT_ArenaZNew(arena, CERTCertificate)(CERTCertificate *)PORT_ArenaZAlloc_Util(arena, sizeof(CERTCertificate
))
;
1666 if (!c)
1667 goto loser;
1668 c->arena = arena;
1669 rv = SEC_ASN1DecodeItemSEC_ASN1DecodeItem_Util(arena, c,
1670 SEC_ASN1_GET(CERT_CertificateTemplate)CERT_CertificateTemplate, der);
1671 if (rv) {
1672 SECU_PrintErrMsg(out, 0, "Error", "Parsing extension");
1673 goto loser;
1674 }
1675
1676 SECU_PrintName(out, &c->subject, "Subject", 0);
1677 if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
1678 SECU_Newline(out);
1679 SECU_PrintName(out, &c->issuer, "Issuer", 0);
1680 if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
1681 SECU_Newline(out);
1682 SECU_PrintInteger(out, &c->serialNumber, "Serial Number", 0);
1683
1684 derIssuerB64 = BTOA_ConvertItemToAsciiBTOA_ConvertItemToAscii_Util(&c->derIssuer);
1685 derSerialB64 = BTOA_ConvertItemToAsciiBTOA_ConvertItemToAscii_Util(&c->serialNumber);
1686
1687 fprintf(out, "Issuer DER Base64:\n");
1688 if (SECU_GetWrapEnabled()) {
1689 fprintf(out, "%s\n", derIssuerB64);
1690 } else {
1691 printStringWithoutCRLF(out, derIssuerB64);
1692 fputs("\n", out);
1693 }
1694
1695 fprintf(out, "Serial DER Base64:\n");
1696 if (SECU_GetWrapEnabled()) {
1697 fprintf(out, "%s\n", derSerialB64);
1698 } else {
1699 printStringWithoutCRLF(out, derSerialB64);
1700 fputs("\n", out);
1701 }
1702
1703 PORT_FreePORT_Free_Util(derIssuerB64);
1704 PORT_FreePORT_Free_Util(derSerialB64);
1705
1706 fprintf(out, "Serial DER as C source: \n{ %d, \"", c->serialNumber.len);
1707
1708 {
1709 unsigned int i;
1710 for (i = 0; i < c->serialNumber.len; ++i) {
1711 unsigned char *chardata = (unsigned char *)(c->serialNumber.data);
1712 unsigned char ch = *(chardata + i);
1713
1714 fprintf(out, "\\x%02x", ch);
1715 }
1716 fprintf(out, "\" }\n");
1717 }
1718
1719loser:
1720 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
1721 return rv;
1722}
1723
1724static SECStatus
1725secu_PrintX509InvalidDate(FILE *out, SECItem *value, char *msg, int level)
1726{
1727 SECItem decodedValue;
1728 SECStatus rv;
1729 PRTime invalidTime;
1730 char *formattedTime = NULL((void*)0);
1731
1732 decodedValue.data = NULL((void*)0);
1733 rv = SEC_ASN1DecodeItemSEC_ASN1DecodeItem_Util(NULL((void*)0), &decodedValue,
1734 SEC_ASN1_GET(SEC_GeneralizedTimeTemplate)SEC_GeneralizedTimeTemplate_Util,
1735 value);
1736 if (rv == SECSuccess) {
1737 rv = DER_GeneralizedTimeToTimeDER_GeneralizedTimeToTime_Util(&invalidTime, &decodedValue);
1738 if (rv == SECSuccess) {
1739 formattedTime = CERT_GenTime2FormattedAsciiCERT_GenTime2FormattedAscii_Util(invalidTime, "%a %b %d %H:%M:%S %Y");
1740 SECU_Indent(out, level + 1);
1741 fprintf(out, "%s: %s\n", msg, formattedTime);
1742 PORT_FreePORT_Free_Util(formattedTime);
1743 }
1744 }
1745 PORT_FreePORT_Free_Util(decodedValue.data);
1746 return (rv);
1747}
1748
1749static SECStatus
1750PrintExtKeyUsageExtension(FILE *out, SECItem *value, char *msg, int level)
1751{
1752 CERTOidSequence *os;
1753 SECItem **op;
1754
1755 os = CERT_DecodeOidSequence(value);
1756 if ((CERTOidSequence *)NULL((void*)0) == os) {
1757 return SECFailure;
1758 }
1759
1760 for (op = os->oids; *op; op++) {
1761 SECU_PrintObjectID(out, *op, msg, level + 1);
1762 }
1763 CERT_DestroyOidSequence(os);
1764 return SECSuccess;
1765}
1766
1767static SECStatus
1768secu_PrintBasicConstraints(FILE *out, SECItem *value, char *msg, int level)
1769{
1770 CERTBasicConstraints constraints;
1771 SECStatus rv;
1772
1773 SECU_Indent(out, level);
1774 if (msg) {
1775 fprintf(out, "%s: ", msg);
1776 }
1777 rv = CERT_DecodeBasicConstraintValue(&constraints, value);
1778 if (rv == SECSuccess && constraints.isCA) {
1779 if (constraints.pathLenConstraint >= 0) {
1780 fprintf(out, "Is a CA with a maximum path length of %d.\n",
1781 constraints.pathLenConstraint);
1782 } else {
1783 fprintf(out, "Is a CA with no maximum path length.\n");
1784 }
1785 } else {
1786 fprintf(out, "Is not a CA.\n");
1787 }
1788 return SECSuccess;
1789}
1790
1791static const char *const nsTypeBits[] = {
1792 "SSL Client",
1793 "SSL Server",
1794 "S/MIME",
1795 "Object Signing",
1796 "Reserved",
1797 "SSL CA",
1798 "S/MIME CA",
1799 "ObjectSigning CA"
1800};
1801
1802/* NSCertType is merely a bit string whose bits are displayed symbolically */
1803static SECStatus
1804secu_PrintNSCertType(FILE *out, SECItem *value, char *msg, int level)
1805{
1806 int unused;
1807 int NS_Type;
1808 int i;
1809 int found = 0;
1810 SECItem my = *value;
1811
1812 if ((my.data[0] != SEC_ASN1_BIT_STRING0x03) ||
1813 SECSuccess != SECU_StripTagAndLength(&my)) {
1814 SECU_PrintAny(out, value, "Data", level);
1815 return SECSuccess;
1816 }
1817
1818 unused = (my.len == 2) ? (my.data[0] & 0x0f) : 0;
1819 NS_Type = my.data[1] & (0xff << unused);
1820
1821 SECU_Indent(out, level);
1822 if (msg) {
1823 fprintf(out, "%s: ", msg);
1824 } else {
1825 fprintf(out, "Netscape Certificate Type: ");
1826 }
1827 for (i = 0; i < 8; i++) {
1828 if ((0x80 >> i) & NS_Type) {
1829 fprintf(out, "%c%s", (found ? ',' : '<'), nsTypeBits[i]);
1830 found = 1;
1831 }
1832 }
1833 fprintf(out, (found ? ">\n" : "none\n"));
1834 return SECSuccess;
1835}
1836
1837static const char *const usageBits[] = {
1838 "Digital Signature", /* 0x80 */
1839 "Non-Repudiation", /* 0x40 */
1840 "Key Encipherment", /* 0x20 */
1841 "Data Encipherment", /* 0x10 */
1842 "Key Agreement", /* 0x08 */
1843 "Certificate Signing", /* 0x04 */
1844 "CRL Signing", /* 0x02 */
1845 "Encipher Only", /* 0x01 */
1846 "Decipher Only", /* 0x0080 */
1847 NULL((void*)0)
1848};
1849
1850/* X509KeyUsage is merely a bit string whose bits are displayed symbolically */
1851static void
1852secu_PrintX509KeyUsage(FILE *out, SECItem *value, char *msg, int level)
1853{
1854 int unused;
1855 int usage;
1856 int i;
1857 int found = 0;
1858 SECItem my = *value;
1859
1860 if ((my.data[0] != SEC_ASN1_BIT_STRING0x03) ||
1861 SECSuccess != SECU_StripTagAndLength(&my)) {
1862 SECU_PrintAny(out, value, "Data", level);
1863 return;
1864 }
1865
1866 unused = (my.len >= 2) ? (my.data[0] & 0x0f) : 0;
1867 usage = (my.len == 2) ? (my.data[1] & (0xff << unused)) << 8
1868 : (my.data[1] << 8) |
1869 (my.data[2] & (0xff << unused));
1870
1871 SECU_Indent(out, level);
1872 fprintf(out, "Usages: ");
1873 for (i = 0; usageBits[i]; i++) {
1874 if ((0x8000 >> i) & usage) {
1875 if (found)
1876 SECU_Indent(out, level + 2);
1877 fprintf(out, "%s\n", usageBits[i]);
1878 found = 1;
1879 }
1880 }
1881 if (!found) {
1882 fprintf(out, "(none)\n");
1883 }
1884}
1885
1886static void
1887secu_PrintIPAddress(FILE *out, SECItem *value, char *msg, int level)
1888{
1889 PRStatus st;
1890 PRNetAddr addr;
1891 char addrBuf[80];
1892
1893 memset(&addr, 0, sizeof addr);
1894 if (value->len == 4) {
1895 addr.inet.family = PR_AF_INET2;
1896 memcpy(&addr.inet.ip, value->data, value->len);
1897 } else if (value->len == 16) {
1898 addr.ipv6.family = PR_AF_INET610;
1899 memcpy(addr.ipv6.ip.pr_s6_addr_S6_un._S6_u8, value->data, value->len);
1900 if (PR_IsNetAddrType(&addr, PR_IpAddrV4Mapped)) {
1901 /* convert to IPv4. */
1902 addr.inet.family = PR_AF_INET2;
1903 memcpy(&addr.inet.ip, &addr.ipv6.ip.pr_s6_addr_S6_un._S6_u8[12], 4);
1904 memset(&addr.inet.pad[0], 0, sizeof addr.inet.pad);
1905 }
1906 } else {
1907 goto loser;
1908 }
1909
1910 st = PR_NetAddrToString(&addr, addrBuf, sizeof addrBuf);
1911 if (st == PR_SUCCESS) {
1912 SECU_Indent(out, level);
1913 fprintf(out, "%s: %s\n", msg, addrBuf);
1914 } else {
1915 loser:
1916 SECU_PrintAsHex(out, value, msg, level);
1917 }
1918}
1919
1920static void
1921secu_PrintGeneralName(FILE *out, CERTGeneralName *gname, char *msg, int level)
1922{
1923 char label[40];
1924 if (msg && msg[0]) {
1925 SECU_Indent(out, level++);
1926 fprintf(out, "%s: \n", msg);
1927 }
1928 switch (gname->type) {
1929 case certOtherName:
1930 SECU_PrintAny(out, &gname->name.OthName.name, "Other Name", level);
1931 SECU_PrintObjectID(out, &gname->name.OthName.oid, "OID", level + 1);
1932 break;
1933 case certDirectoryName:
1934 SECU_PrintName(out, &gname->name.directoryName, "Directory Name", level);
1935 break;
1936 case certRFC822Name:
1937 secu_PrintRawString(out, &gname->name.other, "RFC822 Name", level);
1938 break;
1939 case certDNSName:
1940 secu_PrintRawString(out, &gname->name.other, "DNS name", level);
1941 break;
1942 case certURI:
1943 secu_PrintRawString(out, &gname->name.other, "URI", level);
1944 break;
1945 case certIPAddress:
1946 secu_PrintIPAddress(out, &gname->name.other, "IP Address", level);
1947 break;
1948 case certRegisterID:
1949 SECU_PrintObjectID(out, &gname->name.other, "Registered ID", level);
1950 break;
1951 case certX400Address:
1952 SECU_PrintAny(out, &gname->name.other, "X400 Address", level);
1953 break;
1954 case certEDIPartyName:
1955 SECU_PrintAny(out, &gname->name.other, "EDI Party", level);
1956 break;
1957 default:
1958 PR_snprintf(label, sizeof label, "unknown type [%d]",
1959 (int)gname->type - 1);
1960 SECU_PrintAsHex(out, &gname->name.other, label, level);
1961 break;
1962 }
1963}
1964
1965static void
1966secu_PrintGeneralNames(FILE *out, CERTGeneralName *gname, char *msg, int level)
1967{
1968 CERTGeneralName *name = gname;
1969 do {
1970 secu_PrintGeneralName(out, name, msg, level);
1971 name = CERT_GetNextGeneralName(name);
1972 } while (name && name != gname);
1973}
1974
1975static void
1976secu_PrintAuthKeyIDExtension(FILE *out, SECItem *value, char *msg, int level)
1977{
1978 CERTAuthKeyID *kid = NULL((void*)0);
1979 PLArenaPool *pool = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
1980
1981 if (!pool) {
1982 SECU_PrintError("Error", "Allocating new ArenaPool");
1983 return;
1984 }
1985 kid = CERT_DecodeAuthKeyID(pool, value);
1986 if (!kid) {
1987 SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
1988 SECU_PrintAny(out, value, "Data", level);
1989 } else {
1990 int keyIDPresent = (kid->keyID.data && kid->keyID.len);
1991 int issuerPresent = kid->authCertIssuer != NULL((void*)0);
1992 int snPresent = (kid->authCertSerialNumber.data &&
1993 kid->authCertSerialNumber.len);
1994
1995 if (keyIDPresent)
1996 SECU_PrintAsHex(out, &kid->keyID, "Key ID", level);
1997 if (issuerPresent)
1998 secu_PrintGeneralName(out, kid->authCertIssuer, "Issuer", level);
1999 if (snPresent)
2000 SECU_PrintInteger(out, &kid->authCertSerialNumber,
2001 "Serial Number", level);
2002 }
2003 PORT_FreeArenaPORT_FreeArena_Util(pool, PR_FALSE0);
2004}
2005
2006static void
2007secu_PrintAltNameExtension(FILE *out, SECItem *value, char *msg, int level)
2008{
2009 CERTGeneralName *nameList;
2010 CERTGeneralName *current;
2011 PLArenaPool *pool = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
2012
2013 if (!pool) {
2014 SECU_PrintError("Error", "Allocating new ArenaPool");
2015 return;
2016 }
2017 nameList = current = CERT_DecodeAltNameExtension(pool, value);
2018 if (!current) {
2019 if (PORT_GetErrorPORT_GetError_Util() == SEC_ERROR_EXTENSION_NOT_FOUND) {
2020 /* Decoder found empty sequence, which is invalid. */
2021 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_EXTENSION_VALUE_INVALID);
2022 }
2023 SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
2024 SECU_PrintAny(out, value, "Data", level);
2025 } else {
2026 do {
2027 secu_PrintGeneralName(out, current, msg, level);
2028 current = CERT_GetNextGeneralName(current);
2029 } while (current != nameList);
2030 }
2031 PORT_FreeArenaPORT_FreeArena_Util(pool, PR_FALSE0);
2032}
2033
2034static void
2035secu_PrintCRLDistPtsExtension(FILE *out, SECItem *value, char *msg, int level)
2036{
2037 CERTCrlDistributionPoints *dPoints;
2038 PLArenaPool *pool = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
2039
2040 if (!pool) {
2041 SECU_PrintError("Error", "Allocating new ArenaPool");
2042 return;
2043 }
2044 dPoints = CERT_DecodeCRLDistributionPoints(pool, value);
2045 if (dPoints && dPoints->distPoints && dPoints->distPoints[0]) {
2046 CRLDistributionPoint **pPoints = dPoints->distPoints;
2047 CRLDistributionPoint *pPoint;
2048 while (NULL((void*)0) != (pPoint = *pPoints++)) {
2049 SECU_Indent(out, level);
2050 fputs("Distribution point:\n", out);
2051 if (pPoint->distPointType == generalName &&
2052 pPoint->distPoint.fullName != NULL((void*)0)) {
2053 secu_PrintGeneralNames(out, pPoint->distPoint.fullName, NULL((void*)0),
2054 level + 1);
2055 } else if (pPoint->distPointType == relativeDistinguishedName &&
2056 pPoint->distPoint.relativeName.avas) {
2057 SECU_PrintRDN(out, &pPoint->distPoint.relativeName, "RDN",
2058 level + 1);
2059 } else if (pPoint->derDistPoint.data) {
2060 SECU_PrintAny(out, &pPoint->derDistPoint, "Point", level + 1);
2061 }
2062 if (pPoint->reasons.data) {
2063 secu_PrintDecodedBitString(out, &pPoint->reasons, "Reasons",
2064 level + 1);
2065 }
2066 if (pPoint->crlIssuer) {
2067 secu_PrintGeneralName(out, pPoint->crlIssuer, "CRL issuer",
2068 level + 1);
2069 }
2070 }
2071 } else {
2072 SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
2073 SECU_PrintAny(out, value, "Data", level);
2074 }
2075 PORT_FreeArenaPORT_FreeArena_Util(pool, PR_FALSE0);
2076}
2077
2078static void
2079secu_PrintNameConstraintSubtree(FILE *out, CERTNameConstraint *value,
2080 char *msg, int level)
2081{
2082 CERTNameConstraint *head = value;
2083 SECU_Indent(out, level);
2084 fprintf(out, "%s Subtree:\n", msg);
2085 level++;
2086 do {
2087 secu_PrintGeneralName(out, &value->name, NULL((void*)0), level);
2088 if (value->min.data)
2089 SECU_PrintInteger(out, &value->min, "Minimum", level + 1);
2090 if (value->max.data)
2091 SECU_PrintInteger(out, &value->max, "Maximum", level + 1);
2092 value = CERT_GetNextNameConstraint(value);
2093 } while (value != head);
2094}
2095
2096static void
2097secu_PrintNameConstraintsExtension(FILE *out, SECItem *value, char *msg, int level)
2098{
2099 CERTNameConstraints *cnstrnts;
2100 PLArenaPool *pool = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
2101
2102 if (!pool) {
2103 SECU_PrintError("Error", "Allocating new ArenaPool");
2104 return;
2105 }
2106 cnstrnts = CERT_DecodeNameConstraintsExtension(pool, value);
2107 if (!cnstrnts) {
2108 SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
2109 SECU_PrintAny(out, value, "Raw", level);
2110 } else {
2111 if (cnstrnts->permited)
2112 secu_PrintNameConstraintSubtree(out, cnstrnts->permited,
2113 "Permitted", level);
2114 if (cnstrnts->excluded)
2115 secu_PrintNameConstraintSubtree(out, cnstrnts->excluded,
2116 "Excluded", level);
2117 }
2118 PORT_FreeArenaPORT_FreeArena_Util(pool, PR_FALSE0);
2119}
2120
2121static void
2122secu_PrintAuthorityInfoAcess(FILE *out, SECItem *value, char *msg, int level)
2123{
2124 CERTAuthInfoAccess **infos = NULL((void*)0);
2125 PLArenaPool *pool = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
2126
2127 if (!pool) {
2128 SECU_PrintError("Error", "Allocating new ArenaPool");
2129 return;
2130 }
2131 infos = CERT_DecodeAuthInfoAccessExtension(pool, value);
2132 if (!infos) {
2133 SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
2134 SECU_PrintAny(out, value, "Raw", level);
2135 } else {
2136 CERTAuthInfoAccess *info;
2137 while (NULL((void*)0) != (info = *infos++)) {
2138 if (info->method.data) {
2139 SECU_PrintObjectID(out, &info->method, "Method", level);
2140 } else {
2141 SECU_Indent(out, level);
2142 fprintf(out, "Error: missing method\n");
2143 }
2144 if (info->location) {
2145 secu_PrintGeneralName(out, info->location, "Location", level);
2146 } else {
2147 SECU_PrintAny(out, &info->derLocation, "Location", level);
2148 }
2149 }
2150 }
2151 PORT_FreeArenaPORT_FreeArena_Util(pool, PR_FALSE0);
2152}
2153
2154void
2155SECU_PrintExtensions(FILE *out, CERTCertExtension **extensions,
2156 char *msg, int level)
2157{
2158 SECOidTag oidTag;
2159
2160 if (extensions) {
2161 if (msg && *msg) {
2162 SECU_Indent(out, level++);
2163 fprintf(out, "%s:\n", msg);
2164 }
2165
2166 while (*extensions) {
2167 SECItem *tmpitem;
2168
2169 tmpitem = &(*extensions)->id;
2170 SECU_PrintObjectID(out, tmpitem, "Name", level);
2171
2172 tmpitem = &(*extensions)->critical;
2173 if (tmpitem->len) {
2174 secu_PrintBoolean(out, tmpitem, "Critical", level);
2175 }
2176
2177 oidTag = SECOID_FindOIDTagSECOID_FindOIDTag_Util(&((*extensions)->id));
2178 tmpitem = &((*extensions)->value);
2179
2180 switch (oidTag) {
2181 case SEC_OID_X509_INVALID_DATE:
2182 case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_TIME:
2183 secu_PrintX509InvalidDate(out, tmpitem, "Date", level);
2184 break;
2185 case SEC_OID_X509_CERTIFICATE_POLICIES:
2186 SECU_PrintPolicy(out, tmpitem, "Data", level);
2187 break;
2188 case SEC_OID_NS_CERT_EXT_BASE_URL:
2189 case SEC_OID_NS_CERT_EXT_REVOCATION_URL:
2190 case SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL:
2191 case SEC_OID_NS_CERT_EXT_CA_CRL_URL:
2192 case SEC_OID_NS_CERT_EXT_CA_CERT_URL:
2193 case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL:
2194 case SEC_OID_NS_CERT_EXT_CA_POLICY_URL:
2195 case SEC_OID_NS_CERT_EXT_HOMEPAGE_URL:
2196 case SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL:
2197 case SEC_OID_OCSP_RESPONDER:
2198 SECU_PrintString(out, tmpitem, "URL", level);
2199 break;
2200 case SEC_OID_NS_CERT_EXT_COMMENT:
2201 SECU_PrintString(out, tmpitem, "Comment", level);
2202 break;
2203 case SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME:
2204 SECU_PrintString(out, tmpitem, "ServerName", level);
2205 break;
2206 case SEC_OID_NS_CERT_EXT_CERT_TYPE:
2207 secu_PrintNSCertType(out, tmpitem, "Data", level);
2208 break;
2209 case SEC_OID_X509_BASIC_CONSTRAINTS:
2210 secu_PrintBasicConstraints(out, tmpitem, "Data", level);
2211 break;
2212 case SEC_OID_X509_EXT_KEY_USAGE:
2213 PrintExtKeyUsageExtension(out, tmpitem, NULL((void*)0), level);
2214 break;
2215 case SEC_OID_X509_KEY_USAGE:
2216 secu_PrintX509KeyUsage(out, tmpitem, NULL((void*)0), level);
2217 break;
2218 case SEC_OID_X509_AUTH_KEY_ID:
2219 secu_PrintAuthKeyIDExtension(out, tmpitem, NULL((void*)0), level);
2220 break;
2221 case SEC_OID_X509_SUBJECT_ALT_NAME:
2222 case SEC_OID_X509_ISSUER_ALT_NAME:
2223 secu_PrintAltNameExtension(out, tmpitem, NULL((void*)0), level);
2224 break;
2225 case SEC_OID_X509_CRL_DIST_POINTS:
2226 secu_PrintCRLDistPtsExtension(out, tmpitem, NULL((void*)0), level);
2227 break;
2228 case SEC_OID_X509_PRIVATE_KEY_USAGE_PERIOD:
2229 SECU_PrintPrivKeyUsagePeriodExtension(out, tmpitem, NULL((void*)0),
2230 level);
2231 break;
2232 case SEC_OID_X509_NAME_CONSTRAINTS:
2233 secu_PrintNameConstraintsExtension(out, tmpitem, NULL((void*)0), level);
2234 break;
2235 case SEC_OID_X509_AUTH_INFO_ACCESS:
2236 secu_PrintAuthorityInfoAcess(out, tmpitem, NULL((void*)0), level);
2237 break;
2238
2239 case SEC_OID_X509_CRL_NUMBER:
2240 case SEC_OID_X509_REASON_CODE:
2241
2242 /* PKIX OIDs */
2243 case SEC_OID_PKIX_OCSP:
2244 case SEC_OID_PKIX_OCSP_BASIC_RESPONSE:
2245 case SEC_OID_PKIX_OCSP_NONCE:
2246 case SEC_OID_PKIX_OCSP_CRL:
2247 case SEC_OID_PKIX_OCSP_RESPONSE:
2248 case SEC_OID_PKIX_OCSP_NO_CHECK:
2249 case SEC_OID_PKIX_OCSP_ARCHIVE_CUTOFF:
2250 case SEC_OID_PKIX_OCSP_SERVICE_LOCATOR:
2251 case SEC_OID_PKIX_REGCTRL_REGTOKEN:
2252 case SEC_OID_PKIX_REGCTRL_AUTHENTICATOR:
2253 case SEC_OID_PKIX_REGCTRL_PKIPUBINFO:
2254 case SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS:
2255 case SEC_OID_PKIX_REGCTRL_OLD_CERT_ID:
2256 case SEC_OID_PKIX_REGCTRL_PROTOCOL_ENC_KEY:
2257 case SEC_OID_PKIX_REGINFO_UTF8_PAIRS:
2258 case SEC_OID_PKIX_REGINFO_CERT_REQUEST:
2259
2260 /* Netscape extension OIDs. */
2261 case SEC_OID_NS_CERT_EXT_NETSCAPE_OK:
2262 case SEC_OID_NS_CERT_EXT_ISSUER_LOGO:
2263 case SEC_OID_NS_CERT_EXT_SUBJECT_LOGO:
2264 case SEC_OID_NS_CERT_EXT_ENTITY_LOGO:
2265 case SEC_OID_NS_CERT_EXT_USER_PICTURE:
2266
2267 /* x.509 v3 Extensions */
2268 case SEC_OID_X509_SUBJECT_DIRECTORY_ATTR:
2269 case SEC_OID_X509_SUBJECT_KEY_ID:
2270 case SEC_OID_X509_POLICY_MAPPINGS:
2271 case SEC_OID_X509_POLICY_CONSTRAINTS:
2272
2273 default:
2274 SECU_PrintAny(out, tmpitem, "Data", level);
2275 break;
2276 }
2277
2278 SECU_Newline(out);
2279 extensions++;
2280 }
2281 }
2282}
2283
2284/* An RDN is a subset of a DirectoryName, and we already know how to
2285 * print those, so make a directory name out of the RDN, and print it.
2286 */
2287void
2288SECU_PrintRDN(FILE *out, CERTRDN *rdn, const char *msg, int level)
2289{
2290 CERTName name;
2291 CERTRDN *rdns[2];
2292
2293 name.arena = NULL((void*)0);
2294 name.rdns = rdns;
2295 rdns[0] = rdn;
2296 rdns[1] = NULL((void*)0);
2297 SECU_PrintName(out, &name, msg, level);
2298}
2299
2300void
2301SECU_PrintNameQuotesOptional(FILE *out, CERTName *name, const char *msg,
2302 int level, PRBool quotes)
2303{
2304 char *nameStr = NULL((void*)0);
2305 char *str;
2306 SECItem my;
2307
2308 if (!name) {
2309 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
2310 return;
2311 }
2312 if (!name->rdns || !name->rdns[0]) {
2313 str = "(empty)";
2314 } else {
2315 str = nameStr = CERT_NameToAscii(name);
2316 }
2317 if (!str) {
2318 str = "!Invalid AVA!";
2319 }
2320 my.data = (unsigned char *)str;
2321 my.len = PORT_Strlen(str)strlen(str);
2322#if 1
2323 secu_PrintRawStringQuotesOptional(out, &my, msg, level, quotes);
2324#else
2325 SECU_Indent(out, level);
2326 fprintf(out, "%s: ", msg);
2327 fprintf(out, str);
2328 SECU_Newline(out);
2329#endif
2330 PORT_FreePORT_Free_Util(nameStr);
2331}
2332
2333void
2334SECU_PrintName(FILE *out, CERTName *name, const char *msg, int level)
2335{
2336 SECU_PrintNameQuotesOptional(out, name, msg, level, PR_TRUE1);
2337}
2338
2339void
2340printflags(char *trusts, unsigned int flags)
2341{
2342 if (flags & CERTDB_VALID_CA(1u << 3))
2343 if (!(flags & CERTDB_TRUSTED_CA(1u << 4)) &&
2344 !(flags & CERTDB_TRUSTED_CLIENT_CA(1u << 7)))
2345 PORT_Strcatstrcat(trusts, "c");
2346 if (flags & CERTDB_TERMINAL_RECORD(1u << 0))
2347 if (!(flags & CERTDB_TRUSTED(1u << 1)))
2348 PORT_Strcatstrcat(trusts, "p");
2349 if (flags & CERTDB_TRUSTED_CA(1u << 4))
2350 PORT_Strcatstrcat(trusts, "C");
2351 if (flags & CERTDB_TRUSTED_CLIENT_CA(1u << 7))
2352 PORT_Strcatstrcat(trusts, "T");
2353 if (flags & CERTDB_TRUSTED(1u << 1))
2354 PORT_Strcatstrcat(trusts, "P");
2355 if (flags & CERTDB_USER(1u << 6))
2356 PORT_Strcatstrcat(trusts, "u");
2357 if (flags & CERTDB_SEND_WARN(1u << 2))
2358 PORT_Strcatstrcat(trusts, "w");
2359 if (flags & CERTDB_INVISIBLE_CA(1u << 8))
2360 PORT_Strcatstrcat(trusts, "I");
2361 if (flags & CERTDB_GOVT_APPROVED_CA(1u << 9))
2362 PORT_Strcatstrcat(trusts, "G");
2363 return;
2364}
2365
2366/* callback for listing certs through pkcs11 */
2367SECStatus
2368SECU_PrintCertNickname(CERTCertListNode *node, void *data)
2369{
2370 CERTCertTrust trust;
2371 CERTCertificate *cert;
2372 FILE *out;
2373 char trusts[30];
2374 char *name;
2375
2376 cert = node->cert;
2377
2378 PORT_Memsetmemset(trusts, 0, sizeof(trusts));
2379 out = (FILE *)data;
2380
2381 name = node->appData;
2382 if (!name || !name[0]) {
2383 name = cert->nickname;
2384 }
2385 if (!name || !name[0]) {
2386 name = cert->emailAddr;
2387 }
2388 if (!name || !name[0]) {
2389 name = "(NULL)";
2390 }
2391
2392 if (CERT_GetCertTrust(cert, &trust) == SECSuccess) {
2393 printflags(trusts, trust.sslFlags);
2394 PORT_Strcatstrcat(trusts, ",");
2395 printflags(trusts, trust.emailFlags);
2396 PORT_Strcatstrcat(trusts, ",");
2397 printflags(trusts, trust.objectSigningFlags);
2398 } else {
2399 PORT_Memcpymemcpy(trusts, ",,", 3);
2400 }
2401 fprintf(out, "%-60s %-5s\n", name, trusts);
2402
2403 return (SECSuccess);
2404}
2405
2406int
2407SECU_DecodeAndPrintExtensions(FILE *out, SECItem *any, char *m, int level)
2408{
2409 CERTCertExtension **extensions = NULL((void*)0);
2410 PLArenaPool *arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
2411 int rv = 0;
2412
2413 if (!arena)
2414 return SEC_ERROR_NO_MEMORY;
2415
2416 rv = SEC_QuickDERDecodeItemSEC_QuickDERDecodeItem_Util(arena, &extensions,
2417 SEC_ASN1_GET(CERT_SequenceOfCertExtensionTemplate)CERT_SequenceOfCertExtensionTemplate, any);
2418 if (!rv)
2419 SECU_PrintExtensions(out, extensions, m, level);
2420 else
2421 SECU_PrintAny(out, any, m, level);
2422 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
2423 return rv;
2424}
2425
2426/* print a decoded SET OF or SEQUENCE OF Extensions */
2427int
2428SECU_PrintSetOfExtensions(FILE *out, SECItem **any, char *m, int level)
2429{
2430 int rv = 0;
2431 if (m && *m) {
2432 SECU_Indent(out, level++);
2433 fprintf(out, "%s:\n", m);
2434 }
2435 while (any && any[0]) {
2436 rv |= SECU_DecodeAndPrintExtensions(out, any[0], "", level);
2437 any++;
2438 }
2439 return rv;
2440}
2441
2442/* print a decoded SET OF or SEQUENCE OF "ANY" */
2443int
2444SECU_PrintSetOfAny(FILE *out, SECItem **any, char *m, int level)
2445{
2446 int rv = 0;
2447 if (m && *m) {
2448 SECU_Indent(out, level++);
2449 fprintf(out, "%s:\n", m);
2450 }
2451 while (any && any[0]) {
2452 SECU_PrintAny(out, any[0], "", level);
2453 any++;
2454 }
2455 return rv;
2456}
2457
2458int
2459SECU_PrintCertAttribute(FILE *out, CERTAttribute *attr, char *m, int level)
2460{
2461 int rv = 0;
2462 SECOidTag tag;
2463 tag = SECU_PrintObjectID(out, &attr->attrType, "Attribute Type", level);
2464 if (tag == SEC_OID_PKCS9_EXTENSION_REQUEST) {
2465 rv = SECU_PrintSetOfExtensions(out, attr->attrValue, "Extensions", level);
2466 } else {
2467 rv = SECU_PrintSetOfAny(out, attr->attrValue, "Attribute Values", level);
2468 }
2469 return rv;
2470}
2471
2472int
2473SECU_PrintCertAttributes(FILE *out, CERTAttribute **attrs, char *m, int level)
2474{
2475 int rv = 0;
2476 while (attrs[0]) {
2477 rv |= SECU_PrintCertAttribute(out, attrs[0], m, level + 1);
2478 attrs++;
2479 }
2480 return rv;
2481}
2482
2483/* sometimes a PRErrorCode, other times a SECStatus. Sigh. */
2484int
2485SECU_PrintCertificateRequest(FILE *out, const SECItem *der, const char *m, int level)
2486{
2487 PLArenaPool *arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
2488 CERTCertificateRequest *cr;
2489 int rv = SEC_ERROR_NO_MEMORY;
2490
2491 if (!arena)
2492 return rv;
2493
2494 /* Decode certificate request */
2495 cr = PORT_ArenaZNew(arena, CERTCertificateRequest)(CERTCertificateRequest *)PORT_ArenaZAlloc_Util(arena, sizeof
(CERTCertificateRequest))
;
2496 if (!cr)
2497 goto loser;
2498 cr->arena = arena;
2499 rv = SEC_QuickDERDecodeItemSEC_QuickDERDecodeItem_Util(arena, cr,
2500 SEC_ASN1_GET(CERT_CertificateRequestTemplate)CERT_CertificateRequestTemplate, der);
2501 if (rv)
2502 goto loser;
2503
2504 /* Pretty print it out */
2505 SECU_Indent(out, level);
2506 fprintf(out, "%s:\n", m);
2507 SECU_PrintInteger(out, &cr->version, "Version", level + 1);
2508 SECU_PrintName(out, &cr->subject, "Subject", level + 1);
2509 if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
2510 SECU_Newline(out);
2511 secu_PrintSubjectPublicKeyInfo(out, arena, &cr->subjectPublicKeyInfo,
2512 "Subject Public Key Info", level + 1);
2513 if (cr->attributes)
2514 SECU_PrintCertAttributes(out, cr->attributes, "Attributes", level + 1);
2515 rv = 0;
2516loser:
2517 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
2518 return rv;
2519}
2520
2521int
2522SECU_PrintCertificate(FILE *out, const SECItem *der, const char *m, int level)
2523{
2524 PLArenaPool *arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
2525 CERTCertificate *c;
2526 int rv = SEC_ERROR_NO_MEMORY;
2527 int iv;
2528
2529 if (!arena)
2530 return rv;
2531
2532 /* Decode certificate */
2533 c = PORT_ArenaZNew(arena, CERTCertificate)(CERTCertificate *)PORT_ArenaZAlloc_Util(arena, sizeof(CERTCertificate
))
;
2534 if (!c)
2535 goto loser;
2536 c->arena = arena;
2537 rv = SEC_ASN1DecodeItemSEC_ASN1DecodeItem_Util(arena, c,
2538 SEC_ASN1_GET(CERT_CertificateTemplate)CERT_CertificateTemplate, der);
2539 if (rv) {
2540 SECU_Indent(out, level);
2541 SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
2542 SECU_PrintAny(out, der, "Raw", level);
2543 goto loser;
2544 }
2545 /* Pretty print it out */
2546 SECU_Indent(out, level);
2547 fprintf(out, "%s:\n", m);
2548 iv = c->version.len ? DER_GetIntegerDER_GetInteger_Util(&c->version) : 0; /* version is optional */
2549 SECU_Indent(out, level + 1);
2550 fprintf(out, "%s: %d (0x%x)\n", "Version", iv + 1, iv);
2551
2552 SECU_PrintInteger(out, &c->serialNumber, "Serial Number", level + 1);
2553 SECU_PrintAlgorithmID(out, &c->signature, "Signature Algorithm", level + 1);
2554 SECU_PrintName(out, &c->issuer, "Issuer", level + 1);
2555 if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
2556 SECU_Newline(out);
2557 secu_PrintValidity(out, &c->validity, "Validity", level + 1);
2558 SECU_PrintName(out, &c->subject, "Subject", level + 1);
2559 if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
2560 SECU_Newline(out);
2561 secu_PrintSubjectPublicKeyInfo(out, arena, &c->subjectPublicKeyInfo,
2562 "Subject Public Key Info", level + 1);
2563 if (c->issuerID.data)
2564 secu_PrintDecodedBitString(out, &c->issuerID, "Issuer Unique ID", level + 1);
2565 if (c->subjectID.data)
2566 secu_PrintDecodedBitString(out, &c->subjectID, "Subject Unique ID", level + 1);
2567 SECU_PrintExtensions(out, c->extensions, "Signed Extensions", level + 1);
2568loser:
2569 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
2570 return rv;
2571}
2572
2573int
2574SECU_PrintCertificateBasicInfo(FILE *out, const SECItem *der, const char *m, int level)
2575{
2576 PLArenaPool *arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
2577 CERTCertificate *c;
2578 int rv = SEC_ERROR_NO_MEMORY;
2579
2580 if (!arena)
2581 return rv;
2582
2583 /* Decode certificate */
2584 c = PORT_ArenaZNew(arena, CERTCertificate)(CERTCertificate *)PORT_ArenaZAlloc_Util(arena, sizeof(CERTCertificate
))
;
2585 if (!c)
2586 goto loser;
2587 c->arena = arena;
2588 rv = SEC_ASN1DecodeItemSEC_ASN1DecodeItem_Util(arena, c,
2589 SEC_ASN1_GET(CERT_CertificateTemplate)CERT_CertificateTemplate, der);
2590 if (rv) {
2591 SECU_Indent(out, level);
2592 SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
2593 SECU_PrintAny(out, der, "Raw", level);
2594 goto loser;
2595 }
2596 /* Pretty print it out */
2597 SECU_Indent(out, level);
2598 fprintf(out, "%s:\n", m);
2599 SECU_PrintInteger(out, &c->serialNumber, "Serial Number", level + 1);
2600 SECU_PrintAlgorithmID(out, &c->signature, "Signature Algorithm", level + 1);
2601 SECU_PrintName(out, &c->issuer, "Issuer", level + 1);
2602 if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
2603 SECU_Newline(out);
2604 secu_PrintValidity(out, &c->validity, "Validity", level + 1);
2605 SECU_PrintName(out, &c->subject, "Subject", level + 1);
2606 if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
2607 SECU_Newline(out);
2608loser:
2609 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
2610 return rv;
2611}
2612
2613int
2614SECU_PrintSubjectPublicKeyInfo(FILE *out, SECItem *der, char *m, int level)
2615{
2616 PLArenaPool *arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
2617 int rv = SEC_ERROR_NO_MEMORY;
2618 CERTSubjectPublicKeyInfo spki;
2619
2620 if (!arena)
2621 return rv;
2622
2623 PORT_Memsetmemset(&spki, 0, sizeof spki);
2624 rv = SEC_ASN1DecodeItemSEC_ASN1DecodeItem_Util(arena, &spki,
2625 SEC_ASN1_GET(CERT_SubjectPublicKeyInfoTemplate)CERT_SubjectPublicKeyInfoTemplate,
2626 der);
2627 if (!rv) {
2628 if (m && *m) {
2629 SECU_Indent(out, level);
2630 fprintf(out, "%s:\n", m);
2631 }
2632 secu_PrintSubjectPublicKeyInfo(out, arena, &spki,
2633 "Subject Public Key Info", level + 1);
2634 }
2635
2636 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
2637 return rv;
2638}
2639
2640int
2641SECU_PrintPrivateKey(FILE *out, SECItem *der, char *m, int level)
2642{
2643 PLArenaPool *arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
2644 SECKEYEncryptedPrivateKeyInfo key;
2645 int rv = SEC_ERROR_NO_MEMORY;
2646
2647 if (!arena)
2648 return rv;
2649
2650 PORT_Memsetmemset(&key, 0, sizeof(key));
2651 rv = SEC_ASN1DecodeItemSEC_ASN1DecodeItem_Util(arena, &key,
2652 SEC_ASN1_GET(SECKEY_EncryptedPrivateKeyInfoTemplate)SECKEY_EncryptedPrivateKeyInfoTemplate, der);
2653 if (rv)
2654 goto loser;
2655
2656 /* Pretty print it out */
2657 SECU_Indent(out, level);
2658 fprintf(out, "%s:\n", m);
2659 SECU_PrintAlgorithmID(out, &key.algorithm, "Encryption Algorithm",
2660 level + 1);
2661 SECU_PrintAsHex(out, &key.encryptedData, "Encrypted Data", level + 1);
2662loser:
2663 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_TRUE1);
2664 return rv;
2665}
2666
2667int
2668SECU_PrintFingerprints(FILE *out, SECItem *derCert, char *m, int level)
2669{
2670 unsigned char fingerprint[SHA256_LENGTH32];
2671 char *fpStr = NULL((void*)0);
2672 int err = PORT_GetErrorPORT_GetError_Util();
2673 SECStatus rv;
2674 SECItem fpItem;
2675
2676 /* Print SHA-256 fingerprint */
2677 memset(fingerprint, 0, sizeof fingerprint);
2678 rv = PK11_HashBuf(SEC_OID_SHA256, fingerprint, derCert->data, derCert->len);
2679 fpItem.data = fingerprint;
2680 fpItem.len = SHA256_LENGTH32;
2681 fpStr = CERT_Hexify(&fpItem, 1);
2682 SECU_Indent(out, level);
2683 fprintf(out, "%s (SHA-256):", m);
2684 if (SECU_GetWrapEnabled()) {
2685 fprintf(out, "\n");
2686 SECU_Indent(out, level + 1);
2687 } else {
2688 fprintf(out, " ");
2689 }
2690 fprintf(out, "%s\n", fpStr);
2691 PORT_FreePORT_Free_Util(fpStr);
2692 fpStr = NULL((void*)0);
2693 if (rv != SECSuccess && !err)
2694 err = PORT_GetErrorPORT_GetError_Util();
2695
2696 /* print SHA1 fingerprint */
2697 memset(fingerprint, 0, sizeof fingerprint);
2698 rv = PK11_HashBuf(SEC_OID_SHA1, fingerprint, derCert->data, derCert->len);
2699 fpItem.data = fingerprint;
2700 fpItem.len = SHA1_LENGTH20;
2701 fpStr = CERT_Hexify(&fpItem, 1);
2702 SECU_Indent(out, level);
2703 fprintf(out, "%s (SHA1):", m);
2704 if (SECU_GetWrapEnabled()) {
2705 fprintf(out, "\n");
2706 SECU_Indent(out, level + 1);
2707 } else {
2708 fprintf(out, " ");
2709 }
2710 fprintf(out, "%s\n", fpStr);
2711 PORT_FreePORT_Free_Util(fpStr);
2712 if (SECU_GetWrapEnabled())
2713 fprintf(out, "\n");
2714
2715 if (err)
2716 PORT_SetErrorPORT_SetError_Util(err);
2717 if (err || rv != SECSuccess)
2718 return SECFailure;
2719
2720 return 0;
2721}
2722
2723/*
2724** PKCS7 Support
2725*/
2726
2727/* forward declaration */
2728typedef enum {
2729 secuPKCS7Unknown = 0,
2730 secuPKCS7PKCS12AuthSafe,
2731 secuPKCS7PKCS12Safe
2732} secuPKCS7State;
2733
2734static int
2735secu_PrintPKCS7ContentInfo(FILE *, SEC_PKCS7ContentInfo *, secuPKCS7State,
2736 const char *, int);
2737static int
2738secu_PrintDERPKCS7ContentInfo(FILE *, SECItem *, secuPKCS7State,
2739 const char *, int);
2740
2741/*
2742** secu_PrintPKCS7EncContent
2743** Prints a SEC_PKCS7EncryptedContentInfo (without decrypting it)
2744*/
2745static int
2746secu_PrintPKCS7EncContent(FILE *out, SEC_PKCS7EncryptedContentInfo *src,
2747 secuPKCS7State state, const char *m, int level)
2748{
2749 if (src->contentTypeTag == NULL((void*)0))
2750 src->contentTypeTag = SECOID_FindOIDSECOID_FindOID_Util(&(src->contentType));
2751
2752 SECU_Indent(out, level);
2753 fprintf(out, "%s:\n", m);
2754 SECU_Indent(out, level + 1);
2755 fprintf(out, "Content Type: %s\n",
2756 (src->contentTypeTag != NULL((void*)0)) ? src->contentTypeTag->desc
2757 : "Unknown");
2758 SECU_PrintAlgorithmID(out, &(src->contentEncAlg),
2759 "Content Encryption Algorithm", level + 1);
2760 SECU_PrintAsHex(out, &(src->encContent),
2761 "Encrypted Content", level + 1);
2762 return 0;
2763}
2764
2765/*
2766** secu_PrintRecipientInfo
2767** Prints a PKCS7RecipientInfo type
2768*/
2769static void
2770secu_PrintRecipientInfo(FILE *out, SEC_PKCS7RecipientInfo *info,
2771 const char *m, int level)
2772{
2773 SECU_Indent(out, level);
2774 fprintf(out, "%s:\n", m);
2775 SECU_PrintInteger(out, &(info->version), "Version", level + 1);
2776
2777 SECU_PrintName(out, &(info->issuerAndSN->issuer), "Issuer",
2778 level + 1);
2779 SECU_PrintInteger(out, &(info->issuerAndSN->serialNumber),
2780 "Serial Number", level + 1);
2781
2782 /* Parse and display encrypted key */
2783 SECU_PrintAlgorithmID(out, &(info->keyEncAlg),
2784 "Key Encryption Algorithm", level + 1);
2785 SECU_PrintAsHex(out, &(info->encKey), "Encrypted Key", level + 1);
2786}
2787
2788/*
2789** secu_PrintSignerInfo
2790** Prints a PKCS7SingerInfo type
2791*/
2792static void
2793secu_PrintSignerInfo(FILE *out, SEC_PKCS7SignerInfo *info,
2794 const char *m, int level)
2795{
2796 SEC_PKCS7Attribute *attr;
2797 int iv;
2798 char om[100];
2799
2800 SECU_Indent(out, level);
2801 fprintf(out, "%s:\n", m);
2802 SECU_PrintInteger(out, &(info->version), "Version", level + 1);
2803
2804 SECU_PrintName(out, &(info->issuerAndSN->issuer), "Issuer",
2805 level + 1);
2806 SECU_PrintInteger(out, &(info->issuerAndSN->serialNumber),
2807 "Serial Number", level + 1);
2808
2809 SECU_PrintAlgorithmID(out, &(info->digestAlg), "Digest Algorithm",
2810 level + 1);
2811
2812 if (info->authAttr != NULL((void*)0)) {
2813 SECU_Indent(out, level + 1);
2814 fprintf(out, "Authenticated Attributes:\n");
2815 iv = 0;
2816 while ((attr = info->authAttr[iv++]) != NULL((void*)0)) {
2817 snprintf(om, sizeof(om), "Attribute (%d)", iv);
2818 secu_PrintAttribute(out, attr, om, level + 2);
2819 }
2820 }
2821
2822 /* Parse and display signature */
2823 SECU_PrintAlgorithmID(out, &(info->digestEncAlg),
2824 "Digest Encryption Algorithm", level + 1);
2825 SECU_PrintAsHex(out, &(info->encDigest), "Encrypted Digest", level + 1);
2826
2827 if (info->unAuthAttr != NULL((void*)0)) {
2828 SECU_Indent(out, level + 1);
2829 fprintf(out, "Unauthenticated Attributes:\n");
2830 iv = 0;
2831 while ((attr = info->unAuthAttr[iv++]) != NULL((void*)0)) {
2832 snprintf(om, sizeof(om), "Attribute (%x)", iv);
2833 secu_PrintAttribute(out, attr, om, level + 2);
2834 }
2835 }
2836}
2837
2838/* callers of this function must make sure that the CERTSignedCrl
2839 from which they are extracting the CERTCrl has been fully-decoded.
2840 Otherwise it will not have the entries even though the CRL may have
2841 some */
2842
2843void
2844SECU_PrintCRLInfo(FILE *out, CERTCrl *crl, const char *m, int level)
2845{
2846 CERTCrlEntry *entry;
2847 int iv;
2848 char om[100];
2849
2850 SECU_Indent(out, level);
2851 fprintf(out, "%s:\n", m);
2852 /* version is optional */
2853 iv = crl->version.len ? DER_GetIntegerDER_GetInteger_Util(&crl->version) : 0;
2854 SECU_Indent(out, level + 1);
2855 fprintf(out, "%s: %d (0x%x)\n", "Version", iv + 1, iv);
2856 SECU_PrintAlgorithmID(out, &(crl->signatureAlg), "Signature Algorithm",
2857 level + 1);
2858 SECU_PrintName(out, &(crl->name), "Issuer", level + 1);
2859 SECU_PrintTimeChoice(out, &(crl->lastUpdate), "This Update", level + 1);
2860 if (crl->nextUpdate.data && crl->nextUpdate.len) /* is optional */
2861 SECU_PrintTimeChoice(out, &(crl->nextUpdate), "Next Update", level + 1);
2862
2863 if (crl->entries != NULL((void*)0)) {
2864 iv = 0;
2865 while ((entry = crl->entries[iv++]) != NULL((void*)0)) {
2866 snprintf(om, sizeof(om), "Entry %d (0x%x):\n", iv, iv);
2867 SECU_Indent(out, level + 1);
2868 fputs(om, out);
2869 SECU_PrintInteger(out, &(entry->serialNumber), "Serial Number",
2870 level + 2);
2871 SECU_PrintTimeChoice(out, &(entry->revocationDate),
2872 "Revocation Date", level + 2);
2873 SECU_PrintExtensions(out, entry->extensions,
2874 "Entry Extensions", level + 2);
2875 }
2876 }
2877 SECU_PrintExtensions(out, crl->extensions, "CRL Extensions", level + 1);
2878}
2879
2880/*
2881** secu_PrintPKCS7Signed
2882** Pretty print a PKCS7 signed data type (up to version 1).
2883*/
2884static int
2885secu_PrintPKCS7Signed(FILE *out, SEC_PKCS7SignedData *src,
2886 secuPKCS7State state, const char *m, int level)
2887{
2888 SECAlgorithmID *digAlg; /* digest algorithms */
2889 SECItem *aCert; /* certificate */
2890 CERTSignedCrl *aCrl; /* certificate revocation list */
2891 SEC_PKCS7SignerInfo *sigInfo; /* signer information */
2892 int rv, iv;
2893 char om[100];
2894
2895 SECU_Indent(out, level);
2896 fprintf(out, "%s:\n", m);
2897 SECU_PrintInteger(out, &(src->version), "Version", level + 1);
2898
2899 /* Parse and list digest algorithms (if any) */
2900 if (src->digestAlgorithms != NULL((void*)0)) {
2901 SECU_Indent(out, level + 1);
2902 fprintf(out, "Digest Algorithm List:\n");
2903 iv = 0;
2904 while ((digAlg = src->digestAlgorithms[iv++]) != NULL((void*)0)) {
2905 snprintf(om, sizeof(om), "Digest Algorithm (%x)", iv);
2906 SECU_PrintAlgorithmID(out, digAlg, om, level + 2);
2907 }
2908 }
2909
2910 /* Now for the content */
2911 rv = secu_PrintPKCS7ContentInfo(out, &(src->contentInfo),
2912 state, "Content Information", level + 1);
2913 if (rv != 0)
2914 return rv;
2915
2916 /* Parse and list certificates (if any) */
2917 if (src->rawCerts != NULL((void*)0)) {
2918 SECU_Indent(out, level + 1);
2919 fprintf(out, "Certificate List:\n");
2920 iv = 0;
2921 while ((aCert = src->rawCerts[iv++]) != NULL((void*)0)) {
2922 snprintf(om, sizeof(om), "Certificate (%x)", iv);
2923 rv = SECU_PrintSignedData(out, aCert, om, level + 2,
2924 SECU_PrintCertificate);
2925 if (rv)
2926 return rv;
2927 }
2928 }
2929
2930 /* Parse and list CRL's (if any) */
2931 if (src->crls != NULL((void*)0)) {
2932 SECU_Indent(out, level + 1);
2933 fprintf(out, "Signed Revocation Lists:\n");
2934 iv = 0;
2935 while ((aCrl = src->crls[iv++]) != NULL((void*)0)) {
2936 snprintf(om, sizeof(om), "Signed Revocation List (%x)", iv);
2937 SECU_Indent(out, level + 2);
2938 fprintf(out, "%s:\n", om);
2939 SECU_PrintAlgorithmID(out, &aCrl->signatureWrap.signatureAlgorithm,
2940 "Signature Algorithm", level + 3);
2941 DER_ConvertBitString(&aCrl->signatureWrap.signature){ (&aCrl->signatureWrap.signature)->len = ((&aCrl
->signatureWrap.signature)->len + 7) >> 3; }
;
2942 SECU_PrintAsHex(out, &aCrl->signatureWrap.signature, "Signature",
2943 level + 3);
2944 SECU_PrintCRLInfo(out, &aCrl->crl, "Certificate Revocation List",
2945 level + 3);
2946 }
2947 }
2948
2949 /* Parse and list signatures (if any) */
2950 if (src->signerInfos != NULL((void*)0)) {
2951 SECU_Indent(out, level + 1);
2952 fprintf(out, "Signer Information List:\n");
2953 iv = 0;
2954 while ((sigInfo = src->signerInfos[iv++]) != NULL((void*)0)) {
2955 snprintf(om, sizeof(om), "Signer Information (%x)", iv);
2956 secu_PrintSignerInfo(out, sigInfo, om, level + 2);
2957 }
2958 }
2959
2960 return 0;
2961}
2962
2963/*
2964** secu_PrintPKCS7Enveloped
2965** Pretty print a PKCS7 enveloped data type (up to version 1).
2966*/
2967static int
2968secu_PrintPKCS7Enveloped(FILE *out, SEC_PKCS7EnvelopedData *src,
2969 secuPKCS7State state, const char *m, int level)
2970{
2971 SEC_PKCS7RecipientInfo *recInfo; /* pointer for signer information */
2972 int iv;
2973 char om[100];
2974
2975 SECU_Indent(out, level);
2976 fprintf(out, "%s:\n", m);
2977 SECU_PrintInteger(out, &(src->version), "Version", level + 1);
2978
2979 /* Parse and list recipients (this is not optional) */
2980 if (src->recipientInfos != NULL((void*)0)) {
2981 SECU_Indent(out, level + 1);
2982 fprintf(out, "Recipient Information List:\n");
2983 iv = 0;
2984 while ((recInfo = src->recipientInfos[iv++]) != NULL((void*)0)) {
2985 snprintf(om, sizeof(om), "Recipient Information (%x)", iv);
2986 secu_PrintRecipientInfo(out, recInfo, om, level + 2);
2987 }
2988 }
2989
2990 return secu_PrintPKCS7EncContent(out, &src->encContentInfo, state,
2991 "Encrypted Content Information", level + 1);
2992}
2993
2994/*
2995** secu_PrintPKCS7SignedEnveloped
2996** Pretty print a PKCS7 singed and enveloped data type (up to version 1).
2997*/
2998static int
2999secu_PrintPKCS7SignedAndEnveloped(FILE *out,
3000 SEC_PKCS7SignedAndEnvelopedData *src,
3001 secuPKCS7State state, const char *m,
3002 int level)
3003{
3004 SECAlgorithmID *digAlg; /* pointer for digest algorithms */
3005 SECItem *aCert; /* pointer for certificate */
3006 CERTSignedCrl *aCrl; /* pointer for certificate revocation list */
3007 SEC_PKCS7SignerInfo *sigInfo; /* pointer for signer information */
3008 SEC_PKCS7RecipientInfo *recInfo; /* pointer for recipient information */
3009 int rv, iv;
3010 char om[100];
3011
3012 SECU_Indent(out, level);
3013 fprintf(out, "%s:\n", m);
3014 SECU_PrintInteger(out, &(src->version), "Version", level + 1);
3015
3016 /* Parse and list recipients (this is not optional) */
3017 if (src->recipientInfos != NULL((void*)0)) {
3018 SECU_Indent(out, level + 1);
3019 fprintf(out, "Recipient Information List:\n");
3020 iv = 0;
3021 while ((recInfo = src->recipientInfos[iv++]) != NULL((void*)0)) {
3022 snprintf(om, sizeof(om), "Recipient Information (%x)", iv);
3023 secu_PrintRecipientInfo(out, recInfo, om, level + 2);
3024 }
3025 }
3026
3027 /* Parse and list digest algorithms (if any) */
3028 if (src->digestAlgorithms != NULL((void*)0)) {
3029 SECU_Indent(out, level + 1);
3030 fprintf(out, "Digest Algorithm List:\n");
3031 iv = 0;
3032 while ((digAlg = src->digestAlgorithms[iv++]) != NULL((void*)0)) {
3033 snprintf(om, sizeof(om), "Digest Algorithm (%x)", iv);
3034 SECU_PrintAlgorithmID(out, digAlg, om, level + 2);
3035 }
3036 }
3037
3038 rv = secu_PrintPKCS7EncContent(out, &src->encContentInfo, state,
3039 "Encrypted Content Information", level + 1);
3040 if (rv)
3041 return rv;
3042
3043 /* Parse and list certificates (if any) */
3044 if (src->rawCerts != NULL((void*)0)) {
3045 SECU_Indent(out, level + 1);
3046 fprintf(out, "Certificate List:\n");
3047 iv = 0;
3048 while ((aCert = src->rawCerts[iv++]) != NULL((void*)0)) {
3049 snprintf(om, sizeof(om), "Certificate (%x)", iv);
3050 rv = SECU_PrintSignedData(out, aCert, om, level + 2,
3051 SECU_PrintCertificate);
3052 if (rv)
3053 return rv;
3054 }
3055 }
3056
3057 /* Parse and list CRL's (if any) */
3058 if (src->crls != NULL((void*)0)) {
3059 SECU_Indent(out, level + 1);
3060 fprintf(out, "Signed Revocation Lists:\n");
3061 iv = 0;
3062 while ((aCrl = src->crls[iv++]) != NULL((void*)0)) {
3063 snprintf(om, sizeof(om), "Signed Revocation List (%x)", iv);
3064 SECU_Indent(out, level + 2);
3065 fprintf(out, "%s:\n", om);
3066 SECU_PrintAlgorithmID(out, &aCrl->signatureWrap.signatureAlgorithm,
3067 "Signature Algorithm", level + 3);
3068 DER_ConvertBitString(&aCrl->signatureWrap.signature){ (&aCrl->signatureWrap.signature)->len = ((&aCrl
->signatureWrap.signature)->len + 7) >> 3; }
;
3069 SECU_PrintAsHex(out, &aCrl->signatureWrap.signature, "Signature",
3070 level + 3);
3071 SECU_PrintCRLInfo(out, &aCrl->crl, "Certificate Revocation List",
3072 level + 3);
3073 }
3074 }
3075
3076 /* Parse and list signatures (if any) */
3077 if (src->signerInfos != NULL((void*)0)) {
3078 SECU_Indent(out, level + 1);
3079 fprintf(out, "Signer Information List:\n");
3080 iv = 0;
3081 while ((sigInfo = src->signerInfos[iv++]) != NULL((void*)0)) {
3082 snprintf(om, sizeof(om), "Signer Information (%x)", iv);
3083 secu_PrintSignerInfo(out, sigInfo, om, level + 2);
3084 }
3085 }
3086
3087 return 0;
3088}
3089
3090int
3091SECU_PrintCrl(FILE *out, const SECItem *der, const char *m, int level)
3092{
3093 PLArenaPool *arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
3094 CERTCrl *c = NULL((void*)0);
3095 int rv = SEC_ERROR_NO_MEMORY;
3096
3097 if (!arena)
3098 return rv;
3099 do {
3100 /* Decode CRL */
3101 c = PORT_ArenaZNew(arena, CERTCrl)(CERTCrl *)PORT_ArenaZAlloc_Util(arena, sizeof(CERTCrl));
3102 if (!c)
3103 break;
3104
3105 rv = SEC_QuickDERDecodeItemSEC_QuickDERDecodeItem_Util(arena, c, SEC_ASN1_GET(CERT_CrlTemplate)CERT_CrlTemplate, der);
3106 if (rv != SECSuccess)
3107 break;
3108 SECU_PrintCRLInfo(out, c, m, level);
3109 } while (0);
3110 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
3111 return rv;
3112}
3113
3114/*
3115** secu_PrintPKCS7Encrypted
3116** Pretty print a PKCS7 encrypted data type (up to version 1).
3117*/
3118static int
3119secu_PrintPKCS7Encrypted(FILE *out, SEC_PKCS7EncryptedData *src,
3120 secuPKCS7State state, const char *m, int level)
3121{
3122 SECU_Indent(out, level);
3123 fprintf(out, "%s:\n", m);
3124 SECU_PrintInteger(out, &(src->version), "Version", level + 1);
3125
3126 return secu_PrintPKCS7EncContent(out, &src->encContentInfo, state,
3127 "Encrypted Content Information", level + 1);
3128}
3129
3130/*
3131** secu_PrintPKCS7Digested
3132** Pretty print a PKCS7 digested data type (up to version 1).
3133*/
3134static int
3135secu_PrintPKCS7Digested(FILE *out, SEC_PKCS7DigestedData *src,
3136 secuPKCS7State state, const char *m, int level)
3137{
3138 SECU_Indent(out, level);
3139 fprintf(out, "%s:\n", m);
3140 SECU_PrintInteger(out, &(src->version), "Version", level + 1);
3141
3142 SECU_PrintAlgorithmID(out, &src->digestAlg, "Digest Algorithm",
3143 level + 1);
3144 secu_PrintPKCS7ContentInfo(out, &src->contentInfo, state,
3145 "Content Information", level + 1);
3146 SECU_PrintAsHex(out, &src->digest, "Digest", level + 1);
3147 return 0;
3148}
3149
3150static int
3151secu_PrintPKCS12Attributes(FILE *out, SECItem *item, const char *m, int level)
3152{
3153 SECItem my = *item;
3154 SECItem attribute;
3155 SECItem attributeID;
3156 SECItem attributeValues;
3157
3158 if ((my.data[0] != (SEC_ASN1_CONSTRUCTED0x20 | SEC_ASN1_SET0x11)) ||
3159 SECSuccess != SECU_StripTagAndLength(&my)) {
3160 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
3161 return SECFailure;
3162 }
3163 SECU_Indent(out, level);
3164 fprintf(out, "%s:\n", m);
3165 level++;
3166
3167 while (my.len) {
3168 if (SECSuccess != SECU_ExtractBERAndStep(&my, &attribute)) {
3169 return SECFailure;
3170 }
3171 if ((attribute.data[0] != (SEC_ASN1_CONSTRUCTED0x20 | SEC_ASN1_SEQUENCE0x10)) ||
3172 SECSuccess != SECU_StripTagAndLength(&attribute)) {
3173 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
3174 return SECFailure;
3175 }
3176
3177 /* attribute ID */
3178 if (SECSuccess != SECU_ExtractBERAndStep(&attribute, &attributeID)) {
3179 return SECFailure;
3180 }
3181 if ((attributeID.data[0] & SEC_ASN1_TAGNUM_MASK0x1f) != SEC_ASN1_OBJECT_ID0x06) {
3182 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
3183 return SECFailure;
3184 }
3185 SECU_PrintEncodedObjectID(out, &attributeID, "Attribute ID", level);
3186
3187 /* attribute values */
3188 if (!attribute.len) { /* skip if there aren't any */
3189 continue;
3190 }
3191 if (SECSuccess != SECU_ExtractBERAndStep(&attribute, &attributeValues)) {
3192 return SECFailure;
3193 }
3194 if (SECSuccess != SECU_StripTagAndLength(&attributeValues)) {
3195 return SECFailure;
3196 }
3197 while (attributeValues.len) {
3198 SECItem tmp;
3199 if (SECSuccess != SECU_ExtractBERAndStep(&attributeValues, &tmp)) {
3200 return SECFailure;
3201 }
3202 SECU_PrintAny(out, &tmp, NULL((void*)0), level + 1);
3203 }
3204 }
3205 return SECSuccess;
3206}
3207
3208static int
3209secu_PrintPKCS12Bag(FILE *out, SECItem *item, const char *desc, int level)
3210{
3211 SECItem my = *item;
3212 SECItem bagID;
3213 SECItem bagValue;
3214 SECItem bagAttributes;
3215 SECOidTag bagTag;
3216 SECStatus rv;
3217 int i;
3218 char *m;
3219
3220 if ((my.data[0] != (SEC_ASN1_CONSTRUCTED0x20 | SEC_ASN1_SEQUENCE0x10)) ||
3221 SECSuccess != SECU_StripTagAndLength(&my)) {
3222 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
3223 return SECFailure;
3224 }
3225
3226 /* bagId BAG-TYPE.&id ({PKCS12BagSet}) */
3227 if (SECSuccess != SECU_ExtractBERAndStep(&my, &bagID)) {
3228 return SECFailure;
3229 }
3230 if ((bagID.data[0] & SEC_ASN1_TAGNUM_MASK0x1f) != SEC_ASN1_OBJECT_ID0x06) {
3231 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
3232 return SECFailure;
3233 }
3234 m = PR_smprintf("%s ID", desc);
3235 bagTag = SECU_PrintEncodedObjectID(out, &bagID, m ? m : "Bag ID", level);
3236 if (m)
3237 PR_smprintf_free(m);
3238
3239 /* bagValue [0] EXPLICIT BAG-TYPE.&type({PKCS12BagSet}{@bagID}) */
3240 if (SECSuccess != SECU_ExtractBERAndStep(&my, &bagValue)) {
3241 return SECFailure;
3242 }
3243 if ((bagValue.data[0] & (SEC_ASN1_CLASS_MASK0xc0 | SEC_ASN1_TAGNUM_MASK0x1f)) !=
3244 (SEC_ASN1_CONTEXT_SPECIFIC0x80 | 0)) {
3245 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
3246 return SECFailure;
3247 }
3248 if (SECSuccess != SECU_StripTagAndLength(&bagValue)) {
3249 return SECFailure;
3250 }
3251
3252 rv = SECSuccess;
3253 switch (bagTag) {
3254 case SEC_OID_PKCS12_V1_KEY_BAG_ID:
3255 /* Future we need to print out raw private keys. Not a priority since
3256 * p12util can't create files with unencrypted private keys, but
3257 * some tools can and do */
3258 SECU_PrintAny(out, &bagValue, "Private Key", level);
3259 break;
3260 case SEC_OID_PKCS12_V1_PKCS8_SHROUDED_KEY_BAG_ID:
3261 rv = SECU_PrintPrivateKey(out, &bagValue,
3262 "Encrypted Private Key", level);
3263 break;
3264 case SEC_OID_PKCS12_V1_CERT_BAG_ID:
3265 rv = secu_PrintPKCS12Bag(out, &bagValue, "Certificate Bag", level + 1);
3266 break;
3267 case SEC_OID_PKCS12_V1_CRL_BAG_ID:
3268 rv = secu_PrintPKCS12Bag(out, &bagValue, "Crl Bag", level + 1);
3269 break;
3270 case SEC_OID_PKCS12_V1_SECRET_BAG_ID:
3271 rv = secu_PrintPKCS12Bag(out, &bagValue, "Secret Bag", level + 1);
3272 break;
3273 /* from recursive call from CRL and certificate Bag */
3274 case SEC_OID_PKCS9_X509_CRL:
3275 case SEC_OID_PKCS9_X509_CERT:
3276 case SEC_OID_PKCS9_SDSI_CERT:
3277 /* unwrap the octect string */
3278 rv = SECU_StripTagAndLength(&bagValue);
3279 if (rv != SECSuccess) {
3280 break;
3281 }
3282 /* fall through */
3283 case SEC_OID_PKCS12_CERT_AND_CRL_BAG_ID:
3284 case SEC_OID_PKCS12_X509_CERT_CRL_BAG:
3285 case SEC_OID_PKCS12_SDSI_CERT_BAG:
3286 if (strcmp(desc, "Crl Bag") == 0) {
3287 rv = SECU_PrintSignedData(out, &bagValue, NULL((void*)0), level + 1,
3288 SECU_PrintCrl);
3289 } else {
3290 rv = SECU_PrintSignedData(out, &bagValue, NULL((void*)0), level + 1,
3291 SECU_PrintCertificate);
3292 }
3293 break;
3294 case SEC_OID_PKCS12_V1_SAFE_CONTENTS_BAG_ID:
3295 for (i = 1; my.len; i++) {
3296 SECItem nextBag;
3297 rv = SECU_ExtractBERAndStep(&bagValue, &nextBag);
3298 if (rv != SECSuccess) {
3299 break;
3300 }
3301 m = PR_smprintf("Nested Bag %d", i);
3302 rv = secu_PrintPKCS12Bag(out, &nextBag,
3303 m ? m : "Nested Bag", level + 1);
3304 if (m)
3305 PR_smprintf_free(m);
3306 if (rv != SECSuccess) {
3307 break;
3308 }
3309 }
3310 break;
3311 default:
3312 m = PR_smprintf("%s Value", desc);
3313 SECU_PrintAny(out, &bagValue, m ? m : "Bag Value", level);
3314 if (m)
3315 PR_smprintf_free(m);
3316 }
3317 if (rv != SECSuccess) {
3318 return rv;
3319 }
3320
3321 /* bagAttributes SET OF PKCS12Attributes OPTIONAL */
3322 if (my.len &&
3323 (my.data[0] == (SEC_ASN1_CONSTRUCTED0x20 | SEC_ASN1_SET0x11))) {
3324 if (SECSuccess != SECU_ExtractBERAndStep(&my, &bagAttributes)) {
3325 return SECFailure;
3326 }
3327 m = PR_smprintf("%s Attributes", desc);
3328 rv = secu_PrintPKCS12Attributes(out, &bagAttributes,
3329 m ? m : "Bag Attributes", level);
3330 if (m)
3331 PR_smprintf_free(m);
3332 }
3333 return rv;
3334}
3335
3336static int
3337secu_PrintPKCS7Data(FILE *out, SECItem *item, secuPKCS7State state,
3338 const char *desc, int level)
3339{
3340 SECItem my = *item;
3341 SECItem nextbag;
3342 int i;
3343 SECStatus rv;
3344
3345 /* walk down each safe */
3346 switch (state) {
3347 case secuPKCS7PKCS12AuthSafe:
3348 if ((my.data[0] != (SEC_ASN1_CONSTRUCTED0x20 | SEC_ASN1_SEQUENCE0x10)) ||
3349 SECSuccess != SECU_StripTagAndLength(&my)) {
3350 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
3351 return SECFailure;
3352 }
3353 for (i = 1; my.len; i++) {
3354 char *m;
3355 if (SECSuccess != SECU_ExtractBERAndStep(&my, &nextbag)) {
3356 return SECFailure;
3357 }
3358 m = PR_smprintf("Safe %d", i);
3359 rv = secu_PrintDERPKCS7ContentInfo(out, &nextbag,
3360 secuPKCS7PKCS12Safe,
3361 m ? m : "Safe", level);
3362 if (m)
3363 PR_smprintf_free(m);
3364 if (rv != SECSuccess) {
3365 return SECFailure;
3366 }
3367 }
3368 return SECSuccess;
3369 case secuPKCS7PKCS12Safe:
3370 if ((my.data[0] != (SEC_ASN1_CONSTRUCTED0x20 | SEC_ASN1_SEQUENCE0x10)) ||
3371 SECSuccess != SECU_StripTagAndLength(&my)) {
3372 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
3373 return SECFailure;
3374 }
3375 for (i = 1; my.len; i++) {
3376 char *m;
3377 if (SECSuccess != SECU_ExtractBERAndStep(&my, &nextbag)) {
3378 return SECFailure;
3379 }
3380 m = PR_smprintf("Bag %d", i);
3381 rv = secu_PrintPKCS12Bag(out, &nextbag,
3382 m ? m : "Bag", level);
3383 if (m)
3384 PR_smprintf_free(m);
3385 if (rv != SECSuccess) {
3386 return SECFailure;
3387 }
3388 }
3389 return SECSuccess;
3390 case secuPKCS7Unknown:
3391 SECU_PrintAsHex(out, item, desc, level);
3392 break;
3393 }
3394 return SECSuccess;
3395}
3396
3397/*
3398** secu_PrintPKCS7ContentInfo
3399** Takes a SEC_PKCS7ContentInfo type and sends the contents to the
3400** appropriate function
3401*/
3402static int
3403secu_PrintPKCS7ContentInfo(FILE *out, SEC_PKCS7ContentInfo *src,
3404 secuPKCS7State state, const char *m, int level)
3405{
3406 const char *desc;
3407 SECOidTag kind;
3408 int rv;
3409
3410 SECU_Indent(out, level);
3411 fprintf(out, "%s:\n", m);
3412 level++;
3413
3414 if (src->contentTypeTag == NULL((void*)0))
3415 src->contentTypeTag = SECOID_FindOIDSECOID_FindOID_Util(&(src->contentType));
3416
3417 if (src->contentTypeTag == NULL((void*)0)) {
3418 desc = "Unknown";
3419 kind = SEC_OID_UNKNOWN;
3420 } else {
3421 desc = src->contentTypeTag->desc;
3422 kind = src->contentTypeTag->offset;
3423 }
3424
3425 if (src->content.data == NULL((void*)0)) {
3426 SECU_Indent(out, level);
3427 fprintf(out, "%s:\n", desc);
3428 level++;
3429 SECU_Indent(out, level);
3430 fprintf(out, "<no content>\n");
3431 return 0;
3432 }
3433
3434 rv = 0;
3435 switch (kind) {
3436 case SEC_OID_PKCS7_SIGNED_DATA: /* Signed Data */
3437 rv = secu_PrintPKCS7Signed(out, src->content.signedData,
3438 state, desc, level);
3439 break;
3440
3441 case SEC_OID_PKCS7_ENVELOPED_DATA: /* Enveloped Data */
3442 rv = secu_PrintPKCS7Enveloped(out, src->content.envelopedData,
3443 state, desc, level);
3444 break;
3445
3446 case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: /* Signed and Enveloped */
3447 rv = secu_PrintPKCS7SignedAndEnveloped(out,
3448 src->content.signedAndEnvelopedData,
3449 state, desc, level);
3450 break;
3451
3452 case SEC_OID_PKCS7_DIGESTED_DATA: /* Digested Data */
3453 rv = secu_PrintPKCS7Digested(out, src->content.digestedData,
3454 state, desc, level);
3455 break;
3456
3457 case SEC_OID_PKCS7_ENCRYPTED_DATA: /* Encrypted Data */
3458 rv = secu_PrintPKCS7Encrypted(out, src->content.encryptedData,
3459 state, desc, level);
3460 break;
3461
3462 case SEC_OID_PKCS7_DATA:
3463 rv = secu_PrintPKCS7Data(out, src->content.data, state, desc, level);
3464 break;
3465
3466 default:
3467 SECU_PrintAsHex(out, src->content.data, desc, level);
3468 break;
3469 }
3470
3471 return rv;
3472}
3473
3474/*
3475** SECU_PrintPKCS7ContentInfo
3476** Decode and print any major PKCS7 data type (up to version 1).
3477*/
3478static int
3479secu_PrintDERPKCS7ContentInfo(FILE *out, SECItem *der, secuPKCS7State state,
3480 const char *m, int level)
3481{
3482 SEC_PKCS7ContentInfo *cinfo;
3483 int rv;
3484
3485 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));
3486 if (cinfo != NULL((void*)0)) {
3487 /* Send it to recursive parsing and printing module */
3488 rv = secu_PrintPKCS7ContentInfo(out, cinfo, state, m, level);
3489 SEC_PKCS7DestroyContentInfo(cinfo);
3490 } else {
3491 rv = -1;
3492 }
3493
3494 return rv;
3495}
3496
3497int
3498SECU_PrintPKCS7ContentInfo(FILE *out, SECItem *der, char *m, int level)
3499{
3500 return secu_PrintDERPKCS7ContentInfo(out, der, secuPKCS7Unknown, m, level);
3501}
3502
3503/*
3504** End of PKCS7 functions
3505*/
3506
3507void
3508printFlags(FILE *out, unsigned int flags, int level)
3509{
3510 if (flags & CERTDB_TERMINAL_RECORD(1u << 0)) {
3511 SECU_Indent(out, level);
3512 fprintf(out, "Terminal Record\n");
3513 }
3514 if (flags & CERTDB_TRUSTED(1u << 1)) {
3515 SECU_Indent(out, level);
3516 fprintf(out, "Trusted\n");
3517 }
3518 if (flags & CERTDB_SEND_WARN(1u << 2)) {
3519 SECU_Indent(out, level);
3520 fprintf(out, "Warn When Sending\n");
3521 }
3522 if (flags & CERTDB_VALID_CA(1u << 3)) {
3523 SECU_Indent(out, level);
3524 fprintf(out, "Valid CA\n");
3525 }
3526 if (flags & CERTDB_TRUSTED_CA(1u << 4)) {
3527 SECU_Indent(out, level);
3528 fprintf(out, "Trusted CA\n");
3529 }
3530 if (flags & CERTDB_NS_TRUSTED_CA(1u << 5)) {
3531 SECU_Indent(out, level);
3532 fprintf(out, "Netscape Trusted CA\n");
3533 }
3534 if (flags & CERTDB_USER(1u << 6)) {
3535 SECU_Indent(out, level);
3536 fprintf(out, "User\n");
3537 }
3538 if (flags & CERTDB_TRUSTED_CLIENT_CA(1u << 7)) {
3539 SECU_Indent(out, level);
3540 fprintf(out, "Trusted Client CA\n");
3541 }
3542 if (flags & CERTDB_GOVT_APPROVED_CA(1u << 9)) {
3543 SECU_Indent(out, level);
3544 fprintf(out, "Step-up\n");
3545 }
3546}
3547
3548void
3549SECU_PrintTrustFlags(FILE *out, CERTCertTrust *trust, char *m, int level)
3550{
3551 SECU_Indent(out, level);
3552 fprintf(out, "%s:\n", m);
3553 SECU_Indent(out, level + 1);
3554 fprintf(out, "SSL Flags:\n");
3555 printFlags(out, trust->sslFlags, level + 2);
3556 SECU_Indent(out, level + 1);
3557 fprintf(out, "Email Flags:\n");
3558 printFlags(out, trust->emailFlags, level + 2);
3559 SECU_Indent(out, level + 1);
3560 fprintf(out, "Object Signing Flags:\n");
3561 printFlags(out, trust->objectSigningFlags, level + 2);
3562}
3563
3564int
3565SECU_PrintDERName(FILE *out, SECItem *der, const char *m, int level)
3566{
3567 PLArenaPool *arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
3568 CERTName *name;
3569 int rv = SEC_ERROR_NO_MEMORY;
3570
3571 if (!arena)
3572 return rv;
3573
3574 name = PORT_ArenaZNew(arena, CERTName)(CERTName *)PORT_ArenaZAlloc_Util(arena, sizeof(CERTName));
3575 if (!name)
3576 goto loser;
3577
3578 rv = SEC_ASN1DecodeItemSEC_ASN1DecodeItem_Util(arena, name, SEC_ASN1_GET(CERT_NameTemplate)CERT_NameTemplate, der);
3579 if (rv)
3580 goto loser;
3581
3582 SECU_PrintName(out, name, m, level);
3583 if (!SECU_GetWrapEnabled()) /*SECU_PrintName didn't add newline*/
3584 SECU_Newline(out);
3585loser:
3586 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
3587 return rv;
3588}
3589
3590typedef enum {
3591 noSignature = 0,
3592 withSignature = 1
3593} SignatureOptionType;
3594
3595static int
3596secu_PrintSignedDataSigOpt(FILE *out, SECItem *der, const char *m,
3597 int level, SECU_PPFunc inner,
3598 SignatureOptionType signatureOption)
3599{
3600 PLArenaPool *arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
3601 CERTSignedData *sd;
3602 int rv = SEC_ERROR_NO_MEMORY;
3603
3604 if (!arena)
3605 return rv;
3606
3607 /* Strip off the signature */
3608 sd = PORT_ArenaZNew(arena, CERTSignedData)(CERTSignedData *)PORT_ArenaZAlloc_Util(arena, sizeof(CERTSignedData
))
;
3609 if (!sd)
3610 goto loser;
3611
3612 rv = SEC_ASN1DecodeItemSEC_ASN1DecodeItem_Util(arena, sd, SEC_ASN1_GET(CERT_SignedDataTemplate)CERT_SignedDataTemplate,
3613 der);
3614 if (rv)
3615 goto loser;
3616
3617 if (m) {
3618 SECU_Indent(out, level);
3619 fprintf(out, "%s:\n", m);
3620 } else {
3621 level -= 1;
3622 }
3623 rv = (*inner)(out, &sd->data, "Data", level + 1);
3624
3625 if (signatureOption == withSignature) {
3626 SECU_PrintAlgorithmID(out, &sd->signatureAlgorithm, "Signature Algorithm",
3627 level + 1);
3628 DER_ConvertBitString(&sd->signature){ (&sd->signature)->len = ((&sd->signature)->
len + 7) >> 3; }
;
3629 SECU_PrintAsHex(out, &sd->signature, "Signature", level + 1);
3630 }
3631 SECU_PrintFingerprints(out, der, "Fingerprint", level + 1);
3632loser:
3633 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
3634 return rv;
3635}
3636
3637int
3638SECU_PrintSignedData(FILE *out, SECItem *der, const char *m,
3639 int level, SECU_PPFunc inner)
3640{
3641 return secu_PrintSignedDataSigOpt(out, der, m, level, inner,
3642 withSignature);
3643}
3644
3645int
3646SECU_PrintSignedContent(FILE *out, SECItem *der, char *m,
3647 int level, SECU_PPFunc inner)
3648{
3649 return secu_PrintSignedDataSigOpt(out, der, m, level, inner,
3650 noSignature);
3651}
3652
3653SECStatus
3654SEC_PrintCertificateAndTrust(CERTCertificate *cert,
3655 const char *label,
3656 CERTCertTrust *trust)
3657{
3658 SECStatus rv;
3659 SECItem data;
3660 CERTCertTrust certTrust;
3661 PK11SlotList *slotList;
3662 PRBool falseAttributeFound = PR_FALSE0;
3663 PRBool trueAttributeFound = PR_FALSE0;
3664 const char *moz_policy_ca_info = NULL((void*)0);
3665
3666 data.data = cert->derCert.data;
3667 data.len = cert->derCert.len;
3668
3669 rv = SECU_PrintSignedData(stdoutstdout, &data, label, 0,
3670 SECU_PrintCertificate);
3671 if (rv) {
3672 return (SECFailure);
3673 }
3674
3675 slotList = PK11_GetAllSlotsForCert(cert, NULL((void*)0));
3676 if (slotList) {
3677 PK11SlotListElement *se = PK11_GetFirstSafe(slotList);
3678 for (; se; se = PK11_GetNextSafe(slotList, se, PR_FALSE0)) {
3679 CK_OBJECT_HANDLE handle = PK11_FindCertInSlot(se->slot, cert, NULL((void*)0));
3680 if (handle != CK_INVALID_HANDLE0) {
3681 PORT_SetErrorPORT_SetError_Util(0);
3682 if (PK11_HasAttributeSet(se->slot, handle,
3683 CKA_NSS_MOZILLA_CA_POLICY((0x80000000UL | 0x4E534350) + 34), PR_FALSE0)) {
3684 trueAttributeFound = PR_TRUE1;
3685 } else if (!PORT_GetErrorPORT_GetError_Util()) {
3686 falseAttributeFound = PR_TRUE1;
3687 }
3688 }
3689 }
3690 PK11_FreeSlotList(slotList);
3691 }
3692
3693 if (trueAttributeFound) {
3694 moz_policy_ca_info = "true (attribute present)";
3695 } else if (falseAttributeFound) {
3696 moz_policy_ca_info = "false (attribute present)";
3697 } else {
3698 moz_policy_ca_info = "false (attribute missing)";
3699 }
3700 SECU_Indent(stdoutstdout, 1);
3701 printf("Mozilla-CA-Policy: %s\n", moz_policy_ca_info);
3702
3703 if (trust) {
3704 SECU_PrintTrustFlags(stdoutstdout, trust,
3705 "Certificate Trust Flags", 1);
3706 } else if (CERT_GetCertTrust(cert, &certTrust) == SECSuccess) {
3707 SECU_PrintTrustFlags(stdoutstdout, &certTrust,
3708 "Certificate Trust Flags", 1);
3709 }
3710
3711 /* The distrust fields are hard-coded in nssckbi and read-only.
3712 * If verifying some cert, with vfychain, for instance, the certificate may
3713 * not have a defined slot if not imported. */
3714 if (cert->slot != NULL((void*)0) && cert->distrust != NULL((void*)0)) {
3715 const unsigned int kDistrustFieldSize = 13;
3716 fprintf(stdoutstdout, "\n");
3717 SECU_Indent(stdoutstdout, 1);
3718 fprintf(stdoutstdout, "%s:\n", "Certificate Distrust Dates");
3719 if (cert->distrust->serverDistrustAfter.len == kDistrustFieldSize) {
3720 SECU_PrintTimeChoice(stdoutstdout,
3721 &cert->distrust->serverDistrustAfter,
3722 "Server Distrust After", 2);
3723 }
3724 if (cert->distrust->emailDistrustAfter.len == kDistrustFieldSize) {
3725 SECU_PrintTimeChoice(stdoutstdout,
3726 &cert->distrust->emailDistrustAfter,
3727 "E-mail Distrust After", 2);
3728 }
3729 }
3730
3731 printf("\n");
3732
3733 return (SECSuccess);
3734}
3735
3736static char *
3737bestCertName(CERTCertificate *cert)
3738{
3739 if (cert->nickname) {
3740 return cert->nickname;
3741 }
3742 if (cert->emailAddr && cert->emailAddr[0]) {
3743 return cert->emailAddr;
3744 }
3745 return cert->subjectName;
3746}
3747
3748void
3749SECU_printCertProblemsOnDate(FILE *outfile, CERTCertDBHandle *handle,
3750 CERTCertificate *cert, PRBool checksig,
3751 SECCertificateUsage certUsage, void *pinArg, PRBool verbose,
3752 PRTime datetime)
3753{
3754 CERTVerifyLog log;
3755 CERTVerifyLogNode *node;
3756
3757 PRErrorCode err = PORT_GetErrorPORT_GetError_Util();
3758
3759 log.arena = PORT_NewArenaPORT_NewArena_Util(512);
3760 log.head = log.tail = NULL((void*)0);
3761 log.count = 0;
3762 CERT_VerifyCertificate(handle, cert, checksig, certUsage, datetime, pinArg, &log, NULL((void*)0));
3763
3764 SECU_displayVerifyLog(outfile, &log, verbose);
2
Calling 'SECU_displayVerifyLog'
3765
3766 for (node = log.head; node; node = node->next) {
3767 if (node->cert)
3768 CERT_DestroyCertificate(node->cert);
3769 }
3770 PORT_FreeArenaPORT_FreeArena_Util(log.arena, PR_FALSE0);
3771
3772 PORT_SetErrorPORT_SetError_Util(err); /* restore original error code */
3773}
3774
3775void
3776SECU_displayVerifyLog(FILE *outfile, CERTVerifyLog *log,
3777 PRBool verbose)
3778{
3779 CERTVerifyLogNode *node = NULL((void*)0);
3780 unsigned int depth = (unsigned int)-1;
3781 unsigned int flags = 0;
3782 char *errstr = NULL((void*)0);
3783
3784 if (log->count > 0) {
3
Assuming field 'count' is > 0
4
Taking true branch
3785 fprintf(outfile, "PROBLEM WITH THE CERT CHAIN:\n");
3786 for (node = log->head; node; node = node->next) {
5
Loop condition is true. Entering loop body
3787 if (depth != node->depth) {
6
Assuming 'depth' is equal to field 'depth'
7
Taking false branch
3788 depth = node->depth;
3789 fprintf(outfile, "CERT %d. %s %s:\n", depth,
3790 bestCertName(node->cert),
3791 depth ? "[Certificate Authority]" : "");
3792 if (verbose) {
3793 const char *emailAddr;
3794 emailAddr = CERT_GetFirstEmailAddress(node->cert);
3795 if (emailAddr) {
3796 fprintf(outfile, "Email Address(es): ");
3797 do {
3798 fprintf(outfile, "%s\n", emailAddr);
3799 emailAddr = CERT_GetNextEmailAddress(node->cert,
3800 emailAddr);
3801 } while (emailAddr);
3802 }
3803 }
3804 }
3805 fprintf(outfile, " ERROR %ld: %s\n", node->error,
3806 SECU_Strerror(node->error)PR_ErrorToString((node->error), 0));
3807 errstr = NULL((void*)0);
3808 switch (node->error) {
8
Control jumps to 'case SEC_ERROR_INADEQUATE_KEY_USAGE:' at line 3809
3809 case SEC_ERROR_INADEQUATE_KEY_USAGE:
3810 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
3811 switch (flags) {
3812 case KU_DIGITAL_SIGNATURE(0x80):
3813 errstr = "Cert cannot sign.";
3814 break;
3815 case KU_KEY_ENCIPHERMENT(0x20):
3816 errstr = "Cert cannot encrypt.";
3817 break;
3818 case KU_KEY_CERT_SIGN(0x04):
3819 errstr = "Cert cannot sign other certs.";
3820 break;
3821 default:
3822 errstr = "[unknown usage].";
3823 break;
3824 }
3825 break;
3826 case SEC_ERROR_INADEQUATE_CERT_TYPE:
3827 flags = (unsigned int)((char *)node->arg - (char *)NULL((void*)0));
3828 switch (flags) {
3829 case NS_CERT_TYPE_SSL_CLIENT(0x80):
3830 case NS_CERT_TYPE_SSL_SERVER(0x40):
3831 errstr = "Cert cannot be used for SSL.";
3832 break;
3833 case NS_CERT_TYPE_SSL_CA(0x04):
3834 errstr = "Cert cannot be used as an SSL CA.";
3835 break;
3836 case NS_CERT_TYPE_EMAIL(0x20):
3837 errstr = "Cert cannot be used for SMIME.";
3838 break;
3839 case NS_CERT_TYPE_EMAIL_CA(0x02):
3840 errstr = "Cert cannot be used as an SMIME CA.";
3841 break;
3842 case NS_CERT_TYPE_OBJECT_SIGNING(0x10):
3843 errstr = "Cert cannot be used for object signing.";
3844 break;
3845 case NS_CERT_TYPE_OBJECT_SIGNING_CA(0x01):
3846 errstr = "Cert cannot be used as an object signing CA.";
3847 break;
3848 default:
3849 errstr = "[unknown usage].";
3850 break;
3851 }
3852 break;
3853 case SEC_ERROR_UNKNOWN_ISSUER:
3854 case SEC_ERROR_UNTRUSTED_ISSUER:
3855 case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
3856 errstr = node->cert->issuerName;
3857 break;
3858 default:
3859 break;
3860 }
3861 if (errstr) {
3862 fprintf(stderrstderr, " %s\n", errstr);
3863 }
3864 }
3865 }
3866}
3867
3868void
3869SECU_printCertProblems(FILE *outfile, CERTCertDBHandle *handle,
3870 CERTCertificate *cert, PRBool checksig,
3871 SECCertificateUsage certUsage, void *pinArg, PRBool verbose)
3872{
3873 SECU_printCertProblemsOnDate(outfile, handle, cert, checksig,
1
Calling 'SECU_printCertProblemsOnDate'
3874 certUsage, pinArg, verbose, PR_Now());
3875}
3876
3877SECStatus
3878SECU_StoreCRL(PK11SlotInfo *slot, SECItem *derCrl, PRFileDesc *outFile,
3879 PRBool ascii, char *url)
3880{
3881 PORT_Assert(derCrl != NULL)((derCrl != ((void*)0)) ? ((void)0) : PR_Assert("derCrl != NULL"
, "/root/firefox-clang/security/nss/cmd/lib/secutil.c", 3881)
)
;
3882 if (!derCrl) {
3883 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
3884 return SECFailure;
3885 }
3886
3887 if (outFile != NULL((void*)0)) {
3888 if (ascii) {
3889 PR_fprintf(outFile, "%s\n%s\n%s\n", NS_CRL_HEADER"-----BEGIN CRL-----",
3890 BTOA_DataToAsciiBTOA_DataToAscii_Util(derCrl->data, derCrl->len),
3891 NS_CRL_TRAILER"-----END CRL-----");
3892 } else {
3893 if (PR_Write(outFile, derCrl->data, derCrl->len) != derCrl->len) {
3894 return SECFailure;
3895 }
3896 }
3897 }
3898 if (slot) {
3899 CERTSignedCrl *newCrl = PK11_ImportCRL(slot, derCrl, url,
3900 SEC_CRL_TYPE1, NULL((void*)0), 0, NULL((void*)0), 0);
3901 if (newCrl != NULL((void*)0)) {
3902 SEC_DestroyCrl(newCrl);
3903 return SECSuccess;
3904 }
3905 return SECFailure;
3906 }
3907 if (!outFile && !slot) {
3908 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
3909 return SECFailure;
3910 }
3911 return SECSuccess;
3912}
3913
3914SECStatus
3915SECU_SignAndEncodeCRL(CERTCertificate *issuer, CERTSignedCrl *signCrl,
3916 SECOidTag hashAlgTag, SignAndEncodeFuncExitStat *resCode)
3917{
3918 SECItem der;
3919 SECKEYPrivateKey *caPrivateKey = NULL((void*)0);
3920 SECStatus rv;
3921 PLArenaPool *arena;
3922 SECOidTag algID;
3923 void *dummy;
3924
3925 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", 3925)
)
;
3926 if (!issuer || !signCrl) {
3927 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
3928 return SECFailure;
3929 }
3930
3931 arena = signCrl->arena;
3932
3933 caPrivateKey = PK11_FindKeyByAnyCert(issuer, NULL((void*)0));
3934 if (caPrivateKey == NULL((void*)0)) {
3935 *resCode = noKeyFound;
3936 return SECFailure;
3937 }
3938
3939 algID = SEC_GetSignatureAlgorithmOidTagByKey(caPrivateKey, NULL((void*)0), hashAlgTag);
3940 if (algID == SEC_OID_UNKNOWN) {
3941 *resCode = noSignatureMatch;
3942 rv = SECFailure;
3943 goto done;
3944 }
3945
3946 if (!signCrl->crl.signatureAlg.parameters.data) {
3947 rv = SECOID_SetAlgorithmIDSECOID_SetAlgorithmID_Util(arena, &signCrl->crl.signatureAlg, algID, 0);
3948 if (rv != SECSuccess) {
3949 *resCode = failToEncode;
3950 goto done;
3951 }
3952 }
3953
3954 der.len = 0;
3955 der.data = NULL((void*)0);
3956 dummy = SEC_ASN1EncodeItemSEC_ASN1EncodeItem_Util(arena, &der, &signCrl->crl,
3957 SEC_ASN1_GET(CERT_CrlTemplate)CERT_CrlTemplate);
3958 if (!dummy) {
3959 *resCode = failToEncode;
3960 rv = SECFailure;
3961 goto done;
3962 }
3963
3964 rv = SECU_DerSignDataCRL(arena, &signCrl->signatureWrap,
3965 der.data, der.len, caPrivateKey, algID);
3966 if (rv != SECSuccess) {
3967 *resCode = failToSign;
3968 goto done;
3969 }
3970
3971 signCrl->derCrl = PORT_ArenaZNew(arena, SECItem)(SECItem *)PORT_ArenaZAlloc_Util(arena, sizeof(SECItem));
3972 if (signCrl->derCrl == NULL((void*)0)) {
3973 *resCode = noMem;
3974 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_MEMORY);
3975 rv = SECFailure;
3976 goto done;
3977 }
3978
3979 signCrl->derCrl->len = 0;
3980 signCrl->derCrl->data = NULL((void*)0);
3981 dummy = SEC_ASN1EncodeItemSEC_ASN1EncodeItem_Util(arena, signCrl->derCrl, signCrl,
3982 SEC_ASN1_GET(CERT_SignedCrlTemplate)CERT_SignedCrlTemplate);
3983 if (!dummy) {
3984 *resCode = failToEncode;
3985 rv = SECFailure;
3986 goto done;
3987 }
3988
3989done:
3990 SECKEY_DestroyPrivateKey(caPrivateKey);
3991 return rv;
3992}
3993
3994SECStatus
3995SECU_CopyCRL(PLArenaPool *destArena, CERTCrl *destCrl, CERTCrl *srcCrl)
3996{
3997 void *dummy;
3998 SECStatus rv = SECSuccess;
3999 SECItem der;
4000
4001 PORT_Assert(destArena && srcCrl && destCrl)((destArena && srcCrl && destCrl) ? ((void)0)
: PR_Assert("destArena && srcCrl && destCrl"
, "/root/firefox-clang/security/nss/cmd/lib/secutil.c", 4001)
)
;
4002 if (!destArena || !srcCrl || !destCrl) {
4003 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
4004 return SECFailure;
4005 }
4006
4007 der.len = 0;
4008 der.data = NULL((void*)0);
4009 dummy = SEC_ASN1EncodeItemSEC_ASN1EncodeItem_Util(destArena, &der, srcCrl,
4010 SEC_ASN1_GET(CERT_CrlTemplate)CERT_CrlTemplate);
4011 if (!dummy) {
4012 return SECFailure;
4013 }
4014
4015 rv = SEC_QuickDERDecodeItemSEC_QuickDERDecodeItem_Util(destArena, destCrl,
4016 SEC_ASN1_GET(CERT_CrlTemplate)CERT_CrlTemplate, &der);
4017 if (rv != SECSuccess) {
4018 return SECFailure;
4019 }
4020
4021 destCrl->arena = destArena;
4022
4023 return rv;
4024}
4025
4026SECStatus
4027SECU_DerSignDataCRL(PLArenaPool *arena, CERTSignedData *sd,
4028 unsigned char *buf, int len, SECKEYPrivateKey *pk,
4029 SECOidTag algID)
4030{
4031 SECItem it;
4032 SECStatus rv;
4033
4034 it.data = 0;
4035
4036 /* XXX We should probably have some asserts here to make sure the key type
4037 * and algID match
4038 */
4039
4040 /* Sign input buffer */
4041 rv = SEC_SignData(&it, buf, len, pk, algID);
4042 if (rv != SECSuccess) {
4043 goto loser;
4044 }
4045
4046 /* Fill out SignedData object */
4047 PORT_Memsetmemset(sd, 0, sizeof(*sd));
4048 sd->data.data = buf;
4049 sd->data.len = len;
4050 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(arena, &sd->signature, &it);
4051 if (rv != SECSuccess) {
4052 goto loser;
4053 }
4054
4055 sd->signature.len <<= 3; /* convert to bit string */
4056 rv = SECOID_SetAlgorithmIDSECOID_SetAlgorithmID_Util(arena, &sd->signatureAlgorithm, algID, 0);
4057 if (rv != SECSuccess) {
4058 goto loser;
4059 }
4060
4061loser:
4062 PORT_FreePORT_Free_Util(it.data);
4063 return rv;
4064}
4065
4066/*
4067 * Find the issuer of a Crl. Use the authorityKeyID if it exists.
4068 */
4069CERTCertificate *
4070SECU_FindCrlIssuer(CERTCertDBHandle *dbhandle, SECItem *subject,
4071 CERTAuthKeyID *authorityKeyID, PRTime validTime)
4072{
4073 CERTCertificate *issuerCert = NULL((void*)0);
4074 CERTCertList *certList = NULL((void*)0);
4075 CERTCertTrust trust;
4076
4077 if (!subject) {
4078 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
4079 return NULL((void*)0);
4080 }
4081
4082 certList =
4083 CERT_CreateSubjectCertList(NULL((void*)0), dbhandle, subject,
4084 validTime, PR_TRUE1);
4085 if (certList) {
4086 CERTCertListNode *node = CERT_LIST_HEAD(certList)((CERTCertListNode *)(&certList->list)->next);
4087
4088 /* XXX and authoritykeyid in the future */
4089 while (!CERT_LIST_END(node, certList)(((void *)node) == ((void *)&certList->list))) {
4090 CERTCertificate *cert = node->cert;
4091 /* check cert CERTCertTrust data is allocated, check cert
4092 usage extension, check that cert has pkey in db. Select
4093 the first (newest) user cert */
4094 if (CERT_GetCertTrust(cert, &trust) == SECSuccess &&
4095 CERT_CheckCertUsage(cert, KU_CRL_SIGN(0x02)) == SECSuccess &&
4096 CERT_IsUserCert(cert)) {
4097
4098 issuerCert = CERT_DupCertificate(cert);
4099 break;
4100 }
4101 node = CERT_LIST_NEXT(node)((CERTCertListNode *)node->links.next);
4102 }
4103 CERT_DestroyCertList(certList);
4104 }
4105 return (issuerCert);
4106}
4107
4108/* Encodes and adds extensions to the CRL or CRL entries. */
4109SECStatus
4110SECU_EncodeAndAddExtensionValue(PLArenaPool *arena, void *extHandle,
4111 void *value, PRBool criticality, int extenType,
4112 EXTEN_EXT_VALUE_ENCODER EncodeValueFn)
4113{
4114 SECItem encodedValue;
4115 SECStatus rv;
4116
4117 encodedValue.data = NULL((void*)0);
4118 encodedValue.len = 0;
4119 do {
4120 rv = (*EncodeValueFn)(arena, value, &encodedValue);
4121 if (rv != SECSuccess)
4122 break;
4123
4124 rv = CERT_AddExtension(extHandle, extenType, &encodedValue,
4125 criticality, PR_TRUE1);
4126 if (rv != SECSuccess)
4127 break;
4128 } while (0);
4129
4130 return (rv);
4131}
4132
4133CERTCertificate *
4134SECU_FindCertByNicknameOrFilename(CERTCertDBHandle *handle,
4135 char *name, PRBool ascii,
4136 void *pwarg)
4137{
4138 CERTCertificate *the_cert;
4139 the_cert = CERT_FindCertByNicknameOrEmailAddrCX(handle, name, pwarg);
4140 if (the_cert) {
4141 return the_cert;
4142 }
4143 the_cert = PK11_FindCertFromNickname(name, pwarg);
4144 if (!the_cert) {
4145 /* Don't have a cert with name "name" in the DB. Try to
4146 * open a file with such name and get the cert from there.*/
4147 SECStatus rv;
4148 SECItem item = { 0, NULL((void*)0), 0 };
4149 PRFileDesc *fd = PR_Open(name, PR_RDONLY0x01, 0777);
4150 if (!fd) {
4151 return NULL((void*)0);
4152 }
4153 rv = SECU_ReadDERFromFile(&item, fd, ascii, PR_FALSE0);
4154 PR_Close(fd);
4155 if (rv != SECSuccess || !item.len) {
4156 PORT_FreePORT_Free_Util(item.data);
4157 return NULL((void*)0);
4158 }
4159 the_cert = CERT_NewTempCertificate(handle, &item,
4160 NULL((void*)0) /* nickname */,
4161 PR_FALSE0 /* isPerm */,
4162 PR_TRUE1 /* copyDER */);
4163 PORT_FreePORT_Free_Util(item.data);
4164 }
4165 return the_cert;
4166}
4167
4168/* Convert a SSL/TLS protocol version string into the respective numeric value
4169 * defined by the SSL_LIBRARY_VERSION_* constants,
4170 * while accepting a flexible set of case-insensitive identifiers.
4171 *
4172 * Caller must specify bufLen, allowing the function to operate on substrings.
4173 */
4174static SECStatus
4175SECU_GetSSLVersionFromName(const char *buf, size_t bufLen, PRUint16 *version)
4176{
4177 if (!buf || !version) {
4178 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
4179 return SECFailure;
4180 }
4181
4182 if (!PL_strncasecmp(buf, "ssl3", bufLen)) {
4183 *version = SSL_LIBRARY_VERSION_3_00x0300;
4184 return SECSuccess;
4185 }
4186 if (!PL_strncasecmp(buf, "tls1.0", bufLen)) {
4187 *version = SSL_LIBRARY_VERSION_TLS_1_00x0301;
4188 return SECSuccess;
4189 }
4190 if (!PL_strncasecmp(buf, "tls1.1", bufLen)) {
4191 *version = SSL_LIBRARY_VERSION_TLS_1_10x0302;
4192 return SECSuccess;
4193 }
4194 if (!PL_strncasecmp(buf, "tls1.2", bufLen)) {
4195 *version = SSL_LIBRARY_VERSION_TLS_1_20x0303;
4196 return SECSuccess;
4197 }
4198
4199 if (!PL_strncasecmp(buf, "tls1.3", bufLen)) {
4200 *version = SSL_LIBRARY_VERSION_TLS_1_30x0304;
4201 return SECSuccess;
4202 }
4203
4204 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
4205 return SECFailure;
4206}
4207
4208SECStatus
4209SECU_ParseSSLVersionRangeString(const char *input,
4210 const SSLVersionRange defaultVersionRange,
4211 SSLVersionRange *vrange)
4212{
4213 const char *colonPos;
4214 size_t colonIndex;
4215 const char *maxStr;
4216
4217 if (!input || !vrange) {
4218 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
4219 return SECFailure;
4220 }
4221
4222 // We don't support SSL2 any longer.
4223 if (defaultVersionRange.min < SSL_LIBRARY_VERSION_3_00x0300 ||
4224 defaultVersionRange.max < SSL_LIBRARY_VERSION_3_00x0300) {
4225 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
4226 return SECFailure;
4227 }
4228
4229 if (!strcmp(input, ":")) {
4230 /* special value, use default */
4231 *vrange = defaultVersionRange;
4232 return SECSuccess;
4233 }
4234
4235 colonPos = strchr(input, ':');
4236 if (!colonPos) {
4237 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
4238 return SECFailure;
4239 }
4240
4241 colonIndex = colonPos - input;
4242 maxStr = colonPos + 1;
4243
4244 if (!colonIndex) {
4245 /* colon was first character, min version is empty */
4246 vrange->min = defaultVersionRange.min;
4247 } else {
4248 PRUint16 version;
4249 /* colonIndex is equivalent to the length of the min version substring */
4250 if (SECU_GetSSLVersionFromName(input, colonIndex, &version) != SECSuccess) {
4251 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
4252 return SECFailure;
4253 }
4254
4255 vrange->min = version;
4256 }
4257
4258 if (!*maxStr) {
4259 vrange->max = defaultVersionRange.max;
4260 } else {
4261 PRUint16 version;
4262 /* if max version is empty, then maxStr points to the string terminator */
4263 if (SECU_GetSSLVersionFromName(maxStr, strlen(maxStr), &version) !=
4264 SECSuccess) {
4265 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
4266 return SECFailure;
4267 }
4268
4269 vrange->max = version;
4270 }
4271
4272 if (vrange->min > vrange->max) {
4273 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
4274 return SECFailure;
4275 }
4276
4277 return SECSuccess;
4278}
4279
4280#define NAME_AND_LEN(s)sizeof(s) - 1, s sizeof(s) - 1, s
4281static const struct SSLNamedGroupString {
4282 int len;
4283 char *name;
4284 SSLNamedGroup grp;
4285} sslNamedGroupStringArray[] = {
4286 { NAME_AND_LEN("P256")sizeof("P256") - 1, "P256", ssl_grp_ec_secp256r1 },
4287 { NAME_AND_LEN("P384")sizeof("P384") - 1, "P384", ssl_grp_ec_secp384r1 },
4288 { NAME_AND_LEN("P521")sizeof("P521") - 1, "P521", ssl_grp_ec_secp521r1 },
4289 { NAME_AND_LEN("x25519")sizeof("x25519") - 1, "x25519", ssl_grp_ec_curve25519 },
4290 { NAME_AND_LEN("FF2048")sizeof("FF2048") - 1, "FF2048", ssl_grp_ffdhe_2048 },
4291 { NAME_AND_LEN("FF3072")sizeof("FF3072") - 1, "FF3072", ssl_grp_ffdhe_3072 },
4292 { NAME_AND_LEN("FF4096")sizeof("FF4096") - 1, "FF4096", ssl_grp_ffdhe_4096 },
4293 { NAME_AND_LEN("FF6144")sizeof("FF6144") - 1, "FF6144", ssl_grp_ffdhe_6144 },
4294 { NAME_AND_LEN("FF8192")sizeof("FF8192") - 1, "FF8192", ssl_grp_ffdhe_8192 },
4295#ifndef NSS_DISABLE_KYBER
4296 { NAME_AND_LEN("xyber76800")sizeof("xyber76800") - 1, "xyber76800", ssl_grp_kem_xyber768d00 },
4297#endif
4298 { NAME_AND_LEN("x25519mlkem768")sizeof("x25519mlkem768") - 1, "x25519mlkem768", ssl_grp_kem_mlkem768x25519 },
4299 { NAME_AND_LEN("secp256r1mlkem768")sizeof("secp256r1mlkem768") - 1, "secp256r1mlkem768", ssl_grp_kem_secp256r1mlkem768 },
4300 { NAME_AND_LEN("secp384r1mlkem1024")sizeof("secp384r1mlkem1024") - 1, "secp384r1mlkem1024", ssl_grp_kem_secp384r1mlkem1024 },
4301 // keep for compatibility
4302 { NAME_AND_LEN("mlkem768x25519")sizeof("mlkem768x25519") - 1, "mlkem768x25519", ssl_grp_kem_mlkem768x25519 },
4303};
4304
4305static const size_t sslNamedGroupStringLen = PR_ARRAY_SIZE(sslNamedGroupStringArray)(sizeof(sslNamedGroupStringArray) / sizeof((sslNamedGroupStringArray
)[0]))
;
4306
4307static SSLNamedGroup
4308groupNameToNamedGroup(char *name)
4309{
4310 int len = PL_strlen(name);
4311 int i;
4312
4313 for (i = 0; i < sslNamedGroupStringLen; i++) {
4314 const struct SSLNamedGroupString *ngs = &sslNamedGroupStringArray[i];
4315 if (len == ngs->len) {
4316 if (!strncmp(name, ngs->name, len)) {
4317 return ngs->grp;
4318 }
4319 }
4320 }
4321 return ssl_grp_none;
4322}
4323
4324static SECStatus
4325countItems(const char *arg, unsigned int *numItems)
4326{
4327 char *str = PORT_StrdupPORT_Strdup_Util(arg);
4328 if (!str) {
4329 return SECFailure;
4330 }
4331 char *p = strtok(str, ",");
4332 while (p) {
4333 ++(*numItems);
4334 p = strtok(NULL((void*)0), ",");
4335 }
4336 PORT_FreePORT_Free_Util(str);
4337 str = NULL((void*)0);
4338 return SECSuccess;
4339}
4340
4341SECStatus
4342parseGroupList(const char *arg, SSLNamedGroup **enabledGroups,
4343 unsigned int *enabledGroupsCount)
4344{
4345 SSLNamedGroup *groups;
4346 char *str;
4347 char *p;
4348 unsigned int numValues = 0;
4349 unsigned int count = 0;
4350
4351 if (countItems(arg, &numValues) != SECSuccess) {
4352 return SECFailure;
4353 }
4354 groups = PORT_ZNewArray(SSLNamedGroup, numValues)(SSLNamedGroup *)PORT_ZAlloc_Util(sizeof(SSLNamedGroup) * (numValues
))
;
4355 if (!groups) {
4356 return SECFailure;
4357 }
4358
4359 /* Get group names. */
4360 str = PORT_StrdupPORT_Strdup_Util(arg);
4361 if (!str) {
4362 goto done;
4363 }
4364 p = strtok(str, ",");
4365 while (p) {
4366 SSLNamedGroup group = groupNameToNamedGroup(p);
4367 if (group == ssl_grp_none) {
4368 count = 0;
4369 goto done;
4370 }
4371 groups[count++] = group;
4372 p = strtok(NULL((void*)0), ",");
4373 }
4374
4375done:
4376 PORT_FreePORT_Free_Util(str);
4377 if (!count) {
4378 PORT_FreePORT_Free_Util(groups);
4379 return SECFailure;
4380 }
4381
4382 *enabledGroupsCount = count;
4383 *enabledGroups = groups;
4384 return SECSuccess;
4385}
4386
4387const char *
4388SECU_NamedGroupToGroupName(SSLNamedGroup grp)
4389{
4390 int i;
4391 static char unknownBuf[32];
4392
4393 if (grp == ssl_grp_none) {
4394 return "None";
4395 }
4396
4397 for (i = 0; i < sslNamedGroupStringLen; i++) {
4398 const struct SSLNamedGroupString *ngs = &sslNamedGroupStringArray[i];
4399 if (grp == ngs->grp) {
4400 return ngs->name;
4401 }
4402 }
4403 snprintf(unknownBuf, sizeof(unknownBuf), "Unknown %04x\n", grp);
4404
4405 return unknownBuf;
4406}
4407
4408const char *
4409SECU_NamedGroupGetNextName(size_t i)
4410{
4411 if (i >= sslNamedGroupStringLen) {
4412 return NULL((void*)0);
4413 }
4414 return sslNamedGroupStringArray[i].name;
4415}
4416
4417#define MAKE_SCHEME(x){ sizeof("x") - 1, "x", ssl_sig_x } \
4418 { \
4419 sizeof(#x) - 1, #x, ssl_sig_##x \
4420 }
4421static const struct SSLSignatureSchemeString {
4422 int len;
4423 char *name;
4424 SSLSignatureScheme scheme;
4425} sslSignatureSchemeStringArray[] = {
4426 MAKE_SCHEME(rsa_pkcs1_sha1){ sizeof("rsa_pkcs1_sha1") - 1, "rsa_pkcs1_sha1", ssl_sig_rsa_pkcs1_sha1
}
,
4427 MAKE_SCHEME(rsa_pkcs1_sha256){ sizeof("rsa_pkcs1_sha256") - 1, "rsa_pkcs1_sha256", ssl_sig_rsa_pkcs1_sha256
}
,
4428 MAKE_SCHEME(rsa_pkcs1_sha384){ sizeof("rsa_pkcs1_sha384") - 1, "rsa_pkcs1_sha384", ssl_sig_rsa_pkcs1_sha384
}
,
4429 MAKE_SCHEME(rsa_pkcs1_sha512){ sizeof("rsa_pkcs1_sha512") - 1, "rsa_pkcs1_sha512", ssl_sig_rsa_pkcs1_sha512
}
,
4430 MAKE_SCHEME(ecdsa_sha1){ sizeof("ecdsa_sha1") - 1, "ecdsa_sha1", ssl_sig_ecdsa_sha1 },
4431 MAKE_SCHEME(ecdsa_secp256r1_sha256){ sizeof("ecdsa_secp256r1_sha256") - 1, "ecdsa_secp256r1_sha256"
, ssl_sig_ecdsa_secp256r1_sha256 }
,
4432 MAKE_SCHEME(ecdsa_secp384r1_sha384){ sizeof("ecdsa_secp384r1_sha384") - 1, "ecdsa_secp384r1_sha384"
, ssl_sig_ecdsa_secp384r1_sha384 }
,
4433 MAKE_SCHEME(ecdsa_secp521r1_sha512){ sizeof("ecdsa_secp521r1_sha512") - 1, "ecdsa_secp521r1_sha512"
, ssl_sig_ecdsa_secp521r1_sha512 }
,
4434 MAKE_SCHEME(rsa_pss_rsae_sha256){ sizeof("rsa_pss_rsae_sha256") - 1, "rsa_pss_rsae_sha256", ssl_sig_rsa_pss_rsae_sha256
}
,
4435 MAKE_SCHEME(rsa_pss_rsae_sha384){ sizeof("rsa_pss_rsae_sha384") - 1, "rsa_pss_rsae_sha384", ssl_sig_rsa_pss_rsae_sha384
}
,
4436 MAKE_SCHEME(rsa_pss_rsae_sha512){ sizeof("rsa_pss_rsae_sha512") - 1, "rsa_pss_rsae_sha512", ssl_sig_rsa_pss_rsae_sha512
}
,
4437 MAKE_SCHEME(ed25519){ sizeof("ed25519") - 1, "ed25519", ssl_sig_ed25519 },
4438 MAKE_SCHEME(ed448){ sizeof("ed448") - 1, "ed448", ssl_sig_ed448 },
4439 MAKE_SCHEME(rsa_pss_pss_sha256){ sizeof("rsa_pss_pss_sha256") - 1, "rsa_pss_pss_sha256", ssl_sig_rsa_pss_pss_sha256
}
,
4440 MAKE_SCHEME(rsa_pss_pss_sha384){ sizeof("rsa_pss_pss_sha384") - 1, "rsa_pss_pss_sha384", ssl_sig_rsa_pss_pss_sha384
}
,
4441 MAKE_SCHEME(rsa_pss_pss_sha512){ sizeof("rsa_pss_pss_sha512") - 1, "rsa_pss_pss_sha512", ssl_sig_rsa_pss_pss_sha512
}
,
4442 MAKE_SCHEME(dsa_sha1){ sizeof("dsa_sha1") - 1, "dsa_sha1", ssl_sig_dsa_sha1 },
4443 MAKE_SCHEME(dsa_sha256){ sizeof("dsa_sha256") - 1, "dsa_sha256", ssl_sig_dsa_sha256 },
4444 MAKE_SCHEME(dsa_sha384){ sizeof("dsa_sha384") - 1, "dsa_sha384", ssl_sig_dsa_sha384 },
4445 MAKE_SCHEME(dsa_sha512){ sizeof("dsa_sha512") - 1, "dsa_sha512", ssl_sig_dsa_sha512 },
4446 MAKE_SCHEME(mldsa44){ sizeof("mldsa44") - 1, "mldsa44", ssl_sig_mldsa44 },
4447 MAKE_SCHEME(mldsa65){ sizeof("mldsa65") - 1, "mldsa65", ssl_sig_mldsa65 },
4448 MAKE_SCHEME(mldsa87){ sizeof("mldsa87") - 1, "mldsa87", ssl_sig_mldsa87 },
4449};
4450
4451static const size_t sslSignatureSchemeStringLen =
4452 PR_ARRAY_SIZE(sslSignatureSchemeStringArray)(sizeof(sslSignatureSchemeStringArray) / sizeof((sslSignatureSchemeStringArray
)[0]))
;
4453
4454const char *
4455SECU_SignatureSchemeGetNextScheme(size_t i)
4456{
4457 if (i >= sslSignatureSchemeStringLen) {
4458 return NULL((void*)0);
4459 }
4460 return sslSignatureSchemeStringArray[i].name;
4461}
4462
4463const char *
4464SECU_SignatureSchemeName(SSLSignatureScheme scheme)
4465{
4466 int i;
4467 static char unknownBuf[32];
4468
4469 if (scheme == ssl_sig_none) {
4470 return "None";
4471 }
4472
4473 for (i = 0; i < sslSignatureSchemeStringLen; i++) {
4474 const struct SSLSignatureSchemeString *schemp =
4475 &sslSignatureSchemeStringArray[i];
4476 if (scheme == schemp->scheme) {
4477 return schemp->name;
4478 }
4479 }
4480
4481 /* we don't include ssl_sig_rsa_pks1_sha1md5 in our list because we
4482 * don't want to select it from the command line, but if you are using
4483 * ssl3, it's possible for this signataure scheme to pop out, so we
4484 * want output it. The name is the same value tstclnt used for this
4485 * scheme originally */
4486 if (scheme == ssl_sig_rsa_pkcs1_sha1md5) {
4487 return "RSA PKCS#1 SHA1+MD5";
4488 }
4489
4490 snprintf(unknownBuf, sizeof(unknownBuf), "Unknown %04x\n", scheme);
4491
4492 return unknownBuf;
4493}
4494
4495SSLSignatureScheme
4496schemeNameToScheme(const char *name)
4497{
4498 int len = PL_strlen(name);
4499 int i;
4500
4501 for (i = 0; i < sslSignatureSchemeStringLen; i++) {
4502 const struct SSLSignatureSchemeString *schemp =
4503 &sslSignatureSchemeStringArray[i];
4504 if (len == schemp->len) {
4505 if (!strncmp(name, schemp->name, len)) {
4506 return schemp->scheme;
4507 }
4508 }
4509 }
4510 return ssl_sig_none;
4511}
4512
4513SECStatus
4514parseSigSchemeList(const char *arg, const SSLSignatureScheme **enabledSigSchemes,
4515 unsigned int *enabledSigSchemeCount)
4516{
4517 SSLSignatureScheme *schemes;
4518 unsigned int numValues = 0;
4519 unsigned int count = 0;
4520
4521 if (countItems(arg, &numValues) != SECSuccess) {
4522 return SECFailure;
4523 }
4524 schemes = PORT_ZNewArray(SSLSignatureScheme, numValues)(SSLSignatureScheme *)PORT_ZAlloc_Util(sizeof(SSLSignatureScheme
) * (numValues))
;
4525 if (!schemes) {
4526 return SECFailure;
4527 }
4528
4529 /* Get group names. */
4530 char *str = PORT_StrdupPORT_Strdup_Util(arg);
4531 if (!str) {
4532 goto done;
4533 }
4534 char *p = strtok(str, ",");
4535 while (p) {
4536 SSLSignatureScheme scheme = schemeNameToScheme(p);
4537 if (scheme == ssl_sig_none) {
4538 count = 0;
4539 goto done;
4540 }
4541 schemes[count++] = scheme;
4542 p = strtok(NULL((void*)0), ",");
4543 }
4544
4545done:
4546 PORT_FreePORT_Free_Util(str);
4547 if (!count) {
4548 PORT_FreePORT_Free_Util(schemes);
4549 return SECFailure;
4550 }
4551
4552 *enabledSigSchemeCount = count;
4553 *enabledSigSchemes = schemes;
4554 return SECSuccess;
4555}
4556
4557/* Parse the exporter spec in the form: LABEL[:OUTPUT-LENGTH[:CONTEXT]] */
4558static SECStatus
4559parseExporter(const char *arg,
4560 secuExporter *exporter)
4561{
4562 SECStatus rv = SECSuccess;
4563
4564 char *str = PORT_StrdupPORT_Strdup_Util(arg);
4565 if (!str) {
4566 rv = SECFailure;
4567 goto done;
4568 }
4569
4570 char *labelEnd = strchr(str, ':');
4571 if (labelEnd) {
4572 *labelEnd = '\0';
4573 labelEnd++;
4574
4575 /* To extract CONTEXT, first skip OUTPUT-LENGTH */
4576 char *outputEnd = strchr(labelEnd, ':');
4577 if (outputEnd) {
4578 *outputEnd = '\0';
4579 outputEnd++;
4580
4581 exporter->hasContext = PR_TRUE1;
4582 exporter->context.data = (unsigned char *)PORT_StrdupPORT_Strdup_Util(outputEnd);
4583 exporter->context.len = strlen(outputEnd);
4584 if (PORT_StrncasecmpPL_strncasecmp((char *)exporter->context.data, "0x", 2) == 0) {
4585 rv = SECU_SECItemHexStringToBinary(&exporter->context);
4586 if (rv != SECSuccess) {
4587 goto done;
4588 }
4589 }
4590 }
4591 }
4592
4593 if (labelEnd && *labelEnd != '\0') {
4594 long int outputLength = strtol(labelEnd, NULL((void*)0), 10);
4595 if (!(outputLength > 0 && outputLength <= UINT_MAX(2147483647 *2U +1U))) {
4596 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
4597 rv = SECFailure;
4598 goto done;
4599 }
4600 exporter->outputLength = outputLength;
4601 } else {
4602 exporter->outputLength = 20;
4603 }
4604
4605 char *label = PORT_StrdupPORT_Strdup_Util(str);
4606 exporter->label.data = (unsigned char *)label;
4607 exporter->label.len = strlen(label);
4608 if (PORT_StrncasecmpPL_strncasecmp((char *)exporter->label.data, "0x", 2) == 0) {
4609 rv = SECU_SECItemHexStringToBinary(&exporter->label);
4610 if (rv != SECSuccess) {
4611 goto done;
4612 }
4613 }
4614
4615done:
4616 PORT_FreePORT_Free_Util(str);
4617
4618 return rv;
4619}
4620
4621SECStatus
4622parseExporters(const char *arg,
4623 const secuExporter **enabledExporters,
4624 unsigned int *enabledExporterCount)
4625{
4626 secuExporter *exporters;
4627 unsigned int numValues = 0;
4628 unsigned int count = 0;
4629
4630 if (countItems(arg, &numValues) != SECSuccess) {
4631 return SECFailure;
4632 }
4633 exporters = PORT_ZNewArray(secuExporter, numValues)(secuExporter *)PORT_ZAlloc_Util(sizeof(secuExporter) * (numValues
))
;
4634 if (!exporters) {
4635 return SECFailure;
4636 }
4637
4638 /* Get exporter definitions. */
4639 char *str = PORT_StrdupPORT_Strdup_Util(arg);
4640 if (!str) {
4641 goto done;
4642 }
4643 char *p = strtok(str, ",");
4644 while (p) {
4645 SECStatus rv = parseExporter(p, &exporters[count++]);
4646 if (rv != SECSuccess) {
4647 count = 0;
4648 goto done;
4649 }
4650 p = strtok(NULL((void*)0), ",");
4651 }
4652
4653done:
4654 PORT_FreePORT_Free_Util(str);
4655 if (!count) {
4656 PORT_FreePORT_Free_Util(exporters);
4657 return SECFailure;
4658 }
4659
4660 *enabledExporterCount = count;
4661 *enabledExporters = exporters;
4662 return SECSuccess;
4663}
4664
4665static SECStatus
4666exportKeyingMaterial(PRFileDesc *fd, const secuExporter *exporter)
4667{
4668 SECStatus rv = SECSuccess;
4669 unsigned char *out = PORT_AllocPORT_Alloc_Util(exporter->outputLength);
4670
4671 if (!out) {
4672 fprintf(stderrstderr, "Unable to allocate buffer for keying material\n");
4673 return SECFailure;
4674 }
4675 rv = SSL_ExportKeyingMaterial(fd,
4676 (char *)exporter->label.data,
4677 exporter->label.len,
4678 exporter->hasContext,
4679 exporter->context.data,
4680 exporter->context.len,
4681 out,
4682 exporter->outputLength);
4683 if (rv != SECSuccess) {
4684 goto done;
4685 }
4686 fprintf(stdoutstdout, "Exported Keying Material:\n");
4687 secu_PrintRawString(stdoutstdout, (SECItem *)&exporter->label, "Label", 1);
4688 if (exporter->hasContext) {
4689 SECU_PrintAsHex(stdoutstdout, &exporter->context, "Context", 1);
4690 }
4691 SECU_Indent(stdoutstdout, 1);
4692 fprintf(stdoutstdout, "Length: %u\n", exporter->outputLength);
4693 SECItem temp = { siBuffer, out, exporter->outputLength };
4694 SECU_PrintAsHex(stdoutstdout, &temp, "Keying Material", 1);
4695
4696done:
4697 PORT_FreePORT_Free_Util(out);
4698 return rv;
4699}
4700
4701SECStatus
4702exportKeyingMaterials(PRFileDesc *fd,
4703 const secuExporter *exporters,
4704 unsigned int exporterCount)
4705{
4706 unsigned int i;
4707
4708 for (i = 0; i < exporterCount; i++) {
4709 SECStatus rv = exportKeyingMaterial(fd, &exporters[i]);
4710 if (rv != SECSuccess) {
4711 return rv;
4712 }
4713 }
4714
4715 return SECSuccess;
4716}
4717
4718SECStatus
4719readPSK(const char *arg, SECItem *psk, SECItem *label)
4720{
4721 SECStatus rv = SECFailure;
4722 char *str = PORT_StrdupPORT_Strdup_Util(arg);
4723 if (!str) {
4724 goto cleanup;
4725 }
4726
4727 char *pskBytes = strtok(str, ":");
4728 if (!pskBytes) {
4729 goto cleanup;
4730 }
4731 if (PORT_StrncasecmpPL_strncasecmp(pskBytes, "0x", 2) != 0) {
4732 goto cleanup;
4733 }
4734
4735 psk = SECU_HexString2SECItem(NULL((void*)0), psk, &pskBytes[2]);
4736 if (!psk || !psk->data || psk->len != strlen(&str[2]) / 2) {
4737 goto cleanup;
4738 }
4739
4740 SECItem labelItem = { siBuffer, NULL((void*)0), 0 };
4741 char *inLabel = strtok(NULL((void*)0), ":");
4742 if (inLabel) {
4743 labelItem.data = (unsigned char *)PORT_StrdupPORT_Strdup_Util(inLabel);
4744 if (!labelItem.data) {
4745 goto cleanup;
4746 }
4747 labelItem.len = strlen(inLabel);
4748
4749 if (PORT_StrncasecmpPL_strncasecmp(inLabel, "0x", 2) == 0) {
4750 rv = SECU_SECItemHexStringToBinary(&labelItem);
4751 if (rv != SECSuccess) {
4752 SECITEM_FreeItemSECITEM_FreeItem_Util(&labelItem, PR_FALSE0);
4753 goto cleanup;
4754 }
4755 }
4756 rv = SECSuccess;
4757 } else {
4758 PRUint8 defaultLabel[] = { 'C', 'l', 'i', 'e', 'n', 't', '_',
4759 'i', 'd', 'e', 'n', 't', 'i', 't', 'y' };
4760 SECItem src = { siBuffer, defaultLabel, sizeof(defaultLabel) };
4761 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(NULL((void*)0), &labelItem, &src);
4762 }
4763 if (rv == SECSuccess) {
4764 *label = labelItem;
4765 }
4766
4767cleanup:
4768 PORT_FreePORT_Free_Util(str);
4769 return rv;
4770}
4771
4772static SECStatus
4773secu_PrintPKCS12DigestInfo(FILE *out, const SECItem *t, char *m, int level)
4774{
4775 SECItem my = *t;
4776 SECItem rawDigestAlgID;
4777 SECItem digestData;
4778 SECStatus rv;
4779 PLArenaPool *arena;
4780 SECAlgorithmID digestAlgID;
4781 char *mAlgID = NULL((void*)0);
4782 char *mDigest = NULL((void*)0);
4783
4784 /* strip the outer sequence */
4785 if ((my.data[0] != (SEC_ASN1_CONSTRUCTED0x20 | SEC_ASN1_SEQUENCE0x10)) ||
4786 SECSuccess != SECU_StripTagAndLength(&my)) {
4787 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
4788 return SECFailure;
4789 }
4790
4791 /* get the algorithm ID */
4792 if (SECSuccess != SECU_ExtractBERAndStep(&my, &rawDigestAlgID)) {
4793 return SECFailure;
4794 }
4795 arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
4796 if (arena == NULL((void*)0)) {
4797 return SECFailure;
4798 }
4799#define DIGEST_ALGID_STRING"Digest Algorithm ID" "Digest Algorithm ID"
4800 if (m)
4801 mAlgID = PR_smprintf("%s " DIGEST_ALGID_STRING"Digest Algorithm ID", m);
4802 rv = SEC_QuickDERDecodeItemSEC_QuickDERDecodeItem_Util(arena, &digestAlgID,
4803 SEC_ASN1_GET(SECOID_AlgorithmIDTemplate)SECOID_AlgorithmIDTemplate_Util,
4804 &rawDigestAlgID);
4805 if (rv == SECSuccess) {
4806 SECU_PrintAlgorithmID(out, &digestAlgID,
4807 mAlgID ? mAlgID : DIGEST_ALGID_STRING"Digest Algorithm ID", level);
4808 }
4809 if (mAlgID)
4810 PR_smprintf_free(mAlgID);
4811 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
4812 if (rv != SECSuccess) {
4813 return rv;
4814 }
4815
4816 /* get the mac data */
4817 if (SECSuccess != SECU_ExtractBERAndStep(&my, &digestData)) {
4818 return SECFailure;
4819 }
4820 if ((digestData.data[0] & SEC_ASN1_TAGNUM_MASK0x1f) != SEC_ASN1_OCTET_STRING0x04) {
4821 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
4822 return SECFailure;
4823 }
4824#define DIGEST_STRING"Digest" "Digest"
4825 if (m)
4826 mDigest = PR_smprintf("%s " DIGEST_STRING"Digest", m);
4827 secu_PrintOctetString(out, &digestData,
4828 mDigest ? mDigest : DIGEST_STRING"Digest", level);
4829 if (mDigest)
4830 PR_smprintf_free(mDigest);
4831 return SECSuccess;
4832}
4833
4834static SECStatus
4835secu_PrintPKCS12MacData(FILE *out, const SECItem *t, char *m, int level)
4836{
4837 SECItem my = *t;
4838 SECItem hash;
4839 SECItem salt;
4840
4841 if (m) {
4842 SECU_Indent(out, level);
4843 fprintf(out, "%s: \n", m);
4844 level++;
4845 }
4846
4847 /* strip the outer sequence */
4848 if ((my.data[0] != (SEC_ASN1_CONSTRUCTED0x20 | SEC_ASN1_SEQUENCE0x10)) ||
4849 SECSuccess != SECU_StripTagAndLength(&my)) {
4850 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
4851 return SECFailure;
4852 }
4853
4854 if (SECSuccess != SECU_ExtractBERAndStep(&my, &hash)) {
4855 return SECFailure;
4856 }
4857 if (SECSuccess != secu_PrintPKCS12DigestInfo(out, &hash, "Mac", level)) {
4858 return SECFailure;
4859 }
4860
4861 /* handle the salt */
4862 if (SECSuccess != SECU_ExtractBERAndStep(&my, &salt)) {
4863 return SECFailure;
4864 ;
4865 }
4866 if ((salt.data[0] & SEC_ASN1_TAGNUM_MASK0x1f) != SEC_ASN1_OCTET_STRING0x04) {
4867 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
4868 return SECFailure;
4869 }
4870 secu_PrintOctetString(out, &salt, "Mac Salt", level);
4871
4872 if (my.len &&
4873 ((my.data[0] & SEC_ASN1_TAGNUM_MASK0x1f) == SEC_ASN1_INTEGER0x02)) {
4874 SECItem iterator;
4875 if (SECSuccess != SECU_ExtractBERAndStep(&my, &iterator)) {
4876 return SECFailure;
4877 }
4878 SECU_PrintEncodedInteger(out, &iterator, "Iterations", level);
4879 }
4880 return SECSuccess;
4881}
4882
4883SECStatus
4884SECU_PrintPKCS12(FILE *out, const SECItem *t, char *m, int level)
4885{
4886 SECItem my = *t;
4887 SECItem authSafe;
4888 SECItem macData;
4889
4890 SECU_Indent(out, level);
4891 fprintf(out, "%s:\n", m);
4892 level++;
4893
4894 /* strip the outer sequence */
4895 if ((my.data[0] != (SEC_ASN1_CONSTRUCTED0x20 | SEC_ASN1_SEQUENCE0x10)) ||
4896 SECSuccess != SECU_StripTagAndLength(&my)) {
4897 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_BAD_DER);
4898 return SECFailure;
4899 }
4900 /* print and remove the optional version number */
4901 if (my.len && ((my.data[0] & SEC_ASN1_TAGNUM_MASK0x1f) == SEC_ASN1_INTEGER0x02)) {
4902 SECItem version;
4903
4904 if (SECSuccess != SECU_ExtractBERAndStep(&my, &version)) {
4905 return SECFailure;
4906 }
4907 SECU_PrintEncodedInteger(out, &version, "Version", level);
4908 }
4909
4910 /* print the authSafe */
4911 if (SECSuccess != SECU_ExtractBERAndStep(&my, &authSafe)) {
4912 return SECFailure;
4913 }
4914 if (SECSuccess != secu_PrintDERPKCS7ContentInfo(out, &authSafe,
4915 secuPKCS7PKCS12AuthSafe,
4916 "AuthSafe", level)) {
4917 return SECFailure;
4918 }
4919
4920 /* print the mac data (optional) */
4921 if (!my.len) {
4922 return SECSuccess;
4923 }
4924 if (SECSuccess != SECU_ExtractBERAndStep(&my, &macData)) {
4925 return SECFailure;
4926 }
4927 if (SECSuccess != secu_PrintPKCS12MacData(out, &macData,
4928 "Mac Data", level)) {
4929 return SECFailure;
4930 }
4931
4932 if (my.len) {
4933 fprintf(out, "Unknown extra data found \n");
4934 }
4935 return SECSuccess;
4936}