diff options
author | Fraser Tweedale <frase@frase.id.au> | 2018-05-24 18:21:50 +0200 |
---|---|---|
committer | Fraser Tweedale <frase@frase.id.au> | 2018-05-24 18:21:50 +0200 |
commit | 0d35db03cf39b50874c08f0a99481df07c360969 (patch) | |
tree | 9101147cbdc1edf88eeb70eb214aab760ddd3a41 /cmd/certutil | |
parent | 15cc47b99536a75f3b6ce99cc59078fba9f459be (diff) | |
download | nss-hg-0d35db03cf39b50874c08f0a99481df07c360969.tar.gz |
Bug 430198, certutil capability: generate CSR from orphan private key, r=kaie
Diffstat (limited to 'cmd/certutil')
-rw-r--r-- | cmd/certutil/certutil.c | 75 |
1 files changed, 61 insertions, 14 deletions
diff --git a/cmd/certutil/certutil.c b/cmd/certutil/certutil.c index 61a36f3ba..4f265fd37 100644 --- a/cmd/certutil/certutil.c +++ b/cmd/certutil/certutil.c @@ -36,6 +36,8 @@ #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 */ @@ -1573,7 +1575,7 @@ luR(enum usage_level ul, const char *command) " -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 \n", + 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"); @@ -3138,6 +3140,8 @@ certutil_main(int argc, char **argv, PRBool initialize) } initialized = PR_TRUE; SECU_RegisterDynamicOids(); + /* Ensure the SSL error code table has been registered. Bug 1460284. */ + SSL_OptionSetDefault(-1, 0); } certHandle = CERT_GetDefaultCertDB(); @@ -3459,37 +3463,80 @@ certutil_main(int argc, char **argv, PRBool initialize) keycert = CERT_FindCertByNicknameOrEmailAddr(certHandle, keysource); if (!keycert) { keycert = PK11_FindCertFromNickname(keysource, NULL); - if (!keycert) { - SECU_PrintError(progName, - "%s is neither a key-type nor a nickname", keysource); + } + + if (keycert) { + privkey = PK11_FindKeyByDERCert(slot, keycert, &pwdata); + } else { + PLArenaPool *arena = NULL; + SECItem keyidItem = { 0 }; + char *keysourcePtr = keysource; + /* Interpret keysource as CKA_ID */ + 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; + } + } + if (0 == strncasecmp("0x", keysource, 2)) { + keysourcePtr = keysource + 2; // skip leading "0x" + } + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (!arena) { + SECU_PrintError(progName, "unable to allocate arena"); return SECFailure; } + if (SECU_HexString2SECItem(arena, &keyidItem, keysourcePtr)) { + privkey = PK11_FindKeyByKeyID(slot, &keyidItem, &pwdata); + } + PORT_FreeArena(arena, PR_FALSE); + } + + if (!privkey) { + SECU_PrintError( + progName, + "%s is neither a key-type nor a nickname nor a key-id", keysource); + return SECFailure; } - privkey = PK11_FindKeyByDERCert(slot, keycert, &pwdata); - if (privkey) - pubkey = CERT_ExtractPublicKey(keycert); + + pubkey = SECKEY_ConvertToPublicKey(privkey); if (!pubkey) { SECU_PrintError(progName, "Could not get keys from cert %s", keysource); + if (keycert) { + CERT_DestroyCertificate(keycert); + } rv = SECFailure; - CERT_DestroyCertificate(keycert); 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) { - subject = CERT_AsciiToName(keycert->subjectName); - if (!subject) { - SECU_PrintError(progName, - "Could not get subject from certificate %s", keysource); - CERT_DestroyCertificate(keycert); + 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; } } - CERT_DestroyCertificate(keycert); + if (keycert) { + CERT_DestroyCertificate(keycert); + } } else { privkey = CERTUTIL_GeneratePrivateKey(keytype, slot, keysize, |