/* 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
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* ** certutil.c ** ** utility for managing certificates and the cert database **
*/ #include <stdio.h> #include <string.h> #include <stdlib.h>
/* 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;
}
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);
}
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;
}
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);
/* 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;
}
}
} elseif (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;
}
/* output human readable key ID in buffer, which should have at least
* MAX_CKA_ID_STR_LEN + 3 octets (quotations and a null terminator) */ staticvoid
formatPrivateKeyID(SECKEYPrivateKey *privkey, char *buffer)
{
SECItem *ckaID;
/* * 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);
staticvoid
luA(enum usage_level ul, constchar *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();
}
}
staticvoid
luB(enum usage_level ul, constchar *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");
}
staticvoid
luE(enum usage_level ul, constchar *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();
}
staticvoid
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");
}
staticvoid
luC(enum usage_level ul, constchar *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");
}
staticvoid
luG(enum usage_level ul, constchar *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");
}
staticvoid
luD(enum usage_level ul, constchar *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");
}
staticvoid
luF(enum usage_level ul, constchar *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");
}
staticvoid
luU(enum usage_level ul, constchar *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");
}
staticvoid
luK(enum usage_level ul, constchar *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");
}
staticvoid
luL(enum usage_level ul, constchar *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");
}
staticvoid
luM(enum usage_level ul, constchar *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");
}
staticvoid
luN(enum usage_level ul, constchar *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");
}
staticvoid
luT(enum usage_level ul, constchar *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");
}
staticvoid
luO(enum usage_level ul, constchar *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");
}
staticvoid
luR(enum usage_level ul, constchar *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"); if (ul == usage_selected && !is_my_command) return;
FPS "%-20s Specify the subject name (using RFC1485)\n", " -s subject");
FPS "%-20s Output the cert request to this file\n", " -o output-req");
FPS "%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n", " -k key-type-or-id");
FPS "%-20s or nickname of the cert key to use, or key id obtained using -K\n", "");
FPS "%-20s Name of token in which to generate key (default is internal)\n", " -h token-name");
FPS "%-20s Key size in bits, RSA keys only (min %d, max %d, default %d)\n", " -g key-size", MIN_KEY_BITS, MAX_KEY_BITS, DEFAULT_KEY_BITS);
FPS "%-20s Create a certificate request restricted to RSA-PSS (rsa only)\n", " --pss");
FPS "%-20s Name of file containing PQG parameters (dsa only)\n", " -q pqgfile");
FPS "%-20s Elliptic curve name (ec only)\n", " -q curve-name");
FPS "%-20s See the \"-G\" option for a full list of supported names.\n", "");
FPS "%-20s Specify the password file\n", " -f pwfile");
FPS "%-20s Key database directory (default is ~/.netscape)\n", " -d keydir");
FPS "%-20s Cert & Key database prefix\n", " -P dbprefix");
FPS "%-20s Specify the contact phone number (\"123-456-7890\")\n", " -p phone");
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 Output the cert request in ASCII (RFC1113); default is binary\n", " -a");
FPS "%-20s \n", " See -S for available extension options");
FPS "%-20s \n", " See -G for available key flag options");
FPS "\n");
}
staticvoid
luV(enum usage_level ul, constchar *command)
{ int is_my_command = (command && 0 == strcmp(command, "V")); if (ul == usage_all || !command || is_my_command)
FPS "%-15s Validate a certificate\n", "-V"); if (ul == usage_selected && !is_my_command) return;
FPS "%-20s The nickname of the cert to Validate\n", " -n cert-name");
FPS "%-20s validity time (\"YYMMDDHHMMSS[+HHMM|-HHMM|Z]\")\n", " -b time");
FPS "%-20s Check certificate signature \n", " -e ");
FPS "%-20s Specify certificate usage:\n", " -u certusage");
FPS "%-25s C \t SSL Client\n", "");
FPS "%-25s V \t SSL Server\n", "");
FPS "%-25s I \t IPsec\n", "");
FPS "%-25s L \t SSL CA\n", "");
FPS "%-25s A \t Any CA\n", "");
FPS "%-25s Y \t Verify CA\n", "");
FPS "%-25s S \t Email signer\n", "");
FPS "%-25s R \t Email Recipient\n", "");
FPS "%-25s O \t OCSP status responder\n", "");
FPS "%-25s J \t Object signer\n", "");
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 "\n");
}
staticvoid
luW(enum usage_level ul, constchar *command)
{ int is_my_command = (command && 0 == strcmp(command, "W")); if (ul == usage_all || !command || is_my_command)
FPS "%-15s Change the key database password\n", "-W"); if (ul == usage_selected && !is_my_command) return;
FPS "%-20s cert and key database directory\n", " -d certdir");
FPS "%-20s Specify a file with the current password\n", " -f pwfile");
FPS "%-20s Specify a file with the new password in two lines\n", " -@ newpwfile");
FPS "\n");
}
staticvoid
luRename(enum usage_level ul, constchar *command)
{ int is_my_command = (command && 0 == strcmp(command, "rename")); if (ul == usage_all || !command || is_my_command)
FPS "%-15s Change the database nickname of a certificate\n", "--rename"); if (ul == usage_selected && !is_my_command) return;
FPS "%-20s The old nickname of the cert to rename\n", " -n cert-name");
FPS "%-20s The new nickname of the cert to rename\n", " --new-n new-name");
FPS "%-20s Cert database directory (default is ~/.netscape)\n", " -d certdir");
FPS "%-20s Cert & Key database prefix\n", " -P dbprefix");
FPS "\n");
}
staticvoid
luUpgradeMerge(enum usage_level ul, constchar *command)
{ int is_my_command = (command && 0 == strcmp(command, "upgrade-merge")); if (ul == usage_all || !command || is_my_command)
FPS "%-15s Upgrade an old database and merge it into a new one\n", "--upgrade-merge"); if (ul == usage_selected && !is_my_command) return;
FPS "%-20s Cert database directory to merge into (default is ~/.netscape)\n", " -d certdir");
FPS "%-20s Cert & Key database prefix of the target database\n", " -P dbprefix");
FPS "%-20s Specify the password file for the target database\n", " -f pwfile");
FPS "%-20s \n%-20s Cert database directory to upgrade from\n", " --source-dir certdir", "");
FPS "%-20s \n%-20s Cert & Key database prefix of the upgrade database\n", " --source-prefix dbprefix", "");
FPS "%-20s \n%-20s Unique identifier for the upgrade database\n", " --upgrade-id uniqueID", "");
FPS "%-20s \n%-20s Name of the token while it is in upgrade state\n", " --upgrade-token-name name", "");
FPS "%-20s Specify the password file for the upgrade database\n", " -@ pwfile");
FPS "\n");
}
staticvoid
luMerge(enum usage_level ul, constchar *command)
{ int is_my_command = (command && 0 == strcmp(command, "merge")); if (ul == usage_all || !command || is_my_command)
FPS "%-15s Merge source database into the target database\n", "--merge"); if (ul == usage_selected && !is_my_command) return;
FPS "%-20s Cert database directory of target (default is ~/.netscape)\n", " -d certdir");
FPS "%-20s Cert & Key database prefix of the target database\n", " -P dbprefix");
FPS "%-20s Specify the password file for the target database\n", " -f pwfile");
FPS "%-20s \n%-20s Cert database directory of the source database\n", " --source-dir certdir", "");
FPS "%-20s \n%-20s Cert & Key database prefix of the source database\n", " --source-prefix dbprefix", "");
FPS "%-20s Specify the password file for the source database\n", " -@ pwfile");
FPS "\n");
}
staticvoid
luS(enum usage_level ul, constchar *command)
{ int is_my_command = (command && 0 == strcmp(command, "S")); if (ul == usage_all || !command || is_my_command)
FPS "%-15s Make a certificate and add to database\n", "-S"); if (ul == usage_selected && !is_my_command) return;
FPS "%-20s Specify the nickname of the cert\n", " -n key-name");
FPS "%-20s Specify the subject name (using RFC1485)\n", " -s subject");
FPS "%-20s The nickname of the issuer cert\n", " -c issuer-name");
FPS "%-20s Set the certificate trust attributes (see -A above)\n", " -t trustargs");
FPS "%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n", " -k key-type-or-id");
FPS "%-20s Name of token in which to generate key (default is internal)\n", " -h token-name");
FPS "%-20s Key size in bits, RSA keys only (min %d, max %d, default %d)\n", " -g key-size", MIN_KEY_BITS, MAX_KEY_BITS, DEFAULT_KEY_BITS);
FPS "%-20s Create a certificate restricted to RSA-PSS (rsa only)\n", " --pss");
FPS "%-20s Name of file containing PQG parameters (dsa only)\n", " -q pqgfile");
FPS "%-20s Elliptic curve name (ec only)\n", " -q curve-name");
FPS "%-20s See the \"-G\" option for a full list of supported names.\n", "");
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 Specify the contact phone number (\"123-456-7890\")\n", " -p phone");
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 Create key usage extension\n", " -1 ");
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 Create netscape cert type extension\n", " -5 ");
FPS "%-20s Create extended key usage extension\n", " -6 ");
FPS "%-20s Create an email subject alt name extension\n", " -7 emailAddrs ");
FPS "%-20s Create a DNS subject alt name extension\n", " -8 DNS-names");
FPS "%-20s Create an Authority Information Access extension\n", " --extAIA ");
FPS "%-20s Create a Subject Information Access extension\n", " --extSIA ");
FPS "%-20s Create a Certificate Policies extension\n", " --extCP ");
FPS "%-20s Create a Policy Mappings extension\n", " --extPM ");
FPS "%-20s Create a Policy Constraints extension\n", " --extPC ");
FPS "%-20s Create an Inhibit Any Policy extension\n", " --extIA ");
FPS "%-20s Create a subject key ID extension\n", " --extSKID ");
FPS "%-20s \n", " See -G for available key flag options");
FPS "%-20s Create a name constraints extension\n", " --extNC ");
FPS "%-20s \n" "%-20s Create a Subject Alt Name extension with one or multiple names\n", " --extSAN type:name[,type:name]...", "");
FPS "%-20s - type: directory, dn, dns, edi, ediparty, email, ip, ipaddr,\n", "");
FPS "%-20s other, registerid, rfc822, uri, x400, x400addr\n", "");
FPS "%-20s \n" "%-20s Add one or multiple extensions that certutil cannot encode yet,\n" "%-20s by loading their encodings from external files.\n", " --extGeneric OID:critical-flag:filename[,OID:critical-flag:filename]...", "", "");
FPS "%-20s - OID (example): 1.2.3.4\n", "");
FPS "%-20s - critical-flag: critical or not-critical\n", "");
FPS "%-20s - filename: full path to a file containing an encoded extension\n", "");
FPS "\n");
}
staticvoid
luBuildFlags(enum usage_level ul, constchar *command)
{ int is_my_command = (command && 0 == strcmp(command, "build-flags")); if (ul == usage_all || !command || is_my_command)
FPS "%-15s Print enabled build flags relevant for NSS test execution\n", "--build-flags"); if (ul == usage_selected && !is_my_command) return;
FPS "\n");
}
staticvoid
Usage()
{
PR_fprintf(PR_STDERR, "%s - Utility to manipulate NSS certificate databases\n\n" "Usage: %s <command> -d <database-directory> <options>\n\n" "Valid commands:\n",
progName, progName);
LongUsage(usage_selected, NULL);
PR_fprintf(PR_STDERR, "\n" "%s -H <command> : Print available options for the given command\n" "%s -H : Print complete help output of all commands and options\n" "%s --syntax : Print a short summary of all commands and options\n",
progName, progName, progName); exit(1);
}
if (!selfsign) {
issuerCert = CERT_FindCertByNicknameOrEmailAddr(handle, issuerNickName); if (!issuerCert) {
SECU_PrintError(progName, "could not find certificate named \"%s\"",
issuerNickName); return NULL;
}
}
now = PR_Now();
PR_ExplodeTime(now, PR_GMTParameters, &printableTime); if (warpmonths) {
printableTime.tm_month += warpmonths;
now = PR_ImplodeTime(&printableTime);
PR_ExplodeTime(now, PR_GMTParameters, &printableTime);
}
printableTime.tm_month += validityMonths;
after = PR_ImplodeTime(&printableTime);
/* note that the time is now in micro-second unit */
validity = CERT_CreateValidity(now, after); if (validity) {
cert = CERT_CreateCertificate(serialNumber,
(selfsign ? &req->subject
: &issuerCert->subject),
validity, req);
CERT_DestroyValidity(validity);
} if (issuerCert) {
CERT_DestroyCertificate(issuerCert);
}
if (SECOID_GetAlgorithmTag(spkiAlg) == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
srcParams = &spkiAlg->parameters;
} else { /* If the issuer's public key is RSA, the parameter field * of the SPKI should be NULL, which can't be used as a
* basis of RSA-PSS parameters. */
srcParams = NULL;
}
params = SEC_CreateSignatureAlgorithmParameters(arena,
NULL,
SEC_OID_PKCS1_RSA_PSS_SIGNATURE,
hashAlgTag,
srcParams,
privKey); if (!params) {
SECU_PrintError(progName, "Could not create RSA-PSS parameters"); return SECFailure;
}
rv = SECOID_SetAlgorithmID(arena, signAlg,
SEC_OID_PKCS1_RSA_PSS_SIGNATURE,
params); if (rv != SECSuccess) {
SECU_PrintError(progName, "Could not set signature algorithm id."); return rv;
}
} else {
KeyType keyType = SECKEY_GetPrivateKeyType(privKey);
SECOidTag algID;
algID = SEC_GetSignatureAlgorithmOidTag(keyType, hashAlgTag); if (algID == SEC_OID_UNKNOWN) {
SECU_PrintError(progName, "Unknown key or hash type for issuer."); return SECFailure;
}
rv = SECOID_SetAlgorithmID(arena, signAlg, algID, 0); if (rv != SECSuccess) {
SECU_PrintError(progName, "Could not set signature algorithm id."); return rv;
}
} return SECSuccess;
}
switch (certVersion) { case (SEC_CERTIFICATE_VERSION_1): /* The initial version for x509 certificates is version one
* and this default value must be an implicit DER encoding. */
cert->version.data = NULL;
cert->version.len = 0; break; case (SEC_CERTIFICATE_VERSION_2): case (SEC_CERTIFICATE_VERSION_3): case 3: /* unspecified format (would be version 4 certificate). */
*(cert->version.data) = certVersion;
cert->version.len = 1; break; default:
PORT_SetError(SEC_ERROR_INVALID_ARGS);
rv = SECFailure; goto done;
}
rv = SEC_DerSignDataWithAlgorithmID(arena, &cert->derCert, der.data, der.len,
privKey, &cert->signature); if (rv != SECSuccess) {
fprintf(stderr, "Could not sign encoded certificate data.\n"); /* result allocated out of the arena, it will be freed
* when the arena is freed */ goto done;
}
done: if (caPrivateKey) {
SECKEY_DestroyPrivateKey(caPrivateKey);
} return rv;
}
do { /* Create a certrequest object from the input cert request der */
certReq = GetCertRequest(certReqDER, pwarg); if (certReq == NULL) {
GEN_BREAK(SECFailure)
}
if (certutil.options[opt_KeyOpFlagsOn].activated) {
keyOpFlagsOn = GetOpFlags(certutil.options[opt_KeyOpFlagsOn].arg);
} if (certutil.options[opt_KeyOpFlagsOff].activated) {
keyOpFlagsOff = GetOpFlags(certutil.options[opt_KeyOpFlagsOff].arg);
keyOpFlagsOn &= ~keyOpFlagsOff; /* make off override on */
} if (certutil.options[opt_KeyAttrFlags].activated) {
keyAttrFlags = GetAttrFlags(certutil.options[opt_KeyAttrFlags].arg);
}
/* -m serial number */ if (certutil.options[opt_SerialNumber].activated) { int sn = PORT_Atoi(certutil.options[opt_SerialNumber].arg); if (sn < 0) {
PR_fprintf(PR_STDERR, "%s -m: %s is not a valid serial number.\n",
progName, certutil.options[opt_SerialNumber].arg); return 255;
}
serialNumber = sn;
}
/* -P certdb name prefix */ if (certutil.options[opt_DBPrefix].activated) { if (certutil.options[opt_DBPrefix].arg) {
certPrefix = certutil.options[opt_DBPrefix].arg;
} else {
Usage();
}
}
/* --source-prefix certdb name prefix */ if (certutil.options[opt_SourcePrefix].activated) { if (certutil.options[opt_SourcePrefix].arg) {
srcCertPrefix = certutil.options[opt_SourcePrefix].arg;
} else {
Usage();
}
}
/* -q PQG file or curve name */ if (certutil.options[opt_PQGFile].activated) { if ((keytype != dsaKey) && (keytype != ecKey)) {
PR_fprintf(PR_STDERR, "%s -q: specifies a PQG file for DSA keys" " (-k dsa) or a named curve for EC keys (-k ec)\n)",
progName); return 255;
}
}
/* -s subject name */ if (certutil.options[opt_Subject].activated) {
subject = CERT_AsciiToName(certutil.options[opt_Subject].arg); if (!subject) {
PR_fprintf(PR_STDERR, "%s -s: improperly formatted name: \"%s\"\n",
progName, certutil.options[opt_Subject].arg); return 255;
}
}
/* -v validity period */ if (certutil.options[opt_Validity].activated) {
validityMonths = PORT_Atoi(certutil.options[opt_Validity].arg); if (validityMonths < 0) {
PR_fprintf(PR_STDERR, "%s -v: incorrect validity period: \"%s\"\n",
progName, certutil.options[opt_Validity].arg); return 255;
}
}
/* -w warp months */ if (certutil.options[opt_OffsetMonths].activated)
warpmonths = PORT_Atoi(certutil.options[opt_OffsetMonths].arg);
/* -y public exponent (for RSA) */ if (certutil.options[opt_Exponent].activated) {
publicExponent = PORT_Atoi(certutil.options[opt_Exponent].arg); if ((publicExponent != 3) &&
(publicExponent != 17) &&
(publicExponent != 65537)) {
PR_fprintf(PR_STDERR, "%s -y: incorrect public exponent %d.",
progName, publicExponent);
PR_fprintf(PR_STDERR, "Must be 3, 17, or 65537.\n"); return 255;
}
}
/* --certVersion */ if (certutil.options[opt_CertVersion].activated) {
certVersion = PORT_Atoi(certutil.options[opt_CertVersion].arg); if (certVersion < 1 || certVersion > 4) {
PR_fprintf(PR_STDERR, "%s -certVersion: incorrect certificate version %d.",
progName, certVersion);
PR_fprintf(PR_STDERR, "Must be 1, 2, 3 or 4.\n"); return 255;
}
certVersion = certVersion - 1;
}
/* Check number of commands entered. */
commandsEntered = 0; for (i = 0; i < certutil.numCommands; i++) { if (certutil.commands[i].activated) {
commandToRun = certutil.commands[i].flag;
commandsEntered++;
} if (commandsEntered > 1) break;
} if (commandsEntered > 1) {
PR_fprintf(PR_STDERR, "%s: only one command at a time!\n", progName);
PR_fprintf(PR_STDERR, "You entered: "); for (i = 0; i < certutil.numCommands; i++) { if (certutil.commands[i].activated)
PR_fprintf(PR_STDERR, " -%c", certutil.commands[i].flag);
}
PR_fprintf(PR_STDERR, "\n"); return 255;
} if (commandsEntered == 0) {
Usage();
}
/* -A, -D, -M, -S, -V, and all require -n */ if ((certutil.commands[cmd_AddCert].activated ||
certutil.commands[cmd_DeleteCert].activated ||
certutil.commands[cmd_DumpChain].activated ||
certutil.commands[cmd_ModifyCertTrust].activated ||
certutil.commands[cmd_CreateAndAddCert].activated ||
certutil.commands[cmd_CheckCertValidity].activated) &&
!certutil.options[opt_Nickname].activated) {
PR_fprintf(PR_STDERR, "%s -%c: nickname is required for this command (-n).\n",
progName, commandToRun); return 255;
}
/* -A, -E, -M, -S require trust */ if ((certutil.commands[cmd_AddCert].activated ||
certutil.commands[cmd_AddEmailCert].activated ||
certutil.commands[cmd_ModifyCertTrust].activated ||
certutil.commands[cmd_CreateAndAddCert].activated) &&
!certutil.options[opt_Trust].activated) {
PR_fprintf(PR_STDERR, "%s -%c: trust is required for this command (-t).\n",
progName, commandToRun); return 255;
}
/* if -L is given raw, ascii or dump mode, it must be for only one cert. */ if (certutil.commands[cmd_ListCerts].activated &&
(certutil.options[opt_ASCIIForIO].activated ||
certutil.options[opt_DumpExtensionValue].activated ||
certutil.options[opt_BinaryDER].activated) &&
!certutil.options[opt_Nickname].activated) {
PR_fprintf(PR_STDERR, "%s: nickname is required to dump cert in raw or ascii mode.\n",
progName); return 255;
}
/* -L can only be in (raw || ascii). */ if (certutil.commands[cmd_ListCerts].activated &&
certutil.options[opt_ASCIIForIO].activated &&
certutil.options[opt_BinaryDER].activated) {
PR_fprintf(PR_STDERR, "%s: cannot specify both -r and -a when dumping cert.\n",
progName); return 255;
}
/* If making a cert request, need a subject. */ if ((certutil.commands[cmd_CertReq].activated ||
certutil.commands[cmd_CreateAndAddCert].activated) &&
!(certutil.options[opt_Subject].activated || keysource)) {
PR_fprintf(PR_STDERR, "%s -%c: subject is required to create a cert request.\n",
progName, commandToRun); return 255;
}
/* If making a cert, need a serial number. */ if ((certutil.commands[cmd_CreateNewCert].activated ||
certutil.commands[cmd_CreateAndAddCert].activated) &&
!certutil.options[opt_SerialNumber].activated) { /* Make a default serial number from the current time. */
PRTime now = PR_Now();
LL_USHR(now, now, 19);
LL_L2UI(serialNumber, now);
}
/* Validation needs the usage to validate for. */ if (certutil.commands[cmd_CheckCertValidity].activated &&
!certutil.options[opt_Usage].activated) {
PR_fprintf(PR_STDERR, "%s -V: specify a usage to validate the cert for (-u).\n",
progName); return 255;
}
/* Rename needs an old and a new nickname */ if (certutil.commands[cmd_Rename].activated &&
!(certutil.options[opt_Nickname].activated &&
certutil.options[opt_NewNickname].activated)) {
PR_fprintf(PR_STDERR, "%s --rename: specify an old nickname (-n) and\n" " a new nickname (--new-n).\n",
progName); return 255;
}
/* Delete needs a nickname or a key ID */ if (certutil.commands[cmd_DeleteKey].activated &&
!(certutil.options[opt_Nickname].activated || keysource)) {
PR_fprintf(PR_STDERR, "%s -%c: specify a nickname (-n) or\n" " a key ID (-k).\n",
progName, commandToRun); return 255;
}
/* Upgrade/Merge needs a source database and a upgrade id. */ if (certutil.commands[cmd_UpgradeMerge].activated &&
!(certutil.options[opt_SourceDir].activated &&
certutil.options[opt_UpgradeID].activated)) {
PR_fprintf(PR_STDERR, "%s --upgrade-merge: specify an upgrade database directory " "(--source-dir) and\n" " an upgrade ID (--upgrade-id).\n",
progName); return 255;
}
/* Merge needs a source database */ if (certutil.commands[cmd_Merge].activated &&
!certutil.options[opt_SourceDir].activated) {
/* To make a cert, need either a issuer or to self-sign it. */ if (certutil.commands[cmd_CreateAndAddCert].activated &&
!(certutil.options[opt_IssuerName].activated ||
certutil.options[opt_SelfSign].activated)) {
PR_fprintf(PR_STDERR, "%s -S: must specify issuer (-c) or self-sign (-x).\n",
progName); return 255;
}
/* Using slotname == NULL for listing keys and certs on all slots,
* but only that. */ if (!(certutil.commands[cmd_ListKeys].activated ||
certutil.commands[cmd_DumpChain].activated ||
certutil.commands[cmd_ListCerts].activated) &&
slotname == NULL) {
PR_fprintf(PR_STDERR, "%s -%c: cannot use \"-h all\" for this command.\n",
progName, commandToRun); return 255;
}
/* Using keytype == nullKey for list all key types, but only that. */ if (!certutil.commands[cmd_ListKeys].activated && keytype == nullKey) {
PR_fprintf(PR_STDERR, "%s -%c: cannot use \"-k all\" for this command.\n",
progName, commandToRun); return 255;
}
/* Open the input file. */ if (certutil.options[opt_InputFile].activated) {
inFile = PR_Open(certutil.options[opt_InputFile].arg, PR_RDONLY, 0); if (!inFile) {
PR_fprintf(PR_STDERR, "%s: unable to open \"%s\" for reading (%ld, %ld).\n",
progName, certutil.options[opt_InputFile].arg,
PR_GetError(), PR_GetOSError()); return 255;
}
}
/* Open the output file. */ if (certutil.options[opt_OutputFile].activated) {
outFile = PR_Open(certutil.options[opt_OutputFile].arg,
PR_CREATE_FILE | PR_RDWR | PR_TRUNCATE, 00660); if (!outFile) {
PR_fprintf(PR_STDERR, "%s: unable to open \"%s\" for writing (%ld, %ld).\n",
progName, certutil.options[opt_OutputFile].arg,
PR_GetError(), PR_GetOSError()); return 255;
}
}
SECU_PrintError(progName, "could not find the slot %s", slotname);
rv = SECFailure; goto shutdown;
}
/* If creating new database, initialize the password. */ if (certutil.commands[cmd_NewDBs].activated) { if (certutil.options[opt_EmptyPassword].activated && (PK11_NeedUserInit(slot))) {
rv = PK11_InitPin(slot, (char *)NULL, "");
} else {
rv = SECU_ChangePW2(slot, 0, 0, certutil.options[opt_PasswordFile].arg,
certutil.options[opt_NewPasswordFile].arg);
} if (rv != SECSuccess) {
SECU_PrintError(progName, "Could not set password for the slot"); goto shutdown;
}
}
/* if we are going to modify the cert database,
* make sure it's initialized */ if (certutil.commands[cmd_ModifyCertTrust].activated ||
certutil.commands[cmd_CreateAndAddCert].activated ||
certutil.commands[cmd_AddCert].activated ||
certutil.commands[cmd_AddEmailCert].activated) { if (PK11_NeedLogin(slot) && PK11_NeedUserInit(slot)) { char *password = NULL; /* fetch the password from the command line or the file
* if no password is supplied, initialize the password to NULL */ if (pwdata.source == PW_FROMFILE) {
password = SECU_FilePasswd(slot, PR_FALSE, pwdata.data);
} elseif (pwdata.source == PW_PLAINTEXT) {
password = PL_strdup(pwdata.data);
}
rv = PK11_InitPin(slot, (char *)NULL, password ? password : ""); if (password) {
PORT_Memset(password, 0, PL_strlen(password));
PORT_Free(password);
} if (rv != SECSuccess) {
SECU_PrintError(progName, "Could not set password for the slot"); goto shutdown;
}
}
}
/* walk through the upgrade merge if necessary. * This option is more to test what some applications will want to do * to do an automatic upgrade. The --merge command is more useful for * the general case where 2 database need to be merged together.
*/ if (certutil.commands[cmd_UpgradeMerge].activated) { if (*upgradeTokenName == 0) {
upgradeTokenName = upgradeID;
} if (!PK11_IsInternal(slot)) {
fprintf(stderr, "Only internal DB's can be upgraded\n");
rv = SECSuccess; goto shutdown;
} if (!PK11_IsRemovable(slot)) {
printf("database already upgraded.\n");
rv = SECSuccess; goto shutdown;
} if (!PK11_NeedLogin(slot)) {
printf("upgrade complete!\n");
rv = SECSuccess; goto shutdown;
} /* authenticate to the old DB if necessary */ if (PORT_Strcmp(PK11_GetTokenName(slot), upgradeTokenName) == 0) { /* if we need a password, supply it. This will be the password
* for the old database */
rv = PK11_Authenticate(slot, PR_FALSE, &pwdata2); if (rv != SECSuccess) {
SECU_PrintError(progName, "Could not get password for %s",
upgradeTokenName); goto shutdown;
} /* * if we succeeded above, but still aren't logged in, that means * we just supplied the password for the old database. We may * need the password for the new database. NSS will automatically * change the token names at this point
*/ if (PK11_IsLoggedIn(slot, &pwdata)) {
printf("upgrade complete!\n");
rv = SECSuccess; goto shutdown;
}
}
/* call PK11_IsPresent to update our cached token information */ if (!PK11_IsPresent(slot)) { /* this shouldn't happen. We call isPresent to force a token
* info update */
fprintf(stderr, "upgrade/merge internal error\n");
rv = SECFailure; goto shutdown;
}
/* the token is now set to the state of the source database, * if we need a password for it, PK11_Authenticate will
* automatically prompt us */
rv = PK11_Authenticate(slot, PR_FALSE, &pwdata); if (rv == SECSuccess) {
printf("upgrade complete!\n");
} else {
SECU_PrintError(progName, "Could not get password for %s",
PK11_GetTokenName(slot));
} goto shutdown;
}
if (!privkey) {
SECU_PrintError(
progName, "%s is neither a key-type nor a nickname nor a key-id", keysource); return SECFailure;
}
pubkey = SECKEY_ConvertToPublicKey(privkey); if (!pubkey) {
SECU_PrintError(progName, "Could not get keys from cert %s", keysource); if (keycert) {
CERT_DestroyCertificate(keycert);
}
rv = SECFailure; goto shutdown;
}
keytype = privkey->keyType;
/* On CertReq for renewal if no subject has been * specified obtain it from the certificate.
*/ if (certutil.commands[cmd_CertReq].activated && !subject) { if (keycert) {
subject = CERT_AsciiToName(keycert->subjectName); if (!subject) {
SECU_PrintError(
progName, "Could not get subject from certificate %s",
keysource);
CERT_DestroyCertificate(keycert);
rv = SECFailure; goto shutdown;
}
} else {
SECU_PrintError(progName, "Subject name not provided");
rv = SECFailure; goto shutdown;
}
} if (keycert) {
CERT_DestroyCertificate(keycert);
}
} else {
privkey =
CERTUTIL_GeneratePrivateKey(keytype, slot, keysize,
publicExponent,
certutil.options[opt_NoiseFile].arg,
&pubkey,
certutil.options[opt_PQGFile].arg,
keyAttrFlags,
keyOpFlagsOn,
keyOpFlagsOff,
&pwdata); if (privkey == NULL) {
SECU_PrintError(progName, "unable to generate key(s)\n");
rv = SECFailure; goto shutdown;
}
}
privkey->wincx = &pwdata;
PORT_Assert(pubkey != NULL);
/* If all that was needed was keygen, exit. */ if (certutil.commands[cmd_GenKeyPair].activated) {
rv = SECSuccess; goto shutdown;
}
}
if (certutil.options[opt_Pss].activated) { if (!certutil.commands[cmd_CertReq].activated &&
!certutil.commands[cmd_CreateAndAddCert].activated) {
PR_fprintf(PR_STDERR, "%s -%c: --pss only works with -R or -S.\n",
progName, commandToRun); return 255;
} if (keytype != rsaKey) {
PR_fprintf(PR_STDERR, "%s -%c: --pss only works with RSA keys.\n",
progName, commandToRun); return 255;
}
}
/* --pss-sign is to sign a certificate with RSA-PSS, even if the * issuer's key is an RSA key. If the key is an RSA-PSS key, the
* generated signature is always RSA-PSS. */ if (certutil.options[opt_PssSign].activated) { if (!certutil.commands[cmd_CreateNewCert].activated &&
!certutil.commands[cmd_CreateAndAddCert].activated) {
PR_fprintf(PR_STDERR, "%s -%c: --pss-sign only works with -C or -S.\n",
progName, commandToRun); return 255;
} if (keytype != rsaKey) {
PR_fprintf(PR_STDERR, "%s -%c: --pss-sign only works with RSA keys.\n",
progName, commandToRun); return 255;
}
}
if (certutil.options[opt_SimpleSelfSigned].activated &&
!certutil.commands[cmd_DumpChain].activated) {
PR_fprintf(PR_STDERR, "%s -%c: --simple-self-signed only works with -O.\n",
progName, commandToRun); return 255;
}
/* If we need a list of extensions convert the flags into list format */ if (certutil.commands[cmd_CertReq].activated ||
certutil.commands[cmd_CreateAndAddCert].activated ||
certutil.commands[cmd_CreateNewCert].activated) {
certutil_extns[ext_keyUsage].activated =
certutil.options[opt_AddCmdKeyUsageExt].activated; if (!certutil_extns[ext_keyUsage].activated) {
certutil_extns[ext_keyUsage].activated =
certutil.options[opt_AddKeyUsageExt].activated;
} else {
certutil_extns[ext_keyUsage].arg =
certutil.options[opt_AddCmdKeyUsageExt].arg;
}
certutil_extns[ext_basicConstraint].activated =
certutil.options[opt_AddBasicConstraintExt].activated;
certutil_extns[ext_nameConstraints].activated =
certutil.options[opt_AddNameConstraintsExt].activated;
certutil_extns[ext_authorityKeyID].activated =
certutil.options[opt_AddAuthorityKeyIDExt].activated;
certutil_extns[ext_subjectKeyID].activated =
certutil.options[opt_AddSubjectKeyIDExt].activated;
certutil_extns[ext_CRLDistPts].activated =
certutil.options[opt_AddCRLDistPtsExt].activated;
certutil_extns[ext_NSCertType].activated =
certutil.options[opt_AddCmdNSCertTypeExt].activated; if (!certutil_extns[ext_NSCertType].activated) {
certutil_extns[ext_NSCertType].activated =
certutil.options[opt_AddNSCertTypeExt].activated;
} else {
certutil_extns[ext_NSCertType].arg =
certutil.options[opt_AddCmdNSCertTypeExt].arg;
}
/* -A -C or -E Read inFile */ if (certutil.commands[cmd_CreateNewCert].activated ||
certutil.commands[cmd_AddCert].activated ||
certutil.commands[cmd_AddEmailCert].activated) {
PRBool isCreate = certutil.commands[cmd_CreateNewCert].activated;
rv = SECU_ReadDERFromFile(isCreate ? &certReqDER : &certDER, inFile,
certutil.options[opt_ASCIIForIO].activated,
PR_TRUE); if (rv) goto shutdown;
}
/* * Certificate request
*/
/* Make a cert request (-R). */ if (certutil.commands[cmd_CertReq].activated) {
rv = CertReq(privkey, pubkey, keytype, hashAlgTag, subject,
certutil.options[opt_PhoneNumber].arg,
certutil.options[opt_ASCIIForIO].activated,
certutil.options[opt_ExtendedEmailAddrs].arg,
certutil.options[opt_ExtendedDNSNames].arg,
certutil_extns,
(certutil.options[opt_GenericExtensions].activated ? certutil.options[opt_GenericExtensions].arg
: NULL),
certutil.options[opt_Pss].activated,
&certReqDER); if (rv) goto shutdown;
privkey->wincx = &pwdata;
}
/* * Certificate creation
*/
/* If making and adding a cert, create a cert request file first without * any extensions, then load it with the command line extensions * and output the cert to another file.
*/ if (certutil.commands[cmd_CreateAndAddCert].activated) { static certutilExtnList nullextnlist = { { PR_FALSE, NULL } };
rv = CertReq(privkey, pubkey, keytype, hashAlgTag, subject,
certutil.options[opt_PhoneNumber].arg,
PR_FALSE, /* do not BASE64-encode regardless of -a option */
NULL,
NULL,
nullextnlist,
(certutil.options[opt_GenericExtensions].activated ? certutil.options[opt_GenericExtensions].arg
: NULL),
certutil.options[opt_Pss].activated,
&certReqDER); if (rv) goto shutdown;
privkey->wincx = &pwdata;
}
/* -A -E or -S Add the cert to the DB */ if (certutil.commands[cmd_CreateAndAddCert].activated ||
certutil.commands[cmd_AddCert].activated ||
certutil.commands[cmd_AddEmailCert].activated) { if (strstr(certutil.options[opt_Trust].arg, "u")) {
fprintf(stderr, "Notice: Trust flag u is set automatically if the " "private key is present.\n");
}
rv = AddCert(slot, certHandle, name,
certutil.options[opt_Trust].arg,
&certDER,
certutil.commands[cmd_AddEmailCert].activated, &pwdata); if (rv) goto shutdown;
}
shutdown: if (slot) {
PK11_FreeSlot(slot);
} if (privkey) {
SECKEY_DestroyPrivateKey(privkey);
} if (pubkey) {
SECKEY_DestroyPublicKey(pubkey);
} if (subject) {
CERT_DestroyName(subject);
} if (name) {
PL_strfree(name);
} if (newName) {
PL_strfree(newName);
} if (inFile && inFile != PR_STDIN) {
PR_Close(inFile);
} if (outFile && outFile != PR_STDOUT) {
PR_Close(outFile);
}
SECITEM_FreeItem(&certReqDER, PR_FALSE);
SECITEM_FreeItem(&certDER, PR_FALSE); if (pwdata.data && pwdata.source == PW_PLAINTEXT) { /* Allocated by a PL_strdup call in SECU_GetModulePassword. */
PL_strfree(pwdata.data);
} if (email) {
PL_strfree(email);
}
/* Open the batch command file. * * - If -B <command line> option is specified, the contents in the * command file will be interpreted as subsequent certutil * commands to be executed in the current certutil process * context after the current certutil command has been executed. * - Each line in the command file consists of the command * line arguments for certutil. * - The -d <configdir> option will be ignored if specified in the * command file. * - Quoting with double quote characters ("...") is supported * to allow white space in a command line argument. The * double quote character cannot be escaped and quoting cannot * be nested in this version. * - each line in the batch file is limited to 512 characters
*/
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.