summaryrefslogtreecommitdiff
path: root/cmd/certutil
diff options
context:
space:
mode:
authorFraser Tweedale <frase@frase.id.au>2018-05-24 18:21:50 +0200
committerFraser Tweedale <frase@frase.id.au>2018-05-24 18:21:50 +0200
commit0d35db03cf39b50874c08f0a99481df07c360969 (patch)
tree9101147cbdc1edf88eeb70eb214aab760ddd3a41 /cmd/certutil
parent15cc47b99536a75f3b6ce99cc59078fba9f459be (diff)
downloadnss-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.c75
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,