15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/rsa_private_key.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cryptohi.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <keyhi.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <pk11pub.h> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <secmod.h> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <list> 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/leak_annotations.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/nss_util.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/nss_util_internal.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/scoped_nss_types.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// TODO(rafaelw): Consider using NSS's ASN.1 encoder. 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool ReadAttribute(SECKEYPrivateKey* key, 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CK_ATTRIBUTE_TYPE type, 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<uint8>* output) { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECItem item; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECStatus rv; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = PK11_ReadRawAttribute(PK11_TypePrivKey, key, type, &item); 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv != SECSuccess) { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output->assign(item.data, item.data + item.len); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECITEM_FreeItem(&item, PR_FALSE); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if defined(USE_NSS) 42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)struct PublicKeyInfoDeleter { 43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) inline void operator()(CERTSubjectPublicKeyInfo* spki) { 44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SECKEY_DestroySubjectPublicKeyInfo(spki); 45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)typedef scoped_ptr<CERTSubjectPublicKeyInfo, PublicKeyInfoDeleter> 49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ScopedPublicKeyInfo; 50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// The function decodes RSA public key from the |input|. 52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)crypto::ScopedSECKEYPublicKey GetRSAPublicKey(const std::vector<uint8>& input) { 53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // First, decode and save the public key. 54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SECItem key_der; 55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) key_der.type = siBuffer; 56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) key_der.data = const_cast<unsigned char*>(&input[0]); 57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) key_der.len = input.size(); 58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ScopedPublicKeyInfo spki(SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der)); 60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!spki) 61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return crypto::ScopedSECKEYPublicKey(); 62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) crypto::ScopedSECKEYPublicKey result(SECKEY_ExtractPublicKey(spki.get())); 64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Make sure the key is an RSA key.. If not, that's an error. 66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!result || result->keyType != rsaKey) 67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return crypto::ScopedSECKEYPublicKey(); 68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return result.Pass(); 69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif // defined(USE_NSS) 71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace crypto { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RSAPrivateKey::~RSAPrivateKey() { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (key_) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECKEY_DestroyPrivateKey(key_); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (public_key_) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECKEY_DestroyPublicKey(public_key_); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RSAPrivateKey* RSAPrivateKey::Create(uint16 num_bits) { 85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) EnsureNSSInit(); 86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ScopedPK11Slot slot(PK11_GetInternalSlot()); 88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return CreateWithParams(slot.get(), 89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) num_bits, 90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch false /* not permanent */, 91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch false /* not sensitive */); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo( 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<uint8>& input) { 97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) EnsureNSSInit(); 98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ScopedPK11Slot slot(PK11_GetInternalSlot()); 100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return CreateFromPrivateKeyInfoWithParams( 101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) slot.get(), 102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) input, 103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) false /* not permanent */, 104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) false /* not sensitive */); 105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(USE_NSS) 108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// static 109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)RSAPrivateKey* RSAPrivateKey::CreateSensitive(PK11SlotInfo* slot, 110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) uint16 num_bits) { 111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return CreateWithParams(slot, 112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) num_bits, 113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch true /* permanent */, 114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch true /* sensitive */); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RSAPrivateKey* RSAPrivateKey::CreateSensitiveFromPrivateKeyInfo( 119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) PK11SlotInfo* slot, 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<uint8>& input) { 121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return CreateFromPrivateKeyInfoWithParams(slot, 122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) input, 123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch true /* permanent */, 124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch true /* sensitive */); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 128b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)RSAPrivateKey* RSAPrivateKey::CreateFromKey(SECKEYPrivateKey* key) { 129b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK(key); 130b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (SECKEY_GetPrivateKeyType(key) != rsaKey) 131b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return NULL; 132b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) RSAPrivateKey* copy = new RSAPrivateKey(); 133b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) copy->key_ = SECKEY_CopyPrivateKey(key); 134b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) copy->public_key_ = SECKEY_ConvertToPublicKey(key); 135b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!copy->key_ || !copy->public_key_) { 136b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) NOTREACHED(); 137b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) delete copy; 138b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return NULL; 139b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 140b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return copy; 141b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 142b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 143b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// static 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RSAPrivateKey* RSAPrivateKey::FindFromPublicKeyInfo( 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<uint8>& input) { 146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<RSAPrivateKey> result(InitPublicPart(input)); 147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!result) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedSECItem ck_id( 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PK11_MakeIDFromPubKey(&(result->public_key_->u.rsa.modulus))); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ck_id.get()) { 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Search all slots in all modules for the key with the given ID. 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AutoSECMODListReadLock auto_lock; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECMODModuleList* head = SECMOD_GetDefaultModuleList(); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (SECMODModuleList* item = head; item != NULL; item = item->next) { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int slot_count = item->module->loaded ? item->module->slotCount : 0; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < slot_count; i++) { 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Finally...Look for the key! 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->key_ = PK11_FindKeyByKeyID(item->module->slots[i], 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ck_id.get(), NULL); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result->key_) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result.release(); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We didn't find the key. 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)RSAPrivateKey* RSAPrivateKey::FindFromPublicKeyInfoInSlot( 177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const std::vector<uint8>& input, 178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PK11SlotInfo* slot) { 179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!slot) 180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return NULL; 181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<RSAPrivateKey> result(InitPublicPart(input)); 183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!result) 184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return NULL; 185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ScopedSECItem ck_id( 187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PK11_MakeIDFromPubKey(&(result->public_key_->u.rsa.modulus))); 188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!ck_id.get()) { 189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NOTREACHED(); 190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return NULL; 191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) result->key_ = PK11_FindKeyByKeyID(slot, ck_id.get(), NULL); 194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!result->key_) 195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return NULL; 196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return result.release(); 197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RSAPrivateKey* RSAPrivateKey::Copy() const { 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RSAPrivateKey* copy = new RSAPrivateKey(); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) copy->key_ = SECKEY_CopyPrivateKey(key_); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) copy->public_key_ = SECKEY_CopyPublicKey(public_key_); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return copy; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8>* output) const { 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrivateKeyInfoCodec private_key_info(true); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Manually read the component attributes of the private key and build up 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the PrivateKeyInfo. 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ReadAttribute(key_, CKA_MODULUS, private_key_info.modulus()) || 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !ReadAttribute(key_, CKA_PUBLIC_EXPONENT, 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private_key_info.public_exponent()) || 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !ReadAttribute(key_, CKA_PRIVATE_EXPONENT, 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private_key_info.private_exponent()) || 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !ReadAttribute(key_, CKA_PRIME_1, private_key_info.prime1()) || 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !ReadAttribute(key_, CKA_PRIME_2, private_key_info.prime2()) || 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !ReadAttribute(key_, CKA_EXPONENT_1, private_key_info.exponent1()) || 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !ReadAttribute(key_, CKA_EXPONENT_2, private_key_info.exponent2()) || 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !ReadAttribute(key_, CKA_COEFFICIENT, private_key_info.coefficient())) { 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return private_key_info.Export(output); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RSAPrivateKey::ExportPublicKey(std::vector<uint8>* output) const { 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedSECItem der_pubkey(SECKEY_EncodeDERSubjectPublicKeyInfo(public_key_)); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!der_pubkey.get()) { 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output->assign(der_pubkey->data, der_pubkey->data + der_pubkey->len); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RSAPrivateKey::RSAPrivateKey() : key_(NULL), public_key_(NULL) { 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnsureNSSInit(); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 245f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)RSAPrivateKey* RSAPrivateKey::CreateWithParams(PK11SlotInfo* slot, 246f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) uint16 num_bits, 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool permanent, 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool sensitive) { 249f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!slot) 250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return NULL; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PK11RSAGenParams param; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) param.keySizeInBits = num_bits; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) param.pe = 65537L; 257f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) result->key_ = PK11_GenerateKeyPair(slot, 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CKM_RSA_PKCS_KEY_PAIR_GEN, 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ¶m, 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &result->public_key_, 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) permanent, 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sensitive, 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!result->key_) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result.release(); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfoWithParams( 272f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) PK11SlotInfo* slot, 273f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const std::vector<uint8>& input, 274f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool permanent, 275f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool sensitive) { 276f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!slot) 277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return NULL; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECItem der_private_key_info; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) der_private_key_info.data = const_cast<unsigned char*>(&input.front()); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) der_private_key_info.len = input.size(); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Allow the private key to be used for key unwrapping, data decryption, 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and signature generation. 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT | 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KU_DIGITAL_SIGNATURE; 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECStatus rv = PK11_ImportDERPrivateKeyInfoAndReturnKey( 289f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) slot, &der_private_key_info, NULL, NULL, permanent, sensitive, 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_usage, &result->key_, NULL); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv != SECSuccess) { 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->public_key_ = SECKEY_ConvertToPublicKey(result->key_); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!result->public_key_) { 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result.release(); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if defined(USE_NSS) 306cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// static 307cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)RSAPrivateKey* RSAPrivateKey::InitPublicPart(const std::vector<uint8>& input) { 308cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EnsureNSSInit(); 309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey()); 311cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) result->public_key_ = GetRSAPublicKey(input).release(); 312cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!result->public_key_) { 313cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NOTREACHED(); 314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return NULL; 315cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 316cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 317cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return result.release(); 318cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 319cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif // defined(USE_NSS) 320cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace crypto 322