11320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Copyright 2014 The Chromium Authors. All rights reserved. 21320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Use of this source code is governed by a BSD-style license that can be 31320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// found in the LICENSE file. 41320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <openssl/aes.h> 61320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <openssl/evp.h> 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/logging.h" 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/macros.h" 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/numerics/safe_math.h" 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/stl_util.h" 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/child/webcrypto/crypto_data.h" 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/child/webcrypto/openssl/aes_key_openssl.h" 141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/child/webcrypto/openssl/key_openssl.h" 151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/child/webcrypto/openssl/util_openssl.h" 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/child/webcrypto/status.h" 171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/child/webcrypto/webcrypto_util.h" 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "crypto/openssl_util.h" 191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "crypto/scoped_openssl_types.h" 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" 211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace content { 231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace webcrypto { 251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace { 271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst EVP_CIPHER* GetAESCipherByKeyLength(unsigned int key_length_bytes) { 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // BoringSSL does not support 192-bit AES keys. 301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci switch (key_length_bytes) { 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci case 16: 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return EVP_aes_128_ctr(); 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci case 32: 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return EVP_aes_256_ctr(); 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci default: 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return NULL; 371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Encrypts/decrypts given a 128-bit counter. 411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// |output| must be a pointer to a buffer which has a length of at least 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// |input.byte_length()|. 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciStatus AesCtrEncrypt128BitCounter(const EVP_CIPHER* cipher, 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const CryptoData& raw_key, 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const CryptoData& input, 471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const CryptoData& counter, 481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci uint8_t* output) { 491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(cipher); 501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_EQ(16u, counter.byte_length()); 511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci crypto::ScopedOpenSSL<EVP_CIPHER_CTX, EVP_CIPHER_CTX_free>::Type context( 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EVP_CIPHER_CTX_new()); 551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!context.get()) 571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return Status::OperationError(); 581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!EVP_CipherInit_ex(context.get(), 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci cipher, 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci NULL, 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci raw_key.bytes(), 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci counter.bytes(), 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ENCRYPT)) { 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return Status::OperationError(); 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int output_len = 0; 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!EVP_CipherUpdate(context.get(), 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci output, 711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci &output_len, 721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci input.bytes(), 731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci input.byte_length())) { 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return Status::OperationError(); 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int final_output_chunk_len = 0; 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!EVP_CipherFinal_ex( 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci context.get(), output + output_len, &final_output_chunk_len)) { 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return Status::OperationError(); 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci output_len += final_output_chunk_len; 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (static_cast<unsigned int>(output_len) != input.byte_length()) 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return Status::ErrorUnexpected(); 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return Status::Success(); 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Returns ceil(a/b), where a and b are integers. 901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccitemplate <typename T> 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciT CeilDiv(T a, T b) { 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return a == 0 ? 0 : 1 + (a - 1) / b; 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Extracts the counter as a BIGNUM. The counter is the rightmost 961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// "counter_length_bits" of the block, interpreted as a big-endian number. 971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccicrypto::ScopedBIGNUM GetCounter(const CryptoData& counter_block, 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci unsigned int counter_length_bits) { 991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci unsigned int counter_length_remainder_bits = (counter_length_bits % 8); 1001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If the counter is a multiple of 8 bits then can call BN_bin2bn() directly. 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (counter_length_remainder_bits == 0) { 1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci unsigned int byte_length = counter_length_bits / 8; 1041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return crypto::ScopedBIGNUM(BN_bin2bn( 1051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci counter_block.bytes() + counter_block.byte_length() - byte_length, 1061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci byte_length, 1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci NULL)); 1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Otherwise make a copy of the counter and zero out the topmost bits so 1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // BN_bin2bn() can be called with a byte stream. 1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci unsigned int byte_length = CeilDiv(counter_length_bits, 8u); 1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::vector<uint8_t> counter( 1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci counter_block.bytes() + counter_block.byte_length() - byte_length, 1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci counter_block.bytes() + counter_block.byte_length()); 1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci counter[0] &= ~(0xFF << counter_length_remainder_bits); 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return crypto::ScopedBIGNUM( 1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BN_bin2bn(&counter.front(), counter.size(), NULL)); 1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Returns a counter block with the counter bits all set all zero. 1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistd::vector<uint8_t> BlockWithZeroedCounter(const CryptoData& counter_block, 1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci unsigned int counter_length_bits) { 1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci unsigned int counter_length_bytes = counter_length_bits / 8; 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci unsigned int counter_length_bits_remainder = counter_length_bits % 8; 1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::vector<uint8_t> new_counter_block( 1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci counter_block.bytes(), 1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci counter_block.bytes() + counter_block.byte_length()); 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci unsigned int index = new_counter_block.size() - counter_length_bytes; 1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci memset(&new_counter_block.front() + index, 0, counter_length_bytes); 1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (counter_length_bits_remainder) { 1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci new_counter_block[index - 1] &= 0xFF << counter_length_bits_remainder; 1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return new_counter_block; 1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// This function does encryption/decryption for AES-CTR (encryption and 1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// decryption are the same). 1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// 1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// BoringSSL's interface for AES-CTR differs from that of WebCrypto. In 1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// WebCrypto the caller specifies a 16-byte counter block and designates how 1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// many of the right-most X bits to use as a big-endian counter. Whereas in 1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// BoringSSL the entire counter block is interpreted as a 128-bit counter. 1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// 1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// In AES-CTR, the counter block MUST be unique across all messages that are 1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// encrypted/decrypted. WebCrypto expects that the counter can start at any 1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// value, and is therefore permitted to wrap around to zero on overflow. 1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// 1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Some care is taken to fail if the counter wraps back to an earlier value. 1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// However this protection is only enforced during a *single* call to 1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// encrypt/decrypt. 1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciStatus AesCtrEncryptDecrypt(const blink::WebCryptoAlgorithm& algorithm, 1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const blink::WebCryptoKey& key, 1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const CryptoData& data, 1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::vector<uint8_t>* buffer) { 1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const blink::WebCryptoAesCtrParams* params = algorithm.aesCtrParams(); 1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const std::vector<uint8_t>& raw_key = 1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SymKeyOpenSsl::Cast(key)->raw_key_data(); 1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (params->counter().size() != 16) 1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return Status::ErrorIncorrectSizeAesCtrCounter(); 1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci unsigned int counter_length_bits = params->lengthBits(); 1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (counter_length_bits < 1 || counter_length_bits > 128) 1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return Status::ErrorInvalidAesCtrCounterLength(); 1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The output of AES-CTR is the same size as the input. However BoringSSL 1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // expects buffer sizes as an "int". 1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci base::CheckedNumeric<int> output_max_len = data.byte_length(); 1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!output_max_len.IsValid()) 1761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return Status::ErrorDataTooLarge(); 1771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const EVP_CIPHER* const cipher = GetAESCipherByKeyLength(raw_key.size()); 1791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!cipher) 1801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return Status::ErrorUnexpected(); 1811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const CryptoData counter_block(params->counter()); 1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci buffer->resize(output_max_len.ValueOrDie()); 1841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The total number of possible counter values is pow(2, counter_length_bits) 1861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci crypto::ScopedBIGNUM num_counter_values(BN_new()); 1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!BN_lshift(num_counter_values.get(), BN_value_one(), counter_length_bits)) 1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return Status::ErrorUnexpected(); 1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci crypto::ScopedBIGNUM current_counter = 1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GetCounter(counter_block, counter_length_bits); 1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The number of AES blocks needed for encryption/decryption. The counter is 1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // incremented this many times. 1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci crypto::ScopedBIGNUM num_output_blocks(BN_new()); 1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!BN_set_word( 1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci num_output_blocks.get(), 1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CeilDiv(buffer->size(), static_cast<size_t>(AES_BLOCK_SIZE)))) { 1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return Status::ErrorUnexpected(); 2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If the counter is going to be incremented more times than there are counter 2031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // values, fail. (Repeating values of the counter block is bad). 2041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (BN_cmp(num_output_blocks.get(), num_counter_values.get()) > 0) 2051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return Status::ErrorAesCtrInputTooLongCounterRepeated(); 2061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // This is the number of blocks that can be successfully encrypted without 2081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // overflowing the counter. Encrypting the subsequent block will need to 2091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // reset the counter to zero. 2101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci crypto::ScopedBIGNUM num_blocks_until_reset(BN_new()); 2111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!BN_sub(num_blocks_until_reset.get(), 2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci num_counter_values.get(), 2141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci current_counter.get())) { 2151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return Status::ErrorUnexpected(); 2161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If the counter can be incremented for the entire input without 2191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // wrapping-around, do it as a single call into BoringSSL. 2201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (BN_cmp(num_blocks_until_reset.get(), num_output_blocks.get()) >= 0) { 2211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return AesCtrEncrypt128BitCounter(cipher, 2221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CryptoData(raw_key), 2231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci data, 2241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci counter_block, 2251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci vector_as_array(buffer)); 2261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Otherwise the encryption needs to be done in 2 parts. The first part using 2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // the current counter_block, and the next part resetting the counter portion 2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // of the block to zero. 2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // This is guaranteed to fit in an "unsigned int" because input size in bytes 2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // fits in an "unsigned int". 2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BN_ULONG num_blocks_part1 = BN_get_word(num_blocks_until_reset.get()); 2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BN_ULONG input_size_part1 = num_blocks_part1 * AES_BLOCK_SIZE; 2361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_LT(input_size_part1, data.byte_length()); 2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Encrypt the first part (before wrap-around). 2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Status status = 2401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AesCtrEncrypt128BitCounter(cipher, 2411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CryptoData(raw_key), 2421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CryptoData(data.bytes(), input_size_part1), 2431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci counter_block, 2441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci vector_as_array(buffer)); 2451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (status.IsError()) 2461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return status; 2471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Encrypt the second part (after wrap-around). 2491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::vector<uint8_t> counter_block_part2 = 2501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BlockWithZeroedCounter(counter_block, counter_length_bits); 2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return AesCtrEncrypt128BitCounter( 2531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci cipher, 2541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CryptoData(raw_key), 2551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CryptoData(data.bytes() + input_size_part1, 2561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci data.byte_length() - input_size_part1), 2571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CryptoData(counter_block_part2), 2581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci vector_as_array(buffer) + input_size_part1); 2591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciclass AesCtrImplementation : public AesAlgorithm { 2621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci public: 2631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AesCtrImplementation() : AesAlgorithm("CTR") {} 2641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual Status Encrypt(const blink::WebCryptoAlgorithm& algorithm, 2661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const blink::WebCryptoKey& key, 2671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const CryptoData& data, 2681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::vector<uint8_t>* buffer) const OVERRIDE { 2691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return AesCtrEncryptDecrypt(algorithm, key, data, buffer); 2701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci virtual Status Decrypt(const blink::WebCryptoAlgorithm& algorithm, 2731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const blink::WebCryptoKey& key, 2741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const CryptoData& data, 2751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::vector<uint8_t>* buffer) const OVERRIDE { 2761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return AesCtrEncryptDecrypt(algorithm, key, data, buffer); 2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}; 2791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} // namespace 2811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciAlgorithmImplementation* CreatePlatformAesCtrImplementation() { 2831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return new AesCtrImplementation; 2841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} // namespace webcrypto 2871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} // namespace content 289