Fix protobuf_lite_java action ordering in gyp.
[chromium-blink-merge.git] / crypto / rsa_private_key_mac.cc
blobfbe1491e980642eb7ffff2274b4a5a20c528a669
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "crypto/rsa_private_key.h"
7 #include <list>
9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "crypto/cssm_init.h"
13 namespace crypto {
15 // static
16 RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) {
17 scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
19 CSSM_CC_HANDLE cc_handle;
20 CSSM_RETURN crtn;
21 crtn = CSSM_CSP_CreateKeyGenContext(GetSharedCSPHandle(), CSSM_ALGID_RSA,
22 num_bits, NULL, NULL, NULL, NULL, NULL,
23 &cc_handle);
24 if (crtn) {
25 NOTREACHED() << "CSSM_CSP_CreateKeyGenContext failed: " << crtn;
26 return NULL;
29 CSSM_DATA label = { 9,
30 const_cast<uint8*>(reinterpret_cast<const uint8*>("temp_key")) };
31 crtn = CSSM_GenerateKeyPair(cc_handle,
32 CSSM_KEYUSE_VERIFY,
33 CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, &label,
34 result->public_key(), CSSM_KEYUSE_SIGN,
35 CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, &label, NULL,
36 result->key());
37 CSSM_DeleteContext(cc_handle);
38 if (crtn) {
39 NOTREACHED() << "CSSM_CSP_CreateKeyGenContext failed: " << crtn;
40 return NULL;
43 return result.release();
46 // static
47 RSAPrivateKey* RSAPrivateKey::CreateSensitive(uint16 num_bits) {
48 NOTIMPLEMENTED();
49 return NULL;
52 // static
53 RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo(
54 const std::vector<uint8>& input) {
55 if (input.empty())
56 return NULL;
58 scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
60 CSSM_KEY key;
61 memset(&key, 0, sizeof(key));
62 key.KeyData.Data = const_cast<uint8*>(&input.front());
63 key.KeyData.Length = input.size();
64 key.KeyHeader.Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS8;
65 key.KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION;
66 key.KeyHeader.BlobType = CSSM_KEYBLOB_RAW;
67 key.KeyHeader.AlgorithmId = CSSM_ALGID_RSA;
68 key.KeyHeader.KeyClass = CSSM_KEYCLASS_PRIVATE_KEY;
69 key.KeyHeader.KeyAttr = CSSM_KEYATTR_EXTRACTABLE;
70 key.KeyHeader.KeyUsage = CSSM_KEYUSE_ANY;
72 CSSM_KEY_SIZE key_size;
73 CSSM_RETURN crtn;
74 crtn = CSSM_QueryKeySizeInBits(
75 GetSharedCSPHandle(), CSSM_INVALID_HANDLE, &key, &key_size);
76 if (crtn) {
77 NOTREACHED() << "CSSM_QueryKeySizeInBits failed: " << crtn;
78 return NULL;
80 key.KeyHeader.LogicalKeySizeInBits = key_size.LogicalKeySizeInBits;
82 // Perform a NULL unwrap operation on the key so that result's key_
83 // instance variable points to a key that can be released via CSSM_FreeKey().
84 CSSM_ACCESS_CREDENTIALS creds;
85 memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
86 CSSM_CC_HANDLE cc_handle;
87 crtn = CSSM_CSP_CreateSymmetricContext(GetSharedCSPHandle(), CSSM_ALGID_NONE,
88 CSSM_ALGMODE_NONE, &creds, NULL, NULL, CSSM_PADDING_NONE, 0, &cc_handle);
89 if (crtn) {
90 NOTREACHED() << "CSSM_CSP_CreateSymmetricContext failed: " << crtn;
91 return NULL;
93 CSSM_DATA label_data, desc_data = { 0, NULL };
94 label_data.Data =
95 const_cast<uint8*>(reinterpret_cast<const uint8*>("unwrapped"));
96 label_data.Length = 9;
97 crtn = CSSM_UnwrapKey(cc_handle, NULL, &key, CSSM_KEYUSE_ANY,
98 CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE, &label_data,
99 NULL, result->key(), &desc_data);
100 if (crtn) {
101 NOTREACHED() << "CSSM_UnwrapKey failed: " << crtn;
102 return NULL;
105 // Extract a public key from the private key.
106 // Apple doesn't accept CSSM_KEYBLOB_RAW_FORMAT_X509 as a valid key
107 // format when attempting to generate certs, so use PKCS1 instead.
108 PrivateKeyInfoCodec codec(true);
109 std::vector<uint8> private_key_data;
110 private_key_data.assign(key.KeyData.Data,
111 key.KeyData.Data + key.KeyData.Length);
112 if (!codec.Import(private_key_data)) {
113 return NULL;
115 std::vector<uint8> public_key_data;
116 if (!codec.ExportPublicKey(&public_key_data)) {
117 return NULL;
120 CSSM_KEY* public_key = result->public_key();
121 size_t size = public_key_data.size();
122 public_key->KeyData.Data = reinterpret_cast<uint8*>(CSSMMalloc(size));
123 if (!public_key->KeyData.Data) {
124 NOTREACHED() << "CSSMMalloc failed";
125 return NULL;
127 memcpy(public_key->KeyData.Data, &public_key_data.front(), size);
128 public_key->KeyData.Length = size;
129 public_key->KeyHeader.Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS1;
130 public_key->KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION;
131 public_key->KeyHeader.BlobType = CSSM_KEYBLOB_RAW;
132 public_key->KeyHeader.AlgorithmId = CSSM_ALGID_RSA;
133 public_key->KeyHeader.KeyClass = CSSM_KEYCLASS_PUBLIC_KEY;
134 public_key->KeyHeader.KeyAttr = CSSM_KEYATTR_EXTRACTABLE;
135 public_key->KeyHeader.KeyUsage = CSSM_KEYUSE_ANY;
137 crtn = CSSM_QueryKeySizeInBits(
138 GetSharedCSPHandle(), CSSM_INVALID_HANDLE, public_key, &key_size);
139 if (crtn) {
140 DLOG(ERROR) << "CSSM_QueryKeySizeInBits failed " << crtn;
141 return NULL;
143 public_key->KeyHeader.LogicalKeySizeInBits = key_size.LogicalKeySizeInBits;
145 return result.release();
148 // static
149 RSAPrivateKey* RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo(
150 const std::vector<uint8>& input) {
151 NOTIMPLEMENTED();
152 return NULL;
155 // static
156 RSAPrivateKey* RSAPrivateKey::FindFromPublicKeyInfo(
157 const std::vector<uint8>& input) {
158 NOTIMPLEMENTED();
159 return NULL;
162 RSAPrivateKey::RSAPrivateKey() {
163 memset(&key_, 0, sizeof(key_));
164 memset(&public_key_, 0, sizeof(public_key_));
166 EnsureCSSMInit();
169 RSAPrivateKey::~RSAPrivateKey() {
170 if (key_.KeyData.Data) {
171 CSSM_FreeKey(GetSharedCSPHandle(), NULL, &key_, CSSM_FALSE);
173 if (public_key_.KeyData.Data) {
174 CSSM_FreeKey(GetSharedCSPHandle(), NULL, &public_key_, CSSM_FALSE);
178 RSAPrivateKey* RSAPrivateKey::Copy() const {
179 std::vector<uint8> key_bytes;
180 if (!ExportPrivateKey(&key_bytes))
181 return NULL;
182 return CreateFromPrivateKeyInfo(key_bytes);
185 bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) const {
186 if (!key_.KeyData.Data || !key_.KeyData.Length) {
187 return false;
189 output->clear();
190 output->insert(output->end(), key_.KeyData.Data,
191 key_.KeyData.Data + key_.KeyData.Length);
192 return true;
195 bool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) const {
196 PrivateKeyInfoCodec private_key_info(true);
197 std::vector<uint8> private_key_data;
198 private_key_data.assign(key_.KeyData.Data,
199 key_.KeyData.Data + key_.KeyData.Length);
200 return (private_key_info.Import(private_key_data) &&
201 private_key_info.ExportPublicKeyInfo(output));
204 } // namespace crypto