summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiki Ueno <dueno@redhat.com>2018-07-20 12:48:23 +0200
committerDaiki Ueno <dueno@redhat.com>2018-07-20 12:48:23 +0200
commit455c1978a5022f8beea967e752977daedf793e83 (patch)
treeeac1466018e7b59e5f0f33ca9111e7c1a4a2733e
parent8f67b2d1f28fa4ec6234bfa71cad3bcfbca3e0f0 (diff)
downloadnss-hg-455c1978a5022f8beea967e752977daedf793e83.tar.gz
Bug 291383, certutil: Allow -F to delete orphaned private key, r=kaie
Summary: This change makes it possible to remove orphaned private key with the `-F` command. Similarly to `-R` (bug 430198), it reads a key ID from `-k`. Reviewers: kaie Reviewed By: kaie Bug #: 291383 Differential Revision: https://phabricator.services.mozilla.com/D2094
-rw-r--r--cmd/certutil/certutil.c155
-rw-r--r--doc/certutil.xml2
-rw-r--r--doc/html/certutil.html8
-rw-r--r--doc/nroff/certutil.114
-rwxr-xr-xtests/cert/cert.sh24
5 files changed, 145 insertions, 58 deletions
diff --git a/cmd/certutil/certutil.c b/cmd/certutil/certutil.c
index 058bb6238..5ecf1e71a 100644
--- a/cmd/certutil/certutil.c
+++ b/cmd/certutil/certutil.c
@@ -862,34 +862,44 @@ static const char *const keyTypeName[] = {
#define MAX_CKA_ID_BIN_LEN 20
#define MAX_CKA_ID_STR_LEN 40
-/* 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)
+/* 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;
- char ckaIDbuf[MAX_CKA_ID_STR_LEN + 4];
- CERTCertificate *cert;
- KeyType keyType;
- pwarg = NULL;
- ckaID = PK11_GetLowLevelKeyIDForPrivateKey(key);
+ ckaID = PK11_GetLowLevelKeyIDForPrivateKey(privkey);
if (!ckaID) {
- strcpy(ckaIDbuf, "(no CKA_ID)");
+ strcpy(buffer, "(no CKA_ID)");
} else if (ItemIsPrintableASCII(ckaID)) {
int len = PR_MIN(MAX_CKA_ID_STR_LEN, ckaID->len);
- ckaIDbuf[0] = '"';
- memcpy(ckaIDbuf + 1, ckaID->data, len);
- ckaIDbuf[1 + len] = '"';
- ckaIDbuf[2 + len] = '\0';
+ 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, ckaIDbuf);
+ 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;
+
+ pwarg = NULL;
+ formatPrivateKeyID(key, ckaIDbuf);
cert = PK11_GetCertFromPrivateKey(key);
if (cert) {
keyType = CERT_GetCertKeyType(&cert->subjectPublicKeyInfo);
@@ -899,7 +909,6 @@ PrintKey(PRFileDesc *out, const char *nickName, int count,
}
PR_fprintf(out, "<%2d> %-8.8s %-42.42s %s\n", count,
keyTypeName[keyType], ckaIDbuf, nickName);
- SECITEM_ZfreeItem(ckaID, PR_TRUE);
return SECSuccess;
}
@@ -1011,7 +1020,7 @@ ListKeys(PK11SlotInfo *slot, const char *nickName, int index,
}
static SECStatus
-DeleteKey(char *nickname, secuPWData *pwdata)
+DeleteCertAndKey(char *nickname, secuPWData *pwdata)
{
SECStatus rv;
CERTCertificate *cert;
@@ -1040,6 +1049,61 @@ DeleteKey(char *nickname, secuPWData *pwdata)
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
*
@@ -1109,7 +1173,9 @@ PrintSyntax()
"\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 nickname [-d certdir] [-P dbprefix]\n",
+ 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);
@@ -1399,6 +1465,8 @@ luF(enum usage_level ul, const char *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",
@@ -2953,10 +3021,9 @@ certutil_main(int argc, char **argv, PRBool initialize)
readOnly = !certutil.options[opt_RW].activated;
}
- /* -A, -D, -F, -M, -S, -V, and all require -n */
+ /* -A, -D, -M, -S, -V, and all require -n */
if ((certutil.commands[cmd_AddCert].activated ||
certutil.commands[cmd_DeleteCert].activated ||
- certutil.commands[cmd_DeleteKey].activated ||
certutil.commands[cmd_DumpChain].activated ||
certutil.commands[cmd_ModifyCertTrust].activated ||
certutil.commands[cmd_CreateAndAddCert].activated ||
@@ -3043,6 +3110,16 @@ certutil_main(int argc, char **argv, PRBool initialize)
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",
+ commandToRun, progName);
+ return 255;
+ }
+
/* Upgrade/Merge needs a source database and a upgrade id. */
if (certutil.commands[cmd_UpgradeMerge].activated &&
!(certutil.options[opt_SourceDir].activated &&
@@ -3405,7 +3482,19 @@ certutil_main(int argc, char **argv, PRBool initialize)
}
/* Delete key (-F) */
if (certutil.commands[cmd_DeleteKey].activated) {
- rv = DeleteKey(name, &pwdata);
+ if (certutil.options[opt_Nickname].activated) {
+ rv = DeleteCertAndKey(name, &pwdata);
+ } else {
+ privkey = findPrivateKeyByID(slot, keysource, &pwdata);
+ if (!privkey) {
+ SECU_PrintError(progName, "%s is not a key-id", keysource);
+ rv = SECFailure;
+ } else {
+ rv = DeleteKey(privkey, &pwdata);
+ /* already destroyed by PK11_DeleteTokenPrivateKey */
+ privkey = NULL;
+ }
+ }
goto shutdown;
}
/* Modify trust attribute for cert (-M) */
@@ -3477,30 +3566,8 @@ certutil_main(int argc, char **argv, PRBool initialize)
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 == PL_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);
+ privkey = findPrivateKeyByID(slot, keysource, &pwdata);
}
if (!privkey) {
diff --git a/doc/certutil.xml b/doc/certutil.xml
index 4622c75e4..01dfd013b 100644
--- a/doc/certutil.xml
+++ b/doc/certutil.xml
@@ -84,7 +84,7 @@
<varlistentry>
<term>-F</term>
- <listitem><para>Delete a private key and the associated certificate from a database. Specify the key to delete with the -n argument. Specify the database from which to delete the key with the
+ <listitem><para>Delete a private key and the associated certificate from a database. Specify the key to delete with the -n argument or the -k argument. Specify the database from which to delete the key with the
<option>-d</option> argument.
</para>
<para>
diff --git a/doc/html/certutil.html b/doc/html/certutil.html
index 902d1309a..a4257b513 100644
--- a/doc/html/certutil.html
+++ b/doc/html/certutil.html
@@ -1,8 +1,8 @@
-<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>CERTUTIL</title><meta name="generator" content="DocBook XSL Stylesheets Vsnapshot"><link rel="home" href="index.html" title="CERTUTIL"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">CERTUTIL</th></tr></table><hr></div><div class="refentry"><a name="certutil"></a><div class="titlepage"></div><div class="refnamediv"><h2>Name</h2><p>certutil — Manage keys and certificate in both NSS databases and other NSS tokens</p></div><div class="refsynopsisdiv"><h2>Synopsis</h2><div class="cmdsynopsis"><p><code class="command">certutil</code> [<em class="replaceable"><code>options</code></em>] [[<em class="replaceable"><code>arguments</code></em>]]</p></div></div><div class="refsection"><a name="idm140440587239488"></a><h2>STATUS</h2><p>This documentation is still work in progress. Please contribute to the initial review in <a class="ulink" href="https://bugzilla.mozilla.org/show_bug.cgi?id=836477" target="_top">Mozilla NSS bug 836477</a>
- </p></div><div class="refsection"><a name="description"></a><h2>Description</h2><p>The Certificate Database Tool, <span class="command"><strong>certutil</strong></span>, is a command-line utility that can create and modify certificate and key databases. It can specifically list, generate, modify, or delete certificates, create or change the password, generate new public and private key pairs, display the contents of the key database, or delete key pairs within the key database.</p><p>Certificate issuance, part of the key and certificate management process, requires that keys and certificates be created in the key database. This document discusses certificate and key database management. For information on the security module database management, see the <span class="command"><strong>modutil</strong></span> manpage.</p></div><div class="refsection"><a name="options"></a><h2>Command Options and Arguments</h2><p>Running <span class="command"><strong>certutil</strong></span> always requires one and only one command option to specify the type of certificate operation. Each command option may take zero or more arguments. The command option <code class="option">-H</code> will list all the command options and their relevant arguments.</p><p><span class="command"><strong>Command Options</strong></span></p><div class="variablelist"><dl class="variablelist"><dt><span class="term">-A </span></dt><dd><p>Add an existing certificate to a certificate database. The certificate database should already exist; if one is not present, this command option will initialize one by default.</p></dd><dt><span class="term">-B</span></dt><dd><p>Run a series of commands from the specified batch file. This requires the <code class="option">-i</code> argument.</p></dd><dt><span class="term">-C </span></dt><dd><p>Create a new binary certificate file from a binary certificate request file. Use the <code class="option">-i</code> argument to specify the certificate request file. If this argument is not used, <span class="command"><strong>certutil</strong></span> prompts for a filename. </p></dd><dt><span class="term">-D </span></dt><dd><p>Delete a certificate from the certificate database.</p></dd><dt><span class="term">--rename </span></dt><dd><p>Change the database nickname of a certificate.</p></dd><dt><span class="term">-E </span></dt><dd><p>Add an email certificate to the certificate database.</p></dd><dt><span class="term">-F</span></dt><dd><p>Delete a private key from a key database. Specify the key to delete with the -n argument. Specify the database from which to delete the key with the
-<code class="option">-d</code> argument. Use the <code class="option">-k</code> argument to specify explicitly whether to delete a DSA, RSA, or ECC key. If you don't use the <code class="option">-k</code> argument, the option looks for an RSA key matching the specified nickname.
+<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>CERTUTIL</title><meta name="generator" content="DocBook XSL Stylesheets Vsnapshot"><link rel="home" href="index.html" title="CERTUTIL"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">CERTUTIL</th></tr></table><hr></div><div class="refentry"><a name="certutil"></a><div class="titlepage"></div><div class="refnamediv"><h2>Name</h2><p>certutil — Manage keys and certificate in both NSS databases and other NSS tokens</p></div><div class="refsynopsisdiv"><h2>Synopsis</h2><div class="cmdsynopsis"><p><code class="command">certutil</code> [<em class="replaceable"><code>options</code></em>] [[<em class="replaceable"><code>arguments</code></em>]]</p></div></div><div class="refsection"><a name="idm45522631704896"></a><h2>STATUS</h2><p>This documentation is still work in progress. Please contribute to the initial review in <a class="ulink" href="https://bugzilla.mozilla.org/show_bug.cgi?id=836477" target="_top">Mozilla NSS bug 836477</a>
+ </p></div><div class="refsection"><a name="description"></a><h2>Description</h2><p>The Certificate Database Tool, <span class="command"><strong>certutil</strong></span>, is a command-line utility that can create and modify certificate and key databases. It can specifically list, generate, modify, or delete certificates, create or change the password, generate new public and private key pairs, display the contents of the key database, or delete key pairs within the key database.</p><p>Certificate issuance, part of the key and certificate management process, requires that keys and certificates be created in the key database. This document discusses certificate and key database management. For information on the security module database management, see the <span class="command"><strong>modutil</strong></span> manpage.</p></div><div class="refsection"><a name="options"></a><h2>Command Options and Arguments</h2><p>Running <span class="command"><strong>certutil</strong></span> always requires one and only one command option to specify the type of certificate operation. Each command option may take zero or more arguments. The command option <code class="option">-H</code> will list all the command options and their relevant arguments.</p><p><span class="command"><strong>Command Options</strong></span></p><div class="variablelist"><dl class="variablelist"><dt><span class="term">-A </span></dt><dd><p>Add an existing certificate to a certificate database. The certificate database should already exist; if one is not present, this command option will initialize one by default.</p></dd><dt><span class="term">-B</span></dt><dd><p>Run a series of commands from the specified batch file. This requires the <code class="option">-i</code> argument.</p></dd><dt><span class="term">-C </span></dt><dd><p>Create a new binary certificate file from a binary certificate request file. Use the <code class="option">-i</code> argument to specify the certificate request file. If this argument is not used, <span class="command"><strong>certutil</strong></span> prompts for a filename. </p></dd><dt><span class="term">-D </span></dt><dd><p>Delete a certificate from the certificate database.</p></dd><dt><span class="term">--rename </span></dt><dd><p>Change the database nickname of a certificate.</p></dd><dt><span class="term">-E </span></dt><dd><p>Add an email certificate to the certificate database.</p></dd><dt><span class="term">-F</span></dt><dd><p>Delete a private key and the associated certificate from a database. Specify the key to delete with the -n argument or the -k argument. Specify the database from which to delete the key with the
+<code class="option">-d</code> argument.
</p><p>
-When you delete keys, be sure to also remove any certificates associated with those keys from the certificate database, by using -D. Some smart cards do not let you remove a public key you have generated. In such a case, only the private key is deleted from the key pair. You can display the public key with the command certutil -K -h tokenname. </p></dd><dt><span class="term">-G </span></dt><dd><p>Generate a new public and private key pair within a key database. The key database should already exist; if one is not present, this command option will initialize one by default. Some smart cards can store only one key pair. If you create a new key pair for such a card, the previous pair is overwritten.</p></dd><dt><span class="term">-H </span></dt><dd><p>Display a list of the command options and arguments.</p></dd><dt><span class="term">-K </span></dt><dd><p>List the key ID of keys in the key database. A key ID is the modulus of the RSA key or the publicValue of the DSA key. IDs are displayed in hexadecimal ("0x" is not shown).</p></dd><dt><span class="term">-L </span></dt><dd><p>List all the certificates, or display information about a named certificate, in a certificate database.
+Some smart cards do not let you remove a public key you have generated. In such a case, only the private key is deleted from the key pair.</p></dd><dt><span class="term">-G </span></dt><dd><p>Generate a new public and private key pair within a key database. The key database should already exist; if one is not present, this command option will initialize one by default. Some smart cards can store only one key pair. If you create a new key pair for such a card, the previous pair is overwritten.</p></dd><dt><span class="term">-H </span></dt><dd><p>Display a list of the command options and arguments.</p></dd><dt><span class="term">-K </span></dt><dd><p>List the key ID of keys in the key database. A key ID is the modulus of the RSA key or the publicValue of the DSA key. IDs are displayed in hexadecimal ("0x" is not shown).</p></dd><dt><span class="term">-L </span></dt><dd><p>List all the certificates, or display information about a named certificate, in a certificate database.
Use the -h tokenname argument to specify the certificate database on a particular hardware or software token.</p></dd><dt><span class="term">-M </span></dt><dd><p>Modify a certificate's trust attributes using the values of the -t argument.</p></dd><dt><span class="term">-N</span></dt><dd><p>Create new certificate and key databases.</p></dd><dt><span class="term">-O </span></dt><dd><p>Print the certificate chain.</p></dd><dt><span class="term">-R</span></dt><dd><p>Create a certificate request file that can be submitted to a Certificate Authority (CA) for processing into a finished certificate. Output defaults to standard out unless you use -o output-file argument.
Use the -a argument to specify ASCII output.</p></dd><dt><span class="term">-S </span></dt><dd><p>Create an individual certificate and add it to a certificate database.</p></dd><dt><span class="term">-T </span></dt><dd><p>Reset the key database or token.</p></dd><dt><span class="term">-U </span></dt><dd><p>List all available modules or print a single named module.</p></dd><dt><span class="term">-V </span></dt><dd><p>Check the validity of a certificate and its attributes.</p></dd><dt><span class="term">-W </span></dt><dd><p>Change the password to a key database.</p></dd><dt><span class="term">--merge</span></dt><dd><p>Merge two databases into one.</p></dd><dt><span class="term">--upgrade-merge</span></dt><dd><p>Upgrade an old database and merge it into a new database. This is used to migrate legacy NSS databases (<code class="filename">cert8.db</code> and <code class="filename">key3.db</code>) into the newer SQLite databases (<code class="filename">cert9.db</code> and <code class="filename">key4.db</code>).</p></dd></dl></div><p><span class="command"><strong>Arguments</strong></span></p><p>Arguments modify a command option and are usually lower case, numbers, or symbols.</p><div class="variablelist"><dl class="variablelist"><dt><span class="term">-a</span></dt><dd><p>Use ASCII format or allow the use of ASCII format for input or output. This formatting follows RFC 1113.
diff --git a/doc/nroff/certutil.1 b/doc/nroff/certutil.1
index 80a02fc27..4918329cd 100644
--- a/doc/nroff/certutil.1
+++ b/doc/nroff/certutil.1
@@ -2,12 +2,12 @@
.\" Title: CERTUTIL
.\" Author: [see the "Authors" section]
.\" Generator: DocBook XSL Stylesheets vsnapshot <http://docbook.sf.net/>
-.\" Date: 27 October 2017
+.\" Date: 5 October 2017
.\" Manual: NSS Security Tools
.\" Source: nss-tools
.\" Language: English
.\"
-.TH "CERTUTIL" "1" "27 October 2017" "nss-tools" "NSS Security Tools"
+.TH "CERTUTIL" "1" "5 October 2017" "nss-tools" "NSS Security Tools"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@@ -92,15 +92,11 @@ Add an email certificate to the certificate database\&.
.PP
\-F
.RS 4
-Delete a private key from a key database\&. Specify the key to delete with the \-n argument\&. Specify the database from which to delete the key with the
+Delete a private key and the associated certificate from a database\&. Specify the key to delete with the \-n argument or the \-k argument\&. Specify the database from which to delete the key with the
\fB\-d\fR
-argument\&. Use the
-\fB\-k\fR
-argument to specify explicitly whether to delete a DSA, RSA, or ECC key\&. If you don\*(Aqt use the
-\fB\-k\fR
-argument, the option looks for an RSA key matching the specified nickname\&.
+argument\&.
.sp
-When you delete keys, be sure to also remove any certificates associated with those keys from the certificate database, by using \-D\&. Some smart cards do not let you remove a public key you have generated\&. In such a case, only the private key is deleted from the key pair\&. You can display the public key with the command certutil \-K \-h tokenname\&.
+Some smart cards do not let you remove a public key you have generated\&. In such a case, only the private key is deleted from the key pair\&.
.RE
.PP
\-G
diff --git a/tests/cert/cert.sh b/tests/cert/cert.sh
index 1fa3e7483..6da2a0be5 100755
--- a/tests/cert/cert.sh
+++ b/tests/cert/cert.sh
@@ -2496,6 +2496,29 @@ EOF
RETEXPECTED=0
}
+cert_test_orphan_key_delete()
+{
+ CU_ACTION="Create orphan key in serverdir"
+ certu -G -k ec -q nistp256 -f "${R_PWFILE}" -z ${R_NOISE_FILE} -d ${PROFILEDIR}
+ # Let's get the key ID of the first orphan key.
+ # The output of certutil -K (list keys) isn't well formatted.
+ # The initial <key-number> part may or may not contain white space, which
+ # makes the use of awk to filter the column unreliable.
+ # To fix that, we remove the initial <number> field using sed, then select the
+ # column that contains the key ID.
+ ORPHAN=`${BINDIR}/certutil -d ${PROFILEDIR} -K -f ${R_PWFILE} | \
+ sed 's/^<.*>//g' | grep -w orphan | head -1 | awk '{print $2}'`
+ CU_ACTION="Delete orphan key"
+ certu -F -f "${R_PWFILE}" -k ${ORPHAN} -d ${PROFILEDIR}
+ # Ensure that the key is removed
+ certu -K -f "${R_PWFILE}" -d ${PROFILEDIR} | grep ${ORPHAN}
+ RET=$?
+ if [ "$RET" -eq 0 ]; then
+ html_failed "Deleting orphan key ($RET)"
+ cert_log "ERROR: Deleting orphan key failed $RET"
+ fi
+}
+
cert_test_orphan_key_reuse()
{
CU_ACTION="Create orphan key in serverdir"
@@ -2540,6 +2563,7 @@ cert_all_CA
cert_test_implicit_db_init
cert_extended_ssl
cert_ssl
+cert_test_orphan_key_delete
cert_test_orphan_key_reuse
cert_smime_client
IS_FIPS_DISABLED=`certutil --build-flags |grep -cw NSS_FIPS_DISABLED`