Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(944)

Side by Side Diff: content/renderer/webcrypto/webcrypto_impl.cc

Issue 145083006: [webcrypto] Add error messages for failed operations. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Check the Status in unittests Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 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/webcrypto_impl.h" 5 #include "content/renderer/webcrypto/webcrypto_impl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <functional> 8 #include <functional>
9 #include <map> 9 #include <map>
10 #include "base/json/json_reader.h" 10 #include "base/json/json_reader.h"
11 #include "base/lazy_instance.h" 11 #include "base/lazy_instance.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h" 13 #include "base/memory/scoped_ptr.h"
14 #include "base/strings/string_piece.h" 14 #include "base/strings/string_piece.h"
15 #include "base/values.h" 15 #include "base/values.h"
16 #include "content/renderer/webcrypto/webcrypto_util.h"
17 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h" 16 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
18 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" 17 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
19 #include "third_party/WebKit/public/platform/WebCryptoKey.h" 18 #include "third_party/WebKit/public/platform/WebCryptoKey.h"
19 #include "third_party/WebKit/public/platform/WebString.h"
20 20
21 namespace content { 21 namespace content {
22 22
23 using webcrypto::Status;
Ryan Sleevi 2014/01/24 01:21:50 I thought this was discouraged in Chromium side.
eroman 2014/01/24 03:19:21 The practice is quite common in Chrome code, occur
Ryan Sleevi 2014/01/24 20:27:01 Thread: https://groups.google.com/a/chromium.org/
eroman 2014/01/24 21:33:10 Thanks for the link to the thread! I'll give it a
24
23 namespace { 25 namespace {
24 26
27 // Complete |result| with a failure if |status| indicates an error and return
28 // true. Otherwise return false.
29 bool completeWithError(const Status& status, blink::WebCryptoResult* result) {
Ryan Sleevi 2014/01/24 01:21:50 naming: I find it counter-intuitive that completeW
eroman 2014/01/24 03:19:21 How about CompletedWithError() ?
Ryan Sleevi 2014/01/24 20:27:01 I still find that a bit confusing. ShouldReturnWit
eroman 2014/01/25 03:26:08 Seeing how this was confusing, I removed the funct
30 if (status.IsError()) {
31 result->completeWithError(blink::WebString::fromUTF8(status.ToString()));
32 return true;
33 }
34 return false;
35 }
36
25 bool IsAlgorithmAsymmetric(const blink::WebCryptoAlgorithm& algorithm) { 37 bool IsAlgorithmAsymmetric(const blink::WebCryptoAlgorithm& algorithm) {
26 // TODO(padolph): include all other asymmetric algorithms once they are 38 // TODO(padolph): include all other asymmetric algorithms once they are
27 // defined, e.g. EC and DH. 39 // defined, e.g. EC and DH.
28 return (algorithm.id() == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 || 40 return (algorithm.id() == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 ||
29 algorithm.id() == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 || 41 algorithm.id() == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 ||
30 algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep); 42 algorithm.id() == blink::WebCryptoAlgorithmIdRsaOaep);
31 } 43 }
32 44
33 // Binds a specific key length value to a compatible factory function. 45 // Binds a specific key length value to a compatible factory function.
34 typedef blink::WebCryptoAlgorithm (*AlgFactoryFuncWithOneShortArg)( 46 typedef blink::WebCryptoAlgorithm (*AlgFactoryFuncWithOneShortArg)(
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 } 180 }
169 181
170 void WebCryptoImpl::encrypt( 182 void WebCryptoImpl::encrypt(
171 const blink::WebCryptoAlgorithm& algorithm, 183 const blink::WebCryptoAlgorithm& algorithm,
172 const blink::WebCryptoKey& key, 184 const blink::WebCryptoKey& key,
173 const unsigned char* data, 185 const unsigned char* data,
174 unsigned data_size, 186 unsigned data_size,
175 blink::WebCryptoResult result) { 187 blink::WebCryptoResult result) {
176 DCHECK(!algorithm.isNull()); 188 DCHECK(!algorithm.isNull());
177 blink::WebArrayBuffer buffer; 189 blink::WebArrayBuffer buffer;
178 if (!EncryptInternal(algorithm, key, data, data_size, &buffer)) { 190 Status status = EncryptInternal(algorithm, key, data, data_size, &buffer);
179 result.completeWithError(); 191 if (!completeWithError(status, &result)) {
180 } else {
181 result.completeWithBuffer(buffer); 192 result.completeWithBuffer(buffer);
182 } 193 }
183 } 194 }
184 195
185 void WebCryptoImpl::decrypt( 196 void WebCryptoImpl::decrypt(
186 const blink::WebCryptoAlgorithm& algorithm, 197 const blink::WebCryptoAlgorithm& algorithm,
187 const blink::WebCryptoKey& key, 198 const blink::WebCryptoKey& key,
188 const unsigned char* data, 199 const unsigned char* data,
189 unsigned data_size, 200 unsigned data_size,
190 blink::WebCryptoResult result) { 201 blink::WebCryptoResult result) {
191 DCHECK(!algorithm.isNull()); 202 DCHECK(!algorithm.isNull());
192 blink::WebArrayBuffer buffer; 203 blink::WebArrayBuffer buffer;
193 if (!DecryptInternal(algorithm, key, data, data_size, &buffer)) { 204 Status status = DecryptInternal(algorithm, key, data, data_size, &buffer);
194 result.completeWithError(); 205 if (!completeWithError(status, &result)) {
195 } else {
196 result.completeWithBuffer(buffer); 206 result.completeWithBuffer(buffer);
197 } 207 }
198 } 208 }
199 209
200 void WebCryptoImpl::digest( 210 void WebCryptoImpl::digest(
201 const blink::WebCryptoAlgorithm& algorithm, 211 const blink::WebCryptoAlgorithm& algorithm,
202 const unsigned char* data, 212 const unsigned char* data,
203 unsigned data_size, 213 unsigned data_size,
204 blink::WebCryptoResult result) { 214 blink::WebCryptoResult result) {
205 DCHECK(!algorithm.isNull()); 215 DCHECK(!algorithm.isNull());
206 blink::WebArrayBuffer buffer; 216 blink::WebArrayBuffer buffer;
207 if (!DigestInternal(algorithm, data, data_size, &buffer)) { 217 Status status = DigestInternal(algorithm, data, data_size, &buffer);
208 result.completeWithError(); 218 if (!completeWithError(status, &result)) {
209 } else {
210 result.completeWithBuffer(buffer); 219 result.completeWithBuffer(buffer);
211 } 220 }
212 } 221 }
213 222
214 void WebCryptoImpl::generateKey( 223 void WebCryptoImpl::generateKey(
215 const blink::WebCryptoAlgorithm& algorithm, 224 const blink::WebCryptoAlgorithm& algorithm,
216 bool extractable, 225 bool extractable,
217 blink::WebCryptoKeyUsageMask usage_mask, 226 blink::WebCryptoKeyUsageMask usage_mask,
218 blink::WebCryptoResult result) { 227 blink::WebCryptoResult result) {
219 DCHECK(!algorithm.isNull()); 228 DCHECK(!algorithm.isNull());
220 if (IsAlgorithmAsymmetric(algorithm)) { 229 if (IsAlgorithmAsymmetric(algorithm)) {
221 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull(); 230 blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
222 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull(); 231 blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
223 if (!GenerateKeyPairInternal( 232 Status status = GenerateKeyPairInternal(
224 algorithm, extractable, usage_mask, &public_key, &private_key)) { 233 algorithm, extractable, usage_mask, &public_key, &private_key);
225 result.completeWithError(); 234 if (!completeWithError(status, &result)) {
226 } else {
227 DCHECK(public_key.handle()); 235 DCHECK(public_key.handle());
228 DCHECK(private_key.handle()); 236 DCHECK(private_key.handle());
229 DCHECK_EQ(algorithm.id(), public_key.algorithm().id()); 237 DCHECK_EQ(algorithm.id(), public_key.algorithm().id());
230 DCHECK_EQ(algorithm.id(), private_key.algorithm().id()); 238 DCHECK_EQ(algorithm.id(), private_key.algorithm().id());
231 DCHECK_EQ(true, public_key.extractable()); 239 DCHECK_EQ(true, public_key.extractable());
232 DCHECK_EQ(extractable, private_key.extractable()); 240 DCHECK_EQ(extractable, private_key.extractable());
233 DCHECK_EQ(usage_mask, public_key.usages()); 241 DCHECK_EQ(usage_mask, public_key.usages());
234 DCHECK_EQ(usage_mask, private_key.usages()); 242 DCHECK_EQ(usage_mask, private_key.usages());
235 result.completeWithKeyPair(public_key, private_key); 243 result.completeWithKeyPair(public_key, private_key);
236 } 244 }
237 } else { 245 } else {
238 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 246 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
239 if (!GenerateKeyInternal(algorithm, extractable, usage_mask, &key)) { 247 Status status = GenerateKeyInternal(
240 result.completeWithError(); 248 algorithm, extractable, usage_mask, &key);
241 } else { 249 if (!completeWithError(status, &result)) {
242 DCHECK(key.handle()); 250 DCHECK(key.handle());
243 DCHECK_EQ(algorithm.id(), key.algorithm().id()); 251 DCHECK_EQ(algorithm.id(), key.algorithm().id());
244 DCHECK_EQ(extractable, key.extractable()); 252 DCHECK_EQ(extractable, key.extractable());
245 DCHECK_EQ(usage_mask, key.usages()); 253 DCHECK_EQ(usage_mask, key.usages());
246 result.completeWithKey(key); 254 result.completeWithKey(key);
247 } 255 }
248 } 256 }
249 } 257 }
250 258
251 void WebCryptoImpl::importKey( 259 void WebCryptoImpl::importKey(
252 blink::WebCryptoKeyFormat format, 260 blink::WebCryptoKeyFormat format,
253 const unsigned char* key_data, 261 const unsigned char* key_data,
254 unsigned key_data_size, 262 unsigned key_data_size,
255 const blink::WebCryptoAlgorithm& algorithm_or_null, 263 const blink::WebCryptoAlgorithm& algorithm_or_null,
256 bool extractable, 264 bool extractable,
257 blink::WebCryptoKeyUsageMask usage_mask, 265 blink::WebCryptoKeyUsageMask usage_mask,
258 blink::WebCryptoResult result) { 266 blink::WebCryptoResult result) {
259 blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); 267 blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
260 if (format == blink::WebCryptoKeyFormatJwk) { 268 if (format == blink::WebCryptoKeyFormatJwk) {
261 if (!ImportKeyJwk(key_data, 269 Status status = ImportKeyJwk(key_data,
262 key_data_size, 270 key_data_size,
263 algorithm_or_null, 271 algorithm_or_null,
264 extractable, 272 extractable,
265 usage_mask, 273 usage_mask,
266 &key)) { 274 &key);
267 result.completeWithError(); 275 if (completeWithError(status, &result)) {
268 return; 276 return;
269 } 277 }
270 } else { 278 } else {
271 if (!ImportKeyInternal(format, 279 Status status = ImportKeyInternal(format,
272 key_data, 280 key_data,
273 key_data_size, 281 key_data_size,
274 algorithm_or_null, 282 algorithm_or_null,
275 extractable, 283 extractable,
276 usage_mask, 284 usage_mask,
277 &key)) { 285 &key);
278 result.completeWithError(); 286 if (completeWithError(status, &result)) {
279 return; 287 return;
280 } 288 }
281 } 289 }
282 DCHECK(key.handle()); 290 DCHECK(key.handle());
283 DCHECK(!key.algorithm().isNull()); 291 DCHECK(!key.algorithm().isNull());
284 DCHECK_EQ(extractable, key.extractable()); 292 DCHECK_EQ(extractable, key.extractable());
285 result.completeWithKey(key); 293 result.completeWithKey(key);
286 } 294 }
287 295
288 void WebCryptoImpl::exportKey( 296 void WebCryptoImpl::exportKey(
289 blink::WebCryptoKeyFormat format, 297 blink::WebCryptoKeyFormat format,
290 const blink::WebCryptoKey& key, 298 const blink::WebCryptoKey& key,
291 blink::WebCryptoResult result) { 299 blink::WebCryptoResult result) {
292 blink::WebArrayBuffer buffer; 300 blink::WebArrayBuffer buffer;
293 if (!ExportKeyInternal(format, key, &buffer)) { 301 Status status = ExportKeyInternal(format, key, &buffer);
294 result.completeWithError(); 302 if (!completeWithError(status, &result)) {
295 return; 303 result.completeWithBuffer(buffer);
296 } 304 }
297 result.completeWithBuffer(buffer);
298 } 305 }
299 306
300 void WebCryptoImpl::sign( 307 void WebCryptoImpl::sign(
301 const blink::WebCryptoAlgorithm& algorithm, 308 const blink::WebCryptoAlgorithm& algorithm,
302 const blink::WebCryptoKey& key, 309 const blink::WebCryptoKey& key,
303 const unsigned char* data, 310 const unsigned char* data,
304 unsigned data_size, 311 unsigned data_size,
305 blink::WebCryptoResult result) { 312 blink::WebCryptoResult result) {
306 DCHECK(!algorithm.isNull()); 313 DCHECK(!algorithm.isNull());
307 blink::WebArrayBuffer buffer; 314 blink::WebArrayBuffer buffer;
308 if (!SignInternal(algorithm, key, data, data_size, &buffer)) { 315 Status status = SignInternal(algorithm, key, data, data_size, &buffer);
309 result.completeWithError(); 316 if (!completeWithError(status, &result)) {
310 } else {
311 result.completeWithBuffer(buffer); 317 result.completeWithBuffer(buffer);
312 } 318 }
313 } 319 }
314 320
315 void WebCryptoImpl::verifySignature( 321 void WebCryptoImpl::verifySignature(
316 const blink::WebCryptoAlgorithm& algorithm, 322 const blink::WebCryptoAlgorithm& algorithm,
317 const blink::WebCryptoKey& key, 323 const blink::WebCryptoKey& key,
318 const unsigned char* signature, 324 const unsigned char* signature,
319 unsigned signature_size, 325 unsigned signature_size,
320 const unsigned char* data, 326 const unsigned char* data,
321 unsigned data_size, 327 unsigned data_size,
322 blink::WebCryptoResult result) { 328 blink::WebCryptoResult result) {
323 DCHECK(!algorithm.isNull()); 329 DCHECK(!algorithm.isNull());
324 bool signature_match = false; 330 bool signature_match = false;
325 if (!VerifySignatureInternal(algorithm, 331 Status status = VerifySignatureInternal(algorithm,
326 key, 332 key,
327 signature, 333 signature,
328 signature_size, 334 signature_size,
329 data, 335 data,
330 data_size, 336 data_size,
331 &signature_match)) { 337 &signature_match);
332 result.completeWithError(); 338 if (!completeWithError(status, &result)) {
333 } else {
334 result.completeWithBoolean(signature_match); 339 result.completeWithBoolean(signature_match);
335 } 340 }
336 } 341 }
337 342
338 bool WebCryptoImpl::ImportKeyJwk( 343 Status WebCryptoImpl::ImportKeyJwk(
339 const unsigned char* key_data, 344 const unsigned char* key_data,
340 unsigned key_data_size, 345 unsigned key_data_size,
341 const blink::WebCryptoAlgorithm& algorithm_or_null, 346 const blink::WebCryptoAlgorithm& algorithm_or_null,
342 bool extractable, 347 bool extractable,
343 blink::WebCryptoKeyUsageMask usage_mask, 348 blink::WebCryptoKeyUsageMask usage_mask,
344 blink::WebCryptoKey* key) { 349 blink::WebCryptoKey* key) {
345 350
346 // The goal of this method is to extract key material and meta data from the 351 // The goal of this method is to extract key material and meta data from the
347 // incoming JWK, combine them with the input parameters, and ultimately import 352 // incoming JWK, combine them with the input parameters, and ultimately import
348 // a Web Crypto Key. 353 // a Web Crypto Key.
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 // false but the input parameter is true, it is an inconsistency. If both 477 // false but the input parameter is true, it is an inconsistency. If both
473 // are true or both are false, use that value. 478 // are true or both are false, use that value.
474 // 479 //
475 // usage_mask 480 // usage_mask
476 // The input usage_mask must be a strict subset of the interpreted JWK use 481 // The input usage_mask must be a strict subset of the interpreted JWK use
477 // value, else it is judged inconsistent. In all cases the input usage_mask 482 // value, else it is judged inconsistent. In all cases the input usage_mask
478 // is used as the final usage_mask. 483 // is used as the final usage_mask.
479 // 484 //
480 485
481 if (!key_data_size) 486 if (!key_data_size)
482 return false; 487 return Status::ErrorEmptyKeyData();
483 DCHECK(key); 488 DCHECK(key);
484 489
485 // Parse the incoming JWK JSON. 490 // Parse the incoming JWK JSON.
486 base::StringPiece json_string(reinterpret_cast<const char*>(key_data), 491 base::StringPiece json_string(reinterpret_cast<const char*>(key_data),
487 key_data_size); 492 key_data_size);
488 scoped_ptr<base::Value> value(base::JSONReader::Read(json_string)); 493 scoped_ptr<base::Value> value(base::JSONReader::Read(json_string));
489 // Note, bare pointer dict_value is ok since it points into scoped value. 494 // Note, bare pointer dict_value is ok since it points into scoped value.
490 base::DictionaryValue* dict_value = NULL; 495 base::DictionaryValue* dict_value = NULL;
491 if (!value.get() || !value->GetAsDictionary(&dict_value) || !dict_value) 496 if (!value.get() || !value->GetAsDictionary(&dict_value) || !dict_value)
492 return false; 497 return Status::ErrorJwkNotDictionary();
493 498
494 // JWK "kty". Exit early if this required JWK parameter is missing. 499 // JWK "kty". Exit early if this required JWK parameter is missing.
495 std::string jwk_kty_value; 500 std::string jwk_kty_value;
496 if (!dict_value->GetString("kty", &jwk_kty_value)) 501 if (!dict_value->GetString("kty", &jwk_kty_value))
497 return false; 502 return Status::ErrorJwkMissingKty();
498 503
499 // JWK "extractable" (optional) --> extractable parameter 504 // JWK "extractable" (optional) --> extractable parameter
500 { 505 {
501 bool jwk_extractable_value; 506 bool jwk_extractable_value;
502 if (dict_value->GetBoolean("extractable", &jwk_extractable_value)) { 507 if (dict_value->GetBoolean("extractable", &jwk_extractable_value)) {
503 if (!jwk_extractable_value && extractable) 508 if (!jwk_extractable_value && extractable)
504 return false; 509 return Status::ErrorJwkExtractableInconsistent();
505 extractable = extractable && jwk_extractable_value; 510 extractable = extractable && jwk_extractable_value;
506 } 511 }
507 } 512 }
508 513
509 // JWK "alg" (optional) --> algorithm parameter 514 // JWK "alg" (optional) --> algorithm parameter
510 // Note: input algorithm is also optional, so we have six cases to handle. 515 // Note: input algorithm is also optional, so we have six cases to handle.
511 // 1. JWK alg present but unrecognized: error 516 // 1. JWK alg present but unrecognized: error
512 // 2. JWK alg valid AND input algorithm isNull: use JWK value 517 // 2. JWK alg valid AND input algorithm isNull: use JWK value
513 // 3. JWK alg valid AND input algorithm specified, but JWK value 518 // 3. JWK alg valid AND input algorithm specified, but JWK value
514 // inconsistent with input: error 519 // inconsistent with input: error
515 // 4. JWK alg valid AND input algorithm specified, both consistent: use 520 // 4. JWK alg valid AND input algorithm specified, both consistent: use
516 // input value (because it has potentially more details) 521 // input value (because it has potentially more details)
517 // 5. JWK alg missing AND input algorithm isNull: error 522 // 5. JWK alg missing AND input algorithm isNull: error
518 // 6. JWK alg missing AND input algorithm specified: use input value 523 // 6. JWK alg missing AND input algorithm specified: use input value
519 blink::WebCryptoAlgorithm algorithm = blink::WebCryptoAlgorithm::createNull(); 524 blink::WebCryptoAlgorithm algorithm = blink::WebCryptoAlgorithm::createNull();
520 std::string jwk_alg_value; 525 std::string jwk_alg_value;
521 if (dict_value->GetString("alg", &jwk_alg_value)) { 526 if (dict_value->GetString("alg", &jwk_alg_value)) {
522 // JWK alg present 527 // JWK alg present
523 528
524 // TODO(padolph): Validate alg vs kty. For example kty="RSA" implies alg can 529 // TODO(padolph): Validate alg vs kty. For example kty="RSA" implies alg can
525 // only be from the RSA family. 530 // only be from the RSA family.
526 531
527 const blink::WebCryptoAlgorithm jwk_algorithm = 532 const blink::WebCryptoAlgorithm jwk_algorithm =
528 jwk_alg_factory.Get().CreateAlgorithmFromName(jwk_alg_value); 533 jwk_alg_factory.Get().CreateAlgorithmFromName(jwk_alg_value);
529 if (jwk_algorithm.isNull()) { 534 if (jwk_algorithm.isNull()) {
530 // JWK alg unrecognized 535 // JWK alg unrecognized
531 return false; // case 1 536 return Status::ErrorJwkUnrecognizedAlgorithm(); // case 1
532 } 537 }
533 // JWK alg valid 538 // JWK alg valid
534 if (algorithm_or_null.isNull()) { 539 if (algorithm_or_null.isNull()) {
535 // input algorithm not specified 540 // input algorithm not specified
536 algorithm = jwk_algorithm; // case 2 541 algorithm = jwk_algorithm; // case 2
537 } else { 542 } else {
538 // input algorithm specified 543 // input algorithm specified
539 if (!WebCryptoAlgorithmsConsistent(jwk_algorithm, algorithm_or_null)) 544 if (!WebCryptoAlgorithmsConsistent(jwk_algorithm, algorithm_or_null))
540 return false; // case 3 545 return Status::ErrorJwkAlgorithmInconsistent(); // case 3
541 algorithm = algorithm_or_null; // case 4 546 algorithm = algorithm_or_null; // case 4
542 } 547 }
543 } else { 548 } else {
544 // JWK alg missing 549 // JWK alg missing
545 if (algorithm_or_null.isNull()) 550 if (algorithm_or_null.isNull())
546 return false; // case 5 551 return Status::ErrorJwkAlgorithmMissing(); // case 5
547 algorithm = algorithm_or_null; // case 6 552 algorithm = algorithm_or_null; // case 6
548 } 553 }
549 DCHECK(!algorithm.isNull()); 554 DCHECK(!algorithm.isNull());
550 555
551 // JWK "use" (optional) --> usage_mask parameter 556 // JWK "use" (optional) --> usage_mask parameter
552 std::string jwk_use_value; 557 std::string jwk_use_value;
553 if (dict_value->GetString("use", &jwk_use_value)) { 558 if (dict_value->GetString("use", &jwk_use_value)) {
554 blink::WebCryptoKeyUsageMask jwk_usage_mask = 0; 559 blink::WebCryptoKeyUsageMask jwk_usage_mask = 0;
555 if (jwk_use_value == "enc") { 560 if (jwk_use_value == "enc") {
556 jwk_usage_mask = 561 jwk_usage_mask =
557 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt; 562 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageDecrypt;
558 } else if (jwk_use_value == "sig") { 563 } else if (jwk_use_value == "sig") {
559 jwk_usage_mask = 564 jwk_usage_mask =
560 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify; 565 blink::WebCryptoKeyUsageSign | blink::WebCryptoKeyUsageVerify;
561 } else if (jwk_use_value == "wrap") { 566 } else if (jwk_use_value == "wrap") {
562 jwk_usage_mask = 567 jwk_usage_mask =
563 blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey; 568 blink::WebCryptoKeyUsageWrapKey | blink::WebCryptoKeyUsageUnwrapKey;
564 } else { 569 } else {
565 return false; 570 return Status::ErrorJwkUnrecognizedUsage();
566 } 571 }
567 if ((jwk_usage_mask & usage_mask) != usage_mask) { 572 if ((jwk_usage_mask & usage_mask) != usage_mask) {
568 // A usage_mask must be a subset of jwk_usage_mask. 573 // A usage_mask must be a subset of jwk_usage_mask.
569 return false; 574 return Status::ErrorJwkUsageInconsistent();
570 } 575 }
571 } 576 }
572 577
573 // JWK keying material --> ImportKeyInternal() 578 // JWK keying material --> ImportKeyInternal()
574 if (jwk_kty_value == "oct") { 579 if (jwk_kty_value == "oct") {
575 580
576 std::string jwk_k_value; 581 std::string jwk_k_value;
577 if (!GetDecodedUrl64ValueByKey(*dict_value, "k", &jwk_k_value)) 582 if (!GetDecodedUrl64ValueByKey(*dict_value, "k", &jwk_k_value))
578 return false; 583 return Status::ErrorJwkDecodeK();
579 584
580 // TODO(padolph): Some JWK alg ID's embed information about the key length 585 // TODO(padolph): Some JWK alg ID's embed information about the key length
581 // in the alg ID string. For example "A128" implies the JWK carries 128 bits 586 // in the alg ID string. For example "A128" implies the JWK carries 128 bits
582 // of key material, and "HS512" implies the JWK carries _at least_ 512 bits 587 // of key material, and "HS512" implies the JWK carries _at least_ 512 bits
583 // of key material. For such keys validate the actual key length against the 588 // of key material. For such keys validate the actual key length against the
584 // value in the ID. 589 // value in the ID.
585 590
586 return ImportKeyInternal(blink::WebCryptoKeyFormatRaw, 591 return ImportKeyInternal(blink::WebCryptoKeyFormatRaw,
587 reinterpret_cast<const uint8*>(jwk_k_value.data()), 592 reinterpret_cast<const uint8*>(jwk_k_value.data()),
588 jwk_k_value.size(), 593 jwk_k_value.size(),
589 algorithm, 594 algorithm,
590 extractable, 595 extractable,
591 usage_mask, 596 usage_mask,
592 key); 597 key);
593 } else if (jwk_kty_value == "RSA") { 598 } else if (jwk_kty_value == "RSA") {
594 599
595 // An RSA public key must have an "n" (modulus) and an "e" (exponent) entry 600 // An RSA public key must have an "n" (modulus) and an "e" (exponent) entry
596 // in the JWK, while an RSA private key must have those, plus at least a "d" 601 // in the JWK, while an RSA private key must have those, plus at least a "d"
597 // (private exponent) entry. 602 // (private exponent) entry.
598 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18, 603 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18,
599 // section 6.3. 604 // section 6.3.
600 605
601 // RSA private key import is not currently supported, so fail here if a "d" 606 // RSA private key import is not currently supported, so fail here if a "d"
602 // entry is found. 607 // entry is found.
603 // TODO(padolph): Support RSA private key import. 608 // TODO(padolph): Support RSA private key import.
604 if (dict_value->HasKey("d")) 609 if (dict_value->HasKey("d"))
605 return false; 610 return Status::ErrorJwkRsaPrivateKeyUnsupported();
606 611
607 std::string jwk_n_value; 612 std::string jwk_n_value;
608 if (!GetDecodedUrl64ValueByKey(*dict_value, "n", &jwk_n_value)) 613 if (!GetDecodedUrl64ValueByKey(*dict_value, "n", &jwk_n_value))
609 return false; 614 return Status::ErrorJwkDecodeN();
610 std::string jwk_e_value; 615 std::string jwk_e_value;
611 if (!GetDecodedUrl64ValueByKey(*dict_value, "e", &jwk_e_value)) 616 if (!GetDecodedUrl64ValueByKey(*dict_value, "e", &jwk_e_value))
612 return false; 617 return Status::ErrorJwkDecodeE();
613 618
614 return ImportRsaPublicKeyInternal( 619 return ImportRsaPublicKeyInternal(
615 reinterpret_cast<const uint8*>(jwk_n_value.data()), 620 reinterpret_cast<const uint8*>(jwk_n_value.data()),
616 jwk_n_value.size(), 621 jwk_n_value.size(),
617 reinterpret_cast<const uint8*>(jwk_e_value.data()), 622 reinterpret_cast<const uint8*>(jwk_e_value.data()),
618 jwk_e_value.size(), 623 jwk_e_value.size(),
619 algorithm, 624 algorithm,
620 extractable, 625 extractable,
621 usage_mask, 626 usage_mask,
622 key); 627 key);
623 628
624 } else { 629 } else {
625 return false; 630 return Status::ErrorJwkUnrecognizedKty();
626 } 631 }
627 632
628 return true; 633 return Status::Success();
629 } 634 }
630 635
631 } // namespace content 636 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698