OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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/platform_crypto.h" | 5 #include "content/renderer/webcrypto/platform_crypto.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 #include <openssl/aes.h> | 8 #include <openssl/aes.h> |
9 #include <openssl/evp.h> | 9 #include <openssl/evp.h> |
10 #include <openssl/hmac.h> | 10 #include <openssl/hmac.h> |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
51 return EVP_aes_128_cbc(); | 51 return EVP_aes_128_cbc(); |
52 case 24: | 52 case 24: |
53 return EVP_aes_192_cbc(); | 53 return EVP_aes_192_cbc(); |
54 case 32: | 54 case 32: |
55 return EVP_aes_256_cbc(); | 55 return EVP_aes_256_cbc(); |
56 default: | 56 default: |
57 return NULL; | 57 return NULL; |
58 } | 58 } |
59 } | 59 } |
60 | 60 |
| 61 const EVP_MD* GetDigest(blink::WebCryptoAlgorithmId id) { |
| 62 switch (id) { |
| 63 case blink::WebCryptoAlgorithmIdSha1: |
| 64 return EVP_sha1(); |
| 65 case blink::WebCryptoAlgorithmIdSha224: |
| 66 return EVP_sha224(); |
| 67 case blink::WebCryptoAlgorithmIdSha256: |
| 68 return EVP_sha256(); |
| 69 case blink::WebCryptoAlgorithmIdSha384: |
| 70 return EVP_sha384(); |
| 71 case blink::WebCryptoAlgorithmIdSha512: |
| 72 return EVP_sha512(); |
| 73 default: |
| 74 return NULL; |
| 75 } |
| 76 } |
| 77 |
61 // OpenSSL constants for EVP_CipherInit_ex(), do not change | 78 // OpenSSL constants for EVP_CipherInit_ex(), do not change |
62 enum CipherOperation { kDoDecrypt = 0, kDoEncrypt = 1 }; | 79 enum CipherOperation { kDoDecrypt = 0, kDoEncrypt = 1 }; |
63 | 80 |
64 Status AesCbcEncryptDecrypt(EncryptOrDecrypt mode, | 81 Status AesCbcEncryptDecrypt(EncryptOrDecrypt mode, |
65 SymKey* key, | 82 SymKey* key, |
66 const CryptoData& iv, | 83 const CryptoData& iv, |
67 const CryptoData& data, | 84 const CryptoData& data, |
68 blink::WebArrayBuffer* buffer) { | 85 blink::WebArrayBuffer* buffer) { |
69 CipherOperation cipher_operation = | 86 CipherOperation cipher_operation = |
70 (mode == ENCRYPT) ? kDoEncrypt : kDoDecrypt; | 87 (mode == ENCRYPT) ? kDoEncrypt : kDoDecrypt; |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
148 blink::WebArrayBuffer* buffer) { | 165 blink::WebArrayBuffer* buffer) { |
149 // TODO(eroman): inline the function here. | 166 // TODO(eroman): inline the function here. |
150 return AesCbcEncryptDecrypt(mode, key, iv, data, buffer); | 167 return AesCbcEncryptDecrypt(mode, key, iv, data, buffer); |
151 } | 168 } |
152 | 169 |
153 Status DigestSha(blink::WebCryptoAlgorithmId algorithm, | 170 Status DigestSha(blink::WebCryptoAlgorithmId algorithm, |
154 const CryptoData& data, | 171 const CryptoData& data, |
155 blink::WebArrayBuffer* buffer) { | 172 blink::WebArrayBuffer* buffer) { |
156 crypto::OpenSSLErrStackTracer(FROM_HERE); | 173 crypto::OpenSSLErrStackTracer(FROM_HERE); |
157 | 174 |
158 const EVP_MD* digest_algorithm; | 175 const EVP_MD* digest_algorithm = GetDigest(algorithm); |
159 switch (algorithm) { | 176 if (!digest_algorithm) |
160 case blink::WebCryptoAlgorithmIdSha1: | 177 return Status::ErrorUnexpected(); |
161 digest_algorithm = EVP_sha1(); | |
162 break; | |
163 case blink::WebCryptoAlgorithmIdSha224: | |
164 digest_algorithm = EVP_sha224(); | |
165 break; | |
166 case blink::WebCryptoAlgorithmIdSha256: | |
167 digest_algorithm = EVP_sha256(); | |
168 break; | |
169 case blink::WebCryptoAlgorithmIdSha384: | |
170 digest_algorithm = EVP_sha384(); | |
171 break; | |
172 case blink::WebCryptoAlgorithmIdSha512: | |
173 digest_algorithm = EVP_sha512(); | |
174 break; | |
175 default: | |
176 // Not a SHA algorithm. | |
177 return Status::ErrorUnexpected(); | |
178 } | |
179 | 178 |
180 crypto::ScopedOpenSSL<EVP_MD_CTX, EVP_MD_CTX_destroy> digest_context( | 179 crypto::ScopedOpenSSL<EVP_MD_CTX, EVP_MD_CTX_destroy> digest_context( |
181 EVP_MD_CTX_create()); | 180 EVP_MD_CTX_create()); |
182 if (!digest_context.get()) | 181 if (!digest_context.get()) |
183 return Status::Error(); | 182 return Status::Error(); |
184 | 183 |
185 if (!EVP_DigestInit_ex(digest_context.get(), digest_algorithm, NULL) || | 184 if (!EVP_DigestInit_ex(digest_context.get(), digest_algorithm, NULL) || |
186 !EVP_DigestUpdate( | 185 !EVP_DigestUpdate( |
187 digest_context.get(), data.bytes(), data.byte_length())) { | 186 digest_context.get(), data.bytes(), data.byte_length())) { |
188 return Status::Error(); | 187 return Status::Error(); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
254 | 253 |
255 return Status::Success(); | 254 return Status::Success(); |
256 } | 255 } |
257 | 256 |
258 Status SignHmac(SymKey* key, | 257 Status SignHmac(SymKey* key, |
259 const blink::WebCryptoAlgorithm& hash, | 258 const blink::WebCryptoAlgorithm& hash, |
260 const CryptoData& data, | 259 const CryptoData& data, |
261 blink::WebArrayBuffer* buffer) { | 260 blink::WebArrayBuffer* buffer) { |
262 blink::WebArrayBuffer result; | 261 blink::WebArrayBuffer result; |
263 | 262 |
264 const EVP_MD* evp_sha = 0; | 263 const EVP_MD* digest_algorithm = GetDigest(hash.id()); |
265 unsigned int hmac_expected_length = 0; | 264 if (!digest_algorithm) |
266 // Note that HMAC length is determined by the hash used. | 265 return Status::ErrorUnsupported(); |
267 switch (hash.id()) { | 266 unsigned int hmac_expected_length = EVP_MD_size(digest_algorithm); |
268 case blink::WebCryptoAlgorithmIdSha1: | |
269 evp_sha = EVP_sha1(); | |
270 hmac_expected_length = SHA_DIGEST_LENGTH; | |
271 break; | |
272 case blink::WebCryptoAlgorithmIdSha224: | |
273 evp_sha = EVP_sha224(); | |
274 hmac_expected_length = SHA224_DIGEST_LENGTH; | |
275 break; | |
276 case blink::WebCryptoAlgorithmIdSha256: | |
277 evp_sha = EVP_sha256(); | |
278 hmac_expected_length = SHA256_DIGEST_LENGTH; | |
279 break; | |
280 case blink::WebCryptoAlgorithmIdSha384: | |
281 evp_sha = EVP_sha384(); | |
282 hmac_expected_length = SHA384_DIGEST_LENGTH; | |
283 break; | |
284 case blink::WebCryptoAlgorithmIdSha512: | |
285 evp_sha = EVP_sha512(); | |
286 hmac_expected_length = SHA512_DIGEST_LENGTH; | |
287 break; | |
288 default: | |
289 // Not a digest algorithm. | |
290 return Status::ErrorUnsupported(); | |
291 } | |
292 | 267 |
293 const std::vector<unsigned char>& raw_key = key->key(); | 268 const std::vector<unsigned char>& raw_key = key->key(); |
294 | 269 |
295 // OpenSSL wierdness here. | 270 // OpenSSL wierdness here. |
296 // First, HMAC() needs a void* for the key data, so make one up front as a | 271 // First, HMAC() needs a void* for the key data, so make one up front as a |
297 // cosmetic to avoid a cast. Second, OpenSSL does not like a NULL key, | 272 // cosmetic to avoid a cast. Second, OpenSSL does not like a NULL key, |
298 // which will result if the raw_key vector is empty; an entirely valid | 273 // which will result if the raw_key vector is empty; an entirely valid |
299 // case. Handle this specific case by pointing to an empty array. | 274 // case. Handle this specific case by pointing to an empty array. |
300 const unsigned char null_key[] = {}; | 275 const unsigned char null_key[] = {}; |
301 const void* const raw_key_voidp = raw_key.size() ? &raw_key[0] : null_key; | 276 const void* const raw_key_voidp = raw_key.size() ? &raw_key[0] : null_key; |
302 | 277 |
303 result = blink::WebArrayBuffer::create(hmac_expected_length, 1); | 278 result = blink::WebArrayBuffer::create(hmac_expected_length, 1); |
304 crypto::ScopedOpenSSLSafeSizeBuffer<EVP_MAX_MD_SIZE> hmac_result( | 279 crypto::ScopedOpenSSLSafeSizeBuffer<EVP_MAX_MD_SIZE> hmac_result( |
305 reinterpret_cast<unsigned char*>(result.data()), hmac_expected_length); | 280 reinterpret_cast<unsigned char*>(result.data()), hmac_expected_length); |
306 | 281 |
307 crypto::OpenSSLErrStackTracer(FROM_HERE); | 282 crypto::OpenSSLErrStackTracer(FROM_HERE); |
308 | 283 |
309 unsigned int hmac_actual_length; | 284 unsigned int hmac_actual_length; |
310 unsigned char* const success = HMAC(evp_sha, | 285 unsigned char* const success = HMAC(digest_algorithm, |
311 raw_key_voidp, | 286 raw_key_voidp, |
312 raw_key.size(), | 287 raw_key.size(), |
313 data.bytes(), | 288 data.bytes(), |
314 data.byte_length(), | 289 data.byte_length(), |
315 hmac_result.safe_buffer(), | 290 hmac_result.safe_buffer(), |
316 &hmac_actual_length); | 291 &hmac_actual_length); |
317 if (!success || hmac_actual_length != hmac_expected_length) | 292 if (!success || hmac_actual_length != hmac_expected_length) |
318 return Status::Error(); | 293 return Status::Error(); |
319 | 294 |
320 *buffer = result; | 295 *buffer = result; |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
397 Status ExportKeySpki(PublicKey* key, blink::WebArrayBuffer* buffer) { | 372 Status ExportKeySpki(PublicKey* key, blink::WebArrayBuffer* buffer) { |
398 // TODO(eroman): http://crbug.com/267888 | 373 // TODO(eroman): http://crbug.com/267888 |
399 return Status::ErrorUnsupported(); | 374 return Status::ErrorUnsupported(); |
400 } | 375 } |
401 | 376 |
402 } // namespace platform | 377 } // namespace platform |
403 | 378 |
404 } // namespace webcrypto | 379 } // namespace webcrypto |
405 | 380 |
406 } // namespace content | 381 } // namespace content |
OLD | NEW |