| 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 |