--- a/cmd/certutil/certutil.c
+++ b/cmd/certutil/certutil.c
@@ -1197,16 +1197,29 @@ static void luG(enum usage_level ul, con
FPS "%-20s secp112r2, secp128r1, secp128r2, sect113r1, sect113r2\n", "");
FPS "%-20s sect131r1, sect131r2\n", "");
#endif /* NSS_ECC_MORE_THAN_SUITE_B */
#endif
FPS "%-20s Key database directory (default is ~/.netscape)\n",
" -d keydir");
FPS "%-20s Cert & Key database prefix\n",
" -P dbprefix");
+ FPS "%-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 PKCS #11 key Operation Flags\n",
+ " --keyOpFlagsOn opflags.");
+ FPS "%-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");
}
static void luD(enum usage_level ul, const char *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",
@@ -1428,16 +1441,18 @@ static void luR(enum usage_level ul, con
FPS "%-20s Cert & Key database prefix\n",
" -P dbprefix");
FPS "%-20s Specify the contact phone number (\"123-456-7890\")\n",
" -p phone");
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");
}
static void luV(enum usage_level ul, const char *command)
{
int is_my_command = (command && 0 == strcmp(command, "V"));
if (ul == usage_all || !command || is_my_command)
FPS "%-15s Validate a certificate\n",
@@ -1610,16 +1625,18 @@ static void luS(enum usage_level ul, con
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 "\n");
}
static void LongUsage(char *progName, enum usage_level ul, const char *command)
{
luA(ul, command);
@@ -1930,16 +1947,113 @@ getObjectClass(CK_ULONG classType)
}
if (classType >= CKO_NSS && classType <= CKO_NSS_BUILTIN_ROOT_LIST) {
return objNSSClassArray[classType - CKO_NSS];
}
sprintf(buf, "0x%lx", classType);
return buf;
}
+typedef struct {
+ char *name;
+ int nameSize;
+ CK_ULONG value;
+} flagArray;
+
+#define NAME_SIZE(x) #x,sizeof(#x)-1
+
+flagArray opFlagsArray[] =
+{
+ {NAME_SIZE(encrypt), CKF_ENCRYPT},
+ {NAME_SIZE(decrypt), CKF_DECRYPT},
+ {NAME_SIZE(sign), CKF_SIGN},
+ {NAME_SIZE(sign_recover), CKF_SIGN_RECOVER},
+ {NAME_SIZE(verify), CKF_VERIFY},
+ {NAME_SIZE(verify_recover), CKF_VERIFY_RECOVER},
+ {NAME_SIZE(wrap), CKF_WRAP},
+ {NAME_SIZE(unwrap), CKF_UNWRAP},
+ {NAME_SIZE(derive), CKF_DERIVE},
+};
+
+int opFlagsCount = sizeof(opFlagsArray)/sizeof(flagArray);
+
+flagArray attrFlagsArray[] =
+{
+ {NAME_SIZE(token), PK11_ATTR_TOKEN},
+ {NAME_SIZE(session), PK11_ATTR_SESSION},
+ {NAME_SIZE(private), PK11_ATTR_PRIVATE},
+ {NAME_SIZE(public), PK11_ATTR_PUBLIC},
+ {NAME_SIZE(modifiable), PK11_ATTR_MODIFIABLE},
+ {NAME_SIZE(unmodifiable), PK11_ATTR_UNMODIFIABLE},
+ {NAME_SIZE(sensitive), PK11_ATTR_SENSITIVE},
+ {NAME_SIZE(insensitive), PK11_ATTR_INSENSITIVE},
+ {NAME_SIZE(extractable), PK11_ATTR_EXTRACTABLE},
+ {NAME_SIZE(unextractable), PK11_ATTR_EXTRACTABLE}
+
+};
+
+int attrFlagsCount = sizeof(attrFlagsArray)/sizeof(flagArray);
+
+#define MAX_STRING 30
+CK_ULONG
+GetFlags(char *flagsString, flagArray *flagArray, int count)
+{
+ CK_ULONG flagsValue = strtol(flagsString, NULL, 0);
+ int i;
+
+fprintf(stderr, "parsing flags <%s>\n", flagsString);
+
+ if ((flagsValue != 0) || (*flagsString == 0)) {
+ return flagsValue;
+ }
+ while (*flagsString) {
+ for (i=0; i < count; i++) {
+ if (strncmp(flagsString, flagArray[i].name, flagArray[i].nameSize)
+ == 0) {
+ flagsValue |= flagArray[i].value;
+ flagsString += flagArray[i].nameSize;
+ if (*flagsString != 0) {
+ flagsString++;
+ }
+ break;
+ }
+ }
+ if (i == count) {
+ char name[MAX_STRING];
+ char *tok;
+
+ strncpy(name,flagsString, MAX_STRING);
+ name[MAX_STRING-1] = 0;
+ tok = strchr(name, ',');
+ if (tok) {
+ *tok = 0;
+ }
+ fprintf(stderr,"Unknown flag (%s)\n",name);
+ tok = strchr(flagsString, ',');
+ if (tok == NULL) {
+ break;
+ }
+ flagsString = tok+1;
+ }
+ }
+ return flagsValue;
+}
+
+CK_FLAGS
+GetOpFlags(char *flags)
+{
+ return GetFlags(flags, opFlagsArray, opFlagsCount);
+}
+
+PK11AttrFlags
+GetAttrFlags(char *flags)
+{
+ return GetFlags(flags, attrFlagsArray, attrFlagsCount);
+}
+
char *mkNickname(unsigned char *data, int len)
{
char *nick = PORT_Alloc(len+1);
if (!nick) {
return nick;
}
PORT_Memcpy(nick, data, len);
nick[len] = 0;
@@ -2069,16 +2183,19 @@ enum certutilOpts {
opt_AddSubjectKeyIDExt,
opt_AddCmdKeyUsageExt,
opt_AddCmdNSCertTypeExt,
opt_AddCmdExtKeyUsageExt,
opt_SourceDir,
opt_SourcePrefix,
opt_UpgradeID,
opt_UpgradeTokenName,
+ opt_KeyOpFlagsOn,
+ opt_KeyOpFlagsOff,
+ opt_KeyAttrFlags,
opt_Help
};
static const
secuCommandFlag commands_init[] =
{
{ /* cmd_AddCert */ 'A', PR_FALSE, 0, PR_FALSE },
{ /* cmd_CreateNewCert */ 'C', PR_FALSE, 0, PR_FALSE },
@@ -2170,16 +2287,22 @@ secuCommandFlag options_init[] =
{ /* opt_SourceDir */ 0, PR_TRUE, 0, PR_FALSE,
"source-dir"},
{ /* opt_SourcePrefix */ 0, PR_TRUE, 0, PR_FALSE,
"source-prefix"},
{ /* opt_UpgradeID */ 0, PR_TRUE, 0, PR_FALSE,
"upgrade-id"},
{ /* opt_UpgradeTokenName */ 0, PR_TRUE, 0, PR_FALSE,
"upgrade-token-name"},
+ { /* opt_KeyOpFlagsOn */ 0, PR_TRUE, 0, PR_FALSE,
+ "keyOpFlagsOn"},
+ { /* opt_KeyOpFlagsOff */ 0, PR_TRUE, 0, PR_FALSE,
+ "keyOpFlagsOff"},
+ { /* opt_KeyAttrFlags */ 0, PR_TRUE, 0, PR_FALSE,
+ "keyAttrFlags"},
};
#define NUM_OPTIONS ((sizeof options_init) / (sizeof options_init[0]))
static secuCommandFlag certutil_commands[NUM_COMMANDS];
static secuCommandFlag certutil_options [NUM_OPTIONS ];
static const secuCommand certutil = {
NUM_COMMANDS,
@@ -2217,16 +2340,20 @@ certutil_main(int argc, char **argv, PRB
int warpmonths = 0;
int validityMonths = 3;
int commandsEntered = 0;
char commandToRun = '\0';
secuPWData pwdata = { PW_NONE, 0 };
secuPWData pwdata2 = { PW_NONE, 0 };
PRBool readOnly = PR_FALSE;
PRBool initialized = PR_FALSE;
+ CK_FLAGS keyOpFlagsOn = 0;
+ CK_FLAGS keyOpFlagsOff = 0;
+ PK11AttrFlags keyAttrFlags =
+ PK11_ATTR_TOKEN | PK11_ATTR_SENSITIVE | PK11_ATTR_PRIVATE;
SECKEYPrivateKey *privkey = NULL;
SECKEYPublicKey *pubkey = NULL;
int i;
SECStatus rv;
progName = PORT_Strrchr(argv[0], '/');
@@ -2339,16 +2466,27 @@ certutil_main(int argc, char **argv, PRB
} else {
/* use an existing private/public key pair */
keysource = arg;
}
} else if (certutil.commands[cmd_ListKeys].activated) {
keytype = nullKey;
}
+ 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;
}
@@ -2932,16 +3070,19 @@ merge_fail:
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;