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 3 // found in the LICENSE file. 4 5 #include "base/crypto/rsa_private_key.h" 6 7 #include <cryptohi.h> 8 #include <keyhi.h> 9 #include <pk11pub.h> 10 11 #include <iostream> 12 #include <list> 13 14 #include "base/logging.h" 15 #include "base/nss_util.h" 16 #include "base/scoped_ptr.h" 17 #include "base/string_util.h" 18 19 // TODO(rafaelw): Consider refactoring common functions and definitions from 20 // rsa_private_key_win.cc or using NSS's ASN.1 encoder. 21 namespace { 22 23 static bool ReadAttribute(SECKEYPrivateKey* key, 24 CK_ATTRIBUTE_TYPE type, 25 std::vector<uint8>* output) { 26 SECItem item; 27 SECStatus rv; 28 rv = PK11_ReadRawAttribute(PK11_TypePrivKey, key, type, &item); 29 if (rv != SECSuccess) { 30 NOTREACHED(); 31 return false; 32 } 33 34 output->assign(item.data, item.data + item.len); 35 SECITEM_FreeItem(&item, PR_FALSE); 36 return true; 37 } 38 39 } // namespace 40 41 namespace base { 42 43 // static 44 RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) { 45 scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); 46 47 PK11SlotInfo *slot = PK11_GetInternalSlot(); 48 if (!slot) 49 return NULL; 50 51 PK11RSAGenParams param; 52 param.keySizeInBits = num_bits; 53 param.pe = 65537L; 54 result->key_ = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, ¶m, 55 &result->public_key_, PR_FALSE, PR_FALSE, NULL); 56 PK11_FreeSlot(slot); 57 if (!result->key_) 58 return NULL; 59 60 return result.release(); 61 } 62 63 // static 64 RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo( 65 const std::vector<uint8>& input) { 66 scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); 67 68 PK11SlotInfo *slot = PK11_GetInternalSlot(); 69 if (!slot) 70 return NULL; 71 72 SECItem der_private_key_info; 73 der_private_key_info.data = const_cast<unsigned char*>(&input.front()); 74 der_private_key_info.len = input.size(); 75 SECStatus rv = PK11_ImportDERPrivateKeyInfoAndReturnKey(slot, 76 &der_private_key_info, NULL, NULL, PR_FALSE, PR_FALSE, 77 KU_DIGITAL_SIGNATURE, &result->key_, NULL); 78 PK11_FreeSlot(slot); 79 if (rv != SECSuccess) { 80 NOTREACHED(); 81 return NULL; 82 } 83 84 result->public_key_ = SECKEY_ConvertToPublicKey(result->key_); 85 if (!result->public_key_) { 86 NOTREACHED(); 87 return NULL; 88 } 89 90 return result.release(); 91 } 92 93 RSAPrivateKey::RSAPrivateKey() : key_(NULL), public_key_(NULL) { 94 EnsureNSSInit(); 95 } 96 97 RSAPrivateKey::~RSAPrivateKey() { 98 if (key_) 99 SECKEY_DestroyPrivateKey(key_); 100 if (public_key_) 101 SECKEY_DestroyPublicKey(public_key_); 102 } 103 104 bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) { 105 PrivateKeyInfoCodec private_key_info(true); 106 107 // Manually read the component attributes of the private key and build up 108 // the PrivateKeyInfo. 109 if (!ReadAttribute(key_, CKA_MODULUS, private_key_info.modulus()) || 110 !ReadAttribute(key_, CKA_PUBLIC_EXPONENT, 111 private_key_info.public_exponent()) || 112 !ReadAttribute(key_, CKA_PRIVATE_EXPONENT, 113 private_key_info.private_exponent()) || 114 !ReadAttribute(key_, CKA_PRIME_1, private_key_info.prime1()) || 115 !ReadAttribute(key_, CKA_PRIME_2, private_key_info.prime2()) || 116 !ReadAttribute(key_, CKA_EXPONENT_1, private_key_info.exponent1()) || 117 !ReadAttribute(key_, CKA_EXPONENT_2, private_key_info.exponent2()) || 118 !ReadAttribute(key_, CKA_COEFFICIENT, private_key_info.coefficient())) { 119 NOTREACHED(); 120 return false; 121 } 122 123 return private_key_info.Export(output); 124 } 125 126 bool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) { 127 SECItem* der_pubkey = SECKEY_EncodeDERSubjectPublicKeyInfo(public_key_); 128 if (!der_pubkey) { 129 NOTREACHED(); 130 return false; 131 } 132 133 for (size_t i = 0; i < der_pubkey->len; ++i) 134 output->push_back(der_pubkey->data[i]); 135 136 SECITEM_FreeItem(der_pubkey, PR_TRUE); 137 return true; 138 } 139 140 } // namespace base 141