OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/webcrypto_impl.h" | 5 #include "content/renderer/webcrypto_impl.h" |
6 | 6 |
7 #include <cryptohi.h> | 7 #include <cryptohi.h> |
8 #include <pk11pub.h> | 8 #include <pk11pub.h> |
9 #include <sechash.h> | 9 #include <sechash.h> |
10 | 10 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
74 if (new_size == buffer->byteLength()) | 74 if (new_size == buffer->byteLength()) |
75 return; | 75 return; |
76 | 76 |
77 WebKit::WebArrayBuffer new_buffer = | 77 WebKit::WebArrayBuffer new_buffer = |
78 WebKit::WebArrayBuffer::create(new_size, 1); | 78 WebKit::WebArrayBuffer::create(new_size, 1); |
79 CHECK(!new_buffer.isNull()); | 79 CHECK(!new_buffer.isNull()); |
80 memcpy(new_buffer.data(), buffer->data(), new_size); | 80 memcpy(new_buffer.data(), buffer->data(), new_size); |
81 *buffer = new_buffer; | 81 *buffer = new_buffer; |
82 } | 82 } |
83 | 83 |
84 } // namespace | 84 bool AesCbcEncryptDecrypt( |
85 | 85 CK_ATTRIBUTE_TYPE operation, |
86 void WebCryptoImpl::Init() { | |
87 crypto::EnsureNSSInit(); | |
88 } | |
89 | |
90 bool WebCryptoImpl::EncryptInternal( | |
91 const WebKit::WebCryptoAlgorithm& algorithm, | 86 const WebKit::WebCryptoAlgorithm& algorithm, |
92 const WebKit::WebCryptoKey& key, | 87 const WebKit::WebCryptoKey& key, |
93 const unsigned char* data, | 88 const unsigned char* data, |
94 unsigned data_size, | 89 unsigned data_size, |
95 WebKit::WebArrayBuffer* buffer) { | 90 WebKit::WebArrayBuffer* buffer) { |
96 if (algorithm.id() != WebKit::WebCryptoAlgorithmIdAesCbc) | 91 DCHECK_EQ(WebKit::WebCryptoAlgorithmIdAesCbc, algorithm.id()); |
97 return false; | |
98 | |
99 CHECK_EQ(algorithm.id(), key.algorithm().id()); | 92 CHECK_EQ(algorithm.id(), key.algorithm().id()); |
100 CHECK_EQ(WebKit::WebCryptoKeyTypeSecret, key.type()); | 93 CHECK_EQ(WebKit::WebCryptoKeyTypeSecret, key.type()); |
94 CHECK(operation == CKA_ENCRYPT || operation == CKA_DECRYPT); | |
jamesr
2013/09/25 21:29:05
why are these hard CHECKs?
eroman
2013/09/25 22:11:59
Changed to DCHECK()
| |
101 | 95 |
102 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); | 96 SymKeyHandle* sym_key = reinterpret_cast<SymKeyHandle*>(key.handle()); |
103 | 97 |
104 const WebKit::WebCryptoAesCbcParams* params = algorithm.aesCbcParams(); | 98 const WebKit::WebCryptoAesCbcParams* params = algorithm.aesCbcParams(); |
105 if (params->iv().size() != AES_BLOCK_SIZE) | 99 if (params->iv().size() != AES_BLOCK_SIZE) |
106 return false; | 100 return false; |
107 | 101 |
108 SECItem iv_item; | 102 SECItem iv_item; |
109 iv_item.type = siBuffer; | 103 iv_item.type = siBuffer; |
110 iv_item.data = const_cast<unsigned char*>(params->iv().data()); | 104 iv_item.data = const_cast<unsigned char*>(params->iv().data()); |
111 iv_item.len = params->iv().size(); | 105 iv_item.len = params->iv().size(); |
112 | 106 |
113 crypto::ScopedSECItem param(PK11_ParamFromIV(CKM_AES_CBC_PAD, &iv_item)); | 107 crypto::ScopedSECItem param(PK11_ParamFromIV(CKM_AES_CBC_PAD, &iv_item)); |
114 if (!param) | 108 if (!param) |
115 return false; | 109 return false; |
116 | 110 |
117 crypto::ScopedPK11Context context(PK11_CreateContextBySymKey( | 111 crypto::ScopedPK11Context context(PK11_CreateContextBySymKey( |
118 CKM_AES_CBC_PAD, CKA_ENCRYPT, sym_key->key(), param.get())); | 112 CKM_AES_CBC_PAD, operation, sym_key->key(), param.get())); |
119 | 113 |
120 if (!context.get()) | 114 if (!context.get()) |
121 return false; | 115 return false; |
122 | 116 |
123 // Oddly PK11_CipherOp takes input and output lenths as "int" rather than | 117 // Oddly PK11_CipherOp takes input and output lenths as "int" rather than |
124 // "unsigned". Do some checks now to avoid integer overflowing. | 118 // "unsigned". Do some checks now to avoid integer overflowing. |
125 if (data_size >= INT_MAX - AES_BLOCK_SIZE) { | 119 if (data_size >= INT_MAX - AES_BLOCK_SIZE) { |
126 // TODO(eroman): Handle this by chunking the input fed into NSS. Right now | 120 // TODO(eroman): Handle this by chunking the input fed into NSS. Right now |
127 // it doesn't make much difference since the one-shot API would end up | 121 // it doesn't make much difference since the one-shot API would end up |
128 // blowing out the memory and crashing anyway. However a newer version of | 122 // blowing out the memory and crashing anyway. However a newer version of |
129 // the spec allows for a sequence<CryptoData> so this will be relevant. | 123 // the spec allows for a sequence<CryptoData> so this will be relevant. |
130 return false; | 124 return false; |
131 } | 125 } |
132 | 126 |
127 // TODO(eroman): Refine the output buffer size. It can be computed exactly for | |
128 // encryption, and can be smaller for decryption. | |
133 unsigned output_max_len = data_size + AES_BLOCK_SIZE; | 129 unsigned output_max_len = data_size + AES_BLOCK_SIZE; |
134 CHECK_GT(output_max_len, data_size); | 130 CHECK_GT(output_max_len, data_size); |
135 | 131 |
136 *buffer = WebKit::WebArrayBuffer::create(output_max_len, 1); | 132 *buffer = WebKit::WebArrayBuffer::create(output_max_len, 1); |
137 | 133 |
138 unsigned char* buffer_data = reinterpret_cast<unsigned char*>(buffer->data()); | 134 unsigned char* buffer_data = reinterpret_cast<unsigned char*>(buffer->data()); |
139 | 135 |
140 int output_len; | 136 int output_len; |
141 if (SECSuccess != PK11_CipherOp(context.get(), | 137 if (SECSuccess != PK11_CipherOp(context.get(), |
142 buffer_data, | 138 buffer_data, |
143 &output_len, | 139 &output_len, |
144 buffer->byteLength(), | 140 buffer->byteLength(), |
145 data, | 141 data, |
146 data_size)) { | 142 data_size)) { |
147 return false; | 143 return false; |
148 } | 144 } |
149 | 145 |
150 unsigned int final_output_chunk_len; | 146 unsigned int final_output_chunk_len; |
151 if (SECSuccess != PK11_DigestFinal(context.get(), | 147 if (SECSuccess != PK11_DigestFinal(context.get(), |
152 buffer_data + output_len, | 148 buffer_data + output_len, |
153 &final_output_chunk_len, | 149 &final_output_chunk_len, |
154 output_max_len - output_len)) { | 150 output_max_len - output_len)) { |
155 return false; | 151 return false; |
156 } | 152 } |
157 | 153 |
158 ShrinkBuffer(buffer, final_output_chunk_len + output_len); | 154 ShrinkBuffer(buffer, final_output_chunk_len + output_len); |
159 return true; | 155 return true; |
160 } | 156 } |
161 | 157 |
158 } // namespace | |
159 | |
160 void WebCryptoImpl::Init() { | |
161 crypto::EnsureNSSInit(); | |
162 } | |
163 | |
164 bool WebCryptoImpl::EncryptInternal( | |
165 const WebKit::WebCryptoAlgorithm& algorithm, | |
166 const WebKit::WebCryptoKey& key, | |
167 const unsigned char* data, | |
168 unsigned data_size, | |
169 WebKit::WebArrayBuffer* buffer) { | |
170 if (algorithm.id() == WebKit::WebCryptoAlgorithmIdAesCbc) { | |
171 return AesCbcEncryptDecrypt( | |
172 CKA_ENCRYPT, algorithm, key, data, data_size, buffer); | |
173 } | |
174 | |
175 return false; | |
176 } | |
177 | |
178 bool WebCryptoImpl::DecryptInternal( | |
179 const WebKit::WebCryptoAlgorithm& algorithm, | |
180 const WebKit::WebCryptoKey& key, | |
181 const unsigned char* data, | |
182 unsigned data_size, | |
183 WebKit::WebArrayBuffer* buffer) { | |
184 if (algorithm.id() == WebKit::WebCryptoAlgorithmIdAesCbc) { | |
185 return AesCbcEncryptDecrypt( | |
186 CKA_DECRYPT, algorithm, key, data, data_size, buffer); | |
187 } | |
188 | |
189 return false; | |
190 } | |
191 | |
162 bool WebCryptoImpl::DigestInternal( | 192 bool WebCryptoImpl::DigestInternal( |
163 const WebKit::WebCryptoAlgorithm& algorithm, | 193 const WebKit::WebCryptoAlgorithm& algorithm, |
164 const unsigned char* data, | 194 const unsigned char* data, |
165 unsigned data_size, | 195 unsigned data_size, |
166 WebKit::WebArrayBuffer* buffer) { | 196 WebKit::WebArrayBuffer* buffer) { |
167 HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm); | 197 HASH_HashType hash_type = WebCryptoAlgorithmToNSSHashType(algorithm); |
168 if (hash_type == HASH_AlgNULL) { | 198 if (hash_type == HASH_AlgNULL) { |
169 return false; | 199 return false; |
170 } | 200 } |
171 | 201 |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
337 } | 367 } |
338 default: | 368 default: |
339 return false; | 369 return false; |
340 } | 370 } |
341 | 371 |
342 *buffer = result; | 372 *buffer = result; |
343 return true; | 373 return true; |
344 } | 374 } |
345 | 375 |
346 } // namespace content | 376 } // namespace content |
OLD | NEW |