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/child/webcrypto/shared_crypto.h" | 5 #include "content/child/webcrypto/shared_crypto.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "content/child/webcrypto/crypto_data.h" | 8 #include "content/child/webcrypto/crypto_data.h" |
9 #include "content/child/webcrypto/jwk.h" | 9 #include "content/child/webcrypto/jwk.h" |
10 #include "content/child/webcrypto/platform_crypto.h" | 10 #include "content/child/webcrypto/platform_crypto.h" |
11 #include "content/child/webcrypto/status.h" | 11 #include "content/child/webcrypto/status.h" |
12 #include "content/child/webcrypto/webcrypto_util.h" | 12 #include "content/child/webcrypto/webcrypto_util.h" |
13 #include "crypto/secure_util.h" | 13 #include "crypto/secure_util.h" |
14 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" | 14 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" |
15 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" | 15 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" |
16 #include "third_party/WebKit/public/platform/WebCryptoKey.h" | 16 #include "third_party/WebKit/public/platform/WebCryptoKey.h" |
17 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" | 17 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" |
18 | 18 |
19 namespace content { | 19 namespace content { |
20 | 20 |
21 namespace webcrypto { | 21 namespace webcrypto { |
22 | 22 |
23 // ------------ | |
24 // Threading: | |
25 // ------------ | |
26 // | |
27 // All functions in this file are called from the webcrypto worker pool except | |
28 // for: | |
29 // | |
30 // * SerializeKeyForClone() | |
31 // * DeserializeKeyForClone() | |
32 // * ImportKey() // TODO(eroman): Change this. | |
33 | |
34 namespace { | 23 namespace { |
35 | 24 |
36 // TODO(eroman): Move this helper to WebCryptoKey. | 25 // TODO(eroman): Move this helper to WebCryptoKey. |
37 bool KeyUsageAllows(const blink::WebCryptoKey& key, | 26 bool KeyUsageAllows(const blink::WebCryptoKey& key, |
38 const blink::WebCryptoKeyUsage usage) { | 27 const blink::WebCryptoKeyUsage usage) { |
39 return ((key.usages() & usage) != 0); | 28 return ((key.usages() & usage) != 0); |
40 } | 29 } |
41 | 30 |
42 bool IsValidAesKeyLengthBits(unsigned int length_bits) { | 31 bool IsValidAesKeyLengthBits(unsigned int length_bits) { |
43 return length_bits == 128 || length_bits == 192 || length_bits == 256; | 32 return length_bits == 128 || length_bits == 192 || length_bits == 256; |
(...skipping 26 matching lines...) Expand all Loading... |
70 return Status::ErrorUnexpectedKeyType(); | 59 return Status::ErrorUnexpectedKeyType(); |
71 return Status::Success(); | 60 return Status::Success(); |
72 } | 61 } |
73 | 62 |
74 const size_t kAesBlockSizeBytes = 16; | 63 const size_t kAesBlockSizeBytes = 16; |
75 | 64 |
76 Status EncryptDecryptAesCbc(EncryptOrDecrypt mode, | 65 Status EncryptDecryptAesCbc(EncryptOrDecrypt mode, |
77 const blink::WebCryptoAlgorithm& algorithm, | 66 const blink::WebCryptoAlgorithm& algorithm, |
78 const blink::WebCryptoKey& key, | 67 const blink::WebCryptoKey& key, |
79 const CryptoData& data, | 68 const CryptoData& data, |
80 std::vector<uint8>* buffer) { | 69 blink::WebArrayBuffer* buffer) { |
81 platform::SymKey* sym_key; | 70 platform::SymKey* sym_key; |
82 Status status = ToPlatformSymKey(key, &sym_key); | 71 Status status = ToPlatformSymKey(key, &sym_key); |
83 if (status.IsError()) | 72 if (status.IsError()) |
84 return status; | 73 return status; |
85 | 74 |
86 const blink::WebCryptoAesCbcParams* params = algorithm.aesCbcParams(); | 75 const blink::WebCryptoAesCbcParams* params = algorithm.aesCbcParams(); |
87 if (!params) | 76 if (!params) |
88 return Status::ErrorUnexpected(); | 77 return Status::ErrorUnexpected(); |
89 | 78 |
90 CryptoData iv(params->iv().data(), params->iv().size()); | 79 CryptoData iv(params->iv().data(), params->iv().size()); |
91 if (iv.byte_length() != kAesBlockSizeBytes) | 80 if (iv.byte_length() != kAesBlockSizeBytes) |
92 return Status::ErrorIncorrectSizeAesCbcIv(); | 81 return Status::ErrorIncorrectSizeAesCbcIv(); |
93 | 82 |
94 return platform::EncryptDecryptAesCbc(mode, sym_key, data, iv, buffer); | 83 return platform::EncryptDecryptAesCbc(mode, sym_key, data, iv, buffer); |
95 } | 84 } |
96 | 85 |
97 Status EncryptDecryptAesGcm(EncryptOrDecrypt mode, | 86 Status EncryptDecryptAesGcm(EncryptOrDecrypt mode, |
98 const blink::WebCryptoAlgorithm& algorithm, | 87 const blink::WebCryptoAlgorithm& algorithm, |
99 const blink::WebCryptoKey& key, | 88 const blink::WebCryptoKey& key, |
100 const CryptoData& data, | 89 const CryptoData& data, |
101 std::vector<uint8>* buffer) { | 90 blink::WebArrayBuffer* buffer) { |
102 platform::SymKey* sym_key; | 91 platform::SymKey* sym_key; |
103 Status status = ToPlatformSymKey(key, &sym_key); | 92 Status status = ToPlatformSymKey(key, &sym_key); |
104 if (status.IsError()) | 93 if (status.IsError()) |
105 return status; | 94 return status; |
106 | 95 |
107 const blink::WebCryptoAesGcmParams* params = algorithm.aesGcmParams(); | 96 const blink::WebCryptoAesGcmParams* params = algorithm.aesGcmParams(); |
108 if (!params) | 97 if (!params) |
109 return Status::ErrorUnexpected(); | 98 return Status::ErrorUnexpected(); |
110 | 99 |
111 unsigned int tag_length_bits = 128; | 100 unsigned int tag_length_bits = 128; |
(...skipping 11 matching lines...) Expand all Loading... |
123 data, | 112 data, |
124 CryptoData(params->iv()), | 113 CryptoData(params->iv()), |
125 CryptoData(params->optionalAdditionalData()), | 114 CryptoData(params->optionalAdditionalData()), |
126 tag_length_bits, | 115 tag_length_bits, |
127 buffer); | 116 buffer); |
128 } | 117 } |
129 | 118 |
130 Status EncryptRsaEsPkcs1v1_5(const blink::WebCryptoAlgorithm& algorithm, | 119 Status EncryptRsaEsPkcs1v1_5(const blink::WebCryptoAlgorithm& algorithm, |
131 const blink::WebCryptoKey& key, | 120 const blink::WebCryptoKey& key, |
132 const CryptoData& data, | 121 const CryptoData& data, |
133 std::vector<uint8>* buffer) { | 122 blink::WebArrayBuffer* buffer) { |
134 platform::PublicKey* public_key; | 123 platform::PublicKey* public_key; |
135 Status status = ToPlatformPublicKey(key, &public_key); | 124 Status status = ToPlatformPublicKey(key, &public_key); |
136 if (status.IsError()) | 125 if (status.IsError()) |
137 return status; | 126 return status; |
138 | 127 |
139 // RSAES encryption does not support empty input | 128 // RSAES encryption does not support empty input |
140 if (!data.byte_length()) | 129 if (!data.byte_length()) |
141 return Status::ErrorDataTooSmall(); | 130 return Status::ErrorDataTooSmall(); |
142 | 131 |
143 return platform::EncryptRsaEsPkcs1v1_5(public_key, data, buffer); | 132 return platform::EncryptRsaEsPkcs1v1_5(public_key, data, buffer); |
144 } | 133 } |
145 | 134 |
146 Status DecryptRsaEsPkcs1v1_5(const blink::WebCryptoAlgorithm& algorithm, | 135 Status DecryptRsaEsPkcs1v1_5(const blink::WebCryptoAlgorithm& algorithm, |
147 const blink::WebCryptoKey& key, | 136 const blink::WebCryptoKey& key, |
148 const CryptoData& data, | 137 const CryptoData& data, |
149 std::vector<uint8>* buffer) { | 138 blink::WebArrayBuffer* buffer) { |
150 platform::PrivateKey* private_key; | 139 platform::PrivateKey* private_key; |
151 Status status = ToPlatformPrivateKey(key, &private_key); | 140 Status status = ToPlatformPrivateKey(key, &private_key); |
152 if (status.IsError()) | 141 if (status.IsError()) |
153 return status; | 142 return status; |
154 | 143 |
155 // RSAES decryption does not support empty input | 144 // RSAES decryption does not support empty input |
156 if (!data.byte_length()) | 145 if (!data.byte_length()) |
157 return Status::ErrorDataTooSmall(); | 146 return Status::ErrorDataTooSmall(); |
158 | 147 |
159 return platform::DecryptRsaEsPkcs1v1_5(private_key, data, buffer); | 148 return platform::DecryptRsaEsPkcs1v1_5(private_key, data, buffer); |
160 } | 149 } |
161 | 150 |
162 Status SignHmac(const blink::WebCryptoAlgorithm& algorithm, | 151 Status SignHmac(const blink::WebCryptoAlgorithm& algorithm, |
163 const blink::WebCryptoKey& key, | 152 const blink::WebCryptoKey& key, |
164 const CryptoData& data, | 153 const CryptoData& data, |
165 std::vector<uint8>* buffer) { | 154 blink::WebArrayBuffer* buffer) { |
166 platform::SymKey* sym_key; | 155 platform::SymKey* sym_key; |
167 Status status = ToPlatformSymKey(key, &sym_key); | 156 Status status = ToPlatformSymKey(key, &sym_key); |
168 if (status.IsError()) | 157 if (status.IsError()) |
169 return status; | 158 return status; |
170 | 159 |
171 return platform::SignHmac( | 160 return platform::SignHmac( |
172 sym_key, key.algorithm().hmacParams()->hash(), data, buffer); | 161 sym_key, key.algorithm().hmacParams()->hash(), data, buffer); |
173 } | 162 } |
174 | 163 |
175 Status VerifyHmac(const blink::WebCryptoAlgorithm& algorithm, | 164 Status VerifyHmac(const blink::WebCryptoAlgorithm& algorithm, |
176 const blink::WebCryptoKey& key, | 165 const blink::WebCryptoKey& key, |
177 const CryptoData& signature, | 166 const CryptoData& signature, |
178 const CryptoData& data, | 167 const CryptoData& data, |
179 bool* signature_match) { | 168 bool* signature_match) { |
180 std::vector<uint8> result; | 169 blink::WebArrayBuffer result; |
181 Status status = SignHmac(algorithm, key, data, &result); | 170 Status status = SignHmac(algorithm, key, data, &result); |
182 if (status.IsError()) | 171 if (status.IsError()) |
183 return status; | 172 return status; |
184 | 173 |
185 // Do not allow verification of truncated MACs. | 174 // Do not allow verification of truncated MACs. |
186 *signature_match = | 175 *signature_match = |
187 result.size() == signature.byte_length() && | 176 result.byteLength() == signature.byte_length() && |
188 crypto::SecureMemEqual( | 177 crypto::SecureMemEqual( |
189 Uint8VectorStart(result), signature.bytes(), signature.byte_length()); | 178 result.data(), signature.bytes(), signature.byte_length()); |
190 | 179 |
191 return Status::Success(); | 180 return Status::Success(); |
192 } | 181 } |
193 | 182 |
194 Status SignRsaSsaPkcs1v1_5(const blink::WebCryptoAlgorithm& algorithm, | 183 Status SignRsaSsaPkcs1v1_5(const blink::WebCryptoAlgorithm& algorithm, |
195 const blink::WebCryptoKey& key, | 184 const blink::WebCryptoKey& key, |
196 const CryptoData& data, | 185 const CryptoData& data, |
197 std::vector<uint8>* buffer) { | 186 blink::WebArrayBuffer* buffer) { |
198 platform::PrivateKey* private_key; | 187 platform::PrivateKey* private_key; |
199 Status status = ToPlatformPrivateKey(key, &private_key); | 188 Status status = ToPlatformPrivateKey(key, &private_key); |
200 if (status.IsError()) | 189 if (status.IsError()) |
201 return status; | 190 return status; |
202 | 191 |
203 return platform::SignRsaSsaPkcs1v1_5( | 192 return platform::SignRsaSsaPkcs1v1_5( |
204 private_key, key.algorithm().rsaHashedParams()->hash(), data, buffer); | 193 private_key, key.algorithm().rsaHashedParams()->hash(), data, buffer); |
205 } | 194 } |
206 | 195 |
207 Status VerifyRsaSsaPkcs1v1_5(const blink::WebCryptoAlgorithm& algorithm, | 196 Status VerifyRsaSsaPkcs1v1_5(const blink::WebCryptoAlgorithm& algorithm, |
208 const blink::WebCryptoKey& key, | 197 const blink::WebCryptoKey& key, |
209 const CryptoData& signature, | 198 const CryptoData& signature, |
210 const CryptoData& data, | 199 const CryptoData& data, |
211 bool* signature_match) { | 200 bool* signature_match) { |
212 platform::PublicKey* public_key; | 201 platform::PublicKey* public_key; |
213 Status status = ToPlatformPublicKey(key, &public_key); | 202 Status status = ToPlatformPublicKey(key, &public_key); |
214 if (status.IsError()) | 203 if (status.IsError()) |
215 return status; | 204 return status; |
216 | 205 |
217 return platform::VerifyRsaSsaPkcs1v1_5( | 206 return platform::VerifyRsaSsaPkcs1v1_5( |
218 public_key, | 207 public_key, |
219 key.algorithm().rsaHashedParams()->hash(), | 208 key.algorithm().rsaHashedParams()->hash(), |
220 signature, | 209 signature, |
221 data, | 210 data, |
222 signature_match); | 211 signature_match); |
223 } | 212 } |
224 | 213 |
225 // Note that this function may be called from the target Blink thread. | |
226 Status ImportKeyRaw(const CryptoData& key_data, | 214 Status ImportKeyRaw(const CryptoData& key_data, |
227 const blink::WebCryptoAlgorithm& algorithm, | 215 const blink::WebCryptoAlgorithm& algorithm, |
228 bool extractable, | 216 bool extractable, |
229 blink::WebCryptoKeyUsageMask usage_mask, | 217 blink::WebCryptoKeyUsageMask usage_mask, |
230 blink::WebCryptoKey* key) { | 218 blink::WebCryptoKey* key) { |
231 switch (algorithm.id()) { | 219 switch (algorithm.id()) { |
232 case blink::WebCryptoAlgorithmIdAesCtr: | 220 case blink::WebCryptoAlgorithmIdAesCtr: |
233 case blink::WebCryptoAlgorithmIdAesCbc: | 221 case blink::WebCryptoAlgorithmIdAesCbc: |
234 case blink::WebCryptoAlgorithmIdAesGcm: | 222 case blink::WebCryptoAlgorithmIdAesGcm: |
235 case blink::WebCryptoAlgorithmIdAesKw: | 223 case blink::WebCryptoAlgorithmIdAesKw: |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
278 return blink::WebCryptoAlgorithm::createNull(); | 266 return blink::WebCryptoAlgorithm::createNull(); |
279 } | 267 } |
280 | 268 |
281 // There is some duplicated information in the serialized format used by | 269 // There is some duplicated information in the serialized format used by |
282 // structured clone (since the KeyAlgorithm is serialized separately from the | 270 // structured clone (since the KeyAlgorithm is serialized separately from the |
283 // key data). Use this extra information to further validate what was | 271 // key data). Use this extra information to further validate what was |
284 // deserialized from the key data. | 272 // deserialized from the key data. |
285 // | 273 // |
286 // A failure here implies either a bug in the code, or that the serialized data | 274 // A failure here implies either a bug in the code, or that the serialized data |
287 // was corrupted. | 275 // was corrupted. |
288 bool ValidateDeserializedKey(const blink::WebCryptoKey& key, | 276 Status ValidateDeserializedKey(const blink::WebCryptoKey& key, |
289 const blink::WebCryptoKeyAlgorithm& algorithm, | 277 const blink::WebCryptoKeyAlgorithm& algorithm, |
290 blink::WebCryptoKeyType type) { | 278 blink::WebCryptoKeyType type) { |
291 if (algorithm.id() != key.algorithm().id()) | 279 if (algorithm.id() != key.algorithm().id()) |
292 return false; | 280 return Status::ErrorUnexpected(); |
293 | 281 |
294 if (key.type() != type) | 282 if (key.type() != type) |
295 return false; | 283 return Status::ErrorUnexpected(); |
296 | 284 |
297 switch (algorithm.paramsType()) { | 285 switch (algorithm.paramsType()) { |
298 case blink::WebCryptoKeyAlgorithmParamsTypeAes: | 286 case blink::WebCryptoKeyAlgorithmParamsTypeAes: |
299 if (algorithm.aesParams()->lengthBits() != | 287 if (algorithm.aesParams()->lengthBits() != |
300 key.algorithm().aesParams()->lengthBits()) | 288 key.algorithm().aesParams()->lengthBits()) |
301 return false; | 289 return Status::ErrorUnexpected(); |
302 break; | 290 break; |
303 case blink::WebCryptoKeyAlgorithmParamsTypeRsa: | 291 case blink::WebCryptoKeyAlgorithmParamsTypeRsa: |
304 case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed: | 292 case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed: |
305 if (algorithm.rsaParams()->modulusLengthBits() != | 293 if (algorithm.rsaParams()->modulusLengthBits() != |
306 key.algorithm().rsaParams()->modulusLengthBits()) | 294 key.algorithm().rsaParams()->modulusLengthBits()) |
307 return false; | 295 return Status::ErrorUnexpected(); |
308 if (algorithm.rsaParams()->publicExponent().size() != | 296 if (algorithm.rsaParams()->publicExponent().size() != |
309 key.algorithm().rsaParams()->publicExponent().size()) | 297 key.algorithm().rsaParams()->publicExponent().size()) |
310 return false; | 298 return Status::ErrorUnexpected(); |
311 if (memcmp(algorithm.rsaParams()->publicExponent().data(), | 299 if (memcmp(algorithm.rsaParams()->publicExponent().data(), |
312 key.algorithm().rsaParams()->publicExponent().data(), | 300 key.algorithm().rsaParams()->publicExponent().data(), |
313 key.algorithm().rsaParams()->publicExponent().size()) != 0) | 301 key.algorithm().rsaParams()->publicExponent().size()) != 0) |
314 return false; | 302 return Status::ErrorUnexpected(); |
315 break; | 303 break; |
316 case blink::WebCryptoKeyAlgorithmParamsTypeNone: | 304 case blink::WebCryptoKeyAlgorithmParamsTypeNone: |
317 case blink::WebCryptoKeyAlgorithmParamsTypeHmac: | 305 case blink::WebCryptoKeyAlgorithmParamsTypeHmac: |
318 break; | 306 break; |
319 } | 307 } |
320 | 308 |
321 return true; | 309 return Status::Success(); |
322 } | 310 } |
323 | 311 |
324 // Validates the size of data input to AES-KW. AES-KW requires the input data | 312 // Validates the size of data input to AES-KW. AES-KW requires the input data |
325 // size to be at least 24 bytes and a multiple of 8 bytes. | 313 // size to be at least 24 bytes and a multiple of 8 bytes. |
326 Status CheckAesKwInputSize(const CryptoData& aeskw_input_data) { | 314 Status CheckAesKwInputSize(const CryptoData& aeskw_input_data) { |
327 if (aeskw_input_data.byte_length() < 24) | 315 if (aeskw_input_data.byte_length() < 24) |
328 return Status::ErrorDataTooSmall(); | 316 return Status::ErrorDataTooSmall(); |
329 if (aeskw_input_data.byte_length() % 8) | 317 if (aeskw_input_data.byte_length() % 8) |
330 return Status::ErrorInvalidAesKwDataLength(); | 318 return Status::ErrorInvalidAesKwDataLength(); |
331 return Status::Success(); | 319 return Status::Success(); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
371 key); | 359 key); |
372 } | 360 } |
373 default: | 361 default: |
374 return Status::ErrorUnsupported(); | 362 return Status::ErrorUnsupported(); |
375 } | 363 } |
376 } | 364 } |
377 | 365 |
378 Status WrapKeyRaw(const blink::WebCryptoKey& wrapping_key, | 366 Status WrapKeyRaw(const blink::WebCryptoKey& wrapping_key, |
379 const blink::WebCryptoKey& key_to_wrap, | 367 const blink::WebCryptoKey& key_to_wrap, |
380 const blink::WebCryptoAlgorithm& wrapping_algorithm, | 368 const blink::WebCryptoAlgorithm& wrapping_algorithm, |
381 std::vector<uint8>* buffer) { | 369 blink::WebArrayBuffer* buffer) { |
382 // A raw key is always a symmetric key. | 370 // A raw key is always a symmetric key. |
383 platform::SymKey* platform_key; | 371 platform::SymKey* platform_key; |
384 Status status = ToPlatformSymKey(key_to_wrap, &platform_key); | 372 Status status = ToPlatformSymKey(key_to_wrap, &platform_key); |
385 if (status.IsError()) | 373 if (status.IsError()) |
386 return status; | 374 return status; |
387 | 375 |
388 // TODO(padolph): Handle other wrapping algorithms | 376 // TODO(padolph): Handle other wrapping algorithms |
389 switch (wrapping_algorithm.id()) { | 377 switch (wrapping_algorithm.id()) { |
390 case blink::WebCryptoAlgorithmIdAesKw: { | 378 case blink::WebCryptoAlgorithmIdAesKw: { |
391 platform::SymKey* platform_wrapping_key; | 379 platform::SymKey* platform_wrapping_key; |
(...skipping 12 matching lines...) Expand all Loading... |
404 platform_wrapping_key, platform_key, buffer); | 392 platform_wrapping_key, platform_key, buffer); |
405 } | 393 } |
406 default: | 394 default: |
407 return Status::ErrorUnsupported(); | 395 return Status::ErrorUnsupported(); |
408 } | 396 } |
409 } | 397 } |
410 | 398 |
411 Status DecryptAesKw(const blink::WebCryptoAlgorithm& algorithm, | 399 Status DecryptAesKw(const blink::WebCryptoAlgorithm& algorithm, |
412 const blink::WebCryptoKey& key, | 400 const blink::WebCryptoKey& key, |
413 const CryptoData& data, | 401 const CryptoData& data, |
414 std::vector<uint8>* buffer) { | 402 blink::WebArrayBuffer* buffer) { |
415 platform::SymKey* sym_key; | 403 platform::SymKey* sym_key; |
416 Status status = ToPlatformSymKey(key, &sym_key); | 404 Status status = ToPlatformSymKey(key, &sym_key); |
417 if (status.IsError()) | 405 if (status.IsError()) |
418 return status; | 406 return status; |
419 status = CheckAesKwInputSize(data); | 407 status = CheckAesKwInputSize(data); |
420 if (status.IsError()) | 408 if (status.IsError()) |
421 return status; | 409 return status; |
422 return platform::DecryptAesKw(sym_key, data, buffer); | 410 return platform::DecryptAesKw(sym_key, data, buffer); |
423 } | 411 } |
424 | 412 |
425 Status DecryptDontCheckKeyUsage(const blink::WebCryptoAlgorithm& algorithm, | 413 Status DecryptDontCheckKeyUsage(const blink::WebCryptoAlgorithm& algorithm, |
426 const blink::WebCryptoKey& key, | 414 const blink::WebCryptoKey& key, |
427 const CryptoData& data, | 415 const CryptoData& data, |
428 std::vector<uint8>* buffer) { | 416 blink::WebArrayBuffer* buffer) { |
429 if (algorithm.id() != key.algorithm().id()) | 417 if (algorithm.id() != key.algorithm().id()) |
430 return Status::ErrorUnexpected(); | 418 return Status::ErrorUnexpected(); |
431 switch (algorithm.id()) { | 419 switch (algorithm.id()) { |
432 case blink::WebCryptoAlgorithmIdAesCbc: | 420 case blink::WebCryptoAlgorithmIdAesCbc: |
433 return EncryptDecryptAesCbc(DECRYPT, algorithm, key, data, buffer); | 421 return EncryptDecryptAesCbc(DECRYPT, algorithm, key, data, buffer); |
434 case blink::WebCryptoAlgorithmIdAesGcm: | 422 case blink::WebCryptoAlgorithmIdAesGcm: |
435 return EncryptDecryptAesGcm(DECRYPT, algorithm, key, data, buffer); | 423 return EncryptDecryptAesGcm(DECRYPT, algorithm, key, data, buffer); |
436 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: | 424 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: |
437 return DecryptRsaEsPkcs1v1_5(algorithm, key, data, buffer); | 425 return DecryptRsaEsPkcs1v1_5(algorithm, key, data, buffer); |
438 case blink::WebCryptoAlgorithmIdAesKw: | 426 case blink::WebCryptoAlgorithmIdAesKw: |
439 return DecryptAesKw(algorithm, key, data, buffer); | 427 return DecryptAesKw(algorithm, key, data, buffer); |
440 default: | 428 default: |
441 return Status::ErrorUnsupported(); | 429 return Status::ErrorUnsupported(); |
442 } | 430 } |
443 } | 431 } |
444 | 432 |
445 Status EncryptDontCheckUsage(const blink::WebCryptoAlgorithm& algorithm, | 433 Status EncryptDontCheckUsage(const blink::WebCryptoAlgorithm& algorithm, |
446 const blink::WebCryptoKey& key, | 434 const blink::WebCryptoKey& key, |
447 const CryptoData& data, | 435 const CryptoData& data, |
448 std::vector<uint8>* buffer) { | 436 blink::WebArrayBuffer* buffer) { |
449 if (algorithm.id() != key.algorithm().id()) | 437 if (algorithm.id() != key.algorithm().id()) |
450 return Status::ErrorUnexpected(); | 438 return Status::ErrorUnexpected(); |
451 switch (algorithm.id()) { | 439 switch (algorithm.id()) { |
452 case blink::WebCryptoAlgorithmIdAesCbc: | 440 case blink::WebCryptoAlgorithmIdAesCbc: |
453 return EncryptDecryptAesCbc(ENCRYPT, algorithm, key, data, buffer); | 441 return EncryptDecryptAesCbc(ENCRYPT, algorithm, key, data, buffer); |
454 case blink::WebCryptoAlgorithmIdAesGcm: | 442 case blink::WebCryptoAlgorithmIdAesGcm: |
455 return EncryptDecryptAesGcm(ENCRYPT, algorithm, key, data, buffer); | 443 return EncryptDecryptAesGcm(ENCRYPT, algorithm, key, data, buffer); |
456 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: | 444 case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5: |
457 return EncryptRsaEsPkcs1v1_5(algorithm, key, data, buffer); | 445 return EncryptRsaEsPkcs1v1_5(algorithm, key, data, buffer); |
458 default: | 446 default: |
459 return Status::ErrorUnsupported(); | 447 return Status::ErrorUnsupported(); |
460 } | 448 } |
461 } | 449 } |
462 | 450 |
463 Status UnwrapKeyDecryptAndImport( | 451 Status UnwrapKeyDecryptAndImport( |
464 blink::WebCryptoKeyFormat format, | 452 blink::WebCryptoKeyFormat format, |
465 const CryptoData& wrapped_key_data, | 453 const CryptoData& wrapped_key_data, |
466 const blink::WebCryptoKey& wrapping_key, | 454 const blink::WebCryptoKey& wrapping_key, |
467 const blink::WebCryptoAlgorithm& wrapping_algorithm, | 455 const blink::WebCryptoAlgorithm& wrapping_algorithm, |
468 const blink::WebCryptoAlgorithm& algorithm, | 456 const blink::WebCryptoAlgorithm& algorithm, |
469 bool extractable, | 457 bool extractable, |
470 blink::WebCryptoKeyUsageMask usage_mask, | 458 blink::WebCryptoKeyUsageMask usage_mask, |
471 blink::WebCryptoKey* key) { | 459 blink::WebCryptoKey* key) { |
472 std::vector<uint8> buffer; | 460 blink::WebArrayBuffer buffer; |
473 Status status = DecryptDontCheckKeyUsage( | 461 Status status = DecryptDontCheckKeyUsage( |
474 wrapping_algorithm, wrapping_key, wrapped_key_data, &buffer); | 462 wrapping_algorithm, wrapping_key, wrapped_key_data, &buffer); |
475 if (status.IsError()) | 463 if (status.IsError()) |
476 return status; | 464 return status; |
477 status = ImportKey( | 465 status = ImportKey( |
478 format, CryptoData(buffer), algorithm, extractable, usage_mask, key); | 466 format, CryptoData(buffer), algorithm, extractable, usage_mask, key); |
479 // NOTE! Returning the details of any ImportKey() failure here would leak | 467 // NOTE! Returning the details of any ImportKey() failure here would leak |
480 // information about the plaintext internals of the encrypted key. Instead, | 468 // information about the plaintext internals of the encrypted key. Instead, |
481 // collapse any error into the generic Status::OperationError(). | 469 // collapse any error into the generic Status::OperationError(). |
482 return status.IsError() ? Status::OperationError() : Status::Success(); | 470 return status.IsError() ? Status::OperationError() : Status::Success(); |
483 } | 471 } |
484 | 472 |
485 Status WrapKeyExportAndEncrypt( | 473 Status WrapKeyExportAndEncrypt( |
486 blink::WebCryptoKeyFormat format, | 474 blink::WebCryptoKeyFormat format, |
487 const blink::WebCryptoKey& wrapping_key, | 475 const blink::WebCryptoKey& wrapping_key, |
488 const blink::WebCryptoKey& key_to_wrap, | 476 const blink::WebCryptoKey& key_to_wrap, |
489 const blink::WebCryptoAlgorithm& wrapping_algorithm, | 477 const blink::WebCryptoAlgorithm& wrapping_algorithm, |
490 std::vector<uint8>* buffer) { | 478 blink::WebArrayBuffer* buffer) { |
491 std::vector<uint8> exported_data; | 479 blink::WebArrayBuffer exported_data; |
492 Status status = ExportKey(format, key_to_wrap, &exported_data); | 480 Status status = ExportKey(format, key_to_wrap, &exported_data); |
493 if (status.IsError()) | 481 if (status.IsError()) |
494 return status; | 482 return status; |
495 return EncryptDontCheckUsage( | 483 return EncryptDontCheckUsage( |
496 wrapping_algorithm, wrapping_key, CryptoData(exported_data), buffer); | 484 wrapping_algorithm, wrapping_key, CryptoData(exported_data), buffer); |
497 } | 485 } |
498 | 486 |
499 // Returns the internal block size for SHA-* | 487 // Returns the internal block size for SHA-* |
500 unsigned int ShaBlockSizeBytes(blink::WebCryptoAlgorithmId hash_id) { | 488 unsigned int ShaBlockSizeBytes(blink::WebCryptoAlgorithmId hash_id) { |
501 switch (hash_id) { | 489 switch (hash_id) { |
502 case blink::WebCryptoAlgorithmIdSha1: | 490 case blink::WebCryptoAlgorithmIdSha1: |
503 case blink::WebCryptoAlgorithmIdSha256: | 491 case blink::WebCryptoAlgorithmIdSha256: |
504 return 64; | 492 return 64; |
505 case blink::WebCryptoAlgorithmIdSha384: | 493 case blink::WebCryptoAlgorithmIdSha384: |
506 case blink::WebCryptoAlgorithmIdSha512: | 494 case blink::WebCryptoAlgorithmIdSha512: |
507 return 128; | 495 return 128; |
508 default: | 496 default: |
509 NOTREACHED(); | 497 NOTREACHED(); |
510 return 0; | 498 return 0; |
511 } | 499 } |
512 } | 500 } |
513 | 501 |
514 } // namespace | 502 } // namespace |
515 | 503 |
516 void Init() { platform::Init(); } | 504 void Init() { platform::Init(); } |
517 | 505 |
518 Status Encrypt(const blink::WebCryptoAlgorithm& algorithm, | 506 Status Encrypt(const blink::WebCryptoAlgorithm& algorithm, |
519 const blink::WebCryptoKey& key, | 507 const blink::WebCryptoKey& key, |
520 const CryptoData& data, | 508 const CryptoData& data, |
521 std::vector<uint8>* buffer) { | 509 blink::WebArrayBuffer* buffer) { |
522 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageEncrypt)) | 510 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageEncrypt)) |
523 return Status::ErrorUnexpected(); | 511 return Status::ErrorUnexpected(); |
524 return EncryptDontCheckUsage(algorithm, key, data, buffer); | 512 return EncryptDontCheckUsage(algorithm, key, data, buffer); |
525 } | 513 } |
526 | 514 |
527 Status Decrypt(const blink::WebCryptoAlgorithm& algorithm, | 515 Status Decrypt(const blink::WebCryptoAlgorithm& algorithm, |
528 const blink::WebCryptoKey& key, | 516 const blink::WebCryptoKey& key, |
529 const CryptoData& data, | 517 const CryptoData& data, |
530 std::vector<uint8>* buffer) { | 518 blink::WebArrayBuffer* buffer) { |
531 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageDecrypt)) | 519 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageDecrypt)) |
532 return Status::ErrorUnexpected(); | 520 return Status::ErrorUnexpected(); |
533 return DecryptDontCheckKeyUsage(algorithm, key, data, buffer); | 521 return DecryptDontCheckKeyUsage(algorithm, key, data, buffer); |
534 } | 522 } |
535 | 523 |
536 Status Digest(const blink::WebCryptoAlgorithm& algorithm, | 524 Status Digest(const blink::WebCryptoAlgorithm& algorithm, |
537 const CryptoData& data, | 525 const CryptoData& data, |
538 std::vector<uint8>* buffer) { | 526 blink::WebArrayBuffer* buffer) { |
539 switch (algorithm.id()) { | 527 switch (algorithm.id()) { |
540 case blink::WebCryptoAlgorithmIdSha1: | 528 case blink::WebCryptoAlgorithmIdSha1: |
541 case blink::WebCryptoAlgorithmIdSha256: | 529 case blink::WebCryptoAlgorithmIdSha256: |
542 case blink::WebCryptoAlgorithmIdSha384: | 530 case blink::WebCryptoAlgorithmIdSha384: |
543 case blink::WebCryptoAlgorithmIdSha512: | 531 case blink::WebCryptoAlgorithmIdSha512: |
544 return platform::DigestSha(algorithm.id(), data, buffer); | 532 return platform::DigestSha(algorithm.id(), data, buffer); |
545 default: | 533 default: |
546 return Status::ErrorUnsupported(); | 534 return Status::ErrorUnsupported(); |
547 } | 535 } |
548 } | 536 } |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
631 publicExponent, | 619 publicExponent, |
632 hash_or_null, | 620 hash_or_null, |
633 public_key, | 621 public_key, |
634 private_key); | 622 private_key); |
635 } | 623 } |
636 default: | 624 default: |
637 return Status::ErrorUnsupported(); | 625 return Status::ErrorUnsupported(); |
638 } | 626 } |
639 } | 627 } |
640 | 628 |
641 // Note that this function may be called from the target Blink thread. | |
642 Status ImportKey(blink::WebCryptoKeyFormat format, | 629 Status ImportKey(blink::WebCryptoKeyFormat format, |
643 const CryptoData& key_data, | 630 const CryptoData& key_data, |
644 const blink::WebCryptoAlgorithm& algorithm, | 631 const blink::WebCryptoAlgorithm& algorithm, |
645 bool extractable, | 632 bool extractable, |
646 blink::WebCryptoKeyUsageMask usage_mask, | 633 blink::WebCryptoKeyUsageMask usage_mask, |
647 blink::WebCryptoKey* key) { | 634 blink::WebCryptoKey* key) { |
648 switch (format) { | 635 switch (format) { |
649 case blink::WebCryptoKeyFormatRaw: | 636 case blink::WebCryptoKeyFormatRaw: |
650 return ImportKeyRaw(key_data, algorithm, extractable, usage_mask, key); | 637 return ImportKeyRaw(key_data, algorithm, extractable, usage_mask, key); |
651 case blink::WebCryptoKeyFormatSpki: | 638 case blink::WebCryptoKeyFormatSpki: |
652 return platform::ImportKeySpki( | 639 return platform::ImportKeySpki( |
653 algorithm, key_data, extractable, usage_mask, key); | 640 algorithm, key_data, extractable, usage_mask, key); |
654 case blink::WebCryptoKeyFormatPkcs8: | 641 case blink::WebCryptoKeyFormatPkcs8: |
655 return platform::ImportKeyPkcs8( | 642 return platform::ImportKeyPkcs8( |
656 algorithm, key_data, extractable, usage_mask, key); | 643 algorithm, key_data, extractable, usage_mask, key); |
657 case blink::WebCryptoKeyFormatJwk: | 644 case blink::WebCryptoKeyFormatJwk: |
658 return ImportKeyJwk(key_data, algorithm, extractable, usage_mask, key); | 645 return ImportKeyJwk(key_data, algorithm, extractable, usage_mask, key); |
659 default: | 646 default: |
660 return Status::ErrorUnsupported(); | 647 return Status::ErrorUnsupported(); |
661 } | 648 } |
662 } | 649 } |
663 | 650 |
664 // TODO(eroman): Move this to anonymous namespace. | 651 // TODO(eroman): Move this to anonymous namespace. |
665 Status ExportKeyDontCheckExtractability(blink::WebCryptoKeyFormat format, | 652 Status ExportKeyDontCheckExtractability(blink::WebCryptoKeyFormat format, |
666 const blink::WebCryptoKey& key, | 653 const blink::WebCryptoKey& key, |
667 std::vector<uint8>* buffer) { | 654 blink::WebArrayBuffer* buffer) { |
668 switch (format) { | 655 switch (format) { |
669 case blink::WebCryptoKeyFormatRaw: { | 656 case blink::WebCryptoKeyFormatRaw: { |
670 platform::SymKey* sym_key; | 657 platform::SymKey* sym_key; |
671 Status status = ToPlatformSymKey(key, &sym_key); | 658 Status status = ToPlatformSymKey(key, &sym_key); |
672 if (status.IsError()) | 659 if (status.IsError()) |
673 return status; | 660 return status; |
674 return platform::ExportKeyRaw(sym_key, buffer); | 661 return platform::ExportKeyRaw(sym_key, buffer); |
675 } | 662 } |
676 case blink::WebCryptoKeyFormatSpki: { | 663 case blink::WebCryptoKeyFormatSpki: { |
677 platform::PublicKey* public_key; | 664 platform::PublicKey* public_key; |
(...skipping 11 matching lines...) Expand all Loading... |
689 } | 676 } |
690 case blink::WebCryptoKeyFormatJwk: | 677 case blink::WebCryptoKeyFormatJwk: |
691 return ExportKeyJwk(key, buffer); | 678 return ExportKeyJwk(key, buffer); |
692 default: | 679 default: |
693 return Status::ErrorUnsupported(); | 680 return Status::ErrorUnsupported(); |
694 } | 681 } |
695 } | 682 } |
696 | 683 |
697 Status ExportKey(blink::WebCryptoKeyFormat format, | 684 Status ExportKey(blink::WebCryptoKeyFormat format, |
698 const blink::WebCryptoKey& key, | 685 const blink::WebCryptoKey& key, |
699 std::vector<uint8>* buffer) { | 686 blink::WebArrayBuffer* buffer) { |
700 if (!key.extractable()) | 687 if (!key.extractable()) |
701 return Status::ErrorKeyNotExtractable(); | 688 return Status::ErrorKeyNotExtractable(); |
702 return ExportKeyDontCheckExtractability(format, key, buffer); | 689 return ExportKeyDontCheckExtractability(format, key, buffer); |
703 } | 690 } |
704 | 691 |
705 Status Sign(const blink::WebCryptoAlgorithm& algorithm, | 692 Status Sign(const blink::WebCryptoAlgorithm& algorithm, |
706 const blink::WebCryptoKey& key, | 693 const blink::WebCryptoKey& key, |
707 const CryptoData& data, | 694 const CryptoData& data, |
708 std::vector<uint8>* buffer) { | 695 blink::WebArrayBuffer* buffer) { |
709 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageSign)) | 696 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageSign)) |
710 return Status::ErrorUnexpected(); | 697 return Status::ErrorUnexpected(); |
711 if (algorithm.id() != key.algorithm().id()) | 698 if (algorithm.id() != key.algorithm().id()) |
712 return Status::ErrorUnexpected(); | 699 return Status::ErrorUnexpected(); |
713 | 700 |
714 switch (algorithm.id()) { | 701 switch (algorithm.id()) { |
715 case blink::WebCryptoAlgorithmIdHmac: | 702 case blink::WebCryptoAlgorithmIdHmac: |
716 return SignHmac(algorithm, key, data, buffer); | 703 return SignHmac(algorithm, key, data, buffer); |
717 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: | 704 case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: |
718 return SignRsaSsaPkcs1v1_5(algorithm, key, data, buffer); | 705 return SignRsaSsaPkcs1v1_5(algorithm, key, data, buffer); |
(...skipping 28 matching lines...) Expand all Loading... |
747 algorithm, key, signature, data, signature_match); | 734 algorithm, key, signature, data, signature_match); |
748 default: | 735 default: |
749 return Status::ErrorUnsupported(); | 736 return Status::ErrorUnsupported(); |
750 } | 737 } |
751 } | 738 } |
752 | 739 |
753 Status WrapKey(blink::WebCryptoKeyFormat format, | 740 Status WrapKey(blink::WebCryptoKeyFormat format, |
754 const blink::WebCryptoKey& wrapping_key, | 741 const blink::WebCryptoKey& wrapping_key, |
755 const blink::WebCryptoKey& key_to_wrap, | 742 const blink::WebCryptoKey& key_to_wrap, |
756 const blink::WebCryptoAlgorithm& wrapping_algorithm, | 743 const blink::WebCryptoAlgorithm& wrapping_algorithm, |
757 std::vector<uint8>* buffer) { | 744 blink::WebArrayBuffer* buffer) { |
758 if (!KeyUsageAllows(wrapping_key, blink::WebCryptoKeyUsageWrapKey)) | 745 if (!KeyUsageAllows(wrapping_key, blink::WebCryptoKeyUsageWrapKey)) |
759 return Status::ErrorUnexpected(); | 746 return Status::ErrorUnexpected(); |
760 if (wrapping_algorithm.id() != wrapping_key.algorithm().id()) | 747 if (wrapping_algorithm.id() != wrapping_key.algorithm().id()) |
761 return Status::ErrorUnexpected(); | 748 return Status::ErrorUnexpected(); |
762 | 749 |
763 switch (format) { | 750 switch (format) { |
764 case blink::WebCryptoKeyFormatRaw: | 751 case blink::WebCryptoKeyFormatRaw: |
765 return WrapKeyRaw(wrapping_key, key_to_wrap, wrapping_algorithm, buffer); | 752 return WrapKeyRaw(wrapping_key, key_to_wrap, wrapping_algorithm, buffer); |
766 case blink::WebCryptoKeyFormatJwk: | 753 case blink::WebCryptoKeyFormatJwk: |
767 return WrapKeyExportAndEncrypt( | 754 return WrapKeyExportAndEncrypt( |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
808 key); | 795 key); |
809 case blink::WebCryptoKeyFormatSpki: | 796 case blink::WebCryptoKeyFormatSpki: |
810 case blink::WebCryptoKeyFormatPkcs8: | 797 case blink::WebCryptoKeyFormatPkcs8: |
811 return Status::ErrorUnsupported(); // TODO(padolph) | 798 return Status::ErrorUnsupported(); // TODO(padolph) |
812 default: | 799 default: |
813 NOTREACHED(); | 800 NOTREACHED(); |
814 return Status::ErrorUnsupported(); | 801 return Status::ErrorUnsupported(); |
815 } | 802 } |
816 } | 803 } |
817 | 804 |
818 // Note that this function is called from the target Blink thread. | 805 Status SerializeKeyForClone(const blink::WebCryptoKey& key, |
819 bool SerializeKeyForClone(const blink::WebCryptoKey& key, | 806 blink::WebVector<unsigned char>* data) { |
820 blink::WebVector<uint8>* key_data) { | 807 blink::WebArrayBuffer buffer; |
821 return static_cast<webcrypto::platform::Key*>(key.handle()) | 808 Status status = ExportKeyDontCheckExtractability( |
822 ->ThreadSafeSerializeForClone(key_data); | 809 GetCloneFormatForKeyType(key.type()), key, &buffer); |
| 810 if (status.IsError()) |
| 811 return status; |
| 812 data->assign( |
| 813 reinterpret_cast<unsigned char*>(buffer.data()), buffer.byteLength()); |
| 814 return Status::Success(); |
823 } | 815 } |
824 | 816 |
825 // Note that this function is called from the target Blink thread. | 817 Status DeserializeKeyForClone(const blink::WebCryptoKeyAlgorithm& algorithm, |
826 bool DeserializeKeyForClone(const blink::WebCryptoKeyAlgorithm& algorithm, | 818 blink::WebCryptoKeyType type, |
827 blink::WebCryptoKeyType type, | 819 bool extractable, |
828 bool extractable, | 820 blink::WebCryptoKeyUsageMask usage_mask, |
829 blink::WebCryptoKeyUsageMask usage_mask, | 821 const CryptoData& key_data, |
830 const CryptoData& key_data, | 822 blink::WebCryptoKey* key) { |
831 blink::WebCryptoKey* key) { | |
832 // TODO(eroman): This should not call into the platform crypto layer. | |
833 // Otherwise it runs the risk of stalling while the NSS/OpenSSL global locks | |
834 // are held. | |
835 // | |
836 // An alternate approach is to defer the key import until the key is used. | |
837 // However this means that any deserialization errors would have to be | |
838 // surfaced as WebCrypto errors, leading to slightly different behaviors. For | |
839 // instance you could clone a key which fails to be deserialized. | |
840 Status status = ImportKey(GetCloneFormatForKeyType(type), | 823 Status status = ImportKey(GetCloneFormatForKeyType(type), |
841 key_data, | 824 key_data, |
842 KeyAlgorithmToImportAlgorithm(algorithm), | 825 KeyAlgorithmToImportAlgorithm(algorithm), |
843 extractable, | 826 extractable, |
844 usage_mask, | 827 usage_mask, |
845 key); | 828 key); |
846 if (status.IsError()) | 829 if (status.IsError()) |
847 return false; | 830 return status; |
| 831 |
848 return ValidateDeserializedKey(*key, algorithm, type); | 832 return ValidateDeserializedKey(*key, algorithm, type); |
849 } | 833 } |
850 | 834 |
851 } // namespace webcrypto | 835 } // namespace webcrypto |
852 | 836 |
853 } // namespace content | 837 } // namespace content |
OLD | NEW |