Bug 341371, add a way to make CSR with an existing key
authorneil.williams%sun.com
Fri, 15 Jun 2007 21:28:05 +0000
changeset 7872 5900855733c94f0b733a4d5bf8cef45399bb2dac
parent 7871 89ed52b476bcf00956b7f951373311ffd1112e0a
child 7873 d8de87f9440447c5fb6e9277be0c35ca30970bb2
push idunknown
push userunknown
push dateunknown
bugs341371
Bug 341371, add a way to make CSR with an existing key r=nelson
security/nss/cmd/certutil/certutil.c
--- a/security/nss/cmd/certutil/certutil.c
+++ b/security/nss/cmd/certutil/certutil.c
@@ -851,23 +851,23 @@ Usage(char *progName)
 	progName);
 #endif /* NSS_ENABLE_ECC */
     FPS "\t\t [-f pwfile] [-X] [-d certdir] [-P dbprefix]\n");
     FPS "\t%s -L [-n cert-name] [-X] [-d certdir] [-P dbprefix] [-r] [-a]\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] [-P dbprefix]\n", progName);
     FPS "\t%s -R -s subj -o cert-request-file [-d certdir] [-P dbprefix] [-p phone] [-a]\n"
-	"\t\t [-y emailAddrs] [-k key-type] [-h token-name] [-f pwfile] [-g key-size]\n",
+	"\t\t [-y emailAddrs] [-k key-type-or-id] [-h token-name] [-f pwfile] [-g key-size]\n",
 	progName);
     FPS "\t%s -V -n cert-name -u usage [-b time] [-e] \n"
 	"\t\t[-X] [-d certdir] [-P dbprefix]\n",
 	progName);
     FPS "\t%s -S -n cert-name -s subj [-c issuer-name | -x]  -t trustargs\n"
-	"\t\t [-k key-type] [-q key-params] [-h token-name] [-g key-size]\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]\n"
         "\t\t [-p phone] [-1] [-2] [-3] [-4] [-5] [-6] [-7 emailAddrs]\n"
         "\t\t [-8 dns-names]\n",
 	progName);
     FPS "\t%s -U [-X] [-d certdir] [-P dbprefix]\n", progName);
     exit(1);
 }
@@ -1102,21 +1102,22 @@ static void LongUsage(char *progName)
     FPS "%-15s Generate a certificate request (stdout)\n",
 	"-R");
     FPS "%-20s Specify the subject name (using RFC1485)\n",
 	"   -s subject");
     FPS "%-20s Output the cert request to this file\n",
 	"   -o output-req");
 #ifdef NSS_ENABLE_ECC
     FPS "%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n",
-	"   -k key-type");
 #else
     FPS "%-20s Type of key pair to generate (\"dsa\", \"rsa\" (default))\n",
-	"   -k key-type");
 #endif /* NSS_ENABLE_ECC */
+	"   -k key-type-or-id");
+    FPS "%-20s or nickname of the cert key to use \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 Name of file containing PQG parameters (dsa only)\n",
 	"   -q pqgfile");
 #ifdef NSS_ENABLE_ECC
     FPS "%-20s Elliptic curve name (ec only)\n",
@@ -1167,21 +1168,20 @@ static void LongUsage(char *progName)
     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");
 #ifdef NSS_ENABLE_ECC
     FPS "%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n",
-	"   -k key-type");
 #else
     FPS "%-20s Type of key pair to generate (\"dsa\", \"rsa\" (default))\n",
-	"   -k key-type");
 #endif /* NSS_ENABLE_ECC */
+	"   -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 Name of file containing PQG parameters (dsa only)\n",
 	"   -q pqgfile");
 #ifdef NSS_ENABLE_ECC
     FPS "%-20s Elliptic curve name (ec only)\n",
@@ -1536,16 +1536,17 @@ certutil_main(int argc, char **argv, PRB
     PRFileDesc *inFile          = PR_STDIN;
     PRFileDesc *outFile         = NULL;
     char *      certfile        = "tempcert";
     char *      certreqfile     = "tempcertreq";
     char *      slotname        = "internal";
     char *      certPrefix      = "";
     KeyType     keytype         = rsaKey;
     char *      name            = NULL;
+    char *	keysource	= NULL;
     SECOidTag   hashAlgTag      = SEC_OID_UNKNOWN;
     int	        keysize	        = DEFAULT_KEY_BITS;
     int         publicExponent  = 0x010001;
     unsigned int serialNumber   = 0;
     int         warpmonths      = 0;
     int         validityMonths  = 3;
     int         commandsEntered = 0;
     char        commandToRun    = '\0';
@@ -1698,19 +1699,18 @@ secuCommandFlag certutil_options[] =
 	    keytype = dsaKey;
 #ifdef NSS_ENABLE_ECC
 	} else if (PL_strcmp(arg, "ec") == 0) {
 	    keytype = ecKey;
 #endif /* NSS_ENABLE_ECC */
 	} else if (PL_strcmp(arg, "all") == 0) {
 	    keytype = nullKey;
 	} else {
-	    PR_fprintf(PR_STDERR, "%s -k:  %s is not a recognized type.\n",
-	               progName, arg);
-	    return 255;
+	    /* use an existing private/public key pair */
+	    keysource = 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",
@@ -2083,32 +2083,54 @@ secuCommandFlag certutil_options[] =
 	                  &pwdata);
 	goto shutdown;
     }
 
     /*
      *  Key generation
      */
 
-    /*  These commands require keygen.  */
+    /*  These commands may require keygen.  */
     if (certutil.commands[cmd_CertReq].activated ||
         certutil.commands[cmd_CreateAndAddCert].activated ||
 	certutil.commands[cmd_GenKeyPair].activated) {
-	/*  XXX Give it a nickname.  */
-	privkey = 
-	    CERTUTIL_GeneratePrivateKey(keytype, slot, keysize,
-	                                publicExponent, 
-	                                certutil.options[opt_NoiseFile].arg,
-	                                &pubkey, 
-	                                certutil.options[opt_PQGFile].arg,
-	                                &pwdata);
-	if (privkey == NULL) {
-	    SECU_PrintError(progName, "unable to generate key(s)\n");
-	    rv = SECFailure;
-	    goto shutdown;
+	if (keysource) {
+	    CERTCertificate *keycert;
+	    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);
+		    return SECFailure;
+		}
+	    }
+	    privkey = PK11_FindKeyByDERCert(slot, keycert, &pwdata);
+	    if (privkey)
+		pubkey = CERT_ExtractPublicKey(keycert);
+	    CERT_DestroyCertificate(keycert);
+	    if (!pubkey) {
+		SECU_PrintError(progName,
+				"Could not get keys from cert %s", keysource);
+		rv = SECFailure;
+		goto shutdown;
+	    }
+	} else {
+	    privkey = 
+		CERTUTIL_GeneratePrivateKey(keytype, slot, keysize,
+					    publicExponent, 
+					    certutil.options[opt_NoiseFile].arg,
+					    &pubkey, 
+					    certutil.options[opt_PQGFile].arg,
+					    &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;