Chromium Code Reviews| 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 <vector> | |
|
eroman
2013/09/25 00:00:59
style nit: probably need to sort this after <opens
padolph
2013/09/25 02:00:38
I followed the include header ordering recommendat
eroman
2013/09/27 00:15:52
My mistake then!
| |
| 8 #include <openssl/hmac.h> | |
| 9 #include <openssl/sha.h> | |
| 10 | |
| 11 #include "base/logging.h" | |
| 12 #include "crypto/openssl_util.h" | |
| 13 #include "third_party/WebKit/public/platform/WebArrayBuffer.h" | |
| 14 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" | |
| 15 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" | |
| 16 | |
| 7 namespace content { | 17 namespace content { |
| 8 | 18 |
| 9 void WebCryptoImpl::Init() { | 19 namespace { |
| 10 } | |
| 11 | 20 |
| 12 bool WebCryptoImpl::DigestInternal( | 21 class SymKeyHandle : public WebKit::WebCryptoKeyHandle { |
| 13 const WebKit::WebCryptoAlgorithm& algorithm, | 22 public: |
| 14 const unsigned char* data, | 23 explicit SymKeyHandle(const unsigned char* key_data, unsigned key_data_size) |
|
eroman
2013/09/25 00:00:59
style nit: can remove "explicit"
padolph
2013/09/25 02:00:38
Done.
| |
| 15 unsigned data_size, | 24 : key_(key_data, key_data + key_data_size) {} |
| 16 WebKit::WebArrayBuffer* buffer) { | 25 |
| 17 // TODO(bryaneyler): Placeholder for OpenSSL implementation. | 26 const std::vector<unsigned char>& key() const { return key_; } |
| 27 | |
| 28 private: | |
| 29 const std::vector<unsigned char> key_; | |
| 30 | |
| 31 DISALLOW_COPY_AND_ASSIGN(SymKeyHandle); | |
| 32 }; | |
| 33 | |
| 34 } // anonymous namespace | |
| 35 | |
| 36 void WebCryptoImpl::Init() { crypto::EnsureOpenSSLInit(); } | |
| 37 | |
| 38 bool WebCryptoImpl::DigestInternal(const WebKit::WebCryptoAlgorithm& algorithm, | |
| 39 const unsigned char* data, | |
| 40 unsigned data_size, | |
| 41 WebKit::WebArrayBuffer* buffer) { | |
| 42 // TODO(padolph): Placeholder for OpenSSL implementation. | |
| 18 // Issue http://crbug.com/267888. | 43 // Issue http://crbug.com/267888. |
| 19 return false; | 44 return false; |
| 20 } | 45 } |
| 21 | 46 |
| 22 bool WebCryptoImpl::ImportKeyInternal( | 47 bool WebCryptoImpl::ImportKeyInternal( |
| 23 WebKit::WebCryptoKeyFormat format, | 48 WebKit::WebCryptoKeyFormat format, |
| 24 const unsigned char* key_data, | 49 const unsigned char* key_data, |
| 25 unsigned key_data_size, | 50 unsigned key_data_size, |
| 26 const WebKit::WebCryptoAlgorithm& algorithm, | 51 const WebKit::WebCryptoAlgorithm& algorithm, |
| 27 WebKit::WebCryptoKeyUsageMask usage_mask, | 52 WebKit::WebCryptoKeyUsageMask /*usage_mask*/, |
| 28 scoped_ptr<WebKit::WebCryptoKeyHandle>* handle, | 53 scoped_ptr<WebKit::WebCryptoKeyHandle>* handle, |
| 29 WebKit::WebCryptoKeyType* type) { | 54 WebKit::WebCryptoKeyType* type) { |
| 30 // TODO(bryaneyler): Placeholder for OpenSSL implementation. | 55 |
| 31 // Issue http://crbug.com/267888. | 56 // TODO(padolph): Support all relevant alg types and then remove this gate. |
| 32 return false; | 57 if (algorithm.id() != WebKit::WebCryptoAlgorithmIdHmac && |
| 58 algorithm.id() != WebKit::WebCryptoAlgorithmIdAesCbc) { | |
| 59 return false; | |
| 60 } | |
| 61 | |
| 62 // TODO(padolph): Need to split handling for symmetric (raw or jwk format) and | |
| 63 // asymmetric (jwk, spki, or pkcs8 format) keys. | |
| 64 // Currently only supporting symmetric. | |
| 65 | |
| 66 // TODO(padolph): jwk handling. Define precedence between jwk contents and | |
| 67 // this method's parameters, e.g. 'alg' in jwk vs algorithm.id(). Who wins if | |
| 68 // they differ? (jwk, probably) | |
| 69 | |
| 70 // Symmetric keys are always type secret | |
| 71 *type = WebKit::WebCryptoKeyTypeSecret; | |
| 72 | |
| 73 const unsigned char* raw_key_data; | |
| 74 unsigned raw_key_data_size; | |
| 75 switch (format) { | |
| 76 case WebKit::WebCryptoKeyFormatRaw: | |
| 77 raw_key_data = key_data; | |
| 78 raw_key_data_size = key_data_size; | |
| 79 break; | |
| 80 case WebKit::WebCryptoKeyFormatJwk: | |
| 81 // TODO(padolph): Handle jwk format; need simple JSON parser. | |
| 82 // break; | |
| 83 return false; | |
| 84 default: | |
| 85 return false; | |
| 86 } | |
| 87 | |
| 88 scoped_ptr<SymKeyHandle> sym_key( | |
| 89 new SymKeyHandle(raw_key_data, raw_key_data_size)); | |
| 90 *handle = sym_key.Pass(); | |
|
eroman
2013/09/25 00:00:59
style nit: You could get rid of the sym_key tempor
padolph
2013/09/25 02:00:38
Done.
| |
| 91 | |
| 92 return true; | |
| 33 } | 93 } |
| 34 | 94 |
| 35 bool WebCryptoImpl::SignInternal( | 95 bool WebCryptoImpl::SignInternal(const WebKit::WebCryptoAlgorithm& algorithm, |
| 36 const WebKit::WebCryptoAlgorithm& algorithm, | 96 const WebKit::WebCryptoKey& key, |
| 37 const WebKit::WebCryptoKey& key, | 97 const unsigned char* data, |
| 38 const unsigned char* data, | 98 unsigned data_size, |
| 39 unsigned data_size, | 99 WebKit::WebArrayBuffer* buffer) { |
| 40 WebKit::WebArrayBuffer* buffer) { | 100 |
| 41 // TODO(bryaneyler): Placeholder for OpenSSL implementation. | 101 WebKit::WebArrayBuffer result; |
| 42 // Issue http://crbug.com/267888. | 102 |
| 43 return false; | 103 switch (algorithm.id()) { |
| 104 case WebKit::WebCryptoAlgorithmIdHmac: { | |
| 105 | |
| 106 DCHECK(key.algorithm().id() == WebKit::WebCryptoAlgorithmIdHmac); | |
|
eroman
2013/09/25 00:00:59
style nit: You can use DCHECK_EQ() in this case (g
padolph
2013/09/25 02:00:38
Done.
| |
| 107 DCHECK_NE(0, key.usages() & WebKit::WebCryptoKeyUsageSign); | |
| 108 | |
| 109 const WebKit::WebCryptoHmacParams* const params = algorithm.hmacParams(); | |
| 110 if (!params) | |
| 111 return false; | |
| 112 | |
| 113 const EVP_MD* evp_sha = 0; | |
| 114 unsigned int hmac_expected_length = 0; | |
| 115 // Note that HMAC length is determined by the hash used. | |
| 116 switch (params->hash().id()) { | |
| 117 case WebKit::WebCryptoAlgorithmIdSha1: | |
| 118 evp_sha = EVP_sha1(); | |
| 119 hmac_expected_length = SHA_DIGEST_LENGTH; | |
| 120 break; | |
| 121 case WebKit::WebCryptoAlgorithmIdSha224: | |
| 122 evp_sha = EVP_sha224(); | |
| 123 hmac_expected_length = SHA224_DIGEST_LENGTH; | |
| 124 break; | |
| 125 case WebKit::WebCryptoAlgorithmIdSha256: | |
| 126 evp_sha = EVP_sha256(); | |
| 127 hmac_expected_length = SHA256_DIGEST_LENGTH; | |
| 128 break; | |
| 129 case WebKit::WebCryptoAlgorithmIdSha384: | |
| 130 evp_sha = EVP_sha384(); | |
| 131 hmac_expected_length = SHA384_DIGEST_LENGTH; | |
| 132 break; | |
| 133 case WebKit::WebCryptoAlgorithmIdSha512: | |
| 134 evp_sha = EVP_sha512(); | |
| 135 hmac_expected_length = SHA512_DIGEST_LENGTH; | |
| 136 break; | |
| 137 default: | |
| 138 // Not a digest algorithm. | |
| 139 return false; | |
| 140 } | |
| 141 | |
| 142 SymKeyHandle* const sym_key = | |
| 143 reinterpret_cast<SymKeyHandle*>(key.handle()); | |
| 144 const std::vector<unsigned char>& raw_key = sym_key->key(); | |
| 145 | |
| 146 // OpenSSL wierdness here. | |
| 147 // First, HMAC() needs a void* for the key data, so make one up front as a | |
| 148 // cosmetic to avoid a cast. Second, OpenSSL does not like a NULL key, | |
| 149 // which will result if the raw_key vector is empty; an entirely valid | |
|
eroman
2013/09/25 00:00:59
Is a 0-byte key a supported use-case? On the NSS s
padolph
2013/09/25 02:00:38
Done.
padolph
2013/09/25 02:00:38
This code is required to pass Bryan's "Empty Sets"
| |
| 150 // case. Handle this specific case by pointing to an empty array. | |
| 151 const unsigned char null_key[] = {}; | |
| 152 const void* const raw_key_voidp = raw_key.size() ? &raw_key[0] : null_key; | |
| 153 | |
| 154 result = WebKit::WebArrayBuffer::create(hmac_expected_length, 1); | |
| 155 crypto::ScopedOpenSSLSafeSizeBuffer<EVP_MAX_MD_SIZE> hmac_result( | |
| 156 reinterpret_cast<unsigned char*>(result.data()), | |
| 157 hmac_expected_length); | |
| 158 | |
| 159 crypto::OpenSSLErrStackTracer(FROM_HERE); | |
| 160 | |
| 161 unsigned int hmac_actual_length; | |
| 162 unsigned char* const success = HMAC(evp_sha, | |
| 163 raw_key_voidp, | |
| 164 raw_key.size(), | |
| 165 data, | |
| 166 data_size, | |
| 167 hmac_result.safe_buffer(), | |
| 168 &hmac_actual_length); | |
| 169 if (!success || hmac_actual_length != hmac_expected_length) | |
| 170 return false; | |
| 171 | |
| 172 break; | |
| 173 } | |
| 174 default: | |
| 175 return false; | |
| 176 } | |
| 177 | |
| 178 *buffer = result; | |
| 179 return true; | |
| 44 } | 180 } |
| 45 | 181 |
| 46 } // namespace content | 182 } // namespace content |
| OLD | NEW |