Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(584)

Side by Side Diff: content/child/webcrypto/openssl/aes_cbc_openssl.cc

Issue 379383002: Refactor WebCrypto code (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase onto master (no longer has BoringSSL) Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <openssl/aes.h>
6 #include <openssl/evp.h>
7
8 #include "base/logging.h"
9 #include "content/child/webcrypto/crypto_data.h"
10 #include "content/child/webcrypto/openssl/aes_key_openssl.h"
11 #include "content/child/webcrypto/openssl/key_openssl.h"
12 #include "content/child/webcrypto/status.h"
13 #include "content/child/webcrypto/webcrypto_util.h"
14 #include "crypto/scoped_openssl_types.h"
15 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
16
17 namespace content {
18
19 namespace webcrypto {
20
21 namespace {
22
23 const EVP_CIPHER* GetAESCipherByKeyLength(unsigned int key_length_bytes) {
24 // BoringSSL does not support 192-bit AES keys.
25 switch (key_length_bytes) {
26 case 16:
27 return EVP_aes_128_cbc();
28 case 32:
29 return EVP_aes_256_cbc();
30 default:
31 return NULL;
32 }
33 }
34
35 // OpenSSL constants for EVP_CipherInit_ex(), do not change
36 enum CipherOperation { kDoDecrypt = 0, kDoEncrypt = 1 };
37
38 Status AesCbcEncryptDecrypt(CipherOperation cipher_operation,
39 const blink::WebCryptoAlgorithm& algorithm,
40 const blink::WebCryptoKey& key,
41 const CryptoData& data,
42 std::vector<uint8>* buffer) {
43 const blink::WebCryptoAesCbcParams* params = algorithm.aesCbcParams();
44 const std::vector<uint8>& raw_key = SymKeyOpenSsl::Cast(key)->raw_key_data();
45
46 if (params->iv().size() != 16)
47 return Status::ErrorIncorrectSizeAesCbcIv();
48
49 if (data.byte_length() >= INT_MAX - AES_BLOCK_SIZE) {
50 // TODO(padolph): Handle this by chunking the input fed into OpenSSL. Right
51 // now it doesn't make much difference since the one-shot API would end up
52 // blowing out the memory and crashing anyway.
53 return Status::ErrorDataTooLarge();
54 }
55
56 // Note: PKCS padding is enabled by default
57 crypto::ScopedOpenSSL<EVP_CIPHER_CTX, EVP_CIPHER_CTX_free>::Type context(
58 EVP_CIPHER_CTX_new());
59
60 if (!context.get())
61 return Status::OperationError();
62
63 const EVP_CIPHER* const cipher = GetAESCipherByKeyLength(raw_key.size());
64 DCHECK(cipher);
65
66 if (!EVP_CipherInit_ex(context.get(),
67 cipher,
68 NULL,
69 &raw_key[0],
70 params->iv().data(),
71 cipher_operation)) {
72 return Status::OperationError();
73 }
74
75 // According to the openssl docs, the amount of data written may be as large
76 // as (data_size + cipher_block_size - 1), constrained to a multiple of
77 // cipher_block_size.
78 unsigned int output_max_len = data.byte_length() + AES_BLOCK_SIZE - 1;
79 const unsigned remainder = output_max_len % AES_BLOCK_SIZE;
80 if (remainder != 0)
81 output_max_len += AES_BLOCK_SIZE - remainder;
82 DCHECK_GT(output_max_len, data.byte_length());
83
84 buffer->resize(output_max_len);
85
86 unsigned char* const buffer_data = Uint8VectorStart(buffer);
87
88 int output_len = 0;
89 if (!EVP_CipherUpdate(context.get(),
90 buffer_data,
91 &output_len,
92 data.bytes(),
93 data.byte_length()))
94 return Status::OperationError();
95 int final_output_chunk_len = 0;
96 if (!EVP_CipherFinal_ex(
97 context.get(), buffer_data + output_len, &final_output_chunk_len)) {
98 return Status::OperationError();
99 }
100
101 const unsigned int final_output_len =
102 static_cast<unsigned int>(output_len) +
103 static_cast<unsigned int>(final_output_chunk_len);
104 DCHECK_LE(final_output_len, output_max_len);
105
106 buffer->resize(final_output_len);
107
108 return Status::Success();
109 }
110
111 class AesCbcImplementation : public AesAlgorithm {
112 public:
113 AesCbcImplementation() : AesAlgorithm("CBC") {}
114
115 virtual Status Encrypt(const blink::WebCryptoAlgorithm& algorithm,
116 const blink::WebCryptoKey& key,
117 const CryptoData& data,
118 std::vector<uint8>* buffer) const OVERRIDE {
119 return AesCbcEncryptDecrypt(kDoEncrypt, algorithm, key, data, buffer);
120 }
121
122 virtual Status Decrypt(const blink::WebCryptoAlgorithm& algorithm,
123 const blink::WebCryptoKey& key,
124 const CryptoData& data,
125 std::vector<uint8>* buffer) const OVERRIDE {
126 return AesCbcEncryptDecrypt(kDoDecrypt, algorithm, key, data, buffer);
127 }
128 };
129
130 } // namespace
131
132 AlgorithmImplementation* CreatePlatformAesCbcImplementation() {
133 return new AesCbcImplementation;
134 }
135
136 } // namespace webcrypto
137
138 } // namespace content
OLDNEW
« no previous file with comments | « content/child/webcrypto/nss/util_nss.cc ('k') | content/child/webcrypto/openssl/aes_gcm_openssl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698