fix for #92940, PKCS#12 broken in FIPS mode. Force keygen to occur on token, added new PKCS#11 mechanisms to handle PKCS#12 integrity key generation.

This commit is contained in:
mcgreer%netscape.com 2001-08-03 18:50:54 +00:00
Родитель bec1d3cddc
Коммит 9d98643622
8 изменённых файлов: 156 добавлений и 42 удалений

Просмотреть файл

@ -455,6 +455,17 @@ void PK11_SetFortezzaHack(PK11SymKey *symKey) ;
/**********************************************************************
* PBE functions
**********************************************************************/
/* This function creates PBE parameters from the given inputs. The result
* can be used to create a password integrity key for PKCS#12, by sending
* the return value to PK11_KeyGen along with the appropriate mechanism.
*/
SECItem *
PK11_CreatePBEParams(SECItem *salt, SECItem *pwd, unsigned int iterations);
/* free params created above (can be called after keygen is done */
void PK11_DestroyPBEParams(SECItem *params);
SECAlgorithmID *
PK11_CreatePBEAlgorithmID(SECOidTag algorithm, int iteration, SECItem *salt);
PK11SymKey *

Просмотреть файл

@ -1207,7 +1207,7 @@ PK11_TokenKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param,
int keySize, SECItem *keyid, PRBool isToken, void *wincx)
{
PK11SymKey *symKey;
CK_ATTRIBUTE genTemplate[4];
CK_ATTRIBUTE genTemplate[5];
CK_ATTRIBUTE *attrs = genTemplate;
int count = sizeof(genTemplate)/sizeof(genTemplate[0]);
CK_SESSION_HANDLE session;
@ -1243,6 +1243,8 @@ PK11_TokenKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param,
PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(cktrue)); attrs++;
}
PK11_SETATTRS(attrs, CKA_SIGN, &cktrue, sizeof(cktrue)); attrs++;
count = attrs - genTemplate;
PR_ASSERT(count <= sizeof(genTemplate)/sizeof(CK_ATTRIBUTE));
@ -4053,6 +4055,49 @@ PK11_DigestFinal(PK11Context *context,unsigned char *data,
*
****************************************************************************/
static void
pk11_destroy_ck_pbe_params(CK_PBE_PARAMS *pbe_params)
{
if (pbe_params) {
if (pbe_params->pPassword)
PORT_ZFree(pbe_params->pPassword, PR_FALSE);
if (pbe_params->pSalt)
PORT_ZFree(pbe_params->pSalt, PR_FALSE);
PORT_ZFree(pbe_params, PR_TRUE);
}
}
SECItem *
PK11_CreatePBEParams(SECItem *salt, SECItem *pwd, unsigned int iterations)
{
CK_PBE_PARAMS *pbe_params = NULL;
SECItem *paramRV = NULL;
pbe_params = (CK_PBE_PARAMS *)PORT_ZAlloc(sizeof(CK_PBE_PARAMS));
pbe_params->pPassword = (CK_CHAR_PTR)PORT_ZAlloc(pwd->len);
if (pbe_params->pPassword != NULL) {
PORT_Memcpy(pbe_params->pPassword, pwd->data, pwd->len);
pbe_params->ulPasswordLen = pwd->len;
} else goto loser;
pbe_params->pSalt = (CK_CHAR_PTR)PORT_ZAlloc(salt->len);
if (pbe_params->pSalt != NULL) {
PORT_Memcpy(pbe_params->pSalt, salt->data, salt->len);
pbe_params->ulSaltLen = salt->len;
} else goto loser;
pbe_params->ulIteration = (CK_ULONG)iterations;
paramRV = SECITEM_AllocItem(NULL, NULL, sizeof(CK_PBE_PARAMS));
paramRV->data = (unsigned char *)pbe_params;
return paramRV;
loser:
pk11_destroy_ck_pbe_params(pbe_params);
return NULL;
}
void
PK11_DestroyPBEParams(SECItem *params)
{
pk11_destroy_ck_pbe_params((CK_PBE_PARAMS *)params->data);
}
SECAlgorithmID *
PK11_CreatePBEAlgorithmID(SECOidTag algorithm, int iteration, SECItem *salt)
{

Просмотреть файл

@ -2829,6 +2829,9 @@ PK11_GetKeyGen(CK_MECHANISM_TYPE type)
return CKM_GENERIC_SECRET_KEY_GEN;
case CKM_PBE_MD2_DES_CBC:
case CKM_PBE_MD5_DES_CBC:
case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN:
case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN:
case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN:
case CKM_NETSCAPE_PBE_SHA1_DES_CBC:
case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC:
case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC:

Просмотреть файл

@ -1152,14 +1152,16 @@ static SECStatus
sec_pkcs12_decoder_verify_mac(SEC_PKCS12DecoderContext *p12dcx)
{
SECStatus rv = SECFailure;
PBEBitGenContext *pbeCtxt = NULL;
SECItem *hmacKey = NULL, hmacRes;
SECItem hmacRes;
unsigned char buf[IN_BUF_LEN];
unsigned int bufLen;
int iteration;
PK11Context *pk11cx;
SECOidTag algtag;
SECItem ignore = {0};
PK11SymKey *symKey;
SECItem *params;
SECOidTag algtag;
CK_MECHANISM_TYPE integrityMech;
if(!p12dcx || p12dcx->error) {
return SECFailure;
@ -1171,28 +1173,28 @@ sec_pkcs12_decoder_verify_mac(SEC_PKCS12DecoderContext *p12dcx)
} else {
iteration = 1;
}
pbeCtxt = PBE_CreateContext(SECOID_GetAlgorithmTag(
&p12dcx->macData.safeMac.digestAlgorithm),
pbeBitGenIntegrityKey, p12dcx->pwitem,
&p12dcx->macData.macSalt, 160, iteration);
if(!pbeCtxt) {
return SECFailure;
}
hmacKey = PBE_GenerateBits(pbeCtxt);
PBE_DestroyContext(pbeCtxt);
pbeCtxt = NULL;
if(!hmacKey) {
return SECFailure;
params = PK11_CreatePBEParams(&p12dcx->macData.macSalt, p12dcx->pwitem,
iteration);
algtag = SECOID_GetAlgorithmTag(&p12dcx->macData.safeMac.digestAlgorithm);
switch (algtag) {
case SEC_OID_SHA1:
integrityMech = CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN; break;
case SEC_OID_MD5:
integrityMech = CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN; break;
case SEC_OID_MD2:
integrityMech = CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN; break;
default:
goto loser;
}
symKey = PK11_KeyGen(NULL, integrityMech, params, 20, NULL);
PK11_DestroyPBEParams(params);
if (!symKey) goto loser;
/* init hmac */
algtag = SECOID_GetAlgorithmTag(&p12dcx->macData.safeMac.digestAlgorithm);
pk11cx = PK11_CreateContextByRawKey(NULL,
sec_pkcs12_algtag_to_mech(algtag),
PK11_OriginDerive, CKA_SIGN,
hmacKey, &ignore, NULL);
SECITEM_ZfreeItem(hmacKey, PR_TRUE);
hmacKey = NULL;
pk11cx = PK11_CreateContextBySymKey(sec_pkcs12_algtag_to_mech(algtag),
CKA_SIGN, symKey, &ignore);
if(!pk11cx) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
return SECFailure;
@ -1247,10 +1249,6 @@ loser:
PK11_DestroyContext(pk11cx, PR_TRUE);
}
if(hmacKey) {
SECITEM_ZfreeItem(hmacKey, PR_TRUE);
}
return rv;
}

Просмотреть файл

@ -1660,9 +1660,11 @@ sec_pkcs12_encoder_start_context(SEC_PKCS12ExportContext *p12exp)
/* init password pased integrity mode */
if(p12exp->integrityEnabled) {
SECItem pwd = {siBuffer,NULL, 0}, *key;
SECItem pwd = {siBuffer,NULL, 0};
SECItem *salt = sec_pkcs12_generate_salt();
PBEBitGenContext *pbeCtxt = NULL;
PK11SymKey *symKey;
SECItem *params;
CK_MECHANISM_TYPE integrityMech;
/* zero out macData and set values */
PORT_Memset(&p12enc->mac, 0, sizeof(sec_PKCS12MacData));
@ -1676,7 +1678,6 @@ sec_pkcs12_encoder_start_context(SEC_PKCS12ExportContext *p12exp)
PORT_SetError(SEC_ERROR_NO_MEMORY);
goto loser;
}
SECITEM_ZfreeItem(salt, PR_TRUE);
/* generate HMAC key */
if(!sec_pkcs12_convert_item_to_unicode(NULL, &pwd,
@ -1684,25 +1685,32 @@ sec_pkcs12_encoder_start_context(SEC_PKCS12ExportContext *p12exp)
PR_TRUE, PR_TRUE)) {
goto loser;
}
pbeCtxt = PBE_CreateContext(p12exp->integrityInfo.pwdInfo.algorithm,
pbeBitGenIntegrityKey, &pwd,
&(p12enc->mac.macSalt), 160, 1);
params = PK11_CreatePBEParams(salt, &pwd, 1);
SECITEM_ZfreeItem(salt, PR_TRUE);
SECITEM_ZfreeItem(&pwd, PR_FALSE);
if(!pbeCtxt) {
switch (p12exp->integrityInfo.pwdInfo.algorithm) {
case SEC_OID_SHA1:
integrityMech = CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN; break;
case SEC_OID_MD5:
integrityMech = CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN; break;
case SEC_OID_MD2:
integrityMech = CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN; break;
default:
goto loser;
}
key = PBE_GenerateBits(pbeCtxt);
PBE_DestroyContext(pbeCtxt);
if(!key) {
symKey = PK11_KeyGen(NULL, integrityMech, params, 20, NULL);
PK11_DestroyPBEParams(params);
if(!symKey) {
goto loser;
}
/* initialize hmac */
p12enc->hmacCx = PK11_CreateContextByRawKey(NULL,
p12enc->hmacCx = PK11_CreateContextBySymKey(
sec_pkcs12_algtag_to_mech(p12exp->integrityInfo.pwdInfo.algorithm),
PK11_OriginDerive, CKA_SIGN,
key, &ignore, NULL);
SECITEM_ZfreeItem(key, PR_TRUE);
CKA_SIGN, symKey, &ignore);
if(!p12enc->hmacCx) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
goto loser;

Просмотреть файл

@ -406,6 +406,9 @@ static struct mechanismList mechanisms[] = {
{CKM_PBE_SHA1_RC2_128_CBC, {128,128, CKF_GENERATE}, PR_TRUE},
{CKM_PBE_SHA1_RC4_40, {40,40, CKF_GENERATE}, PR_TRUE},
{CKM_PBE_SHA1_RC4_128, {128,128, CKF_GENERATE}, PR_TRUE},
{CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN, {1,32, CKF_GENERATE}, PR_TRUE},
{CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN, {1,32, CKF_GENERATE}, PR_TRUE},
{CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN, {1,32, CKF_GENERATE}, PR_TRUE},
};
static CK_ULONG mechanismCount = sizeof(mechanisms)/sizeof(mechanisms[0]);
/* load up our token database */

Просмотреть файл

@ -2832,6 +2832,40 @@ CK_RV NSC_GenerateRandom(CK_SESSION_HANDLE hSession,
**************************** Key Functions: ************************
*/
CK_RV
pk11_pbe_hmac_key_gen(CK_MECHANISM_PTR pMechanism, char *buf,
unsigned long *len, PRBool faultyPBE3DES)
{
PBEBitGenContext *pbeCx;
SECItem pwd, salt, *key;
SECOidTag hashAlg;
unsigned long keylenbits;
CK_PBE_PARAMS *pbe_params = NULL;
pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
pwd.data = (unsigned char *)pbe_params->pPassword;
pwd.len = (unsigned int)pbe_params->ulPasswordLen;
salt.data = (unsigned char *)pbe_params->pSalt;
salt.len = (unsigned int)pbe_params->ulSaltLen;
switch (pMechanism->mechanism) {
case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN:
hashAlg = SEC_OID_SHA1; keylenbits = 160; break;
case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN:
hashAlg = SEC_OID_MD5; keylenbits = 128; break;
case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN:
hashAlg = SEC_OID_MD2; keylenbits = 128; break;
default:
return CKR_MECHANISM_INVALID;
}
pbeCx = PBE_CreateContext(hashAlg, pbeBitGenIntegrityKey, &pwd,
&salt, keylenbits, pbe_params->ulIteration);
key = PBE_GenerateBits(pbeCx);
PORT_Memcpy(buf, key->data, key->len);
*len = key->len;
PBE_DestroyContext(pbeCx);
SECITEM_ZfreeItem(key, PR_TRUE);
return CKR_OK;
}
/*
* generate a password based encryption key. This code uses
* PKCS5 to do the work. Note that it calls PBE_PK11ParamToAlgid, which is
@ -3041,7 +3075,7 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession,
int i;
PK11Slot *slot = pk11_SlotFromSessionHandle(hSession);
char buf[MAX_KEY_LEN];
enum {pk11_pbe, pk11_ssl, pk11_bulk} key_gen_type;
enum {pk11_pbe, pk11_pbe_hmac, pk11_ssl, pk11_bulk} key_gen_type;
SECOidTag algtag = SEC_OID_UNKNOWN;
SSL3RSAPreMasterSecret *rsa_pms;
CK_VERSION *version;
@ -3106,6 +3140,11 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession,
break;
case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC:
faultyPBE3DES = PR_TRUE;
case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN:
case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN:
case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN:
key_gen_type = pk11_pbe_hmac;
break;
case CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC:
case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC:
case CKM_NETSCAPE_PBE_SHA1_DES_CBC:
@ -3142,6 +3181,10 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession,
* now to the actual key gen.
*/
switch (key_gen_type) {
case pk11_pbe_hmac:
crv = pk11_pbe_hmac_key_gen(pMechanism, buf, &key_length,
faultyPBE3DES);
break;
case pk11_pbe:
crv = pk11_pbe_key_gen(algtag, pMechanism, buf, &key_length,
faultyPBE3DES);

Просмотреть файл

@ -1112,6 +1112,9 @@ typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR;
#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4 0x80000006L
#define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4 0x80000007L
#define CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC 0x80000008L
#define CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN 0x80000009L
#define CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN 0x8000000aL
#define CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN 0x8000000bL
#define CKM_TLS_MASTER_KEY_DERIVE 0x80000371L
#define CKM_TLS_KEY_AND_MAC_DERIVE 0x80000372L
#define CKM_TLS_PRF_GENERAL 0x80000373L