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

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

Powered by Google App Engine
This is Rietveld 408576698