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-09-01-224014-2642839-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 mldsa -q paramset [-f pwfile]\n"
1164 "\t\t [-z noisefile] [-d certdir] [-P dbprefix]\n", progName);
1165 FPS "\t%s -K [-n key-name] [-h token-name] [-k dsa|ec|rsa|mldsa|all]\n",
1166 progName);
1167 FPS "\t\t [-f pwfile] [-X] [-d certdir] [-P dbprefix]\n");
1168 FPS "\t%s --upgrade-merge --source-dir upgradeDir --upgrade-id uniqueID\n",
1169 progName);
1170 FPS "\t\t [--upgrade-token-name tokenName] [-d targetDBDir]\n");
1171 FPS "\t\t [-P targetDBPrefix] [--source-prefix upgradeDBPrefix]\n");
1172 FPS "\t\t [-f targetPWfile] [-@ upgradePWFile]\n");
1173 FPS "\t%s --merge --source-dir sourceDBDir [-d targetDBdir]\n",
1174 progName);
1175 FPS "\t\t [-P targetDBPrefix] [--source-prefix sourceDBPrefix]\n");
1176 FPS "\t\t [-f targetPWfile] [-@ sourcePWFile]\n");
1177 FPS "\t%s -L [-n cert-name] [-h token-name] [--email email-address]\n",
1178 progName);
1179 FPS "\t\t [-X] [-r] [-a] [--dump-ext-val OID] [-d certdir] [-P dbprefix]\n");
1180 FPS "\t%s --build-flags\n", progName);
1181 FPS "\t%s -M -n cert-name -t trustargs [-d certdir] [-P dbprefix]\n",
1182 progName);
1183 FPS "\t%s -O -n cert-name [-X] [-d certdir] [-a] [-P dbprefix]\n"
1184 "\t\t [--simple-self-signed]\n",
1185 progName);
1186 FPS "\t%s -R -s subj -o cert-request-file [-d certdir] [-P dbprefix] [-p phone] [-a]\n"
1187 "\t\t [-7 emailAddrs] [-k key-type-or-id] [-h token-name] [-f pwfile]\n"
1188 "\t\t [-g key-size] [-Z hashAlg]\n",
1189 progName);
1190 FPS "\t%s -V -n cert-name -u usage [-b time] [-e] [-a]\n"
1191 "\t\t[-X] [-d certdir] [-P dbprefix]\n",
1192 progName);
1193 FPS "Usage: %s -W [-d certdir] [-f pwfile] [-@newpwfile]\n",
1194 progName);
1195 FPS "\t%s -S -n cert-name -s subj [-c issuer-name | -x] -t trustargs\n"
1196 "\t\t [-k key-type-or-id] [-q key-params] [-h token-name] [-g key-size]\n"
1197 "\t\t [-m serial-number] [-w warp-months] [-v months-valid]\n"
1198 "\t\t [-f pwfile] [-d certdir] [-P dbprefix] [-Z hashAlg]\n"
1199 "\t\t [-p phone] [-1] [-2] [-3] [-4] [-5] [-6] [-7 emailAddrs]\n"
1200 "\t\t [-8 DNS-names]\n"
1201 "\t\t [--extAIA] [--extSIA] [--extCP] [--extPM] [--extPC] [--extIA]\n"
1202 "\t\t [--extSKID] [--extNC] [--extSAN type:name[,type:name]...]\n"
1203 "\t\t [--extGeneric OID:critical-flag:filename[,OID:critical-flag:filename]...]\n", progName);
1204 FPS "\t%s -U [-X] [-d certdir] [-P dbprefix]\n", progName);
1205 exit(1);
1206}
1207
1208enum usage_level {
1209 usage_all = 0,
1210 usage_selected = 1
1211};
1212
1213static void luCommonDetailsAE();
1214
1215static void
1216luA(enum usage_level ul, const char *command)
1217{
1218 int is_my_command = (command && 0 == strcmp(command, "A"));
1219 if (ul == usage_all || !command || is_my_command)
1220 FPS "%-15s Add a certificate to the database (create if needed)\n",
1221 "-A");
1222 if (ul == usage_selected && !is_my_command)
1223 return;
1224 if (ul == usage_all) {
1225 FPS "%-20s\n", " All options under -E apply");
1226 } else {
1227 luCommonDetailsAE();
1228 }
1229}
1230
1231static void
1232luB(enum usage_level ul, const char *command)
1233{
1234 int is_my_command = (command && 0 == strcmp(command, "B"));
1235 if (ul == usage_all || !command || is_my_command)
1236 FPS "%-15s Run a series of certutil commands from a batch file\n", "-B");
1237 if (ul == usage_selected && !is_my_command)
1238 return;
1239 FPS "%-20s Specify the batch file\n", " -i batch-file");
1240}
1241
1242static void
1243luE(enum usage_level ul, const char *command)
1244{
1245 int is_my_command = (command && 0 == strcmp(command, "E"));
1246 if (ul == usage_all || !command || is_my_command)
1247 FPS "%-15s Add an Email certificate to the database (create if needed)\n",
1248 "-E");
1249 if (ul == usage_selected && !is_my_command)
1250 return;
1251 luCommonDetailsAE();
1252}
1253
1254static void
1255luCommonDetailsAE()
1256{
1257 FPS "%-20s Specify the nickname of the certificate to add\n",
1258 " -n cert-name");
1259 FPS "%-20s Set the certificate trust attributes:\n",
1260 " -t trustargs");
1261 FPS "%-25s trustargs is of the form x,y,z where x is for SSL, y is for S/MIME,\n", "");
1262 FPS "%-25s and z is for code signing. Use ,, for no explicit trust.\n", "");
1263 FPS "%-25s p \t prohibited (explicitly distrusted)\n", "");
1264 FPS "%-25s P \t trusted peer\n", "");
1265 FPS "%-25s c \t valid CA\n", "");
1266 FPS "%-25s T \t trusted CA to issue client certs (implies c)\n", "");
1267 FPS "%-25s C \t trusted CA to issue server certs (implies c)\n", "");
1268 FPS "%-25s u \t user cert\n", "");
1269 FPS "%-25s w \t send warning\n", "");
1270 FPS "%-25s g \t make step-up cert\n", "");
1271 FPS "%-20s Specify the password file\n",
1272 " -f pwfile");
1273 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1274 " -d certdir");
1275 FPS "%-20s Cert & Key database prefix\n",
1276 " -P dbprefix");
1277 FPS "%-20s The input certificate is encoded in ASCII (RFC1113)\n",
1278 " -a");
1279 FPS "%-20s Specify the certificate file (default is stdin)\n",
1280 " -i input");
1281 FPS "\n");
1282}
1283
1284static void
1285luC(enum usage_level ul, const char *command)
1286{
1287 int is_my_command = (command && 0 == strcmp(command, "C"));
1288 if (ul == usage_all || !command || is_my_command)
1289 FPS "%-15s Create a new binary certificate from a BINARY cert request\n",
1290 "-C");
1291 if (ul == usage_selected && !is_my_command)
1292 return;
1293 FPS "%-20s The nickname of the issuer cert\n",
1294 " -c issuer-name");
1295 FPS "%-20s The BINARY certificate request file\n",
1296 " -i cert-request ");
1297 FPS "%-20s Output binary cert to this file (default is stdout)\n",
1298 " -o output-cert");
1299 FPS "%-20s Self sign\n",
1300 " -x");
1301 FPS "%-20s Sign the certificate with RSA-PSS (the issuer key must be rsa)\n",
1302 " --pss-sign");
1303 FPS "%-20s Cert serial number\n",
1304 " -m serial-number");
1305 FPS "%-20s Time Warp\n",
1306 " -w warp-months");
1307 FPS "%-20s Months valid (default is 3)\n",
1308 " -v months-valid");
1309 FPS "%-20s Specify the password file\n",
1310 " -f pwfile");
1311 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1312 " -d certdir");
1313 FPS "%-20s Cert & Key database prefix\n",
1314 " -P dbprefix");
1315 FPS "%-20s \n"
1316 "%-20s Specify the hash algorithm to use. Possible keywords:\n"
1317 "%-20s \"MD2\", \"MD4\", \"MD5\", \"SHA1\", \"SHA224\",\n"
1318 "%-20s \"SHA256\", \"SHA384\", \"SHA512\"\n",
1319 " -Z hashAlg", "", "", "");
1320 FPS "%-20s \n"
1321 "%-20s Create key usage extension. Possible keywords:\n"
1322 "%-20s \"digitalSignature\", \"nonRepudiation\", \"keyEncipherment\",\n"
1323 "%-20s \"dataEncipherment\", \"keyAgreement\", \"certSigning\",\n"
1324 "%-20s \"crlSigning\", \"critical\"\n",
1325 " -1 | --keyUsage keyword,keyword,...", "", "", "", "");
1326 FPS "%-20s Create basic constraint extension\n",
1327 " -2 ");
1328 FPS "%-20s Create authority key ID extension\n",
1329 " -3 ");
1330 FPS "%-20s Create crl distribution point extension\n",
1331 " -4 ");
1332 FPS "%-20s \n"
1333 "%-20s Create netscape cert type extension. Possible keywords:\n"
1334 "%-20s \"sslClient\", \"sslServer\", \"smime\", \"objectSigning\",\n"
1335 "%-20s \"sslCA\", \"smimeCA\", \"objectSigningCA\", \"critical\".\n",
1336 " -5 | --nsCertType keyword,keyword,... ", "", "", "");
1337 FPS "%-20s \n"
1338 "%-20s Create extended key usage extension. Possible keywords:\n"
1339 "%-20s \"serverAuth\", \"clientAuth\",\"codeSigning\",\n"
1340 "%-20s \"emailProtection\", \"timeStamp\",\"ocspResponder\",\n"
1341 "%-20s \"stepUp\", \"msTrustListSign\", \"x509Any\",\n"
1342 "%-20s \"ipsecIKE\", \"ipsecIKEEnd\", \"ipsecIKEIntermediate\",\n"
1343 "%-20s \"ipsecEnd\", \"ipsecTunnel\", \"ipsecUser\",\n"
1344 "%-20s \"critical\"\n",
1345 " -6 | --extKeyUsage keyword,keyword,...", "", "", "", "", "", "", "");
1346 FPS "%-20s Create an email subject alt name extension\n",
1347 " -7 emailAddrs");
1348 FPS "%-20s Create an dns subject alt name extension\n",
1349 " -8 dnsNames");
1350 FPS "%-20s The input certificate request is encoded in ASCII (RFC1113)\n",
1351 " -a");
1352 FPS "\n");
1353}
1354
1355static void
1356luG(enum usage_level ul, const char *command)
1357{
1358 int is_my_command = (command && 0 == strcmp(command, "G"));
1359 if (ul == usage_all || !command || is_my_command)
1360 FPS "%-15s Generate a new key pair\n",
1361 "-G");
1362 if (ul == usage_selected && !is_my_command)
1363 return;
1364 FPS "%-20s Name of token in which to generate key (default is internal)\n",
1365 " -h token-name");
1366 FPS "%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n",
1367 " -k key-type");
1368 FPS "%-20s Key size in bits, (min %d, max %d, default %d) (not for ec)\n",
1369 " -g key-size", MIN_KEY_BITS512, MAX_KEY_BITS8192, DEFAULT_KEY_BITS2048);
1370 FPS "%-20s Set the public exponent value (3, 17, 65537) (rsa only)\n",
1371 " -y exp");
1372 FPS "%-20s Specify the password file\n",
1373 " -f password-file");
1374 FPS "%-20s Specify the noise file to be used\n",
1375 " -z noisefile");
1376 FPS "%-20s read PQG value from pqgfile (dsa only)\n",
1377 " -q pqgfile");
1378 FPS "%-20s Elliptic curve name (ec only)\n",
1379 " -q curve-name");
1380 FPS "%-20s One of nistp256, nistp384, nistp521, curve25519.\n", "");
1381 FPS "%-20s If a custom token is present, the following curves are also supported:\n", "");
1382 FPS "%-20s sect163k1, nistk163, sect163r1, sect163r2,\n", "");
1383 FPS "%-20s nistb163, sect193r1, sect193r2, sect233k1, nistk233,\n", "");
1384 FPS "%-20s sect233r1, nistb233, sect239k1, sect283k1, nistk283,\n", "");
1385 FPS "%-20s sect283r1, nistb283, sect409k1, nistk409, sect409r1,\n", "");
1386 FPS "%-20s nistb409, sect571k1, nistk571, sect571r1, nistb571,\n", "");
1387 FPS "%-20s secp160k1, secp160r1, secp160r2, secp192k1, secp192r1,\n", "");
1388 FPS "%-20s nistp192, secp224k1, secp224r1, nistp224, secp256k1,\n", "");
1389 FPS "%-20s secp256r1, secp384r1, secp521r1,\n", "");
1390 FPS "%-20s prime192v1, prime192v2, prime192v3, \n", "");
1391 FPS "%-20s prime239v1, prime239v2, prime239v3, c2pnb163v1, \n", "");
1392 FPS "%-20s c2pnb163v2, c2pnb163v3, c2pnb176v1, c2tnb191v1, \n", "");
1393 FPS "%-20s c2tnb191v2, c2tnb191v3, \n", "");
1394 FPS "%-20s c2pnb208w1, c2tnb239v1, c2tnb239v2, c2tnb239v3, \n", "");
1395 FPS "%-20s c2pnb272w1, c2pnb304w1, \n", "");
1396 FPS "%-20s c2tnb359w1, c2pnb368w1, c2tnb431r1, secp112r1, \n", "");
1397 FPS "%-20s secp112r2, secp128r1, secp128r2, sect113r1, sect113r2\n", "");
1398 FPS "%-20s sect131r1, sect131r2\n", "");
1399 FPS "%-20s ML-DSA parameter set (mldsa only)\n",
1400 " -q paramset");
1401 FPS "%-20s valid values are ml-dsa-44, ml-dsa-65, ml-dsa-87:\n", "");
1402 FPS "%-20s Key database directory (default is ~/.netscape)\n",
1403 " -d keydir");
1404 FPS "%-20s Cert & Key database prefix\n",
1405 " -P dbprefix");
1406 FPS "%-20s\n"
1407 "%-20s PKCS #11 key Attributes.\n",
1408 " --keyAttrFlags attrflags", "");
1409 FPS "%-20s Comma separated list of key attribute attribute flags,\n", "");
1410 FPS "%-20s selected from the following list of choices:\n", "");
1411 FPS "%-20s {token | session} {public | private} {sensitive | insensitive}\n", "");
1412 FPS "%-20s {modifiable | unmodifiable} {extractable | unextractable}\n", "");
1413 FPS "%-20s\n",
1414 " --keyOpFlagsOn opflags");
1415 FPS "%-20s\n"
1416 "%-20s PKCS #11 key Operation Flags.\n",
1417 " --keyOpFlagsOff opflags", "");
1418 FPS "%-20s Comma separated list of one or more of the following:\n", "");
1419 FPS "%-20s encrypt, decrypt, sign, sign_recover, verify,\n", "");
1420 FPS "%-20s verify_recover, wrap, unwrap, derive\n", "");
1421 FPS "\n");
1422}
1423
1424static void
1425luD(enum usage_level ul, const char *command)
1426{
1427 int is_my_command = (command && 0 == strcmp(command, "D"));
1428 if (ul == usage_all || !command || is_my_command)
1429 FPS "%-15s Delete a certificate from the database\n",
1430 "-D");
1431 if (ul == usage_selected && !is_my_command)
1432 return;
1433 FPS "%-20s The nickname of the cert to delete\n",
1434 " -n cert-name");
1435 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1436 " -d certdir");
1437 FPS "%-20s Cert & Key database prefix\n",
1438 " -P dbprefix");
1439 FPS "\n");
1440}
1441
1442static void
1443luF(enum usage_level ul, const char *command)
1444{
1445 int is_my_command = (command && 0 == strcmp(command, "F"));
1446 if (ul == usage_all || !command || is_my_command)
1447 FPS "%-15s Delete a key and associated certificate from the database\n",
1448 "-F");
1449 if (ul == usage_selected && !is_my_command)
1450 return;
1451 FPS "%-20s The nickname of the key to delete\n",
1452 " -n cert-name");
1453 FPS "%-20s The key id of the key to delete, obtained using -K\n",
1454 " -k key-id");
1455 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1456 " -d certdir");
1457 FPS "%-20s Cert & Key database prefix\n",
1458 " -P dbprefix");
1459 FPS "\n");
1460}
1461
1462static void
1463luU(enum usage_level ul, const char *command)
1464{
1465 int is_my_command = (command && 0 == strcmp(command, "U"));
1466 if (ul == usage_all || !command || is_my_command)
1467 FPS "%-15s List all modules\n", /*, or print out a single named module\n",*/
1468 "-U");
1469 if (ul == usage_selected && !is_my_command)
1470 return;
1471 FPS "%-20s Module database directory (default is '~/.netscape')\n",
1472 " -d moddir");
1473 FPS "%-20s Cert & Key database prefix\n",
1474 " -P dbprefix");
1475 FPS "%-20s force the database to open R/W\n",
1476 " -X");
1477 FPS "\n");
1478}
1479
1480static void
1481luK(enum usage_level ul, const char *command)
1482{
1483 int is_my_command = (command && 0 == strcmp(command, "K"));
1484 if (ul == usage_all || !command || is_my_command)
1485 FPS "%-15s List all private keys\n",
1486 "-K");
1487 if (ul == usage_selected && !is_my_command)
1488 return;
1489 FPS "%-20s Name of token to search (\"all\" for all tokens)\n",
1490 " -h token-name ");
1491
1492 FPS "%-20s Key type (\"all\" (default), \"dsa\","
1493 " \"ec\","
1494 " \"mldsa\","
1495 " \"rsa\")\n",
1496 " -k key-type");
1497 FPS "%-20s The nickname of the key or associated certificate\n",
1498 " -n name");
1499 FPS "%-20s Specify the password file\n",
1500 " -f password-file");
1501 FPS "%-20s Key database directory (default is ~/.netscape)\n",
1502 " -d keydir");
1503 FPS "%-20s Cert & Key database prefix\n",
1504 " -P dbprefix");
1505 FPS "%-20s force the database to open R/W\n",
1506 " -X");
1507 FPS "\n");
1508}
1509
1510static void
1511luL(enum usage_level ul, const char *command)
1512{
1513 int is_my_command = (command && 0 == strcmp(command, "L"));
1514 if (ul == usage_all || !command || is_my_command)
1515 FPS "%-15s List all certs, or print out a single named cert (or a subset)\n",
1516 "-L");
1517 if (ul == usage_selected && !is_my_command)
1518 return;
1519 FPS "%-20s Name of token to search (\"all\" for all tokens)\n",
1520 " -h token-name ");
1521 FPS "%-20s Pretty print named cert (list all if unspecified)\n",
1522 " -n cert-name");
1523 FPS "%-20s \n"
1524 "%-20s Pretty print cert with email address (list all if unspecified)\n",
1525 " --email email-address", "");
1526 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1527 " -d certdir");
1528 FPS "%-20s Cert & Key database prefix\n",
1529 " -P dbprefix");
1530 FPS "%-20s force the database to open R/W\n",
1531 " -X");
1532 FPS "%-20s For single cert, print binary DER encoding\n",
1533 " -r");
1534 FPS "%-20s For single cert, print ASCII encoding (RFC1113)\n",
1535 " -a");
1536 FPS "%-20s \n"
1537 "%-20s For single cert, print binary DER encoding of extension OID\n",
1538 " --dump-ext-val OID", "");
1539 FPS "\n");
1540}
1541
1542static void
1543luM(enum usage_level ul, const char *command)
1544{
1545 int is_my_command = (command && 0 == strcmp(command, "M"));
1546 if (ul == usage_all || !command || is_my_command)
1547 FPS "%-15s Modify trust attributes of certificate\n",
1548 "-M");
1549 if (ul == usage_selected && !is_my_command)
1550 return;
1551 FPS "%-20s The nickname of the cert to modify\n",
1552 " -n cert-name");
1553 FPS "%-20s Set the certificate trust attributes (see -A above)\n",
1554 " -t trustargs");
1555 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1556 " -d certdir");
1557 FPS "%-20s Cert & Key database prefix\n",
1558 " -P dbprefix");
1559 FPS "\n");
1560}
1561
1562static void
1563luN(enum usage_level ul, const char *command)
1564{
1565 int is_my_command = (command && 0 == strcmp(command, "N"));
1566 if (ul == usage_all || !command || is_my_command)
1567 FPS "%-15s Create a new certificate database\n",
1568 "-N");
1569 if (ul == usage_selected && !is_my_command)
1570 return;
1571 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1572 " -d certdir");
1573 FPS "%-20s Cert & Key database prefix\n",
1574 " -P dbprefix");
1575 FPS "%-20s Specify the password file\n",
1576 " -f password-file");
1577 FPS "%-20s use empty password when creating a new database\n",
1578 " --empty-password");
1579 FPS "\n");
1580}
1581
1582static void
1583luT(enum usage_level ul, const char *command)
1584{
1585 int is_my_command = (command && 0 == strcmp(command, "T"));
1586 if (ul == usage_all || !command || is_my_command)
1587 FPS "%-15s Reset the Key database or token\n",
1588 "-T");
1589 if (ul == usage_selected && !is_my_command)
1590 return;
1591 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1592 " -d certdir");
1593 FPS "%-20s Cert & Key database prefix\n",
1594 " -P dbprefix");
1595 FPS "%-20s Token to reset (default is internal)\n",
1596 " -h token-name");
1597 FPS "%-20s Set token's Site Security Officer password\n",
1598 " -0 SSO-password");
1599 FPS "\n");
1600}
1601
1602static void
1603luO(enum usage_level ul, const char *command)
1604{
1605 int is_my_command = (command && 0 == strcmp(command, "O"));
1606 if (ul == usage_all || !command || is_my_command)
1607 FPS "%-15s Print the chain of a certificate\n",
1608 "-O");
1609 if (ul == usage_selected && !is_my_command)
1610 return;
1611 FPS "%-20s The nickname of the cert to modify\n",
1612 " -n cert-name");
1613 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1614 " -d certdir");
1615 FPS "%-20s Input the certificate in ASCII (RFC1113); default is binary\n",
1616 " -a");
1617 FPS "%-20s Cert & Key database prefix\n",
1618 " -P dbprefix");
1619 FPS "%-20s force the database to open R/W\n",
1620 " -X");
1621 FPS "%-20s don't search for a chain if issuer name equals subject name\n",
1622 " --simple-self-signed");
1623 FPS "\n");
1624}
1625
1626static void
1627luR(enum usage_level ul, const char *command)
1628{
1629 int is_my_command = (command && 0 == strcmp(command, "R"));
1630 if (ul == usage_all || !command || is_my_command)
1631 FPS "%-15s Generate a certificate request (stdout)\n",
1632 "-R");
1633 if (ul == usage_selected && !is_my_command)
1634 return;
1635 FPS "%-20s Specify the subject name (using RFC1485)\n",
1636 " -s subject");
1637 FPS "%-20s Output the cert request to this file\n",
1638 " -o output-req");
1639 FPS "%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n",
1640 " -k key-type-or-id");
1641 FPS "%-20s or nickname of the cert key to use, or key id obtained using -K\n",
1642 "");
1643 FPS "%-20s Name of token in which to generate key (default is internal)\n",
1644 " -h token-name");
1645 FPS "%-20s Key size in bits, RSA keys only (min %d, max %d, default %d)\n",
1646 " -g key-size", MIN_KEY_BITS512, MAX_KEY_BITS8192, DEFAULT_KEY_BITS2048);
1647 FPS "%-20s Create a certificate request restricted to RSA-PSS (rsa only)\n",
1648 " --pss");
1649 FPS "%-20s Name of file containing PQG parameters (dsa only)\n",
1650 " -q pqgfile");
1651 FPS "%-20s Elliptic curve name (ec only)\n",
1652 " -q curve-name");
1653 FPS "%-20s See the \"-G\" option for a full list of supported names.\n",
1654 "");
1655 FPS "%-20s ML-DSA parameter set (mldsa only)\n",
1656 " -q paramset");
1657 FPS "%-20s See the \"-G\" option for a full list of supported names.\n",
1658 "");
1659 FPS "%-20s Specify the password file\n",
1660 " -f pwfile");
1661 FPS "%-20s Key database directory (default is ~/.netscape)\n",
1662 " -d keydir");
1663 FPS "%-20s Cert & Key database prefix\n",
1664 " -P dbprefix");
1665 FPS "%-20s Specify the contact phone number (\"123-456-7890\")\n",
1666 " -p phone");
1667 FPS "%-20s \n"
1668 "%-20s Specify the hash algorithm to use. Possible keywords:\n"
1669 "%-20s \"MD2\", \"MD4\", \"MD5\", \"SHA1\", \"SHA224\",\n"
1670 "%-20s \"SHA256\", \"SHA384\", \"SHA512\"\n",
1671 " -Z hashAlg", "", "", "");
1672 FPS "%-20s Output the cert request in ASCII (RFC1113); default is binary\n",
1673 " -a");
1674 FPS "%-20s \n",
1675 " See -S for available extension options");
1676 FPS "%-20s \n",
1677 " See -G for available key flag options");
1678 FPS "\n");
1679}
1680
1681static void
1682luV(enum usage_level ul, const char *command)
1683{
1684 int is_my_command = (command && 0 == strcmp(command, "V"));
1685 if (ul == usage_all || !command || is_my_command)
1686 FPS "%-15s Validate a certificate\n",
1687 "-V");
1688 if (ul == usage_selected && !is_my_command)
1689 return;
1690 FPS "%-20s The nickname of the cert to Validate\n",
1691 " -n cert-name");
1692 FPS "%-20s validity time (\"YYMMDDHHMMSS[+HHMM|-HHMM|Z]\")\n",
1693 " -b time");
1694 FPS "%-20s Check certificate signature \n",
1695 " -e ");
1696 FPS "%-20s Specify certificate usage:\n", " -u certusage");
1697 FPS "%-25s C \t SSL Client\n", "");
1698 FPS "%-25s V \t SSL Server\n", "");
1699 FPS "%-25s I \t IPsec\n", "");
1700 FPS "%-25s L \t SSL CA\n", "");
1701 FPS "%-25s A \t Any CA\n", "");
1702 FPS "%-25s Y \t Verify CA\n", "");
1703 FPS "%-25s S \t Email signer\n", "");
1704 FPS "%-25s R \t Email Recipient\n", "");
1705 FPS "%-25s O \t OCSP status responder\n", "");
1706 FPS "%-25s J \t Object signer\n", "");
1707 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1708 " -d certdir");
1709 FPS "%-20s Input the certificate in ASCII (RFC1113); default is binary\n",
1710 " -a");
1711 FPS "%-20s Cert & Key database prefix\n",
1712 " -P dbprefix");
1713 FPS "%-20s force the database to open R/W\n",
1714 " -X");
1715 FPS "\n");
1716}
1717
1718static void
1719luW(enum usage_level ul, const char *command)
1720{
1721 int is_my_command = (command && 0 == strcmp(command, "W"));
1722 if (ul == usage_all || !command || is_my_command)
1723 FPS "%-15s Change the key database password\n",
1724 "-W");
1725 if (ul == usage_selected && !is_my_command)
1726 return;
1727 FPS "%-20s cert and key database directory\n",
1728 " -d certdir");
1729 FPS "%-20s Specify a file with the current password\n",
1730 " -f pwfile");
1731 FPS "%-20s Specify a file with the new password in two lines\n",
1732 " -@ newpwfile");
1733 FPS "\n");
1734}
1735
1736static void
1737luRename(enum usage_level ul, const char *command)
1738{
1739 int is_my_command = (command && 0 == strcmp(command, "rename"));
1740 if (ul == usage_all || !command || is_my_command)
1741 FPS "%-15s Change the database nickname of a certificate\n",
1742 "--rename");
1743 if (ul == usage_selected && !is_my_command)
1744 return;
1745 FPS "%-20s The old nickname of the cert to rename\n",
1746 " -n cert-name");
1747 FPS "%-20s The new nickname of the cert to rename\n",
1748 " --new-n new-name");
1749 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1750 " -d certdir");
1751 FPS "%-20s Cert & Key database prefix\n",
1752 " -P dbprefix");
1753 FPS "\n");
1754}
1755
1756static void
1757luUpgradeMerge(enum usage_level ul, const char *command)
1758{
1759 int is_my_command = (command && 0 == strcmp(command, "upgrade-merge"));
1760 if (ul == usage_all || !command || is_my_command)
1761 FPS "%-15s Upgrade an old database and merge it into a new one\n",
1762 "--upgrade-merge");
1763 if (ul == usage_selected && !is_my_command)
1764 return;
1765 FPS "%-20s Cert database directory to merge into (default is ~/.netscape)\n",
1766 " -d certdir");
1767 FPS "%-20s Cert & Key database prefix of the target database\n",
1768 " -P dbprefix");
1769 FPS "%-20s Specify the password file for the target database\n",
1770 " -f pwfile");
1771 FPS "%-20s \n%-20s Cert database directory to upgrade from\n",
1772 " --source-dir certdir", "");
1773 FPS "%-20s \n%-20s Cert & Key database prefix of the upgrade database\n",
1774 " --source-prefix dbprefix", "");
1775 FPS "%-20s \n%-20s Unique identifier for the upgrade database\n",
1776 " --upgrade-id uniqueID", "");
1777 FPS "%-20s \n%-20s Name of the token while it is in upgrade state\n",
1778 " --upgrade-token-name name", "");
1779 FPS "%-20s Specify the password file for the upgrade database\n",
1780 " -@ pwfile");
1781 FPS "\n");
1782}
1783
1784static void
1785luMerge(enum usage_level ul, const char *command)
1786{
1787 int is_my_command = (command && 0 == strcmp(command, "merge"));
1788 if (ul == usage_all || !command || is_my_command)
1789 FPS "%-15s Merge source database into the target database\n",
1790 "--merge");
1791 if (ul == usage_selected && !is_my_command)
1792 return;
1793 FPS "%-20s Cert database directory of target (default is ~/.netscape)\n",
1794 " -d certdir");
1795 FPS "%-20s Cert & Key database prefix of the target database\n",
1796 " -P dbprefix");
1797 FPS "%-20s Specify the password file for the target database\n",
1798 " -f pwfile");
1799 FPS "%-20s \n%-20s Cert database directory of the source database\n",
1800 " --source-dir certdir", "");
1801 FPS "%-20s \n%-20s Cert & Key database prefix of the source database\n",
1802 " --source-prefix dbprefix", "");
1803 FPS "%-20s Specify the password file for the source database\n",
1804 " -@ pwfile");
1805 FPS "\n");
1806}
1807
1808static void
1809luS(enum usage_level ul, const char *command)
1810{
1811 int is_my_command = (command && 0 == strcmp(command, "S"));
1812 if (ul == usage_all || !command || is_my_command)
1813 FPS "%-15s Make a certificate and add to database\n",
1814 "-S");
1815 if (ul == usage_selected && !is_my_command)
1816 return;
1817 FPS "%-20s Specify the nickname of the cert\n",
1818 " -n key-name");
1819 FPS "%-20s Specify the subject name (using RFC1485)\n",
1820 " -s subject");
1821 FPS "%-20s The nickname of the issuer cert\n",
1822 " -c issuer-name");
1823 FPS "%-20s Set the certificate trust attributes (see -A above)\n",
1824 " -t trustargs");
1825 FPS "%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n",
1826 " -k key-type-or-id");
1827 FPS "%-20s Name of token in which to generate key (default is internal)\n",
1828 " -h token-name");
1829 FPS "%-20s Key size in bits, RSA keys only (min %d, max %d, default %d)\n",
1830 " -g key-size", MIN_KEY_BITS512, MAX_KEY_BITS8192, DEFAULT_KEY_BITS2048);
1831 FPS "%-20s Create a certificate restricted to RSA-PSS (rsa only)\n",
1832 " --pss");
1833 FPS "%-20s Name of file containing PQG parameters (dsa only)\n",
1834 " -q pqgfile");
1835 FPS "%-20s Elliptic curve name (ec only)\n",
1836 " -q curve-name");
1837 FPS "%-20s See the \"-G\" option for a full list of supported names.\n",
1838 "");
1839 FPS "%-20s ML-DSA parameter set (mldsa only)\n",
1840 " -q paramset");
1841 FPS "%-20s See the \"-G\" option for a full list of supported names.\n",
1842 "");
1843 FPS "%-20s Self sign\n",
1844 " -x");
1845 FPS "%-20s Sign the certificate with RSA-PSS (the issuer key must be rsa)\n",
1846 " --pss-sign");
1847 FPS "%-20s Cert serial number\n",
1848 " -m serial-number");
1849 FPS "%-20s Time Warp\n",
1850 " -w warp-months");
1851 FPS "%-20s Months valid (default is 3)\n",
1852 " -v months-valid");
1853 FPS "%-20s Specify the password file\n",
1854 " -f pwfile");
1855 FPS "%-20s Cert database directory (default is ~/.netscape)\n",
1856 " -d certdir");
1857 FPS "%-20s Cert & Key database prefix\n",
1858 " -P dbprefix");
1859 FPS "%-20s Specify the contact phone number (\"123-456-7890\")\n",
1860 " -p phone");
1861 FPS "%-20s \n"
1862 "%-20s Specify the hash algorithm to use. Possible keywords:\n"
1863 "%-20s \"MD2\", \"MD4\", \"MD5\", \"SHA1\", \"SHA224\",\n"
1864 "%-20s \"SHA256\", \"SHA384\", \"SHA512\"\n",
1865 " -Z hashAlg", "", "", "");
1866 FPS "%-20s Create key usage extension\n",
1867 " -1 ");
1868 FPS "%-20s Create basic constraint extension\n",
1869 " -2 ");
1870 FPS "%-20s Create authority key ID extension\n",
1871 " -3 ");
1872 FPS "%-20s Create crl distribution point extension\n",
1873 " -4 ");
1874 FPS "%-20s Create netscape cert type extension\n",
1875 " -5 ");
1876 FPS "%-20s Create extended key usage extension\n",
1877 " -6 ");
1878 FPS "%-20s Create an email subject alt name extension\n",
1879 " -7 emailAddrs ");
1880 FPS "%-20s Create a DNS subject alt name extension\n",
1881 " -8 DNS-names");
1882 FPS "%-20s Create an Authority Information Access extension\n",
1883 " --extAIA ");
1884 FPS "%-20s Create a Subject Information Access extension\n",
1885 " --extSIA ");
1886 FPS "%-20s Create a Certificate Policies extension\n",
1887 " --extCP ");
1888 FPS "%-20s Create a Policy Mappings extension\n",
1889 " --extPM ");
1890 FPS "%-20s Create a Policy Constraints extension\n",
1891 " --extPC ");
1892 FPS "%-20s Create an Inhibit Any Policy extension\n",
1893 " --extIA ");
1894 FPS "%-20s Create a subject key ID extension\n",
1895 " --extSKID ");
1896 FPS "%-20s \n",
1897 " See -G for available key flag options");
1898 FPS "%-20s Create a name constraints extension\n",
1899 " --extNC ");
1900 FPS "%-20s \n"
1901 "%-20s Create a Subject Alt Name extension with one or multiple names\n",
1902 " --extSAN type:name[,type:name]...", "");
1903 FPS "%-20s - type: directory, dn, dns, edi, ediparty, email, ip, ipaddr,\n", "");
1904 FPS "%-20s other, registerid, rfc822, uri, x400, x400addr\n", "");
1905 FPS "%-20s \n"
1906 "%-20s Add one or multiple extensions that certutil cannot encode yet,\n"
1907 "%-20s by loading their encodings from external files.\n",
1908 " --extGeneric OID:critical-flag:filename[,OID:critical-flag:filename]...", "", "");
1909 FPS "%-20s - OID (example): 1.2.3.4\n", "");
1910 FPS "%-20s - critical-flag: critical or not-critical\n", "");
1911 FPS "%-20s - filename: full path to a file containing an encoded extension\n", "");
1912 FPS "\n");
1913}
1914
1915static void
1916luBuildFlags(enum usage_level ul, const char *command)
1917{
1918 int is_my_command = (command && 0 == strcmp(command, "build-flags"));
1919 if (ul == usage_all || !command || is_my_command)
1920 FPS "%-15s Print enabled build flags relevant for NSS test execution\n",
1921 "--build-flags");
1922 if (ul == usage_selected && !is_my_command)
1923 return;
1924 FPS "\n");
1925}
1926
1927static void
1928LongUsage(enum usage_level ul, const char *command)
1929{
1930 luA(ul, command);
1931 luB(ul, command);
1932 luE(ul, command);
1933 luC(ul, command);
1934 luG(ul, command);
1935 luD(ul, command);
1936 luRename(ul, command);
1937 luF(ul, command);
1938 luU(ul, command);
1939 luK(ul, command);
1940 luL(ul, command);
1941 luBuildFlags(ul, command);
1942 luM(ul, command);
1943 luN(ul, command);
1944 luT(ul, command);
1945 luO(ul, command);
1946 luR(ul, command);
1947 luV(ul, command);
1948 luW(ul, command);
1949 luUpgradeMerge(ul, command);
1950 luMerge(ul, command);
1951 luS(ul, command);
1952#undef FPS
1953}
1954
1955static void
1956Usage()
1957{
1958 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
1959 "%s - Utility to manipulate NSS certificate databases\n\n"
1960 "Usage: %s <command> -d <database-directory> <options>\n\n"
1961 "Valid commands:\n",
1962 progName, progName);
1963 LongUsage(usage_selected, NULL((void*)0));
1964 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "\n"
1965 "%s -H <command> : Print available options for the given command\n"
1966 "%s -H : Print complete help output of all commands and options\n"
1967 "%s --syntax : Print a short summary of all commands and options\n",
1968 progName, progName, progName);
1969 exit(1);
1970}
1971
1972static CERTCertificate *
1973MakeV1Cert(CERTCertDBHandle *handle,
1974 CERTCertificateRequest *req,
1975 char *issuerNickName,
1976 PRBool selfsign,
1977 unsigned int serialNumber,
1978 int warpmonths,
1979 int validityMonths)
1980{
1981 CERTCertificate *issuerCert = NULL((void*)0);
1982 CERTValidity *validity;
1983 CERTCertificate *cert = NULL((void*)0);
1984 PRExplodedTime printableTime;
1985 PRTime now, after;
1986
1987 if (!selfsign) {
1988 issuerCert = CERT_FindCertByNicknameOrEmailAddr(handle, issuerNickName);
1989 if (!issuerCert) {
1990 SECU_PrintError(progName, "could not find certificate named \"%s\"",
1991 issuerNickName);
1992 return NULL((void*)0);
1993 }
1994 }
1995
1996 now = PR_Now();
1997 PR_ExplodeTime(now, PR_GMTParameters, &printableTime);
1998 if (warpmonths) {
1999 printableTime.tm_month += warpmonths;
2000 now = PR_ImplodeTime(&printableTime);
2001 PR_ExplodeTime(now, PR_GMTParameters, &printableTime);
2002 }
2003 printableTime.tm_month += validityMonths;
2004 after = PR_ImplodeTime(&printableTime);
2005
2006 /* note that the time is now in micro-second unit */
2007 validity = CERT_CreateValidity(now, after);
2008 if (validity) {
2009 cert = CERT_CreateCertificate(serialNumber,
2010 (selfsign ? &req->subject
2011 : &issuerCert->subject),
2012 validity, req);
2013
2014 CERT_DestroyValidity(validity);
2015 }
2016 if (issuerCert) {
2017 CERT_DestroyCertificate(issuerCert);
2018 }
2019
2020 return (cert);
2021}
2022
2023static SECStatus
2024SetSignatureAlgorithm(PLArenaPool *arena,
2025 SECAlgorithmID *signAlg,
2026 SECAlgorithmID *spkiAlg,
2027 SECOidTag hashAlgTag,
2028 SECKEYPrivateKey *privKey,
2029 PRBool pssSign)
2030{
2031 SECOidTag signAlgTag = SEC_OID_UNKNOWN;
2032 SECItem *params = NULL((void*)0);
2033
2034 if (pssSign) {
2035 signAlgTag = SEC_OID_PKCS1_RSA_PSS_SIGNATURE;
2036 }
2037 if (SECOID_GetAlgorithmTagSECOID_GetAlgorithmTag_Util(spkiAlg) == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
2038 signAlgTag = SEC_OID_PKCS1_RSA_PSS_SIGNATURE;
2039 params = &spkiAlg->parameters;
2040 }
2041 return SEC_CreateSignatureAlgorithmID(arena, signAlg, signAlgTag,
2042 hashAlgTag, params, privKey, NULL((void*)0));
2043}
2044
2045static SECStatus
2046SignCert(CERTCertDBHandle *handle, CERTCertificate *cert, PRBool selfsign,
2047 SECOidTag hashAlgTag,
2048 SECKEYPrivateKey *privKey, char *issuerNickName,
2049 int certVersion, PRBool pssSign, void *pwarg)
2050{
2051 SECItem der;
2052 SECKEYPrivateKey *caPrivateKey = NULL((void*)0);
2053 SECStatus rv;
2054 PLArenaPool *arena;
2055 CERTCertificate *issuer;
2056 void *dummy;
2057
2058 arena = cert->arena;
2059
2060 if (selfsign) {
2061 issuer = cert;
2062 } else {
2063 issuer = PK11_FindCertFromNickname(issuerNickName, pwarg);
2064 if ((CERTCertificate *)NULL((void*)0) == issuer) {
2065 SECU_PrintError(progName, "unable to find issuer with nickname %s",
2066 issuerNickName);
2067 rv = SECFailure;
2068 goto done;
2069 }
2070 privKey = caPrivateKey = PK11_FindKeyByAnyCert(issuer, pwarg);
2071 if (caPrivateKey == NULL((void*)0)) {
2072 SECU_PrintError(progName, "unable to retrieve key %s", issuerNickName);
2073 rv = SECFailure;
2074 CERT_DestroyCertificate(issuer);
2075 goto done;
2076 }
2077 }
2078
2079 if (pssSign &&
2080 (SECKEY_GetPrivateKeyType(privKey) != rsaKey &&
2081 SECKEY_GetPrivateKeyType(privKey) != rsaPssKey)) {
2082 SECU_PrintError(progName, "unable to create RSA-PSS signature with key %s",
2083 issuerNickName);
2084 rv = SECFailure;
2085 if (!selfsign) {
2086 CERT_DestroyCertificate(issuer);
2087 }
2088 goto done;
2089 }
2090
2091 rv = SetSignatureAlgorithm(arena,
2092 &cert->signature,
2093 &issuer->subjectPublicKeyInfo.algorithm,
2094 hashAlgTag,
2095 privKey,
2096 pssSign);
2097 if (!selfsign) {
2098 CERT_DestroyCertificate(issuer);
2099 }
2100 if (rv != SECSuccess) {
2101 goto done;
2102 }
2103
2104 switch (certVersion) {
2105 case (SEC_CERTIFICATE_VERSION_10):
2106 /* The initial version for x509 certificates is version one
2107 * and this default value must be an implicit DER encoding. */
2108 cert->version.data = NULL((void*)0);
2109 cert->version.len = 0;
2110 break;
2111 case (SEC_CERTIFICATE_VERSION_21):
2112 case (SEC_CERTIFICATE_VERSION_32):
2113 case 3: /* unspecified format (would be version 4 certificate). */
2114 *(cert->version.data) = certVersion;
2115 cert->version.len = 1;
2116 break;
2117 default:
2118 PORT_SetErrorPORT_SetError_Util(SEC_ERROR_INVALID_ARGS);
2119 rv = SECFailure;
2120 goto done;
2121 }
2122
2123 der.len = 0;
2124 der.data = NULL((void*)0);
2125 dummy = SEC_ASN1EncodeItemSEC_ASN1EncodeItem_Util(arena, &der, cert,
2126 SEC_ASN1_GET(CERT_CertificateTemplate)CERT_CertificateTemplate);
2127 if (!dummy) {
2128 fprintf(stderrstderr, "Could not encode certificate.\n");
2129 rv = SECFailure;
2130 goto done;
2131 }
2132
2133 rv = SEC_DerSignDataWithAlgorithmID(arena, &cert->derCert, der.data, der.len,
2134 privKey, &cert->signature);
2135 if (rv != SECSuccess) {
2136 fprintf(stderrstderr, "Could not sign encoded certificate data.\n");
2137 /* result allocated out of the arena, it will be freed
2138 * when the arena is freed */
2139 goto done;
2140 }
2141done:
2142 if (caPrivateKey) {
2143 SECKEY_DestroyPrivateKey(caPrivateKey);
2144 }
2145 return rv;
2146}
2147
2148static SECStatus
2149CreateCert(
2150 CERTCertDBHandle *handle,
2151 PK11SlotInfo *slot,
2152 char *issuerNickName,
2153 const SECItem *certReqDER,
2154 SECKEYPrivateKey **selfsignprivkey,
2155 void *pwarg,
2156 SECOidTag hashAlgTag,
2157 unsigned int serialNumber,
2158 int warpmonths,
2159 int validityMonths,
2160 const char *emailAddrs,
2161 const char *dnsNames,
2162 PRBool ascii,
2163 PRBool selfsign,
2164 certutilExtnList extnList,
2165 const char *extGeneric,
2166 int certVersion,
2167 PRBool pssSign,
2168 SECItem *certDER)
2169{
2170 void *extHandle = NULL((void*)0);
2171 CERTCertificate *subjectCert = NULL((void*)0);
2172 CERTCertificateRequest *certReq = NULL((void*)0);
2173 SECStatus rv = SECSuccess;
2174 CERTCertExtension **CRexts;
2175
2176 do {
2177 /* Create a certrequest object from the input cert request der */
2178 certReq = GetCertRequest(certReqDER, pwarg);
2179 if (certReq == NULL((void*)0)) {
2180 GEN_BREAK(SECFailure)rv = SECFailure; break;
2181 }
2182
2183 subjectCert = MakeV1Cert(handle, certReq, issuerNickName, selfsign,
2184 serialNumber, warpmonths, validityMonths);
2185 if (subjectCert == NULL((void*)0)) {
2186 GEN_BREAK(SECFailure)rv = SECFailure; break;
2187 }
2188
2189 extHandle = CERT_StartCertExtensions(subjectCert);
2190 if (extHandle == NULL((void*)0)) {
2191 GEN_BREAK(SECFailure)rv = SECFailure; break;
2192 }
2193
2194 rv = AddExtensions(extHandle, emailAddrs, dnsNames, extnList, extGeneric);
2195 if (rv != SECSuccess) {
2196 GEN_BREAK(SECFailure)rv = SECFailure; break;
2197 }
2198
2199 if (certReq->attributes != NULL((void*)0) &&
2200 certReq->attributes[0] != NULL((void*)0) &&
2201 certReq->attributes[0]->attrType.data != NULL((void*)0) &&
2202 certReq->attributes[0]->attrType.len > 0 &&
2203 SECOID_FindOIDTagSECOID_FindOIDTag_Util(&certReq->attributes[0]->attrType) ==
2204 SEC_OID_PKCS9_EXTENSION_REQUEST) {
2205 rv = CERT_GetCertificateRequestExtensions(certReq, &CRexts);
2206 if (rv != SECSuccess)
2207 break;
2208 rv = CERT_MergeExtensions(extHandle, CRexts);
2209 if (rv != SECSuccess)
2210 break;
2211 }
2212
2213 CERT_FinishExtensions(extHandle);
2214 extHandle = NULL((void*)0);
2215
2216 /* self-signing a cert request, find the private key */
2217 if (selfsign && *selfsignprivkey == NULL((void*)0)) {
2218 *selfsignprivkey = PK11_FindKeyByDERCert(slot, subjectCert, pwarg);
2219 if (!*selfsignprivkey) {
2220 fprintf(stderrstderr, "Failed to locate private key.\n");
2221 rv = SECFailure;
2222 break;
2223 }
2224 }
2225
2226 rv = SignCert(handle, subjectCert, selfsign, hashAlgTag,
2227 *selfsignprivkey, issuerNickName,
2228 certVersion, pssSign, pwarg);
2229 if (rv != SECSuccess)
2230 break;
2231
2232 rv = SECFailure;
2233 if (ascii) {
2234 char *asciiDER = BTOA_DataToAsciiBTOA_DataToAscii_Util(subjectCert->derCert.data,
2235 subjectCert->derCert.len);
2236 if (asciiDER) {
2237 char *wrapped = PR_smprintf("%s\n%s\n%s\n",
2238 NS_CERT_HEADER"-----BEGIN CERTIFICATE-----",
2239 asciiDER,
2240 NS_CERT_TRAILER"-----END CERTIFICATE-----");
2241 if (wrapped) {
2242 PRUint32 wrappedLen = PL_strlen(wrapped);
2243 if (SECITEM_AllocItemSECITEM_AllocItem_Util(NULL((void*)0), certDER, wrappedLen)) {
2244 PORT_Memcpymemcpy(certDER->data, wrapped, wrappedLen);
2245 rv = SECSuccess;
2246 }
2247 PR_smprintf_free(wrapped);
2248 }
2249 PORT_FreePORT_Free_Util(asciiDER);
2250 }
2251 } else {
2252 rv = SECITEM_CopyItemSECITEM_CopyItem_Util(NULL((void*)0), certDER, &subjectCert->derCert);
2253 }
2254 } while (0);
2255 if (extHandle) {
2256 CERT_FinishExtensions(extHandle);
2257 }
2258 CERT_DestroyCertificateRequest(certReq);
2259 CERT_DestroyCertificate(subjectCert);
2260 if (rv != SECSuccess) {
2261 PRErrorCode perr = PR_GetError();
2262 fprintf(stderrstderr, "%s: unable to create cert (%s)\n", progName,
2263 SECU_Strerror(perr)PR_ErrorToString((perr), 0));
2264 }
2265 return (rv);
2266}
2267
2268/*
2269 * map a class to a user presentable string
2270 */
2271static const char *objClassArray[] = {
2272 "Data",
2273 "Certificate",
2274 "Public Key",
2275 "Private Key",
2276 "Secret Key",
2277 "Hardware Feature",
2278 "Domain Parameters",
2279 "Mechanism"
2280};
2281
2282static const char *objNSSClassArray[] = {
2283 "CKO_NSS",
2284 "Crl",
2285 "SMIME Record",
2286 "Trust",
2287 "Builtin Root List"
2288};
2289
2290const char *
2291getObjectClass(CK_ULONG classType)
2292{
2293 static char buf[sizeof(CK_ULONG) * 2 + 3];
2294
2295 if (classType <= CKO_MECHANISM0x00000007UL) {
2296 return objClassArray[classType];
2297 }
2298 if (classType >= CKO_NSS(0x80000000UL | 0x4E534350) && classType <= CKO_NSS_BUILTIN_ROOT_LIST((0x80000000UL | 0x4E534350) + 4)) {
2299 return objNSSClassArray[classType - CKO_NSS(0x80000000UL | 0x4E534350)];
2300 }
2301 snprintf(buf, sizeof(buf), "0x%lx", classType);
2302 return buf;
2303}
2304
2305typedef struct {
2306 char *name;
2307 int nameSize;
2308 CK_ULONG value;
2309} flagArray;
2310
2311#define NAME_SIZE(x)"x", sizeof("x") - 1 #x, sizeof(#x) - 1
2312
2313flagArray opFlagsArray[] = {
2314 { NAME_SIZE(encrypt)"encrypt", sizeof("encrypt") - 1, CKF_ENCRYPT0x00000100UL },
2315 { NAME_SIZE(decrypt)"decrypt", sizeof("decrypt") - 1, CKF_DECRYPT0x00000200UL },
2316 { NAME_SIZE(sign)"sign", sizeof("sign") - 1, CKF_SIGN0x00000800UL },
2317 { NAME_SIZE(sign_recover)"sign_recover", sizeof("sign_recover") - 1, CKF_SIGN_RECOVER0x00001000UL },
2318 { NAME_SIZE(verify)"verify", sizeof("verify") - 1, CKF_VERIFY0x00002000 },
2319 { NAME_SIZE(verify_recover)"verify_recover", sizeof("verify_recover") - 1, CKF_VERIFY_RECOVER0x00004000UL },
2320 { NAME_SIZE(wrap)"wrap", sizeof("wrap") - 1, CKF_WRAP0x00020000UL },
2321 { NAME_SIZE(unwrap)"unwrap", sizeof("unwrap") - 1, CKF_UNWRAP0x00040000UL },
2322 { NAME_SIZE(derive)"derive", sizeof("derive") - 1, CKF_DERIVE0x00080000UL }
2323};
2324
2325int opFlagsCount = PR_ARRAY_SIZE(opFlagsArray)(sizeof(opFlagsArray) / sizeof((opFlagsArray)[0]));
2326
2327flagArray attrFlagsArray[] = {
2328 { NAME_SIZE(token)"token", sizeof("token") - 1, PK11_ATTR_TOKEN0x00000001L },
2329 { NAME_SIZE(session)"session", sizeof("session") - 1, PK11_ATTR_SESSION0x00000002L },
2330 { NAME_SIZE(private)"private", sizeof("private") - 1, PK11_ATTR_PRIVATE0x00000004L },
2331 { NAME_SIZE(public)"public", sizeof("public") - 1, PK11_ATTR_PUBLIC0x00000008L },
2332 { NAME_SIZE(modifiable)"modifiable", sizeof("modifiable") - 1, PK11_ATTR_MODIFIABLE0x00000010L },
2333 { NAME_SIZE(unmodifiable)"unmodifiable", sizeof("unmodifiable") - 1, PK11_ATTR_UNMODIFIABLE0x00000020L },
2334 { NAME_SIZE(sensitive)"sensitive", sizeof("sensitive") - 1, PK11_ATTR_SENSITIVE0x00000040L },
2335 { NAME_SIZE(insensitive)"insensitive", sizeof("insensitive") - 1, PK11_ATTR_INSENSITIVE0x00000080L },
2336 { NAME_SIZE(extractable)"extractable", sizeof("extractable") - 1, PK11_ATTR_EXTRACTABLE0x00000100L },
2337 { NAME_SIZE(unextractable)"unextractable", sizeof("unextractable") - 1, PK11_ATTR_UNEXTRACTABLE0x00000200L }
2338};
2339
2340int attrFlagsCount = PR_ARRAY_SIZE(attrFlagsArray)(sizeof(attrFlagsArray) / sizeof((attrFlagsArray)[0]));
2341
2342#define MAX_STRING30 30
2343CK_ULONG
2344GetFlags(char *flagsString, flagArray *flags, int count)
2345{
2346 CK_ULONG flagsValue = strtol(flagsString, NULL((void*)0), 0);
2347 int i;
2348
2349 if ((flagsValue != 0) || (*flagsString == 0)) {
2350 return flagsValue;
2351 }
2352 while (*flagsString) {
2353 for (i = 0; i < count; i++) {
2354 if (strncmp(flagsString, flags[i].name, flags[i].nameSize) ==
2355 0) {
2356 flagsValue |= flags[i].value;
2357 flagsString += flags[i].nameSize;
2358 if (*flagsString != 0) {
2359 flagsString++;
2360 }
2361 break;
2362 }
2363 }
2364 if (i == count) {
2365 char name[MAX_STRING30];
2366 char *tok;
2367
2368 strncpy(name, flagsString, MAX_STRING30);
2369 name[MAX_STRING30 - 1] = 0;
2370 tok = strchr(name, ',');
2371 if (tok) {
2372 *tok = 0;
2373 }
2374 fprintf(stderrstderr, "Unknown flag (%s)\n", name);
2375 tok = strchr(flagsString, ',');
2376 if (tok == NULL((void*)0)) {
2377 break;
2378 }
2379 flagsString = tok + 1;
2380 }
2381 }
2382 return flagsValue;
2383}
2384
2385CK_FLAGS
2386GetOpFlags(char *flags)
2387{
2388 return GetFlags(flags, opFlagsArray, opFlagsCount);
2389}
2390
2391PK11AttrFlags
2392GetAttrFlags(char *flags)
2393{
2394 return GetFlags(flags, attrFlagsArray, attrFlagsCount);
2395}
2396
2397char *
2398mkNickname(unsigned char *data, int len)
2399{
2400 char *nick = PORT_AllocPORT_Alloc_Util(len + 1);
2401 if (!nick) {
2402 return nick;
2403 }
2404 PORT_Memcpymemcpy(nick, data, len);
2405 nick[len] = 0;
2406 return nick;
2407}
2408
2409/*
2410 * dump a PK11_MergeTokens error log to the console
2411 */
2412void
2413DumpMergeLog(const char *progname, PK11MergeLog *log)
2414{
2415 PK11MergeLogNode *node;
2416
2417 for (node = log->head; node; node = node->next) {
2418 SECItem attrItem;
2419 char *nickname = NULL((void*)0);
2420 const char *objectClass = NULL((void*)0);
2421 SECStatus rv;
2422
2423 attrItem.data = NULL((void*)0);
2424 rv = PK11_ReadRawAttribute(PK11_TypeGeneric, node->object,
2425 CKA_LABEL0x00000003UL, &attrItem);
2426 if (rv == SECSuccess) {
2427 nickname = mkNickname(attrItem.data, attrItem.len);
2428 PORT_FreePORT_Free_Util(attrItem.data);
2429 }
2430 attrItem.data = NULL((void*)0);
2431 rv = PK11_ReadRawAttribute(PK11_TypeGeneric, node->object,
2432 CKA_CLASS0x00000000UL, &attrItem);
2433 if (rv == SECSuccess) {
2434 if (attrItem.len == sizeof(CK_ULONG)) {
2435 objectClass = getObjectClass(*(CK_ULONG *)attrItem.data);
2436 }
2437 PORT_FreePORT_Free_Util(attrItem.data);
2438 }
2439
2440 fprintf(stderrstderr, "%s: Could not merge object %s (type %s): %s\n",
2441 progName,
2442 nickname ? nickname : "unnamed",
2443 objectClass ? objectClass : "unknown",
2444 SECU_Strerror(node->error)PR_ErrorToString((node->error), 0));
2445
2446 if (nickname) {
2447 PORT_FreePORT_Free_Util(nickname);
2448 }
2449 }
2450}
2451
2452/* Certutil commands */
2453enum {
2454 cmd_AddCert = 0,
2455 cmd_CreateNewCert,
2456 cmd_DeleteCert,
2457 cmd_AddEmailCert,
2458 cmd_DeleteKey,
2459 cmd_GenKeyPair,
2460 cmd_PrintHelp,
2461 cmd_PrintSyntax,
2462 cmd_ListKeys,
2463 cmd_ListCerts,
2464 cmd_ModifyCertTrust,
2465 cmd_NewDBs,
2466 cmd_DumpChain,
2467 cmd_CertReq,
2468 cmd_CreateAndAddCert,
2469 cmd_TokenReset,
2470 cmd_ListModules,
2471 cmd_CheckCertValidity,
2472 cmd_ChangePassword,
2473 cmd_Version,
2474 cmd_Batch,
2475 cmd_Merge,
2476 cmd_UpgradeMerge, /* test only */
2477 cmd_Rename,
2478 cmd_BuildFlags,
2479 max_cmd
2480};
2481
2482/* Certutil options */
2483enum certutilOpts {
2484 opt_SSOPass = 0,
2485 opt_AddKeyUsageExt,
2486 opt_AddBasicConstraintExt,
2487 opt_AddAuthorityKeyIDExt,
2488 opt_AddCRLDistPtsExt,
2489 opt_AddNSCertTypeExt,
2490 opt_AddExtKeyUsageExt,
2491 opt_ExtendedEmailAddrs,
2492 opt_ExtendedDNSNames,
2493 opt_ASCIIForIO,
2494 opt_ValidityTime,
2495 opt_IssuerName,
2496 opt_CertDir,
2497 opt_VerifySig,
2498 opt_PasswordFile,
2499 opt_KeySize,
2500 opt_TokenName,
2501 opt_InputFile,
2502 opt_Emailaddress,
2503 opt_KeyIndex,
2504 opt_KeyType,
2505 opt_DetailedInfo,
2506 opt_SerialNumber,
2507 opt_Nickname,
2508 opt_OutputFile,
2509 opt_PhoneNumber,
2510 opt_DBPrefix,
2511 opt_PQGFile,
2512 opt_BinaryDER,
2513 opt_Subject,
2514 opt_Trust,
2515 opt_Usage,
2516 opt_Validity,
2517 opt_OffsetMonths,
2518 opt_SelfSign,
2519 opt_RW,
2520 opt_Exponent,
2521 opt_NoiseFile,
2522 opt_Hash,
2523 opt_NewPasswordFile,
2524 opt_AddAuthInfoAccExt,
2525 opt_AddSubjInfoAccExt,
2526 opt_AddCertPoliciesExt,
2527 opt_AddPolicyMapExt,
2528 opt_AddPolicyConstrExt,
2529 opt_AddInhibAnyExt,
2530 opt_AddNameConstraintsExt,
2531 opt_AddSubjectKeyIDExt,
2532 opt_AddCmdKeyUsageExt,
2533 opt_AddCmdNSCertTypeExt,
2534 opt_AddCmdExtKeyUsageExt,
2535 opt_SourceDir,
2536 opt_SourcePrefix,
2537 opt_UpgradeID,
2538 opt_UpgradeTokenName,
2539 opt_KeyOpFlagsOn,
2540 opt_KeyOpFlagsOff,
2541 opt_KeyAttrFlags,
2542 opt_EmptyPassword,
2543 opt_CertVersion,
2544 opt_AddSubjectAltNameExt,
2545 opt_DumpExtensionValue,
2546 opt_GenericExtensions,
2547 opt_NewNickname,
2548 opt_Pss,
2549 opt_PssSign,
2550 opt_SimpleSelfSigned,
2551 opt_Help
2552};
2553
2554static const secuCommandFlag commands_init[] = {
2555 { /* cmd_AddCert */ 'A', PR_FALSE0, 0, PR_FALSE0 },
2556 { /* cmd_CreateNewCert */ 'C', PR_FALSE0, 0, PR_FALSE0 },
2557 { /* cmd_DeleteCert */ 'D', PR_FALSE0, 0, PR_FALSE0 },
2558 { /* cmd_AddEmailCert */ 'E', PR_FALSE0, 0, PR_FALSE0 },
2559 { /* cmd_DeleteKey */ 'F', PR_FALSE0, 0, PR_FALSE0 },
2560 { /* cmd_GenKeyPair */ 'G', PR_FALSE0, 0, PR_FALSE0 },
2561 { /* cmd_PrintHelp */ 'H', PR_FALSE0, 0, PR_FALSE0, "help" },
2562 { /* cmd_PrintSyntax */ 0, PR_FALSE0, 0, PR_FALSE0,
2563 "syntax" },
2564 { /* cmd_ListKeys */ 'K', PR_FALSE0, 0, PR_FALSE0 },
2565 { /* cmd_ListCerts */ 'L', PR_FALSE0, 0, PR_FALSE0 },
2566 { /* cmd_ModifyCertTrust */ 'M', PR_FALSE0, 0, PR_FALSE0 },
2567 { /* cmd_NewDBs */ 'N', PR_FALSE0, 0, PR_FALSE0 },
2568 { /* cmd_DumpChain */ 'O', PR_FALSE0, 0, PR_FALSE0 },
2569 { /* cmd_CertReq */ 'R', PR_FALSE0, 0, PR_FALSE0 },
2570 { /* cmd_CreateAndAddCert */ 'S', PR_FALSE0, 0, PR_FALSE0 },
2571 { /* cmd_TokenReset */ 'T', PR_FALSE0, 0, PR_FALSE0 },
2572 { /* cmd_ListModules */ 'U', PR_FALSE0, 0, PR_FALSE0 },
2573 { /* cmd_CheckCertValidity */ 'V', PR_FALSE0, 0, PR_FALSE0 },
2574 { /* cmd_ChangePassword */ 'W', PR_FALSE0, 0, PR_FALSE0 },
2575 { /* cmd_Version */ 'Y', PR_FALSE0, 0, PR_FALSE0 },
2576 { /* cmd_Batch */ 'B', PR_FALSE0, 0, PR_FALSE0 },
2577 { /* cmd_Merge */ 0, PR_FALSE0, 0, PR_FALSE0, "merge" },
2578 { /* cmd_UpgradeMerge */ 0, PR_FALSE0, 0, PR_FALSE0,
2579 "upgrade-merge" },
2580 { /* cmd_Rename */ 0, PR_FALSE0, 0, PR_FALSE0,
2581 "rename" },
2582 { /* cmd_BuildFlags */ 0, PR_FALSE0, 0, PR_FALSE0,
2583 "build-flags" }
2584};
2585#define NUM_COMMANDS((sizeof commands_init) / (sizeof commands_init[0])) ((sizeof commands_init) / (sizeof commands_init[0]))
2586
2587static const secuCommandFlag options_init[] = {
2588 { /* opt_SSOPass */ '0', PR_TRUE1, 0, PR_FALSE0 },
2589 { /* opt_AddKeyUsageExt */ '1', PR_FALSE0, 0, PR_FALSE0 },
2590 { /* opt_AddBasicConstraintExt*/ '2', PR_FALSE0, 0, PR_FALSE0 },
2591 { /* opt_AddAuthorityKeyIDExt*/ '3', PR_FALSE0, 0, PR_FALSE0 },
2592 { /* opt_AddCRLDistPtsExt */ '4', PR_FALSE0, 0, PR_FALSE0 },
2593 { /* opt_AddNSCertTypeExt */ '5', PR_FALSE0, 0, PR_FALSE0 },
2594 { /* opt_AddExtKeyUsageExt */ '6', PR_FALSE0, 0, PR_FALSE0 },
2595 { /* opt_ExtendedEmailAddrs */ '7', PR_TRUE1, 0, PR_FALSE0 },
2596 { /* opt_ExtendedDNSNames */ '8', PR_TRUE1, 0, PR_FALSE0 },
2597 { /* opt_ASCIIForIO */ 'a', PR_FALSE0, 0, PR_FALSE0 },
2598 { /* opt_ValidityTime */ 'b', PR_TRUE1, 0, PR_FALSE0 },
2599 { /* opt_IssuerName */ 'c', PR_TRUE1, 0, PR_FALSE0 },
2600 { /* opt_CertDir */ 'd', PR_TRUE1, 0, PR_FALSE0 },
2601 { /* opt_VerifySig */ 'e', PR_FALSE0, 0, PR_FALSE0 },
2602 { /* opt_PasswordFile */ 'f', PR_TRUE1, 0, PR_FALSE0 },
2603 { /* opt_KeySize */ 'g', PR_TRUE1, 0, PR_FALSE0 },
2604 { /* opt_TokenName */ 'h', PR_TRUE1, 0, PR_FALSE0 },
2605 { /* opt_InputFile */ 'i', PR_TRUE1, 0, PR_FALSE0 },
2606 { /* opt_Emailaddress */ 0, PR_TRUE1, 0, PR_FALSE0, "email" },
2607 { /* opt_KeyIndex */ 'j', PR_TRUE1, 0, PR_FALSE0 },
2608 { /* opt_KeyType */ 'k', PR_TRUE1, 0, PR_FALSE0 },
2609 { /* opt_DetailedInfo */ 'l', PR_FALSE0, 0, PR_FALSE0 },
2610 { /* opt_SerialNumber */ 'm', PR_TRUE1, 0, PR_FALSE0 },
2611 { /* opt_Nickname */ 'n', PR_TRUE1, 0, PR_FALSE0 },
2612 { /* opt_OutputFile */ 'o', PR_TRUE1, 0, PR_FALSE0 },
2613 { /* opt_PhoneNumber */ 'p', PR_TRUE1, 0, PR_FALSE0 },
2614 { /* opt_DBPrefix */ 'P', PR_TRUE1, 0, PR_FALSE0 },
2615 { /* opt_PQGFile */ 'q', PR_TRUE1, 0, PR_FALSE0 },
2616 { /* opt_BinaryDER */ 'r', PR_FALSE0, 0, PR_FALSE0 },
2617 { /* opt_Subject */ 's', PR_TRUE1, 0, PR_FALSE0 },
2618 { /* opt_Trust */ 't', PR_TRUE1, 0, PR_FALSE0 },
2619 { /* opt_Usage */ 'u', PR_TRUE1, 0, PR_FALSE0 },
2620 { /* opt_Validity */ 'v', PR_TRUE1, 0, PR_FALSE0 },
2621 { /* opt_OffsetMonths */ 'w', PR_TRUE1, 0, PR_FALSE0 },
2622 { /* opt_SelfSign */ 'x', PR_FALSE0, 0, PR_FALSE0 },
2623 { /* opt_RW */ 'X', PR_FALSE0, 0, PR_FALSE0 },
2624 { /* opt_Exponent */ 'y', PR_TRUE1, 0, PR_FALSE0 },
2625 { /* opt_NoiseFile */ 'z', PR_TRUE1, 0, PR_FALSE0 },
2626 { /* opt_Hash */ 'Z', PR_TRUE1, 0, PR_FALSE0 },
2627 { /* opt_NewPasswordFile */ '@', PR_TRUE1, 0, PR_FALSE0 },
2628 { /* opt_AddAuthInfoAccExt */ 0, PR_FALSE0, 0, PR_FALSE0, "extAIA" },
2629 { /* opt_AddSubjInfoAccExt */ 0, PR_FALSE0, 0, PR_FALSE0, "extSIA" },
2630 { /* opt_AddCertPoliciesExt */ 0, PR_FALSE0, 0, PR_FALSE0, "extCP" },
2631 { /* opt_AddPolicyMapExt */ 0, PR_FALSE0, 0, PR_FALSE0, "extPM" },
2632 { /* opt_AddPolicyConstrExt */ 0, PR_FALSE0, 0, PR_FALSE0, "extPC" },
2633 { /* opt_AddInhibAnyExt */ 0, PR_FALSE0, 0, PR_FALSE0, "extIA" },
2634 { /* opt_AddNameConstraintsExt*/ 0, PR_FALSE0, 0, PR_FALSE0, "extNC" },
2635 { /* opt_AddSubjectKeyIDExt */ 0, PR_FALSE0, 0, PR_FALSE0,
2636 "extSKID" },
2637 { /* opt_AddCmdKeyUsageExt */ 0, PR_TRUE1, 0, PR_FALSE0,
2638 "keyUsage" },
2639 { /* opt_AddCmdNSCertTypeExt */ 0, PR_TRUE1, 0, PR_FALSE0,
2640 "nsCertType" },
2641 { /* opt_AddCmdExtKeyUsageExt*/ 0, PR_TRUE1, 0, PR_FALSE0,
2642 "extKeyUsage" },
2643
2644 { /* opt_SourceDir */ 0, PR_TRUE1, 0, PR_FALSE0,
2645 "source-dir" },
2646 { /* opt_SourcePrefix */ 0, PR_TRUE1, 0, PR_FALSE0,
2647 "source-prefix" },
2648 { /* opt_UpgradeID */ 0, PR_TRUE1, 0, PR_FALSE0,
2649 "upgrade-id" },
2650 { /* opt_UpgradeTokenName */ 0, PR_TRUE1, 0, PR_FALSE0,
2651 "upgrade-token-name" },
2652 { /* opt_KeyOpFlagsOn */ 0, PR_TRUE1, 0, PR_FALSE0,
2653 "keyOpFlagsOn" },
2654 { /* opt_KeyOpFlagsOff */ 0, PR_TRUE1, 0, PR_FALSE0,
2655 "keyOpFlagsOff" },
2656 { /* opt_KeyAttrFlags */ 0, PR_TRUE1, 0, PR_FALSE0,
2657 "keyAttrFlags" },
2658 { /* opt_EmptyPassword */ 0, PR_FALSE0, 0, PR_FALSE0,
2659 "empty-password" },
2660 { /* opt_CertVersion */ 0, PR_TRUE1, 0, PR_FALSE0,
2661 "certVersion" },
2662 { /* opt_AddSubjectAltExt */ 0, PR_TRUE1, 0, PR_FALSE0, "extSAN" },
2663 { /* opt_DumpExtensionValue */ 0, PR_TRUE1, 0, PR_FALSE0,
2664 "dump-ext-val" },
2665 { /* opt_GenericExtensions */ 0, PR_TRUE1, 0, PR_FALSE0,
2666 "extGeneric" },
2667 { /* opt_NewNickname */ 0, PR_TRUE1, 0, PR_FALSE0,
2668 "new-n" },
2669 { /* opt_Pss */ 0, PR_FALSE0, 0, PR_FALSE0,
2670 "pss" },
2671 { /* opt_PssSign */ 0, PR_FALSE0, 0, PR_FALSE0,
2672 "pss-sign" },
2673 { /* opt_SimpleSelfSigned */ 0, PR_FALSE0, 0, PR_FALSE0,
2674 "simple-self-signed" },
2675};
2676#define NUM_OPTIONS((sizeof options_init) / (sizeof options_init[0])) ((sizeof options_init) / (sizeof options_init[0]))
2677
2678static secuCommandFlag certutil_commands[NUM_COMMANDS((sizeof commands_init) / (sizeof commands_init[0]))];
2679static secuCommandFlag certutil_options[NUM_OPTIONS((sizeof options_init) / (sizeof options_init[0]))];
2680
2681static const secuCommand certutil = {
2682 NUM_COMMANDS((sizeof commands_init) / (sizeof commands_init[0])),
2683 NUM_OPTIONS((sizeof options_init) / (sizeof options_init[0])),
2684 certutil_commands,
2685 certutil_options
2686};
2687
2688static certutilExtnList certutil_extns;
2689
2690static int
2691certutil_main(int argc, char **argv, PRBool initialize)
2692{
2693 CERTCertDBHandle *certHandle;
2694 PK11SlotInfo *slot = NULL((void*)0);
2695 CERTName *subject = 0;
2696 PRFileDesc *inFile = PR_STDINPR_GetSpecialFD(PR_StandardInput);
2697 PRFileDesc *outFile = PR_STDOUTPR_GetSpecialFD(PR_StandardOutput);
2698 SECItem certReqDER = { siBuffer, NULL((void*)0), 0 };
2699 SECItem certDER = { siBuffer, NULL((void*)0), 0 };
2700 const char *slotname = "internal";
2701 const char *certPrefix = "";
2702 char *sourceDir = "";
2703 const char *srcCertPrefix = "";
2704 char *upgradeID = "";
2705 char *upgradeTokenName = "";
2706 KeyType keytype = rsaKey;
2707 char *name = NULL((void*)0);
2708 char *newName = NULL((void*)0);
2709 char *email = NULL((void*)0);
2710 char *keysource = NULL((void*)0);
2711 SECOidTag hashAlgTag = SEC_OID_UNKNOWN;
2712 int keysize = DEFAULT_KEY_BITS2048;
2713 int publicExponent = 0x010001;
2714 int certVersion = SEC_CERTIFICATE_VERSION_32;
2715 unsigned int serialNumber = 0;
2716 int warpmonths = 0;
2717 int validityMonths = 3;
2718 int commandsEntered = 0;
2719 char commandToRun = '\0';
2720 secuPWData pwdata = { PW_NONE, 0 };
2721 secuPWData pwdata2 = { PW_NONE, 0 };
2722 PRBool readOnly = PR_FALSE0;
2723 PRBool initialized = PR_FALSE0;
2724 CK_FLAGS keyOpFlagsOn = 0;
2725 CK_FLAGS keyOpFlagsOff = 0;
2726 PK11AttrFlags keyAttrFlags =
2727 PK11_ATTR_TOKEN0x00000001L | PK11_ATTR_SENSITIVE0x00000040L | PK11_ATTR_PRIVATE0x00000004L;
2728
2729 SECKEYPrivateKey *privkey = NULL((void*)0);
2730 SECKEYPublicKey *pubkey = NULL((void*)0);
2731
2732 int i;
2733 SECStatus rv;
2734
2735 progName = PORT_Strrchrstrrchr(argv[0], '/');
2736 progName = progName ? progName + 1 : argv[0];
2737 memcpy(certutil_commands, commands_init, sizeof commands_init);
2738 memcpy(certutil_options, options_init, sizeof options_init);
2739
2740 rv = SECU_ParseCommandLine(argc, argv, progName, &certutil);
2741
2742 if (rv != SECSuccess)
2743 Usage();
2744
2745 if (certutil.commands[cmd_PrintSyntax].activated) {
2746 PrintSyntax();
2747 }
2748
2749 if (certutil.commands[cmd_PrintHelp].activated) {
2750 char buf[2];
2751 const char *command = NULL((void*)0);
2752 for (i = 0; i < max_cmd; i++) {
2753 if (i == cmd_PrintHelp)
2754 continue;
2755 if (certutil.commands[i].activated) {
2756 if (certutil.commands[i].flag) {
2757 buf[0] = certutil.commands[i].flag;
2758 buf[1] = 0;
2759 command = buf;
2760 } else {
2761 command = certutil.commands[i].longform;
2762 }
2763 break;
2764 }
2765 }
2766 LongUsage((command ? usage_selected : usage_all), command);
2767 exit(1);
2768 }
2769
2770 if (certutil.commands[cmd_BuildFlags].activated) {
2771 PrintBuildFlags();
2772 }
2773
2774 if (certutil.options[opt_PasswordFile].arg) {
2775 pwdata.source = PW_FROMFILE;
2776 pwdata.data = certutil.options[opt_PasswordFile].arg;
2777 }
2778 if (certutil.options[opt_NewPasswordFile].arg) {
2779 pwdata2.source = PW_FROMFILE;
2780 pwdata2.data = certutil.options[opt_NewPasswordFile].arg;
2781 }
2782
2783 if (certutil.options[opt_CertDir].activated)
2784 SECU_ConfigDirectory(certutil.options[opt_CertDir].arg);
2785
2786 if (certutil.options[opt_SourceDir].activated)
2787 sourceDir = certutil.options[opt_SourceDir].arg;
2788
2789 if (certutil.options[opt_UpgradeID].activated)
2790 upgradeID = certutil.options[opt_UpgradeID].arg;
2791
2792 if (certutil.options[opt_UpgradeTokenName].activated)
2793 upgradeTokenName = certutil.options[opt_UpgradeTokenName].arg;
2794
2795 /* must be before opt_KeySize! */
2796 /* -k key type */
2797 if (certutil.options[opt_KeyType].activated) {
2798 char *arg = certutil.options[opt_KeyType].arg;
2799 if (PL_strcmp(arg, "rsa") == 0) {
2800 keytype = rsaKey;
2801 } else if (PL_strcmp(arg, "dsa") == 0) {
2802 keytype = dsaKey;
2803 } else if (PL_strcmp(arg, "ec") == 0) {
2804 keytype = ecKey;
2805 } else if (PL_strcmp(arg, "mldsa") == 0) {
2806 keytype = mldsaKey;
2807 } else if (PL_strcmp(arg, "all") == 0) {
2808 keytype = nullKey;
2809 } else {
2810 /* use an existing private/public key pair */
2811 keysource = arg;
2812 }
2813 } else if (certutil.commands[cmd_ListKeys].activated) {
2814 keytype = nullKey;
2815 }
2816
2817 if (certutil.options[opt_KeySize].activated) {
2818 keysize = PORT_Atoi(certutil.options[opt_KeySize].arg)(int)strtol(certutil.options[opt_KeySize].arg, ((void*)0), 10
)
;
2819 /* mldsa limits are much different that rsa and dsa, don't
2820 * do the check here */
2821 if ((keytype != mldsaKey) &&
2822 ((keysize < MIN_KEY_BITS512) || (keysize > MAX_KEY_BITS8192))) {
2823 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
2824 "%s -g: Keysize must be between %d and %d.\n",
2825 progName, MIN_KEY_BITS512, MAX_KEY_BITS8192);
2826 return 255;
2827 }
2828 if (keytype == ecKey) {
2829 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s -g: Not for ec keys.\n", progName);
2830 return 255;
2831 }
2832 }
2833
2834 /* -h specify token name */
2835 if (certutil.options[opt_TokenName].activated) {
2836 if (PL_strcmp(certutil.options[opt_TokenName].arg, "all") == 0)
2837 slotname = NULL((void*)0);
2838 else
2839 slotname = certutil.options[opt_TokenName].arg;
2840 }
2841
2842 /* -Z hash type */
2843 if (certutil.options[opt_Hash].activated) {
2844 char *arg = certutil.options[opt_Hash].arg;
2845 hashAlgTag = SECU_StringToSignatureAlgTag(arg);
2846 if (hashAlgTag == SEC_OID_UNKNOWN) {
2847 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s -Z: %s is not a recognized type.\n",
2848 progName, arg);
2849 return 255;
2850 }
2851 }
2852
2853 if (certutil.options[opt_KeyOpFlagsOn].activated) {
2854 keyOpFlagsOn = GetOpFlags(certutil.options[opt_KeyOpFlagsOn].arg);
2855 }
2856 if (certutil.options[opt_KeyOpFlagsOff].activated) {
2857 keyOpFlagsOff = GetOpFlags(certutil.options[opt_KeyOpFlagsOff].arg);
2858 keyOpFlagsOn &= ~keyOpFlagsOff; /* make off override on */
2859 }
2860 if (certutil.options[opt_KeyAttrFlags].activated) {
2861 keyAttrFlags = GetAttrFlags(certutil.options[opt_KeyAttrFlags].arg);
2862 }
2863
2864 /* -m serial number */
2865 if (certutil.options[opt_SerialNumber].activated) {
2866 int sn = PORT_Atoi(certutil.options[opt_SerialNumber].arg)(int)strtol(certutil.options[opt_SerialNumber].arg, ((void*)0
), 10)
;
2867 if (sn < 0) {
2868 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s -m: %s is not a valid serial number.\n",
2869 progName, certutil.options[opt_SerialNumber].arg);
2870 return 255;
2871 }
2872 serialNumber = sn;
2873 }
2874
2875 /* -P certdb name prefix */
2876 if (certutil.options[opt_DBPrefix].activated) {
2877 if (certutil.options[opt_DBPrefix].arg) {
2878 certPrefix = certutil.options[opt_DBPrefix].arg;
2879 } else {
2880 Usage();
2881 }
2882 }
2883
2884 /* --source-prefix certdb name prefix */
2885 if (certutil.options[opt_SourcePrefix].activated) {
2886 if (certutil.options[opt_SourcePrefix].arg) {
2887 srcCertPrefix = certutil.options[opt_SourcePrefix].arg;
2888 } else {
2889 Usage();
2890 }
2891 }
2892
2893 /* -q PQG file or curve name */
2894 if (certutil.options[opt_PQGFile].activated) {
2895 if ((keytype != dsaKey) && (keytype != ecKey) &&
2896 (keytype != mldsaKey)) {
2897 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s -q: specifies a PQG file for DSA keys"
2898 " (-k dsa)\n"
2899 " or a named curve for EC keys (-k ec)\n"
2900 " or a parameter set for ML-DSA keys (-k mldsa)\n",
2901 progName);
2902 return 255;
2903 }
2904 }
2905
2906 /* -s subject name */
2907 if (certutil.options[opt_Subject].activated) {
2908 subject = CERT_AsciiToName(certutil.options[opt_Subject].arg);
2909 if (!subject) {
2910 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s -s: improperly formatted name: \"%s\"\n",
2911 progName, certutil.options[opt_Subject].arg);
2912 return 255;
2913 }
2914 }
2915
2916 /* -v validity period */
2917 if (certutil.options[opt_Validity].activated) {
2918 validityMonths = PORT_Atoi(certutil.options[opt_Validity].arg)(int)strtol(certutil.options[opt_Validity].arg, ((void*)0), 10
)
;
2919 if (validityMonths < 0) {
2920 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s -v: incorrect validity period: \"%s\"\n",
2921 progName, certutil.options[opt_Validity].arg);
2922 return 255;
2923 }
2924 }
2925
2926 /* -w warp months */
2927 if (certutil.options[opt_OffsetMonths].activated)
2928 warpmonths = PORT_Atoi(certutil.options[opt_OffsetMonths].arg)(int)strtol(certutil.options[opt_OffsetMonths].arg, ((void*)0
), 10)
;
2929
2930 /* -y public exponent (for RSA) */
2931 if (certutil.options[opt_Exponent].activated) {
2932 publicExponent = PORT_Atoi(certutil.options[opt_Exponent].arg)(int)strtol(certutil.options[opt_Exponent].arg, ((void*)0), 10
)
;
2933 if ((publicExponent != 3) &&
2934 (publicExponent != 17) &&
2935 (publicExponent != 65537)) {
2936 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s -y: incorrect public exponent %d.",
2937 progName, publicExponent);
2938 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "Must be 3, 17, or 65537.\n");
2939 return 255;
2940 }
2941 }
2942
2943 /* --certVersion */
2944 if (certutil.options[opt_CertVersion].activated) {
2945 certVersion = PORT_Atoi(certutil.options[opt_CertVersion].arg)(int)strtol(certutil.options[opt_CertVersion].arg, ((void*)0)
, 10)
;
2946 if (certVersion < 1 || certVersion > 4) {
2947 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s -certVersion: incorrect certificate version %d.",
2948 progName, certVersion);
2949 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "Must be 1, 2, 3 or 4.\n");
2950 return 255;
2951 }
2952 certVersion = certVersion - 1;
2953 }
2954
2955 /* Check number of commands entered. */
2956 commandsEntered = 0;
2957 for (i = 0; i < certutil.numCommands; i++) {
2958 if (certutil.commands[i].activated) {
2959 commandToRun = certutil.commands[i].flag;
2960 commandsEntered++;
2961 }
2962 if (commandsEntered > 1)
2963 break;
2964 }
2965 if (commandsEntered > 1) {
2966 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s: only one command at a time!\n", progName);
2967 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "You entered: ");
2968 for (i = 0; i < certutil.numCommands; i++) {
2969 if (certutil.commands[i].activated)
2970 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), " -%c", certutil.commands[i].flag);
2971 }
2972 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "\n");
2973 return 255;
2974 }
2975 if (commandsEntered == 0) {
2976 Usage();
2977 }
2978
2979 if (certutil.commands[cmd_ListCerts].activated ||
2980 certutil.commands[cmd_PrintHelp].activated ||
2981 certutil.commands[cmd_ListKeys].activated ||
2982 certutil.commands[cmd_ListModules].activated ||
2983 certutil.commands[cmd_CheckCertValidity].activated ||
2984 certutil.commands[cmd_Version].activated) {
2985 readOnly = !certutil.options[opt_RW].activated;
2986 }
2987
2988 /* -A, -D, -M, -S, -V, and all require -n */
2989 if ((certutil.commands[cmd_AddCert].activated ||
2990 certutil.commands[cmd_DeleteCert].activated ||
2991 certutil.commands[cmd_DumpChain].activated ||
2992 certutil.commands[cmd_ModifyCertTrust].activated ||
2993 certutil.commands[cmd_CreateAndAddCert].activated ||
2994 certutil.commands[cmd_CheckCertValidity].activated) &&
2995 !certutil.options[opt_Nickname].activated) {
2996 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
2997 "%s -%c: nickname is required for this command (-n).\n",
2998 progName, commandToRun);
2999 return 255;
3000 }
3001
3002 /* -A, -E, -M, -S require trust */
3003 if ((certutil.commands[cmd_AddCert].activated ||
3004 certutil.commands[cmd_AddEmailCert].activated ||
3005 certutil.commands[cmd_ModifyCertTrust].activated ||
3006 certutil.commands[cmd_CreateAndAddCert].activated) &&
3007 !certutil.options[opt_Trust].activated) {
3008 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3009 "%s -%c: trust is required for this command (-t).\n",
3010 progName, commandToRun);
3011 return 255;
3012 }
3013
3014 /* if -L is given raw, ascii or dump mode, it must be for only one cert. */
3015 if (certutil.commands[cmd_ListCerts].activated &&
3016 (certutil.options[opt_ASCIIForIO].activated ||
3017 certutil.options[opt_DumpExtensionValue].activated ||
3018 certutil.options[opt_BinaryDER].activated) &&
3019 !certutil.options[opt_Nickname].activated) {
3020 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3021 "%s: nickname is required to dump cert in raw or ascii mode.\n",
3022 progName);
3023 return 255;
3024 }
3025
3026 /* -L can only be in (raw || ascii). */
3027 if (certutil.commands[cmd_ListCerts].activated &&
3028 certutil.options[opt_ASCIIForIO].activated &&
3029 certutil.options[opt_BinaryDER].activated) {
3030 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3031 "%s: cannot specify both -r and -a when dumping cert.\n",
3032 progName);
3033 return 255;
3034 }
3035
3036 /* If making a cert request, need a subject. */
3037 if ((certutil.commands[cmd_CertReq].activated ||
3038 certutil.commands[cmd_CreateAndAddCert].activated) &&
3039 !(certutil.options[opt_Subject].activated || keysource)) {
3040 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3041 "%s -%c: subject is required to create a cert request.\n",
3042 progName, commandToRun);
3043 return 255;
3044 }
3045
3046 /* If making a cert, need a serial number. */
3047 if ((certutil.commands[cmd_CreateNewCert].activated ||
3048 certutil.commands[cmd_CreateAndAddCert].activated) &&
3049 !certutil.options[opt_SerialNumber].activated) {
3050 /* Make a default serial number from the current time. */
3051 PRTime now = PR_Now();
3052 LL_USHR(now, now, 19)((now) = (PRUint64)(now) >> (19));
3053 LL_L2UI(serialNumber, now)((serialNumber) = (PRUint32)(now));
3054 }
3055
3056 /* Validation needs the usage to validate for. */
3057 if (certutil.commands[cmd_CheckCertValidity].activated &&
3058 !certutil.options[opt_Usage].activated) {
3059 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3060 "%s -V: specify a usage to validate the cert for (-u).\n",
3061 progName);
3062 return 255;
3063 }
3064
3065 /* Rename needs an old and a new nickname */
3066 if (certutil.commands[cmd_Rename].activated &&
3067 !(certutil.options[opt_Nickname].activated &&
3068 certutil.options[opt_NewNickname].activated)) {
3069
3070 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3071 "%s --rename: specify an old nickname (-n) and\n"
3072 " a new nickname (--new-n).\n",
3073 progName);
3074 return 255;
3075 }
3076
3077 /* Delete needs a nickname or a key ID */
3078 if (certutil.commands[cmd_DeleteKey].activated &&
3079 !(certutil.options[opt_Nickname].activated || keysource)) {
3080 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3081 "%s -%c: specify a nickname (-n) or\n"
3082 " a key ID (-k).\n",
3083 progName, commandToRun);
3084 return 255;
3085 }
3086
3087 /* Upgrade/Merge needs a source database and a upgrade id. */
3088 if (certutil.commands[cmd_UpgradeMerge].activated &&
3089 !(certutil.options[opt_SourceDir].activated &&
3090 certutil.options[opt_UpgradeID].activated)) {
3091
3092 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3093 "%s --upgrade-merge: specify an upgrade database directory "
3094 "(--source-dir) and\n"
3095 " an upgrade ID (--upgrade-id).\n",
3096 progName);
3097 return 255;
3098 }
3099
3100 /* Merge needs a source database */
3101 if (certutil.commands[cmd_Merge].activated &&
3102 !certutil.options[opt_SourceDir].activated) {
3103
3104 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3105 "%s --merge: specify an source database directory "
3106 "(--source-dir)\n",
3107 progName);
3108 return 255;
3109 }
3110
3111 /* To make a cert, need either a issuer or to self-sign it. */
3112 if (certutil.commands[cmd_CreateAndAddCert].activated &&
3113 !(certutil.options[opt_IssuerName].activated ||
3114 certutil.options[opt_SelfSign].activated)) {
3115 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3116 "%s -S: must specify issuer (-c) or self-sign (-x).\n",
3117 progName);
3118 return 255;
3119 }
3120
3121 /* Using slotname == NULL for listing keys and certs on all slots,
3122 * but only that. */
3123 if (!(certutil.commands[cmd_ListKeys].activated ||
3124 certutil.commands[cmd_DumpChain].activated ||
3125 certutil.commands[cmd_ListCerts].activated) &&
3126 slotname == NULL((void*)0)) {
3127 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3128 "%s -%c: cannot use \"-h all\" for this command.\n",
3129 progName, commandToRun);
3130 return 255;
3131 }
3132
3133 /* Using keytype == nullKey for list all key types, but only that. */
3134 if (!certutil.commands[cmd_ListKeys].activated && keytype == nullKey) {
3135 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3136 "%s -%c: cannot use \"-k all\" for this command.\n",
3137 progName, commandToRun);
3138 return 255;
3139 }
3140
3141 /* Open the input file. */
3142 if (certutil.options[opt_InputFile].activated) {
3143 inFile = PR_Open(certutil.options[opt_InputFile].arg, PR_RDONLY0x01, 0);
3144 if (!inFile) {
3145 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3146 "%s: unable to open \"%s\" for reading (%ld, %ld).\n",
3147 progName, certutil.options[opt_InputFile].arg,
3148 PR_GetError(), PR_GetOSError());
3149 return 255;
3150 }
3151 }
3152
3153 /* Open the output file. */
3154 if (certutil.options[opt_OutputFile].activated) {
3155 outFile = PR_Open(certutil.options[opt_OutputFile].arg,
3156 PR_CREATE_FILE0x08 | PR_RDWR0x04 | PR_TRUNCATE0x20, 00660);
3157 if (!outFile) {
3158 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3159 "%s: unable to open \"%s\" for writing (%ld, %ld).\n",
3160 progName, certutil.options[opt_OutputFile].arg,
3161 PR_GetError(), PR_GetOSError());
3162 return 255;
3163 }
3164 }
3165
3166 name = SECU_GetOptionArg(&certutil, opt_Nickname);
3167 newName = SECU_GetOptionArg(&certutil, opt_NewNickname);
3168 email = SECU_GetOptionArg(&certutil, opt_Emailaddress);
3169
3170 PK11_SetPasswordFunc(SECU_GetModulePassword);
3171
3172 if (PR_TRUE1 == initialize) {
3173 /* Initialize NSPR and NSS. */
3174 PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
3175 if (!certutil.commands[cmd_UpgradeMerge].activated) {
3176 rv = NSS_Initialize(SECU_ConfigDirectory(NULL((void*)0)),
3177 certPrefix, certPrefix,
3178 "secmod.db", readOnly ? NSS_INIT_READONLY0x1 : 0);
3179 } else {
3180 rv = NSS_InitWithMerge(SECU_ConfigDirectory(NULL((void*)0)),
3181 certPrefix, certPrefix, "secmod.db",
3182 sourceDir, srcCertPrefix, srcCertPrefix,
3183 upgradeID, upgradeTokenName,
3184 readOnly ? NSS_INIT_READONLY0x1 : 0);
3185 }
3186 if (rv != SECSuccess) {
3187 SECU_PrintPRandOSError(progName);
3188 rv = SECFailure;
3189 goto shutdown;
3190 }
3191 initialized = PR_TRUE1;
3192 SECU_RegisterDynamicOids();
3193 /* Ensure the SSL error code table has been registered. Bug 1460284. */
3194 SSL_OptionSetDefault(-1, 0);
3195 }
3196 certHandle = CERT_GetDefaultCertDB();
3197
3198 if (certutil.commands[cmd_Version].activated) {
3199 printf("Certificate database content version: command not implemented.\n");
3200 }
3201
3202 if (PL_strcmp(slotname, "internal") == 0)
3203 slot = PK11_GetInternalKeySlot();
3204 else if (slotname != NULL((void*)0))
3205 slot = PK11_FindSlotByName(slotname);
3206
3207 if (!slot && (certutil.commands[cmd_NewDBs].activated ||
3208 certutil.commands[cmd_ModifyCertTrust].activated ||
3209 certutil.commands[cmd_ChangePassword].activated ||
3210 certutil.commands[cmd_TokenReset].activated ||
3211 certutil.commands[cmd_CreateAndAddCert].activated ||
3212 certutil.commands[cmd_AddCert].activated ||
3213 certutil.commands[cmd_Merge].activated ||
3214 certutil.commands[cmd_UpgradeMerge].activated ||
3215 certutil.commands[cmd_AddEmailCert].activated)) {
3216
3217 SECU_PrintError(progName, "could not find the slot %s", slotname);
3218 rv = SECFailure;
3219 goto shutdown;
3220 }
3221
3222 /* If creating new database, initialize the password. */
3223 if (certutil.commands[cmd_NewDBs].activated) {
3224 if (certutil.options[opt_EmptyPassword].activated && (PK11_NeedUserInit(slot))) {
3225 rv = PK11_InitPin(slot, (char *)NULL((void*)0), "");
3226 } else {
3227 rv = SECU_ChangePW2(slot, 0, 0, certutil.options[opt_PasswordFile].arg,
3228 certutil.options[opt_NewPasswordFile].arg);
3229 }
3230 if (rv != SECSuccess) {
3231 SECU_PrintError(progName, "Could not set password for the slot");
3232 goto shutdown;
3233 }
3234 }
3235
3236 /* if we are going to modify the cert database,
3237 * make sure it's initialized */
3238 if (certutil.commands[cmd_ModifyCertTrust].activated ||
3239 certutil.commands[cmd_CreateAndAddCert].activated ||
3240 certutil.commands[cmd_AddCert].activated ||
3241 certutil.commands[cmd_AddEmailCert].activated) {
3242 if (PK11_NeedLogin(slot) && PK11_NeedUserInit(slot)) {
3243 char *password = NULL((void*)0);
3244 /* fetch the password from the command line or the file
3245 * if no password is supplied, initialize the password to NULL */
3246 if (pwdata.source == PW_FROMFILE) {
3247 password = SECU_FilePasswd(slot, PR_FALSE0, pwdata.data);
3248 } else if (pwdata.source == PW_PLAINTEXT) {
3249 password = PL_strdup(pwdata.data);
3250 }
3251 rv = PK11_InitPin(slot, (char *)NULL((void*)0), password ? password : "");
3252 if (password) {
3253 PORT_Memsetmemset(password, 0, PL_strlen(password));
3254 PORT_FreePORT_Free_Util(password);
3255 }
3256 if (rv != SECSuccess) {
3257 SECU_PrintError(progName, "Could not set password for the slot");
3258 goto shutdown;
3259 }
3260 }
3261 }
3262
3263 /* walk through the upgrade merge if necessary.
3264 * This option is more to test what some applications will want to do
3265 * to do an automatic upgrade. The --merge command is more useful for
3266 * the general case where 2 database need to be merged together.
3267 */
3268 if (certutil.commands[cmd_UpgradeMerge].activated) {
3269 if (*upgradeTokenName == 0) {
3270 upgradeTokenName = upgradeID;
3271 }
3272 if (!PK11_IsInternal(slot)) {
3273 fprintf(stderrstderr, "Only internal DB's can be upgraded\n");
3274 rv = SECSuccess;
3275 goto shutdown;
3276 }
3277 if (!PK11_IsRemovable(slot)) {
3278 printf("database already upgraded.\n");
3279 rv = SECSuccess;
3280 goto shutdown;
3281 }
3282 if (!PK11_NeedLogin(slot)) {
3283 printf("upgrade complete!\n");
3284 rv = SECSuccess;
3285 goto shutdown;
3286 }
3287 /* authenticate to the old DB if necessary */
3288 if (PORT_Strcmpstrcmp(PK11_GetTokenName(slot), upgradeTokenName) == 0) {
3289 /* if we need a password, supply it. This will be the password
3290 * for the old database */
3291 rv = PK11_Authenticate(slot, PR_FALSE0, &pwdata2);
3292 if (rv != SECSuccess) {
3293 SECU_PrintError(progName, "Could not get password for %s",
3294 upgradeTokenName);
3295 goto shutdown;
3296 }
3297 /*
3298 * if we succeeded above, but still aren't logged in, that means
3299 * we just supplied the password for the old database. We may
3300 * need the password for the new database. NSS will automatically
3301 * change the token names at this point
3302 */
3303 if (PK11_IsLoggedIn(slot, &pwdata)) {
3304 printf("upgrade complete!\n");
3305 rv = SECSuccess;
3306 goto shutdown;
3307 }
3308 }
3309
3310 /* call PK11_IsPresent to update our cached token information */
3311 if (!PK11_IsPresent(slot)) {
3312 /* this shouldn't happen. We call isPresent to force a token
3313 * info update */
3314 fprintf(stderrstderr, "upgrade/merge internal error\n");
3315 rv = SECFailure;
3316 goto shutdown;
3317 }
3318
3319 /* the token is now set to the state of the source database,
3320 * if we need a password for it, PK11_Authenticate will
3321 * automatically prompt us */
3322 rv = PK11_Authenticate(slot, PR_FALSE0, &pwdata);
3323 if (rv == SECSuccess) {
3324 printf("upgrade complete!\n");
3325 } else {
3326 SECU_PrintError(progName, "Could not get password for %s",
3327 PK11_GetTokenName(slot));
3328 }
3329 goto shutdown;
3330 }
3331
3332 /*
3333 * merge 2 databases.
3334 */
3335 if (certutil.commands[cmd_Merge].activated) {
3336 PK11SlotInfo *sourceSlot = NULL((void*)0);
3337 PK11MergeLog *log;
3338 char *modspec = PR_smprintf(
3339 "configDir='%s' certPrefix='%s' tokenDescription='%s'",
3340 sourceDir, srcCertPrefix,
3341 *upgradeTokenName ? upgradeTokenName : "Source Database");
3342
3343 if (!modspec) {
3344 rv = SECFailure;
3345 goto shutdown;
3346 }
3347
3348 sourceSlot = SECMOD_OpenUserDB(modspec);
3349 PR_smprintf_free(modspec);
3350 if (!sourceSlot) {
3351 SECU_PrintError(progName, "couldn't open source database");
3352 rv = SECFailure;
3353 goto shutdown;
3354 }
3355
3356 rv = PK11_Authenticate(slot, PR_FALSE0, &pwdata);
3357 if (rv != SECSuccess) {
3358 SECU_PrintError(progName, "Couldn't get password for %s",
3359 PK11_GetTokenName(slot));
3360 goto merge_fail;
3361 }
3362
3363 rv = PK11_Authenticate(sourceSlot, PR_FALSE0, &pwdata2);
3364 if (rv != SECSuccess) {
3365 SECU_PrintError(progName, "Couldn't get password for %s",
3366 PK11_GetTokenName(sourceSlot));
3367 goto merge_fail;
3368 }
3369
3370 log = PK11_CreateMergeLog();
3371 if (!log) {
3372 rv = SECFailure;
3373 SECU_PrintError(progName, "couldn't create error log");
3374 goto merge_fail;
3375 }
3376
3377 rv = PK11_MergeTokens(slot, sourceSlot, log, &pwdata, &pwdata2);
3378 if (rv != SECSuccess) {
3379 DumpMergeLog(progName, log);
3380 }
3381 PK11_DestroyMergeLog(log);
3382
3383 merge_fail:
3384 SECMOD_CloseUserDB(sourceSlot);
3385 PK11_FreeSlot(sourceSlot);
3386 goto shutdown;
3387 }
3388
3389 /* The following 8 options are mutually exclusive with all others. */
3390
3391 /* List certs (-L) */
3392 if (certutil.commands[cmd_ListCerts].activated) {
3393 if (certutil.options[opt_DumpExtensionValue].activated) {
3394 const char *oid_str;
3395 SECItem oid_item;
3396 SECStatus srv;
3397 oid_item.data = NULL((void*)0);
3398 oid_item.len = 0;
3399 oid_str = certutil.options[opt_DumpExtensionValue].arg;
3400 srv = GetOidFromString(NULL((void*)0), &oid_item, oid_str, strlen(oid_str));
3401 if (srv != SECSuccess) {
3402 SECU_PrintError(progName, "malformed extension OID %s",
3403 oid_str);
3404 goto shutdown;
3405 }
3406 rv = ListCerts(certHandle, name, email, slot,
3407 PR_TRUE1 /*binary*/, PR_FALSE0 /*ascii*/,
3408 &oid_item,
3409 outFile, &pwdata);
3410 SECITEM_FreeItemSECITEM_FreeItem_Util(&oid_item, PR_FALSE0);
3411 } else {
3412 rv = ListCerts(certHandle, name, email, slot,
3413 certutil.options[opt_BinaryDER].activated,
3414 certutil.options[opt_ASCIIForIO].activated,
3415 NULL((void*)0), outFile, &pwdata);
3416 }
3417 goto shutdown;
3418 }
3419 if (certutil.commands[cmd_DumpChain].activated) {
3420 rv = DumpChain(certHandle, name,
3421 certutil.options[opt_ASCIIForIO].activated,
3422 certutil.options[opt_SimpleSelfSigned].activated);
3423 goto shutdown;
3424 }
3425 /* XXX needs work */
3426 /* List keys (-K) */
3427 if (certutil.commands[cmd_ListKeys].activated) {
3428 rv = ListKeys(slot, name, 0 /*keyindex*/, keytype, PR_FALSE0 /*dopriv*/,
3429 &pwdata);
3430 goto shutdown;
3431 }
3432 /* List modules (-U) */
3433 if (certutil.commands[cmd_ListModules].activated) {
3434 rv = ListModules();
3435 goto shutdown;
3436 }
3437 /* Delete cert (-D) */
3438 if (certutil.commands[cmd_DeleteCert].activated) {
3439 rv = DeleteCert(certHandle, name, &pwdata);
3440 goto shutdown;
3441 }
3442 /* Rename cert (--rename) */
3443 if (certutil.commands[cmd_Rename].activated) {
3444 rv = RenameCert(certHandle, name, newName, &pwdata);
3445 goto shutdown;
3446 }
3447 /* Delete key (-F) */
3448 if (certutil.commands[cmd_DeleteKey].activated) {
3449 if (certutil.options[opt_Nickname].activated) {
3450 rv = DeleteCertAndKey(name, &pwdata);
3451 } else {
3452 privkey = findPrivateKeyByID(slot, keysource, &pwdata);
3453 if (!privkey) {
3454 SECU_PrintError(progName, "%s is not a key-id", keysource);
3455 rv = SECFailure;
3456 } else {
3457 rv = DeleteKey(privkey, &pwdata);
3458 /* already destroyed by PK11_DeleteTokenPrivateKey */
3459 privkey = NULL((void*)0);
3460 }
3461 }
3462 goto shutdown;
3463 }
3464 /* Modify trust attribute for cert (-M) */
3465 if (certutil.commands[cmd_ModifyCertTrust].activated) {
3466 rv = ChangeTrustAttributes(certHandle, slot, name,
3467 certutil.options[opt_Trust].arg, &pwdata);
3468 goto shutdown;
3469 }
3470 /* Change key db password (-W) (future - change pw to slot?) */
3471 if (certutil.commands[cmd_ChangePassword].activated) {
3472 rv = SECU_ChangePW2(slot, 0, 0, certutil.options[opt_PasswordFile].arg,
3473 certutil.options[opt_NewPasswordFile].arg);
3474 if (rv != SECSuccess) {
3475 SECU_PrintError(progName, "Could not set password for the slot");
3476 goto shutdown;
3477 }
3478 }
3479 /* Reset the a token */
3480 if (certutil.commands[cmd_TokenReset].activated) {
3481 char *sso_pass = "";
3482
3483 if (certutil.options[opt_SSOPass].activated) {
3484 sso_pass = certutil.options[opt_SSOPass].arg;
3485 }
3486 rv = PK11_ResetToken(slot, sso_pass);
3487
3488 goto shutdown;
3489 }
3490 /* Check cert validity against current time (-V) */
3491 if (certutil.commands[cmd_CheckCertValidity].activated) {
3492 /* XXX temporary hack for fips - must log in to get priv key */
3493 if (certutil.options[opt_VerifySig].activated) {
3494 if (slot && PK11_NeedLogin(slot)) {
3495 SECStatus newrv = PK11_Authenticate(slot, PR_TRUE1, &pwdata);
3496 if (newrv != SECSuccess) {
3497 SECU_PrintError(progName, "could not authenticate to token %s.",
3498 PK11_GetTokenName(slot));
3499 goto shutdown;
3500 }
3501 }
3502 }
3503 rv = ValidateCert(certHandle, name,
3504 certutil.options[opt_ValidityTime].arg,
3505 certutil.options[opt_Usage].arg,
3506 certutil.options[opt_VerifySig].activated,
3507 certutil.options[opt_DetailedInfo].activated,
3508 certutil.options[opt_ASCIIForIO].activated,
3509 &pwdata);
3510 if (rv != SECSuccess && PR_GetError() == SEC_ERROR_INVALID_ARGS)
3511 SECU_PrintError(progName, "validation failed");
3512 goto shutdown;
3513 }
3514
3515 /*
3516 * Key generation
3517 */
3518
3519 /* These commands may require keygen. */
3520 if (certutil.commands[cmd_CertReq].activated ||
3521 certutil.commands[cmd_CreateAndAddCert].activated ||
3522 certutil.commands[cmd_GenKeyPair].activated) {
3523 if (keysource) {
3524 CERTCertificate *keycert;
3525 keycert = CERT_FindCertByNicknameOrEmailAddr(certHandle, keysource);
3526 if (!keycert) {
3527 keycert = PK11_FindCertFromNickname(keysource, NULL((void*)0));
3528 }
3529
3530 if (keycert) {
3531 privkey = PK11_FindKeyByDERCert(slot, keycert, &pwdata);
3532 } else {
3533 /* Interpret keysource as CKA_ID */
3534 privkey = findPrivateKeyByID(slot, keysource, &pwdata);
3535 }
3536
3537 if (!privkey) {
3538 SECU_PrintError(
3539 progName,
3540 "%s is neither a key-type nor a nickname nor a key-id", keysource);
3541 return SECFailure;
3542 }
3543
3544 pubkey = SECKEY_ConvertToPublicKey(privkey);
3545 if (!pubkey) {
3546 SECU_PrintError(progName,
3547 "Could not get keys from cert %s", keysource);
3548 if (keycert) {
3549 CERT_DestroyCertificate(keycert);
3550 }
3551 rv = SECFailure;
3552 goto shutdown;
3553 }
3554 keytype = privkey->keyType;
3555
3556 /* On CertReq for renewal if no subject has been
3557 * specified obtain it from the certificate.
3558 */
3559 if (certutil.commands[cmd_CertReq].activated && !subject) {
3560 if (keycert) {
3561 subject = CERT_AsciiToName(keycert->subjectName);
3562 if (!subject) {
3563 SECU_PrintError(
3564 progName,
3565 "Could not get subject from certificate %s",
3566 keysource);
3567 CERT_DestroyCertificate(keycert);
3568 rv = SECFailure;
3569 goto shutdown;
3570 }
3571 } else {
3572 SECU_PrintError(progName, "Subject name not provided");
3573 rv = SECFailure;
3574 goto shutdown;
3575 }
3576 }
3577 if (keycert) {
3578 CERT_DestroyCertificate(keycert);
3579 }
3580 } else {
3581 privkey =
3582 CERTUTIL_GeneratePrivateKey(keytype, slot, keysize,
3583 publicExponent,
3584 certutil.options[opt_NoiseFile].arg,
3585 &pubkey,
3586 certutil.options[opt_PQGFile].arg,
3587 keyAttrFlags,
3588 keyOpFlagsOn,
3589 keyOpFlagsOff,
3590 &pwdata);
3591 if (privkey == NULL((void*)0)) {
3592 SECU_PrintError(progName, "unable to generate key(s)\n");
3593 rv = SECFailure;
3594 goto shutdown;
3595 }
3596 }
3597 privkey->wincx = &pwdata;
3598 PORT_Assert(pubkey != NULL)((pubkey != ((void*)0)) ? ((void)0) : PR_Assert("pubkey != NULL"
, "/root/firefox-clang/security/nss/cmd/certutil/certutil.c",
3598))
;
3599
3600 /* If all that was needed was keygen, exit. */
3601 if (certutil.commands[cmd_GenKeyPair].activated) {
3602 rv = SECSuccess;
3603 goto shutdown;
3604 }
3605 }
3606
3607 if (certutil.options[opt_Pss].activated) {
3608 if (!certutil.commands[cmd_CertReq].activated &&
3609 !certutil.commands[cmd_CreateAndAddCert].activated) {
3610 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3611 "%s -%c: --pss only works with -R or -S.\n",
3612 progName, commandToRun);
3613 return 255;
3614 }
3615 if (keytype != rsaKey) {
3616 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3617 "%s -%c: --pss only works with RSA keys.\n",
3618 progName, commandToRun);
3619 return 255;
3620 }
3621 }
3622
3623 /* --pss-sign is to sign a certificate with RSA-PSS, even if the
3624 * issuer's key is an RSA key. If the key is an RSA-PSS key, the
3625 * generated signature is always RSA-PSS. */
3626 if (certutil.options[opt_PssSign].activated) {
3627 if (!certutil.commands[cmd_CreateNewCert].activated &&
3628 !certutil.commands[cmd_CreateAndAddCert].activated) {
3629 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3630 "%s -%c: --pss-sign only works with -C or -S.\n",
3631 progName, commandToRun);
3632 return 255;
3633 }
3634 if (keytype != rsaKey) {
3635 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3636 "%s -%c: --pss-sign only works with RSA keys.\n",
3637 progName, commandToRun);
3638 return 255;
3639 }
3640 }
3641
3642 if (certutil.options[opt_SimpleSelfSigned].activated &&
3643 !certutil.commands[cmd_DumpChain].activated) {
3644 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3645 "%s -%c: --simple-self-signed only works with -O.\n",
3646 progName, commandToRun);
3647 return 255;
3648 }
3649
3650 /* If we need a list of extensions convert the flags into list format */
3651 if (certutil.commands[cmd_CertReq].activated ||
3652 certutil.commands[cmd_CreateAndAddCert].activated ||
3653 certutil.commands[cmd_CreateNewCert].activated) {
3654 certutil_extns[ext_keyUsage].activated =
3655 certutil.options[opt_AddCmdKeyUsageExt].activated;
3656 if (!certutil_extns[ext_keyUsage].activated) {
3657 certutil_extns[ext_keyUsage].activated =
3658 certutil.options[opt_AddKeyUsageExt].activated;
3659 } else {
3660 certutil_extns[ext_keyUsage].arg =
3661 certutil.options[opt_AddCmdKeyUsageExt].arg;
3662 }
3663 certutil_extns[ext_basicConstraint].activated =
3664 certutil.options[opt_AddBasicConstraintExt].activated;
3665 certutil_extns[ext_nameConstraints].activated =
3666 certutil.options[opt_AddNameConstraintsExt].activated;
3667 certutil_extns[ext_authorityKeyID].activated =
3668 certutil.options[opt_AddAuthorityKeyIDExt].activated;
3669 certutil_extns[ext_subjectKeyID].activated =
3670 certutil.options[opt_AddSubjectKeyIDExt].activated;
3671 certutil_extns[ext_CRLDistPts].activated =
3672 certutil.options[opt_AddCRLDistPtsExt].activated;
3673 certutil_extns[ext_NSCertType].activated =
3674 certutil.options[opt_AddCmdNSCertTypeExt].activated;
3675 if (!certutil_extns[ext_NSCertType].activated) {
3676 certutil_extns[ext_NSCertType].activated =
3677 certutil.options[opt_AddNSCertTypeExt].activated;
3678 } else {
3679 certutil_extns[ext_NSCertType].arg =
3680 certutil.options[opt_AddCmdNSCertTypeExt].arg;
3681 }
3682
3683 certutil_extns[ext_extKeyUsage].activated =
3684 certutil.options[opt_AddCmdExtKeyUsageExt].activated;
3685 if (!certutil_extns[ext_extKeyUsage].activated) {
3686 certutil_extns[ext_extKeyUsage].activated =
3687 certutil.options[opt_AddExtKeyUsageExt].activated;
3688 } else {
3689 certutil_extns[ext_extKeyUsage].arg =
3690 certutil.options[opt_AddCmdExtKeyUsageExt].arg;
3691 }
3692 certutil_extns[ext_subjectAltName].activated =
3693 certutil.options[opt_AddSubjectAltNameExt].activated;
3694 if (certutil_extns[ext_subjectAltName].activated) {
3695 certutil_extns[ext_subjectAltName].arg =
3696 certutil.options[opt_AddSubjectAltNameExt].arg;
3697 }
3698
3699 certutil_extns[ext_authInfoAcc].activated =
3700 certutil.options[opt_AddAuthInfoAccExt].activated;
3701 certutil_extns[ext_subjInfoAcc].activated =
3702 certutil.options[opt_AddSubjInfoAccExt].activated;
3703 certutil_extns[ext_certPolicies].activated =
3704 certutil.options[opt_AddCertPoliciesExt].activated;
3705 certutil_extns[ext_policyMappings].activated =
3706 certutil.options[opt_AddPolicyMapExt].activated;
3707 certutil_extns[ext_policyConstr].activated =
3708 certutil.options[opt_AddPolicyConstrExt].activated;
3709 certutil_extns[ext_inhibitAnyPolicy].activated =
3710 certutil.options[opt_AddInhibAnyExt].activated;
3711 }
3712
3713 /* -A -C or -E Read inFile */
3714 if (certutil.commands[cmd_CreateNewCert].activated ||
3715 certutil.commands[cmd_AddCert].activated ||
3716 certutil.commands[cmd_AddEmailCert].activated) {
3717 PRBool isCreate = certutil.commands[cmd_CreateNewCert].activated;
3718 rv = SECU_ReadDERFromFile(isCreate ? &certReqDER : &certDER, inFile,
3719 certutil.options[opt_ASCIIForIO].activated,
3720 PR_TRUE1);
3721 if (rv)
3722 goto shutdown;
3723 }
3724
3725 /*
3726 * Certificate request
3727 */
3728
3729 /* Make a cert request (-R). */
3730 if (certutil.commands[cmd_CertReq].activated) {
3731 rv = CertReq(privkey, pubkey, keytype, hashAlgTag, subject,
3732 certutil.options[opt_PhoneNumber].arg,
3733 certutil.options[opt_ASCIIForIO].activated,
3734 certutil.options[opt_ExtendedEmailAddrs].arg,
3735 certutil.options[opt_ExtendedDNSNames].arg,
3736 certutil_extns,
3737 (certutil.options[opt_GenericExtensions].activated ? certutil.options[opt_GenericExtensions].arg
3738 : NULL((void*)0)),
3739 certutil.options[opt_Pss].activated,
3740 &certReqDER);
3741 if (rv)
3742 goto shutdown;
3743 privkey->wincx = &pwdata;
3744 }
3745
3746 /*
3747 * Certificate creation
3748 */
3749
3750 /* If making and adding a cert, create a cert request file first without
3751 * any extensions, then load it with the command line extensions
3752 * and output the cert to another file.
3753 */
3754 if (certutil.commands[cmd_CreateAndAddCert].activated) {
3755 static certutilExtnList nullextnlist = { { PR_FALSE0, NULL((void*)0) } };
3756 rv = CertReq(privkey, pubkey, keytype, hashAlgTag, subject,
3757 certutil.options[opt_PhoneNumber].arg,
3758 PR_FALSE0, /* do not BASE64-encode regardless of -a option */
3759 NULL((void*)0),
3760 NULL((void*)0),
3761 nullextnlist,
3762 (certutil.options[opt_GenericExtensions].activated ? certutil.options[opt_GenericExtensions].arg
3763 : NULL((void*)0)),
3764 certutil.options[opt_Pss].activated,
3765 &certReqDER);
3766 if (rv)
3767 goto shutdown;
3768 privkey->wincx = &pwdata;
3769 }
3770
3771 /* Create a certificate (-C or -S). */
3772 if (certutil.commands[cmd_CreateAndAddCert].activated ||
3773 certutil.commands[cmd_CreateNewCert].activated) {
3774 rv = CreateCert(certHandle, slot,
3775 certutil.options[opt_IssuerName].arg,
3776 &certReqDER, &privkey, &pwdata, hashAlgTag,
3777 serialNumber, warpmonths, validityMonths,
3778 certutil.options[opt_ExtendedEmailAddrs].arg,
3779 certutil.options[opt_ExtendedDNSNames].arg,
3780 certutil.options[opt_ASCIIForIO].activated &&
3781 certutil.commands[cmd_CreateNewCert].activated,
3782 certutil.options[opt_SelfSign].activated,
3783 certutil_extns,
3784 (certutil.options[opt_GenericExtensions].activated ? certutil.options[opt_GenericExtensions].arg
3785 : NULL((void*)0)),
3786 certVersion,
3787 certutil.options[opt_PssSign].activated,
3788 &certDER);
3789 if (rv)
3790 goto shutdown;
3791 }
3792
3793 /*
3794 * Adding a cert to the database (or slot)
3795 */
3796
3797 /* -A -E or -S Add the cert to the DB */
3798 if (certutil.commands[cmd_CreateAndAddCert].activated ||
3799 certutil.commands[cmd_AddCert].activated ||
3800 certutil.commands[cmd_AddEmailCert].activated) {
3801 if (strstr(certutil.options[opt_Trust].arg, "u")) {
3802 fprintf(stderrstderr, "Notice: Trust flag u is set automatically if the "
3803 "private key is present.\n");
3804 }
3805 rv = AddCert(slot, certHandle, name,
3806 certutil.options[opt_Trust].arg,
3807 &certDER,
3808 certutil.commands[cmd_AddEmailCert].activated, &pwdata);
3809 if (rv)
3810 goto shutdown;
3811 }
3812
3813 if (certutil.commands[cmd_CertReq].activated ||
3814 certutil.commands[cmd_CreateNewCert].activated) {
3815 SECItem *item = certutil.commands[cmd_CertReq].activated ? &certReqDER
3816 : &certDER;
3817 PRInt32 written = PR_Write(outFile, item->data, item->len);
3818 if (written < 0 || (PRUint32)written != item->len) {
3819 rv = SECFailure;
3820 }
3821 }
3822
3823shutdown:
3824 if (slot) {
3825 PK11_FreeSlot(slot);
3826 }
3827 if (privkey) {
3828 SECKEY_DestroyPrivateKey(privkey);
3829 }
3830 if (pubkey) {
3831 SECKEY_DestroyPublicKey(pubkey);
3832 }
3833 if (subject) {
3834 CERT_DestroyName(subject);
3835 }
3836 if (name) {
3837 PL_strfree(name);
3838 }
3839 if (newName) {
3840 PL_strfree(newName);
3841 }
3842 if (inFile && inFile != PR_STDINPR_GetSpecialFD(PR_StandardInput)) {
3843 PR_Close(inFile);
3844 }
3845 if (outFile && outFile != PR_STDOUTPR_GetSpecialFD(PR_StandardOutput)) {
3846 PR_Close(outFile);
3847 }
3848 SECITEM_FreeItemSECITEM_FreeItem_Util(&certReqDER, PR_FALSE0);
3849 SECITEM_FreeItemSECITEM_FreeItem_Util(&certDER, PR_FALSE0);
3850 if (pwdata.data && pwdata.source == PW_PLAINTEXT) {
3851 /* Allocated by a PL_strdup call in SECU_GetModulePassword. */
3852 PL_strfree(pwdata.data);
3853 }
3854 if (email) {
3855 PL_strfree(email);
3856 }
3857
3858 /* Open the batch command file.
3859 *
3860 * - If -B <command line> option is specified, the contents in the
3861 * command file will be interpreted as subsequent certutil
3862 * commands to be executed in the current certutil process
3863 * context after the current certutil command has been executed.
3864 * - Each line in the command file consists of the command
3865 * line arguments for certutil.
3866 * - The -d <configdir> option will be ignored if specified in the
3867 * command file.
3868 * - Quoting with double quote characters ("...") is supported
3869 * to allow white space in a command line argument. The
3870 * double quote character cannot be escaped and quoting cannot
3871 * be nested in this version.
3872 * - each line in the batch file is limited to 512 characters
3873 */
3874
3875 if ((SECSuccess == rv) && certutil.commands[cmd_Batch].activated) {
3876 FILE *batchFile = NULL((void*)0);
3877 char *nextcommand = NULL((void*)0);
3878 PRInt32 cmd_len = 0, buf_size = 0;
3879 static const int increment = 512;
3880
3881 if (!certutil.options[opt_InputFile].activated ||
3882 !certutil.options[opt_InputFile].arg) {
3883 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3884 "%s: no batch input file specified.\n",
3885 progName);
3886 return 255;
3887 }
3888 batchFile = fopen(certutil.options[opt_InputFile].arg, "r");
3889 if (!batchFile) {
3890 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
3891 "%s: unable to open \"%s\" for reading (%ld, %ld).\n",
3892 progName, certutil.options[opt_InputFile].arg,
3893 PR_GetError(), PR_GetOSError());
3894 return 255;
3895 }
3896 /* read and execute command-lines in a loop */
3897 while (SECSuccess == rv) {
3898 PRBool invalid = PR_FALSE0;
3899 int newargc = 2;
3900 char *space = NULL((void*)0);
3901 char *nextarg = NULL((void*)0);
3902 char **newargv = NULL((void*)0);
3903 char *crlf;
3904
3905 if (cmd_len + increment > buf_size) {
3906 char *new_buf;
3907 buf_size += increment;
3908 new_buf = PORT_ReallocPORT_Realloc_Util(nextcommand, buf_size);
3909 if (!new_buf) {
3910 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "%s: PORT_Realloc(%ld) failed\n",
3911 progName, buf_size);
3912 break;
3913 }
3914 nextcommand = new_buf;
3915 nextcommand[cmd_len] = '\0';
3916 }
3917 if (!fgets(nextcommand + cmd_len, buf_size - cmd_len, batchFile)) {
3918 break;
3919 }
3920 crlf = PORT_Strrchrstrrchr(nextcommand, '\n');
3921 if (crlf) {
3922 *crlf = '\0';
3923 }
3924 cmd_len = strlen(nextcommand);
3925 if (cmd_len && nextcommand[cmd_len - 1] == '\\') {
3926 nextcommand[--cmd_len] = '\0';
3927 continue;
3928 }
3929
3930 /* we now need to split the command into argc / argv format */
3931
3932 newargv = PORT_AllocPORT_Alloc_Util(sizeof(char *) * (newargc + 1));
3933 newargv[0] = progName;
3934 newargv[1] = nextcommand;
3935 nextarg = nextcommand;
3936 while ((space = PORT_Strpbrkstrpbrk(nextarg, " \f\n\r\t\v"))) {
3937 while (isspace((unsigned char)*space)((*__ctype_b_loc ())[(int) (((unsigned char)*space))] & (
unsigned short int) _ISspace)
) {
3938 *space = '\0';
3939 space++;
3940 }
3941 if (*space == '\0') {
3942 break;
3943 } else if (*space != '\"') {
3944 nextarg = space;
3945 } else {
3946 char *closingquote = strchr(space + 1, '\"');
3947 if (closingquote) {
3948 *closingquote = '\0';
3949 space++;
3950 nextarg = closingquote + 1;
3951 } else {
3952 invalid = PR_TRUE1;
3953 nextarg = space;
3954 }
3955 }
3956 newargc++;
3957 newargv = PORT_ReallocPORT_Realloc_Util(newargv, sizeof(char *) * (newargc + 1));
3958 newargv[newargc - 1] = space;
3959 }
3960 newargv[newargc] = NULL((void*)0);
3961
3962 /* invoke next command */
3963 if (PR_TRUE1 == invalid) {
3964 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "Missing closing quote in batch command :\n%s\nNot executed.\n",
3965 nextcommand);
3966 rv = SECFailure;
3967 } else {
3968 if (0 != certutil_main(newargc, newargv, PR_FALSE0))
3969 rv = SECFailure;
3970 }
3971 PORT_FreePORT_Free_Util(newargv);
3972 cmd_len = 0;
3973 nextcommand[0] = '\0';
3974 }
3975 PORT_FreePORT_Free_Util(nextcommand);
3976 fclose(batchFile);
3977 }
3978
3979 if ((initialized == PR_TRUE1) && NSS_Shutdown() != SECSuccess) {
3980 exit(1);
3981 }
3982 if (rv == SECSuccess) {
3983 return 0;
3984 } else {
3985 return 255;
3986 }
3987}
3988
3989int
3990main(int argc, char **argv)
3991{
3992 int rv = certutil_main(argc, argv, PR_TRUE1);
3993 PL_ArenaFinish();
3994 PR_Cleanup();
3995 return rv;
3996}