summaryrefslogtreecommitdiffstats
path: root/base/crypto
diff options
context:
space:
mode:
authordmaclach@chromium.org <dmaclach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-08 14:28:29 +0000
committerdmaclach@chromium.org <dmaclach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-02-08 14:28:29 +0000
commiteed0011868749ef759ab95cb906fc0fe8e23cde1 (patch)
tree88c449642e823cb60826b424c01fa4ceac2d7b7e /base/crypto
parent13f50ec8d5db4bc3b6dd5f2b062f96cd9f5cc031 (diff)
downloadchromium_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.cc134
-rw-r--r--base/crypto/cssm_init.h31
-rw-r--r--base/crypto/rsa_private_key.cc32
-rw-r--r--base/crypto/rsa_private_key.h6
-rw-r--r--base/crypto/rsa_private_key_mac.cc51
-rw-r--r--base/crypto/signature_creator_mac.cc10
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;
}