15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 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/symmetric_key.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <nss.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <pk11pub.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/nss_util.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace crypto { 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SymmetricKey::~SymmetricKey() {} 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SymmetricKey* SymmetricKey::GenerateRandomKey(Algorithm algorithm, 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t key_size_in_bits) { 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(AES, algorithm); 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnsureNSSInit(); 235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Whitelist supported key sizes to avoid accidentaly relying on 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // algorithms available in NSS but not BoringSSL and vice 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // versa. Note that BoringSSL does not support AES-192. 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (key_size_in_bits != 128 && key_size_in_bits != 256) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedPK11Slot slot(PK11_GetInternalSlot()); 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!slot.get()) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PK11SymKey* sym_key = PK11_KeyGen(slot.get(), CKM_AES_KEY_GEN, NULL, 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_size_in_bits / 8, NULL); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!sym_key) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new SymmetricKey(sym_key); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SymmetricKey* SymmetricKey::DeriveKeyFromPassword(Algorithm algorithm, 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& password, 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& salt, 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t iterations, 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t key_size_in_bits) { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnsureNSSInit(); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (salt.empty() || iterations == 0 || key_size_in_bits == 0) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (algorithm == AES) { 535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Whitelist supported key sizes to avoid accidentaly relying on 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // algorithms available in NSS but not BoringSSL and vice 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // versa. Note that BoringSSL does not support AES-192. 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (key_size_in_bits != 128 && key_size_in_bits != 256) 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return NULL; 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECItem password_item; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) password_item.type = siBuffer; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) password_item.data = reinterpret_cast<unsigned char*>( 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const_cast<char *>(password.data())); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) password_item.len = password.size(); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECItem salt_item; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) salt_item.type = siBuffer; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) salt_item.data = reinterpret_cast<unsigned char*>( 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const_cast<char *>(salt.data())); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) salt_item.len = salt.size(); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECOidTag cipher_algorithm = 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) algorithm == AES ? SEC_OID_AES_256_CBC : SEC_OID_HMAC_SHA1; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedSECAlgorithmID alg_id(PK11_CreatePBEV2AlgorithmID(SEC_OID_PKCS5_PBKDF2, 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cipher_algorithm, 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SEC_OID_HMAC_SHA1, 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_size_in_bits / 8, 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iterations, 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &salt_item)); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!alg_id.get()) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedPK11Slot slot(PK11_GetInternalSlot()); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!slot.get()) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PK11SymKey* sym_key = PK11_PBEKeyGen(slot.get(), alg_id.get(), &password_item, 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PR_FALSE, NULL); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!sym_key) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new SymmetricKey(sym_key); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SymmetricKey* SymmetricKey::Import(Algorithm algorithm, 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& raw_key) { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnsureNSSInit(); 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (algorithm == AES) { 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Whitelist supported key sizes to avoid accidentaly relying on 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // algorithms available in NSS but not BoringSSL and vice 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // versa. Note that BoringSSL does not support AES-192. 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (raw_key.size() != 128/8 && raw_key.size() != 256/8) 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return NULL; 1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CK_MECHANISM_TYPE cipher = 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) algorithm == AES ? CKM_AES_CBC : CKM_SHA_1_HMAC; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECItem key_item; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_item.type = siBuffer; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_item.data = reinterpret_cast<unsigned char*>( 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const_cast<char *>(raw_key.data())); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_item.len = raw_key.size(); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedPK11Slot slot(PK11_GetInternalSlot()); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!slot.get()) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The exact value of the |origin| argument doesn't matter to NSS as long as 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // it's not PK11_OriginFortezzaHack, so we pass PK11_OriginUnwrap as a 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // placeholder. 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PK11SymKey* sym_key = PK11_ImportSymKey(slot.get(), cipher, PK11_OriginUnwrap, 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CKA_ENCRYPT, &key_item, NULL); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!sym_key) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new SymmetricKey(sym_key); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SymmetricKey::GetRawKey(std::string* raw_key) { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECStatus rv = PK11_ExtractKeyValue(key_.get()); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SECSuccess != rv) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECItem* key_item = PK11_GetKeyData(key_.get()); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!key_item) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raw_key->assign(reinterpret_cast<char*>(key_item->data), key_item->len); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SymmetricKey::SymmetricKey(PK11SymKey* key) : key_(key) { 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(key); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace crypto 150