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 |