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

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

Powered by Google App Engine
This is Rietveld 408576698