Bug Summary

File:root/firefox-clang/security/nss/cmd/certutil/certutil.c
Warning:line 62, column 13
Value stored to 'rv' is never read

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 certutil.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/certutil/certutil_certutil -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/security/nss/cmd/certutil/certutil_certutil -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_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/certutil -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/security/nss/cmd/certutil/certutil_certutil -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/private/nss -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -D MOZILLA_CLIENT -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=tautological-type-limit-compare -Wno-range-loop-analysis -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-unknown-warning-option -Wno-character-conversion -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-10-17-231001-351276-1 -x c /root/firefox-clang/security/nss/cmd/certutil/certutil.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/*
6** certutil.c
7**
8** utility for managing certificates and the cert database
9**
10*/
11#include <stdio.h>
12#include <string.h>
13#include <stdlib.h>
14
15#if defined(WIN32)
16#include "fcntl.h"
17#include "io.h"
18#endif
19
20#include "secutil.h"
21
22#if defined(XP_UNIX1)
23#include <unistd.h>
24#endif
25
26#include "nspr.h"
27#include "prtypes.h"
28#include "prtime.h"
29#include "prlong.h"
30
31#include "pk11func.h"
32#include "secasn1.h"
33#include "cert.h"
34#include "cryptohi.h"
35#include "secoid.h"
36#include "certdb.h"
37#include "nss.h"
38#include "certutil.h"
39#include "basicutil.h"
40#include "ssl.h"
41
42#define MIN_KEY_BITS512 512
43/* MAX_KEY_BITS should agree with RSA_MAX_MODULUS_BITS in freebl */
44#define MAX_KEY_BITS8192 8192
45#define DEFAULT_KEY_BITS2048 2048
46
47#define GEN_BREAK(e)rv = e; break; \
48 rv = e; \
49 break;
50
51char *progName;
52
53static SECStatus
54ChangeCertTrust(CERTCertDBHandle *handle, CERTCertificate *cert,
55 CERTCertTrust *trust, PK11SlotInfo *slot, void *pwdata)
56{
57 SECStatus rv;
58
59 rv = CERT_ChangeCertTrust(handle, cert, trust);
60 if (rv != SECSuccess) {
61 if (PORT_GetErrorPORT_GetError_Util() == SEC_ERROR_TOKEN_NOT_LOGGED_IN) {
62 rv = PK11_Authenticate(slot, PR_TRUE1, pwdata);
Value stored to 'rv' is never read
63 if (PORT_GetErrorPORT_GetError_Util() == SEC_ERROR_TOKEN_NOT_LOGGED_IN) {
64 PK11SlotInfo *internalslot;
65 internalslot = PK11_GetInternalKeySlot();
66 rv = PK11_Authenticate(internalslot, PR_TRUE1, pwdata);
67 if (rv != SECSuccess) {
68 SECU_PrintError(progName,
69 "could not authenticate to token %s.",
70 PK11_GetTokenName(internalslot));
71 PK11_FreeSlot(internalslot);
72 return SECFailure;
73 }
74 PK11_FreeSlot(internalslot);
75 }
76 rv = CERT_ChangeCertTrust(handle, cert, trust);
77 }
78 }
79 return rv;
80}
81
82static CERTCertificateRequest *
83GetCertRequest(const SECItem *reqDER, void *pwarg)
84{
85 CERTCertificateRequest *certReq = NULL((void*)0);
86 CERTSignedData signedData;
87 PLArenaPool *arena = NULL((void*)0);
88 SECStatus rv;
89
90 do {
91 arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
92 if (arena == NULL((void*)0)) {
93 GEN_BREAK(SECFailure)rv = SECFailure; break;;
94 }
95
96 certReq = (CERTCertificateRequest *)PORT_ArenaZAllocPORT_ArenaZAlloc_Util(arena, sizeof(CERTCertificateRequest));
97 if (!certReq) {
98 GEN_BREAK(SECFailure)rv = SECFailure; break;;
99 }
100 certReq->arena = arena;
101
102 /* Since cert request is a signed data, must decode to get the inner
103 data
104 */
105 PORT_Memsetmemset(&signedData, 0, sizeof(signedData));
106 rv = SEC_ASN1DecodeItemSEC_ASN1DecodeItem_Util(arena, &signedData,
107 SEC_ASN1_GET(CERT_SignedDataTemplate)CERT_SignedDataTemplate, reqDER);
108 if (rv) {
109 break;
110 }
111 rv = SEC_ASN1DecodeItemSEC_ASN1DecodeItem_Util(arena, certReq,
112 SEC_ASN1_GET(CERT_CertificateRequestTemplate)CERT_CertificateRequestTemplate, &signedData.data);
113 if (rv) {
114 break;
115 }
116 rv = CERT_VerifySignedDataWithPublicKeyInfo(&signedData,
117 &certReq->subjectPublicKeyInfo, pwarg);
118 } while (0);
119
120 if (rv) {
121 SECU_PrintError(progName, "bad certificate request\n");
122 if (arena) {
123 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
124 }
125 certReq = NULL((void*)0);
126 }
127
128 return certReq;
129}
130
131static SECStatus
132AddCert(PK11SlotInfo *slot, CERTCertDBHandle *handle, char *name, char *trusts,
133 const SECItem *certDER, PRBool emailcert, void *pwdata)
134{
135 CERTCertTrust *trust = NULL((void*)0);
136 CERTCertificate *cert = NULL((void*)0);
137 SECStatus rv;
138
139 do {
140 /* Read in an ASCII cert and return a CERTCertificate */
141 cert = CERT_DecodeCertFromPackage((char *)certDER->data, certDER->len);
142 if (!cert) {
143 SECU_PrintError(progName, "could not decode certificate");
144 GEN_BREAK(SECFailure)rv = SECFailure; break;;
145 }
146
147 /* Create a cert trust */
148 trust = (CERTCertTrust *)PORT_ZAllocPORT_ZAlloc_Util(sizeof(CERTCertTrust));
149 if (!trust) {
150 SECU_PrintError(progName, "unable to allocate cert trust");
151 GEN_BREAK(SECFailure)rv = SECFailure; break;;
152 }
153
154 rv = CERT_DecodeTrustString(trust, trusts);
155 if (rv) {
156 SECU_PrintError(progName, "unable to decode trust string");
157 GEN_BREAK(SECFailure)rv = SECFailure; break;;
158 }
159
160 rv = PK11_ImportCert(slot, cert, CK_INVALID_HANDLE0, name, PR_FALSE0);
161 if (rv != SECSuccess) {
162 /* sigh, PK11_Import Cert and CERT_ChangeCertTrust should have
163 * been coded to take a password arg. */
164 if (PORT_GetErrorPORT_GetError_Util() == SEC_ERROR_TOKEN_NOT_LOGGED_IN) {
165 rv = PK11_Authenticate(slot, PR_TRUE1, pwdata);
166 if (rv != SECSuccess) {
167 SECU_PrintError(progName,
168 "could not authenticate to token %s.",
169 PK11_GetTokenName(slot));
170 GEN_BREAK(SECFailure)rv = SECFailure; break;;
171 }
172 rv = PK11_ImportCert(slot, cert, CK_INVALID_HANDLE0,
173 name, PR_FALSE0);
174 }
175 if (rv != SECSuccess) {
176 SECU_PrintError(progName,
177 "could not add certificate to token or database");
178 GEN_BREAK(SECFailure)rv = SECFailure; break;;
179 }
180 }
181 rv = ChangeCertTrust(handle, cert, trust, slot, pwdata);
182 if (rv != SECSuccess) {
183 SECU_PrintError(progName,
184 "could not change trust on certificate");
185 GEN_BREAK(SECFailure)rv = SECFailure; break;;
186 }
187
188 if (emailcert) {
189 CERT_SaveSMimeProfile(cert, NULL((void*)0), pwdata);
190 }
191
192 } while (0);
193
194 CERT_DestroyCertificate(cert);
195 PORT_FreePORT_Free_Util(trust);
196
197 return rv;
198}
199
200static SECStatus
201CertReq(SECKEYPrivateKey *privk, SECKEYPublicKey *pubk, KeyType keyType,
202 SECOidTag hashAlgTag, CERTName *subject, const char *phone, int ascii,
203 const char *emailAddrs, const char *dnsNames,
204 certutilExtnList extnList, const char *extGeneric,
205 PRBool pssCertificate, /*out*/ SECItem *result)
206{
207 CERTSubjectPublicKeyInfo *spki;
208 CERTCertificateRequest *cr;
209 SECItem *encoding;
210 SECOidTag signAlgTag = SEC_OID_UNKNOWN;
211 SECStatus rv;
212 PLArenaPool *arena;
213 void *extHandle;
214 SECItem signedReq = { siBuffer, NULL((void*)0), 0 };
215 SECAlgorithmID signAlg;
216
217 arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
218 if (!arena) {
219 SECU_PrintError(progName, "out of memory");
220 return SECFailure;
221 }
222
223 /* Create info about public key */
224 spki = SECKEY_CreateSubjectPublicKeyInfo(pubk);
225 if (!spki) {
226 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
227 SECU_PrintError(progName, "unable to create subject public key");
228 return SECFailure;
229 }
230
231 /* Change cert type to RSA-PSS, if desired. */
232 if (pssCertificate) {
233 /* force a PSS signature. We can do a PSS signature with an
234 * RSA key, this will force us to generate a PSS signature */
235 signAlgTag = SEC_OID_PKCS1_RSA_PSS_SIGNATURE;
236 /* override the SPKI algorithm id. */
237 rv = SEC_CreateSignatureAlgorithmID(arena, &spki->algorithm,
238 signAlgTag, hashAlgTag,
239 NULL((void*)0), NULL((void*)0), pubk);
240 if (rv != SECSuccess) {
241 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
242 SECKEY_DestroySubjectPublicKeyInfo(spki);
243 SECU_PrintError(progName, "unable to set algorithm ID");
244 return SECFailure;
245 }
246 }
247
248 /* Generate certificate request */
249 cr = CERT_CreateCertificateRequest(subject, spki, NULL((void*)0));
250 SECKEY_DestroySubjectPublicKeyInfo(spki);
251 if (!cr) {
252 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
253 SECU_PrintError(progName, "unable to make certificate request");
254 return SECFailure;
255 }
256
257 extHandle = CERT_StartCertificateRequestAttributes(cr);
258 if (extHandle == NULL((void*)0)) {
259 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
260 CERT_DestroyCertificateRequest(cr);
261 return SECFailure;
262 }
263 if (AddExtensions(extHandle, emailAddrs, dnsNames, extnList, extGeneric) !=
264 SECSuccess) {
265 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
266 CERT_FinishExtensions(extHandle);
267 CERT_DestroyCertificateRequest(cr);
268 return SECFailure;
269 }
270 CERT_FinishExtensions(extHandle);
271 CERT_FinishCertificateRequestAttributes(cr);
272
273 /* Der encode the request */
274 encoding = SEC_ASN1EncodeItemSEC_ASN1EncodeItem_Util(arena, NULL((void*)0), cr,
275 SEC_ASN1_GET(CERT_CertificateRequestTemplate)CERT_CertificateRequestTemplate);
276 CERT_DestroyCertificateRequest(cr);
277 if (encoding == NULL((void*)0)) {
278 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
279 SECU_PrintError(progName, "der encoding of request failed");
280 return SECFailure;
281 }
282
283 PORT_Memsetmemset(&signAlg, 0, sizeof(signAlg));
284 rv = SEC_CreateSignatureAlgorithmID(arena, &signAlg, signAlgTag, hashAlgTag,
285 NULL((void*)0), privk, NULL((void*)0));
286 if (rv != SECSuccess) {
287 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
288 SECU_PrintError(progName, "can't create a signature algorithm id");
289 return SECFailure;
290 }
291
292 /* Sign the request */
293 rv = SEC_DerSignDataWithAlgorithmID(arena, &signedReq,
294 encoding->data, encoding->len,
295 privk, &signAlg);
296 if (rv) {
297 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
298 SECU_PrintError(progName, "signing of data failed");
299 return SECFailure;
300 }
301
302 /* Encode request in specified format */
303 if (ascii) {
304 char *obuf;
305 char *header, *name, *email, *org, *state, *country;
306
307 obuf = BTOA_ConvertItemToAsciiBTOA_ConvertItemToAscii_Util(&signedReq);
308 if (!obuf) {
309 goto oom;
310 }
311
312 name = CERT_GetCommonName(subject);
313 if (!name) {
314 name = PORT_StrdupPORT_Strdup_Util("(not specified)");
315 }
316
317 if (!phone)
318 phone = "(not specified)";
319
320 email = CERT_GetCertEmailAddress(subject);
321 if (!email)
322 email = PORT_StrdupPORT_Strdup_Util("(not specified)");
323
324 org = CERT_GetOrgName(subject);
325 if (!org)
326 org = PORT_StrdupPORT_Strdup_Util("(not specified)");
327
328 state = CERT_GetStateName(subject);
329 if (!state)
330 state = PORT_StrdupPORT_Strdup_Util("(not specified)");
331
332 country = CERT_GetCountryName(subject);
333 if (!country)
334 country = PORT_StrdupPORT_Strdup_Util("(not specified)");
335
336 header = PR_smprintf(
337 "\nCertificate request generated by Netscape certutil\n"
338 "Phone: %s\n\n"
339 "Common Name: %s\n"
340 "Email: %s\n"
341 "Organization: %s\n"
342 "State: %s\n"
343 "Country: %s\n\n"
344 "%s\n",
345 phone, name, email, org, state, country, NS_CERTREQ_HEADER"-----BEGIN NEW CERTIFICATE REQUEST-----");
346
347 PORT_FreePORT_Free_Util(name);
348 PORT_FreePORT_Free_Util(email);
349 PORT_FreePORT_Free_Util(org);
350 PORT_FreePORT_Free_Util(state);
351 PORT_FreePORT_Free_Util(country);
352
353 if (header) {
354 char *trailer = PR_smprintf("\n%s\n", NS_CERTREQ_TRAILER"-----END NEW CERTIFICATE REQUEST-----");
355 if (trailer) {
356 PRUint32 headerLen = PL_strlen(header);
357 PRUint32 obufLen = PL_strlen(obuf);
358 PRUint32 trailerLen = PL_strlen(trailer);
359 SECITEM_AllocItemSECITEM_AllocItem_Util(NULL((void*)0), result,
360 headerLen + obufLen + trailerLen);
361 if (result->data) {
362 PORT_Memcpymemcpy(result->data, header, headerLen);
363 PORT_Memcpymemcpy(result->data + headerLen, obuf, obufLen);
364 PORT_Memcpymemcpy(result->data + headerLen + obufLen,
365 trailer, trailerLen);
366 }
367 PR_smprintf_free(trailer);
368 }
369 PR_smprintf_free(header);
370 }
371 PORT_FreePORT_Free_Util(obuf);
372 } else {
373 (void)SECITEM_CopyItemSECITEM_CopyItem_Util(NULL((void*)0), result, &signedReq);
374 }
375
376 if (!result->data) {
377 oom:
378 SECU_PrintError(progName, "out of memory");
379 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_NO_MEMORY);
380 rv = SECFailure;
381 }
382
383 PORT_FreeArenaPORT_FreeArena_Util(arena, PR_FALSE0);
384 return rv;
385}
386
387static SECStatus
388ChangeTrustAttributes(CERTCertDBHandle *handle, PK11SlotInfo *slot,
389 char *name, char *trusts, void *pwdata)
390{
391 SECStatus rv;
392 CERTCertificate *cert;
393 CERTCertTrust *trust;
394
395 cert = CERT_FindCertByNicknameOrEmailAddrCX(handle, name, pwdata);
396 if (!cert) {
397 SECU_PrintError(progName, "could not find certificate named \"%s\"",
398 name);
399 return SECFailure;
400 }
401
402 trust = (CERTCertTrust *)PORT_ZAllocPORT_ZAlloc_Util(sizeof(CERTCertTrust));
403 if (!trust) {
404 SECU_PrintError(progName, "unable to allocate cert trust");
405 return SECFailure;
406 }
407
408 /* This function only decodes these characters: pPwcTCu, */
409 rv = CERT_DecodeTrustString(trust, trusts);
410 if (rv) {
411 SECU_PrintError(progName, "unable to decode trust string");
412 return SECFailure;
413 }
414
415 /* CERT_ChangeCertTrust API does not have a way to pass in
416 * a context, so NSS can't prompt for the password if it needs to.
417 * check to see if the failure was token not logged in and
418 * log in if need be. */
419 rv = ChangeCertTrust(handle, cert, trust, slot, pwdata);
420 if (rv != SECSuccess) {
421 SECU_PrintError(progName, "unable to modify trust attributes");
422 return SECFailure;
423 }
424 CERT_DestroyCertificate(cert);
425 PORT_FreePORT_Free_Util(trust);
426
427 return SECSuccess;
428}
429
430static SECStatus
431DumpChain(CERTCertDBHandle *handle, char *name, PRBool ascii,
432 PRBool simpleSelfSigned)
433{
434 CERTCertificate *the_cert;
435 CERTCertificateList *chain;
436 int i, j;
437 the_cert = SECU_FindCertByNicknameOrFilename(handle, name,
438 ascii, NULL((void*)0));
439 if (!the_cert) {
440 SECU_PrintError(progName, "Could not find: %s\n", name);
441 return SECFailure;
442 }
443 if (simpleSelfSigned &&
444 SECEqual == SECITEM_CompareItemSECITEM_CompareItem_Util(&the_cert->derIssuer,
445 &the_cert->derSubject)) {
446 printf("\"%s\" [%s]\n\n", the_cert->nickname, the_cert->subjectName);
447 CERT_DestroyCertificate(the_cert);
448 return SECSuccess;
449 }
450
451 chain = CERT_CertChainFromCert(the_cert, 0, PR_TRUE1);
452 CERT_DestroyCertificate(the_cert);
453 if (!chain) {
454 SECU_PrintError(progName, "Could not obtain chain for: %s\n", name);
455 return SECFailure;
456 }
457 for (i = chain->len - 1; i >= 0; i--) {
458 CERTCertificate *c;
459 c = CERT_FindCertByDERCert(handle, &chain->certs[i]);
460 for (j = i; j < chain->len - 1; j++) {
461 printf(" ");
462 }
463 if (c) {
464 printf("\"%s\" [%s]\n\n", c->nickname, c->subjectName);
465 CERT_DestroyCertificate(c);
466 } else {
467 printf("(null)\n\n");
468 }
469 }
470 CERT_DestroyCertificateList(chain);
471 return SECSuccess;
472}
473
474static SECStatus
475outputCertOrExtension(CERTCertificate *the_cert, PRBool raw, PRBool ascii,
476 SECItem *extensionOID, PRFileDesc *outfile)
477{
478 SECItem data;
479 PRInt32 numBytes;
480 SECStatus rv = SECFailure;
481 if (extensionOID) {
482 int i;
483 PRBool found = PR_FALSE0;
484 for (i = 0; the_cert->extensions[i] != NULL((void*)0); i++) {
485 CERTCertExtension *extension = the_cert->extensions[i];
486 if (SECITEM_CompareItemSECITEM_CompareItem_Util(&extension->id, extensionOID) == SECEqual) {
487 found = PR_TRUE1;
488 numBytes = PR_Write(outfile, extension->value.data,
489 extension->value.len);
490 rv = SECSuccess;
491 if (numBytes != (PRInt32)extension->value.len) {
492 SECU_PrintSystemError(progName, "error writing extension");
493 rv = SECFailure;
494 }
495 break;
496 }
497 }
498 if (!found) {
499 SECU_PrintSystemError(progName, "extension not found");
500 rv = SECFailure;
501 }
502 } else {
503 data.data = the_cert->derCert.data;
504 data.len = the_cert->derCert.len;
505 if (ascii) {
506 PR_fprintf(outfile, "%s\n%s\n%s\n", NS_CERT_HEADER"-----BEGIN CERTIFICATE-----",
507 BTOA_DataToAsciiBTOA_DataToAscii_Util(data.data, data.len), NS_CERT_TRAILER"-----END CERTIFICATE-----");
508 rv = SECSuccess;
509 } else if (raw) {
510 numBytes = PR_Write(outfile, data.data, data.len);
511 rv = SECSuccess;
512 if (numBytes != (PRInt32)data.len) {
513 SECU_PrintSystemError(progName, "error writing raw cert");
514 rv = SECFailure;
515 }
516 } else {
517 rv = SEC_PrintCertificateAndTrust(the_cert, "Certificate", NULL((void*)0));
518 if (rv != SECSuccess) {
519 SECU_PrintError(progName, "problem printing certificate");
520 }
521 }
522 }
523 return rv;
524}
525
526static SECStatus
527listCerts(CERTCertDBHandle *handle, char *name, char *email,
528 PK11SlotInfo *slot, PRBool raw, PRBool ascii,
529 SECItem *extensionOID,
530 PRFileDesc *outfile, void *pwarg)
531{
532 SECStatus rv = SECFailure;
533 CERTCertList *certs;
534 CERTCertListNode *node;
535
536 /* List certs on a non-internal slot. */
537 if (!PK11_IsFriendly(slot) && PK11_NeedLogin(slot)) {
538 SECStatus newrv = PK11_Authenticate(slot, PR_TRUE1, pwarg);
539 if (newrv != SECSuccess) {
540 SECU_PrintError(progName, "could not authenticate to token %s.",
541 PK11_GetTokenName(slot));
542 return SECFailure;
543 }
544 }
545 if (name) {
546 CERTCertificate *the_cert =
547 SECU_FindCertByNicknameOrFilename(handle, name, ascii, NULL((void*)0));
548 if (!the_cert) {
549 SECU_PrintError(progName, "Could not find cert: %s\n", name);
550 return SECFailure;
551 }
552 /* Here, we have one cert with the desired nickname or email
553 * address. Now, we will attempt to get a list of ALL certs
554 * with the same subject name as the cert we have. That list
555 * should contain, at a minimum, the one cert we have already found.
556 * If the list of certs is empty (NULL), the libraries have failed.
557 */
558 certs = CERT_CreateSubjectCertList(NULL((void*)0), handle, &the_cert->derSubject,
559 PR_Now(), PR_FALSE0);
560 CERT_DestroyCertificate(the_cert);
561 if (!certs) {
562 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_LIBRARY_FAILURE);
563 SECU_PrintError(progName, "problem printing certificates");
564 return SECFailure;
565 }
566 for (node = CERT_LIST_HEAD(certs)((CERTCertListNode *)(&certs->list)->next); !CERT_LIST_END(node, certs)(((void *)node) == ((void *)&certs->list));
567 node = CERT_LIST_NEXT(node)((CERTCertListNode *)node->links.next)) {
568 rv = outputCertOrExtension(node->cert, raw, ascii, extensionOID,
569 outfile);
570 if (rv != SECSuccess) {
571 break;
572 }
573 }
574 } else if (email) {
575 certs = PK11_FindCertsFromEmailAddress(email, NULL((void*)0));
576 if (!certs) {
577 SECU_PrintError(progName,
578 "Could not find certificates for email address: %s\n",
579 email);
580 return SECFailure;
581 }
582 for (node = CERT_LIST_HEAD(certs)((CERTCertListNode *)(&certs->list)->next); !CERT_LIST_END(node, certs)(((void *)node) == ((void *)&certs->list));
583 node = CERT_LIST_NEXT(node)((CERTCertListNode *)node->links.next)) {
584 rv = outputCertOrExtension(node->cert, raw, ascii, extensionOID,
585 outfile);
586 if (rv != SECSuccess) {
587 break;
588 }
589 }
590 } else {
591 certs = PK11_ListCertsInSlot(slot);
592 if (certs) {
593 for (node = CERT_LIST_HEAD(certs)((CERTCertListNode *)(&certs->list)->next); !CERT_LIST_END(node, certs)(((void *)node) == ((void *)&certs->list));
594 node = CERT_LIST_NEXT(node)((CERTCertListNode *)node->links.next)) {
595 SECU_PrintCertNickname(node, stdoutstdout);
596 }
597 rv = SECSuccess;
598 }
599 }
600 if (certs) {
601 CERT_DestroyCertList(certs);
602 }
603 if (rv) {
604 SECU_PrintError(progName, "problem printing certificate nicknames");
605 return SECFailure;
606 }
607
608 return SECSuccess; /* not rv ?? */
609}
610
611static SECStatus
612ListCerts(CERTCertDBHandle *handle, char *nickname, char *email,
613 PK11SlotInfo *slot, PRBool raw, PRBool ascii,
614 SECItem *extensionOID,
615 PRFileDesc *outfile, secuPWData *pwdata)
616{
617 SECStatus rv;
618
619 if (slot && PK11_NeedUserInit(slot)) {
620 printf("\nDatabase needs user init\n");
621 }
622
623 if (!ascii && !raw && !nickname && !email) {
624 PR_fprintf(outfile, "\n%-60s %-5s\n%-60s %-5s\n\n",
625 "Certificate Nickname", "Trust Attributes", "",
626 "SSL,S/MIME,JAR/XPI");
627 }
628 if (slot == NULL((void*)0)) {
629 CERTCertList *list;
630 CERTCertListNode *node;
631
632 list = PK11_ListCerts(PK11CertListAll, pwdata);
633 for (node = CERT_LIST_HEAD(list)((CERTCertListNode *)(&list->list)->next); !CERT_LIST_END(node, list)(((void *)node) == ((void *)&list->list));
634 node = CERT_LIST_NEXT(node)((CERTCertListNode *)node->links.next)) {
635 SECU_PrintCertNickname(node, stdoutstdout);
636 }
637 CERT_DestroyCertList(list);
638 return SECSuccess;
639 }
640 rv = listCerts(handle, nickname, email, slot, raw, ascii,
641 extensionOID, outfile, pwdata);
642 return rv;
643}
644
645static SECStatus
646DeleteCert(CERTCertDBHandle *handle, char *name, void *pwdata)
647{
648 SECStatus rv;
649 CERTCertificate *cert;
650
651 cert = CERT_FindCertByNicknameOrEmailAddrCX(handle, name, pwdata);
652 if (!cert) {
653 SECU_PrintError(progName, "could not find certificate named \"%s\"",
654 name);
655 return SECFailure;
656 }
657
658 rv = SEC_DeletePermCertificate(cert);
659 CERT_DestroyCertificate(cert);
660 if (rv) {
661 SECU_PrintError(progName, "unable to delete certificate");
662 }
663 return rv;
664}
665
666static SECStatus
667RenameCert(CERTCertDBHandle *handle, char *name, char *newName, void *pwdata)
668{
669 SECStatus rv;
670 CERTCertificate *cert;
671
672 cert = CERT_FindCertByNicknameOrEmailAddrCX(handle, name, pwdata);
673 if (!cert) {
674 SECU_PrintError(progName, "could not find certificate named \"%s\"",
675 name);
676 return SECFailure;
677 }
678
679 rv = __PK11_SetCertificateNickname(cert, newName);
680 CERT_DestroyCertificate(cert);
681 if (rv) {
682 SECU_PrintError(progName, "unable to rename certificate");
683 }
684 return rv;
685}
686
687static SECStatus
688ValidateCert(CERTCertDBHandle *handle, char *name, char *date,
689 char *certUsage, PRBool checkSig, PRBool logit,
690 PRBool ascii, secuPWData *pwdata)
691{
692 SECStatus rv;
693 CERTCertificate *cert = NULL((void*)0);
694 PRTime timeBoundary;
695 SECCertificateUsage usage;
696 CERTVerifyLog reallog;
697 CERTVerifyLog *log = NULL((void*)0);
698
699 if (!certUsage) {
700 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
701 return (SECFailure);
702 }
703
704 switch (*certUsage) {
705 case 'O':
706 usage = certificateUsageStatusResponder(0x0400);
707 break;
708 case 'L':
709 usage = certificateUsageSSLCA(0x0008);
710 break;
711 case 'A':
712 usage = certificateUsageAnyCA(0x0800);
713 break;
714 case 'Y':
715 usage = certificateUsageVerifyCA(0x0100);
716 break;
717 case 'C':
718 usage = certificateUsageSSLClient(0x0001);
719 break;
720 case 'V':
721 usage = certificateUsageSSLServer(0x0002);
722 break;
723 case 'I':
724 usage = certificateUsageIPsec(0x1000);
725 break;
726 case 'S':
727 usage = certificateUsageEmailSigner(0x0010);
728 break;
729 case 'R':
730 usage = certificateUsageEmailRecipient(0x0020);
731 break;
732 case 'J':
733 usage = certificateUsageObjectSigner(0x0040);
734 break;
735 default:
736 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
737 return (SECFailure);
738 }
739 do {
740 cert = SECU_FindCertByNicknameOrFilename(handle, name, ascii,
741 NULL((void*)0));
742 if (!cert) {
743 SECU_PrintError(progName, "could not find certificate named \"%s\"",
744 name);
745 GEN_BREAK(SECFailure)rv = SECFailure; break;
746 }
747
748 if (date != NULL((void*)0)) {
749 rv = DER_AsciiToTimeDER_AsciiToTime_Util(&timeBoundary, date);
750 if (rv) {
751 SECU_PrintError(progName, "invalid input date");
752 GEN_BREAK(SECFailure)rv = SECFailure; break;
753 }
754 } else {
755 timeBoundary = PR_Now();
756 }
757
758 if (logit) {
759 log = &reallog;
760
761 log->count = 0;
762 log->head = NULL((void*)0);
763 log->tail = NULL((void*)0);
764 log->arena = PORT_NewArenaPORT_NewArena_Util(DER_DEFAULT_CHUNKSIZE(2048));
765 if (log->arena == NULL((void*)0)) {
766 SECU_PrintError(progName, "out of memory");
767 GEN_BREAK(SECFailure)rv = SECFailure; break;
768 }
769 }
770
771 rv = CERT_VerifyCertificate(handle, cert, checkSig, usage,
772 timeBoundary, pwdata, log, &usage);
773 if (log) {
774 if (log->head == NULL((void*)0)) {
775 fprintf(stdoutstdout, "%s: certificate is valid\n", progName);
776 GEN_BREAK(SECSuccess)rv = SECSuccess; break;
777 } else {
778 char *nick;
779 CERTVerifyLogNode *node;
780
781 node = log->head;
782 while (node) {
783 if (node->cert->nickname != NULL((void*)0)) {
784 nick = node->cert->nickname;
785 } else {
786 nick = node->cert->subjectName;
787 }
788 fprintf(stderrstderr, "%s : %s\n", nick,
789 SECU_Strerror(node->error)PR_ErrorToString((node->error), 0));
790 CERT_DestroyCertificate(node->cert);
791 node = node->next;
792 }
793 }
794 } else {
795 if (rv != SECSuccess) {
796 PRErrorCode perr = PORT_GetErrorPORT_GetError_Util();
797 fprintf(stdoutstdout, "%s: certificate is invalid: %s\n",
798 progName, SECU_Strerror(perr)PR_ErrorToString((perr), 0));
799 GEN_BREAK(SECFailure)rv = SECFailure; break;
800 }
801 fprintf(stdoutstdout, "%s: certificate is valid\n", progName);
802 GEN_BREAK(SECSuccess)rv = SECSuccess; break;
803 }
804 } while (0);
805
806 if (cert) {
807 CERT_DestroyCertificate(cert);
808 }
809
810 return (rv);
811}
812
813static PRBool
814ItemIsPrintableASCII(const SECItem *item)
815{
816 unsigned char *src = item->data;
817 unsigned int len = item->len;
818 while (len-- > 0) {
819 unsigned char uc = *src++;
820 if (uc < 0x20 || uc > 0x7e)
821 return PR_FALSE0;
822 }
823 return PR_TRUE1;
824}
825
826/* Caller ensures that dst is at least item->len*2+1 bytes long */
827static void
828SECItemToHex(const SECItem *item, char *dst)
829{
830 if (dst && item && item->data) {
831 unsigned char *src = item->data;
832 unsigned int len = item->len;
833 for (; len > 0; --len, dst += 2) {
834 snprintf(dst, 3, "%02x", *src++);
835 }
836 *dst = '\0';
837 }
838}
839
840#define MAX_CKA_ID_BIN_LEN20 20
841#define MAX_CKA_ID_STR_LEN40 40
842
843/* output human readable key ID in buffer, which should have at least
844 * MAX_CKA_ID_STR_LEN + 3 octets (quotations and a null terminator) */
845static void
846formatPrivateKeyID(SECKEYPrivateKey *privkey, char *buffer)
847{
848 SECItem *ckaID;
849
850 ckaID = PK11_GetLowLevelKeyIDForPrivateKey(privkey);
851 if (!ckaID) {
852 strcpy(buffer, "(no CKA_ID)");
853 } else if (ItemIsPrintableASCII(ckaID)) {
854 int len = PR_MIN(MAX_CKA_ID_STR_LEN, ckaID->len)((40) < (ckaID->len) ? (40) : (ckaID->len));
855 buffer[0] = '"';
856 memcpy(buffer + 1, ckaID->data, len);
857 buffer[1 + len] = '"';
858 buffer[2 + len] = '\0';
859 } else {
860 /* print ckaid in hex */
861 SECItem idItem = *ckaID;
862 if (idItem.len > MAX_CKA_ID_BIN_LEN20)
863 idItem.len = MAX_CKA_ID_BIN_LEN20;
864 SECItemToHex(&idItem, buffer);
865 }
866 SECITEM_ZfreeItemSECITEM_ZfreeItem_Util(ckaID, PR_TRUE1);
867}
868
869/* print key number, key ID (in hex or ASCII), key label (nickname) */
870static SECStatus
871PrintKey(PRFileDesc *out, const char *nickName, int count,
872 SECKEYPrivateKey *key, void *pwarg)
873{
874 char ckaIDbuf[MAX_CKA_ID_STR_LEN40 + 4];
875 CERTCertificate *cert;
876 KeyType keyType;
877
878 formatPrivateKeyID(key, ckaIDbuf);
879 cert = PK11_GetCertFromPrivateKey(key);
880 if (cert) {
881 keyType = CERT_GetCertKeyType(&cert->subjectPublicKeyInfo);
882 CERT_DestroyCertificate(cert);
883 } else {
884 keyType = key->keyType;
885 }
886 PR_fprintf(out, "<%2d> %-8.8s %-42.42s %s\n", count,
887 SECKEY_GetKeyTypeString(keyType), ckaIDbuf, nickName);
888
889 return SECSuccess;
890}
891
892/* returns SECSuccess if ANY keys are found, SECFailure otherwise. */
893static SECStatus
894ListKeysInSlot(PK11SlotInfo *slot, const char *nickName, KeyType keyType,
895 void *pwarg)
896{
897 SECKEYPrivateKeyList *list;
898 SECKEYPrivateKeyListNode *node;
899 int count = 0;
900
901 if (PK11_NeedLogin(slot)) {
902 SECStatus rv = PK11_Authenticate(slot, PR_TRUE1, pwarg);
903 if (rv != SECSuccess) {
904 SECU_PrintError(progName, "could not authenticate to token %s.",
905 PK11_GetTokenName(slot));
906 return SECFailure;
907 }
908 }
909
910 if (nickName && nickName[0])
911 list = PK11_ListPrivKeysInSlot(slot, (char *)nickName, pwarg);
912 else
913 list = PK11_ListPrivateKeysInSlot(slot);
914 if (list == NULL((void*)0)) {
915 SECU_PrintError(progName, "problem listing keys");
916 return SECFailure;
917 }
918 for (node = PRIVKEY_LIST_HEAD(list)((SECKEYPrivateKeyListNode *)(&list->list)->next);
919 !PRIVKEY_LIST_END(node, list)(((void *)node) == ((void *)&list->list));
920 node = PRIVKEY_LIST_NEXT(node)((SECKEYPrivateKeyListNode *)node->links.next)) {
921 char *keyName;
922 static const char orphan[] = { "(orphan)" };
923
924 if (keyType != nullKey && keyType != node->key->keyType)
925 continue;
926 keyName = PK11_GetPrivateKeyNickname(node->key);
927 if (!keyName || !keyName[0]) {
928 /* Try extra hard to find nicknames for keys that lack them. */
929 CERTCertificate *cert;
930 PORT_FreePORT_Free_Util((void *)keyName);
931 keyName = NULL((void*)0);
932 cert = PK11_GetCertFromPrivateKey(node->key);
933 if (cert) {
934 if (cert->nickname && cert->nickname[0]) {
935 keyName = PORT_StrdupPORT_Strdup_Util(cert->nickname);
936 } else if (cert->emailAddr && cert->emailAddr[0]) {
937 keyName = PORT_StrdupPORT_Strdup_Util(cert->emailAddr);
938 }
939 CERT_DestroyCertificate(cert);
940 }
941 }
942 if (nickName) {
943 if (!keyName || PL_strcmp(keyName, nickName)) {
944 /* PKCS#11 module returned unwanted keys */
945 PORT_FreePORT_Free_Util((void *)keyName);
946 continue;
947 }
948 }
949 if (!keyName)
950 keyName = (char *)orphan;
951
952 PrintKey(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), keyName, count, node->key, pwarg);
953
954 if (keyName != (char *)orphan)
955 PORT_FreePORT_Free_Util((void *)keyName);
956 count++;
957 }
958 SECKEY_DestroyPrivateKeyList(list);
959
960 if (count == 0) {
961 PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), "%s: no keys found\n", progName);
962 return SECFailure;
963 }
964 return SECSuccess;
965}
966
967/* returns SECSuccess if ANY keys are found, SECFailure otherwise. */
968static SECStatus
969ListKeys(PK11SlotInfo *slot, const char *nickName, int index,
970 KeyType keyType, PRBool dopriv, secuPWData *pwdata)
971{
972 SECStatus rv = SECFailure;
973 static const char fmt[] =
974 "%s: Checking token \"%.33s\" in slot \"%.65s\"\n";
975
976 if (slot == NULL((void*)0)) {
977 PK11SlotList *list;
978 PK11SlotListElement *le;
979
980 list = PK11_GetAllTokens(CKM_INVALID_MECHANISM0xffffffffUL, PR_FALSE0, PR_FALSE0, pwdata);
981 if (list) {
982 for (le = list->head; le; le = le->next) {
983 PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), fmt, progName,
984 PK11_GetTokenName(le->slot),
985 PK11_GetSlotName(le->slot));
986 rv &= ListKeysInSlot(le->slot, nickName, keyType, pwdata);
987 }
988 PK11_FreeSlotList(list);
989 }
990 } else {
991 PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), fmt, progName, PK11_GetTokenName(slot),
992 PK11_GetSlotName(slot));
993 rv = ListKeysInSlot(slot, nickName, keyType, pwdata);
994 }
995 return rv;
996}
997
998static SECStatus
999DeleteCertAndKey(char *nickname, secuPWData *pwdata)
1000{
1001 SECStatus rv;
1002 CERTCertificate *cert;
1003 PK11SlotInfo *slot;
1004
1005 slot = PK11_GetInternalKeySlot();
1006 if (PK11_NeedLogin(slot)) {
1007 rv = PK11_Authenticate(slot, PR_TRUE1, pwdata);
1008 if (rv != SECSuccess) {
1009 SECU_PrintError(progName, "could not authenticate to token %s.",
1010 PK11_GetTokenName(slot));
1011 PK11_FreeSlot(slot);
1012 return SECFailure;
1013 }
1014 }
1015 cert = PK11_FindCertFromNickname(nickname, pwdata);
1016 if (!cert) {
1017 PK11_FreeSlot(slot);
1018 return SECFailure;
1019 }
1020 rv = PK11_DeleteTokenCertAndKey(cert, pwdata);
1021 if (rv != SECSuccess) {
1022 SECU_PrintError("problem deleting private key \"%s\"\n", nickname);
1023 }
1024 CERT_DestroyCertificate(cert);
1025 PK11_FreeSlot(slot);
1026 return rv;
1027}
1028
1029static SECKEYPrivateKey *
1030findPrivateKeyByID(PK11SlotInfo *slot, const char *ckaID, secuPWData *pwarg)
1031{
1032 PORTCheapArenaPool arena;
1033 SECItem ckaIDItem = { 0 };
1034 SECKEYPrivateKey *privkey = NULL((void*)0);
1035 SECStatus rv;
1036
1037 if (PK11_NeedLogin(slot)) {
1038 rv = PK11_Authenticate(slot, PR_TRUE1, pwarg);
1039 if (rv != SECSuccess) {
1040 SECU_PrintError(progName, "could not authenticate to token %s.",
1041 PK11_GetTokenName(slot));
1042 return NULL((void*)0);
1043 }
1044 }
1045
1046 if (0 == PL_strncasecmp("0x", ckaID, 2)) {
1047 ckaID += 2; /* skip leading "0x" */
1048 }
1049 PORT_InitCheapArena(&arena, DER_DEFAULT_CHUNKSIZE(2048));
1050 if (SECU_HexString2SECItem(&arena.arena, &ckaIDItem, ckaID)) {
1051 privkey = PK11_FindKeyByKeyID(slot, &ckaIDItem, pwarg);
1052 }
1053 PORT_DestroyCheapArena(&arena);
1054 return privkey;
1055}
1056
1057static SECStatus
1058DeleteKey(SECKEYPrivateKey *privkey, secuPWData *pwarg)
1059{
1060 SECStatus rv;
1061 PK11SlotInfo *slot;
1062
1063 slot = PK11_GetSlotFromPrivateKey(privkey);
1064 if (PK11_NeedLogin(slot)) {
1065 rv = PK11_Authenticate(slot, PR_TRUE1, pwarg);
1066 if (rv != SECSuccess) {
1067 SECU_PrintError(progName, "could not authenticate to token %s.",
1068 PK11_GetTokenName(slot));
1069 return SECFailure;
1070 }
1071 }
1072
1073 rv = PK11_DeleteTokenPrivateKey(privkey, PR_TRUE1);
1074 if (rv != SECSuccess) {
1075 char ckaIDbuf[MAX_CKA_ID_STR_LEN40 + 4];
1076 formatPrivateKeyID(privkey, ckaIDbuf);
1077 SECU_PrintError("problem deleting private key \"%s\"\n", ckaIDbuf);
1078 }
1079
1080 PK11_FreeSlot(slot);
1081 return rv;
1082}
1083
1084/*
1085 * L i s t M o d u l e s
1086 *
1087 * Print a list of the PKCS11 modules that are
1088 * available. This is useful for smartcard people to
1089 * make sure they have the drivers loaded.
1090 *
1091 */
1092static SECStatus
1093ListModules(void)
1094{
1095 PK11SlotList *list;
1096 PK11SlotListElement *le;
1097
1098 /* get them all! */
1099 list = PK11_GetAllTokens(CKM_INVALID_MECHANISM0xffffffffUL, PR_FALSE0, PR_FALSE0, NULL((void*)0));
1100 if (list == NULL((void*)0))
1101 return SECFailure;
1102
1103 /* look at each slot*/
1104 for (le = list->head; le; le = le->next) {
1105 char *token_uri = PK11_GetTokenURI(le->slot);
1106 printf("\n");
1107 printf(" slot: %s\n", PK11_GetSlotName(le->slot));
1108 printf(" token: %s\n", PK11_GetTokenName(le->slot));
1109 printf(" uri: %s\n", token_uri);
1110 PORT_FreePORT_Free_Util(token_uri);
1111 }
1112 PK11_FreeSlotList(list);
1113
1114 return SECSuccess;
1115}
1116
1117static void
1118PrintBuildFlags()
1119{
1120#ifdef NSS_FIPS_DISABLED1
1121 PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), "NSS_FIPS_DISABLED\n");
1122#endif
1123#ifdef NSS_NO_INIT_SUPPORT1
1124 PR_fprintf(PR_STDOUTPR_GetSpecialFD(PR_StandardOutput), "NSS_NO_INIT_SUPPORT\n");
1125#endif
1126 exit(0);
1127}
1128
1129static void
1130PrintSyntax()
1131{
1132#define FPS fprintf(stderrstderr,
1133 FPS "Type %s -H for more detailed descriptions\n", progName);
1134 FPS "Usage: %s -N [-d certdir] [-P dbprefix] [-f pwfile] [--empty-password]\n", progName);
1135 FPS "Usage: %s -T [-d certdir] [-P dbprefix] [-h token-name]\n"
1136 "\t\t [-f pwfile] [-0 SSO-password]\n", progName);
1137 FPS "\t%s -A -n cert-name -t trustargs [-d certdir] [-P dbprefix] [-a] [-i input]\n",
1138 progName);
1139 FPS "\t%s -B -i batch-file\n", progName);
1140 FPS "\t%s -C [-c issuer-name | -x] -i cert-request-file -o cert-file\n"
1141 "\t\t [-m serial-number] [-w warp-months] [-v months-valid]\n"
1142 "\t\t [-f pwfile] [-d certdir] [-P dbprefix] [-Z hashAlg]\n"
1143 "\t\t [-1 | --keyUsage [keyUsageKeyword,..]] [-2] [-3] [-4]\n"
1144 "\t\t [-5 | --nsCertType [nsCertTypeKeyword,...]]\n"
1145 "\t\t [-6 | --extKeyUsage [extKeyUsageKeyword,...]] [-7 emailAddrs]\n"
1146 "\t\t [-8 dns-names] [-a]\n",
1147 progName);
1148 FPS "\t%s -D -n cert-name [-d certdir] [-P dbprefix]\n", progName);
1149 FPS "\t%s --rename -n cert-name --new-n new-cert-name\n"
1150 "\t\t [-d certdir] [-P dbprefix]\n", progName);
1151 FPS "\t%s -E -n cert-name -t trustargs [-d certdir] [-P dbprefix] [-a] [-i input]\n",
1152 progName);
1153 FPS "\t%s -F -n cert-name [-d certdir] [-P dbprefix]\n",
1154 progName);
1155 FPS "\t%s -F -k key-id [-d certdir] [-P dbprefix]\n",
1156 progName);
1157 FPS "\t%s -G -n key-name [-h token-name] [-k rsa] [-g key-size] [-y exp]\n"
1158 "\t\t [-f pwfile] [-z noisefile] [-d certdir] [-P dbprefix]\n", progName);
1159 FPS "\t%s -G [-h token-name] -k dsa [-q pqgfile -g key-size] [-f pwfile]\n"
1160 "\t\t [-z noisefile] [-d certdir] [-P dbprefix]\n", progName);
1161 FPS "\t%s -G [-h token-name] -k ec -q curve [-f pwfile]\n"
1162 "\t\t [-z noisefile] [-d certdir] [-P dbprefix]\n", progName);
1163 FPS "\t%s -G [-h token-name] -k ed -q curve [-f pwfile]\n"
1164 "\t\t [-z noisefile] [-d certdir] [-P dbprefix]\n", progName);
1165 FPS "\t%s -G [-h token-name] -k mldsa -q paramset [-f pwfile]\n"
1166 "\t\t [-z noisefile] [-d certdir] [-P dbprefix]\n", progName);
1167 FPS "\t%s -K [-n key-name] [-h token-name] [-k dsa|ec|ed|rsa|mldsa|all]\n",
1168 progName);
1169 FPS "\t\t [-f pwfile] [-X] [-d certdir] [-P dbprefix]\n");
1170 FPS "\t%s --upgrade-merge --source-dir upgradeDir --upgrade-id uniqueID\n",
1171 progName);
1172 FPS "\t\t [--upgrade-token-name tokenName] [-d targetDBDir]\n");
1173 FPS "\t\t [-P targetDBPrefix] [--source-prefix upgradeDBPrefix]\n");
1174 FPS "\t\t [-f targetPWfile] [-@ upgradePWFile]\n");
1175 FPS "\t%s --merge --source-dir sourceDBDir [-d targetDBdir]\n",
1176 progName);
1177 FPS "\t\t [-P targetDBPrefix] [--source-prefix sourceDBPrefix]\n");
1178 FPS "\t\t [-f targetPWfile] [-@ sourcePWFile]\n");
1179 FPS "\t%s -L [-n cert-name] [-h token-name] [--email email-address]\n",
1180 progName);
1181 FPS "\t\t [-X] [-r] [-a] [--dump-ext-val OID] [-d certdir] [-P dbprefix]\n");
1182 FPS "\t%s --build-flags\n", progName);
1183 FPS "\t%s -M -n cert-name -t trustargs [-d certdir] [-P dbprefix]\n",
1184 progName);
1185 FPS "\t%s -O -n cert-name [-X] [-d certdir] [-a] [-P dbprefix]\n"
1186 "\t\t [--simple-self-signed]\n",
1187 progName);
1188 FPS "\t%s -R -s subj -o cert-request-file [-d certdir] [-P dbprefix] [-p phone] [-a]\n"
1189 "\t\t [-7 emailAddrs] [-k key-type-or-id] [-h token-name] [-f pwfile]\n"
1190 "\t\t [-g key-size] [-Z hashAlg]\n",
1191 progName);
1192 FPS "\t%s -V -n cert-name -u usage [-b time] [-e] [-a]\n"
1193 "\t\t[-X] [-d certdir] [-P dbprefix]\n",
1194 progName);
1195 FPS "Usage: %s -W [-d certdir] [-f pwfile] [-@newpwfile]\n",
1196 progName);
1197 FPS "\t%s -S -n cert-name -s subj [-c issuer-name | -x] -t trustargs\n"
1198 "\t\t [-k key-type-or-id] [-q key-params] [-h token-name] [-g key-size]\n"
1199 "\t\t [-m serial-number] [-w warp-months] [-v months-valid]\n"
1200 "\t\t [-f pwfile] [-d certdir] [-P dbprefix] [-Z hashAlg]\n"
1201 "\t\t [-p phone] [-1] [-2] [-3] [-4] [-5] [-6] [-7 emailAddrs]\n"
1202 "\t\t [-8 DNS-names]\n"
1203 "\t\t [--extAIA] [--extSIA] [--extCP] [--extPM] [--extPC] [--extIA]\n"
1204 "\t\t [--extSKID] [--extNC] [--extSAN type:name[,type:name]...]\n"
1205 "\t\t [--extGeneric OID:critical-flag:filename[,OID:critical-flag:filename]...]\n", progName);
1206 FPS "\t%s -U [-X] [-d certdir] [-P dbprefix]\n", progName);
1207 exit(1);
1208}
1209
1210enum usage_level {
1211 usage_all = 0,
1212 usage_selected = 1
1213};
1214
1215static void luCommonDetailsAE();
1216
1217static void
1218luA(enum usage_level ul, const char *command)
1219{
1220 int is_my_command = (command && 0 == strcmp(command, "A"));
1221 if (ul == usage_all || !command || is_my_command)
1222 FPS "%-15s Add a certificate to the database (create if needed)\n",
1223 "-A");
1224 if (ul == usage_selected && !is_my_command)
1225 return;
1226 if (ul == usage_all) {
1227 FPS "%-20s\n", " All options under -E apply");
1228 } else {
1229 luCommonDetailsAE();
1230 }
1231}
1232
1233static void
1234luB(enum usage_level ul, const char *command)
1235{
1236 int is_my_command = (command && 0 == strcmp(command, "B"));
1237 if (ul == usage_all || !command || is_my_command)
1238 FPS "%-15s Run a series of certutil commands from a batch file\n", "-B");
1239 if (ul == usage_selected && !is_my_command)
1240 return;
1241 FPS "%-20s Specify the batch file\n", " -i batch-file");
1242}
1243
1244static void
1245luE(enum usage_level ul, const char *command)
1246{
1247 int is_my_command = (command && 0 == strcmp(command, "E"));
1248 if (ul == usage_all || !command || is_my_command)
1249 FPS "%-15s Add an Email certificate to the database (create if needed)\n",
1250 "-E");
1251 if (ul == usage_selected && !is_my_command)
1252 return;
1253 luCommonDetailsAE();
1254}
1255
1256static void
1257luCommonDetailsAE()
1258{
1259 FPS "%-20s Specify the nickname of the certificate to add\n",
1260 " -n cert-name");
1261 FPS "%-20s Set the certificate trust attributes:\n",
1262 " -t trustargs");
1263 FPS "%-25s trustargs is of the form x,y,z where x is for SSL, y is for S/MIME,\n", "");
1264 FPS "%-25s and z is for code signing. Use ,, for no explicit trust.\n", "");
1265 FPS "%-25s p \t prohibited (explicitly distrusted)\n", "");
1266 FPS "%-25s P \t trusted peer\n", "");
1267 FPS "%-25s c \t valid CA\n", "");
1268 FPS "%-25s T \t trusted CA to issue client certs (implies c)\n", "");
1269 FPS "%-25s C \t trusted CA to issue server certs (implies c)\n", "");
1270 FPS "%-25s u \t user cert\n", "");
1271 FPS "%-25s w \t send warning\n", "");
1272 FPS "%-25s g \t make step-up cert\n", "");
1273 FPS "%-20s Specify the password file\n",
1274 " -f pwfile");
1275 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1276 " -d certdir");
1277 FPS "%-20s Cert & Key database prefix\n",
1278 " -P dbprefix");
1279 FPS "%-20s The input certificate is encoded in ASCII (RFC1113)\n",
1280 " -a");
1281 FPS "%-20s Specify the certificate file (default is stdin)\n",
1282 " -i input");
1283 FPS "\n");
1284}
1285
1286static void
1287luC(enum usage_level ul, const char *command)
1288{
1289 int is_my_command = (command && 0 == strcmp(command, "C"));
1290 if (ul == usage_all || !command || is_my_command)
1291 FPS "%-15s Create a new binary certificate from a BINARY cert request\n",
1292 "-C");
1293 if (ul == usage_selected && !is_my_command)
1294 return;
1295 FPS "%-20s The nickname of the issuer cert\n",
1296 " -c issuer-name");
1297 FPS "%-20s The BINARY certificate request file\n",
1298 " -i cert-request ");
1299 FPS "%-20s Output binary cert to this file (default is stdout)\n",
1300 " -o output-cert");
1301 FPS "%-20s Self sign\n",
1302 " -x");
1303 FPS "%-20s Sign the certificate with RSA-PSS (the issuer key must be rsa)\n",
1304 " --pss-sign");
1305 FPS "%-20s Cert serial number\n",
1306 " -m serial-number");
1307 FPS "%-20s Time Warp\n",
1308 " -w warp-months");
1309 FPS "%-20s Months valid (default is 3)\n",
1310 " -v months-valid");
1311 FPS "%-20s Specify the password file\n",
1312 " -f pwfile");
1313 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1314 " -d certdir");
1315 FPS "%-20s Cert & Key database prefix\n",
1316 " -P dbprefix");
1317 FPS "%-20s \n"
1318 "%-20s Specify the hash algorithm to use. Possible keywords:\n"
1319 "%-20s \"MD2\", \"MD4\", \"MD5\", \"SHA1\", \"SHA224\",\n"
1320 "%-20s \"SHA256\", \"SHA384\", \"SHA512\"\n",
1321 " -Z hashAlg", "", "", "");
1322 FPS "%-20s \n"
1323 "%-20s Create key usage extension. Possible keywords:\n"
1324 "%-20s \"digitalSignature\", \"nonRepudiation\", \"keyEncipherment\",\n"
1325 "%-20s \"dataEncipherment\", \"keyAgreement\", \"certSigning\",\n"
1326 "%-20s \"crlSigning\", \"critical\"\n",
1327 " -1 | --keyUsage keyword,keyword,...", "", "", "", "");
1328 FPS "%-20s Create basic constraint extension\n",
1329 " -2 ");
1330 FPS "%-20s Create authority key ID extension\n",
1331 " -3 ");
1332 FPS "%-20s Create crl distribution point extension\n",
1333 " -4 ");
1334 FPS "%-20s \n"
1335 "%-20s Create netscape cert type extension. Possible keywords:\n"
1336 "%-20s \"sslClient\", \"sslServer\", \"smime\", \"objectSigning\",\n"
1337 "%-20s \"sslCA\", \"smimeCA\", \"objectSigningCA\", \"critical\".\n",
1338 " -5 | --nsCertType keyword,keyword,... ", "", "", "");
1339 FPS "%-20s \n"
1340 "%-20s Create extended key usage extension. Possible keywords:\n"
1341 "%-20s \"serverAuth\", \"clientAuth\",\"codeSigning\",\n"
1342 "%-20s \"emailProtection\", \"timeStamp\",\"ocspResponder\",\n"
1343 "%-20s \"stepUp\", \"msTrustListSign\", \"x509Any\",\n"
1344 "%-20s \"ipsecIKE\", \"ipsecIKEEnd\", \"ipsecIKEIntermediate\",\n"
1345 "%-20s \"ipsecEnd\", \"ipsecTunnel\", \"ipsecUser\",\n"
1346 "%-20s \"critical\"\n",
1347 " -6 | --extKeyUsage keyword,keyword,...", "", "", "", "", "", "", "");
1348 FPS "%-20s Create an email subject alt name extension\n",
1349 " -7 emailAddrs");
1350 FPS "%-20s Create an dns subject alt name extension\n",
1351 " -8 dnsNames");
1352 FPS "%-20s The input certificate request is encoded in ASCII (RFC1113)\n",
1353 " -a");
1354 FPS "\n");
1355}
1356
1357static void
1358luG(enum usage_level ul, const char *command)
1359{
1360 int is_my_command = (command && 0 == strcmp(command, "G"));
1361 if (ul == usage_all || !command || is_my_command)
1362 FPS "%-15s Generate a new key pair\n",
1363 "-G");
1364 if (ul == usage_selected && !is_my_command)
1365 return;
1366 FPS "%-20s Name of token in which to generate key (default is internal)\n",
1367 " -h token-name");
1368 FPS "%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n",
1369 " -k key-type");
1370 FPS "%-20s Key size in bits, (min %d, max %d, default %d) (not for ec)\n",
1371 " -g key-size", MIN_KEY_BITS512, MAX_KEY_BITS8192, DEFAULT_KEY_BITS2048);
1372 FPS "%-20s Set the public exponent value (3, 17, 65537) (rsa only)\n",
1373 " -y exp");
1374 FPS "%-20s Specify the password file\n",
1375 " -f password-file");
1376 FPS "%-20s Specify the noise file to be used\n",
1377 " -z noisefile");
1378 FPS "%-20s read PQG value from pqgfile (dsa only)\n",
1379 " -q pqgfile");
1380 FPS "%-20s Elliptic curve name (ec only)\n",
1381 " -q curve-name");
1382 FPS "%-20s One of nistp256, nistp384, nistp521, curve25519.\n", "");
1383 FPS "%-20s If a custom token is present, the following curves are also supported:\n", "");
1384 FPS "%-20s sect163k1, nistk163, sect163r1, sect163r2,\n", "");
1385 FPS "%-20s nistb163, sect193r1, sect193r2, sect233k1, nistk233,\n", "");
1386 FPS "%-20s sect233r1, nistb233, sect239k1, sect283k1, nistk283,\n", "");
1387 FPS "%-20s sect283r1, nistb283, sect409k1, nistk409, sect409r1,\n", "");
1388 FPS "%-20s nistb409, sect571k1, nistk571, sect571r1, nistb571,\n", "");
1389 FPS "%-20s secp160k1, secp160r1, secp160r2, secp192k1, secp192r1,\n", "");
1390 FPS "%-20s nistp192, secp224k1, secp224r1, nistp224, secp256k1,\n", "");
1391 FPS "%-20s secp256r1, secp384r1, secp521r1,\n", "");
1392 FPS "%-20s prime192v1, prime192v2, prime192v3, \n", "");
1393 FPS "%-20s prime239v1, prime239v2, prime239v3, c2pnb163v1, \n", "");
1394 FPS "%-20s c2pnb163v2, c2pnb163v3, c2pnb176v1, c2tnb191v1, \n", "");
1395 FPS "%-20s c2tnb191v2, c2tnb191v3, \n", "");
1396 FPS "%-20s c2pnb208w1, c2tnb239v1, c2tnb239v2, c2tnb239v3, \n", "");
1397 FPS "%-20s c2pnb272w1, c2pnb304w1, \n", "");
1398 FPS "%-20s c2tnb359w1, c2pnb368w1, c2tnb431r1, secp112r1, \n", "");
1399 FPS "%-20s secp112r2, secp128r1, secp128r2, sect113r1, sect113r2\n", "");
1400 FPS "%-20s sect131r1, sect131r2\n", "");
1401 FPS "%-20s Edwards elliptic curve name (ed only)\n",
1402 " -q curve-name");
1403 FPS "%-20s One of ed25519.\n", "");
1404 FPS "%-20s ML-DSA parameter set (mldsa only)\n",
1405 " -q paramset");
1406 FPS "%-20s valid values are ml-dsa-44, ml-dsa-65, ml-dsa-87:\n", "");
1407 FPS "%-20s Key database directory (default is ~/.netscape)\n",
1408 " -d keydir");
1409 FPS "%-20s Cert & Key database prefix\n",
1410 " -P dbprefix");
1411 FPS "%-20s\n"
1412 "%-20s PKCS #11 key Attributes.\n",
1413 " --keyAttrFlags attrflags", "");
1414 FPS "%-20s Comma separated list of key attribute attribute flags,\n", "");
1415 FPS "%-20s selected from the following list of choices:\n", "");
1416 FPS "%-20s {token | session} {public | private} {sensitive | insensitive}\n", "");
1417 FPS "%-20s {modifiable | unmodifiable} {extractable | unextractable}\n", "");
1418 FPS "%-20s\n",
1419 " --keyOpFlagsOn opflags");
1420 FPS "%-20s\n"
1421 "%-20s PKCS #11 key Operation Flags.\n",
1422 " --keyOpFlagsOff opflags", "");
1423 FPS "%-20s Comma separated list of one or more of the following:\n", "");
1424 FPS "%-20s encrypt, decrypt, sign, sign_recover, verify,\n", "");
1425 FPS "%-20s verify_recover, wrap, unwrap, derive\n", "");
1426 FPS "\n");
1427}
1428
1429static void
1430luD(enum usage_level ul, const char *command)
1431{
1432 int is_my_command = (command && 0 == strcmp(command, "D"));
1433 if (ul == usage_all || !command || is_my_command)
1434 FPS "%-15s Delete a certificate from the database\n",
1435 "-D");
1436 if (ul == usage_selected && !is_my_command)
1437 return;
1438 FPS "%-20s The nickname of the cert to delete\n",
1439 " -n cert-name");
1440 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1441 " -d certdir");
1442 FPS "%-20s Cert & Key database prefix\n",
1443 " -P dbprefix");
1444 FPS "\n");
1445}
1446
1447static void
1448luF(enum usage_level ul, const char *command)
1449{
1450 int is_my_command = (command && 0 == strcmp(command, "F"));
1451 if (ul == usage_all || !command || is_my_command)
1452 FPS "%-15s Delete a key and associated certificate from the database\n",
1453 "-F");
1454 if (ul == usage_selected && !is_my_command)
1455 return;
1456 FPS "%-20s The nickname of the key to delete\n",
1457 " -n cert-name");
1458 FPS "%-20s The key id of the key to delete, obtained using -K\n",
1459 " -k key-id");
1460 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1461 " -d certdir");
1462 FPS "%-20s Cert & Key database prefix\n",
1463 " -P dbprefix");
1464 FPS "\n");
1465}
1466
1467static void
1468luU(enum usage_level ul, const char *command)
1469{
1470 int is_my_command = (command && 0 == strcmp(command, "U"));
1471 if (ul == usage_all || !command || is_my_command)
1472 FPS "%-15s List all modules\n", /*, or print out a single named module\n",*/
1473 "-U");
1474 if (ul == usage_selected && !is_my_command)
1475 return;
1476 FPS "%-20s Module database directory (default is '~/.netscape')\n",
1477 " -d moddir");
1478 FPS "%-20s Cert & Key database prefix\n",
1479 " -P dbprefix");
1480 FPS "%-20s force the database to open R/W\n",
1481 " -X");
1482 FPS "\n");
1483}
1484
1485static void
1486luK(enum usage_level ul, const char *command)
1487{
1488 int is_my_command = (command && 0 == strcmp(command, "K"));
1489 if (ul == usage_all || !command || is_my_command)
1490 FPS "%-15s List all private keys\n",
1491 "-K");
1492 if (ul == usage_selected && !is_my_command)
1493 return;
1494 FPS "%-20s Name of token to search (\"all\" for all tokens)\n",
1495 " -h token-name ");
1496
1497 FPS "%-20s Key type (\"all\" (default), \"dsa\","
1498 " \"ec\","
1499 " \"ed\","
1500 " \"mldsa\","
1501 " \"rsa\")\n",
1502 " -k key-type");
1503 FPS "%-20s The nickname of the key or associated certificate\n",
1504 " -n name");
1505 FPS "%-20s Specify the password file\n",
1506 " -f password-file");
1507 FPS "%-20s Key database directory (default is ~/.netscape)\n",
1508 " -d keydir");
1509 FPS "%-20s Cert & Key database prefix\n",
1510 " -P dbprefix");
1511 FPS "%-20s force the database to open R/W\n",
1512 " -X");
1513 FPS "\n");
1514}
1515
1516static void
1517luL(enum usage_level ul, const char *command)
1518{
1519 int is_my_command = (command && 0 == strcmp(command, "L"));
1520 if (ul == usage_all || !command || is_my_command)
1521 FPS "%-15s List all certs, or print out a single named cert (or a subset)\n",
1522 "-L");
1523 if (ul == usage_selected && !is_my_command)
1524 return;
1525 FPS "%-20s Name of token to search (\"all\" for all tokens)\n",
1526 " -h token-name ");
1527 FPS "%-20s Pretty print named cert (list all if unspecified)\n",
1528 " -n cert-name");
1529 FPS "%-20s \n"
1530 "%-20s Pretty print cert with email address (list all if unspecified)\n",
1531 " --email email-address", "");
1532 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1533 " -d certdir");
1534 FPS "%-20s Cert & Key database prefix\n",
1535 " -P dbprefix");
1536 FPS "%-20s force the database to open R/W\n",
1537 " -X");
1538 FPS "%-20s For single cert, print binary DER encoding\n",
1539 " -r");
1540 FPS "%-20s For single cert, print ASCII encoding (RFC1113)\n",
1541 " -a");
1542 FPS "%-20s \n"
1543 "%-20s For single cert, print binary DER encoding of extension OID\n",
1544 " --dump-ext-val OID", "");
1545 FPS "\n");
1546}
1547
1548static void
1549luM(enum usage_level ul, const char *command)
1550{
1551 int is_my_command = (command && 0 == strcmp(command, "M"));
1552 if (ul == usage_all || !command || is_my_command)
1553 FPS "%-15s Modify trust attributes of certificate\n",
1554 "-M");
1555 if (ul == usage_selected && !is_my_command)
1556 return;
1557 FPS "%-20s The nickname of the cert to modify\n",
1558 " -n cert-name");
1559 FPS "%-20s Set the certificate trust attributes (see -A above)\n",
1560 " -t trustargs");
1561 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1562 " -d certdir");
1563 FPS "%-20s Cert & Key database prefix\n",
1564 " -P dbprefix");
1565 FPS "\n");
1566}
1567
1568static void
1569luN(enum usage_level ul, const char *command)
1570{
1571 int is_my_command = (command && 0 == strcmp(command, "N"));
1572 if (ul == usage_all || !command || is_my_command)
1573 FPS "%-15s Create a new certificate database\n",
1574 "-N");
1575 if (ul == usage_selected && !is_my_command)
1576 return;
1577 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1578 " -d certdir");
1579 FPS "%-20s Cert & Key database prefix\n",
1580 " -P dbprefix");
1581 FPS "%-20s Specify the password file\n",
1582 " -f password-file");
1583 FPS "%-20s use empty password when creating a new database\n",
1584 " --empty-password");
1585 FPS "\n");
1586}
1587
1588static void
1589luT(enum usage_level ul, const char *command)
1590{
1591 int is_my_command = (command && 0 == strcmp(command, "T"));
1592 if (ul == usage_all || !command || is_my_command)
1593 FPS "%-15s Reset the Key database or token\n",
1594 "-T");
1595 if (ul == usage_selected && !is_my_command)
1596 return;
1597 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1598 " -d certdir");
1599 FPS "%-20s Cert & Key database prefix\n",
1600 " -P dbprefix");
1601 FPS "%-20s Token to reset (default is internal)\n",
1602 " -h token-name");
1603 FPS "%-20s Set token's Site Security Officer password\n",
1604 " -0 SSO-password");
1605 FPS "\n");
1606}
1607
1608static void
1609luO(enum usage_level ul, const char *command)
1610{
1611 int is_my_command = (command && 0 == strcmp(command, "O"));
1612 if (ul == usage_all || !command || is_my_command)
1613 FPS "%-15s Print the chain of a certificate\n",
1614 "-O");
1615 if (ul == usage_selected && !is_my_command)
1616 return;
1617 FPS "%-20s The nickname of the cert to modify\n",
1618 " -n cert-name");
1619 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1620 " -d certdir");
1621 FPS "%-20s Input the certificate in ASCII (RFC1113); default is binary\n",
1622 " -a");
1623 FPS "%-20s Cert & Key database prefix\n",
1624 " -P dbprefix");
1625 FPS "%-20s force the database to open R/W\n",
1626 " -X");
1627 FPS "%-20s don't search for a chain if issuer name equals subject name\n",
1628 " --simple-self-signed");
1629 FPS "\n");
1630}
1631
1632static void
1633luR(enum usage_level ul, const char *command)
1634{
1635 int is_my_command = (command && 0 == strcmp(command, "R"));
1636 if (ul == usage_all || !command || is_my_command)
1637 FPS "%-15s Generate a certificate request (stdout)\n",
1638 "-R");
1639 if (ul == usage_selected && !is_my_command)
1640 return;
1641 FPS "%-20s Specify the subject name (using RFC1485)\n",
1642 " -s subject");
1643 FPS "%-20s Output the cert request to this file\n",
1644 " -o output-req");
1645 FPS "%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n",
1646 " -k key-type-or-id");
1647 FPS "%-20s or nickname of the cert key to use, or key id obtained using -K\n",
1648 "");
1649 FPS "%-20s Name of token in which to generate key (default is internal)\n",
1650 " -h token-name");
1651 FPS "%-20s Key size in bits, RSA keys only (min %d, max %d, default %d)\n",
1652 " -g key-size", MIN_KEY_BITS512, MAX_KEY_BITS8192, DEFAULT_KEY_BITS2048);
1653 FPS "%-20s Create a certificate request restricted to RSA-PSS (rsa only)\n",
1654 " --pss");
1655 FPS "%-20s Name of file containing PQG parameters (dsa only)\n",
1656 " -q pqgfile");
1657 FPS "%-20s Elliptic curve name (ec only)\n",
1658 " -q curve-name");
1659 FPS "%-20s See the \"-G\" option for a full list of supported names.\n",
1660 "");
1661 FPS "%-20s Edwards elliptic curve name (ed only)\n",
1662 " -q curve-name");
1663 FPS "%-20s See the \"-G\" option for a full list of supported names.\n",
1664 "");
1665 FPS "%-20s ML-DSA parameter set (mldsa only)\n",
1666 " -q paramset");
1667 FPS "%-20s See the \"-G\" option for a full list of supported names.\n",
1668 "");
1669 FPS "%-20s Specify the password file\n",
1670 " -f pwfile");
1671 FPS "%-20s Key database directory (default is ~/.netscape)\n",
1672 " -d keydir");
1673 FPS "%-20s Cert & Key database prefix\n",
1674 " -P dbprefix");
1675 FPS "%-20s Specify the contact phone number (\"123-456-7890\")\n",
1676 " -p phone");
1677 FPS "%-20s \n"
1678 "%-20s Specify the hash algorithm to use. Possible keywords:\n"
1679 "%-20s \"MD2\", \"MD4\", \"MD5\", \"SHA1\", \"SHA224\",\n"
1680 "%-20s \"SHA256\", \"SHA384\", \"SHA512\"\n",
1681 " -Z hashAlg", "", "", "");
1682 FPS "%-20s Output the cert request in ASCII (RFC1113); default is binary\n",
1683 " -a");
1684 FPS "%-20s \n",
1685 " See -S for available extension options");
1686 FPS "%-20s \n",
1687 " See -G for available key flag options");
1688 FPS "\n");
1689}
1690
1691static void
1692luV(enum usage_level ul, const char *command)
1693{
1694 int is_my_command = (command && 0 == strcmp(command, "V"));
1695 if (ul == usage_all || !command || is_my_command)
1696 FPS "%-15s Validate a certificate\n",
1697 "-V");
1698 if (ul == usage_selected && !is_my_command)
1699 return;
1700 FPS "%-20s The nickname of the cert to Validate\n",
1701 " -n cert-name");
1702 FPS "%-20s validity time (\"YYMMDDHHMMSS[+HHMM|-HHMM|Z]\")\n",
1703 " -b time");
1704 FPS "%-20s Check certificate signature \n",
1705 " -e ");
1706 FPS "%-20s Specify certificate usage:\n", " -u certusage");
1707 FPS "%-25s C \t SSL Client\n", "");
1708 FPS "%-25s V \t SSL Server\n", "");
1709 FPS "%-25s I \t IPsec\n", "");
1710 FPS "%-25s L \t SSL CA\n", "");
1711 FPS "%-25s A \t Any CA\n", "");
1712 FPS "%-25s Y \t Verify CA\n", "");
1713 FPS "%-25s S \t Email signer\n", "");
1714 FPS "%-25s R \t Email Recipient\n", "");
1715 FPS "%-25s O \t OCSP status responder\n", "");
1716 FPS "%-25s J \t Object signer\n", "");
1717 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1718 " -d certdir");
1719 FPS "%-20s Input the certificate in ASCII (RFC1113); default is binary\n",
1720 " -a");
1721 FPS "%-20s Cert & Key database prefix\n",
1722 " -P dbprefix");
1723 FPS "%-20s force the database to open R/W\n",
1724 " -X");
1725 FPS "\n");
1726}
1727
1728static void
1729luW(enum usage_level ul, const char *command)
1730{
1731 int is_my_command = (command && 0 == strcmp(command, "W"));
1732 if (ul == usage_all || !command || is_my_command)
1733 FPS "%-15s Change the key database password\n",
1734 "-W");
1735 if (ul == usage_selected && !is_my_command)
1736 return;
1737 FPS "%-20s cert and key database directory\n",
1738 " -d certdir");
1739 FPS "%-20s Specify a file with the current password\n",
1740 " -f pwfile");
1741 FPS "%-20s Specify a file with the new password in two lines\n",
1742 " -@ newpwfile");
1743 FPS "\n");
1744}
1745
1746static void
1747luRename(enum usage_level ul, const char *command)
1748{
1749 int is_my_command = (command && 0 == strcmp(command, "rename"));
1750 if (ul == usage_all || !command || is_my_command)
1751 FPS "%-15s Change the database nickname of a certificate\n",
1752 "--rename");
1753 if (ul == usage_selected && !is_my_command)
1754 return;
1755 FPS "%-20s The old nickname of the cert to rename\n",
1756 " -n cert-name");
1757 FPS "%-20s The new nickname of the cert to rename\n",
1758 " --new-n new-name");
1759 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1760 " -d certdir");
1761 FPS "%-20s Cert & Key database prefix\n",
1762 " -P dbprefix");
1763 FPS "\n");
1764}
1765
1766static void
1767luUpgradeMerge(enum usage_level ul, const char *command)
1768{
1769 int is_my_command = (command && 0 == strcmp(command, "upgrade-merge"));
1770 if (ul == usage_all || !command || is_my_command)
1771 FPS "%-15s Upgrade an old database and merge it into a new one\n",
1772 "--upgrade-merge");
1773 if (ul == usage_selected && !is_my_command)
1774 return;
1775 FPS "%-20s Cert database directory to merge into (default is ~/.netscape)\n",
1776 " -d certdir");
1777 FPS "%-20s Cert & Key database prefix of the target database\n",
1778 " -P dbprefix");
1779 FPS "%-20s Specify the password file for the target database\n",
1780 " -f pwfile");
1781 FPS "%-20s \n%-20s Cert database directory to upgrade from\n",
1782 " --source-dir certdir", "");
1783 FPS "%-20s \n%-20s Cert & Key database prefix of the upgrade database\n",
1784 " --source-prefix dbprefix", "");
1785 FPS "%-20s \n%-20s Unique identifier for the upgrade database\n",
1786 " --upgrade-id uniqueID", "");
1787 FPS "%-20s \n%-20s Name of the token while it is in upgrade state\n",
1788 " --upgrade-token-name name", "");
1789 FPS "%-20s Specify the password file for the upgrade database\n",
1790 " -@ pwfile");
1791 FPS "\n");
1792}
1793
1794static void
1795luMerge(enum usage_level ul, const char *command)
1796{
1797 int is_my_command = (command && 0 == strcmp(command, "merge"));
1798 if (ul == usage_all || !command || is_my_command)
1799 FPS "%-15s Merge source database into the target database\n",
1800 "--merge");
1801 if (ul == usage_selected && !is_my_command)
1802 return;
1803 FPS "%-20s Cert database directory of target (default is ~/.netscape)\n",
1804 " -d certdir");
1805 FPS "%-20s Cert & Key database prefix of the target database\n",
1806 " -P dbprefix");
1807 FPS "%-20s Specify the password file for the target database\n",
1808 " -f pwfile");
1809 FPS "%-20s \n%-20s Cert database directory of the source database\n",
1810 " --source-dir certdir", "");
1811 FPS "%-20s \n%-20s Cert & Key database prefix of the source database\n",
1812 " --source-prefix dbprefix", "");
1813 FPS "%-20s Specify the password file for the source database\n",
1814 " -@ pwfile");
1815 FPS "\n");
1816}
1817
1818static void
1819luS(enum usage_level ul, const char *command)
1820{
1821 int is_my_command = (command && 0 == strcmp(command, "S"));
1822 if (ul == usage_all || !command || is_my_command)
1823 FPS "%-15s Make a certificate and add to database\n",
1824 "-S");
1825 if (ul == usage_selected && !is_my_command)
1826 return;
1827 FPS "%-20s Specify the nickname of the cert\n",
1828 " -n key-name");
1829 FPS "%-20s Specify the subject name (using RFC1485)\n",
1830 " -s subject");
1831 FPS "%-20s The nickname of the issuer cert\n",
1832 " -c issuer-name");
1833 FPS "%-20s Set the certificate trust attributes (see -A above)\n",
1834 " -t trustargs");
1835 FPS "%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n",
1836 " -k key-type-or-id");
1837 FPS "%-20s Name of token in which to generate key (default is internal)\n",
1838 " -h token-name");
1839 FPS "%-20s Key size in bits, RSA keys only (min %d, max %d, default %d)\n",
1840 " -g key-size", MIN_KEY_BITS512, MAX_KEY_BITS8192, DEFAULT_KEY_BITS2048);
1841 FPS "%-20s Create a certificate restricted to RSA-PSS (rsa only)\n",
1842 " --pss");
1843 FPS "%-20s Name of file containing PQG parameters (dsa only)\n",
1844 " -q pqgfile");
1845 FPS "%-20s Elliptic curve name (ec only)\n",
1846 " -q curve-name");
1847 FPS "%-20s See the \"-G\" option for a full list of supported names.\n",
1848 "");
1849 FPS "%-20s Edwards elliptic curve name (ed only)\n",
1850 " -q curve-name");
1851 FPS "%-20s See the \"-G\" option for a full list of supported names.\n",
1852 "");
1853 FPS "%-20s ML-DSA parameter set (mldsa only)\n",
1854 " -q paramset");
1855 FPS "%-20s See the \"-G\" option for a full list of supported names.\n",
1856 "");
1857 FPS "%-20s Self sign\n",
1858 " -x");
1859 FPS "%-20s Sign the certificate with RSA-PSS (the issuer key must be rsa)\n",
1860 " --pss-sign");
1861 FPS "%-20s Cert serial number\n",
1862 " -m serial-number");
1863 FPS "%-20s Time Warp\n",
1864 " -w warp-months");
1865 FPS "%-20s Months valid (default is 3)\n",
1866 " -v months-valid");
1867 FPS "%-20s Specify the password file\n",
1868 " -f pwfile");
1869 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1870 " -d certdir");
1871 FPS "%-20s Cert & Key database prefix\n",
1872 " -P dbprefix");
1873 FPS "%-20s Specify the contact phone number (\"123-456-7890\")\n",
1874 " -p phone");
1875 FPS "%-20s \n"
1876 "%-20s Specify the hash algorithm to use. Possible keywords:\n"
1877 "%-20s \"MD2\", \"MD4\", \"MD5\", \"SHA1\", \"SHA224\",\n"
1878 "%-20s \"SHA256\", \"SHA384\", \"SHA512\"\n",
1879 " -Z hashAlg", "", "", "");
1880 FPS "%-20s Create key usage extension\n",
1881 " -1 ");
1882 FPS "%-20s Create basic constraint extension\n",
1883 " -2 ");
1884 FPS "%-20s Create authority key ID extension\n",
1885 " -3 ");
1886 FPS "%-20s Create crl distribution point extension\n",
1887 " -4 ");
1888 FPS "%-20s Create netscape cert type extension\n",
1889 " -5 ");
1890 FPS "%-20s Create extended key usage extension\n",
1891 " -6 ");
1892 FPS "%-20s Create an email subject alt name extension\n",
1893 " -7 emailAddrs ");
1894 FPS "%-20s Create a DNS subject alt name extension\n",
1895 " -8 DNS-names");
1896 FPS "%-20s Create an Authority Information Access extension\n",
1897 " --extAIA ");
1898 FPS "%-20s Create a Subject Information Access extension\n",
1899 " --extSIA ");
1900 FPS "%-20s Create a Certificate Policies extension\n",
1901 " --extCP ");
1902 FPS "%-20s Create a Policy Mappings extension\n",
1903 " --extPM ");
1904 FPS "%-20s Create a Policy Constraints extension\n",
1905 " --extPC ");
1906 FPS "%-20s Create an Inhibit Any Policy extension\n",
1907 " --extIA ");
1908 FPS "%-20s Create a subject key ID extension\n",
1909 " --extSKID ");
1910 FPS "%-20s \n",
1911 " See -G for available key flag options");
1912 FPS "%-20s Create a name constraints extension\n",
1913 " --extNC ");
1914 FPS "%-20s \n"
1915 "%-20s Create a Subject Alt Name extension with one or multiple names\n",
1916 " --extSAN type:name[,type:name]...", "");
1917 FPS "%-20s - type: directory, dn, dns, edi, ediparty, email, ip, ipaddr,\n", "");
1918 FPS "%-20s other, registerid, rfc822, uri, x400, x400addr\n", "");
1919 FPS "%-20s \n"
1920 "%-20s Add one or multiple extensions that certutil cannot encode yet,\n"
1921 "%-20s by loading their encodings from external files.\n",
1922 " --extGeneric OID:critical-flag:filename[,OID:critical-flag:filename]...", "", "");
1923 FPS "%-20s - OID (example): 1.2.3.4\n", "");
1924 FPS "%-20s - critical-flag: critical or not-critical\n", "");
1925 FPS "%-20s - filename: full path to a file containing an encoded extension\n", "");
1926 FPS "\n");
1927}
1928
1929static void
1930luBuildFlags(enum usage_level ul, const char *command)
1931{
1932 int is_my_command = (command && 0 == strcmp(command, "build-flags"));
1933 if (ul == usage_all || !command || is_my_command)
1934 FPS "%-15s Print enabled build flags relevant for NSS test execution\n",
1935 "--build-flags");
1936 if (ul == usage_selected && !is_my_command)
1937 return;
1938 FPS "\n");
1939}
1940
1941static void
1942LongUsage(enum usage_level ul, const char *command)
1943{
1944 luA(ul, command);
1945 luB(ul, command);
1946 luE(ul, command);
1947 luC(ul, command);
1948 luG(ul, command);
1949 luD(ul, command);
1950 luRename(ul, command);
1951 luF(ul, command);
1952 luU(ul, command);
1953 luK(ul, command);
1954 luL(ul, command);
1955 luBuildFlags(ul, command);
1956 luM(ul, command);
1957 luN(ul, command);
1958 luT(ul, command);
1959 luO(ul, command);
1960 luR(ul, command);
1961 luV(ul, command);
1962 luW(ul, command);
1963 luUpgradeMerge(ul, command);
1964 luMerge(ul, command);
1965 luS(ul, command);
1966#undef FPS
1967}
1968
1969static void
1970Usage()
1971{
1972 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
1973 "%s - Utility to manipulate NSS certificate databases\n\n"
1974 "Usage: %s <command> -d <database-directory> <options>\n\n"
1975 "Valid commands:\n",
1976 progName, progName);
1977 LongUsage(usage_selected, NULL((void*)0));
1978 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "\n"
1979 "%s -H <command> : Print available options for the given command\n"
1980 "%s -H : Print complete help output of all commands and options\n"
1981 "%s --syntax : Print a short summary of all commands and options\n",
1982 progName, progName, progName);
1983 exit(1);
1984}
1985
1986static CERTCertificate *
1987MakeV1Cert(CERTCertDBHandle *handle,
1988 CERTCertificateRequest *req,
1989 char *issuerNickName,
1990 PRBool selfsign,
1991 unsigned int serialNumber,
1992 int warpmonths,
1993 int validityMonths)
1994{
1995 CERTCertificate *issuerCert = NULL((void*)0);
1996 CERTValidity *validity;
1997 CERTCertificate *cert = NULL((void*)0);
1998 PRExplodedTime printableTime;
1999 PRTime now, after;
2000
2001 if (!selfsign) {
2002 issuerCert = CERT_FindCertByNicknameOrEmailAddr(handle, issuerNickName);
2003 if (!issuerCert) {
2004 SECU_PrintError(progName, "could not find certificate named \"%s\"",
2005 issuerNickName);
2006 return NULL((void*)0);
2007 }
2008 }
2009
2010 now = PR_Now();
2011 PR_ExplodeTime(now, PR_GMTParameters, &printableTime);
2012 if (warpmonths) {
2013 printableTime.tm_month += warpmonths;
2014 now = PR_ImplodeTime(&printableTime);
2015 PR_ExplodeTime(now, PR_GMTParameters, &printableTime);
2016 }
2017 printableTime.tm_month += validityMonths;
2018 after = PR_ImplodeTime(&printableTime);
2019
2020 /* note that the time is now in micro-second unit */
2021 validity = CERT_CreateValidity(now, after);
2022 if (validity) {
2023 cert = CERT_CreateCertificate(serialNumber,
2024 (selfsign ? &req->subject
2025 : &issuerCert->subject),
2026 validity, req);
2027
2028 CERT_DestroyValidity(validity);
2029 }
2030 if (issuerCert) {
2031 CERT_DestroyCertificate(issuerCert);
2032 }
2033
2034 return (cert);
2035}
2036
2037static SECStatus
2038SetSignatureAlgorithm(PLArenaPool *arena,
2039 SECAlgorithmID *signAlg,
2040 SECAlgorithmID *spkiAlg,
2041 SECOidTag hashAlgTag,
2042 SECKEYPrivateKey *privKey,
2043 PRBool pssSign)
2044{
2045 SECOidTag signAlgTag = SEC_OID_UNKNOWN;
2046 SECItem *params = NULL((void*)0);
2047
2048 if (pssSign) {
2049 signAlgTag = SEC_OID_PKCS1_RSA_PSS_SIGNATURE;
2050 }
2051 if (SECOID_GetAlgorithmTagSECOID_GetAlgorithmTag_Util(spkiAlg) == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
2052 signAlgTag = SEC_OID_PKCS1_RSA_PSS_SIGNATURE;
2053 params = &spkiAlg->parameters;
2054 }
2055 return SEC_CreateSignatureAlgorithmID(arena, signAlg, signAlgTag,
2056 hashAlgTag, params, privKey, NULL((void*)0));
2057}
2058
2059static SECStatus
2060SignCert(CERTCertDBHandle *handle, CERTCertificate *cert, PRBool selfsign,
2061 SECOidTag hashAlgTag,
2062 SECKEYPrivateKey *privKey, char *issuerNickName,
2063 int certVersion, PRBool pssSign, void *pwarg)
2064{
2065 SECItem der;
2066 SECKEYPrivateKey *caPrivateKey = NULL((void*)0);
2067 SECStatus rv;
2068 PLArenaPool *arena;
2069 CERTCertificate *issuer;
2070 void *dummy;
2071
2072 arena = cert->arena;
2073
2074 if (selfsign) {
2075 issuer = cert;
2076 } else {
2077 issuer = PK11_FindCertFromNickname(issuerNickName, pwarg);
2078 if ((CERTCertificate *)NULL((void*)0) == issuer) {
2079 SECU_PrintError(progName, "unable to find issuer with nickname %s",
2080 issuerNickName);
2081 rv = SECFailure;
2082 goto done;
2083 }
2084 privKey = caPrivateKey = PK11_FindKeyByAnyCert(issuer, pwarg);
2085 if (caPrivateKey == NULL((void*)0)) {
2086 SECU_PrintError(progName, "unable to retrieve key %s", issuerNickName);
2087 rv = SECFailure;
2088 CERT_DestroyCertificate(issuer);
2089 goto done;
2090 }
2091 }
2092
2093 if (pssSign &&
2094 (SECKEY_GetPrivateKeyType(privKey) != rsaKey &&
2095 SECKEY_GetPrivateKeyType(privKey) != rsaPssKey)) {
2096 SECU_PrintError(progName, "unable to create RSA-PSS signature with key %s",
2097 issuerNickName);
2098 rv = SECFailure;
2099 if (!selfsign) {
2100 CERT_DestroyCertificate(issuer);
2101 }
2102 goto done;
2103 }
2104
2105 rv = SetSignatureAlgorithm(arena,
2106 &cert->signature,
2107 &issuer->subjectPublicKeyInfo.algorithm,
2108 hashAlgTag,
2109 privKey,
2110 pssSign);
2111 if (!selfsign) {
2112 CERT_DestroyCertificate(issuer);
2113 }
2114 if (rv != SECSuccess) {
2115 goto done;
2116 }
2117
2118 switch (certVersion) {
2119 case (SEC_CERTIFICATE_VERSION_10):
2120 /* The initial version for x509 certificates is version one
2121 * and this default value must be an implicit DER encoding. */
2122 cert->version.data = NULL((void*)0);
2123 cert->version.len = 0;
2124 break;
2125 case (SEC_CERTIFICATE_VERSION_21):
2126 case (SEC_CERTIFICATE_VERSION_32):
2127 case 3: /* unspecified format (would be version 4 certificate). */
2128 *(cert->version.data) = certVersion;
2129 cert->version.len = 1;
2130 break;
2131 default:
2132 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
2133 rv = SECFailure;
2134 goto done;
2135 }
2136
2137 der.len = 0;
2138 der.data = NULL((void*)0);
2139 dummy = SEC_ASN1EncodeItemSEC_ASN1EncodeItem_Util(arena, &der, cert,
2140 SEC_ASN1_GET(CERT_CertificateTemplate)CERT_CertificateTemplate);
2141 if (!dummy) {
2142 fprintf(stderrstderr, "Could not encode certificate.\n");
2143 rv = SECFailure;
2144 goto done;
2145 }
2146
2147 rv = SEC_DerSignDataWithAlgorithmID(arena, &cert->derCert, der.data, der.len,
2148 privKey, &cert->signature);
2149 if (rv != SECSuccess) {
2150 fprintf(stderrstderr, "Could not sign encoded certificate data.\n");
2151 /* result allocated out of the arena, it will be freed
2152 * when the arena is freed */
2153 goto done;
2154 }
2155done:
2156 if (caPrivateKey) {
2157 SECKEY_DestroyPrivateKey(caPrivateKey);
2158 }
2159 return rv;
2160}
2161
2162static SECStatus
2163CreateCert(
2164 CERTCertDBHandle *handle,
2165 PK11SlotInfo *slot,
2166 char *issuerNickName,
2167 const SECItem *certReqDER,
2168 SECKEYPrivateKey **selfsignprivkey,
2169 void *pwarg,
2170 SECOidTag hashAlgTag,
2171 unsigned int serialNumber,
2172 int warpmonths,
2173 int validityMonths,
2174 const char *emailAddrs,
2175 const char *dnsNames,
2176 PRBool ascii,
2177 PRBool selfsign,
2178 certutilExtnList extnList,
2179 const char *extGeneric,
2180 int certVersion,
2181 PRBool pssSign,
2182 SECItem *certDER)
2183{
2184 void *extHandle = NULL((void*)0);
2185 CERTCertificate *subjectCert = NULL((void*)0);
2186 CERTCertificateRequest *certReq = NULL((void*)0);
2187 SECStatus rv = SECSuccess;
2188 CERTCertExtension **CRexts;
2189
2190 do {
2191 /* Create a certrequest object from the input cert request der */
2192 certReq = GetCertRequest(certReqDER, pwarg);
2193 if (certReq == NULL((void*)0)) {
2194 GEN_BREAK(SECFailure)rv = SECFailure; break;
2195 }
2196
2197 subjectCert = MakeV1Cert(handle, certReq, issuerNickName, selfsign,
2198 serialNumber, warpmonths, validityMonths);
2199 if (subjectCert == NULL((void*)0)) {
2200 GEN_BREAK(SECFailure)rv = SECFailure; break;
2201 }
2202
2203 extHandle = CERT_StartCertExtensions(subjectCert);
2204 if (extHandle == NULL((void*)0)) {
2205 GEN_BREAK(SECFailure)rv = SECFailure; break;
2206 }
2207
2208 rv = AddExtensions(extHandle, emailAddrs, dnsNames, extnList, extGeneric);
2209 if (rv != SECSuccess) {
2210 GEN_BREAK(SECFailure)rv = SECFailure; break;
2211 }
2212
2213 if (certReq->attributes != NULL((void*)0) &&
2214 certReq->attributes[0] != NULL((void*)0) &&
2215 certReq->attributes[0]->attrType.data != NULL((void*)0) &&
2216 certReq->attributes[0]->attrType.len > 0 &&
2217 SECOID_FindOIDTagSECOID_FindOIDTag_Util(&certReq->attributes[0]->attrType) ==
2218 SEC_OID_PKCS9_EXTENSION_REQUEST) {
2219 rv = CERT_GetCertificateRequestExtensions(certReq, &CRexts);
2220 if (rv != SECSuccess)
2221 break;
2222 rv = CERT_MergeExtensions(extHandle, CRexts);
2223 if (rv != SECSuccess)
2224 break;
2225 }
2226
2227 CERT_FinishExtensions(extHandle);
2228 extHandle = NULL((void*)0);
2229
2230 /* self-signing a cert request, find the private key */
2231 if (selfsign && *selfsignprivkey == NULL((void*)0)) {
2232 *selfsignprivkey = PK11_FindKeyByDERCert(slot, subjectCert, pwarg);
2233 if (!*selfsignprivkey) {
2234 fprintf(stderrstderr, "Failed to locate private key.\n");
2235 rv = SECFailure;
2236 break;
2237 }
2238 }
2239
2240 rv = SignCert(handle, subjectCert, selfsign, hashAlgTag,
2241 *selfsignprivkey, issuerNickName,
2242 certVersion, pssSign, pwarg);
2243 if (rv != SECSuccess)
2244 break;
2245
2246 rv = SECFailure;
2247 if (ascii) {
2248 char *asciiDER = BTOA_DataToAsciiBTOA_DataToAscii_Util(subjectCert->derCert.data,
2249 subjectCert->derCert.len);
2250 if (asciiDER) {
2251 char *wrapped = PR_smprintf("%s\n%s\n%s\n",
2252 NS_CERT_HEADER"-----BEGIN CERTIFICATE-----",
2253 asciiDER,
2254 NS_CERT_TRAILER"-----END CERTIFICATE-----");
2255 if (wrapped) {
2256 PRUint32 wrappedLen = PL_strlen(wrapped);
2257 if (SECITEM_AllocItemSECITEM_AllocItem_Util(NULL((void*)0), certDER, wrappedLen)) {
2258 PORT_Memcpymemcpy(certDER->data, wrapped, wrappedLen);
2259 rv = SECSuccess;
2260 }
2261 PR_smprintf_free(wrapped);
2262 }
2263 PORT_FreePORT_Free_Util(asciiDER);
2264 }
2265 } else {
2266 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(NULL((void*)0), certDER, &subjectCert->derCert);
2267 }
2268 } while (0);
2269 if (extHandle) {
2270 CERT_FinishExtensions(extHandle);
2271 }
2272 CERT_DestroyCertificateRequest(certReq);
2273 CERT_DestroyCertificate(subjectCert);
2274 if (rv != SECSuccess) {
2275 PRErrorCode perr = PR_GetError();
2276 fprintf(stderrstderr, "%s: unable to create cert (%s)\n", progName,
2277 SECU_Strerror(perr)PR_ErrorToString((perr), 0));
2278 }
2279 return (rv);
2280}
2281
2282/*
2283 * map a class to a user presentable string
2284 */
2285static const char *objClassArray[] = {
2286 "Data",
2287 "Certificate",
2288 "Public Key",
2289 "Private Key",
2290 "Secret Key",
2291 "Hardware Feature",
2292 "Domain Parameters",
2293 "Mechanism"
2294};
2295
2296static const char *objNSSClassArray[] = {
2297 "CKO_NSS",
2298 "Crl",
2299 "SMIME Record",
2300 "Trust",
2301 "Builtin Root List"
2302};
2303
2304const char *
2305getObjectClass(CK_ULONG classType)
2306{
2307 static char buf[sizeof(CK_ULONG) * 2 + 3];
2308
2309 if (classType <= CKO_MECHANISM0x00000007UL) {
2310 return objClassArray[classType];
2311 }
2312 if (classType >= CKO_NSS(0x80000000UL | 0x4E534350) && classType <= CKO_NSS_BUILTIN_ROOT_LIST((0x80000000UL | 0x4E534350) + 4)) {
2313 return objNSSClassArray[classType - CKO_NSS(0x80000000UL | 0x4E534350)];
2314 }
2315 snprintf(buf, sizeof(buf), "0x%lx", classType);
2316 return buf;
2317}
2318
2319typedef struct {
2320 char *name;
2321 int nameSize;
2322 CK_ULONG value;
2323} flagArray;
2324
2325#define NAME_SIZE(x)"x", sizeof("x") - 1 #x, sizeof(#x) - 1
2326
2327flagArray opFlagsArray[] = {
2328 { NAME_SIZE(encrypt)"encrypt", sizeof("encrypt") - 1, CKF_ENCRYPT0x00000100UL },
2329 { NAME_SIZE(decrypt)"decrypt", sizeof("decrypt") - 1, CKF_DECRYPT0x00000200UL },
2330 { NAME_SIZE(sign)"sign", sizeof("sign") - 1, CKF_SIGN0x00000800UL },
2331 { NAME_SIZE(sign_recover)"sign_recover", sizeof("sign_recover") - 1, CKF_SIGN_RECOVER0x00001000UL },
2332 { NAME_SIZE(verify)"verify", sizeof("verify") - 1, CKF_VERIFY0x00002000 },
2333 { NAME_SIZE(verify_recover)"verify_recover", sizeof("verify_recover") - 1, CKF_VERIFY_RECOVER0x00004000UL },
2334 { NAME_SIZE(wrap)"wrap", sizeof("wrap") - 1, CKF_WRAP0x00020000UL },
2335 { NAME_SIZE(unwrap)"unwrap", sizeof("unwrap") - 1, CKF_UNWRAP0x00040000UL },
2336 { NAME_SIZE(derive)"derive", sizeof("derive") - 1, CKF_DERIVE0x00080000UL }
2337};
2338
2339int opFlagsCount = PR_ARRAY_SIZE(opFlagsArray)(sizeof(opFlagsArray) / sizeof((opFlagsArray)[0]));
2340
2341flagArray attrFlagsArray[] = {
2342 { NAME_SIZE(token)"token", sizeof("token") - 1, PK11_ATTR_TOKEN0x00000001L },
2343 { NAME_SIZE(session)"session", sizeof("session") - 1, PK11_ATTR_SESSION0x00000002L },
2344 { NAME_SIZE(private)"private", sizeof("private") - 1, PK11_ATTR_PRIVATE0x00000004L },
2345 { NAME_SIZE(public)"public", sizeof("public") - 1, PK11_ATTR_PUBLIC0x00000008L },
2346 { NAME_SIZE(modifiable)"modifiable", sizeof("modifiable") - 1, PK11_ATTR_MODIFIABLE0x00000010L },
2347 { NAME_SIZE(unmodifiable)"unmodifiable", sizeof("unmodifiable") - 1, PK11_ATTR_UNMODIFIABLE0x00000020L },
2348 { NAME_SIZE(sensitive)"sensitive", sizeof("sensitive") - 1, PK11_ATTR_SENSITIVE0x00000040L },
2349 { NAME_SIZE(insensitive)"insensitive", sizeof("insensitive") - 1, PK11_ATTR_INSENSITIVE0x00000080L },
2350 { NAME_SIZE(extractable)"extractable", sizeof("extractable") - 1, PK11_ATTR_EXTRACTABLE0x00000100L },
2351 { NAME_SIZE(unextractable)"unextractable", sizeof("unextractable") - 1, PK11_ATTR_UNEXTRACTABLE0x00000200L }
2352};
2353
2354int attrFlagsCount = PR_ARRAY_SIZE(attrFlagsArray)(sizeof(attrFlagsArray) / sizeof((attrFlagsArray)[0]));
2355
2356#define MAX_STRING30 30
2357CK_ULONG
2358GetFlags(char *flagsString, flagArray *flags, int count)
2359{
2360 CK_ULONG flagsValue = strtol(flagsString, NULL((void*)0), 0);
2361 int i;
2362
2363 if ((flagsValue != 0) || (*flagsString == 0)) {
2364 return flagsValue;
2365 }
2366 while (*flagsString) {
2367 for (i = 0; i < count; i++) {
2368 if (strncmp(flagsString, flags[i].name, flags[i].nameSize) ==
2369 0) {
2370 flagsValue |= flags[i].value;
2371 flagsString += flags[i].nameSize;
2372 if (*flagsString != 0) {
2373 flagsString++;
2374 }
2375 break;
2376 }
2377 }
2378 if (i == count) {
2379 char name[MAX_STRING30];
2380 char *tok;
2381
2382 strncpy(name, flagsString, MAX_STRING30);
2383 name[MAX_STRING30 - 1] = 0;
2384 tok = strchr(name, ',');
2385 if (tok) {
2386 *tok = 0;
2387 }
2388 fprintf(stderrstderr, "Unknown flag (%s)\n", name);
2389 tok = strchr(flagsString, ',');
2390 if (tok == NULL((void*)0)) {
2391 break;
2392 }
2393 flagsString = tok + 1;
2394 }
2395 }
2396 return flagsValue;
2397}
2398
2399CK_FLAGS
2400GetOpFlags(char *flags)
2401{
2402 return GetFlags(flags, opFlagsArray, opFlagsCount);
2403}
2404
2405PK11AttrFlags
2406GetAttrFlags(char *flags)
2407{
2408 return GetFlags(flags, attrFlagsArray, attrFlagsCount);
2409}
2410
2411char *
2412mkNickname(unsigned char *data, int len)
2413{
2414 char *nick = PORT_AllocPORT_Alloc_Util(len + 1);
2415 if (!nick) {
2416 return nick;
2417 }
2418 PORT_Memcpymemcpy(nick, data, len);
2419 nick[len] = 0;
2420 return nick;
2421}
2422
2423/*
2424 * dump a PK11_MergeTokens error log to the console
2425 */
2426void
2427DumpMergeLog(const char *progname, PK11MergeLog *log)
2428{
2429 PK11MergeLogNode *node;
2430
2431 for (node = log->head; node; node = node->next) {
2432 SECItem attrItem;
2433 char *nickname = NULL((void*)0);
2434 const char *objectClass = NULL((void*)0);
2435 SECStatus rv;
2436
2437 attrItem.data = NULL((void*)0);
2438 rv = PK11_ReadRawAttribute(PK11_TypeGeneric, node->object,
2439 CKA_LABEL0x00000003UL, &attrItem);
2440 if (rv == SECSuccess) {
2441 nickname = mkNickname(attrItem.data, attrItem.len);
2442 PORT_FreePORT_Free_Util(attrItem.data);
2443 }
2444 attrItem.data = NULL((void*)0);
2445 rv = PK11_ReadRawAttribute(PK11_TypeGeneric, node->object,
2446 CKA_CLASS0x00000000UL, &attrItem);
2447 if (rv == SECSuccess) {
2448 if (attrItem.len == sizeof(CK_ULONG)) {
2449 objectClass = getObjectClass(*(CK_ULONG *)attrItem.data);
2450 }
2451 PORT_FreePORT_Free_Util(attrItem.data);
2452 }
2453
2454 fprintf(stderrstderr, "%s: Could not merge object %s (type %s): %s\n",
2455 progName,
2456 nickname ? nickname : "unnamed",
2457 objectClass ? objectClass : "unknown",
2458 SECU_Strerror(node->error)PR_ErrorToString((node->error), 0));
2459
2460 if (nickname) {
2461 PORT_FreePORT_Free_Util(nickname);
2462 }
2463 }
2464}
2465
2466/* Certutil commands */
2467enum {
2468 cmd_AddCert = 0,
2469 cmd_CreateNewCert,
2470 cmd_DeleteCert,
2471 cmd_AddEmailCert,
2472 cmd_DeleteKey,
2473 cmd_GenKeyPair,
2474 cmd_PrintHelp,
2475 cmd_PrintSyntax,
2476 cmd_ListKeys,
2477 cmd_ListCerts,
2478 cmd_ModifyCertTrust,
2479 cmd_NewDBs,
2480 cmd_DumpChain,
2481 cmd_CertReq,
2482 cmd_CreateAndAddCert,
2483 cmd_TokenReset,
2484 cmd_ListModules,
2485 cmd_CheckCertValidity,
2486 cmd_ChangePassword,
2487 cmd_Version,
2488 cmd_Batch,
2489 cmd_Merge,
2490 cmd_UpgradeMerge, /* test only */
2491 cmd_Rename,
2492 cmd_BuildFlags,
2493 max_cmd
2494};
2495
2496/* Certutil options */
2497enum certutilOpts {
2498 opt_SSOPass = 0,
2499 opt_AddKeyUsageExt,
2500 opt_AddBasicConstraintExt,
2501 opt_AddAuthorityKeyIDExt,
2502 opt_AddCRLDistPtsExt,
2503 opt_AddNSCertTypeExt,
2504 opt_AddExtKeyUsageExt,
2505 opt_ExtendedEmailAddrs,
2506 opt_ExtendedDNSNames,
2507 opt_ASCIIForIO,
2508 opt_ValidityTime,
2509 opt_IssuerName,
2510 opt_CertDir,
2511 opt_VerifySig,
2512 opt_PasswordFile,
2513 opt_KeySize,
2514 opt_TokenName,
2515 opt_InputFile,
2516 opt_Emailaddress,
2517 opt_KeyIndex,
2518 opt_KeyType,
2519 opt_DetailedInfo,
2520 opt_SerialNumber,
2521 opt_Nickname,
2522 opt_OutputFile,
2523 opt_PhoneNumber,
2524 opt_DBPrefix,
2525 opt_PQGFile,
2526 opt_BinaryDER,
2527 opt_Subject,
2528 opt_Trust,
2529 opt_Usage,
2530 opt_Validity,
2531 opt_OffsetMonths,
2532 opt_SelfSign,
2533 opt_RW,
2534 opt_Exponent,
2535 opt_NoiseFile,
2536 opt_Hash,
2537 opt_NewPasswordFile,
2538 opt_AddAuthInfoAccExt,
2539 opt_AddSubjInfoAccExt,
2540 opt_AddCertPoliciesExt,
2541 opt_AddPolicyMapExt,
2542 opt_AddPolicyConstrExt,
2543 opt_AddInhibAnyExt,
2544 opt_AddNameConstraintsExt,
2545 opt_AddSubjectKeyIDExt,
2546 opt_AddCmdKeyUsageExt,
2547 opt_AddCmdNSCertTypeExt,
2548 opt_AddCmdExtKeyUsageExt,
2549 opt_SourceDir,
2550 opt_SourcePrefix,
2551 opt_UpgradeID,
2552 opt_UpgradeTokenName,
2553 opt_KeyOpFlagsOn,
2554 opt_KeyOpFlagsOff,
2555 opt_KeyAttrFlags,
2556 opt_EmptyPassword,
2557 opt_CertVersion,
2558 opt_AddSubjectAltNameExt,
2559 opt_DumpExtensionValue,
2560 opt_GenericExtensions,
2561 opt_NewNickname,
2562 opt_Pss,
2563 opt_PssSign,
2564 opt_SimpleSelfSigned,
2565 opt_Help
2566};
2567
2568static const secuCommandFlag commands_init[] = {
2569 { /* cmd_AddCert */ 'A', PR_FALSE0, 0, PR_FALSE0 },
2570 { /* cmd_CreateNewCert */ 'C', PR_FALSE0, 0, PR_FALSE0 },
2571 { /* cmd_DeleteCert */ 'D', PR_FALSE0, 0, PR_FALSE0 },
2572 { /* cmd_AddEmailCert */ 'E', PR_FALSE0, 0, PR_FALSE0 },
2573 { /* cmd_DeleteKey */ 'F', PR_FALSE0, 0, PR_FALSE0 },
2574 { /* cmd_GenKeyPair */ 'G', PR_FALSE0, 0, PR_FALSE0 },
2575 { /* cmd_PrintHelp */ 'H', PR_FALSE0, 0, PR_FALSE0, "help" },
2576 { /* cmd_PrintSyntax */ 0, PR_FALSE0, 0, PR_FALSE0,
2577 "syntax" },
2578 { /* cmd_ListKeys */ 'K', PR_FALSE0, 0, PR_FALSE0 },
2579 { /* cmd_ListCerts */ 'L', PR_FALSE0, 0, PR_FALSE0 },
2580 { /* cmd_ModifyCertTrust */ 'M', PR_FALSE0, 0, PR_FALSE0 },
2581 { /* cmd_NewDBs */ 'N', PR_FALSE0, 0, PR_FALSE0 },
2582 { /* cmd_DumpChain */ 'O', PR_FALSE0, 0, PR_FALSE0 },
2583 { /* cmd_CertReq */ 'R', PR_FALSE0, 0, PR_FALSE0 },
2584 { /* cmd_CreateAndAddCert */ 'S', PR_FALSE0, 0, PR_FALSE0 },
2585 { /* cmd_TokenReset */ 'T', PR_FALSE0, 0, PR_FALSE0 },
2586 { /* cmd_ListModules */ 'U', PR_FALSE0, 0, PR_FALSE0 },
2587 { /* cmd_CheckCertValidity */ 'V', PR_FALSE0, 0, PR_FALSE0 },
2588 { /* cmd_ChangePassword */ 'W', PR_FALSE0, 0, PR_FALSE0 },
2589 { /* cmd_Version */ 'Y', PR_FALSE0, 0, PR_FALSE0 },
2590 { /* cmd_Batch */ 'B', PR_FALSE0, 0, PR_FALSE0 },
2591 { /* cmd_Merge */ 0, PR_FALSE0, 0, PR_FALSE0, "merge" },
2592 { /* cmd_UpgradeMerge */ 0, PR_FALSE0, 0, PR_FALSE0,
2593 "upgrade-merge" },
2594 { /* cmd_Rename */ 0, PR_FALSE0, 0, PR_FALSE0,
2595 "rename" },
2596 { /* cmd_BuildFlags */ 0, PR_FALSE0, 0, PR_FALSE0,
2597 "build-flags" }
2598};
2599#define NUM_COMMANDS((sizeof commands_init) / (sizeof commands_init[0])) ((sizeof commands_init) / (sizeof commands_init[0]))
2600
2601static const secuCommandFlag options_init[] = {
2602 { /* opt_SSOPass */ '0', PR_TRUE1, 0, PR_FALSE0 },
2603 { /* opt_AddKeyUsageExt */ '1', PR_FALSE0, 0, PR_FALSE0 },
2604 { /* opt_AddBasicConstraintExt*/ '2', PR_FALSE0, 0, PR_FALSE0 },
2605 { /* opt_AddAuthorityKeyIDExt*/ '3', PR_FALSE0, 0, PR_FALSE0 },
2606 { /* opt_AddCRLDistPtsExt */ '4', PR_FALSE0, 0, PR_FALSE0 },
2607 { /* opt_AddNSCertTypeExt */ '5', PR_FALSE0, 0, PR_FALSE0 },
2608 { /* opt_AddExtKeyUsageExt */ '6', PR_FALSE0, 0, PR_FALSE0 },
2609 { /* opt_ExtendedEmailAddrs */ '7', PR_TRUE1, 0, PR_FALSE0 },
2610 { /* opt_ExtendedDNSNames */ '8', PR_TRUE1, 0, PR_FALSE0 },
2611 { /* opt_ASCIIForIO */ 'a', PR_FALSE0, 0, PR_FALSE0 },
2612 { /* opt_ValidityTime */ 'b', PR_TRUE1, 0, PR_FALSE0 },
2613 { /* opt_IssuerName */ 'c', PR_TRUE1, 0, PR_FALSE0 },
2614 { /* opt_CertDir */ 'd', PR_TRUE1, 0, PR_FALSE0 },
2615 { /* opt_VerifySig */ 'e', PR_FALSE0, 0, PR_FALSE0 },
2616 { /* opt_PasswordFile */ 'f', PR_TRUE1, 0, PR_FALSE0 },
2617 { /* opt_KeySize */ 'g', PR_TRUE1, 0, PR_FALSE0 },
2618 { /* opt_TokenName */ 'h', PR_TRUE1, 0, PR_FALSE0 },
2619 { /* opt_InputFile */ 'i', PR_TRUE1, 0, PR_FALSE0 },
2620 { /* opt_Emailaddress */ 0, PR_TRUE1, 0, PR_FALSE0, "email" },
2621 { /* opt_KeyIndex */ 'j', PR_TRUE1, 0, PR_FALSE0 },
2622 { /* opt_KeyType */ 'k', PR_TRUE1, 0, PR_FALSE0 },
2623 { /* opt_DetailedInfo */ 'l', PR_FALSE0, 0, PR_FALSE0 },
2624 { /* opt_SerialNumber */ 'm', PR_TRUE1, 0, PR_FALSE0 },
2625 { /* opt_Nickname */ 'n', PR_TRUE1, 0, PR_FALSE0 },
2626 { /* opt_OutputFile */ 'o', PR_TRUE1, 0, PR_FALSE0 },
2627 { /* opt_PhoneNumber */ 'p', PR_TRUE1, 0, PR_FALSE0 },
2628 { /* opt_DBPrefix */ 'P', PR_TRUE1, 0, PR_FALSE0 },
2629 { /* opt_PQGFile */ 'q', PR_TRUE1, 0, PR_FALSE0 },
2630 { /* opt_BinaryDER */ 'r', PR_FALSE0, 0, PR_FALSE0 },
2631 { /* opt_Subject */ 's', PR_TRUE1, 0, PR_FALSE0 },
2632 { /* opt_Trust */ 't', PR_TRUE1, 0, PR_FALSE0 },
2633 { /* opt_Usage */ 'u', PR_TRUE1, 0, PR_FALSE0 },
2634 { /* opt_Validity */ 'v', PR_TRUE1, 0, PR_FALSE0 },
2635 { /* opt_OffsetMonths */ 'w', PR_TRUE1, 0, PR_FALSE0 },
2636 { /* opt_SelfSign */ 'x', PR_FALSE0, 0, PR_FALSE0 },
2637 { /* opt_RW */ 'X', PR_FALSE0, 0, PR_FALSE0 },
2638 { /* opt_Exponent */ 'y', PR_TRUE1, 0, PR_FALSE0 },
2639 { /* opt_NoiseFile */ 'z', PR_TRUE1, 0, PR_FALSE0 },
2640 { /* opt_Hash */ 'Z', PR_TRUE1, 0, PR_FALSE0 },
2641 { /* opt_NewPasswordFile */ '@', PR_TRUE1, 0, PR_FALSE0 },
2642 { /* opt_AddAuthInfoAccExt */ 0, PR_FALSE0, 0, PR_FALSE0, "extAIA" },
2643 { /* opt_AddSubjInfoAccExt */ 0, PR_FALSE0, 0, PR_FALSE0, "extSIA" },
2644 { /* opt_AddCertPoliciesExt */ 0, PR_FALSE0, 0, PR_FALSE0, "extCP" },
2645 { /* opt_AddPolicyMapExt */ 0, PR_FALSE0, 0, PR_FALSE0, "extPM" },
2646 { /* opt_AddPolicyConstrExt */ 0, PR_FALSE0, 0, PR_FALSE0, "extPC" },
2647 { /* opt_AddInhibAnyExt */ 0, PR_FALSE0, 0, PR_FALSE0, "extIA" },
2648 { /* opt_AddNameConstraintsExt*/ 0, PR_FALSE0, 0, PR_FALSE0, "extNC" },
2649 { /* opt_AddSubjectKeyIDExt */ 0, PR_FALSE0, 0, PR_FALSE0,
2650 "extSKID" },
2651 { /* opt_AddCmdKeyUsageExt */ 0, PR_TRUE1, 0, PR_FALSE0,
2652 "keyUsage" },
2653 { /* opt_AddCmdNSCertTypeExt */ 0, PR_TRUE1, 0, PR_FALSE0,
2654 "nsCertType" },
2655 { /* opt_AddCmdExtKeyUsageExt*/ 0, PR_TRUE1, 0, PR_FALSE0,
2656 "extKeyUsage" },
2657
2658 { /* opt_SourceDir */ 0, PR_TRUE1, 0, PR_FALSE0,
2659 "source-dir" },
2660 { /* opt_SourcePrefix */ 0, PR_TRUE1, 0, PR_FALSE0,
2661 "source-prefix" },
2662 { /* opt_UpgradeID */ 0, PR_TRUE1, 0, PR_FALSE0,
2663 "upgrade-id" },
2664 { /* opt_UpgradeTokenName */ 0, PR_TRUE1, 0, PR_FALSE0,
2665 "upgrade-token-name" },
2666 { /* opt_KeyOpFlagsOn */ 0, PR_TRUE1, 0, PR_FALSE0,
2667 "keyOpFlagsOn" },
2668 { /* opt_KeyOpFlagsOff */ 0, PR_TRUE1, 0, PR_FALSE0,
2669 "keyOpFlagsOff" },
2670 { /* opt_KeyAttrFlags */ 0, PR_TRUE1, 0, PR_FALSE0,
2671 "keyAttrFlags" },
2672 { /* opt_EmptyPassword */ 0, PR_FALSE0, 0, PR_FALSE0,
2673 "empty-password" },
2674 { /* opt_CertVersion */ 0, PR_TRUE1, 0, PR_FALSE0,
2675 "certVersion" },
2676 { /* opt_AddSubjectAltExt */ 0, PR_TRUE1, 0, PR_FALSE0, "extSAN" },
2677 { /* opt_DumpExtensionValue */ 0, PR_TRUE1, 0, PR_FALSE0,
2678 "dump-ext-val" },
2679 { /* opt_GenericExtensions */ 0, PR_TRUE1, 0, PR_FALSE0,
2680 "extGeneric" },
2681 { /* opt_NewNickname */ 0, PR_TRUE1, 0, PR_FALSE0,
2682 "new-n" },
2683 { /* opt_Pss */ 0, PR_FALSE0, 0, PR_FALSE0,
2684 "pss" },
2685 { /* opt_PssSign */ 0, PR_FALSE0, 0, PR_FALSE0,
2686 "pss-sign" },
2687 { /* opt_SimpleSelfSigned */ 0, PR_FALSE0, 0, PR_FALSE0,
2688 "simple-self-signed" },
2689};
2690#define NUM_OPTIONS((sizeof options_init) / (sizeof options_init[0])) ((sizeof options_init) / (sizeof options_init[0]))
2691
2692static secuCommandFlag certutil_commands[NUM_COMMANDS((sizeof commands_init) / (sizeof commands_init[0]))];
2693static secuCommandFlag certutil_options[NUM_OPTIONS((sizeof options_init) / (sizeof options_init[0]))];
2694
2695static const secuCommand certutil = {
2696 NUM_COMMANDS((sizeof commands_init) / (sizeof commands_init[0])),
2697 NUM_OPTIONS((sizeof options_init) / (sizeof options_init[0])),
2698 certutil_commands,
2699 certutil_options
2700};
2701
2702static certutilExtnList certutil_extns;
2703
2704static int
2705certutil_main(int argc, char **argv, PRBool initialize)
2706{
2707 CERTCertDBHandle *certHandle;
2708 PK11SlotInfo *slot = NULL((void*)0);
2709 CERTName *subject = 0;
2710 PRFileDesc *inFile = PR_STDINPR_GetSpecialFD(PR_StandardInput);
2711 PRFileDesc *outFile = PR_STDOUTPR_GetSpecialFD(PR_StandardOutput);
2712 SECItem certReqDER = { siBuffer, NULL((void*)0), 0 };
2713 SECItem certDER = { siBuffer, NULL((void*)0), 0 };
2714 const char *slotname = "internal";
2715 const char *certPrefix = "";
2716 char *sourceDir = "";
2717 const char *srcCertPrefix = "";
2718 char *upgradeID = "";
2719 char *upgradeTokenName = "";
2720 KeyType keytype = rsaKey;
2721 char *name = NULL((void*)0);
2722 char *newName = NULL((void*)0);
2723 char *email = NULL((void*)0);
2724 char *keysource = NULL((void*)0);
2725 SECOidTag hashAlgTag = SEC_OID_UNKNOWN;
2726 int keysize = DEFAULT_KEY_BITS2048;
2727 int publicExponent = 0x010001;
2728 int certVersion = SEC_CERTIFICATE_VERSION_32;
2729 unsigned int serialNumber = 0;
2730 int warpmonths = 0;
2731 int validityMonths = 3;
2732 int commandsEntered = 0;
2733 char commandToRun = '\0';
2734 secuPWData pwdata = { PW_NONE, 0 };
2735 secuPWData pwdata2 = { PW_NONE, 0 };
2736 PRBool readOnly = PR_FALSE0;
2737 PRBool initialized = PR_FALSE0;
2738 CK_FLAGS keyOpFlagsOn = 0;
2739 CK_FLAGS keyOpFlagsOff = 0;
2740 PK11AttrFlags keyAttrFlags =
2741 PK11_ATTR_TOKEN0x00000001L | PK11_ATTR_SENSITIVE0x00000040L | PK11_ATTR_PRIVATE0x00000004L;
2742
2743 SECKEYPrivateKey *privkey = NULL((void*)0);
2744 SECKEYPublicKey *pubkey = NULL((void*)0);
2745
2746 int i;
2747 SECStatus rv;
2748
2749 progName = PORT_Strrchrstrrchr(argv[0], '/');
2750 progName = progName ? progName + 1 : argv[0];
2751 memcpy(certutil_commands, commands_init, sizeof commands_init);
2752 memcpy(certutil_options, options_init, sizeof options_init);
2753
2754 rv = SECU_ParseCommandLine(argc, argv, progName, &certutil);
2755
2756 if (rv != SECSuccess)
2757 Usage();
2758
2759 if (certutil.commands[cmd_PrintSyntax].activated) {
2760 PrintSyntax();
2761 }
2762
2763 if (certutil.commands[cmd_PrintHelp].activated) {
2764 char buf[2];
2765 const char *command = NULL((void*)0);
2766 for (i = 0; i < max_cmd; i++) {
2767 if (i == cmd_PrintHelp)
2768 continue;
2769 if (certutil.commands[i].activated) {
2770 if (certutil.commands[i].flag) {
2771 buf[0] = certutil.commands[i].flag;
2772 buf[1] = 0;
2773 command = buf;
2774 } else {
2775 command = certutil.commands[i].longform;
2776 }
2777 break;
2778 }
2779 }
2780 LongUsage((command ? usage_selected : usage_all), command);
2781 exit(1);
2782 }
2783
2784 if (certutil.commands[cmd_BuildFlags].activated) {
2785 PrintBuildFlags();
2786 }
2787
2788 if (certutil.options[opt_PasswordFile].arg) {
2789 pwdata.source = PW_FROMFILE;
2790 pwdata.data = certutil.options[opt_PasswordFile].arg;
2791 }
2792 if (certutil.options[opt_NewPasswordFile].arg) {
2793 pwdata2.source = PW_FROMFILE;
2794 pwdata2.data = certutil.options[opt_NewPasswordFile].arg;
2795 }
2796
2797 if (certutil.options[opt_CertDir].activated)
2798 SECU_ConfigDirectory(certutil.options[opt_CertDir].arg);
2799
2800 if (certutil.options[opt_SourceDir].activated)
2801 sourceDir = certutil.options[opt_SourceDir].arg;
2802
2803 if (certutil.options[opt_UpgradeID].activated)
2804 upgradeID = certutil.options[opt_UpgradeID].arg;
2805
2806 if (certutil.options[opt_UpgradeTokenName].activated)
2807 upgradeTokenName = certutil.options[opt_UpgradeTokenName].arg;
2808
2809 /* must be before opt_KeySize! */
2810 /* -k key type */
2811 if (certutil.options[opt_KeyType].activated) {
2812 char *arg = certutil.options[opt_KeyType].arg;
2813 if (PL_strcmp(arg, "rsa") == 0) {
2814 keytype = rsaKey;
2815 } else if (PL_strcmp(arg, "dsa") == 0) {
2816 keytype = dsaKey;
2817 } else if (PL_strcmp(arg, "ec") == 0) {
2818 keytype = ecKey;
2819 } else if (PL_strcmp(arg, "ed") == 0) {
2820 keytype = edKey;
2821 } else if (PL_strcmp(arg, "mldsa") == 0) {
2822 keytype = mldsaKey;
2823 } else if (PL_strcmp(arg, "all") == 0) {
2824 keytype = nullKey;
2825 } else {
2826 /* use an existing private/public key pair */
2827 keysource = arg;
2828 }
2829 } else if (certutil.commands[cmd_ListKeys].activated) {
2830 keytype = nullKey;
2831 }
2832
2833 if (certutil.options[opt_KeySize].activated) {
2834 keysize = PORT_Atoi(certutil.options[opt_KeySize].arg)(int)strtol(certutil.options[opt_KeySize].arg, ((void*)0), 10
)
;
2835 /* mldsa limits are much different that rsa and dsa, don't
2836 * do the check here */
2837 if ((keytype != mldsaKey) &&
2838 ((keysize < MIN_KEY_BITS512) || (keysize > MAX_KEY_BITS8192))) {
2839 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
2840 "%s -g: Keysize must be between %d and %d.\n",
2841 progName, MIN_KEY_BITS512, MAX_KEY_BITS8192);
2842 return 255;
2843 }
2844 if (keytype == ecKey) {
2845 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s -g: Not for ec keys.\n", progName);
2846 return 255;
2847 }
2848 }
2849
2850 /* -h specify token name */
2851 if (certutil.options[opt_TokenName].activated) {
2852 if (PL_strcmp(certutil.options[opt_TokenName].arg, "all") == 0)
2853 slotname = NULL((void*)0);
2854 else
2855 slotname = certutil.options[opt_TokenName].arg;
2856 }
2857
2858 /* -Z hash type */
2859 if (certutil.options[opt_Hash].activated) {
2860 char *arg = certutil.options[opt_Hash].arg;
2861 hashAlgTag = SECU_StringToSignatureAlgTag(arg);
2862 if (hashAlgTag == SEC_OID_UNKNOWN) {
2863 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s -Z: %s is not a recognized type.\n",
2864 progName, arg);
2865 return 255;
2866 }
2867 }
2868
2869 if (certutil.options[opt_KeyOpFlagsOn].activated) {
2870 keyOpFlagsOn = GetOpFlags(certutil.options[opt_KeyOpFlagsOn].arg);
2871 }
2872 if (certutil.options[opt_KeyOpFlagsOff].activated) {
2873 keyOpFlagsOff = GetOpFlags(certutil.options[opt_KeyOpFlagsOff].arg);
2874 keyOpFlagsOn &= ~keyOpFlagsOff; /* make off override on */
2875 }
2876 if (certutil.options[opt_KeyAttrFlags].activated) {
2877 keyAttrFlags = GetAttrFlags(certutil.options[opt_KeyAttrFlags].arg);
2878 }
2879
2880 /* -m serial number */
2881 if (certutil.options[opt_SerialNumber].activated) {
2882 int sn = PORT_Atoi(certutil.options[opt_SerialNumber].arg)(int)strtol(certutil.options[opt_SerialNumber].arg, ((void*)0
), 10)
;
2883 if (sn < 0) {
2884 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s -m: %s is not a valid serial number.\n",
2885 progName, certutil.options[opt_SerialNumber].arg);
2886 return 255;
2887 }
2888 serialNumber = sn;
2889 }
2890
2891 /* -P certdb name prefix */
2892 if (certutil.options[opt_DBPrefix].activated) {
2893 if (certutil.options[opt_DBPrefix].arg) {
2894 certPrefix = certutil.options[opt_DBPrefix].arg;
2895 } else {
2896 Usage();
2897 }
2898 }
2899
2900 /* --source-prefix certdb name prefix */
2901 if (certutil.options[opt_SourcePrefix].activated) {
2902 if (certutil.options[opt_SourcePrefix].arg) {
2903 srcCertPrefix = certutil.options[opt_SourcePrefix].arg;
2904 } else {
2905 Usage();
2906 }
2907 }
2908
2909 /* -q PQG file or curve name */
2910 if (certutil.options[opt_PQGFile].activated) {
2911 if ((keytype != dsaKey) && (keytype != ecKey) && (keytype != edKey) &&
2912 (keytype != mldsaKey)) {
2913 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s -q: specifies a PQG file for DSA keys"
2914 " (-k dsa)\n"
2915 " or a named curve for EC and ED keys (-k ec, ed)\n"
2916 " or a parameter set for ML-DSA keys (-k mldsa)\n",
2917 progName);
2918 return 255;
2919 }
2920 }
2921
2922 /* -s subject name */
2923 if (certutil.options[opt_Subject].activated) {
2924 subject = CERT_AsciiToName(certutil.options[opt_Subject].arg);
2925 if (!subject) {
2926 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s -s: improperly formatted name: \"%s\"\n",
2927 progName, certutil.options[opt_Subject].arg);
2928 return 255;
2929 }
2930 }
2931
2932 /* -v validity period */
2933 if (certutil.options[opt_Validity].activated) {
2934 validityMonths = PORT_Atoi(certutil.options[opt_Validity].arg)(int)strtol(certutil.options[opt_Validity].arg, ((void*)0), 10
)
;
2935 if (validityMonths < 0) {
2936 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s -v: incorrect validity period: \"%s\"\n",
2937 progName, certutil.options[opt_Validity].arg);
2938 return 255;
2939 }
2940 }
2941
2942 /* -w warp months */
2943 if (certutil.options[opt_OffsetMonths].activated)
2944 warpmonths = PORT_Atoi(certutil.options[opt_OffsetMonths].arg)(int)strtol(certutil.options[opt_OffsetMonths].arg, ((void*)0
), 10)
;
2945
2946 /* -y public exponent (for RSA) */
2947 if (certutil.options[opt_Exponent].activated) {
2948 publicExponent = PORT_Atoi(certutil.options[opt_Exponent].arg)(int)strtol(certutil.options[opt_Exponent].arg, ((void*)0), 10
)
;
2949 if ((publicExponent != 3) &&
2950 (publicExponent != 17) &&
2951 (publicExponent != 65537)) {
2952 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s -y: incorrect public exponent %d.",
2953 progName, publicExponent);
2954 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "Must be 3, 17, or 65537.\n");
2955 return 255;
2956 }
2957 }
2958
2959 /* --certVersion */
2960 if (certutil.options[opt_CertVersion].activated) {
2961 certVersion = PORT_Atoi(certutil.options[opt_CertVersion].arg)(int)strtol(certutil.options[opt_CertVersion].arg, ((void*)0)
, 10)
;
2962 if (certVersion < 1 || certVersion > 4) {
2963 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s -certVersion: incorrect certificate version %d.",
2964 progName, certVersion);
2965 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "Must be 1, 2, 3 or 4.\n");
2966 return 255;
2967 }
2968 certVersion = certVersion - 1;
2969 }
2970
2971 /* Check number of commands entered. */
2972 commandsEntered = 0;
2973 for (i = 0; i < certutil.numCommands; i++) {
2974 if (certutil.commands[i].activated) {
2975 commandToRun = certutil.commands[i].flag;
2976 commandsEntered++;
2977 }
2978 if (commandsEntered > 1)
2979 break;
2980 }
2981 if (commandsEntered > 1) {
2982 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s: only one command at a time!\n", progName);
2983 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "You entered: ");
2984 for (i = 0; i < certutil.numCommands; i++) {
2985 if (certutil.commands[i].activated)
2986 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), " -%c", certutil.commands[i].flag);
2987 }
2988 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "\n");
2989 return 255;
2990 }
2991 if (commandsEntered == 0) {
2992 Usage();
2993 }
2994
2995 if (certutil.commands[cmd_ListCerts].activated ||
2996 certutil.commands[cmd_PrintHelp].activated ||
2997 certutil.commands[cmd_ListKeys].activated ||
2998 certutil.commands[cmd_ListModules].activated ||
2999 certutil.commands[cmd_CheckCertValidity].activated ||
3000 certutil.commands[cmd_Version].activated) {
3001 readOnly = !certutil.options[opt_RW].activated;
3002 }
3003
3004 /* -A, -D, -M, -S, -V, and all require -n */
3005 if ((certutil.commands[cmd_AddCert].activated ||
3006 certutil.commands[cmd_DeleteCert].activated ||
3007 certutil.commands[cmd_DumpChain].activated ||
3008 certutil.commands[cmd_ModifyCertTrust].activated ||
3009 certutil.commands[cmd_CreateAndAddCert].activated ||
3010 certutil.commands[cmd_CheckCertValidity].activated) &&
3011 !certutil.options[opt_Nickname].activated) {
3012 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3013 "%s -%c: nickname is required for this command (-n).\n",
3014 progName, commandToRun);
3015 return 255;
3016 }
3017
3018 /* -A, -E, -M, -S require trust */
3019 if ((certutil.commands[cmd_AddCert].activated ||
3020 certutil.commands[cmd_AddEmailCert].activated ||
3021 certutil.commands[cmd_ModifyCertTrust].activated ||
3022 certutil.commands[cmd_CreateAndAddCert].activated) &&
3023 !certutil.options[opt_Trust].activated) {
3024 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3025 "%s -%c: trust is required for this command (-t).\n",
3026 progName, commandToRun);
3027 return 255;
3028 }
3029
3030 /* if -L is given raw, ascii or dump mode, it must be for only one cert. */
3031 if (certutil.commands[cmd_ListCerts].activated &&
3032 (certutil.options[opt_ASCIIForIO].activated ||
3033 certutil.options[opt_DumpExtensionValue].activated ||
3034 certutil.options[opt_BinaryDER].activated) &&
3035 !certutil.options[opt_Nickname].activated) {
3036 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3037 "%s: nickname is required to dump cert in raw or ascii mode.\n",
3038 progName);
3039 return 255;
3040 }
3041
3042 /* -L can only be in (raw || ascii). */
3043 if (certutil.commands[cmd_ListCerts].activated &&
3044 certutil.options[opt_ASCIIForIO].activated &&
3045 certutil.options[opt_BinaryDER].activated) {
3046 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3047 "%s: cannot specify both -r and -a when dumping cert.\n",
3048 progName);
3049 return 255;
3050 }
3051
3052 /* If making a cert request, need a subject. */
3053 if ((certutil.commands[cmd_CertReq].activated ||
3054 certutil.commands[cmd_CreateAndAddCert].activated) &&
3055 !(certutil.options[opt_Subject].activated || keysource)) {
3056 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3057 "%s -%c: subject is required to create a cert request.\n",
3058 progName, commandToRun);
3059 return 255;
3060 }
3061
3062 /* If making a cert, need a serial number. */
3063 if ((certutil.commands[cmd_CreateNewCert].activated ||
3064 certutil.commands[cmd_CreateAndAddCert].activated) &&
3065 !certutil.options[opt_SerialNumber].activated) {
3066 /* Make a default serial number from the current time. */
3067 PRTime now = PR_Now();
3068 LL_USHR(now, now, 19)((now) = (PRUint64)(now) >> (19));
3069 LL_L2UI(serialNumber, now)((serialNumber) = (PRUint32)(now));
3070 }
3071
3072 /* Validation needs the usage to validate for. */
3073 if (certutil.commands[cmd_CheckCertValidity].activated &&
3074 !certutil.options[opt_Usage].activated) {
3075 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3076 "%s -V: specify a usage to validate the cert for (-u).\n",
3077 progName);
3078 return 255;
3079 }
3080
3081 /* Rename needs an old and a new nickname */
3082 if (certutil.commands[cmd_Rename].activated &&
3083 !(certutil.options[opt_Nickname].activated &&
3084 certutil.options[opt_NewNickname].activated)) {
3085
3086 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3087 "%s --rename: specify an old nickname (-n) and\n"
3088 " a new nickname (--new-n).\n",
3089 progName);
3090 return 255;
3091 }
3092
3093 /* Delete needs a nickname or a key ID */
3094 if (certutil.commands[cmd_DeleteKey].activated &&
3095 !(certutil.options[opt_Nickname].activated || keysource)) {
3096 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3097 "%s -%c: specify a nickname (-n) or\n"
3098 " a key ID (-k).\n",
3099 progName, commandToRun);
3100 return 255;
3101 }
3102
3103 /* Upgrade/Merge needs a source database and a upgrade id. */
3104 if (certutil.commands[cmd_UpgradeMerge].activated &&
3105 !(certutil.options[opt_SourceDir].activated &&
3106 certutil.options[opt_UpgradeID].activated)) {
3107
3108 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3109 "%s --upgrade-merge: specify an upgrade database directory "
3110 "(--source-dir) and\n"
3111 " an upgrade ID (--upgrade-id).\n",
3112 progName);
3113 return 255;
3114 }
3115
3116 /* Merge needs a source database */
3117 if (certutil.commands[cmd_Merge].activated &&
3118 !certutil.options[opt_SourceDir].activated) {
3119
3120 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3121 "%s --merge: specify an source database directory "
3122 "(--source-dir)\n",
3123 progName);
3124 return 255;
3125 }
3126
3127 /* To make a cert, need either a issuer or to self-sign it. */
3128 if (certutil.commands[cmd_CreateAndAddCert].activated &&
3129 !(certutil.options[opt_IssuerName].activated ||
3130 certutil.options[opt_SelfSign].activated)) {
3131 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3132 "%s -S: must specify issuer (-c) or self-sign (-x).\n",
3133 progName);
3134 return 255;
3135 }
3136
3137 /* Using slotname == NULL for listing keys and certs on all slots,
3138 * but only that. */
3139 if (!(certutil.commands[cmd_ListKeys].activated ||
3140 certutil.commands[cmd_DumpChain].activated ||
3141 certutil.commands[cmd_ListCerts].activated) &&
3142 slotname == NULL((void*)0)) {
3143 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3144 "%s -%c: cannot use \"-h all\" for this command.\n",
3145 progName, commandToRun);
3146 return 255;
3147 }
3148
3149 /* Using keytype == nullKey for list all key types, but only that. */
3150 if (!certutil.commands[cmd_ListKeys].activated && keytype == nullKey) {
3151 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3152 "%s -%c: cannot use \"-k all\" for this command.\n",
3153 progName, commandToRun);
3154 return 255;
3155 }
3156
3157 /* Open the input file. */
3158 if (certutil.options[opt_InputFile].activated) {
3159 inFile = PR_Open(certutil.options[opt_InputFile].arg, PR_RDONLY0x01, 0);
3160 if (!inFile) {
3161 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3162 "%s: unable to open \"%s\" for reading (%ld, %ld).\n",
3163 progName, certutil.options[opt_InputFile].arg,
3164 PR_GetError(), PR_GetOSError());
3165 return 255;
3166 }
3167 }
3168
3169 /* Open the output file. */
3170 if (certutil.options[opt_OutputFile].activated) {
3171 outFile = PR_Open(certutil.options[opt_OutputFile].arg,
3172 PR_CREATE_FILE0x08 | PR_RDWR0x04 | PR_TRUNCATE0x20, 00660);
3173 if (!outFile) {
3174 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3175 "%s: unable to open \"%s\" for writing (%ld, %ld).\n",
3176 progName, certutil.options[opt_OutputFile].arg,
3177 PR_GetError(), PR_GetOSError());
3178 return 255;
3179 }
3180 }
3181
3182 name = SECU_GetOptionArg(&certutil, opt_Nickname);
3183 newName = SECU_GetOptionArg(&certutil, opt_NewNickname);
3184 email = SECU_GetOptionArg(&certutil, opt_Emailaddress);
3185
3186 PK11_SetPasswordFunc(SECU_GetModulePassword);
3187
3188 if (PR_TRUE1 == initialize) {
3189 /* Initialize NSPR and NSS. */
3190 PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
3191 if (!certutil.commands[cmd_UpgradeMerge].activated) {
3192 rv = NSS_Initialize(SECU_ConfigDirectory(NULL((void*)0)),
3193 certPrefix, certPrefix,
3194 "secmod.db", readOnly ? NSS_INIT_READONLY0x1 : 0);
3195 } else {
3196 rv = NSS_InitWithMerge(SECU_ConfigDirectory(NULL((void*)0)),
3197 certPrefix, certPrefix, "secmod.db",
3198 sourceDir, srcCertPrefix, srcCertPrefix,
3199 upgradeID, upgradeTokenName,
3200 readOnly ? NSS_INIT_READONLY0x1 : 0);
3201 }
3202 if (rv != SECSuccess) {
3203 SECU_PrintPRandOSError(progName);
3204 rv = SECFailure;
3205 goto shutdown;
3206 }
3207 initialized = PR_TRUE1;
3208 SECU_RegisterDynamicOids();
3209 /* Ensure the SSL error code table has been registered. Bug 1460284. */
3210 SSL_OptionSetDefault(-1, 0);
3211 }
3212 certHandle = CERT_GetDefaultCertDB();
3213
3214 if (certutil.commands[cmd_Version].activated) {
3215 printf("Certificate database content version: command not implemented.\n");
3216 }
3217
3218 if (PL_strcmp(slotname, "internal") == 0)
3219 slot = PK11_GetInternalKeySlot();
3220 else if (slotname != NULL((void*)0))
3221 slot = PK11_FindSlotByName(slotname);
3222
3223 if (!slot && (certutil.commands[cmd_NewDBs].activated ||
3224 certutil.commands[cmd_ModifyCertTrust].activated ||
3225 certutil.commands[cmd_ChangePassword].activated ||
3226 certutil.commands[cmd_TokenReset].activated ||
3227 certutil.commands[cmd_CreateAndAddCert].activated ||
3228 certutil.commands[cmd_AddCert].activated ||
3229 certutil.commands[cmd_Merge].activated ||
3230 certutil.commands[cmd_UpgradeMerge].activated ||
3231 certutil.commands[cmd_AddEmailCert].activated)) {
3232
3233 SECU_PrintError(progName, "could not find the slot %s", slotname);
3234 rv = SECFailure;
3235 goto shutdown;
3236 }
3237
3238 /* If creating new database, initialize the password. */
3239 if (certutil.commands[cmd_NewDBs].activated) {
3240 if (certutil.options[opt_EmptyPassword].activated && (PK11_NeedUserInit(slot))) {
3241 rv = PK11_InitPin(slot, (char *)NULL((void*)0), "");
3242 } else {
3243 rv = SECU_ChangePW2(slot, 0, 0, certutil.options[opt_PasswordFile].arg,
3244 certutil.options[opt_NewPasswordFile].arg);
3245 }
3246 if (rv != SECSuccess) {
3247 SECU_PrintError(progName, "Could not set password for the slot");
3248 goto shutdown;
3249 }
3250 }
3251
3252 /* if we are going to modify the cert database,
3253 * make sure it's initialized */
3254 if (certutil.commands[cmd_ModifyCertTrust].activated ||
3255 certutil.commands[cmd_CreateAndAddCert].activated ||
3256 certutil.commands[cmd_AddCert].activated ||
3257 certutil.commands[cmd_AddEmailCert].activated) {
3258 if (PK11_NeedLogin(slot) && PK11_NeedUserInit(slot)) {
3259 char *password = NULL((void*)0);
3260 /* fetch the password from the command line or the file
3261 * if no password is supplied, initialize the password to NULL */
3262 if (pwdata.source == PW_FROMFILE) {
3263 password = SECU_FilePasswd(slot, PR_FALSE0, pwdata.data);
3264 } else if (pwdata.source == PW_PLAINTEXT) {
3265 password = PL_strdup(pwdata.data);
3266 }
3267 rv = PK11_InitPin(slot, (char *)NULL((void*)0), password ? password : "");
3268 if (password) {
3269 PORT_Memsetmemset(password, 0, PL_strlen(password));
3270 PORT_FreePORT_Free_Util(password);
3271 }
3272 if (rv != SECSuccess) {
3273 SECU_PrintError(progName, "Could not set password for the slot");
3274 goto shutdown;
3275 }
3276 }
3277 }
3278
3279 /* walk through the upgrade merge if necessary.
3280 * This option is more to test what some applications will want to do
3281 * to do an automatic upgrade. The --merge command is more useful for
3282 * the general case where 2 database need to be merged together.
3283 */
3284 if (certutil.commands[cmd_UpgradeMerge].activated) {
3285 if (*upgradeTokenName == 0) {
3286 upgradeTokenName = upgradeID;
3287 }
3288 if (!PK11_IsInternal(slot)) {
3289 fprintf(stderrstderr, "Only internal DB's can be upgraded\n");
3290 rv = SECSuccess;
3291 goto shutdown;
3292 }
3293 if (!PK11_IsRemovable(slot)) {
3294 printf("database already upgraded.\n");
3295 rv = SECSuccess;
3296 goto shutdown;
3297 }
3298 if (!PK11_NeedLogin(slot)) {
3299 printf("upgrade complete!\n");
3300 rv = SECSuccess;
3301 goto shutdown;
3302 }
3303 /* authenticate to the old DB if necessary */
3304 if (PORT_Strcmpstrcmp(PK11_GetTokenName(slot), upgradeTokenName) == 0) {
3305 /* if we need a password, supply it. This will be the password
3306 * for the old database */
3307 rv = PK11_Authenticate(slot, PR_FALSE0, &pwdata2);
3308 if (rv != SECSuccess) {
3309 SECU_PrintError(progName, "Could not get password for %s",
3310 upgradeTokenName);
3311 goto shutdown;
3312 }
3313 /*
3314 * if we succeeded above, but still aren't logged in, that means
3315 * we just supplied the password for the old database. We may
3316 * need the password for the new database. NSS will automatically
3317 * change the token names at this point
3318 */
3319 if (PK11_IsLoggedIn(slot, &pwdata)) {
3320 printf("upgrade complete!\n");
3321 rv = SECSuccess;
3322 goto shutdown;
3323 }
3324 }
3325
3326 /* call PK11_IsPresent to update our cached token information */
3327 if (!PK11_IsPresent(slot)) {
3328 /* this shouldn't happen. We call isPresent to force a token
3329 * info update */
3330 fprintf(stderrstderr, "upgrade/merge internal error\n");
3331 rv = SECFailure;
3332 goto shutdown;
3333 }
3334
3335 /* the token is now set to the state of the source database,
3336 * if we need a password for it, PK11_Authenticate will
3337 * automatically prompt us */
3338 rv = PK11_Authenticate(slot, PR_FALSE0, &pwdata);
3339 if (rv == SECSuccess) {
3340 printf("upgrade complete!\n");
3341 } else {
3342 SECU_PrintError(progName, "Could not get password for %s",
3343 PK11_GetTokenName(slot));
3344 }
3345 goto shutdown;
3346 }
3347
3348 /*
3349 * merge 2 databases.
3350 */
3351 if (certutil.commands[cmd_Merge].activated) {
3352 PK11SlotInfo *sourceSlot = NULL((void*)0);
3353 PK11MergeLog *log;
3354 char *modspec = PR_smprintf(
3355 "configDir='%s' certPrefix='%s' tokenDescription='%s'",
3356 sourceDir, srcCertPrefix,
3357 *upgradeTokenName ? upgradeTokenName : "Source Database");
3358
3359 if (!modspec) {
3360 rv = SECFailure;
3361 goto shutdown;
3362 }
3363
3364 sourceSlot = SECMOD_OpenUserDB(modspec);
3365 PR_smprintf_free(modspec);
3366 if (!sourceSlot) {
3367 SECU_PrintError(progName, "couldn't open source database");
3368 rv = SECFailure;
3369 goto shutdown;
3370 }
3371
3372 rv = PK11_Authenticate(slot, PR_FALSE0, &pwdata);
3373 if (rv != SECSuccess) {
3374 SECU_PrintError(progName, "Couldn't get password for %s",
3375 PK11_GetTokenName(slot));
3376 goto merge_fail;
3377 }
3378
3379 rv = PK11_Authenticate(sourceSlot, PR_FALSE0, &pwdata2);
3380 if (rv != SECSuccess) {
3381 SECU_PrintError(progName, "Couldn't get password for %s",
3382 PK11_GetTokenName(sourceSlot));
3383 goto merge_fail;
3384 }
3385
3386 log = PK11_CreateMergeLog();
3387 if (!log) {
3388 rv = SECFailure;
3389 SECU_PrintError(progName, "couldn't create error log");
3390 goto merge_fail;
3391 }
3392
3393 rv = PK11_MergeTokens(slot, sourceSlot, log, &pwdata, &pwdata2);
3394 if (rv != SECSuccess) {
3395 DumpMergeLog(progName, log);
3396 }
3397 PK11_DestroyMergeLog(log);
3398
3399 merge_fail:
3400 SECMOD_CloseUserDB(sourceSlot);
3401 PK11_FreeSlot(sourceSlot);
3402 goto shutdown;
3403 }
3404
3405 /* The following 8 options are mutually exclusive with all others. */
3406
3407 /* List certs (-L) */
3408 if (certutil.commands[cmd_ListCerts].activated) {
3409 if (certutil.options[opt_DumpExtensionValue].activated) {
3410 const char *oid_str;
3411 SECItem oid_item;
3412 SECStatus srv;
3413 oid_item.data = NULL((void*)0);
3414 oid_item.len = 0;
3415 oid_str = certutil.options[opt_DumpExtensionValue].arg;
3416 srv = GetOidFromString(NULL((void*)0), &oid_item, oid_str, strlen(oid_str));
3417 if (srv != SECSuccess) {
3418 SECU_PrintError(progName, "malformed extension OID %s",
3419 oid_str);
3420 goto shutdown;
3421 }
3422 rv = ListCerts(certHandle, name, email, slot,
3423 PR_TRUE1 /*binary*/, PR_FALSE0 /*ascii*/,
3424 &oid_item,
3425 outFile, &pwdata);
3426 SECITEM_FreeItemSECITEM_FreeItem_Util(&oid_item, PR_FALSE0);
3427 } else {
3428 rv = ListCerts(certHandle, name, email, slot,
3429 certutil.options[opt_BinaryDER].activated,
3430 certutil.options[opt_ASCIIForIO].activated,
3431 NULL((void*)0), outFile, &pwdata);
3432 }
3433 goto shutdown;
3434 }
3435 if (certutil.commands[cmd_DumpChain].activated) {
3436 rv = DumpChain(certHandle, name,
3437 certutil.options[opt_ASCIIForIO].activated,
3438 certutil.options[opt_SimpleSelfSigned].activated);
3439 goto shutdown;
3440 }
3441 /* XXX needs work */
3442 /* List keys (-K) */
3443 if (certutil.commands[cmd_ListKeys].activated) {
3444 rv = ListKeys(slot, name, 0 /*keyindex*/, keytype, PR_FALSE0 /*dopriv*/,
3445 &pwdata);
3446 goto shutdown;
3447 }
3448 /* List modules (-U) */
3449 if (certutil.commands[cmd_ListModules].activated) {
3450 rv = ListModules();
3451 goto shutdown;
3452 }
3453 /* Delete cert (-D) */
3454 if (certutil.commands[cmd_DeleteCert].activated) {
3455 rv = DeleteCert(certHandle, name, &pwdata);
3456 goto shutdown;
3457 }
3458 /* Rename cert (--rename) */
3459 if (certutil.commands[cmd_Rename].activated) {
3460 rv = RenameCert(certHandle, name, newName, &pwdata);
3461 goto shutdown;
3462 }
3463 /* Delete key (-F) */
3464 if (certutil.commands[cmd_DeleteKey].activated) {
3465 if (certutil.options[opt_Nickname].activated) {
3466 rv = DeleteCertAndKey(name, &pwdata);
3467 } else {
3468 privkey = findPrivateKeyByID(slot, keysource, &pwdata);
3469 if (!privkey) {
3470 SECU_PrintError(progName, "%s is not a key-id", keysource);
3471 rv = SECFailure;
3472 } else {
3473 rv = DeleteKey(privkey, &pwdata);
3474 /* already destroyed by PK11_DeleteTokenPrivateKey */
3475 privkey = NULL((void*)0);
3476 }
3477 }
3478 goto shutdown;
3479 }
3480 /* Modify trust attribute for cert (-M) */
3481 if (certutil.commands[cmd_ModifyCertTrust].activated) {
3482 rv = ChangeTrustAttributes(certHandle, slot, name,
3483 certutil.options[opt_Trust].arg, &pwdata);
3484 goto shutdown;
3485 }
3486 /* Change key db password (-W) (future - change pw to slot?) */
3487 if (certutil.commands[cmd_ChangePassword].activated) {
3488 rv = SECU_ChangePW2(slot, 0, 0, certutil.options[opt_PasswordFile].arg,
3489 certutil.options[opt_NewPasswordFile].arg);
3490 if (rv != SECSuccess) {
3491 SECU_PrintError(progName, "Could not set password for the slot");
3492 goto shutdown;
3493 }
3494 }
3495 /* Reset the a token */
3496 if (certutil.commands[cmd_TokenReset].activated) {
3497 char *sso_pass = "";
3498
3499 if (certutil.options[opt_SSOPass].activated) {
3500 sso_pass = certutil.options[opt_SSOPass].arg;
3501 }
3502 rv = PK11_ResetToken(slot, sso_pass);
3503
3504 goto shutdown;
3505 }
3506 /* Check cert validity against current time (-V) */
3507 if (certutil.commands[cmd_CheckCertValidity].activated) {
3508 /* XXX temporary hack for fips - must log in to get priv key */
3509 if (certutil.options[opt_VerifySig].activated) {
3510 if (slot && PK11_NeedLogin(slot)) {
3511 SECStatus newrv = PK11_Authenticate(slot, PR_TRUE1, &pwdata);
3512 if (newrv != SECSuccess) {
3513 SECU_PrintError(progName, "could not authenticate to token %s.",
3514 PK11_GetTokenName(slot));
3515 goto shutdown;
3516 }
3517 }
3518 }
3519 rv = ValidateCert(certHandle, name,
3520 certutil.options[opt_ValidityTime].arg,
3521 certutil.options[opt_Usage].arg,
3522 certutil.options[opt_VerifySig].activated,
3523 certutil.options[opt_DetailedInfo].activated,
3524 certutil.options[opt_ASCIIForIO].activated,
3525 &pwdata);
3526 if (rv != SECSuccess && PR_GetError() == SEC_ERROR_INVALID_ARGS)
3527 SECU_PrintError(progName, "validation failed");
3528 goto shutdown;
3529 }
3530
3531 /*
3532 * Key generation
3533 */
3534
3535 /* These commands may require keygen. */
3536 if (certutil.commands[cmd_CertReq].activated ||
3537 certutil.commands[cmd_CreateAndAddCert].activated ||
3538 certutil.commands[cmd_GenKeyPair].activated) {
3539 if (keysource) {
3540 CERTCertificate *keycert;
3541 keycert = CERT_FindCertByNicknameOrEmailAddr(certHandle, keysource);
3542 if (!keycert) {
3543 keycert = PK11_FindCertFromNickname(keysource, NULL((void*)0));
3544 }
3545
3546 if (keycert) {
3547 privkey = PK11_FindKeyByDERCert(slot, keycert, &pwdata);
3548 } else {
3549 /* Interpret keysource as CKA_ID */
3550 privkey = findPrivateKeyByID(slot, keysource, &pwdata);
3551 }
3552
3553 if (!privkey) {
3554 SECU_PrintError(
3555 progName,
3556 "%s is neither a key-type nor a nickname nor a key-id", keysource);
3557 return SECFailure;
3558 }
3559
3560 pubkey = SECKEY_ConvertToPublicKey(privkey);
3561 if (!pubkey) {
3562 SECU_PrintError(progName,
3563 "Could not get keys from cert %s", keysource);
3564 if (keycert) {
3565 CERT_DestroyCertificate(keycert);
3566 }
3567 rv = SECFailure;
3568 goto shutdown;
3569 }
3570 keytype = privkey->keyType;
3571
3572 /* On CertReq for renewal if no subject has been
3573 * specified obtain it from the certificate.
3574 */
3575 if (certutil.commands[cmd_CertReq].activated && !subject) {
3576 if (keycert) {
3577 subject = CERT_AsciiToName(keycert->subjectName);
3578 if (!subject) {
3579 SECU_PrintError(
3580 progName,
3581 "Could not get subject from certificate %s",
3582 keysource);
3583 CERT_DestroyCertificate(keycert);
3584 rv = SECFailure;
3585 goto shutdown;
3586 }
3587 } else {
3588 SECU_PrintError(progName, "Subject name not provided");
3589 rv = SECFailure;
3590 goto shutdown;
3591 }
3592 }
3593 if (keycert) {
3594 CERT_DestroyCertificate(keycert);
3595 }
3596 } else {
3597 privkey =
3598 CERTUTIL_GeneratePrivateKey(keytype, slot, keysize,
3599 publicExponent,
3600 certutil.options[opt_NoiseFile].arg,
3601 &pubkey,
3602 certutil.options[opt_PQGFile].arg,
3603 keyAttrFlags,
3604 keyOpFlagsOn,
3605 keyOpFlagsOff,
3606 &pwdata);
3607 if (privkey == NULL((void*)0)) {
3608 SECU_PrintError(progName, "unable to generate key(s)\n");
3609 rv = SECFailure;
3610 goto shutdown;
3611 }
3612 }
3613 privkey->wincx = &pwdata;
3614 PORT_Assert(pubkey != NULL)((pubkey != ((void*)0)) ? ((void)0) : PR_Assert("pubkey != NULL"
, "/root/firefox-clang/security/nss/cmd/certutil/certutil.c",
3614))
;
3615
3616 /* If all that was needed was keygen, exit. */
3617 if (certutil.commands[cmd_GenKeyPair].activated) {
3618 rv = SECSuccess;
3619 goto shutdown;
3620 }
3621 }
3622
3623 if (certutil.options[opt_Pss].activated) {
3624 if (!certutil.commands[cmd_CertReq].activated &&
3625 !certutil.commands[cmd_CreateAndAddCert].activated) {
3626 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3627 "%s -%c: --pss only works with -R or -S.\n",
3628 progName, commandToRun);
3629 return 255;
3630 }
3631 if (keytype != rsaKey) {
3632 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3633 "%s -%c: --pss only works with RSA keys.\n",
3634 progName, commandToRun);
3635 return 255;
3636 }
3637 }
3638
3639 /* --pss-sign is to sign a certificate with RSA-PSS, even if the
3640 * issuer's key is an RSA key. If the key is an RSA-PSS key, the
3641 * generated signature is always RSA-PSS. */
3642 if (certutil.options[opt_PssSign].activated) {
3643 if (!certutil.commands[cmd_CreateNewCert].activated &&
3644 !certutil.commands[cmd_CreateAndAddCert].activated) {
3645 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3646 "%s -%c: --pss-sign only works with -C or -S.\n",
3647 progName, commandToRun);
3648 return 255;
3649 }
3650 if (keytype != rsaKey) {
3651 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3652 "%s -%c: --pss-sign only works with RSA keys.\n",
3653 progName, commandToRun);
3654 return 255;
3655 }
3656 }
3657
3658 if (certutil.options[opt_SimpleSelfSigned].activated &&
3659 !certutil.commands[cmd_DumpChain].activated) {
3660 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3661 "%s -%c: --simple-self-signed only works with -O.\n",
3662 progName, commandToRun);
3663 return 255;
3664 }
3665
3666 /* If we need a list of extensions convert the flags into list format */
3667 if (certutil.commands[cmd_CertReq].activated ||
3668 certutil.commands[cmd_CreateAndAddCert].activated ||
3669 certutil.commands[cmd_CreateNewCert].activated) {
3670 certutil_extns[ext_keyUsage].activated =
3671 certutil.options[opt_AddCmdKeyUsageExt].activated;
3672 if (!certutil_extns[ext_keyUsage].activated) {
3673 certutil_extns[ext_keyUsage].activated =
3674 certutil.options[opt_AddKeyUsageExt].activated;
3675 } else {
3676 certutil_extns[ext_keyUsage].arg =
3677 certutil.options[opt_AddCmdKeyUsageExt].arg;
3678 }
3679 certutil_extns[ext_basicConstraint].activated =
3680 certutil.options[opt_AddBasicConstraintExt].activated;
3681 certutil_extns[ext_nameConstraints].activated =
3682 certutil.options[opt_AddNameConstraintsExt].activated;
3683 certutil_extns[ext_authorityKeyID].activated =
3684 certutil.options[opt_AddAuthorityKeyIDExt].activated;
3685 certutil_extns[ext_subjectKeyID].activated =
3686 certutil.options[opt_AddSubjectKeyIDExt].activated;
3687 certutil_extns[ext_CRLDistPts].activated =
3688 certutil.options[opt_AddCRLDistPtsExt].activated;
3689 certutil_extns[ext_NSCertType].activated =
3690 certutil.options[opt_AddCmdNSCertTypeExt].activated;
3691 if (!certutil_extns[ext_NSCertType].activated) {
3692 certutil_extns[ext_NSCertType].activated =
3693 certutil.options[opt_AddNSCertTypeExt].activated;
3694 } else {
3695 certutil_extns[ext_NSCertType].arg =
3696 certutil.options[opt_AddCmdNSCertTypeExt].arg;
3697 }
3698
3699 certutil_extns[ext_extKeyUsage].activated =
3700 certutil.options[opt_AddCmdExtKeyUsageExt].activated;
3701 if (!certutil_extns[ext_extKeyUsage].activated) {
3702 certutil_extns[ext_extKeyUsage].activated =
3703 certutil.options[opt_AddExtKeyUsageExt].activated;
3704 } else {
3705 certutil_extns[ext_extKeyUsage].arg =
3706 certutil.options[opt_AddCmdExtKeyUsageExt].arg;
3707 }
3708 certutil_extns[ext_subjectAltName].activated =
3709 certutil.options[opt_AddSubjectAltNameExt].activated;
3710 if (certutil_extns[ext_subjectAltName].activated) {
3711 certutil_extns[ext_subjectAltName].arg =
3712 certutil.options[opt_AddSubjectAltNameExt].arg;
3713 }
3714
3715 certutil_extns[ext_authInfoAcc].activated =
3716 certutil.options[opt_AddAuthInfoAccExt].activated;
3717 certutil_extns[ext_subjInfoAcc].activated =
3718 certutil.options[opt_AddSubjInfoAccExt].activated;
3719 certutil_extns[ext_certPolicies].activated =
3720 certutil.options[opt_AddCertPoliciesExt].activated;
3721 certutil_extns[ext_policyMappings].activated =
3722 certutil.options[opt_AddPolicyMapExt].activated;
3723 certutil_extns[ext_policyConstr].activated =
3724 certutil.options[opt_AddPolicyConstrExt].activated;
3725 certutil_extns[ext_inhibitAnyPolicy].activated =
3726 certutil.options[opt_AddInhibAnyExt].activated;
3727 }
3728
3729 /* -A -C or -E Read inFile */
3730 if (certutil.commands[cmd_CreateNewCert].activated ||
3731 certutil.commands[cmd_AddCert].activated ||
3732 certutil.commands[cmd_AddEmailCert].activated) {
3733 PRBool isCreate = certutil.commands[cmd_CreateNewCert].activated;
3734 rv = SECU_ReadDERFromFile(isCreate ? &certReqDER : &certDER, inFile,
3735 certutil.options[opt_ASCIIForIO].activated,
3736 PR_TRUE1);
3737 if (rv)
3738 goto shutdown;
3739 }
3740
3741 /*
3742 * Certificate request
3743 */
3744
3745 /* Make a cert request (-R). */
3746 if (certutil.commands[cmd_CertReq].activated) {
3747 rv = CertReq(privkey, pubkey, keytype, hashAlgTag, subject,
3748 certutil.options[opt_PhoneNumber].arg,
3749 certutil.options[opt_ASCIIForIO].activated,
3750 certutil.options[opt_ExtendedEmailAddrs].arg,
3751 certutil.options[opt_ExtendedDNSNames].arg,
3752 certutil_extns,
3753 (certutil.options[opt_GenericExtensions].activated ? certutil.options[opt_GenericExtensions].arg
3754 : NULL((void*)0)),
3755 certutil.options[opt_Pss].activated,
3756 &certReqDER);
3757 if (rv)
3758 goto shutdown;
3759 privkey->wincx = &pwdata;
3760 }
3761
3762 /*
3763 * Certificate creation
3764 */
3765
3766 /* If making and adding a cert, create a cert request file first without
3767 * any extensions, then load it with the command line extensions
3768 * and output the cert to another file.
3769 */
3770 if (certutil.commands[cmd_CreateAndAddCert].activated) {
3771 static certutilExtnList nullextnlist = { { PR_FALSE0, NULL((void*)0) } };
3772 rv = CertReq(privkey, pubkey, keytype, hashAlgTag, subject,
3773 certutil.options[opt_PhoneNumber].arg,
3774 PR_FALSE0, /* do not BASE64-encode regardless of -a option */
3775 NULL((void*)0),
3776 NULL((void*)0),
3777 nullextnlist,
3778 (certutil.options[opt_GenericExtensions].activated ? certutil.options[opt_GenericExtensions].arg
3779 : NULL((void*)0)),
3780 certutil.options[opt_Pss].activated,
3781 &certReqDER);
3782 if (rv)
3783 goto shutdown;
3784 privkey->wincx = &pwdata;
3785 }
3786
3787 /* Create a certificate (-C or -S). */
3788 if (certutil.commands[cmd_CreateAndAddCert].activated ||
3789 certutil.commands[cmd_CreateNewCert].activated) {
3790 rv = CreateCert(certHandle, slot,
3791 certutil.options[opt_IssuerName].arg,
3792 &certReqDER, &privkey, &pwdata, hashAlgTag,
3793 serialNumber, warpmonths, validityMonths,
3794 certutil.options[opt_ExtendedEmailAddrs].arg,
3795 certutil.options[opt_ExtendedDNSNames].arg,
3796 certutil.options[opt_ASCIIForIO].activated &&
3797 certutil.commands[cmd_CreateNewCert].activated,
3798 certutil.options[opt_SelfSign].activated,
3799 certutil_extns,
3800 (certutil.options[opt_GenericExtensions].activated ? certutil.options[opt_GenericExtensions].arg
3801 : NULL((void*)0)),
3802 certVersion,
3803 certutil.options[opt_PssSign].activated,
3804 &certDER);
3805 if (rv)
3806 goto shutdown;
3807 }
3808
3809 /*
3810 * Adding a cert to the database (or slot)
3811 */
3812
3813 /* -A -E or -S Add the cert to the DB */
3814 if (certutil.commands[cmd_CreateAndAddCert].activated ||
3815 certutil.commands[cmd_AddCert].activated ||
3816 certutil.commands[cmd_AddEmailCert].activated) {
3817 if (strstr(certutil.options[opt_Trust].arg, "u")) {
3818 fprintf(stderrstderr, "Notice: Trust flag u is set automatically if the "
3819 "private key is present.\n");
3820 }
3821 rv = AddCert(slot, certHandle, name,
3822 certutil.options[opt_Trust].arg,
3823 &certDER,
3824 certutil.commands[cmd_AddEmailCert].activated, &pwdata);
3825 if (rv)
3826 goto shutdown;
3827 }
3828
3829 if (certutil.commands[cmd_CertReq].activated ||
3830 certutil.commands[cmd_CreateNewCert].activated) {
3831 SECItem *item = certutil.commands[cmd_CertReq].activated ? &certReqDER
3832 : &certDER;
3833 PRInt32 written = PR_Write(outFile, item->data, item->len);
3834 if (written < 0 || (PRUint32)written != item->len) {
3835 rv = SECFailure;
3836 }
3837 }
3838
3839shutdown:
3840 if (slot) {
3841 PK11_FreeSlot(slot);
3842 }
3843 if (privkey) {
3844 SECKEY_DestroyPrivateKey(privkey);
3845 }
3846 if (pubkey) {
3847 SECKEY_DestroyPublicKey(pubkey);
3848 }
3849 if (subject) {
3850 CERT_DestroyName(subject);
3851 }
3852 if (name) {
3853 PL_strfree(name);
3854 }
3855 if (newName) {
3856 PL_strfree(newName);
3857 }
3858 if (inFile && inFile != PR_STDINPR_GetSpecialFD(PR_StandardInput)) {
3859 PR_Close(inFile);
3860 }
3861 if (outFile && outFile != PR_STDOUTPR_GetSpecialFD(PR_StandardOutput)) {
3862 PR_Close(outFile);
3863 }
3864 SECITEM_FreeItemSECITEM_FreeItem_Util(&certReqDER, PR_FALSE0);
3865 SECITEM_FreeItemSECITEM_FreeItem_Util(&certDER, PR_FALSE0);
3866 if (pwdata.data && pwdata.source == PW_PLAINTEXT) {
3867 /* Allocated by a PL_strdup call in SECU_GetModulePassword. */
3868 PL_strfree(pwdata.data);
3869 }
3870 if (email) {
3871 PL_strfree(email);
3872 }
3873
3874 /* Open the batch command file.
3875 *
3876 * - If -B <command line> option is specified, the contents in the
3877 * command file will be interpreted as subsequent certutil
3878 * commands to be executed in the current certutil process
3879 * context after the current certutil command has been executed.
3880 * - Each line in the command file consists of the command
3881 * line arguments for certutil.
3882 * - The -d <configdir> option will be ignored if specified in the
3883 * command file.
3884 * - Quoting with double quote characters ("...") is supported
3885 * to allow white space in a command line argument. The
3886 * double quote character cannot be escaped and quoting cannot
3887 * be nested in this version.
3888 * - each line in the batch file is limited to 512 characters
3889 */
3890
3891 if ((SECSuccess == rv) && certutil.commands[cmd_Batch].activated) {
3892 FILE *batchFile = NULL((void*)0);
3893 char *nextcommand = NULL((void*)0);
3894 PRInt32 cmd_len = 0, buf_size = 0;
3895 static const int increment = 512;
3896
3897 if (!certutil.options[opt_InputFile].activated ||
3898 !certutil.options[opt_InputFile].arg) {
3899 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3900 "%s: no batch input file specified.\n",
3901 progName);
3902 return 255;
3903 }
3904 batchFile = fopen(certutil.options[opt_InputFile].arg, "r");
3905 if (!batchFile) {
3906 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3907 "%s: unable to open \"%s\" for reading (%ld, %ld).\n",
3908 progName, certutil.options[opt_InputFile].arg,
3909 PR_GetError(), PR_GetOSError());
3910 return 255;
3911 }
3912 /* read and execute command-lines in a loop */
3913 while (SECSuccess == rv) {
3914 PRBool invalid = PR_FALSE0;
3915 int newargc = 2;
3916 char *space = NULL((void*)0);
3917 char *nextarg = NULL((void*)0);
3918 char **newargv = NULL((void*)0);
3919 char *crlf;
3920
3921 if (cmd_len + increment > buf_size) {
3922 char *new_buf;
3923 buf_size += increment;
3924 new_buf = PORT_ReallocPORT_Realloc_Util(nextcommand, buf_size);
3925 if (!new_buf) {
3926 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s: PORT_Realloc(%ld) failed\n",
3927 progName, buf_size);
3928 break;
3929 }
3930 nextcommand = new_buf;
3931 nextcommand[cmd_len] = '\0';
3932 }
3933 if (!fgets(nextcommand + cmd_len, buf_size - cmd_len, batchFile)) {
3934 break;
3935 }
3936 crlf = PORT_Strrchrstrrchr(nextcommand, '\n');
3937 if (crlf) {
3938 *crlf = '\0';
3939 }
3940 cmd_len = strlen(nextcommand);
3941 if (cmd_len && nextcommand[cmd_len - 1] == '\\') {
3942 nextcommand[--cmd_len] = '\0';
3943 continue;
3944 }
3945
3946 /* we now need to split the command into argc / argv format */
3947
3948 newargv = PORT_AllocPORT_Alloc_Util(sizeof(char *) * (newargc + 1));
3949 newargv[0] = progName;
3950 newargv[1] = nextcommand;
3951 nextarg = nextcommand;
3952 while ((space = PORT_Strpbrkstrpbrk(nextarg, " \f\n\r\t\v"))) {
3953 while (isspace((unsigned char)*space)((*__ctype_b_loc ())[(int) (((unsigned char)*space))] & (
unsigned short int) _ISspace)
) {
3954 *space = '\0';
3955 space++;
3956 }
3957 if (*space == '\0') {
3958 break;
3959 } else if (*space != '\"') {
3960 nextarg = space;
3961 } else {
3962 char *closingquote = strchr(space + 1, '\"');
3963 if (closingquote) {
3964 *closingquote = '\0';
3965 space++;
3966 nextarg = closingquote + 1;
3967 } else {
3968 invalid = PR_TRUE1;
3969 nextarg = space;
3970 }
3971 }
3972 newargc++;
3973 newargv = PORT_ReallocPORT_Realloc_Util(newargv, sizeof(char *) * (newargc + 1));
3974 newargv[newargc - 1] = space;
3975 }
3976 newargv[newargc] = NULL((void*)0);
3977
3978 /* invoke next command */
3979 if (PR_TRUE1 == invalid) {
3980 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "Missing closing quote in batch command :\n%s\nNot executed.\n",
3981 nextcommand);
3982 rv = SECFailure;
3983 } else {
3984 if (0 != certutil_main(newargc, newargv, PR_FALSE0))
3985 rv = SECFailure;
3986 }
3987 PORT_FreePORT_Free_Util(newargv);
3988 cmd_len = 0;
3989 nextcommand[0] = '\0';
3990 }
3991 PORT_FreePORT_Free_Util(nextcommand);
3992 fclose(batchFile);
3993 }
3994
3995 if ((initialized == PR_TRUE1) && NSS_Shutdown() != SECSuccess) {
3996 exit(1);
3997 }
3998 if (rv == SECSuccess) {
3999 return 0;
4000 } else {
4001 return 255;
4002 }
4003}
4004
4005int
4006main(int argc, char **argv)
4007{
4008 int rv = certutil_main(argc, argv, PR_TRUE1);
4009 PL_ArenaFinish();
4010 PR_Cleanup();
4011 return rv;
4012}