diff options
author | dmaclach@chromium.org <dmaclach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-08 14:28:29 +0000 |
---|---|---|
committer | dmaclach@chromium.org <dmaclach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-08 14:28:29 +0000 |
commit | eed0011868749ef759ab95cb906fc0fe8e23cde1 (patch) | |
tree | 88c449642e823cb60826b424c01fa4ceac2d7b7e /base/crypto | |
parent | 13f50ec8d5db4bc3b6dd5f2b062f96cd9f5cc031 (diff) | |
download | chromium_src-eed0011868749ef759ab95cb906fc0fe8e23cde1.zip chromium_src-eed0011868749ef759ab95cb906fc0fe8e23cde1.tar.gz chromium_src-eed0011868749ef759ab95cb906fc0fe8e23cde1.tar.bz2 |
Add ability to create self signed certs to mac.
BUG=67929
TEST=BUILD
Review URL: http://codereview.chromium.org/6312157
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@74115 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/crypto')
-rw-r--r-- | base/crypto/cssm_init.cc | 134 | ||||
-rw-r--r-- | base/crypto/cssm_init.h | 31 | ||||
-rw-r--r-- | base/crypto/rsa_private_key.cc | 32 | ||||
-rw-r--r-- | base/crypto/rsa_private_key.h | 6 | ||||
-rw-r--r-- | base/crypto/rsa_private_key_mac.cc | 51 | ||||
-rw-r--r-- | base/crypto/signature_creator_mac.cc | 10 |
6 files changed, 207 insertions, 57 deletions
diff --git a/base/crypto/cssm_init.cc b/base/crypto/cssm_init.cc index eea9d1b..570dcc3 100644 --- a/base/crypto/cssm_init.cc +++ b/base/crypto/cssm_init.cc @@ -7,6 +7,7 @@ #include <Security/SecBase.h> #include "base/logging.h" +#include "base/mac/scoped_cftyperef.h" #include "base/singleton.h" #include "base/synchronization/lock.h" #include "base/sys_string_conversions.h" @@ -20,6 +21,22 @@ namespace { +void* CSSMMalloc(CSSM_SIZE size, void* alloc_ref) { + return malloc(size); +} + +void CSSMFree(void* mem_ptr, void* alloc_ref) { + free(mem_ptr); +} + +void* CSSMRealloc(void* ptr, CSSM_SIZE size, void* alloc_ref) { + return realloc(ptr, size); +} + +void* CSSMCalloc(uint32 num, CSSM_SIZE size, void* alloc_ref) { + return calloc(num, size); +} + class CSSMInitSingleton { public: static CSSMInitSingleton* GetInstance() { @@ -27,10 +44,15 @@ class CSSMInitSingleton { LeakySingletonTraits<CSSMInitSingleton> >::get(); } - CSSM_CSP_HANDLE csp_handle() const { return csp_handle_; } + CSSM_CSP_HANDLE csp_handle() const { return csp_handle_; } + CSSM_CL_HANDLE cl_handle() const { return cl_handle_; } + CSSM_TP_HANDLE tp_handle() const { return tp_handle_; } private: - CSSMInitSingleton() : inited_(false), loaded_(false), csp_handle_(NULL) { + CSSMInitSingleton() + : inited_(false), csp_loaded_(false), cl_loaded_(false), + tp_loaded_(false), csp_handle_(NULL), cl_handle_(NULL), + tp_handle_(NULL) { static CSSM_VERSION version = {2, 0}; // TODO(wtc): what should our caller GUID be? static const CSSM_GUID test_guid = { @@ -51,13 +73,42 @@ class CSSMInitSingleton { NOTREACHED(); return; } - loaded_ = true; + csp_loaded_ = true; + crtn = CSSM_ModuleLoad( + &gGuidAppleX509CL, CSSM_KEY_HIERARCHY_NONE, NULL, NULL); + if (crtn) { + NOTREACHED(); + return; + } + cl_loaded_ = true; + crtn = CSSM_ModuleLoad( + &gGuidAppleX509TP, CSSM_KEY_HIERARCHY_NONE, NULL, NULL); + if (crtn) { + NOTREACHED(); + return; + } + tp_loaded_ = true; + + const CSSM_API_MEMORY_FUNCS cssmMemoryFunctions = { + CSSMMalloc, + CSSMFree, + CSSMRealloc, + CSSMCalloc, + NULL + }; - crtn = CSSM_ModuleAttach(&gGuidAppleCSP, &version, - &base::kCssmMemoryFunctions, 0, + crtn = CSSM_ModuleAttach(&gGuidAppleCSP, &version, &cssmMemoryFunctions, 0, CSSM_SERVICE_CSP, 0, CSSM_KEY_HIERARCHY_NONE, NULL, 0, NULL, &csp_handle_); DCHECK(crtn == CSSM_OK); + crtn = CSSM_ModuleAttach(&gGuidAppleX509CL, &version, &cssmMemoryFunctions, + 0, CSSM_SERVICE_CL, 0, CSSM_KEY_HIERARCHY_NONE, + NULL, 0, NULL, &cl_handle_); + DCHECK(crtn == CSSM_OK); + crtn = CSSM_ModuleAttach(&gGuidAppleX509TP, &version, &cssmMemoryFunctions, + 0, CSSM_SERVICE_TP, 0, CSSM_KEY_HIERARCHY_NONE, + NULL, 0, NULL, &tp_handle_); + DCHECK(crtn == CSSM_OK); } ~CSSMInitSingleton() { @@ -66,10 +117,26 @@ class CSSMInitSingleton { CSSM_RETURN crtn = CSSM_ModuleDetach(csp_handle_); DCHECK(crtn == CSSM_OK); } - if (loaded_) { + if (cl_handle_) { + CSSM_RETURN crtn = CSSM_ModuleDetach(cl_handle_); + DCHECK(crtn == CSSM_OK); + } + if (tp_handle_) { + CSSM_RETURN crtn = CSSM_ModuleDetach(tp_handle_); + DCHECK(crtn == CSSM_OK); + } + if (csp_loaded_) { crtn = CSSM_ModuleUnload(&gGuidAppleCSP, NULL, NULL); DCHECK(crtn == CSSM_OK); } + if (cl_loaded_) { + crtn = CSSM_ModuleUnload(&gGuidAppleX509CL, NULL, NULL); + DCHECK(crtn == CSSM_OK); + } + if (tp_loaded_) { + crtn = CSSM_ModuleUnload(&gGuidAppleX509TP, NULL, NULL); + DCHECK(crtn == CSSM_OK); + } if (inited_) { crtn = CSSM_Terminate(); DCHECK(crtn == CSSM_OK); @@ -77,8 +144,12 @@ class CSSMInitSingleton { } bool inited_; // True if CSSM_Init has been called successfully. - bool loaded_; // True if CSSM_ModuleLoad has been called successfully. + bool csp_loaded_; // True if gGuidAppleCSP has been loaded + bool cl_loaded_; // True if gGuidAppleX509CL has been loaded. + bool tp_loaded_; // True if gGuidAppleX509TP has been loaded. CSSM_CSP_HANDLE csp_handle_; + CSSM_CL_HANDLE cl_handle_; + CSSM_TP_HANDLE tp_handle_; friend struct DefaultSingletonTraits<CSSMInitSingleton>; }; @@ -117,45 +188,44 @@ CSSM_CSP_HANDLE GetSharedCSPHandle() { return CSSMInitSingleton::GetInstance()->csp_handle(); } -void* CSSMMalloc(CSSM_SIZE size, void *alloc_ref) { - return malloc(size); +CSSM_CL_HANDLE GetSharedCLHandle() { + return CSSMInitSingleton::GetInstance()->cl_handle(); } -void CSSMFree(void* mem_ptr, void* alloc_ref) { - free(mem_ptr); +CSSM_TP_HANDLE GetSharedTPHandle() { + return CSSMInitSingleton::GetInstance()->tp_handle(); } -void* CSSMRealloc(void* ptr, CSSM_SIZE size, void* alloc_ref) { - return realloc(ptr, size); +void* CSSMMalloc(CSSM_SIZE size) { + return ::CSSMMalloc(size, NULL); } -void* CSSMCalloc(uint32 num, CSSM_SIZE size, void* alloc_ref) { - return calloc(num, size); +void CSSMFree(void* ptr) { + ::CSSMFree(ptr, NULL); } -const CSSM_API_MEMORY_FUNCS kCssmMemoryFunctions = { - CSSMMalloc, - CSSMFree, - CSSMRealloc, - CSSMCalloc, - NULL -}; - -void LogCSSMError(const char *fn_name, CSSM_RETURN err) { +void LogCSSMError(const char* fn_name, CSSM_RETURN err) { if (!err) return; - CFStringRef cfstr = SecCopyErrorMessageString(err, NULL); - if (cfstr) { - std::string err_name = SysCFStringRefToUTF8(cfstr); - CFRelease(cfstr); - LOG(ERROR) << fn_name << " returned " << err << " (" << err_name << ")"; - } else { - LOG(ERROR) << fn_name << " returned " << err; - } + base::mac::ScopedCFTypeRef<CFStringRef> cfstr( + SecCopyErrorMessageString(err, NULL)); + LOG(ERROR) << fn_name << " returned " << err + << " (" << SysCFStringRefToUTF8(cfstr) << ")"; } base::Lock& GetMacSecurityServicesLock() { return SecurityServicesSingleton::GetInstance()->lock(); } +ScopedCSSMData::ScopedCSSMData() { + memset(&data_, 0, sizeof(data_)); +} + +ScopedCSSMData::~ScopedCSSMData() { + if (data_.Data) { + CSSMFree(data_.Data); + data_.Data = NULL; + } +} + } // namespace base diff --git a/base/crypto/cssm_init.h b/base/crypto/cssm_init.h index 5644d7e..b51a3b5 100644 --- a/base/crypto/cssm_init.h +++ b/base/crypto/cssm_init.h @@ -8,7 +8,7 @@ #include <Security/cssm.h> -#include "base/scoped_ptr.h" +#include "base/basictypes.h" namespace base { @@ -22,12 +22,22 @@ void EnsureCSSMInit(); // Returns the shared CSP handle used by CSSM functions. CSSM_CSP_HANDLE GetSharedCSPHandle(); +// Returns the shared CL handle used by CSSM functions. +CSSM_CL_HANDLE GetSharedCLHandle(); + +// Returns the shared TP handle used by CSSM functions. +CSSM_TP_HANDLE GetSharedTPHandle(); + // Set of pointers to memory function wrappers that are required for CSSM extern const CSSM_API_MEMORY_FUNCS kCssmMemoryFunctions; // Utility function to log an error message including the error name. void LogCSSMError(const char *function_name, CSSM_RETURN err); +// Utility functions to allocate and release CSSM memory. +void* CSSMMalloc(CSSM_SIZE size); +void CSSMFree(void* ptr); + // The OS X certificate and key management wrappers over CSSM are not // thread-safe. In particular, code that accesses the CSSM database is // problematic. @@ -35,6 +45,25 @@ void LogCSSMError(const char *function_name, CSSM_RETURN err); // http://developer.apple.com/mac/library/documentation/Security/Reference/certifkeytrustservices/Reference/reference.html Lock& GetMacSecurityServicesLock(); +// Wrapper class for CSSM_DATA type. This should only be used when using the +// CL/TP/CSP handles from above, since that's the only time we're guaranteed (or +// supposed to be guaranteed) that our memory management functions will be used. +// Apple's Sec* APIs manage their own memory so it shouldn't be used for those. +// The constructor initializes data_ to zero and the destructor releases the +// data properly. +class ScopedCSSMData { + public: + ScopedCSSMData(); + ~ScopedCSSMData(); + operator CSSM_DATA*() { return &data_; } + CSSM_DATA* operator ->() { return &data_; } + + private: + CSSM_DATA data_; + + DISALLOW_COPY_AND_ASSIGN(ScopedCSSMData); +}; + } // namespace base #endif // BASE_CRYPTO_CSSM_INIT_H_ diff --git a/base/crypto/rsa_private_key.cc b/base/crypto/rsa_private_key.cc index 2ab0c14..024f741 100644 --- a/base/crypto/rsa_private_key.cc +++ b/base/crypto/rsa_private_key.cc @@ -89,19 +89,12 @@ bool PrivateKeyInfoCodec::Export(std::vector<uint8>* output) { bool PrivateKeyInfoCodec::ExportPublicKeyInfo(std::vector<uint8>* output) { // Create a sequence with the modulus (n) and public exponent (e). - std::list<uint8> content; - PrependInteger(&public_exponent_[0], - static_cast<int>(public_exponent_.size()), - &content); - PrependInteger(&modulus_[0], static_cast<int>(modulus_.size()), &content); - PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content); - - // Copy the sequence with n and e into a buffer. std::vector<uint8> bit_string; - for (std::list<uint8>::iterator i = content.begin(); i != content.end(); ++i) - bit_string.push_back(*i); - content.clear(); + if (!ExportPublicKey(&bit_string)) + return false; + // Add the sequence as the contents of a bit string. + std::list<uint8> content; PrependBitString(&bit_string[0], static_cast<int>(bit_string.size()), &content); @@ -120,6 +113,23 @@ bool PrivateKeyInfoCodec::ExportPublicKeyInfo(std::vector<uint8>* output) { return true; } +bool PrivateKeyInfoCodec::ExportPublicKey(std::vector<uint8>* output) { + // Create a sequence with the modulus (n) and public exponent (e). + std::list<uint8> content; + PrependInteger(&public_exponent_[0], + static_cast<int>(public_exponent_.size()), + &content); + PrependInteger(&modulus_[0], static_cast<int>(modulus_.size()), &content); + PrependTypeHeaderAndLength(kSequenceTag, content.size(), &content); + + // Copy everything into the output. + output->reserve(content.size()); + for (std::list<uint8>::iterator i = content.begin(); i != content.end(); ++i) + output->push_back(*i); + + return true; +} + bool PrivateKeyInfoCodec::Import(const std::vector<uint8>& input) { if (input.empty()) { return false; diff --git a/base/crypto/rsa_private_key.h b/base/crypto/rsa_private_key.h index 9b8b4fd..5357adc 100644 --- a/base/crypto/rsa_private_key.h +++ b/base/crypto/rsa_private_key.h @@ -64,6 +64,10 @@ class PrivateKeyInfoCodec { // of the PublicKeyInfo structure to |output|. bool ExportPublicKeyInfo(std::vector<uint8>* output); + // Exports the contents of the integer components to the ASN.1 DER encoding + // of the RSAPublicKey structure to |output|. + bool ExportPublicKey(std::vector<uint8>* output); + // Parses the ASN.1 DER encoding of the PrivateKeyInfo structure in |input| // and populates the integer components with |big_endian_| byte-significance. // IMPORTANT NOTE: This is currently *not* security-approved for importing @@ -215,6 +219,7 @@ class RSAPrivateKey { HCRYPTKEY key() { return key_; } #elif defined(OS_MACOSX) CSSM_KEY_PTR key() { return &key_; } + CSSM_KEY_PTR public_key() { return &public_key_; } #endif // Exports the private key to a PKCS #1 PrivateKey block. @@ -257,6 +262,7 @@ class RSAPrivateKey { ScopedHCRYPTKEY key_; #elif defined(OS_MACOSX) CSSM_KEY key_; + CSSM_KEY public_key_; #endif DISALLOW_COPY_AND_ASSIGN(RSAPrivateKey); diff --git a/base/crypto/rsa_private_key_mac.cc b/base/crypto/rsa_private_key_mac.cc index e46e93e..ede8014 100644 --- a/base/crypto/rsa_private_key_mac.cc +++ b/base/crypto/rsa_private_key_mac.cc @@ -26,14 +26,12 @@ RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) { return NULL; } - CSSM_KEY public_key; - memset(&public_key, 0, sizeof(CSSM_KEY)); CSSM_DATA label = { 9, const_cast<uint8*>(reinterpret_cast<const uint8*>("temp_key")) }; crtn = CSSM_GenerateKeyPair(cc_handle, CSSM_KEYUSE_VERIFY, CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, &label, - &public_key, CSSM_KEYUSE_SIGN, + result->public_key(), CSSM_KEYUSE_SIGN, CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, &label, NULL, result->key()); CSSM_DeleteContext(cc_handle); @@ -42,9 +40,6 @@ RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) { return NULL; } - // Public key is not needed. - CSSM_FreeKey(GetSharedCSPHandle(), NULL, &public_key, CSSM_FALSE); - return result.release(); } @@ -106,6 +101,46 @@ RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo( return NULL; } + // Extract a public key from the private key. + // Apple doesn't accept CSSM_KEYBLOB_RAW_FORMAT_X509 as a valid key + // format when attempting to generate certs, so use PKCS1 instead. + PrivateKeyInfoCodec codec(true); + std::vector<uint8> private_key_data; + private_key_data.assign(key.KeyData.Data, + key.KeyData.Data + key.KeyData.Length); + if (!codec.Import(private_key_data)) { + return NULL; + } + std::vector<uint8> public_key_data; + if (!codec.ExportPublicKey(&public_key_data)) { + return NULL; + } + + CSSM_KEY* public_key = result->public_key(); + size_t size = public_key_data.size(); + public_key->KeyData.Data = reinterpret_cast<uint8*>(CSSMMalloc(size)); + if (!public_key->KeyData.Data) { + NOTREACHED() << "CSSMMalloc failed"; + return NULL; + } + memcpy(public_key->KeyData.Data, &public_key_data.front(), size); + public_key->KeyData.Length = size; + public_key->KeyHeader.Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS1; + public_key->KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION; + public_key->KeyHeader.BlobType = CSSM_KEYBLOB_RAW; + public_key->KeyHeader.AlgorithmId = CSSM_ALGID_RSA; + public_key->KeyHeader.KeyClass = CSSM_KEYCLASS_PUBLIC_KEY; + public_key->KeyHeader.KeyAttr = CSSM_KEYATTR_EXTRACTABLE; + public_key->KeyHeader.KeyUsage = CSSM_KEYUSE_ANY; + + crtn = CSSM_QueryKeySizeInBits( + base::GetSharedCSPHandle(), NULL, public_key, &key_size); + if (crtn) { + DLOG(ERROR) << "CSSM_QueryKeySizeInBits failed " << crtn; + return NULL; + } + public_key->KeyHeader.LogicalKeySizeInBits = key_size.LogicalKeySizeInBits; + return result.release(); } @@ -125,6 +160,7 @@ RSAPrivateKey* RSAPrivateKey::FindFromPublicKeyInfo( RSAPrivateKey::RSAPrivateKey() { memset(&key_, 0, sizeof(key_)); + memset(&public_key_, 0, sizeof(public_key_)); EnsureCSSMInit(); } @@ -133,6 +169,9 @@ RSAPrivateKey::~RSAPrivateKey() { if (key_.KeyData.Data) { CSSM_FreeKey(GetSharedCSPHandle(), NULL, &key_, CSSM_FALSE); } + if (public_key_.KeyData.Data) { + CSSM_FreeKey(GetSharedCSPHandle(), NULL, &public_key_, CSSM_FALSE); + } } bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) { diff --git a/base/crypto/signature_creator_mac.cc b/base/crypto/signature_creator_mac.cc index d10d54c..1001c64 100644 --- a/base/crypto/signature_creator_mac.cc +++ b/base/crypto/signature_creator_mac.cc @@ -59,19 +59,15 @@ bool SignatureCreator::Update(const uint8* data_part, int data_part_len) { } bool SignatureCreator::Final(std::vector<uint8>* signature) { - CSSM_DATA sig; - memset(&sig, 0, sizeof(CSSM_DATA)); // Allow CSSM allocate memory; - CSSM_RETURN crtn = CSSM_SignDataFinal(sig_handle_, &sig); + ScopedCSSMData sig; + CSSM_RETURN crtn = CSSM_SignDataFinal(sig_handle_, sig); if (crtn) { NOTREACHED(); return false; } - signature->assign(sig.Data, sig.Data + sig.Length); - kCssmMemoryFunctions.free_func(sig.Data, NULL); // Release data alloc'd - // by CSSM - + signature->assign(sig->Data, sig->Data + sig->Length); return true; } |