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