| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/crypto/rsa_private_key.h" | 5 #include "base/crypto/rsa_private_key.h" |
| 6 | 6 |
| 7 #include <list> | 7 #include <list> |
| 8 | 8 |
| 9 #include "base/crypto/cssm_init.h" | 9 #include "base/crypto/cssm_init.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/scoped_ptr.h" | 11 #include "base/scoped_ptr.h" |
| 12 | 12 |
| 13 namespace base { | 13 namespace base { |
| 14 | 14 |
| 15 // static | 15 // static |
| 16 RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) { | 16 RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) { |
| 17 scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); | 17 scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); |
| 18 | 18 |
| 19 CSSM_CC_HANDLE cc_handle; | 19 CSSM_CC_HANDLE cc_handle; |
| 20 CSSM_RETURN crtn; | 20 CSSM_RETURN crtn; |
| 21 crtn = CSSM_CSP_CreateKeyGenContext(result->csp_handle(), CSSM_ALGID_RSA, | 21 crtn = CSSM_CSP_CreateKeyGenContext(GetSharedCSPHandle(), CSSM_ALGID_RSA, |
| 22 num_bits, NULL, NULL, NULL, NULL, NULL, | 22 num_bits, NULL, NULL, NULL, NULL, NULL, |
| 23 &cc_handle); | 23 &cc_handle); |
| 24 if (crtn) { | 24 if (crtn) { |
| 25 NOTREACHED() << "CSSM_CSP_CreateKeyGenContext failed: " << crtn; | 25 NOTREACHED() << "CSSM_CSP_CreateKeyGenContext failed: " << crtn; |
| 26 return NULL; | 26 return NULL; |
| 27 } | 27 } |
| 28 | 28 |
| 29 CSSM_KEY public_key; | 29 CSSM_KEY public_key; |
| 30 memset(&public_key, 0, sizeof(CSSM_KEY)); | 30 memset(&public_key, 0, sizeof(CSSM_KEY)); |
| 31 CSSM_DATA label = { 9, | 31 CSSM_DATA label = { 9, |
| 32 const_cast<uint8*>(reinterpret_cast<const uint8*>("temp_key")) }; | 32 const_cast<uint8*>(reinterpret_cast<const uint8*>("temp_key")) }; |
| 33 crtn = CSSM_GenerateKeyPair(cc_handle, | 33 crtn = CSSM_GenerateKeyPair(cc_handle, |
| 34 CSSM_KEYUSE_VERIFY, | 34 CSSM_KEYUSE_VERIFY, |
| 35 CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, &label, | 35 CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, &label, |
| 36 &public_key, CSSM_KEYUSE_SIGN, | 36 &public_key, CSSM_KEYUSE_SIGN, |
| 37 CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, &label, NULL, | 37 CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, &label, NULL, |
| 38 result->key()); | 38 result->key()); |
| 39 CSSM_DeleteContext(cc_handle); | 39 CSSM_DeleteContext(cc_handle); |
| 40 if (crtn) { | 40 if (crtn) { |
| 41 NOTREACHED() << "CSSM_CSP_CreateKeyGenContext failed: " << crtn; | 41 NOTREACHED() << "CSSM_CSP_CreateKeyGenContext failed: " << crtn; |
| 42 return NULL; | 42 return NULL; |
| 43 } | 43 } |
| 44 | 44 |
| 45 // Public key is not needed. | 45 // Public key is not needed. |
| 46 CSSM_FreeKey(result->csp_handle(), NULL, &public_key, CSSM_FALSE); | 46 CSSM_FreeKey(GetSharedCSPHandle(), NULL, &public_key, CSSM_FALSE); |
| 47 | 47 |
| 48 return result.release(); | 48 return result.release(); |
| 49 } | 49 } |
| 50 | 50 |
| 51 // static | 51 // static |
| 52 RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo( | 52 RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo( |
| 53 const std::vector<uint8>& input) { | 53 const std::vector<uint8>& input) { |
| 54 if (input.empty()) | 54 if (input.empty()) |
| 55 return NULL; | 55 return NULL; |
| 56 | 56 |
| 57 scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); | 57 scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); |
| 58 | 58 |
| 59 CSSM_KEY key; | 59 CSSM_KEY key; |
| 60 memset(&key, 0, sizeof(key)); | 60 memset(&key, 0, sizeof(key)); |
| 61 key.KeyData.Data = const_cast<uint8*>(&input.front()); | 61 key.KeyData.Data = const_cast<uint8*>(&input.front()); |
| 62 key.KeyData.Length = input.size(); | 62 key.KeyData.Length = input.size(); |
| 63 key.KeyHeader.Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS8; | 63 key.KeyHeader.Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS8; |
| 64 key.KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION; | 64 key.KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION; |
| 65 key.KeyHeader.BlobType = CSSM_KEYBLOB_RAW; | 65 key.KeyHeader.BlobType = CSSM_KEYBLOB_RAW; |
| 66 key.KeyHeader.AlgorithmId = CSSM_ALGID_RSA; | 66 key.KeyHeader.AlgorithmId = CSSM_ALGID_RSA; |
| 67 key.KeyHeader.KeyClass = CSSM_KEYCLASS_PRIVATE_KEY; | 67 key.KeyHeader.KeyClass = CSSM_KEYCLASS_PRIVATE_KEY; |
| 68 key.KeyHeader.KeyAttr = CSSM_KEYATTR_EXTRACTABLE; | 68 key.KeyHeader.KeyAttr = CSSM_KEYATTR_EXTRACTABLE; |
| 69 key.KeyHeader.KeyUsage = CSSM_KEYUSE_ANY; | 69 key.KeyHeader.KeyUsage = CSSM_KEYUSE_ANY; |
| 70 | 70 |
| 71 CSSM_KEY_SIZE key_size; | 71 CSSM_KEY_SIZE key_size; |
| 72 CSSM_RETURN crtn; | 72 CSSM_RETURN crtn; |
| 73 crtn = CSSM_QueryKeySizeInBits(result->csp_handle(), NULL, &key, &key_size); | 73 crtn = CSSM_QueryKeySizeInBits(GetSharedCSPHandle(), NULL, &key, &key_size); |
| 74 if (crtn) { | 74 if (crtn) { |
| 75 NOTREACHED() << "CSSM_QueryKeySizeInBits failed: " << crtn; | 75 NOTREACHED() << "CSSM_QueryKeySizeInBits failed: " << crtn; |
| 76 return NULL; | 76 return NULL; |
| 77 } | 77 } |
| 78 key.KeyHeader.LogicalKeySizeInBits = key_size.LogicalKeySizeInBits; | 78 key.KeyHeader.LogicalKeySizeInBits = key_size.LogicalKeySizeInBits; |
| 79 | 79 |
| 80 // Perform a NULL unwrap operation on the key so that result's key_ | 80 // Perform a NULL unwrap operation on the key so that result's key_ |
| 81 // instance variable points to a key that can be released via CSSM_FreeKey(). | 81 // instance variable points to a key that can be released via CSSM_FreeKey(). |
| 82 CSSM_ACCESS_CREDENTIALS creds; | 82 CSSM_ACCESS_CREDENTIALS creds; |
| 83 memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); | 83 memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); |
| 84 CSSM_CC_HANDLE cc_handle; | 84 CSSM_CC_HANDLE cc_handle; |
| 85 crtn = CSSM_CSP_CreateSymmetricContext(result->csp_handle(), CSSM_ALGID_NONE, | 85 crtn = CSSM_CSP_CreateSymmetricContext(GetSharedCSPHandle(), CSSM_ALGID_NONE, |
| 86 CSSM_ALGMODE_NONE, &creds, NULL, NULL, CSSM_PADDING_NONE, 0, &cc_handle); | 86 CSSM_ALGMODE_NONE, &creds, NULL, NULL, CSSM_PADDING_NONE, 0, &cc_handle); |
| 87 if (crtn) { | 87 if (crtn) { |
| 88 NOTREACHED() << "CSSM_CSP_CreateSymmetricContext failed: " << crtn; | 88 NOTREACHED() << "CSSM_CSP_CreateSymmetricContext failed: " << crtn; |
| 89 return NULL; | 89 return NULL; |
| 90 } | 90 } |
| 91 CSSM_DATA label_data, desc_data = { 0, NULL }; | 91 CSSM_DATA label_data, desc_data = { 0, NULL }; |
| 92 label_data.Data = | 92 label_data.Data = |
| 93 const_cast<uint8*>(reinterpret_cast<const uint8*>("unwrapped")); | 93 const_cast<uint8*>(reinterpret_cast<const uint8*>("unwrapped")); |
| 94 label_data.Length = 9; | 94 label_data.Length = 9; |
| 95 crtn = CSSM_UnwrapKey(cc_handle, NULL, &key, CSSM_KEYUSE_ANY, | 95 crtn = CSSM_UnwrapKey(cc_handle, NULL, &key, CSSM_KEYUSE_ANY, |
| 96 CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, &label_data, | 96 CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, &label_data, |
| 97 NULL, result->key(), &desc_data); | 97 NULL, result->key(), &desc_data); |
| 98 if (crtn) { | 98 if (crtn) { |
| 99 NOTREACHED() << "CSSM_UnwrapKey failed: " << crtn; | 99 NOTREACHED() << "CSSM_UnwrapKey failed: " << crtn; |
| 100 return NULL; | 100 return NULL; |
| 101 } | 101 } |
| 102 | 102 |
| 103 return result.release(); | 103 return result.release(); |
| 104 } | 104 } |
| 105 | 105 |
| 106 RSAPrivateKey::RSAPrivateKey() : csp_handle_(0) { | 106 RSAPrivateKey::RSAPrivateKey() { |
| 107 memset(&key_, 0, sizeof(key_)); | 107 memset(&key_, 0, sizeof(key_)); |
| 108 | 108 |
| 109 EnsureCSSMInit(); | 109 EnsureCSSMInit(); |
| 110 | |
| 111 static CSSM_VERSION version = {2, 0}; | |
| 112 CSSM_RETURN crtn; | |
| 113 crtn = CSSM_ModuleAttach(&gGuidAppleCSP, &version, &kCssmMemoryFunctions, 0, | |
| 114 CSSM_SERVICE_CSP, 0, CSSM_KEY_HIERARCHY_NONE, | |
| 115 NULL, 0, NULL, &csp_handle_); | |
| 116 DCHECK(crtn == CSSM_OK); | |
| 117 } | 110 } |
| 118 | 111 |
| 119 RSAPrivateKey::~RSAPrivateKey() { | 112 RSAPrivateKey::~RSAPrivateKey() { |
| 120 if (csp_handle_) { | 113 if (key_.KeyData.Data) { |
| 121 if (key_.KeyData.Data) { | 114 CSSM_FreeKey(GetSharedCSPHandle(), NULL, &key_, CSSM_FALSE); |
| 122 CSSM_FreeKey(csp_handle_, NULL, &key_, CSSM_FALSE); | |
| 123 } | |
| 124 CSSM_RETURN crtn = CSSM_ModuleDetach(csp_handle_); | |
| 125 DCHECK(crtn == CSSM_OK); | |
| 126 } | 115 } |
| 127 } | 116 } |
| 128 | 117 |
| 129 bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) { | 118 bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) { |
| 130 if (!key_.KeyData.Data || !key_.KeyData.Length) { | 119 if (!key_.KeyData.Data || !key_.KeyData.Length) { |
| 131 return false; | 120 return false; |
| 132 } | 121 } |
| 133 output->clear(); | 122 output->clear(); |
| 134 output->insert(output->end(), key_.KeyData.Data, | 123 output->insert(output->end(), key_.KeyData.Data, |
| 135 key_.KeyData.Data + key_.KeyData.Length); | 124 key_.KeyData.Data + key_.KeyData.Length); |
| 136 return true; | 125 return true; |
| 137 } | 126 } |
| 138 | 127 |
| 139 bool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) { | 128 bool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) { |
| 140 PrivateKeyInfoCodec private_key_info(true); | 129 PrivateKeyInfoCodec private_key_info(true); |
| 141 std::vector<uint8> private_key_data; | 130 std::vector<uint8> private_key_data; |
| 142 private_key_data.assign(key_.KeyData.Data, | 131 private_key_data.assign(key_.KeyData.Data, |
| 143 key_.KeyData.Data + key_.KeyData.Length); | 132 key_.KeyData.Data + key_.KeyData.Length); |
| 144 return (private_key_info.Import(private_key_data) && | 133 return (private_key_info.Import(private_key_data) && |
| 145 private_key_info.ExportPublicKeyInfo(output)); | 134 private_key_info.ExportPublicKeyInfo(output)); |
| 146 } | 135 } |
| 147 | 136 |
| 148 } // namespace base | 137 } // namespace base |
| OLD | NEW |