Source code
Revision control
Copy as Markdown
Other Tools
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
/*
** certutil.c
**
** utility for managing certificates and the cert database
**
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#if defined(WIN32)
#include "fcntl.h"
#include "io.h"
#endif
#include "secutil.h"
#if defined(XP_UNIX)
#include <unistd.h>
#endif
#include "nspr.h"
#include "prtypes.h"
#include "prtime.h"
#include "prlong.h"
#include "pk11func.h"
#include "secasn1.h"
#include "cert.h"
#include "cryptohi.h"
#include "secoid.h"
#include "certdb.h"
#include "nss.h"
#include "certutil.h"
#include "basicutil.h"
#include "ssl.h"
#define MIN_KEY_BITS 512
/* MAX_KEY_BITS should agree with RSA_MAX_MODULUS_BITS in freebl */
#define MAX_KEY_BITS 8192
#define DEFAULT_KEY_BITS 2048
#define GEN_BREAK(e) \
rv = e; \
break;
char *progName;
static SECStatus
ChangeCertTrust(CERTCertDBHandle *handle, CERTCertificate *cert,
CERTCertTrust *trust, PK11SlotInfo *slot, void *pwdata)
{
SECStatus rv;
rv = CERT_ChangeCertTrust(handle, cert, trust);
if (rv != SECSuccess) {
if (PORT_GetError() == SEC_ERROR_TOKEN_NOT_LOGGED_IN) {
rv = PK11_Authenticate(slot, PR_TRUE, pwdata);
if (PORT_GetError() == SEC_ERROR_TOKEN_NOT_LOGGED_IN) {
PK11SlotInfo *internalslot;
internalslot = PK11_GetInternalKeySlot();
rv = PK11_Authenticate(internalslot, PR_TRUE, pwdata);
if (rv != SECSuccess) {
SECU_PrintError(progName,
"could not authenticate to token %s.",
PK11_GetTokenName(internalslot));
PK11_FreeSlot(internalslot);
return SECFailure;
}
PK11_FreeSlot(internalslot);
}
rv = CERT_ChangeCertTrust(handle, cert, trust);
}
}
return rv;
}
static CERTCertificateRequest *
GetCertRequest(const SECItem *reqDER, void *pwarg)
{
CERTCertificateRequest *certReq = NULL;
CERTSignedData signedData;
PLArenaPool *arena = NULL;
SECStatus rv;
do {
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (arena == NULL) {
GEN_BREAK(SECFailure);
}
certReq = (CERTCertificateRequest *)PORT_ArenaZAlloc(arena, sizeof(CERTCertificateRequest));
if (!certReq) {
GEN_BREAK(SECFailure);
}
certReq->arena = arena;
/* Since cert request is a signed data, must decode to get the inner
data
*/
PORT_Memset(&signedData, 0, sizeof(signedData));
rv = SEC_ASN1DecodeItem(arena, &signedData,
SEC_ASN1_GET(CERT_SignedDataTemplate), reqDER);
if (rv) {
break;
}
rv = SEC_ASN1DecodeItem(arena, certReq,
SEC_ASN1_GET(CERT_CertificateRequestTemplate), &signedData.data);
if (rv) {
break;
}
rv = CERT_VerifySignedDataWithPublicKeyInfo(&signedData,
&certReq->subjectPublicKeyInfo, pwarg);
} while (0);
if (rv) {
SECU_PrintError(progName, "bad certificate request\n");
if (arena) {
PORT_FreeArena(arena, PR_FALSE);
}
certReq = NULL;
}
return certReq;
}
static SECStatus
AddCert(PK11SlotInfo *slot, CERTCertDBHandle *handle, char *name, char *trusts,
const SECItem *certDER, PRBool emailcert, void *pwdata)
{
CERTCertTrust *trust = NULL;
CERTCertificate *cert = NULL;
SECStatus rv;
do {
/* Read in an ASCII cert and return a CERTCertificate */
cert = CERT_DecodeCertFromPackage((char *)certDER->data, certDER->len);
if (!cert) {
SECU_PrintError(progName, "could not decode certificate");
GEN_BREAK(SECFailure);
}
/* Create a cert trust */
trust = (CERTCertTrust *)PORT_ZAlloc(sizeof(CERTCertTrust));
if (!trust) {
SECU_PrintError(progName, "unable to allocate cert trust");
GEN_BREAK(SECFailure);
}
rv = CERT_DecodeTrustString(trust, trusts);
if (rv) {
SECU_PrintError(progName, "unable to decode trust string");
GEN_BREAK(SECFailure);
}
rv = PK11_ImportCert(slot, cert, CK_INVALID_HANDLE, name, PR_FALSE);
if (rv != SECSuccess) {
/* sigh, PK11_Import Cert and CERT_ChangeCertTrust should have
* been coded to take a password arg. */
if (PORT_GetError() == SEC_ERROR_TOKEN_NOT_LOGGED_IN) {
rv = PK11_Authenticate(slot, PR_TRUE, pwdata);
if (rv != SECSuccess) {
SECU_PrintError(progName,
"could not authenticate to token %s.",
PK11_GetTokenName(slot));
GEN_BREAK(SECFailure);
}
rv = PK11_ImportCert(slot, cert, CK_INVALID_HANDLE,
name, PR_FALSE);
}
if (rv != SECSuccess) {
SECU_PrintError(progName,
"could not add certificate to token or database");
GEN_BREAK(SECFailure);
}
}
rv = ChangeCertTrust(handle, cert, trust, slot, pwdata);
if (rv != SECSuccess) {
SECU_PrintError(progName,
"could not change trust on certificate");
GEN_BREAK(SECFailure);
}
if (emailcert) {
CERT_SaveSMimeProfile(cert, NULL, pwdata);
}
} while (0);
CERT_DestroyCertificate(cert);
PORT_Free(trust);
return rv;
}
static SECStatus
CertReq(SECKEYPrivateKey *privk, SECKEYPublicKey *pubk, KeyType keyType,
SECOidTag hashAlgTag, CERTName *subject, const char *phone, int ascii,
const char *emailAddrs, const char *dnsNames,
certutilExtnList extnList, const char *extGeneric,
PRBool pssCertificate, /*out*/ SECItem *result)
{
CERTSubjectPublicKeyInfo *spki;
CERTCertificateRequest *cr;
SECItem *encoding;
SECOidTag signAlgTag;
SECStatus rv;
PLArenaPool *arena;
void *extHandle;
SECItem signedReq = { siBuffer, NULL, 0 };
SECAlgorithmID signAlg;
SECItem *params = NULL;
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (!arena) {
SECU_PrintError(progName, "out of memory");
return SECFailure;
}
/* Create info about public key */
spki = SECKEY_CreateSubjectPublicKeyInfo(pubk);
if (!spki) {
PORT_FreeArena(arena, PR_FALSE);
SECU_PrintError(progName, "unable to create subject public key");
return SECFailure;
}
/* Change cert type to RSA-PSS, if desired. */
if (pssCertificate) {
params = SEC_CreateSignatureAlgorithmParameters(arena,
NULL,
SEC_OID_PKCS1_RSA_PSS_SIGNATURE,
hashAlgTag,
NULL,
privk);
if (!params) {
PORT_FreeArena(arena, PR_FALSE);
SECKEY_DestroySubjectPublicKeyInfo(spki);
SECU_PrintError(progName, "unable to create RSA-PSS parameters");
return SECFailure;
}
spki->algorithm.parameters.data = NULL;
rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
SEC_OID_PKCS1_RSA_PSS_SIGNATURE,
hashAlgTag == SEC_OID_UNKNOWN ? NULL : params);
if (rv != SECSuccess) {
PORT_FreeArena(arena, PR_FALSE);
SECKEY_DestroySubjectPublicKeyInfo(spki);
SECU_PrintError(progName, "unable to set algorithm ID");
return SECFailure;
}
}
/* Generate certificate request */
cr = CERT_CreateCertificateRequest(subject, spki, NULL);
SECKEY_DestroySubjectPublicKeyInfo(spki);
if (!cr) {
PORT_FreeArena(arena, PR_FALSE);
SECU_PrintError(progName, "unable to make certificate request");
return SECFailure;
}
extHandle = CERT_StartCertificateRequestAttributes(cr);
if (extHandle == NULL) {
PORT_FreeArena(arena, PR_FALSE);
CERT_DestroyCertificateRequest(cr);
return SECFailure;
}
if (AddExtensions(extHandle, emailAddrs, dnsNames, extnList, extGeneric) !=
SECSuccess) {
PORT_FreeArena(arena, PR_FALSE);
CERT_FinishExtensions(extHandle);
CERT_DestroyCertificateRequest(cr);
return SECFailure;
}
CERT_FinishExtensions(extHandle);
CERT_FinishCertificateRequestAttributes(cr);
/* Der encode the request */
encoding = SEC_ASN1EncodeItem(arena, NULL, cr,
SEC_ASN1_GET(CERT_CertificateRequestTemplate));
CERT_DestroyCertificateRequest(cr);
if (encoding == NULL) {
PORT_FreeArena(arena, PR_FALSE);
SECU_PrintError(progName, "der encoding of request failed");
return SECFailure;
}
PORT_Memset(&signAlg, 0, sizeof(signAlg));
if (pssCertificate) {
rv = SECOID_SetAlgorithmID(arena, &signAlg,
SEC_OID_PKCS1_RSA_PSS_SIGNATURE, params);
if (rv != SECSuccess) {
PORT_FreeArena(arena, PR_FALSE);
SECU_PrintError(progName, "unable to set algorithm ID");
return SECFailure;
}
} else {
signAlgTag = SEC_GetSignatureAlgorithmOidTag(keyType, hashAlgTag);
if (signAlgTag == SEC_OID_UNKNOWN) {
PORT_FreeArena(arena, PR_FALSE);
SECU_PrintError(progName, "unknown Key or Hash type");
return SECFailure;
}
rv = SECOID_SetAlgorithmID(arena, &signAlg, signAlgTag, 0);
if (rv != SECSuccess) {
PORT_FreeArena(arena, PR_FALSE);
SECU_PrintError(progName, "unable to set algorithm ID");
return SECFailure;
}
}
/* Sign the request */
rv = SEC_DerSignDataWithAlgorithmID(arena, &signedReq,
encoding->data, encoding->len,
privk, &signAlg);
if (rv) {
PORT_FreeArena(arena, PR_FALSE);
SECU_PrintError(progName, "signing of data failed");
return SECFailure;
}
/* Encode request in specified format */
if (ascii) {
char *obuf;
char *header, *name, *email, *org, *state, *country;
obuf = BTOA_ConvertItemToAscii(&signedReq);
if (!obuf) {
goto oom;
}
name = CERT_GetCommonName(subject);
if (!name) {
name = PORT_Strdup("(not specified)");
}
if (!phone)
phone = "(not specified)";
email = CERT_GetCertEmailAddress(subject);
if (!email)
email = PORT_Strdup("(not specified)");
org = CERT_GetOrgName(subject);
if (!org)
org = PORT_Strdup("(not specified)");
state = CERT_GetStateName(subject);
if (!state)
state = PORT_Strdup("(not specified)");
country = CERT_GetCountryName(subject);
if (!country)
country = PORT_Strdup("(not specified)");
header = PR_smprintf(
"\nCertificate request generated by Netscape certutil\n"
"Phone: %s\n\n"
"Common Name: %s\n"
"Email: %s\n"
"Organization: %s\n"
"State: %s\n"
"Country: %s\n\n"
"%s\n",
phone, name, email, org, state, country, NS_CERTREQ_HEADER);
PORT_Free(name);
PORT_Free(email);
PORT_Free(org);
PORT_Free(state);
PORT_Free(country);
if (header) {
char *trailer = PR_smprintf("\n%s\n", NS_CERTREQ_TRAILER);
if (trailer) {
PRUint32 headerLen = PL_strlen(header);
PRUint32 obufLen = PL_strlen(obuf);
PRUint32 trailerLen = PL_strlen(trailer);
SECITEM_AllocItem(NULL, result,
headerLen + obufLen + trailerLen);
if (result->data) {
PORT_Memcpy(result->data, header, headerLen);
PORT_Memcpy(result->data + headerLen, obuf, obufLen);
PORT_Memcpy(result->data + headerLen + obufLen,
trailer, trailerLen);
}
PR_smprintf_free(trailer);
}
PR_smprintf_free(header);
}
PORT_Free(obuf);
} else {
(void)SECITEM_CopyItem(NULL, result, &signedReq);
}
if (!result->data) {
oom:
SECU_PrintError(progName, "out of memory");
PORT_SetError(SEC_ERROR_NO_MEMORY);
rv = SECFailure;
}
PORT_FreeArena(arena, PR_FALSE);
return rv;
}
static SECStatus
ChangeTrustAttributes(CERTCertDBHandle *handle, PK11SlotInfo *slot,
char *name, char *trusts, void *pwdata)
{
SECStatus rv;
CERTCertificate *cert;
CERTCertTrust *trust;
cert = CERT_FindCertByNicknameOrEmailAddrCX(handle, name, pwdata);
if (!cert) {
SECU_PrintError(progName, "could not find certificate named \"%s\"",
name);
return SECFailure;
}
trust = (CERTCertTrust *)PORT_ZAlloc(sizeof(CERTCertTrust));
if (!trust) {
SECU_PrintError(progName, "unable to allocate cert trust");
return SECFailure;
}
/* This function only decodes these characters: pPwcTCu, */
rv = CERT_DecodeTrustString(trust, trusts);
if (rv) {
SECU_PrintError(progName, "unable to decode trust string");
return SECFailure;
}
/* CERT_ChangeCertTrust API does not have a way to pass in
* a context, so NSS can't prompt for the password if it needs to.
* check to see if the failure was token not logged in and
* log in if need be. */
rv = ChangeCertTrust(handle, cert, trust, slot, pwdata);
if (rv != SECSuccess) {
SECU_PrintError(progName, "unable to modify trust attributes");
return SECFailure;
}
CERT_DestroyCertificate(cert);
PORT_Free(trust);
return SECSuccess;
}
static SECStatus
DumpChain(CERTCertDBHandle *handle, char *name, PRBool ascii,
PRBool simpleSelfSigned)
{
CERTCertificate *the_cert;
CERTCertificateList *chain;
int i, j;
the_cert = SECU_FindCertByNicknameOrFilename(handle, name,
ascii, NULL);
if (!the_cert) {
SECU_PrintError(progName, "Could not find: %s\n", name);
return SECFailure;
}
if (simpleSelfSigned &&
SECEqual == SECITEM_CompareItem(&the_cert->derIssuer,
&the_cert->derSubject)) {
printf("\"%s\" [%s]\n\n", the_cert->nickname, the_cert->subjectName);
CERT_DestroyCertificate(the_cert);
return SECSuccess;
}
chain = CERT_CertChainFromCert(the_cert, 0, PR_TRUE);
CERT_DestroyCertificate(the_cert);
if (!chain) {
SECU_PrintError(progName, "Could not obtain chain for: %s\n", name);
return SECFailure;
}
for (i = chain->len - 1; i >= 0; i--) {
CERTCertificate *c;
c = CERT_FindCertByDERCert(handle, &chain->certs[i]);
for (j = i; j < chain->len - 1; j++) {
printf(" ");
}
if (c) {
printf("\"%s\" [%s]\n\n", c->nickname, c->subjectName);
CERT_DestroyCertificate(c);
} else {
printf("(null)\n\n");
}
}
CERT_DestroyCertificateList(chain);
return SECSuccess;
}
static SECStatus
outputCertOrExtension(CERTCertificate *the_cert, PRBool raw, PRBool ascii,
SECItem *extensionOID, PRFileDesc *outfile)
{
SECItem data;
PRInt32 numBytes;
SECStatus rv = SECFailure;
if (extensionOID) {
int i;
PRBool found = PR_FALSE;
for (i = 0; the_cert->extensions[i] != NULL; i++) {
CERTCertExtension *extension = the_cert->extensions[i];
if (SECITEM_CompareItem(&extension->id, extensionOID) == SECEqual) {
found = PR_TRUE;
numBytes = PR_Write(outfile, extension->value.data,
extension->value.len);
rv = SECSuccess;
if (numBytes != (PRInt32)extension->value.len) {
SECU_PrintSystemError(progName, "error writing extension");
rv = SECFailure;
}
break;
}
}
if (!found) {
SECU_PrintSystemError(progName, "extension not found");
rv = SECFailure;
}
} else {
data.data = the_cert->derCert.data;
data.len = the_cert->derCert.len;
if (ascii) {
PR_fprintf(outfile, "%s\n%s\n%s\n", NS_CERT_HEADER,
BTOA_DataToAscii(data.data, data.len), NS_CERT_TRAILER);
rv = SECSuccess;
} else if (raw) {
numBytes = PR_Write(outfile, data.data, data.len);
rv = SECSuccess;
if (numBytes != (PRInt32)data.len) {
SECU_PrintSystemError(progName, "error writing raw cert");
rv = SECFailure;
}
} else {
rv = SEC_PrintCertificateAndTrust(the_cert, "Certificate", NULL);
if (rv != SECSuccess) {
SECU_PrintError(progName, "problem printing certificate");
}
}
}
return rv;
}
static SECStatus
listCerts(CERTCertDBHandle *handle, char *name, char *email,
PK11SlotInfo *slot, PRBool raw, PRBool ascii,
SECItem *extensionOID,
PRFileDesc *outfile, void *pwarg)
{
SECStatus rv = SECFailure;
CERTCertList *certs;
CERTCertListNode *node;
/* List certs on a non-internal slot. */
if (!PK11_IsFriendly(slot) && PK11_NeedLogin(slot)) {
SECStatus newrv = PK11_Authenticate(slot, PR_TRUE, pwarg);
if (newrv != SECSuccess) {
SECU_PrintError(progName, "could not authenticate to token %s.",
PK11_GetTokenName(slot));
return SECFailure;
}
}
if (name) {
CERTCertificate *the_cert =
SECU_FindCertByNicknameOrFilename(handle, name, ascii, NULL);
if (!the_cert) {
SECU_PrintError(progName, "Could not find cert: %s\n", name);
return SECFailure;
}
/* Here, we have one cert with the desired nickname or email
* address. Now, we will attempt to get a list of ALL certs
* with the same subject name as the cert we have. That list
* should contain, at a minimum, the one cert we have already found.
* If the list of certs is empty (NULL), the libraries have failed.
*/
certs = CERT_CreateSubjectCertList(NULL, handle, &the_cert->derSubject,
PR_Now(), PR_FALSE);
CERT_DestroyCertificate(the_cert);
if (!certs) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
SECU_PrintError(progName, "problem printing certificates");
return SECFailure;
}
for (node = CERT_LIST_HEAD(certs); !CERT_LIST_END(node, certs);
node = CERT_LIST_NEXT(node)) {
rv = outputCertOrExtension(node->cert, raw, ascii, extensionOID,
outfile);
if (rv != SECSuccess) {
break;
}
}
} else if (email) {
certs = PK11_FindCertsFromEmailAddress(email, NULL);
if (!certs) {
SECU_PrintError(progName,
"Could not find certificates for email address: %s\n",
email);
return SECFailure;
}
for (node = CERT_LIST_HEAD(certs); !CERT_LIST_END(node, certs);
node = CERT_LIST_NEXT(node)) {
rv = outputCertOrExtension(node->cert, raw, ascii, extensionOID,
outfile);
if (rv != SECSuccess) {
break;
}
}
} else {
certs = PK11_ListCertsInSlot(slot);
if (certs) {
for (node = CERT_LIST_HEAD(certs); !CERT_LIST_END(node, certs);
node = CERT_LIST_NEXT(node)) {
SECU_PrintCertNickname(node, stdout);
}
rv = SECSuccess;
}
}
if (certs) {
CERT_DestroyCertList(certs);
}
if (rv) {
SECU_PrintError(progName, "problem printing certificate nicknames");
return SECFailure;
}
return SECSuccess; /* not rv ?? */
}
static SECStatus
ListCerts(CERTCertDBHandle *handle, char *nickname, char *email,
PK11SlotInfo *slot, PRBool raw, PRBool ascii,
SECItem *extensionOID,
PRFileDesc *outfile, secuPWData *pwdata)
{
SECStatus rv;
if (slot && PK11_NeedUserInit(slot)) {
printf("\nDatabase needs user init\n");
}
if (!ascii && !raw && !nickname && !email) {
PR_fprintf(outfile, "\n%-60s %-5s\n%-60s %-5s\n\n",
"Certificate Nickname", "Trust Attributes", "",
"SSL,S/MIME,JAR/XPI");
}
if (slot == NULL) {
CERTCertList *list;
CERTCertListNode *node;
list = PK11_ListCerts(PK11CertListAll, pwdata);
for (node = CERT_LIST_HEAD(list); !CERT_LIST_END(node, list);
node = CERT_LIST_NEXT(node)) {
SECU_PrintCertNickname(node, stdout);
}
CERT_DestroyCertList(list);
return SECSuccess;
}
rv = listCerts(handle, nickname, email, slot, raw, ascii,
extensionOID, outfile, pwdata);
return rv;
}
static SECStatus
DeleteCert(CERTCertDBHandle *handle, char *name, void *pwdata)
{
SECStatus rv;
CERTCertificate *cert;
cert = CERT_FindCertByNicknameOrEmailAddrCX(handle, name, pwdata);
if (!cert) {
SECU_PrintError(progName, "could not find certificate named \"%s\"",
name);
return SECFailure;
}
rv = SEC_DeletePermCertificate(cert);
CERT_DestroyCertificate(cert);
if (rv) {
SECU_PrintError(progName, "unable to delete certificate");
}
return rv;
}
static SECStatus
RenameCert(CERTCertDBHandle *handle, char *name, char *newName, void *pwdata)
{
SECStatus rv;
CERTCertificate *cert;
cert = CERT_FindCertByNicknameOrEmailAddrCX(handle, name, pwdata);
if (!cert) {
SECU_PrintError(progName, "could not find certificate named \"%s\"",
name);
return SECFailure;
}
rv = __PK11_SetCertificateNickname(cert, newName);
CERT_DestroyCertificate(cert);
if (rv) {
SECU_PrintError(progName, "unable to rename certificate");
}
return rv;
}
static SECStatus
ValidateCert(CERTCertDBHandle *handle, char *name, char *date,
char *certUsage, PRBool checkSig, PRBool logit,
PRBool ascii, secuPWData *pwdata)
{
SECStatus rv;
CERTCertificate *cert = NULL;
PRTime timeBoundary;
SECCertificateUsage usage;
CERTVerifyLog reallog;
CERTVerifyLog *log = NULL;
if (!certUsage) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return (SECFailure);
}
switch (*certUsage) {
case 'O':
usage = certificateUsageStatusResponder;
break;
case 'L':
usage = certificateUsageSSLCA;
break;
case 'A':
usage = certificateUsageAnyCA;
break;
case 'Y':
usage = certificateUsageVerifyCA;
break;
case 'C':
usage = certificateUsageSSLClient;
break;
case 'V':
usage = certificateUsageSSLServer;
break;
case 'I':
usage = certificateUsageIPsec;
break;
case 'S':
usage = certificateUsageEmailSigner;
break;
case 'R':
usage = certificateUsageEmailRecipient;
break;
case 'J':
usage = certificateUsageObjectSigner;
break;
default:
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return (SECFailure);
}
do {
cert = SECU_FindCertByNicknameOrFilename(handle, name, ascii,
NULL);
if (!cert) {
SECU_PrintError(progName, "could not find certificate named \"%s\"",
name);
GEN_BREAK(SECFailure)
}
if (date != NULL) {
rv = DER_AsciiToTime(&timeBoundary, date);
if (rv) {
SECU_PrintError(progName, "invalid input date");
GEN_BREAK(SECFailure)
}
} else {
timeBoundary = PR_Now();
}
if (logit) {
log = &reallog;
log->count = 0;
log->head = NULL;
log->tail = NULL;
log->arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (log->arena == NULL) {
SECU_PrintError(progName, "out of memory");
GEN_BREAK(SECFailure)
}
}
rv = CERT_VerifyCertificate(handle, cert, checkSig, usage,
timeBoundary, pwdata, log, &usage);
if (log) {
if (log->head == NULL) {
fprintf(stdout, "%s: certificate is valid\n", progName);
GEN_BREAK(SECSuccess)
} else {
char *nick;
CERTVerifyLogNode *node;
node = log->head;
while (node) {
if (node->cert->nickname != NULL) {
nick = node->cert->nickname;
} else {
nick = node->cert->subjectName;
}
fprintf(stderr, "%s : %s\n", nick,
SECU_Strerror(node->error));
CERT_DestroyCertificate(node->cert);
node = node->next;
}
}
} else {
if (rv != SECSuccess) {
PRErrorCode perr = PORT_GetError();
fprintf(stdout, "%s: certificate is invalid: %s\n",
progName, SECU_Strerror(perr));
GEN_BREAK(SECFailure)
}
fprintf(stdout, "%s: certificate is valid\n", progName);
GEN_BREAK(SECSuccess)
}
} while (0);
if (cert) {
CERT_DestroyCertificate(cert);
}
return (rv);
}
static PRBool
ItemIsPrintableASCII(const SECItem *item)
{
unsigned char *src = item->data;
unsigned int len = item->len;
while (len-- > 0) {
unsigned char uc = *src++;
if (uc < 0x20 || uc > 0x7e)
return PR_FALSE;
}
return PR_TRUE;
}
/* Caller ensures that dst is at least item->len*2+1 bytes long */
static void
SECItemToHex(const SECItem *item, char *dst)
{
if (dst && item && item->data) {
unsigned char *src = item->data;
unsigned int len = item->len;
for (; len > 0; --len, dst += 2) {
snprintf(dst, 3, "%02x", *src++);
}
*dst = '\0';
}
}
static const char *const keyTypeName[] = {
"null", "rsa", "dsa", "fortezza", "dh", "kea", "ec", "rsaPss", "rsaOaep"
};
#define MAX_CKA_ID_BIN_LEN 20
#define MAX_CKA_ID_STR_LEN 40
/* output human readable key ID in buffer, which should have at least
* MAX_CKA_ID_STR_LEN + 3 octets (quotations and a null terminator) */
static void
formatPrivateKeyID(SECKEYPrivateKey *privkey, char *buffer)
{
SECItem *ckaID;
ckaID = PK11_GetLowLevelKeyIDForPrivateKey(privkey);
if (!ckaID) {
strcpy(buffer, "(no CKA_ID)");
} else if (ItemIsPrintableASCII(ckaID)) {
int len = PR_MIN(MAX_CKA_ID_STR_LEN, ckaID->len);
buffer[0] = '"';
memcpy(buffer + 1, ckaID->data, len);
buffer[1 + len] = '"';
buffer[2 + len] = '\0';
} else {
/* print ckaid in hex */
SECItem idItem = *ckaID;
if (idItem.len > MAX_CKA_ID_BIN_LEN)
idItem.len = MAX_CKA_ID_BIN_LEN;
SECItemToHex(&idItem, buffer);
}
SECITEM_ZfreeItem(ckaID, PR_TRUE);
}
/* print key number, key ID (in hex or ASCII), key label (nickname) */
static SECStatus
PrintKey(PRFileDesc *out, const char *nickName, int count,
SECKEYPrivateKey *key, void *pwarg)
{
char ckaIDbuf[MAX_CKA_ID_STR_LEN + 4];
CERTCertificate *cert;
KeyType keyType;
formatPrivateKeyID(key, ckaIDbuf);
cert = PK11_GetCertFromPrivateKey(key);
if (cert) {
keyType = CERT_GetCertKeyType(&cert->subjectPublicKeyInfo);
CERT_DestroyCertificate(cert);
} else {
keyType = key->keyType;
}
PR_fprintf(out, "<%2d> %-8.8s %-42.42s %s\n", count,
keyTypeName[keyType], ckaIDbuf, nickName);
return SECSuccess;
}
/* returns SECSuccess if ANY keys are found, SECFailure otherwise. */
static SECStatus
ListKeysInSlot(PK11SlotInfo *slot, const char *nickName, KeyType keyType,
void *pwarg)
{
SECKEYPrivateKeyList *list;
SECKEYPrivateKeyListNode *node;
int count = 0;
if (PK11_NeedLogin(slot)) {
SECStatus rv = PK11_Authenticate(slot, PR_TRUE, pwarg);
if (rv != SECSuccess) {
SECU_PrintError(progName, "could not authenticate to token %s.",
PK11_GetTokenName(slot));
return SECFailure;
}
}
if (nickName && nickName[0])
list = PK11_ListPrivKeysInSlot(slot, (char *)nickName, pwarg);
else
list = PK11_ListPrivateKeysInSlot(slot);
if (list == NULL) {
SECU_PrintError(progName, "problem listing keys");
return SECFailure;
}
for (node = PRIVKEY_LIST_HEAD(list);
!PRIVKEY_LIST_END(node, list);
node = PRIVKEY_LIST_NEXT(node)) {
char *keyName;
static const char orphan[] = { "(orphan)" };
if (keyType != nullKey && keyType != node->key->keyType)
continue;
keyName = PK11_GetPrivateKeyNickname(node->key);
if (!keyName || !keyName[0]) {
/* Try extra hard to find nicknames for keys that lack them. */
CERTCertificate *cert;
PORT_Free((void *)keyName);
keyName = NULL;
cert = PK11_GetCertFromPrivateKey(node->key);
if (cert) {
if (cert->nickname && cert->nickname[0]) {
keyName = PORT_Strdup(cert->nickname);
} else if (cert->emailAddr && cert->emailAddr[0]) {
keyName = PORT_Strdup(cert->emailAddr);
}
CERT_DestroyCertificate(cert);
}
}
if (nickName) {
if (!keyName || PL_strcmp(keyName, nickName)) {
/* PKCS#11 module returned unwanted keys */
PORT_Free((void *)keyName);
continue;
}
}
if (!keyName)
keyName = (char *)orphan;
PrintKey(PR_STDOUT, keyName, count, node->key, pwarg);
if (keyName != (char *)orphan)
PORT_Free((void *)keyName);
count++;
}
SECKEY_DestroyPrivateKeyList(list);
if (count == 0) {
PR_fprintf(PR_STDOUT, "%s: no keys found\n", progName);
return SECFailure;
}
return SECSuccess;
}
/* returns SECSuccess if ANY keys are found, SECFailure otherwise. */
static SECStatus
ListKeys(PK11SlotInfo *slot, const char *nickName, int index,
KeyType keyType, PRBool dopriv, secuPWData *pwdata)
{
SECStatus rv = SECFailure;
static const char fmt[] =
"%s: Checking token \"%.33s\" in slot \"%.65s\"\n";
if (slot == NULL) {
PK11SlotList *list;
PK11SlotListElement *le;
list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE, pwdata);
if (list) {
for (le = list->head; le; le = le->next) {
PR_fprintf(PR_STDOUT, fmt, progName,
PK11_GetTokenName(le->slot),
PK11_GetSlotName(le->slot));
rv &= ListKeysInSlot(le->slot, nickName, keyType, pwdata);
}
PK11_FreeSlotList(list);
}
} else {
PR_fprintf(PR_STDOUT, fmt, progName, PK11_GetTokenName(slot),
PK11_GetSlotName(slot));
rv = ListKeysInSlot(slot, nickName, keyType, pwdata);
}
return rv;
}
static SECStatus
DeleteCertAndKey(char *nickname, secuPWData *pwdata)
{
SECStatus rv;
CERTCertificate *cert;
PK11SlotInfo *slot;
slot = PK11_GetInternalKeySlot();
if (PK11_NeedLogin(slot)) {
rv = PK11_Authenticate(slot, PR_TRUE, pwdata);
if (rv != SECSuccess) {
SECU_PrintError(progName, "could not authenticate to token %s.",
PK11_GetTokenName(slot));
return SECFailure;
}
}
cert = PK11_FindCertFromNickname(nickname, pwdata);
if (!cert) {
PK11_FreeSlot(slot);
return SECFailure;
}
rv = PK11_DeleteTokenCertAndKey(cert, pwdata);
if (rv != SECSuccess) {
SECU_PrintError("problem deleting private key \"%s\"\n", nickname);
}
CERT_DestroyCertificate(cert);
PK11_FreeSlot(slot);
return rv;
}
static SECKEYPrivateKey *
findPrivateKeyByID(PK11SlotInfo *slot, const char *ckaID, secuPWData *pwarg)
{
PORTCheapArenaPool arena;
SECItem ckaIDItem = { 0 };
SECKEYPrivateKey *privkey = NULL;
SECStatus rv;
if (PK11_NeedLogin(slot)) {
rv = PK11_Authenticate(slot, PR_TRUE, pwarg);
if (rv != SECSuccess) {
SECU_PrintError(progName, "could not authenticate to token %s.",
PK11_GetTokenName(slot));
return NULL;
}
}
if (0 == PL_strncasecmp("0x", ckaID, 2)) {
ckaID += 2; /* skip leading "0x" */
}
PORT_InitCheapArena(&arena, DER_DEFAULT_CHUNKSIZE);
if (SECU_HexString2SECItem(&arena.arena, &ckaIDItem, ckaID)) {
privkey = PK11_FindKeyByKeyID(slot, &ckaIDItem, pwarg);
}
PORT_DestroyCheapArena(&arena);
return privkey;
}
static SECStatus
DeleteKey(SECKEYPrivateKey *privkey, secuPWData *pwarg)
{
SECStatus rv;
PK11SlotInfo *slot;
slot = PK11_GetSlotFromPrivateKey(privkey);
if (PK11_NeedLogin(slot)) {
rv = PK11_Authenticate(slot, PR_TRUE, pwarg);
if (rv != SECSuccess) {
SECU_PrintError(progName, "could not authenticate to token %s.",
PK11_GetTokenName(slot));
return SECFailure;
}
}
rv = PK11_DeleteTokenPrivateKey(privkey, PR_TRUE);
if (rv != SECSuccess) {
char ckaIDbuf[MAX_CKA_ID_STR_LEN + 4];
formatPrivateKeyID(privkey, ckaIDbuf);
SECU_PrintError("problem deleting private key \"%s\"\n", ckaIDbuf);
}
PK11_FreeSlot(slot);
return rv;
}
/*
* L i s t M o d u l e s
*
* Print a list of the PKCS11 modules that are
* available. This is useful for smartcard people to
* make sure they have the drivers loaded.
*
*/
static SECStatus
ListModules(void)
{
PK11SlotList *list;
PK11SlotListElement *le;
/* get them all! */
list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE, NULL);
if (list == NULL)
return SECFailure;
/* look at each slot*/
for (le = list->head; le; le = le->next) {
char *token_uri = PK11_GetTokenURI(le->slot);
printf("\n");
printf(" slot: %s\n", PK11_GetSlotName(le->slot));
printf(" token: %s\n", PK11_GetTokenName(le->slot));
printf(" uri: %s\n", token_uri);
PORT_Free(token_uri);
}
PK11_FreeSlotList(list);
return SECSuccess;
}
static void
PrintBuildFlags()
{
#ifdef NSS_FIPS_DISABLED
PR_fprintf(PR_STDOUT, "NSS_FIPS_DISABLED\n");
#endif
#ifdef NSS_NO_INIT_SUPPORT
PR_fprintf(PR_STDOUT, "NSS_NO_INIT_SUPPORT\n");
#endif
exit(0);
}
static void
PrintSyntax()
{
#define FPS fprintf(stderr,
FPS "Type %s -H for more detailed descriptions\n", progName);
FPS "Usage: %s -N [-d certdir] [-P dbprefix] [-f pwfile] [--empty-password]\n", progName);
FPS "Usage: %s -T [-d certdir] [-P dbprefix] [-h token-name]\n"
"\t\t [-f pwfile] [-0 SSO-password]\n", progName);
FPS "\t%s -A -n cert-name -t trustargs [-d certdir] [-P dbprefix] [-a] [-i input]\n",
progName);
FPS "\t%s -B -i batch-file\n", progName);
FPS "\t%s -C [-c issuer-name | -x] -i cert-request-file -o cert-file\n"
"\t\t [-m serial-number] [-w warp-months] [-v months-valid]\n"
"\t\t [-f pwfile] [-d certdir] [-P dbprefix] [-Z hashAlg]\n"
"\t\t [-1 | --keyUsage [keyUsageKeyword,..]] [-2] [-3] [-4]\n"
"\t\t [-5 | --nsCertType [nsCertTypeKeyword,...]]\n"
"\t\t [-6 | --extKeyUsage [extKeyUsageKeyword,...]] [-7 emailAddrs]\n"
"\t\t [-8 dns-names] [-a]\n",
progName);
FPS "\t%s -D -n cert-name [-d certdir] [-P dbprefix]\n", progName);
FPS "\t%s --rename -n cert-name --new-n new-cert-name\n"
"\t\t [-d certdir] [-P dbprefix]\n", progName);
FPS "\t%s -E -n cert-name -t trustargs [-d certdir] [-P dbprefix] [-a] [-i input]\n",
progName);
FPS "\t%s -F -n cert-name [-d certdir] [-P dbprefix]\n",
progName);
FPS "\t%s -F -k key-id [-d certdir] [-P dbprefix]\n",
progName);
FPS "\t%s -G -n key-name [-h token-name] [-k rsa] [-g key-size] [-y exp]\n"
"\t\t [-f pwfile] [-z noisefile] [-d certdir] [-P dbprefix]\n", progName);
FPS "\t%s -G [-h token-name] -k dsa [-q pqgfile -g key-size] [-f pwfile]\n"
"\t\t [-z noisefile] [-d certdir] [-P dbprefix]\n", progName);
FPS "\t%s -G [-h token-name] -k ec -q curve [-f pwfile]\n"
"\t\t [-z noisefile] [-d certdir] [-P dbprefix]\n", progName);
FPS "\t%s -K [-n key-name] [-h token-name] [-k dsa|ec|rsa|all]\n",
progName);
FPS "\t\t [-f pwfile] [-X] [-d certdir] [-P dbprefix]\n");
FPS "\t%s --upgrade-merge --source-dir upgradeDir --upgrade-id uniqueID\n",
progName);
FPS "\t\t [--upgrade-token-name tokenName] [-d targetDBDir]\n");
FPS "\t\t [-P targetDBPrefix] [--source-prefix upgradeDBPrefix]\n");
FPS "\t\t [-f targetPWfile] [-@ upgradePWFile]\n");
FPS "\t%s --merge --source-dir sourceDBDir [-d targetDBdir]\n",
progName);
FPS "\t\t [-P targetDBPrefix] [--source-prefix sourceDBPrefix]\n");
FPS "\t\t [-f targetPWfile] [-@ sourcePWFile]\n");
FPS "\t%s -L [-n cert-name] [-h token-name] [--email email-address]\n",
progName);
FPS "\t\t [-X] [-r] [-a] [--dump-ext-val OID] [-d certdir] [-P dbprefix]\n");
FPS "\t%s --build-flags\n", progName);
FPS "\t%s -M -n cert-name -t trustargs [-d certdir] [-P dbprefix]\n",
progName);
FPS "\t%s -O -n cert-name [-X] [-d certdir] [-a] [-P dbprefix]\n"
"\t\t [--simple-self-signed]\n",
progName);
FPS "\t%s -R -s subj -o cert-request-file [-d certdir] [-P dbprefix] [-p phone] [-a]\n"
"\t\t [-7 emailAddrs] [-k key-type-or-id] [-h token-name] [-f pwfile]\n"
"\t\t [-g key-size] [-Z hashAlg]\n",
progName);
FPS "\t%s -V -n cert-name -u usage [-b time] [-e] [-a]\n"
"\t\t[-X] [-d certdir] [-P dbprefix]\n",
progName);
FPS "Usage: %s -W [-d certdir] [-f pwfile] [-@newpwfile]\n",
progName);
FPS "\t%s -S -n cert-name -s subj [-c issuer-name | -x] -t trustargs\n"
"\t\t [-k key-type-or-id] [-q key-params] [-h token-name] [-g key-size]\n"
"\t\t [-m serial-number] [-w warp-months] [-v months-valid]\n"
"\t\t [-f pwfile] [-d certdir] [-P dbprefix] [-Z hashAlg]\n"
"\t\t [-p phone] [-1] [-2] [-3] [-4] [-5] [-6] [-7 emailAddrs]\n"
"\t\t [-8 DNS-names]\n"
"\t\t [--extAIA] [--extSIA] [--extCP] [--extPM] [--extPC] [--extIA]\n"
"\t\t [--extSKID] [--extNC] [--extSAN type:name[,type:name]...]\n"
"\t\t [--extGeneric OID:critical-flag:filename[,OID:critical-flag:filename]...]\n", progName);
FPS "\t%s -U [-X] [-d certdir] [-P dbprefix]\n", progName);
exit(1);
}
enum usage_level {
usage_all = 0,
usage_selected = 1
};
static void luCommonDetailsAE();
static void
luA(enum usage_level ul, const char *command)
{
int is_my_command = (command && 0 == strcmp(command, "A"));
if (ul == usage_all || !command || is_my_command)
FPS "%-15s Add a certificate to the database (create if needed)\n",
"-A");
if (ul == usage_selected && !is_my_command)
return;
if (ul == usage_all) {
FPS "%-20s\n", " All options under -E apply");
} else {
luCommonDetailsAE();
}
}
static void
luB(enum usage_level ul, const char *command)
{
int is_my_command = (command && 0 == strcmp(command, "B"));
if (ul == usage_all || !command || is_my_command)
FPS "%-15s Run a series of certutil commands from a batch file\n", "-B");
if (ul == usage_selected && !is_my_command)
return;
FPS "%-20s Specify the batch file\n", " -i batch-file");
}
static void
luE(enum usage_level ul, const char *command)
{
int is_my_command = (command && 0 == strcmp(command, "E"));
if (ul == usage_all || !command || is_my_command)
FPS "%-15s Add an Email certificate to the database (create if needed)\n",
"-E");
if (ul == usage_selected && !is_my_command)
return;
luCommonDetailsAE();
}
static void
luCommonDetailsAE()
{
FPS "%-20s Specify the nickname of the certificate to add\n",
" -n cert-name");
FPS "%-20s Set the certificate trust attributes:\n",
" -t trustargs");
FPS "%-25s trustargs is of the form x,y,z where x is for SSL, y is for S/MIME,\n", "");
FPS "%-25s and z is for code signing. Use ,, for no explicit trust.\n", "");
FPS "%-25s p \t prohibited (explicitly distrusted)\n", "");
FPS "%-25s P \t trusted peer\n", "");
FPS "%-25s c \t valid CA\n", "");
FPS "%-25s T \t trusted CA to issue client certs (implies c)\n", "");
FPS "%-25s C \t trusted CA to issue server certs (implies c)\n", "");
FPS "%-25s u \t user cert\n", "");
FPS "%-25s w \t send warning\n", "");
FPS "%-25s g \t make step-up cert\n", "");
FPS "%-20s Specify the password file\n",
" -f pwfile");
FPS "%-20s Cert database directory (default is ~/.netscape)\n",
" -d certdir");
FPS "%-20s Cert & Key database prefix\n",
" -P dbprefix");
FPS "%-20s The input certificate is encoded in ASCII (RFC1113)\n",
" -a");
FPS "%-20s Specify the certificate file (default is stdin)\n",
" -i input");
FPS "\n");
}
static void
luC(enum usage_level ul, const char *command)
{
int is_my_command = (command && 0 == strcmp(command, "C"));
if (ul == usage_all || !command || is_my_command)
FPS "%-15s Create a new binary certificate from a BINARY cert request\n",
"-C");
if (ul == usage_selected && !is_my_command)
return;
FPS "%-20s The nickname of the issuer cert\n",
" -c issuer-name");
FPS "%-20s The BINARY certificate request file\n",
" -i cert-request ");
FPS "%-20s Output binary cert to this file (default is stdout)\n",
" -o output-cert");
FPS "%-20s Self sign\n",
" -x");
FPS "%-20s Sign the certificate with RSA-PSS (the issuer key must be rsa)\n",
" --pss-sign");
FPS "%-20s Cert serial number\n",
" -m serial-number");
FPS "%-20s Time Warp\n",
" -w warp-months");
FPS "%-20s Months valid (default is 3)\n",
" -v months-valid");
FPS "%-20s Specify the password file\n",
" -f pwfile");
FPS "%-20s Cert database directory (default is ~/.netscape)\n",
" -d certdir");
FPS "%-20s Cert & Key database prefix\n",
" -P dbprefix");
FPS "%-20s \n"
"%-20s Specify the hash algorithm to use. Possible keywords:\n"
"%-20s \"MD2\", \"MD4\", \"MD5\", \"SHA1\", \"SHA224\",\n"
"%-20s \"SHA256\", \"SHA384\", \"SHA512\"\n",
" -Z hashAlg", "", "", "");
FPS "%-20s \n"
"%-20s Create key usage extension. Possible keywords:\n"
"%-20s \"digitalSignature\", \"nonRepudiation\", \"keyEncipherment\",\n"
"%-20s \"dataEncipherment\", \"keyAgreement\", \"certSigning\",\n"
"%-20s \"crlSigning\", \"critical\"\n",
" -1 | --keyUsage keyword,keyword,...", "", "", "", "");
FPS "%-20s Create basic constraint extension\n",
" -2 ");
FPS "%-20s Create authority key ID extension\n",
" -3 ");
FPS "%-20s Create crl distribution point extension\n",
" -4 ");
FPS "%-20s \n"
"%-20s Create netscape cert type extension. Possible keywords:\n"
"%-20s \"sslClient\", \"sslServer\", \"smime\", \"objectSigning\",\n"
"%-20s \"sslCA\", \"smimeCA\", \"objectSigningCA\", \"critical\".\n",
" -5 | --nsCertType keyword,keyword,... ", "", "", "");
FPS "%-20s \n"
"%-20s Create extended key usage extension. Possible keywords:\n"
"%-20s \"serverAuth\", \"clientAuth\",\"codeSigning\",\n"
"%-20s \"emailProtection\", \"timeStamp\",\"ocspResponder\",\n"
"%-20s \"stepUp\", \"msTrustListSign\", \"x509Any\",\n"
"%-20s \"ipsecIKE\", \"ipsecIKEEnd\", \"ipsecIKEIntermediate\",\n"
"%-20s \"ipsecEnd\", \"ipsecTunnel\", \"ipsecUser\",\n"
"%-20s \"critical\"\n",
" -6 | --extKeyUsage keyword,keyword,...", "", "", "", "", "", "", "");
FPS "%-20s Create an email subject alt name extension\n",
" -7 emailAddrs");
FPS "%-20s Create an dns subject alt name extension\n",
" -8 dnsNames");
FPS "%-20s The input certificate request is encoded in ASCII (RFC1113)\n",
" -a");
FPS "\n");
}
static void
luG(enum usage_level ul, const char *command)
{
int is_my_command = (command && 0 == strcmp(command, "G"));
if (ul == usage_all || !command || is_my_command)
FPS "%-15s Generate a new key pair\n",
"-G");
if (ul == usage_selected && !is_my_command)
return;
FPS "%-20s Name of token in which to generate key (default is internal)\n",
" -h token-name");
FPS "%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n",
" -k key-type");
FPS "%-20s Key size in bits, (min %d, max %d, default %d) (not for ec)\n",
" -g key-size", MIN_KEY_BITS, MAX_KEY_BITS, DEFAULT_KEY_BITS);
FPS "%-20s Set the public exponent value (3, 17, 65537) (rsa only)\n",
" -y exp");
FPS "%-20s Specify the password file\n",
" -f password-file");
FPS "%-20s Specify the noise file to be used\n",
" -z noisefile");
FPS "%-20s read PQG value from pqgfile (dsa only)\n",
" -q pqgfile");
FPS "%-20s Elliptic curve name (ec only)\n",
" -q curve-name");
FPS "%-20s One of nistp256, nistp384, nistp521, curve25519.\n", "");
FPS "%-20s If a custom token is present, the following curves are also supported:\n", "");
FPS "%-20s sect163k1, nistk163, sect163r1, sect163r2,\n", "");
FPS "%-20s nistb163, sect193r1, sect193r2, sect233k1, nistk233,\n", "");
FPS "%-20s sect233r1, nistb233, sect239k1, sect283k1, nistk283,\n", "");
FPS "%-20s sect283r1, nistb283, sect409k1, nistk409, sect409r1,\n", "");
FPS "%-20s nistb409, sect571k1, nistk571, sect571r1, nistb571,\n", "");
FPS "%-20s secp160k1, secp160r1, secp160r2, secp192k1, secp192r1,\n", "");
FPS "%-20s nistp192, secp224k1, secp224r1, nistp224, secp256k1,\n", "");
FPS "%-20s secp256r1, secp384r1, secp521r1,\n", "");
FPS "%-20s prime192v1, prime192v2, prime192v3, \n", "");
FPS "%-20s prime239v1, prime239v2, prime239v3, c2pnb163v1, \n", "");
FPS "%-20s c2pnb163v2, c2pnb163v3, c2pnb176v1, c2tnb191v1, \n", "");
FPS "%-20s c2tnb191v2, c2tnb191v3, \n", "");
FPS "%-20s c2pnb208w1, c2tnb239v1, c2tnb239v2, c2tnb239v3, \n", "");
FPS "%-20s c2pnb272w1, c2pnb304w1, \n", "");
FPS "%-20s c2tnb359w1, c2pnb368w1, c2tnb431r1, secp112r1, \n", "");
FPS "%-20s secp112r2, secp128r1, secp128r2, sect113r1, sect113r2\n", "");
FPS "%-20s sect131r1, sect131r2\n", "");
FPS "%-20s Key database directory (default is ~/.netscape)\n",
" -d keydir");
FPS "%-20s Cert & Key database prefix\n",
" -P dbprefix");
FPS "%-20s\n"
"%-20s PKCS #11 key Attributes.\n",
" --keyAttrFlags attrflags", "");
FPS "%-20s Comma separated list of key attribute attribute flags,\n", "");
FPS "%-20s selected from the following list of choices:\n", "");
FPS "%-20s {token | session} {public | private} {sensitive | insensitive}\n", "");
FPS "%-20s {modifiable | unmodifiable} {extractable | unextractable}\n", "");
FPS "%-20s\n",
" --keyOpFlagsOn opflags");
FPS "%-20s\n"
"%-20s PKCS #11 key Operation Flags.\n",
" --keyOpFlagsOff opflags", "");
FPS "%-20s Comma separated list of one or more of the following:\n", "");
FPS "%-20s encrypt, decrypt, sign, sign_recover, verify,\n", "");
FPS "%-20s verify_recover, wrap, unwrap, derive\n", "");
FPS "\n");
}
static void
luD(enum usage_level ul, const char *command)
{
int is_my_command = (command && 0 == strcmp(command, "D"));
if (ul == usage_all || !command || is_my_command)
FPS "%-15s Delete a certificate from the database\n",
"-D");
if (ul == usage_selected && !is_my_command)
return;
FPS "%-20s The nickname of the cert to delete\n",
" -n cert-name");
FPS "%-20s Cert database directory (default is ~/.netscape)\n",
" -d certdir");
FPS "%-20s Cert & Key database prefix\n",
" -P dbprefix");
FPS "\n");
}
static void
luF(enum usage_level ul, const char *command)
{
int is_my_command = (command && 0 == strcmp(command, "F"));
if (ul == usage_all || !command || is_my_command)
FPS "%-15s Delete a key and associated certificate from the database\n",
"-F");
if (ul == usage_selected && !is_my_command)
return;
FPS "%-20s The nickname of the key to delete\n",
" -n cert-name");
FPS "%-20s The key id of the key to delete, obtained using -K\n",
" -k key-id");
FPS "%-20s Cert database directory (default is ~/.netscape)\n",
" -d certdir");
FPS "%-20s Cert & Key database prefix\n",
" -P dbprefix");
FPS "\n");
}
static void
luU(enum usage_level ul, const char *command)
{
int is_my_command = (command && 0 == strcmp(command, "U"));
if (ul == usage_all || !command || is_my_command)
FPS "%-15s List all modules\n", /*, or print out a single named module\n",*/
"-U");
if (ul == usage_selected && !is_my_command)
return;
FPS "%-20s Module database directory (default is '~/.netscape')\n",
" -d moddir");
FPS "%-20s Cert & Key database prefix\n",
" -P dbprefix");
FPS "%-20s force the database to open R/W\n",
" -X");
FPS "\n");
}
static void
luK(enum usage_level ul, const char *command)
{
int is_my_command = (command && 0 == strcmp(command, "K"));
if (ul == usage_all || !command || is_my_command)
FPS "%-15s List all private keys\n",
"-K");
if (ul == usage_selected && !is_my_command)
return;
FPS "%-20s Name of token to search (\"all\" for all tokens)\n",
" -h token-name ");
FPS "%-20s Key type (\"all\" (default), \"dsa\","
" \"ec\","
" \"rsa\")\n",
" -k key-type");
FPS "%-20s The nickname of the key or associated certificate\n",
" -n name");
FPS "%-20s Specify the password file\n",
" -f password-file");
FPS "%-20s Key database directory (default is ~/.netscape)\n",
" -d keydir");
FPS "%-20s Cert & Key database prefix\n",
" -P dbprefix");
FPS "%-20s force the database to open R/W\n",
" -X");
FPS "\n");
}
static void
luL(enum usage_level ul, const char *command)
{
int is_my_command = (command && 0 == strcmp(command, "L"));
if (ul == usage_all || !command || is_my_command)
FPS "%-15s List all certs, or print out a single named cert (or a subset)\n",
"-L");
if (ul == usage_selected && !is_my_command)
return;
FPS "%-20s Name of token to search (\"all\" for all tokens)\n",
" -h token-name ");
FPS "%-20s Pretty print named cert (list all if unspecified)\n",
" -n cert-name");
FPS "%-20s \n"
"%-20s Pretty print cert with email address (list all if unspecified)\n",
" --email email-address", "");
FPS "%-20s Cert database directory (default is ~/.netscape)\n",
" -d certdir");
FPS "%-20s Cert & Key database prefix\n",
" -P dbprefix");
FPS "%-20s force the database to open R/W\n",
" -X");
FPS "%-20s For single cert, print binary DER encoding\n",
" -r");
FPS "%-20s For single cert, print ASCII encoding (RFC1113)\n",
" -a");
FPS "%-20s \n"
"%-20s For single cert, print binary DER encoding of extension OID\n",
" --dump-ext-val OID", "");
FPS "\n");
}
static void
luM(enum usage_level ul, const char *command)
{
int is_my_command = (command && 0 == strcmp(command, "M"));
if (ul == usage_all || !command || is_my_command)
FPS "%-15s Modify trust attributes of certificate\n",
"-M");
if (ul == usage_selected && !is_my_command)
return;
FPS "%-20s The nickname of the cert to modify\n",
" -n cert-name");
FPS "%-20s Set the certificate trust attributes (see -A above)\n",
" -t trustargs");
FPS "%-20s Cert database directory (default is ~/.netscape)\n",
" -d certdir");
FPS "%-20s Cert & Key database prefix\n",
" -P dbprefix");
FPS "\n");
}
static void
luN(enum usage_level ul, const char *command)
{
int is_my_command = (command && 0 == strcmp(command, "N"));
if (ul == usage_all || !command || is_my_command)
FPS "%-15s Create a new certificate database\n",
"-N");
if (ul == usage_selected && !is_my_command)
return;
FPS "%-20s Cert database directory (default is ~/.netscape)\n",
" -d certdir");
FPS "%-20s Cert & Key database prefix\n",
" -P dbprefix");
FPS "%-20s Specify the password file\n",
" -f password-file");
FPS "%-20s use empty password when creating a new database\n",
" --empty-password");
FPS "\n");
}
static void
luT(enum usage_level ul, const char *command)
{
int is_my_command = (command && 0 == strcmp(command, "T"));
if (ul == usage_all || !command || is_my_command)
FPS "%-15s Reset the Key database or token\n",
"-T");
if (ul == usage_selected && !is_my_command)
return;
FPS "%-20s Cert database directory (default is ~/.netscape)\n",
" -d certdir");
FPS "%-20s Cert & Key database prefix\n",
" -P dbprefix");
FPS "%-20s Token to reset (default is internal)\n",
" -h token-name");
FPS "%-20s Set token's Site Security Officer password\n",
" -0 SSO-password");
FPS "\n");
}
static void
luO(enum usage_level ul, const char *command)
{
int is_my_command = (command && 0 == strcmp(command, "O"));
if (ul == usage_all || !command || is_my_command)
FPS "%-15s Print the chain of a certificate\n",
"-O");
if (ul == usage_selected && !is_my_command)
return;
FPS "%-20s The nickname of the cert to modify\n",
" -n cert-name");
FPS "%-20s Cert database directory (default is ~/.netscape)\n",
" -d certdir");
FPS "%-20s Input the certificate in ASCII (RFC1113); default is binary\n",
" -a");
FPS "%-20s Cert & Key database prefix\n",
" -P dbprefix");
FPS "%-20s force the database to open R/W\n",
" -X");
FPS "%-20s don't search for a chain if issuer name equals subject name\n",
" --simple-self-signed");
FPS "\n");
}
static void
luR(enum usage_level ul, const char *command)
{
int is_my_command = (command && 0 == strcmp(command, "R"));
if (ul == usage_all || !command || is_my_command)
FPS "%-15s Generate a certificate request (stdout)\n",
"-R");