void DeriveKey::operator () (CssmData *param, const KeySpec &spec, CssmKey &derivedKey) { check(CSSM_DeriveKey(handle(), param, spec.usage, spec.attributes, spec.label, &compositeRcc(), &derivedKey)); }
Key DeriveKey::operator () (CssmData *param, const KeySpec &spec) { Key derivedKey; check(CSSM_DeriveKey(handle(), param, spec.usage, spec.attributes, spec.label, &compositeRcc(), derivedKey.makeNewKey(attachment()))); derivedKey->activate(); return derivedKey; }
/* * Derive a symmetric CSSM_KEY from the specified raw key material. */ CSSM_RETURN cdsaDeriveKey( CSSM_CSP_HANDLE cspHandle, const void *rawKey, size_t rawKeyLen, CSSM_ALGORITHMS keyAlg, // e.g., CSSM_ALGID_AES uint32 keySizeInBits, CSSM_KEY_PTR key) { CSSM_RETURN crtn; CSSM_CC_HANDLE ccHand; CSSM_DATA dummyLabel = {8, (uint8 *)"tempKey"}; CSSM_DATA saltData = {8, (uint8 *)"someSalt"}; CSSM_PKCS5_PBKDF2_PARAMS pbeParams; CSSM_DATA pbeData; CSSM_ACCESS_CREDENTIALS creds; memset(key, 0, sizeof(CSSM_KEY)); memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); crtn = CSSM_CSP_CreateDeriveKeyContext(cspHandle, CSSM_ALGID_PKCS5_PBKDF2, keyAlg, keySizeInBits, &creds, NULL, // BaseKey 1000, // iterationCount, 1000 is the minimum &saltData, NULL, // seed &ccHand); if(crtn) { return crtn; } /* this is the caller's raw key bits, typically ASCII (though it * could be anything) */ pbeParams.Passphrase.Data = (uint8 *)rawKey; pbeParams.Passphrase.Length = rawKeyLen; /* The only PRF supported by the CSP is HMACSHA1 */ pbeParams.PseudoRandomFunction = CSSM_PKCS5_PBKDF2_PRF_HMAC_SHA1; pbeData.Data = (uint8 *)&pbeParams; pbeData.Length = sizeof(pbeParams); crtn = CSSM_DeriveKey(ccHand, &pbeData, CSSM_KEYUSE_ANY, CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, &dummyLabel, NULL, // cred and acl key); CSSM_DeleteContext(ccHand); // ignore error here return crtn; }
/* * Perform Diffie-Hellman key exchange. * Given "our" private key (in the form of a CSSM_KEY) and "their" public * key (in the form of a raw blob of bytes), cook up a symmetric key. */ CSSM_RETURN cdsaDhKeyExchange( CSSM_CSP_HANDLE cspHandle, CSSM_KEY_PTR myPrivateKey, // from cdsaDhGenerateKeyPair const void *theirPubKey, uint32 theirPubKeyLen, CSSM_KEY_PTR derivedKey, // RETURNED uint32 deriveKeySizeInBits, CSSM_ALGORITHMS derivedKeyAlg) // e.g., CSSM_ALGID_AES { CSSM_RETURN crtn; CSSM_ACCESS_CREDENTIALS creds; CSSM_CC_HANDLE ccHandle; CSSM_DATA labelData = {8, (uint8 *)"tempKey"}; memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); memset(derivedKey, 0, sizeof(CSSM_KEY)); crtn = CSSM_CSP_CreateDeriveKeyContext(cspHandle, CSSM_ALGID_DH, derivedKeyAlg, deriveKeySizeInBits, &creds, myPrivateKey, // BaseKey 0, // IterationCount 0, // Salt 0, // Seed &ccHandle); if(crtn) { return crtn; } /* public key passed in as CSSM_DATA *Param */ CSSM_DATA theirPubKeyData = { theirPubKeyLen, (uint8 *)theirPubKey }; crtn = CSSM_DeriveKey(ccHandle, &theirPubKeyData, CSSM_KEYUSE_ANY, CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, &labelData, NULL, // cread/acl derivedKey); CSSM_DeleteContext(ccHandle); return crtn; }
/* * Derive symmetric key. * Note in the X CSP, we never return an IV. */ CSSM_RETURN cuCspDeriveKey(CSSM_CSP_HANDLE cspHand, uint32 keyAlg, // CSSM_ALGID_RC5, etc. const char *keyLabel, unsigned keyLabelLen, uint32 keyUsage, // CSSM_KEYUSE_ENCRYPT, etc. uint32 keySizeInBits, CSSM_DATA_PTR password, // in PKCS-5 lingo CSSM_DATA_PTR salt, // ditto uint32 iterationCnt, // ditto CSSM_KEY_PTR key) { CSSM_RETURN crtn; CSSM_CC_HANDLE ccHand; uint32 keyAttr; CSSM_DATA dummyLabel; CSSM_PKCS5_PBKDF2_PARAMS pbeParams; CSSM_DATA pbeData; CSSM_ACCESS_CREDENTIALS creds; memset(key, 0, sizeof(CSSM_KEY)); memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); crtn = CSSM_CSP_CreateDeriveKeyContext(cspHand, CSSM_ALGID_PKCS5_PBKDF2, keyAlg, keySizeInBits, &creds, NULL, // BaseKey iterationCnt, salt, NULL, // seed &ccHand); if(crtn) { cuPrintError("CSSM_CSP_CreateDeriveKeyContext", crtn); return crtn; } keyAttr = CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_SENSITIVE; dummyLabel.Length = keyLabelLen; dummyLabel.Data = (uint8 *)keyLabel; /* passing in password is pretty strange....*/ pbeParams.Passphrase = *password; pbeParams.PseudoRandomFunction = CSSM_PKCS5_PBKDF2_PRF_HMAC_SHA1; pbeData.Data = (uint8 *)&pbeParams; pbeData.Length = sizeof(pbeParams); crtn = CSSM_DeriveKey(ccHand, &pbeData, keyUsage, keyAttr, &dummyLabel, NULL, // cred and acl key); if(crtn) { cuPrintError("CSSM_DeriveKey", crtn); return crtn; } crtn = CSSM_DeleteContext(ccHand); if(crtn) { cuPrintError("CSSM_DeleteContext", crtn); } return crtn; }
CSSM_RETURN p12KeyGen( CSSM_CSP_HANDLE cspHand, CSSM_KEY &key, bool isForEncr, // true: en/decrypt false: MAC CSSM_ALGORITHMS keyAlg, CSSM_ALGORITHMS pbeHashAlg, // actually must be SHA1 for now uint32 keySizeInBits, uint32 iterCount, const CSSM_DATA &salt, /* exactly one of the following two must be valid */ const CSSM_DATA *pwd, // unicode external representation const CSSM_KEY *passKey, CSSM_DATA &iv) // referent is optional { CSSM_RETURN crtn; CSSM_CC_HANDLE ccHand; CSSM_DATA dummyLabel; CSSM_ACCESS_CREDENTIALS creds; memset(&key, 0, sizeof(CSSM_KEY)); memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); /* infer key derivation algorithm */ CSSM_ALGORITHMS deriveAlg = CSSM_ALGID_NONE; if(pbeHashAlg != CSSM_ALGID_SHA1) { return CSSMERR_CSP_INVALID_ALGORITHM; } if(isForEncr) { /* * FIXME - if this key is going to be used to wrap/unwrap a * shrouded key bag, its usage will change accordingly... */ deriveAlg = CSSM_ALGID_PKCS12_PBE_ENCR; } else { deriveAlg = CSSM_ALGID_PKCS12_PBE_MAC; } CSSM_CRYPTO_DATA seed; if(pwd) { seed.Param = *pwd; } else { seed.Param.Data = NULL; seed.Param.Length = 0; } seed.Callback = NULL; seed.CallerCtx = NULL; crtn = CSSM_CSP_CreateDeriveKeyContext(cspHand, deriveAlg, keyAlg, keySizeInBits, &creds, passKey, // BaseKey iterCount, &salt, &seed, // seed &ccHand); if(crtn) { p12LogCssmError("CSSM_CSP_CreateDeriveKeyContext", crtn); return crtn; } dummyLabel.Length = strlen(KEY_LABEL); dummyLabel.Data = (uint8 *)KEY_LABEL; /* KEYUSE_ANY - this is just an ephemeral session key */ crtn = CSSM_DeriveKey(ccHand, &iv, CSSM_KEYUSE_ANY, CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_SENSITIVE, &dummyLabel, NULL, // cred and acl &key); CSSM_DeleteContext(ccHand); if(crtn) { p12LogCssmError("CSSM_DeriveKey", crtn); } return crtn; }
/* * Common code to derive a wrap/unwrap key for OpenSSHv1. * Caller must CSSM_FreeKey when done. */ static CSSM_RETURN openSSHv1DeriveKey( CSSM_CSP_HANDLE cspHand, const SecKeyImportExportParameters *keyParams, // required impExpVerifyPhrase verifyPhrase, // for secure passphrase CSSM_KEY_PTR symKey) // RETURNED { CSSM_KEY *passKey = NULL; CFDataRef cfPhrase = NULL; CSSM_RETURN crtn; OSStatus ortn; CSSM_DATA dummyLabel; uint32 keyAttr; CSSM_CC_HANDLE ccHand = 0; CSSM_ACCESS_CREDENTIALS creds; CSSM_CRYPTO_DATA seed; CSSM_DATA nullParam = {0, NULL}; memset(symKey, 0, sizeof(CSSM_KEY)); /* passphrase or passkey? */ ortn = impExpPassphraseCommon(keyParams, cspHand, SPF_Data, verifyPhrase, (CFTypeRef *)&cfPhrase, &passKey); if(ortn) { return ortn; } /* subsequent errors to errOut: */ memset(&seed, 0, sizeof(seed)); if(cfPhrase != NULL) { /* TBD - caller-supplied empty passphrase means "export in the clear" */ size_t len = CFDataGetLength(cfPhrase); seed.Param.Data = (uint8 *)malloc(len); seed.Param.Length = len; memmove(seed.Param.Data, CFDataGetBytePtr(cfPhrase), len); CFRelease(cfPhrase); } memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); crtn = CSSM_CSP_CreateDeriveKeyContext(cspHand, CSSM_ALGID_OPENSSH1, CSSM_ALGID_OPENSSH1, CC_MD5_DIGEST_LENGTH * 8, &creds, passKey, // BaseKey 0, // iterationCount NULL, // salt &seed, &ccHand); if(crtn) { SecSSHDbg("openSSHv1DeriveKey CSSM_CSP_CreateDeriveKeyContext failure"); goto errOut; } /* not extractable even for the short time this key lives */ keyAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_SENSITIVE; dummyLabel.Data = (uint8 *)"temp unwrap key"; dummyLabel.Length = strlen((char *)dummyLabel.Data); crtn = CSSM_DeriveKey(ccHand, &nullParam, CSSM_KEYUSE_ANY, keyAttr, &dummyLabel, NULL, // cred and acl symKey); if(crtn) { SecSSHDbg("openSSHv1DeriveKey CSSM_DeriveKey failure"); } errOut: if(ccHand != 0) { CSSM_DeleteContext(ccHand); } if(passKey != NULL) { CSSM_FreeKey(cspHand, NULL, passKey, CSSM_FALSE); free(passKey); } if(seed.Param.Data) { memset(seed.Param.Data, 0, seed.Param.Length); free(seed.Param.Data); } return crtn; }