14e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 24e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 34e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// found in the LICENSE file. 44e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 54e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/renderer/webcrypto/webcrypto_impl.h" 64e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 74e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <vector> 81e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <openssl/aes.h> 94e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <openssl/evp.h> 104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <openssl/hmac.h> 114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <openssl/sha.h> 121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <openssl/evp.h> 131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include <openssl/rand.h> 144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/logging.h" 16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "content/renderer/webcrypto/webcrypto_util.h" 174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "crypto/openssl_util.h" 184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "crypto/secure_util.h" 194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "third_party/WebKit/public/platform/WebArrayBuffer.h" 204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" 214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" 224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace content { 244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace { 264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class SymKeyHandle : public blink::WebCryptoKeyHandle { 284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public: 294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SymKeyHandle(const unsigned char* key_data, unsigned key_data_size) 304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) : key_(key_data, key_data + key_data_size) {} 314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const std::vector<unsigned char>& key() const { return key_; } 334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) private: 354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const std::vector<unsigned char> key_; 364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(SymKeyHandle); 384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}; 394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const EVP_CIPHER* GetAESCipherByKeyLength(unsigned key_length_bytes) { 411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // OpenSSL supports AES CBC ciphers for only 3 key lengths: 128, 192, 256 bits 421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) switch (key_length_bytes) { 431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) case 16: 441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return EVP_aes_128_cbc(); 451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) case 24: 461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return EVP_aes_192_cbc(); 471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) case 32: 481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return EVP_aes_256_cbc(); 491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) default: 501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return NULL; 511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)unsigned WebCryptoHmacParamsToBlockSize( 55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const blink::WebCryptoHmacKeyParams* params) { 561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DCHECK(params); 571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) switch (params->hash().id()) { 58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case blink::WebCryptoAlgorithmIdSha1: 591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return SHA_DIGEST_LENGTH / 8; 60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case blink::WebCryptoAlgorithmIdSha224: 611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return SHA224_DIGEST_LENGTH / 8; 62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case blink::WebCryptoAlgorithmIdSha256: 631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return SHA256_DIGEST_LENGTH / 8; 64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case blink::WebCryptoAlgorithmIdSha384: 651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return SHA384_DIGEST_LENGTH / 8; 66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case blink::WebCryptoAlgorithmIdSha512: 671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return SHA512_DIGEST_LENGTH / 8; 681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) default: 691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return 0; 701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// OpenSSL constants for EVP_CipherInit_ex(), do not change 741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)enum CipherOperation { 751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) kDoDecrypt = 0, 761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) kDoEncrypt = 1 771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}; 781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)bool AesCbcEncryptDecrypt(CipherOperation cipher_operation, 80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const blink::WebCryptoAlgorithm& algorithm, 81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const blink::WebCryptoKey& key, 821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const unsigned char* data, 831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) unsigned data_size, 84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) blink::WebArrayBuffer* buffer) { 851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // TODO(padolph): Handle other encrypt operations and then remove this gate 87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (algorithm.id() != blink::WebCryptoAlgorithmIdAesCbc) 881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return false; 891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DCHECK_EQ(algorithm.id(), key.algorithm().id()); 91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK_EQ(blink::WebCryptoKeyTypeSecret, key.type()); 921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (data_size >= INT_MAX - AES_BLOCK_SIZE) { 941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // TODO(padolph): Handle this by chunking the input fed into OpenSSL. Right 951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // now it doesn't make much difference since the one-shot API would end up 961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // blowing out the memory and crashing anyway. However a newer version of 971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // the spec allows for a sequence<CryptoData> so this will be relevant. 981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return false; 991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 1001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Note: PKCS padding is enabled by default 1021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) crypto::ScopedOpenSSL<EVP_CIPHER_CTX, EVP_CIPHER_CTX_free> context( 1031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EVP_CIPHER_CTX_new()); 1041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (!context.get()) 1061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return false; 1071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) SymKeyHandle* const sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); 1091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const EVP_CIPHER* const cipher = 1111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) GetAESCipherByKeyLength(sym_key->key().size()); 1121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DCHECK(cipher); 1131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const blink::WebCryptoAesCbcParams* const params = algorithm.aesCbcParams(); 1151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (params->iv().size() != AES_BLOCK_SIZE) 1161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return false; 1171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (!EVP_CipherInit_ex(context.get(), 1191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) cipher, 1201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) NULL, 1211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) &sym_key->key()[0], 1221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) params->iv().data(), 1231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) cipher_operation)) { 1241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return false; 1251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 1261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // According to the openssl docs, the amount of data written may be as large 1281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // as (data_size + cipher_block_size - 1), constrained to a multiple of 1291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // cipher_block_size. 1301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) unsigned output_max_len = data_size + AES_BLOCK_SIZE - 1; 1311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const unsigned remainder = output_max_len % AES_BLOCK_SIZE; 1321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (remainder != 0) 1331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) output_max_len += AES_BLOCK_SIZE - remainder; 1341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DCHECK_GT(output_max_len, data_size); 1351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) *buffer = blink::WebArrayBuffer::create(output_max_len, 1); 1371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) unsigned char* const buffer_data = 1391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) reinterpret_cast<unsigned char*>(buffer->data()); 1401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) int output_len = 0; 1421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (!EVP_CipherUpdate( 1431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) context.get(), buffer_data, &output_len, data, data_size)) 1441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return false; 1451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) int final_output_chunk_len = 0; 1461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (!EVP_CipherFinal_ex( 1471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) context.get(), buffer_data + output_len, &final_output_chunk_len)) 1481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return false; 1491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const unsigned final_output_len = 1511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) static_cast<unsigned>(output_len) + 1521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) static_cast<unsigned>(final_output_chunk_len); 1531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DCHECK_LE(final_output_len, output_max_len); 1541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) webcrypto::ShrinkBuffer(buffer, final_output_len); 156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 157a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return true; 158a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 159a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 160a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool ExportKeyInternalRaw( 161a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const blink::WebCryptoKey& key, 162a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) blink::WebArrayBuffer* buffer) { 163a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 164a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(key.handle()); 165a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(buffer); 166a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 167a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (key.type() != blink::WebCryptoKeyTypeSecret || !key.extractable()) 168a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 169a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 170a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); 171a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 172a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) *buffer = webcrypto::CreateArrayBuffer( 173a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) webcrypto::Uint8VectorStart(sym_key->key()), sym_key->key().size()); 1741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return true; 1761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 1771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} // namespace 1794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WebCryptoImpl::Init() { crypto::EnsureOpenSSLInit(); } 1814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool WebCryptoImpl::EncryptInternal(const blink::WebCryptoAlgorithm& algorithm, 183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const blink::WebCryptoKey& key, 1841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const unsigned char* data, 1851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) unsigned data_size, 186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) blink::WebArrayBuffer* buffer) { 187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (algorithm.id() == blink::WebCryptoAlgorithmIdAesCbc) { 1881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return AesCbcEncryptDecrypt( 1891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) kDoEncrypt, algorithm, key, data, data_size, buffer); 1901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 1911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 1934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 195f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool WebCryptoImpl::DecryptInternal(const blink::WebCryptoAlgorithm& algorithm, 196f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const blink::WebCryptoKey& key, 1971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const unsigned char* data, 1981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) unsigned data_size, 199f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) blink::WebArrayBuffer* buffer) { 200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (algorithm.id() == blink::WebCryptoAlgorithmIdAesCbc) { 2011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return AesCbcEncryptDecrypt( 2021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) kDoDecrypt, algorithm, key, data, data_size, buffer); 2031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 2041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 2064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 2074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 208f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool WebCryptoImpl::DigestInternal(const blink::WebCryptoAlgorithm& algorithm, 2094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const unsigned char* data, 2104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) unsigned data_size, 211f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) blink::WebArrayBuffer* buffer) { 2124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) crypto::OpenSSLErrStackTracer(FROM_HERE); 2144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const EVP_MD* digest_algorithm; 2164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) switch (algorithm.id()) { 217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case blink::WebCryptoAlgorithmIdSha1: 2184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) digest_algorithm = EVP_sha1(); 2194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) break; 220f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case blink::WebCryptoAlgorithmIdSha224: 2214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) digest_algorithm = EVP_sha224(); 2224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) break; 223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case blink::WebCryptoAlgorithmIdSha256: 2244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) digest_algorithm = EVP_sha256(); 2254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) break; 226f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case blink::WebCryptoAlgorithmIdSha384: 2274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) digest_algorithm = EVP_sha384(); 2284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) break; 229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case blink::WebCryptoAlgorithmIdSha512: 2304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) digest_algorithm = EVP_sha512(); 2314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) break; 2324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) default: 2334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Not a digest algorithm. 2344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 2354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) crypto::ScopedOpenSSL<EVP_MD_CTX, EVP_MD_CTX_destroy> digest_context( 2384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EVP_MD_CTX_create()); 2394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!digest_context.get()) { 2404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 2414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!EVP_DigestInit_ex(digest_context.get(), digest_algorithm, NULL) || 2444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) !EVP_DigestUpdate(digest_context.get(), data, data_size)) { 2454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 2464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const int hash_expected_size = EVP_MD_CTX_size(digest_context.get()); 2494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (hash_expected_size <= 0) { 2504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 2514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK_LE(hash_expected_size, EVP_MAX_MD_SIZE); 2534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 254f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) *buffer = blink::WebArrayBuffer::create(hash_expected_size, 1); 2554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) unsigned char* const hash_buffer = 2564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) reinterpret_cast<unsigned char* const>(buffer->data()); 2574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) unsigned hash_size = 0; 2594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!EVP_DigestFinal_ex(digest_context.get(), hash_buffer, &hash_size) || 2604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static_cast<int>(hash_size) != hash_expected_size) { 2614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) buffer->reset(); 2624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 2634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return true; 2664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 2674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 2684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool WebCryptoImpl::GenerateKeyInternal( 269f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const blink::WebCryptoAlgorithm& algorithm, 2701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) bool extractable, 271f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) blink::WebCryptoKeyUsageMask usage_mask, 272f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) blink::WebCryptoKey* key) { 2731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) unsigned keylen_bytes = 0; 275f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) blink::WebCryptoKeyType key_type; 2761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) switch (algorithm.id()) { 277f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case blink::WebCryptoAlgorithmIdAesCbc: { 278f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const blink::WebCryptoAesKeyGenParams* params = 2791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) algorithm.aesKeyGenParams(); 2801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DCHECK(params); 2811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (params->length() % 8) 2821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return false; 2831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) keylen_bytes = params->length() / 8; 2841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (!GetAESCipherByKeyLength(keylen_bytes)) { 2851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return false; 2861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 287f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) key_type = blink::WebCryptoKeyTypeSecret; 2881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) break; 2891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 290f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case blink::WebCryptoAlgorithmIdHmac: { 291f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const blink::WebCryptoHmacKeyParams* params = algorithm.hmacKeyParams(); 2921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DCHECK(params); 2931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (!params->getLength(keylen_bytes)) { 2941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) keylen_bytes = WebCryptoHmacParamsToBlockSize(params); 2951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 296f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) key_type = blink::WebCryptoKeyTypeSecret; 2971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) break; 2981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 2991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 3001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) default: { return false; } 3011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 3021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 3031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (keylen_bytes == 0) { 3041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return false; 3051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 3061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 3071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) crypto::OpenSSLErrStackTracer(FROM_HERE); 3081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 3091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::vector<unsigned char> random_bytes(keylen_bytes, 0); 3101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (!(RAND_bytes(&random_bytes[0], keylen_bytes))) { 3111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return false; 3121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 3131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 314f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) *key = blink::WebCryptoKey::create( 3151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) new SymKeyHandle(&random_bytes[0], random_bytes.size()), 3161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) key_type, extractable, algorithm, usage_mask); 3171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 3181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return true; 3194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 3204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3210f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)bool WebCryptoImpl::GenerateKeyPairInternal( 322f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const blink::WebCryptoAlgorithm& algorithm, 3230f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) bool extractable, 324f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) blink::WebCryptoKeyUsageMask usage_mask, 325f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) blink::WebCryptoKey* public_key, 326f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) blink::WebCryptoKey* private_key) { 3270f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // TODO(padolph): Placeholder for OpenSSL implementation. 3280f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // Issue http://crbug.com/267888. 3290f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return false; 3300f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 3310f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 3324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool WebCryptoImpl::ImportKeyInternal( 333f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) blink::WebCryptoKeyFormat format, 3344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const unsigned char* key_data, 3354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) unsigned key_data_size, 336f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const blink::WebCryptoAlgorithm& algorithm_or_null, 3371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) bool extractable, 338f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) blink::WebCryptoKeyUsageMask usage_mask, 339f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) blink::WebCryptoKey* key) { 3401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // TODO(eroman): Currently expects algorithm to always be specified, as it is 3411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // required for raw format. 3421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (algorithm_or_null.isNull()) 3431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return false; 344f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const blink::WebCryptoAlgorithm& algorithm = algorithm_or_null; 3454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // TODO(padolph): Support all relevant alg types and then remove this gate. 347f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (algorithm.id() != blink::WebCryptoAlgorithmIdHmac && 348f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) algorithm.id() != blink::WebCryptoAlgorithmIdAesCbc) { 3494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 3504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 3514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 352a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // TODO(padolph): Need to split handling for symmetric (raw format) and 353a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // asymmetric (spki or pkcs8 format) keys. 3544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Currently only supporting symmetric. 3554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Symmetric keys are always type secret 357f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) blink::WebCryptoKeyType type = blink::WebCryptoKeyTypeSecret; 3584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const unsigned char* raw_key_data; 3604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) unsigned raw_key_data_size; 3614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) switch (format) { 362f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case blink::WebCryptoKeyFormatRaw: 3634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) raw_key_data = key_data; 3644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) raw_key_data_size = key_data_size; 3651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // The NSS implementation fails when importing a raw AES key with a length 3661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // incompatible with AES. The line below is to match this behavior. 367f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (algorithm.id() == blink::WebCryptoAlgorithmIdAesCbc && 3681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) !GetAESCipherByKeyLength(raw_key_data_size)) { 3691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return false; 3701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 3714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) break; 372f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case blink::WebCryptoKeyFormatJwk: 3734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // TODO(padolph): Handle jwk format; need simple JSON parser. 3744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // break; 3754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 3764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) default: 3774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 3784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 3794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 380f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) *key = blink::WebCryptoKey::create( 3811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) new SymKeyHandle(raw_key_data, raw_key_data_size), 3821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) type, extractable, algorithm, usage_mask); 3834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return true; 3854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 3864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 387f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool WebCryptoImpl::ExportKeyInternal( 388f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) blink::WebCryptoKeyFormat format, 389f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const blink::WebCryptoKey& key, 390f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) blink::WebArrayBuffer* buffer) { 391a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) switch (format) { 392a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case blink::WebCryptoKeyFormatRaw: 393a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return ExportKeyInternalRaw(key, buffer); 394a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case blink::WebCryptoKeyFormatSpki: 395a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // TODO(padolph): Implement spki export 396a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 397a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) case blink::WebCryptoKeyFormatPkcs8: 398a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // TODO(padolph): Implement pkcs8 export 399a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 400a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) default: 401a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 402a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 403f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 404f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 405f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 4064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool WebCryptoImpl::SignInternal( 407f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const blink::WebCryptoAlgorithm& algorithm, 408f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const blink::WebCryptoKey& key, 4094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const unsigned char* data, 4104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) unsigned data_size, 411f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) blink::WebArrayBuffer* buffer) { 4124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 413f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) blink::WebArrayBuffer result; 4144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) switch (algorithm.id()) { 416f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case blink::WebCryptoAlgorithmIdHmac: { 4174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 418f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK_EQ(key.algorithm().id(), blink::WebCryptoAlgorithmIdHmac); 419f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK_NE(0, key.usages() & blink::WebCryptoKeyUsageSign); 4204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 421f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const blink::WebCryptoHmacParams* const params = algorithm.hmacParams(); 4224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!params) 4234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 4244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const EVP_MD* evp_sha = 0; 4264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) unsigned int hmac_expected_length = 0; 4274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Note that HMAC length is determined by the hash used. 4284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) switch (params->hash().id()) { 429f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case blink::WebCryptoAlgorithmIdSha1: 4304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) evp_sha = EVP_sha1(); 4314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) hmac_expected_length = SHA_DIGEST_LENGTH; 4324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) break; 433f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case blink::WebCryptoAlgorithmIdSha224: 4344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) evp_sha = EVP_sha224(); 4354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) hmac_expected_length = SHA224_DIGEST_LENGTH; 4364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) break; 437f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case blink::WebCryptoAlgorithmIdSha256: 4384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) evp_sha = EVP_sha256(); 4394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) hmac_expected_length = SHA256_DIGEST_LENGTH; 4404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) break; 441f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case blink::WebCryptoAlgorithmIdSha384: 4424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) evp_sha = EVP_sha384(); 4434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) hmac_expected_length = SHA384_DIGEST_LENGTH; 4444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) break; 445f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case blink::WebCryptoAlgorithmIdSha512: 4464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) evp_sha = EVP_sha512(); 4474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) hmac_expected_length = SHA512_DIGEST_LENGTH; 4484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) break; 4494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) default: 4504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Not a digest algorithm. 4514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 4524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 4534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SymKeyHandle* const sym_key = 4554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) reinterpret_cast<SymKeyHandle*>(key.handle()); 4564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const std::vector<unsigned char>& raw_key = sym_key->key(); 4574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // OpenSSL wierdness here. 4594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // First, HMAC() needs a void* for the key data, so make one up front as a 4604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // cosmetic to avoid a cast. Second, OpenSSL does not like a NULL key, 4614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // which will result if the raw_key vector is empty; an entirely valid 4624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // case. Handle this specific case by pointing to an empty array. 4634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const unsigned char null_key[] = {}; 4644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const void* const raw_key_voidp = raw_key.size() ? &raw_key[0] : null_key; 4654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 466f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) result = blink::WebArrayBuffer::create(hmac_expected_length, 1); 4674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) crypto::ScopedOpenSSLSafeSizeBuffer<EVP_MAX_MD_SIZE> hmac_result( 4684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) reinterpret_cast<unsigned char*>(result.data()), 4694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) hmac_expected_length); 4704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) crypto::OpenSSLErrStackTracer(FROM_HERE); 4724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) unsigned int hmac_actual_length; 4744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) unsigned char* const success = HMAC(evp_sha, 4754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) raw_key_voidp, 4764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) raw_key.size(), 4774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) data, 4784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) data_size, 4794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) hmac_result.safe_buffer(), 4804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) &hmac_actual_length); 4814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!success || hmac_actual_length != hmac_expected_length) 4824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 4834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) break; 4854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 4864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) default: 4874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 4884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 4894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *buffer = result; 4914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return true; 4924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 4934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 4944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool WebCryptoImpl::VerifySignatureInternal( 495f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const blink::WebCryptoAlgorithm& algorithm, 496f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const blink::WebCryptoKey& key, 4974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const unsigned char* signature, 4984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) unsigned signature_size, 4994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const unsigned char* data, 5004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) unsigned data_size, 5014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool* signature_match) { 5024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) switch (algorithm.id()) { 503f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) case blink::WebCryptoAlgorithmIdHmac: { 504f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) blink::WebArrayBuffer result; 5054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!SignInternal(algorithm, key, data, data_size, &result)) { 5064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 5074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 5084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 5094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Handling of truncated signatures is underspecified in the WebCrypto 5104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // spec, so here we fail verification if a truncated signature is being 5114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // verified. 5124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // See https://www.w3.org/Bugs/Public/show_bug.cgi?id=23097 5134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *signature_match = 5144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) result.byteLength() == signature_size && 5154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) crypto::SecureMemEqual(result.data(), signature, signature_size); 5164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 5174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) break; 5184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 5194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) default: 5204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 5214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 5224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return true; 5234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 5244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 525a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool WebCryptoImpl::ImportRsaPublicKeyInternal( 526a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const unsigned char* modulus_data, 527a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) unsigned modulus_size, 528a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const unsigned char* exponent_data, 529a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) unsigned exponent_size, 530a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const blink::WebCryptoAlgorithm& algorithm, 531a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool extractable, 532a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) blink::WebCryptoKeyUsageMask usage_mask, 533a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) blink::WebCryptoKey* key) { 534a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // TODO(padolph): Placeholder for OpenSSL implementation. 535a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Issue http://crbug.com/267888. 536a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return false; 537a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 538a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 5394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} // namespace content 540