Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "crypto/rsa_private_key.h" | 5 #include "crypto/rsa_private_key.h" |
| 6 | 6 |
| 7 #include <cryptohi.h> | 7 #include <cryptohi.h> |
| 8 #include <keyhi.h> | 8 #include <keyhi.h> |
| 9 #include <pk11pub.h> | 9 #include <pk11pub.h> |
| 10 | 10 |
| 11 #include <list> | 11 #include <list> |
| 12 | 12 |
| 13 #include "base/debug/leak_annotations.h" | 13 #include "base/debug/leak_annotations.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/memory/scoped_ptr.h" | 15 #include "base/memory/scoped_ptr.h" |
| 16 #include "base/string_util.h" | 16 #include "base/string_util.h" |
| 17 #include "crypto/nss_util.h" | 17 #include "crypto/nss_util.h" |
| 18 #include "crypto/nss_util_internal.h" | 18 #include "crypto/nss_util_internal.h" |
| 19 #include "crypto/scoped_nss_types.h" | |
| 19 | 20 |
| 20 // TODO(rafaelw): Consider refactoring common functions and definitions from | 21 // TODO(rafaelw): Consider refactoring common functions and definitions from |
| 21 // rsa_private_key_win.cc or using NSS's ASN.1 encoder. | 22 // rsa_private_key_win.cc or using NSS's ASN.1 encoder. |
| 22 namespace { | 23 namespace { |
| 23 | 24 |
| 24 static bool ReadAttribute(SECKEYPrivateKey* key, | 25 static bool ReadAttribute(SECKEYPrivateKey* key, |
| 25 CK_ATTRIBUTE_TYPE type, | 26 CK_ATTRIBUTE_TYPE type, |
| 26 std::vector<uint8>* output) { | 27 std::vector<uint8>* output) { |
| 27 SECItem item; | 28 SECItem item; |
| 28 SECStatus rv; | 29 SECStatus rv; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 84 EnsureNSSInit(); | 85 EnsureNSSInit(); |
| 85 | 86 |
| 86 scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); | 87 scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); |
| 87 | 88 |
| 88 // First, decode and save the public key. | 89 // First, decode and save the public key. |
| 89 SECItem key_der; | 90 SECItem key_der; |
| 90 key_der.type = siBuffer; | 91 key_der.type = siBuffer; |
| 91 key_der.data = const_cast<unsigned char*>(&input[0]); | 92 key_der.data = const_cast<unsigned char*>(&input[0]); |
| 92 key_der.len = input.size(); | 93 key_der.len = input.size(); |
| 93 | 94 |
| 94 CERTSubjectPublicKeyInfo *spki = | 95 CERTSubjectPublicKeyInfo* spki = |
| 95 SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der); | 96 SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der); |
| 96 if (!spki) { | 97 if (!spki) { |
| 97 NOTREACHED(); | 98 NOTREACHED(); |
| 98 return NULL; | 99 return NULL; |
| 99 } | 100 } |
| 100 | 101 |
| 101 result->public_key_ = SECKEY_ExtractPublicKey(spki); | 102 result->public_key_ = SECKEY_ExtractPublicKey(spki); |
| 102 SECKEY_DestroySubjectPublicKeyInfo(spki); | 103 SECKEY_DestroySubjectPublicKeyInfo(spki); |
| 103 if (!result->public_key_) { | 104 if (!result->public_key_) { |
| 104 NOTREACHED(); | 105 NOTREACHED(); |
| 105 return NULL; | 106 return NULL; |
| 106 } | 107 } |
| 107 | 108 |
| 108 // Now, look for the associated private key in the user's | |
| 109 // hardware-backed NSS DB. If it's not there, consider that an | |
| 110 // error. | |
| 111 PK11SlotInfo *slot = GetPrivateNSSKeySlot(); | |
| 112 if (!slot) { | |
| 113 NOTREACHED(); | |
| 114 return NULL; | |
| 115 } | |
| 116 | |
| 117 // Make sure the key is an RSA key. If not, that's an error | 109 // Make sure the key is an RSA key. If not, that's an error |
| 118 if (result->public_key_->keyType != rsaKey) { | 110 if (result->public_key_->keyType != rsaKey) { |
| 119 PK11_FreeSlot(slot); | |
| 120 NOTREACHED(); | 111 NOTREACHED(); |
| 121 return NULL; | 112 return NULL; |
| 122 } | 113 } |
| 123 | 114 |
| 124 SECItem *ck_id = PK11_MakeIDFromPubKey(&(result->public_key_->u.rsa.modulus)); | 115 ScopedSECItem ck_id( |
| 125 if (!ck_id) { | 116 PK11_MakeIDFromPubKey(&(result->public_key_->u.rsa.modulus))); |
| 126 PK11_FreeSlot(slot); | 117 if (!ck_id.get()) { |
| 118 NOTREACHED(); | |
| 119 return NULL; | |
| 120 } | |
| 121 | |
| 122 ScopedPK11Slot slot(GetPrivateNSSKeySlot()); | |
| 123 if (!slot.get()) { | |
| 127 NOTREACHED(); | 124 NOTREACHED(); |
| 128 return NULL; | 125 return NULL; |
| 129 } | 126 } |
| 130 | 127 |
| 131 // Finally...Look for the key! | 128 // Finally...Look for the key! |
| 132 result->key_ = PK11_FindKeyByKeyID(slot, ck_id, NULL); | 129 result->key_ = PK11_FindKeyByKeyID(slot.get(), ck_id.get(), NULL); |
| 133 | 130 |
| 134 // Cleanup... | 131 // If we don't find the matching key in the private slot, then we |
| 135 PK11_FreeSlot(slot); | 132 // look in the public slot. |
| 136 SECITEM_FreeItem(ck_id, PR_TRUE); | 133 if (!result->key_) { |
| 134 slot.reset(GetPublicNSSKeySlot()); | |
|
wtc
2011/05/25 23:34:01
If the computer doesn't have a TPM, GetPrivateNSSK
| |
| 135 if (!slot.get()) { | |
| 136 NOTREACHED(); | |
| 137 return NULL; | |
| 138 } | |
| 139 result->key_ = PK11_FindKeyByKeyID(slot.get(), ck_id.get(), NULL); | |
| 140 } | |
| 137 | 141 |
| 138 // If we didn't find it, that's ok. | 142 // If we didn't find it, that's ok. |
| 139 if (!result->key_) | 143 if (!result->key_) |
| 140 return NULL; | 144 return NULL; |
| 141 | 145 |
| 142 return result.release(); | 146 return result.release(); |
| 143 } | 147 } |
| 144 | 148 |
| 145 | 149 |
| 146 bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) { | 150 bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) { |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 159 !ReadAttribute(key_, CKA_EXPONENT_2, private_key_info.exponent2()) || | 163 !ReadAttribute(key_, CKA_EXPONENT_2, private_key_info.exponent2()) || |
| 160 !ReadAttribute(key_, CKA_COEFFICIENT, private_key_info.coefficient())) { | 164 !ReadAttribute(key_, CKA_COEFFICIENT, private_key_info.coefficient())) { |
| 161 NOTREACHED(); | 165 NOTREACHED(); |
| 162 return false; | 166 return false; |
| 163 } | 167 } |
| 164 | 168 |
| 165 return private_key_info.Export(output); | 169 return private_key_info.Export(output); |
| 166 } | 170 } |
| 167 | 171 |
| 168 bool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) { | 172 bool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) { |
| 169 SECItem* der_pubkey = SECKEY_EncodeDERSubjectPublicKeyInfo(public_key_); | 173 ScopedSECItem der_pubkey(SECKEY_EncodeDERSubjectPublicKeyInfo(public_key_)); |
| 170 if (!der_pubkey) { | 174 if (!der_pubkey.get()) { |
| 171 NOTREACHED(); | 175 NOTREACHED(); |
| 172 return false; | 176 return false; |
| 173 } | 177 } |
| 174 | 178 |
| 175 for (size_t i = 0; i < der_pubkey->len; ++i) | 179 for (size_t i = 0; i < der_pubkey->len; ++i) |
| 176 output->push_back(der_pubkey->data[i]); | 180 output->push_back(der_pubkey->data[i]); |
| 177 | 181 |
| 178 SECITEM_FreeItem(der_pubkey, PR_TRUE); | |
| 179 return true; | 182 return true; |
| 180 } | 183 } |
| 181 | 184 |
| 182 RSAPrivateKey::RSAPrivateKey() : key_(NULL), public_key_(NULL) { | 185 RSAPrivateKey::RSAPrivateKey() : key_(NULL), public_key_(NULL) { |
| 183 EnsureNSSInit(); | 186 EnsureNSSInit(); |
| 184 } | 187 } |
| 185 | 188 |
| 186 // static | 189 // static |
| 187 RSAPrivateKey* RSAPrivateKey::CreateWithParams(uint16 num_bits, | 190 RSAPrivateKey* RSAPrivateKey::CreateWithParams(uint16 num_bits, |
| 188 bool permanent, | 191 bool permanent, |
| 189 bool sensitive) { | 192 bool sensitive) { |
| 190 EnsureNSSInit(); | 193 EnsureNSSInit(); |
| 191 | 194 |
| 192 scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); | 195 scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); |
| 193 | 196 |
| 194 PK11SlotInfo *slot = GetPrivateNSSKeySlot(); | 197 ScopedPK11Slot slot(GetPrivateNSSKeySlot()); |
| 195 if (!slot) | 198 if (!slot.get()) |
| 196 return NULL; | 199 return NULL; |
| 197 | 200 |
| 198 PK11RSAGenParams param; | 201 PK11RSAGenParams param; |
| 199 param.keySizeInBits = num_bits; | 202 param.keySizeInBits = num_bits; |
| 200 param.pe = 65537L; | 203 param.pe = 65537L; |
| 201 result->key_ = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, ¶m, | 204 result->key_ = PK11_GenerateKeyPair(slot.get(), |
| 202 &result->public_key_, permanent, sensitive, NULL); | 205 CKM_RSA_PKCS_KEY_PAIR_GEN, |
| 203 PK11_FreeSlot(slot); | 206 ¶m, |
| 207 &result->public_key_, | |
| 208 permanent, | |
| 209 sensitive, | |
| 210 NULL); | |
| 204 if (!result->key_) | 211 if (!result->key_) |
| 205 return NULL; | 212 return NULL; |
| 206 | 213 |
| 207 return result.release(); | 214 return result.release(); |
| 208 } | 215 } |
| 209 | 216 |
| 210 // static | 217 // static |
| 211 RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfoWithParams( | 218 RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfoWithParams( |
| 212 const std::vector<uint8>& input, bool permanent, bool sensitive) { | 219 const std::vector<uint8>& input, bool permanent, bool sensitive) { |
| 213 // This method currently leaks some memory. | 220 // This method currently leaks some memory. |
| 214 // See http://crbug.com/34742. | 221 // See http://crbug.com/34742. |
| 215 ANNOTATE_SCOPED_MEMORY_LEAK; | 222 ANNOTATE_SCOPED_MEMORY_LEAK; |
| 216 EnsureNSSInit(); | 223 EnsureNSSInit(); |
| 217 | 224 |
| 218 scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); | 225 scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); |
| 219 | 226 |
| 220 PK11SlotInfo *slot = GetPrivateNSSKeySlot(); | 227 ScopedPK11Slot slot(GetPrivateNSSKeySlot()); |
| 221 if (!slot) | 228 if (!slot.get()) |
| 222 return NULL; | 229 return NULL; |
| 223 | 230 |
| 224 SECItem der_private_key_info; | 231 SECItem der_private_key_info; |
| 225 der_private_key_info.data = const_cast<unsigned char*>(&input.front()); | 232 der_private_key_info.data = const_cast<unsigned char*>(&input.front()); |
| 226 der_private_key_info.len = input.size(); | 233 der_private_key_info.len = input.size(); |
| 227 // Allow the private key to be used for key unwrapping, data decryption, | 234 // Allow the private key to be used for key unwrapping, data decryption, |
| 228 // and signature generation. | 235 // and signature generation. |
| 229 const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT | | 236 const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT | |
| 230 KU_DIGITAL_SIGNATURE; | 237 KU_DIGITAL_SIGNATURE; |
| 231 SECStatus rv = PK11_ImportDERPrivateKeyInfoAndReturnKey( | 238 SECStatus rv = PK11_ImportDERPrivateKeyInfoAndReturnKey( |
| 232 slot, &der_private_key_info, NULL, NULL, permanent, sensitive, | 239 slot.get(), &der_private_key_info, NULL, NULL, permanent, sensitive, |
| 233 key_usage, &result->key_, NULL); | 240 key_usage, &result->key_, NULL); |
| 234 PK11_FreeSlot(slot); | |
| 235 if (rv != SECSuccess) { | 241 if (rv != SECSuccess) { |
| 236 NOTREACHED(); | 242 NOTREACHED(); |
| 237 return NULL; | 243 return NULL; |
| 238 } | 244 } |
| 239 | 245 |
| 240 result->public_key_ = SECKEY_ConvertToPublicKey(result->key_); | 246 result->public_key_ = SECKEY_ConvertToPublicKey(result->key_); |
| 241 if (!result->public_key_) { | 247 if (!result->public_key_) { |
| 242 NOTREACHED(); | 248 NOTREACHED(); |
| 243 return NULL; | 249 return NULL; |
| 244 } | 250 } |
| 245 | 251 |
| 246 return result.release(); | 252 return result.release(); |
| 247 } | 253 } |
| 248 | 254 |
| 249 } // namespace crypto | 255 } // namespace crypto |
| OLD | NEW |