Index: crypto/rsa_private_key_mac.cc |
=================================================================== |
--- crypto/rsa_private_key_mac.cc (revision 0) |
+++ crypto/rsa_private_key_mac.cc (revision 0) |
@@ -0,0 +1,196 @@ |
+// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "crypto/rsa_private_key.h" |
+ |
+#include <list> |
+ |
+#include "base/logging.h" |
+#include "base/memory/scoped_ptr.h" |
+#include "crypto/cssm_init.h" |
+ |
+namespace crypto { |
+ |
+// static |
+RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) { |
+ scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); |
+ |
+ CSSM_CC_HANDLE cc_handle; |
+ CSSM_RETURN crtn; |
+ crtn = CSSM_CSP_CreateKeyGenContext(GetSharedCSPHandle(), CSSM_ALGID_RSA, |
+ num_bits, NULL, NULL, NULL, NULL, NULL, |
+ &cc_handle); |
+ if (crtn) { |
+ NOTREACHED() << "CSSM_CSP_CreateKeyGenContext failed: " << crtn; |
+ return NULL; |
+ } |
+ |
+ 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, |
+ result->public_key(), CSSM_KEYUSE_SIGN, |
+ CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, &label, NULL, |
+ result->key()); |
+ CSSM_DeleteContext(cc_handle); |
+ if (crtn) { |
+ NOTREACHED() << "CSSM_CSP_CreateKeyGenContext failed: " << crtn; |
+ return NULL; |
+ } |
+ |
+ return result.release(); |
+} |
+ |
+// static |
+RSAPrivateKey* RSAPrivateKey::CreateSensitive(uint16 num_bits) { |
+ NOTIMPLEMENTED(); |
+ return NULL; |
+} |
+ |
+// static |
+RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo( |
+ const std::vector<uint8>& input) { |
+ if (input.empty()) |
+ return NULL; |
+ |
+ scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); |
+ |
+ CSSM_KEY key; |
+ memset(&key, 0, sizeof(key)); |
+ key.KeyData.Data = const_cast<uint8*>(&input.front()); |
+ key.KeyData.Length = input.size(); |
+ key.KeyHeader.Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS8; |
+ key.KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION; |
+ key.KeyHeader.BlobType = CSSM_KEYBLOB_RAW; |
+ key.KeyHeader.AlgorithmId = CSSM_ALGID_RSA; |
+ key.KeyHeader.KeyClass = CSSM_KEYCLASS_PRIVATE_KEY; |
+ key.KeyHeader.KeyAttr = CSSM_KEYATTR_EXTRACTABLE; |
+ key.KeyHeader.KeyUsage = CSSM_KEYUSE_ANY; |
+ |
+ CSSM_KEY_SIZE key_size; |
+ CSSM_RETURN crtn; |
+ crtn = CSSM_QueryKeySizeInBits(GetSharedCSPHandle(), NULL, &key, &key_size); |
+ if (crtn) { |
+ NOTREACHED() << "CSSM_QueryKeySizeInBits failed: " << crtn; |
+ return NULL; |
+ } |
+ key.KeyHeader.LogicalKeySizeInBits = key_size.LogicalKeySizeInBits; |
+ |
+ // Perform a NULL unwrap operation on the key so that result's key_ |
+ // instance variable points to a key that can be released via CSSM_FreeKey(). |
+ CSSM_ACCESS_CREDENTIALS creds; |
+ memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); |
+ CSSM_CC_HANDLE cc_handle; |
+ crtn = CSSM_CSP_CreateSymmetricContext(GetSharedCSPHandle(), CSSM_ALGID_NONE, |
+ CSSM_ALGMODE_NONE, &creds, NULL, NULL, CSSM_PADDING_NONE, 0, &cc_handle); |
+ if (crtn) { |
+ NOTREACHED() << "CSSM_CSP_CreateSymmetricContext failed: " << crtn; |
+ return NULL; |
+ } |
+ CSSM_DATA label_data, desc_data = { 0, NULL }; |
+ label_data.Data = |
+ const_cast<uint8*>(reinterpret_cast<const uint8*>("unwrapped")); |
+ label_data.Length = 9; |
+ crtn = CSSM_UnwrapKey(cc_handle, NULL, &key, CSSM_KEYUSE_ANY, |
+ CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, &label_data, |
+ NULL, result->key(), &desc_data); |
+ if (crtn) { |
+ NOTREACHED() << "CSSM_UnwrapKey failed: " << crtn; |
+ 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(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(); |
+} |
+ |
+// static |
+RSAPrivateKey* RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo( |
+ const std::vector<uint8>& input) { |
+ NOTIMPLEMENTED(); |
+ return NULL; |
+} |
+ |
+// static |
+RSAPrivateKey* RSAPrivateKey::FindFromPublicKeyInfo( |
+ const std::vector<uint8>& input) { |
+ NOTIMPLEMENTED(); |
+ return NULL; |
+} |
+ |
+RSAPrivateKey::RSAPrivateKey() { |
+ memset(&key_, 0, sizeof(key_)); |
+ memset(&public_key_, 0, sizeof(public_key_)); |
+ |
+ EnsureCSSMInit(); |
+} |
+ |
+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) { |
+ if (!key_.KeyData.Data || !key_.KeyData.Length) { |
+ return false; |
+ } |
+ output->clear(); |
+ output->insert(output->end(), key_.KeyData.Data, |
+ key_.KeyData.Data + key_.KeyData.Length); |
+ return true; |
+} |
+ |
+bool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) { |
+ PrivateKeyInfoCodec private_key_info(true); |
+ std::vector<uint8> private_key_data; |
+ private_key_data.assign(key_.KeyData.Data, |
+ key_.KeyData.Data + key_.KeyData.Length); |
+ return (private_key_info.Import(private_key_data) && |
+ private_key_info.ExportPublicKeyInfo(output)); |
+} |
+ |
+} // namespace crypto |
Property changes on: crypto\rsa_private_key_mac.cc |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |