diff --git a/security/nss/lib/nss/nss.def b/security/nss/lib/nss/nss.def index ca3fd0d335d5..caa15f605b77 100644 --- a/security/nss/lib/nss/nss.def +++ b/security/nss/lib/nss/nss.def @@ -853,6 +853,7 @@ NSS_Get_CERT_SignedCrlTemplate; ;+NSS_3.10.2 { # NSS 3.10.2 release ;+ global: PK11_TokenKeyGenWithFlags; +PK11_GenerateKeyPairWithFlags; ;+ local: ;+ *; ;+}; diff --git a/security/nss/lib/pk11wrap/pk11akey.c b/security/nss/lib/pk11wrap/pk11akey.c index 6f27edbb383a..865177d54920 100644 --- a/security/nss/lib/pk11wrap/pk11akey.c +++ b/security/nss/lib/pk11wrap/pk11akey.c @@ -501,18 +501,14 @@ PK11_GetPrivateModulusLen(SECKEYPrivateKey *key) * This is used to do a key gen using one pkcs11 module and storing the * result into another. */ -SECKEYPrivateKey * -pk11_loadPrivKey(PK11SlotInfo *slot,SECKEYPrivateKey *privKey, - SECKEYPublicKey *pubKey, PRBool token, PRBool sensitive) +static SECKEYPrivateKey * +pk11_loadPrivKeyWithFlags(PK11SlotInfo *slot,SECKEYPrivateKey *privKey, + SECKEYPublicKey *pubKey, PK11AttrFlags attrFlags) { CK_ATTRIBUTE privTemplate[] = { /* class must be first */ { CKA_CLASS, NULL, 0 }, { CKA_KEY_TYPE, NULL, 0 }, - /* these three must be next */ - { CKA_TOKEN, NULL, 0 }, - { CKA_PRIVATE, NULL, 0 }, - { CKA_SENSITIVE, NULL, 0 }, { CKA_ID, NULL, 0 }, #ifdef notdef { CKA_LABEL, NULL, 0 }, @@ -527,15 +523,31 @@ pk11_loadPrivKey(PK11SlotInfo *slot,SECKEYPrivateKey *privKey, { CKA_EXPONENT_1, NULL, 0 }, { CKA_EXPONENT_2, NULL, 0 }, { CKA_COEFFICIENT, NULL, 0 }, + /* reserve space for the attributes that may be + * specified in attrFlags */ + { CKA_TOKEN, NULL, 0 }, + { CKA_PRIVATE, NULL, 0 }, + { CKA_MODIFIABLE, NULL, 0 }, + { CKA_SENSITIVE, NULL, 0 }, + { CKA_EXTRACTABLE, NULL, 0 }, +#define NUM_RESERVED_ATTRS 5 /* number of reserved attributes above */ }; + CK_BBOOL cktrue = CK_TRUE; + CK_BBOOL ckfalse = CK_FALSE; CK_ATTRIBUTE *attrs = NULL, *ap; - int templateSize = sizeof(privTemplate)/sizeof(privTemplate[0]); + const int templateSize = sizeof(privTemplate)/sizeof(privTemplate[0]); PRArenaPool *arena; CK_OBJECT_HANDLE objectID; int i, count = 0; int extra_count = 0; CK_RV crv; SECStatus rv; + PRBool token = ((attrFlags & PK11_ATTR_TOKEN) != 0); + + if (pk11_BadAttrFlags(attrFlags)) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return NULL; + } for (i=0; i < templateSize; i++) { if (privTemplate[i].type == CKA_MODULUS) { @@ -554,8 +566,8 @@ pk11_loadPrivKey(PK11SlotInfo *slot,SECKEYPrivateKey *privKey, switch (privKey->keyType) { case rsaKey: - count = templateSize; - extra_count = templateSize - (attrs - privTemplate); + count = templateSize - NUM_RESERVED_ATTRS; + extra_count = count - (attrs - privTemplate); break; case dsaKey: ap->type = CKA_PRIME; ap++; count++; extra_count++; @@ -596,10 +608,9 @@ pk11_loadPrivKey(PK11SlotInfo *slot,SECKEYPrivateKey *privKey, return NULL; } - /* Reset sensitive, token, and private */ - *(CK_BBOOL *)(privTemplate[2].pValue) = token ? CK_TRUE : CK_FALSE; - *(CK_BBOOL *)(privTemplate[3].pValue) = token ? CK_TRUE : CK_FALSE; - *(CK_BBOOL *)(privTemplate[4].pValue) = sensitive ? CK_TRUE : CK_FALSE; + /* Set token, private, modifiable, sensitive, and extractable */ + count += pk11_AttrFlagsToAttributes(attrFlags, &privTemplate[count], + &cktrue, &ckfalse); /* Not everyone can handle zero padded key values, give * them the raw data as unsigned */ @@ -630,6 +641,24 @@ pk11_loadPrivKey(PK11SlotInfo *slot,SECKEYPrivateKey *privKey, objectID, privKey->wincx); } +static SECKEYPrivateKey * +pk11_loadPrivKey(PK11SlotInfo *slot,SECKEYPrivateKey *privKey, + SECKEYPublicKey *pubKey, PRBool token, PRBool sensitive) +{ + PK11AttrFlags attrFlags = 0; + if (token) { + attrFlags |= (PK11_ATTR_TOKEN | PK11_ATTR_PRIVATE); + } else { + attrFlags |= PK11_ATTR_PUBLIC; + } + if (sensitive) { + attrFlags |= PK11_ATTR_SENSITIVE; + } else { + attrFlags |= PK11_ATTR_INSENSITIVE; + } + return pk11_loadPrivKeyWithFlags(slot, privKey, pubKey, attrFlags); +} + /* * export this for PSM */ @@ -647,9 +676,8 @@ PK11_LoadPrivKey(PK11SlotInfo *slot,SECKEYPrivateKey *privKey, * from this interface! */ SECKEYPrivateKey * -PK11_GenerateKeyPair(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, - void *param, SECKEYPublicKey **pubKey, PRBool token, - PRBool sensitive, void *wincx) +PK11_GenerateKeyPairWithFlags(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, + void *param, SECKEYPublicKey **pubKey, PK11AttrFlags attrFlags, void *wincx) { /* we have to use these native types because when we call PKCS 11 modules * we have to make sure that we are using the correct sizes for all the @@ -666,6 +694,8 @@ PK11_GenerateKeyPair(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, { CKA_UNWRAP, NULL, 0}, { CKA_SIGN, NULL, 0}, { CKA_DECRYPT, NULL, 0}, + { CKA_EXTRACTABLE, NULL, 0}, + { CKA_MODIFIABLE, NULL, 0}, }; CK_ATTRIBUTE rsaPubTemplate[] = { { CKA_MODULUS_BITS, NULL, 0}, @@ -676,6 +706,7 @@ PK11_GenerateKeyPair(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, { CKA_VERIFY, NULL, 0}, { CKA_VERIFY_RECOVER, NULL, 0}, { CKA_ENCRYPT, NULL, 0}, + { CKA_MODIFIABLE, NULL, 0}, }; CK_ATTRIBUTE dsaPubTemplate[] = { { CKA_PRIME, NULL, 0 }, @@ -687,6 +718,7 @@ PK11_GenerateKeyPair(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, { CKA_VERIFY, NULL, 0}, { CKA_VERIFY_RECOVER, NULL, 0}, { CKA_ENCRYPT, NULL, 0}, + { CKA_MODIFIABLE, NULL, 0}, }; CK_ATTRIBUTE dhPubTemplate[] = { { CKA_PRIME, NULL, 0 }, @@ -697,6 +729,7 @@ PK11_GenerateKeyPair(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, { CKA_VERIFY, NULL, 0}, { CKA_VERIFY_RECOVER, NULL, 0}, { CKA_ENCRYPT, NULL, 0}, + { CKA_MODIFIABLE, NULL, 0}, }; CK_ATTRIBUTE ecPubTemplate[] = { { CKA_EC_PARAMS, NULL, 0 }, @@ -706,16 +739,13 @@ PK11_GenerateKeyPair(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, { CKA_VERIFY, NULL, 0}, { CKA_VERIFY_RECOVER, NULL, 0}, { CKA_ENCRYPT, NULL, 0}, + { CKA_MODIFIABLE, NULL, 0}, }; - int ecPubCount = sizeof(ecPubTemplate)/sizeof(ecPubTemplate[0]); SECKEYECParams * ecParams; - int dsaPubCount = sizeof(dsaPubTemplate)/sizeof(dsaPubTemplate[0]); /*CK_ULONG key_size = 0;*/ CK_ATTRIBUTE *pubTemplate; - int privCount = sizeof(privTemplate)/sizeof(privTemplate[0]); - int rsaPubCount = sizeof(rsaPubTemplate)/sizeof(rsaPubTemplate[0]); - int dhPubCount = sizeof(dhPubTemplate)/sizeof(dhPubTemplate[0]); + int privCount = 0; int pubCount = 0; PK11RSAGenParams *rsaParams; SECKEYPQGParams *dsaParams; @@ -738,6 +768,13 @@ PK11_GenerateKeyPair(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, SECItem *cka_id; PRBool haslock = PR_FALSE; PRBool pubIsToken = PR_FALSE; + PRBool token = ((attrFlags & PK11_ATTR_TOKEN) != 0); + PRBool readOnly = ((attrFlags & PK11_ATTR_READONLY) != 0); + + if (pk11_BadAttrFlags(attrFlags)) { + PORT_SetError( SEC_ERROR_INVALID_ARGS ); + return NULL; + } PORT_Assert(slot != NULL); if (slot == NULL) { @@ -770,8 +807,8 @@ PK11_GenerateKeyPair(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, /* if successful, load the temp key into the new token */ if (privKey != NULL) { - SECKEYPrivateKey *newPrivKey = pk11_loadPrivKey(slot,privKey, - *pubKey,token,sensitive); + SECKEYPrivateKey *newPrivKey = pk11_loadPrivKeyWithFlags(slot, + privKey,*pubKey,attrFlags); SECKEY_DestroyPrivateKey(privKey); if (newPrivKey == NULL) { SECKEY_DestroyPublicKey(*pubKey); @@ -791,12 +828,8 @@ PK11_GenerateKeyPair(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, /* set up the private key template */ privattrs = privTemplate; - PK11_SETATTRS(privattrs, CKA_SENSITIVE, sensitive ? &cktrue : &ckfalse, - sizeof(CK_BBOOL)); privattrs++; - PK11_SETATTRS(privattrs, CKA_TOKEN, token ? &cktrue : &ckfalse, - sizeof(CK_BBOOL)); privattrs++; - PK11_SETATTRS(privattrs, CKA_PRIVATE, sensitive ? &cktrue : &ckfalse, - sizeof(CK_BBOOL)); privattrs++; + privattrs += pk11_AttrFlagsToAttributes(attrFlags, privattrs, + &cktrue, &ckfalse); /* set up the mechanism specific info */ switch (type) { @@ -826,7 +859,6 @@ PK11_GenerateKeyPair(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT, publicExponent, peCount);attrs++; pubTemplate = rsaPubTemplate; - pubCount = rsaPubCount; keyType = rsaKey; test_mech.mechanism = CKM_RSA_PKCS; break; @@ -840,7 +872,6 @@ PK11_GenerateKeyPair(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, PK11_SETATTRS(attrs, CKA_BASE, dsaParams->base.data, dsaParams->base.len); attrs++; pubTemplate = dsaPubTemplate; - pubCount = dsaPubCount; keyType = dsaKey; test_mech.mechanism = CKM_DSA; break; @@ -852,7 +883,6 @@ PK11_GenerateKeyPair(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, PK11_SETATTRS(attrs, CKA_BASE, dhParams->base.data, dhParams->base.len); attrs++; pubTemplate = dhPubTemplate; - pubCount = dhPubCount; keyType = dhKey; test_mech.mechanism = CKM_DH_PKCS_DERIVE; break; @@ -862,7 +892,6 @@ PK11_GenerateKeyPair(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, PK11_SETATTRS(attrs, CKA_EC_PARAMS, ecParams->data, ecParams->len); attrs++; pubTemplate = ecPubTemplate; - pubCount = ecPubCount; keyType = ecKey; /* XXX An EC key can be used for other mechanisms too such * as CKM_ECDSA and CKM_ECDSA_SHA1. How can we reflect @@ -905,7 +934,7 @@ PK11_GenerateKeyPair(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, break; } } - /* set the public key objects */ + /* set the public key attributes */ PK11_SETATTRS(attrs, CKA_TOKEN, token ? &cktrue : &ckfalse, sizeof(CK_BBOOL)); attrs++; PK11_SETATTRS(attrs, CKA_DERIVE, @@ -923,6 +952,12 @@ PK11_GenerateKeyPair(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, PK11_SETATTRS(attrs, CKA_ENCRYPT, mechanism_info.flags & CKF_ENCRYPT? &cktrue : &ckfalse, sizeof(CK_BBOOL)); attrs++; + if (readOnly) { + /* the default value of the CKA_MODIFIABLE attribute is CK_TRUE */ + PK11_SETATTRS(attrs, CKA_MODIFIABLE, &ckfalse, + sizeof(CK_BBOOL)); attrs++; + } + /* set the private key attributes */ PK11_SETATTRS(privattrs, CKA_DERIVE, mechanism_info.flags & CKF_DERIVE ? &cktrue : &ckfalse, sizeof(CK_BBOOL)); privattrs++; @@ -952,6 +987,8 @@ PK11_GenerateKeyPair(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, PORT_SetError(SEC_ERROR_BAD_DATA); return NULL; } + privCount = privattrs - privTemplate; + pubCount = attrs - pubTemplate; crv = PK11_GETTAB(slot)->C_GenerateKeyPair(session_handle, &mechanism, pubTemplate,pubCount,privTemplate,privCount,&pubID,&privID); @@ -1049,6 +1086,25 @@ PK11_GenerateKeyPair(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, return privKey; } +SECKEYPrivateKey * +PK11_GenerateKeyPair(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, + void *param, SECKEYPublicKey **pubKey, PRBool token, + PRBool sensitive, void *wincx) +{ + PK11AttrFlags attrFlags = 0; + + if (token) { + attrFlags |= PK11_ATTR_TOKEN; + } + if (sensitive) { + attrFlags |= (PK11_ATTR_SENSITIVE | PK11_ATTR_PRIVATE); + } else { + attrFlags |= (PK11_ATTR_INSENSITIVE | PK11_ATTR_PUBLIC); + } + return PK11_GenerateKeyPairWithFlags(slot, type, param, pubKey, + attrFlags, wincx); +} + /* build a public KEA key from the public value */ SECKEYPublicKey * PK11_MakeKEAPubKey(unsigned char *keyData,int length) diff --git a/security/nss/lib/pk11wrap/pk11obj.c b/security/nss/lib/pk11wrap/pk11obj.c index db052e71c0f5..f0b183e5f6f7 100644 --- a/security/nss/lib/pk11wrap/pk11obj.c +++ b/security/nss/lib/pk11wrap/pk11obj.c @@ -425,7 +425,7 @@ PK11_CreateNewObject(PK11SlotInfo *slot, CK_SESSION_HANDLE session, /* This function may add a maximum of 9 attributes. */ unsigned int -pk11_FlagsToAttributes(CK_FLAGS flags, CK_ATTRIBUTE *attrs, CK_BBOOL *ckTrue) +pk11_OpFlagsToAttributes(CK_FLAGS flags, CK_ATTRIBUTE *attrs, CK_BBOOL *ckTrue) { const static CK_ATTRIBUTE_TYPE attrTypes[12] = { @@ -454,6 +454,88 @@ pk11_FlagsToAttributes(CK_FLAGS flags, CK_ATTRIBUTE *attrs, CK_BBOOL *ckTrue) return (attr - attrs); } +/* + * Check for conflicting flags, for example, if both PK11_ATTR_PRIVATE + * and PK11_ATTR_PUBLIC are set. + */ +PRBool +pk11_BadAttrFlags(PK11AttrFlags attrFlags) +{ + PK11AttrFlags trueFlags = attrFlags & 0x55555555; + PK11AttrFlags falseFlags = attrFlags >> 1 & 0x55555555; + return (trueFlags & falseFlags) != 0 ? PR_TRUE : PR_FALSE; +} + +/* + * This function may add a maximum of 5 attributes. + * The caller must make sure the attribute flags don't have conflicts. + */ +unsigned int +pk11_AttrFlagsToAttributes(PK11AttrFlags attrFlags, CK_ATTRIBUTE *attrs, + CK_BBOOL *ckTrue, CK_BBOOL *ckFalse) +{ + CK_ATTRIBUTE *attr = attrs; + + PR_ASSERT(!pk11_BadAttrFlags(attrFlags)); + + /* + * The default value of the CKA_TOKEN attribute is CK_FALSE, + * so we only need to set this attribute for CK_TRUE. + */ + if (attrFlags & PK11_ATTR_TOKEN) { + PK11_SETATTRS(attr, CKA_TOKEN, ckTrue, sizeof *ckTrue); + ++attr; + } + + /* + * The default value of the CKA_PRIVATE attribute is + * token-specific. + */ + if (attrFlags & PK11_ATTR_PRIVATE) { + PK11_SETATTRS(attr, CKA_PRIVATE, ckTrue, sizeof *ckTrue); + ++attr; + } else if (attrFlags & PK11_ATTR_PUBLIC) { + PK11_SETATTRS(attr, CKA_PRIVATE, ckFalse, sizeof *ckFalse); + ++attr; + } + + /* + * The default value of the CKA_MODIFIABLE attribute is CK_TRUE, + * so we only need to set this attribute for CK_FALSE. + */ + if (attrFlags & PK11_ATTR_READONLY) { + PK11_SETATTRS(attr, CKA_MODIFIABLE, ckFalse, sizeof *ckFalse); + ++attr; + } + + /* + * For private keys, the default value of the CKA_SENSITIVE + * attribute is token-specific. For secret keys, the default + * value of this attribute is CK_FALSE per PKCS #11 but in + * practice it is token-specific. + */ + if (attrFlags & PK11_ATTR_SENSITIVE) { + PK11_SETATTRS(attr, CKA_SENSITIVE, ckTrue, sizeof *ckTrue); + ++attr; + } else if (attrFlags & PK11_ATTR_INSENSITIVE) { + PK11_SETATTRS(attr, CKA_SENSITIVE, ckFalse, sizeof *ckFalse); + ++attr; + } + + /* + * The default value of the CKA_EXTRACTABLE attribute is + * token-specific. + */ + if (attrFlags & PK11_ATTR_EXTRACTABLE) { + PK11_SETATTRS(attr, CKA_EXTRACTABLE, ckTrue, sizeof *ckTrue); + ++attr; + } else if (attrFlags & PK11_ATTR_UNEXTRACTABLE) { + PK11_SETATTRS(attr, CKA_EXTRACTABLE, ckFalse, sizeof *ckFalse); + ++attr; + } + return (attr - attrs); +} + /* * Some non-compliant PKCS #11 vendors do not give us the modulus, so actually * set up a signature to get the signaure length. diff --git a/security/nss/lib/pk11wrap/pk11pub.h b/security/nss/lib/pk11wrap/pk11pub.h index 9986689497c1..2be5afdefb21 100644 --- a/security/nss/lib/pk11wrap/pk11pub.h +++ b/security/nss/lib/pk11wrap/pk11pub.h @@ -240,8 +240,8 @@ PK11SymKey *PK11_TokenKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, PRBool isToken, void *wincx); PK11SymKey *PK11_TokenKeyGenWithFlags(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param, - int keySize, SECItem *keyid, CK_FLAGS flags, - PRBool isToken, void *wincx); + int keySize, SECItem *keyid, CK_FLAGS opFlags, + PK11AttrFlags attrFlags, void *wincx); PK11SymKey * PK11_ListFixedKeysInSlot(PK11SlotInfo *slot, char *nickname, void *wincx); PK11SymKey *PK11_GetNextSymKey(PK11SymKey *symKey); @@ -351,6 +351,14 @@ SECStatus PK11_ExtractKeyValue(PK11SymKey *symKey); SECItem * PK11_GetKeyData(PK11SymKey *symKey); PK11SlotInfo * PK11_GetSlotFromKey(PK11SymKey *symKey); void *PK11_GetWindow(PK11SymKey *symKey); +/* + * The attrFlags is the logical OR of the PK11_ATTR_XXX bitflags. + * These flags apply to the private key. The PK11_ATTR_TOKEN and + * PK11_ATTR_READONLY flags also apply to the public key. + */ +SECKEYPrivateKey *PK11_GenerateKeyPairWithFlags(PK11SlotInfo *slot, + CK_MECHANISM_TYPE type, void *param, SECKEYPublicKey **pubk, + PK11AttrFlags attrFlags, void *wincx); SECKEYPrivateKey *PK11_GenerateKeyPair(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, void *param, SECKEYPublicKey **pubk, PRBool isPerm, PRBool isSensitive, void *wincx); diff --git a/security/nss/lib/pk11wrap/pk11skey.c b/security/nss/lib/pk11wrap/pk11skey.c index 0fb52efcf9f8..8d9a1d3990ad 100644 --- a/security/nss/lib/pk11wrap/pk11skey.c +++ b/security/nss/lib/pk11wrap/pk11skey.c @@ -424,7 +424,7 @@ PK11_ImportSymKeyWithFlags(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, * default for secret keys */ PK11_SETATTRS(attrs, CKA_PRIVATE, &cktrue, sizeof(cktrue) ); attrs++; } - attrs += pk11_FlagsToAttributes(flags, attrs, &cktrue); + attrs += pk11_OpFlagsToAttributes(flags, attrs, &cktrue); if ((operation != CKA_FLAGS_ONLY) && !pk11_FindAttrInTemplate(keyTemplate, attrs-keyTemplate, operation)) { PK11_SETATTRS(attrs, operation, &cktrue, sizeof(cktrue)); attrs++; @@ -788,11 +788,14 @@ PK11_MoveSymKey(PK11SlotInfo *slot, CK_ATTRIBUTE_TYPE operation, * NOTE: this means to generate a DES2 key from this interface you must * specify CKM_DES2_KEY_GEN as the mechanism directly; specifying * CKM_DES3_CBC as the mechanism and 16 as keySize currently doesn't work. + * + * CK_FLAGS flags: key operation flags + * PK11AttrFlags attrFlags: PK11_ATTR_XXX key attribute flags */ PK11SymKey * PK11_TokenKeyGenWithFlags(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, - SECItem *param, int keySize, SECItem *keyid, CK_FLAGS flags, - PRBool isToken, void *wincx) + SECItem *param, int keySize, SECItem *keyid, CK_FLAGS opFlags, + PK11AttrFlags attrFlags, void *wincx) { PK11SymKey *symKey; CK_ATTRIBUTE genTemplate[MAX_TEMPL_ATTRS]; @@ -802,7 +805,14 @@ PK11_TokenKeyGenWithFlags(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, CK_MECHANISM mechanism; CK_RV crv; CK_BBOOL cktrue = CK_TRUE; + CK_BBOOL ckfalse = CK_FALSE; CK_ULONG ck_key_size; /* only used for variable-length keys */ + PRBool isToken = ((attrFlags & PK11_ATTR_TOKEN) != 0); + + if (pk11_BadAttrFlags(attrFlags)) { + PORT_SetError( SEC_ERROR_INVALID_ARGS ); + return NULL; + } if (keySize != 0) { ck_key_size = keySize; /* Convert to PK11 type */ @@ -816,12 +826,8 @@ PK11_TokenKeyGenWithFlags(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, PK11_SETATTRS(attrs, CKA_ID, keyid->data, keyid->len); attrs++; } - if (isToken) { - PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(cktrue)); attrs++; - PK11_SETATTRS(attrs, CKA_PRIVATE, &cktrue, sizeof(cktrue)); attrs++; - } - - attrs += pk11_FlagsToAttributes(flags, attrs, &cktrue); + attrs += pk11_AttrFlagsToAttributes(attrFlags, attrs, &cktrue, &ckfalse); + attrs += pk11_OpFlagsToAttributes(opFlags, attrs, &cktrue); count = attrs - genTemplate; PR_ASSERT(count <= sizeof(genTemplate)/sizeof(CK_ATTRIBUTE)); @@ -905,7 +911,8 @@ PK11_TokenKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param, { PK11SymKey *symKey; PRBool weird = PR_FALSE; /* hack for fortezza */ - CK_FLAGS flags = CKF_SIGN; + CK_FLAGS opFlags = CKF_SIGN; + PK11AttrFlags attrFlags = 0; if ((keySize == -1) && (type == CKM_SKIPJACK_CBC64)) { weird = PR_TRUE; @@ -913,10 +920,14 @@ PK11_TokenKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param, } /* TNH: Isn't this redundant, since "handleKey" will set defaults? */ - flags |= weird ? CKF_DECRYPT : CKF_ENCRYPT; + opFlags |= weird ? CKF_DECRYPT : CKF_ENCRYPT; + + if (isToken) { + attrFlags |= (PK11_ATTR_TOKEN | PK11_ATTR_PRIVATE); + } symKey = PK11_TokenKeyGenWithFlags(slot, type, param, keySize, keyid, - flags, isToken, wincx); + opFlags, attrFlags, wincx); if (symKey && weird) { PK11_SetFortezzaHack(symKey); } @@ -1210,7 +1221,7 @@ PK11_DeriveWithFlags( PK11SymKey *baseKey, CK_MECHANISM_TYPE derive, CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; unsigned int templateCount; - templateCount = pk11_FlagsToAttributes(flags, keyTemplate, &ckTrue); + templateCount = pk11_OpFlagsToAttributes(flags, keyTemplate, &ckTrue); return pk11_DeriveWithTemplate(baseKey, derive, param, target, operation, keySize, keyTemplate, templateCount, PR_FALSE); } @@ -1230,7 +1241,7 @@ PK11_DeriveWithFlagsPerm( PK11SymKey *baseKey, CK_MECHANISM_TYPE derive, PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL)); attrs++; } templateCount = attrs - keyTemplate; - templateCount += pk11_FlagsToAttributes(flags, attrs, &cktrue); + templateCount += pk11_OpFlagsToAttributes(flags, attrs, &cktrue); return pk11_DeriveWithTemplate(baseKey, derive, param, target, operation, keySize, keyTemplate, templateCount, isPerm); } @@ -1893,7 +1904,7 @@ PK11_UnwrapSymKeyWithFlags(PK11SymKey *wrappingKey, CK_MECHANISM_TYPE wrapType, CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; unsigned int templateCount; - templateCount = pk11_FlagsToAttributes(flags, keyTemplate, &ckTrue); + templateCount = pk11_OpFlagsToAttributes(flags, keyTemplate, &ckTrue); return pk11_AnyUnwrapKey(wrappingKey->slot, wrappingKey->objectID, wrapType, param, wrappedKey, target, operation, keySize, wrappingKey->cx, keyTemplate, templateCount, PR_FALSE); @@ -1916,7 +1927,7 @@ PK11_UnwrapSymKeyWithFlagsPerm(PK11SymKey *wrappingKey, PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL)); attrs++; } templateCount = attrs-keyTemplate; - templateCount += pk11_FlagsToAttributes(flags, attrs, &cktrue); + templateCount += pk11_OpFlagsToAttributes(flags, attrs, &cktrue); return pk11_AnyUnwrapKey(wrappingKey->slot, wrappingKey->objectID, wrapType, param, wrappedKey, target, operation, keySize, @@ -1953,7 +1964,7 @@ PK11_PubUnwrapSymKeyWithFlags(SECKEYPrivateKey *wrappingKey, unsigned int templateCount; PK11SlotInfo *slot = wrappingKey->pkcs11Slot; - templateCount = pk11_FlagsToAttributes(flags, keyTemplate, &ckTrue); + templateCount = pk11_OpFlagsToAttributes(flags, keyTemplate, &ckTrue); if (SECKEY_HAS_ATTRIBUTE_SET(wrappingKey,CKA_PRIVATE)) { PK11_HandlePasswordCheck(slot,wrappingKey->wincx); @@ -1983,7 +1994,7 @@ PK11_PubUnwrapSymKeyWithFlagsPerm(SECKEYPrivateKey *wrappingKey, } templateCount = attrs-keyTemplate; - templateCount += pk11_FlagsToAttributes(flags, attrs, &cktrue); + templateCount += pk11_OpFlagsToAttributes(flags, attrs, &cktrue); if (SECKEY_HAS_ATTRIBUTE_SET(wrappingKey,CKA_PRIVATE)) { PK11_HandlePasswordCheck(slot,wrappingKey->wincx); diff --git a/security/nss/lib/pk11wrap/secmodi.h b/security/nss/lib/pk11wrap/secmodi.h index eca0c4b20ce6..425bf705c313 100644 --- a/security/nss/lib/pk11wrap/secmodi.h +++ b/security/nss/lib/pk11wrap/secmodi.h @@ -124,8 +124,14 @@ CK_SESSION_HANDLE pk11_GetNewSession(PK11SlotInfo *slot, PRBool *owner); void pk11_CloseSession(PK11SlotInfo *slot, CK_SESSION_HANDLE sess, PRBool own); PK11SymKey *pk11_ForceSlot(PK11SymKey *symKey, CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE operation); -unsigned int pk11_FlagsToAttributes(CK_FLAGS flags, +/* Convert key operation flags to PKCS #11 attributes. */ +unsigned int pk11_OpFlagsToAttributes(CK_FLAGS flags, CK_ATTRIBUTE *attrs, CK_BBOOL *ckTrue); +/* Check for bad (conflicting) attribute flags */ +PRBool pk11_BadAttrFlags(PK11AttrFlags attrFlags); +/* Convert key attribute flags to PKCS #11 attributes. */ +unsigned int pk11_AttrFlagsToAttributes(PK11AttrFlags attrFlags, + CK_ATTRIBUTE *attrs, CK_BBOOL *ckTrue, CK_BBOOL *ckFalse); PRBool pk11_FindAttrInTemplate(CK_ATTRIBUTE *attr, unsigned int numAttrs, CK_ATTRIBUTE_TYPE target); diff --git a/security/nss/lib/pk11wrap/secmodt.h b/security/nss/lib/pk11wrap/secmodt.h index 7a07f5302d58..199dfe27bd4c 100644 --- a/security/nss/lib/pk11wrap/secmodt.h +++ b/security/nss/lib/pk11wrap/secmodt.h @@ -194,6 +194,129 @@ struct PK11DefaultArrayEntryStr { #define CKA_DIGEST 0x81000000L #define CKA_FLAGS_ONLY 0 /* CKA_CLASS */ +/* + * PK11AttrFlags + * + * A 32-bit bitmask of PK11_ATTR_XXX flags + */ +typedef PRUint32 PK11AttrFlags; + +/* + * PK11_ATTR_XXX + * + * The following PK11_ATTR_XXX bitflags are used to specify + * PKCS #11 object attributes that have Boolean values. Some NSS + * functions have a "PK11AttrFlags attrFlags" parameter whose value + * is the logical OR of these bitflags. NSS use these bitflags on + * private keys or secret keys. Some of these bitflags also apply + * to the public keys associated with the private keys. + * + * Some of these PKCS #11 object attributes have a token-specific + * default value. For such attributes, we need two bitflags to + * specify not only "true" and "false" but also "default". For + * example, PK11_ATTR_PRIVATE and PK11_ATTR_PUBLIC control the + * CKA_PRIVATE attribute. If PK11_ATTR_PRIVATE is set, we add + * { CKA_PRIVATE, &cktrue, sizeof(CK_BBOOL) } + * to the template. If PK11_ATTR_PUBLIC is set, we add + * { CKA_PRIVATE, &ckfalse, sizeof(CK_BBOOL) } + * to the template. If neither flag is set, we don't add any + * CKA_PRIVATE entry to the template. + */ + +/* + * Attributes for PKCS #11 storage objects, which include not only + * keys but also certificates and domain parameters. + */ + +/* + * PK11_ATTR_TOKEN + * + * If this flag is set, the object is a token object. If this + * flag is not set, the object is *by default* a session object. + * This flag specifies the value of the PKCS #11 CKA_TOKEN + * attribute. + */ +#define PK11_ATTR_TOKEN 0x00000001L +/* Reserved 0x00000002L */ + +/* + * PK11_ATTR_PRIVATE + * PK11_ATTR_PUBLIC + * + * These two flags determine whether the object is a private or + * public object. A user may not access a private object until the + * user has authenticated to the token. + * + * These two flags are related and cannot both be set. + * If the PK11_ATTR_PRIVATE flag is set, the object is a private + * object. If the PK11_ATTR_PUBLIC flag is set, the object is a + * public object. If neither flag is set, it is token-specific + * whether the object is private or public. + * + * These two flags specify the value of the PKCS #11 CKA_PRIVATE + * attribute. NSS only uses this attribute on private and secret + * keys, so public keys created by NSS get the token-specific + * default value of the CKA_PRIVATE attribute. + */ +#define PK11_ATTR_PRIVATE 0x00000004L +#define PK11_ATTR_PUBLIC 0x00000008L + +/* + * PK11_ATTR_READONLY + * + * If this flag is set, the object is read-only. If this flag is + * not set, the object is *by default* modifiable. + * + * This flag specifies the value of the PKCS #11 CKA_MODIFIABLE + * attribute. + * + * XXX Should we name this flag PK11_ATTR_UNMODIFIABLE? + */ +/* Reserved 0x00000010L */ +#define PK11_ATTR_READONLY 0x00000020L + +/* Attributes for PKCS #11 key objects. */ + +/* + * PK11_ATTR_SENSITIVE + * PK11_ATTR_INSENSITIVE + * + * These two flags are related and cannot both be set. + * If the PK11_ATTR_SENSITIVE flag is set, the key is sensitive. + * If the PK11_ATTR_INSENSITIVE flag is set, the key is not + * sensitive. If neither flag is set, it is token-specific whether + * the key is sensitive or not. + * + * If a key is sensitive, certain attributes of the key cannot be + * revealed in plaintext outside the token. + * + * This flag specifies the value of the PKCS #11 CKA_SENSITIVE + * attribute. Although the default value of the CKA_SENSITIVE + * attribute for secret keys is CK_FALSE per PKCS #11, some FIPS + * tokens set the default value to CK_TRUE because only CK_TRUE + * is allowed. So in practice the default value of this attribute + * is token-specific, hence the need for two bitflags. + */ +#define PK11_ATTR_SENSITIVE 0x00000040L +#define PK11_ATTR_INSENSITIVE 0x00000080L + +/* + * PK11_ATTR_EXTRACTABLE + * PK11_ATTR_UNEXTRACTABLE + * + * These two flags are related and cannot both be set. + * If the PK11_ATTR_EXTRACTABLE flag is set, the key is extractable + * and can be wrapped. If the PK11_ATTR_UNEXTRACTABLE flag is set, + * the key is not extractable, and certain attributes of the key + * cannot be revealed in plaintext outside the token (just like a + * sensitive key). If neither flag is set, it is token-specific + * whether the key is extractable or not. + * + * These two flags specify the value of the PKCS #11 CKA_EXTRACTABLE + * attribute. + */ +#define PK11_ATTR_EXTRACTABLE 0x00000100L +#define PK11_ATTR_UNEXTRACTABLE 0x00000200L /* Cryptographic module types */ #define SECMOD_EXTERNAL 0 /* external module */