Chromium Code Reviews| 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/platform_crypto.h" | 9 #include "content/child/webcrypto/platform_crypto.h" |
| 10 #include "content/child/webcrypto/webcrypto_util.h" | 10 #include "content/child/webcrypto/webcrypto_util.h" |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 226 return Status::Error(); | 226 return Status::Error(); |
| 227 // Fallthrough intentional! | 227 // Fallthrough intentional! |
| 228 case blink::WebCryptoAlgorithmIdHmac: | 228 case blink::WebCryptoAlgorithmIdHmac: |
| 229 return platform::ImportKeyRaw( | 229 return platform::ImportKeyRaw( |
| 230 algorithm_or_null, key_data, extractable, usage_mask, key); | 230 algorithm_or_null, key_data, extractable, usage_mask, key); |
| 231 default: | 231 default: |
| 232 return Status::ErrorUnsupported(); | 232 return Status::ErrorUnsupported(); |
| 233 } | 233 } |
| 234 } | 234 } |
| 235 | 235 |
| 236 // Returns the key format to use for structured cloning. | |
| 237 blink::WebCryptoKeyFormat GetCloneFormatForKeyType( | |
| 238 blink::WebCryptoKeyType type) { | |
| 239 switch (type) { | |
| 240 case blink::WebCryptoKeyTypeSecret: | |
| 241 return blink::WebCryptoKeyFormatRaw; | |
| 242 case blink::WebCryptoKeyTypePublic: | |
| 243 return blink::WebCryptoKeyFormatSpki; | |
| 244 case blink::WebCryptoKeyTypePrivate: | |
| 245 return blink::WebCryptoKeyFormatPkcs8; | |
| 246 } | |
| 247 | |
| 248 NOTREACHED(); | |
| 249 return blink::WebCryptoKeyFormatRaw; | |
| 250 } | |
| 251 | |
| 252 // Converts a KeyAlgorithm into an equivalent Algorithm for import. | |
| 253 blink::WebCryptoAlgorithm KeyAlgorithmToImportAlgorithm( | |
| 254 const blink::WebCryptoKeyAlgorithm& algorithm) { | |
| 255 switch (algorithm.paramsType()) { | |
| 256 case blink::WebCryptoKeyAlgorithmParamsTypeAes: | |
| 257 case blink::WebCryptoKeyAlgorithmParamsTypeRsa: | |
| 258 return CreateAlgorithm(algorithm.id()); | |
| 259 case blink::WebCryptoKeyAlgorithmParamsTypeHmac: | |
| 260 return CreateHmacImportAlgorithm(algorithm.hmacParams()->hash().id()); | |
| 261 case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed: | |
| 262 return CreateRsaHashedImportAlgorithm( | |
| 263 algorithm.id(), algorithm.rsaHashedParams()->hash().id()); | |
| 264 case blink::WebCryptoKeyAlgorithmParamsTypeNone: | |
| 265 break; | |
| 266 } | |
| 267 return blink::WebCryptoAlgorithm::createNull(); | |
| 268 } | |
| 269 | |
| 270 // There is some duplicated information in the serialized format used by | |
| 271 // structured clone (since the KeyAlgorithm is serialized separately from the | |
| 272 // key data). Use this extra information to further validate what was | |
| 273 // deserialized from the key data. | |
| 274 // | |
| 275 // A failure here implies either a bug in the code, or that the serialized data | |
| 276 // was corrupted. | |
| 277 Status ValidateDeserializedKey(const blink::WebCryptoKey& key, | |
| 278 const blink::WebCryptoKeyAlgorithm& algorithm, | |
| 279 blink::WebCryptoKeyType type) { | |
| 280 if (algorithm.id() != key.algorithm().id()) | |
| 281 return Status::ErrorUnexpected(); | |
| 282 | |
| 283 if (key.type() != type) | |
| 284 return Status::ErrorUnexpected(); | |
| 285 | |
| 286 switch (algorithm.paramsType()) { | |
| 287 case blink::WebCryptoKeyAlgorithmParamsTypeAes: | |
| 288 if (algorithm.aesParams()->lengthBits() != | |
| 289 key.algorithm().aesParams()->lengthBits()) | |
| 290 return Status::ErrorUnexpected(); | |
| 291 break; | |
| 292 case blink::WebCryptoKeyAlgorithmParamsTypeRsa: | |
| 293 case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed: | |
| 294 if (algorithm.rsaParams()->modulusLengthBits() != | |
| 295 key.algorithm().rsaParams()->modulusLengthBits()) | |
| 296 return Status::ErrorUnexpected(); | |
| 297 if (algorithm.rsaParams()->publicExponent().size() != | |
| 298 key.algorithm().rsaParams()->publicExponent().size()) | |
| 299 return Status::ErrorUnexpected(); | |
| 300 if (memcmp(algorithm.rsaParams()->publicExponent().data(), | |
| 301 key.algorithm().rsaParams()->publicExponent().data(), | |
| 302 key.algorithm().rsaParams()->publicExponent().size()) != 0) | |
| 303 return Status::ErrorUnexpected(); | |
| 304 break; | |
| 305 case blink::WebCryptoKeyAlgorithmParamsTypeNone: | |
| 306 case blink::WebCryptoKeyAlgorithmParamsTypeHmac: | |
| 307 break; | |
| 308 } | |
| 309 | |
| 310 return Status::Success(); | |
| 311 } | |
| 312 | |
| 236 } // namespace | 313 } // namespace |
| 237 | 314 |
| 238 void Init() { platform::Init(); } | 315 void Init() { platform::Init(); } |
| 239 | 316 |
| 240 Status Encrypt(const blink::WebCryptoAlgorithm& algorithm, | 317 Status Encrypt(const blink::WebCryptoAlgorithm& algorithm, |
| 241 const blink::WebCryptoKey& key, | 318 const blink::WebCryptoKey& key, |
| 242 const CryptoData& data, | 319 const CryptoData& data, |
| 243 blink::WebArrayBuffer* buffer) { | 320 blink::WebArrayBuffer* buffer) { |
| 244 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageEncrypt)) | 321 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageEncrypt)) |
| 245 return Status::ErrorUnexpected(); | 322 return Status::ErrorUnexpected(); |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 402 return platform::ImportKeyPkcs8( | 479 return platform::ImportKeyPkcs8( |
| 403 algorithm_or_null, key_data, extractable, usage_mask, key); | 480 algorithm_or_null, key_data, extractable, usage_mask, key); |
| 404 case blink::WebCryptoKeyFormatJwk: | 481 case blink::WebCryptoKeyFormatJwk: |
| 405 return ImportKeyJwk( | 482 return ImportKeyJwk( |
| 406 key_data, algorithm_or_null, extractable, usage_mask, key); | 483 key_data, algorithm_or_null, extractable, usage_mask, key); |
| 407 default: | 484 default: |
| 408 return Status::ErrorUnsupported(); | 485 return Status::ErrorUnsupported(); |
| 409 } | 486 } |
| 410 } | 487 } |
| 411 | 488 |
| 412 Status ExportKey(blink::WebCryptoKeyFormat format, | 489 // TODO(eroman): Move this to anonymous namespace. |
| 413 const blink::WebCryptoKey& key, | 490 Status ExportKeyDontCheckExtractability(blink::WebCryptoKeyFormat format, |
| 414 blink::WebArrayBuffer* buffer) { | 491 const blink::WebCryptoKey& key, |
| 415 if (!key.extractable()) | 492 blink::WebArrayBuffer* buffer) { |
| 416 return Status::ErrorKeyNotExtractable(); | |
| 417 | |
| 418 switch (format) { | 493 switch (format) { |
| 419 case blink::WebCryptoKeyFormatRaw: { | 494 case blink::WebCryptoKeyFormatRaw: { |
| 420 platform::SymKey* sym_key; | 495 platform::SymKey* sym_key; |
| 421 Status status = ToPlatformSymKey(key, &sym_key); | 496 Status status = ToPlatformSymKey(key, &sym_key); |
| 422 if (status.IsError()) | 497 if (status.IsError()) |
| 423 return status; | 498 return status; |
| 424 return platform::ExportKeyRaw(sym_key, buffer); | 499 return platform::ExportKeyRaw(sym_key, buffer); |
| 425 } | 500 } |
| 426 case blink::WebCryptoKeyFormatSpki: { | 501 case blink::WebCryptoKeyFormatSpki: { |
| 427 platform::PublicKey* public_key; | 502 platform::PublicKey* public_key; |
| 428 Status status = ToPlatformPublicKey(key, &public_key); | 503 Status status = ToPlatformPublicKey(key, &public_key); |
| 429 if (status.IsError()) | 504 if (status.IsError()) |
| 430 return status; | 505 return status; |
| 431 return platform::ExportKeySpki(public_key, buffer); | 506 return platform::ExportKeySpki(public_key, buffer); |
| 432 } | 507 } |
| 433 case blink::WebCryptoKeyFormatPkcs8: | 508 case blink::WebCryptoKeyFormatPkcs8: |
| 434 case blink::WebCryptoKeyFormatJwk: | 509 case blink::WebCryptoKeyFormatJwk: |
| 435 // TODO(eroman): | 510 // TODO(eroman): |
| 436 return Status::ErrorUnsupported(); | 511 return Status::ErrorUnsupported(); |
| 437 default: | 512 default: |
| 438 return Status::ErrorUnsupported(); | 513 return Status::ErrorUnsupported(); |
| 439 } | 514 } |
| 440 } | 515 } |
| 441 | 516 |
| 517 Status ExportKey(blink::WebCryptoKeyFormat format, | |
| 518 const blink::WebCryptoKey& key, | |
| 519 blink::WebArrayBuffer* buffer) { | |
| 520 if (!key.extractable()) | |
| 521 return Status::ErrorKeyNotExtractable(); | |
| 522 return ExportKeyDontCheckExtractability(format, key, buffer); | |
| 523 } | |
| 524 | |
| 442 Status Sign(const blink::WebCryptoAlgorithm& algorithm, | 525 Status Sign(const blink::WebCryptoAlgorithm& algorithm, |
| 443 const blink::WebCryptoKey& key, | 526 const blink::WebCryptoKey& key, |
| 444 const CryptoData& data, | 527 const CryptoData& data, |
| 445 blink::WebArrayBuffer* buffer) { | 528 blink::WebArrayBuffer* buffer) { |
| 446 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageSign)) | 529 if (!KeyUsageAllows(key, blink::WebCryptoKeyUsageSign)) |
| 447 return Status::ErrorUnexpected(); | 530 return Status::ErrorUnexpected(); |
| 448 if (algorithm.id() != key.algorithm().id()) | 531 if (algorithm.id() != key.algorithm().id()) |
| 449 return Status::ErrorUnexpected(); | 532 return Status::ErrorUnexpected(); |
| 450 | 533 |
| 451 switch (algorithm.id()) { | 534 switch (algorithm.id()) { |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 563 algorithm_or_null, | 646 algorithm_or_null, |
| 564 extractable, | 647 extractable, |
| 565 usage_mask, | 648 usage_mask, |
| 566 key); | 649 key); |
| 567 } | 650 } |
| 568 default: | 651 default: |
| 569 return Status::ErrorUnsupported(); | 652 return Status::ErrorUnsupported(); |
| 570 } | 653 } |
| 571 } | 654 } |
| 572 | 655 |
| 656 Status SerializeKeyForClone(const blink::WebCryptoKey& key, | |
| 657 blink::WebVector<unsigned char>* data) { | |
| 658 blink::WebArrayBuffer buffer; | |
| 659 Status status = ExportKeyDontCheckExtractability( | |
| 660 GetCloneFormatForKeyType(key.type()), key, &buffer); | |
| 661 if (status.IsError()) | |
| 662 return status; | |
| 663 *data = blink::WebVector<unsigned char>( | |
| 664 reinterpret_cast<unsigned char*>(buffer.data()), buffer.byteLength()); | |
|
Ryan Sleevi
2014/03/12 23:18:41
This seems to follow a double-allocation strategy
eroman
2014/03/13 00:32:33
Changed to data->assign()
Oops, not sure what tha
| |
| 665 return Status::Success(); | |
| 666 } | |
| 667 | |
| 668 Status DeserializeKeyForClone(const blink::WebCryptoKeyAlgorithm& algorithm, | |
| 669 blink::WebCryptoKeyType type, | |
| 670 bool extractable, | |
| 671 blink::WebCryptoKeyUsageMask usage_mask, | |
| 672 const CryptoData& key_data, | |
| 673 blink::WebCryptoKey* key) { | |
| 674 Status status = ImportKey(GetCloneFormatForKeyType(type), | |
| 675 key_data, | |
| 676 KeyAlgorithmToImportAlgorithm(algorithm), | |
| 677 extractable, | |
| 678 usage_mask, | |
| 679 key); | |
| 680 if (status.IsError()) | |
| 681 return status; | |
| 682 | |
| 683 return ValidateDeserializedKey(*key, algorithm, type); | |
| 684 } | |
| 685 | |
| 573 } // namespace webcrypto | 686 } // namespace webcrypto |
| 574 | 687 |
| 575 } // namespace content | 688 } // namespace content |
| OLD | NEW |