Chromium Code Reviews| Index: base/crypto/symmetric_key_mac.cc |
| diff --git a/base/crypto/symmetric_key_mac.cc b/base/crypto/symmetric_key_mac.cc |
| index 8290e71606abd1fd508819f64b101f774ecc55c8..89277c6db078adf2e6fd43bf331ae30b1f68204e 100644 |
| --- a/base/crypto/symmetric_key_mac.cc |
| +++ b/base/crypto/symmetric_key_mac.cc |
| @@ -4,13 +4,75 @@ |
| #include "base/crypto/symmetric_key.h" |
| -namespace base { |
| +#include <CommonCrypto/CommonCryptor.h> |
| +#include <CoreFoundation/CFString.h> |
| +#include <Security/cssm.h> |
| + |
| +#include "base/crypto/cssm_init.h" |
| +#include "base/logging.h" |
| +#include "base/rand_util.h" |
| + |
| +namespace { |
| + |
| +CSSM_KEY_TYPE CheckKeyParams(base::SymmetricKey::Algorithm algorithm, |
| + size_t key_size_in_bits) { |
| + if (algorithm == base::SymmetricKey::AES) { |
| + CHECK(key_size_in_bits == 128 || |
| + key_size_in_bits == 192 || |
| + key_size_in_bits == 256) |
| + << "Invalid key size " << key_size_in_bits << " bits"; |
| + return CSSM_ALGID_AES; |
| + } else { |
| + CHECK(algorithm == base::SymmetricKey::HMAC_SHA1); |
| + CHECK(key_size_in_bits >= 80 && (key_size_in_bits % 8) == 0) |
| + << "Invalid key size " << key_size_in_bits << " bits"; |
| + return CSSM_ALGID_SHA1HMAC_LEGACY; |
|
wtc
2010/03/26 21:14:30
Just curious: why does this ALGID say "LEGACY"?
Jens Alfke
2010/03/29 18:34:17
I don't know -- the header comment says "HMAC/SHA1
|
| + } |
| +} |
| + |
| +void* CreateRandomBytes(size_t size) { |
|
wtc
2010/03/26 21:14:30
It seems better to take a result buffer as an inpu
Jens Alfke
2010/03/29 18:34:17
It would be possible, but not any more efficient,
|
| + CSSM_RETURN err; |
| + CSSM_CC_HANDLE ctx; |
| + err = CSSM_CSP_CreateRandomGenContext(base::GetSharedCSPHandle(), |
| + CSSM_ALGID_APPLE_YARROW, |
| + NULL, |
| + size, &ctx); |
| + if (err) { |
| + base::LogCSSMError("CSSM_CSP_CreateRandomGenContext", err); |
| + return NULL; |
| + } |
| + CSSM_DATA random_data = {}; |
| + err = CSSM_GenerateRandom(ctx, &random_data); |
| + if (err) { |
| + base::LogCSSMError("CSSM_GenerateRandom", err); |
| + random_data.Data = NULL; |
| + } |
| + CSSM_DeleteContext(ctx); |
| + return random_data.Data; // Caller responsible for freeing this |
|
wtc
2010/03/26 21:14:30
Nit: could you move this comment to the beginning
|
| +} |
| + |
| +inline CSSM_DATA StringToData(const std::string& str) { |
| + CSSM_DATA data = { |
| + str.size(), |
| + reinterpret_cast<uint8_t*>(const_cast<char*>(str.data())) |
| + }; |
| + return data; |
| +} |
| -// TODO(albertb): Implement on Mac. |
| +} // namespace |
| + |
| +namespace base { |
| // static |
| -SymmetricKey* SymmetricKey::GenerateRandomKey(Algorithm algorithm, size_t key_size) { |
| - return NULL; |
| +SymmetricKey* SymmetricKey::GenerateRandomKey(Algorithm algorithm, |
| + size_t key_size_in_bits) { |
| + CheckKeyParams(algorithm, key_size_in_bits); |
| + void* random_bytes = CreateRandomBytes((key_size_in_bits + 7) / 8); |
| + if (!random_bytes) |
| + return NULL; |
| + SymmetricKey *key = new SymmetricKey(random_bytes, key_size_in_bits); |
| + free(random_bytes); |
| + return key; |
| } |
| // static |
| @@ -18,12 +80,66 @@ SymmetricKey* SymmetricKey::DeriveKeyFromPassword(Algorithm algorithm, |
| const std::string& password, |
| const std::string& salt, |
| size_t iterations, |
| - size_t key_size) { |
| - return NULL; |
| + size_t key_size_in_bits) { |
| + // Derived (haha) from cdsaDeriveKey() in Apple's CryptoSample. |
| + CSSM_KEY_TYPE key_type = CheckKeyParams(algorithm, key_size_in_bits); |
| + SymmetricKey* derived_key = NULL; |
| + CSSM_KEY cssm_key = {}; |
| + |
| + CSSM_CC_HANDLE ctx = 0; |
| + CSSM_ACCESS_CREDENTIALS credentials = {}; |
| + CSSM_RETURN err; |
| + CSSM_DATA salt_data = StringToData(salt); |
| + err = CSSM_CSP_CreateDeriveKeyContext(GetSharedCSPHandle(), |
| + CSSM_ALGID_PKCS5_PBKDF2, |
| + key_type, key_size_in_bits, |
| + &credentials, |
| + NULL, |
| + iterations, |
| + &salt_data, |
| + NULL, |
| + &ctx); |
| + if (err) { |
| + LogCSSMError("CSSM_CSP_CreateDeriveKeyContext", err); |
| + return NULL; |
| + } |
| + |
| + CSSM_PKCS5_PBKDF2_PARAMS params = {}; |
| + params.Passphrase = StringToData(password); |
| + params.PseudoRandomFunction = CSSM_PKCS5_PBKDF2_PRF_HMAC_SHA1; |
| + CSSM_DATA param_data = {sizeof(params), reinterpret_cast<uint8_t*>(¶ms)}; |
| + err = CSSM_DeriveKey(ctx, |
| + ¶m_data, |
| + CSSM_KEYUSE_ANY, |
| + CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, |
| + NULL, |
| + NULL, |
| + &cssm_key); |
| + if (err) { |
| + LogCSSMError("CSSM_DeriveKey", err); |
| + goto exit; |
| + } |
| + |
| + DCHECK_EQ(cssm_key.KeyData.Length, key_size_in_bits / 8); |
| + derived_key = new SymmetricKey(cssm_key.KeyData.Data, key_size_in_bits); |
| + |
| +exit: |
| + CSSM_DeleteContext(ctx); |
| + CSSM_FreeKey(GetSharedCSPHandle(), &credentials, &cssm_key, false); |
| + return derived_key; |
| } |
| +SymmetricKey::SymmetricKey(const void *key_data, size_t key_size_in_bits) |
| + : key_(reinterpret_cast<const char*>(key_data), |
| + key_size_in_bits / 8) {} |
| + |
| bool SymmetricKey::GetRawKey(std::string* raw_key) { |
| - return false; |
| + *raw_key = key_; |
| + return true; |
| +} |
| + |
| +CSSM_DATA SymmetricKey::cssm_data() const { |
| + return StringToData(key_); |
| } |
| } // namespace base |