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 "jwk.h" | 5 #include "jwk.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <functional> | 8 #include <functional> |
9 #include <map> | 9 #include <map> |
10 | 10 |
11 #include "base/json/json_reader.h" | 11 #include "base/json/json_reader.h" |
12 #include "base/json/json_writer.h" | 12 #include "base/json/json_writer.h" |
13 #include "base/lazy_instance.h" | 13 #include "base/lazy_instance.h" |
14 #include "base/strings/string_piece.h" | 14 #include "base/strings/string_piece.h" |
15 #include "base/strings/stringprintf.h" | 15 #include "base/strings/stringprintf.h" |
16 #include "content/child/webcrypto/crypto_data.h" | 16 #include "content/child/webcrypto/crypto_data.h" |
17 #include "content/child/webcrypto/platform_crypto.h" | 17 #include "content/child/webcrypto/platform_crypto.h" |
18 #include "content/child/webcrypto/shared_crypto.h" | 18 #include "content/child/webcrypto/shared_crypto.h" |
19 #include "content/child/webcrypto/status.h" | 19 #include "content/child/webcrypto/status.h" |
20 #include "content/child/webcrypto/webcrypto_util.h" | 20 #include "content/child/webcrypto/webcrypto_util.h" |
21 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" | 21 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" |
22 | 22 |
| 23 // JSON Web Key Format (JWK) |
| 24 // http://tools.ietf.org/html/draft-ietf-jose-json-web-key-21 |
| 25 // |
| 26 // A JWK is a simple JSON dictionary with the following entries |
| 27 // - "kty" (Key Type) Parameter, REQUIRED |
| 28 // - <kty-specific parameters, see below>, REQUIRED |
| 29 // - "use" (Key Use) Parameter, OPTIONAL |
| 30 // - "key_ops" (Key Operations) Parameter, OPTIONAL |
| 31 // - "alg" (Algorithm) Parameter, OPTIONAL |
| 32 // - "ext" (Key Exportability), OPTIONAL |
| 33 // (all other entries are ignored) |
| 34 // |
| 35 // OPTIONAL here means that this code does not require the entry to be present |
| 36 // in the incoming JWK, because the method input parameters contain similar |
| 37 // information. If the optional JWK entry is present, it will be validated |
| 38 // against the corresponding input parameter for consistency and combined with |
| 39 // it according to rules defined below. |
| 40 // |
| 41 // Input 'key_data' contains the JWK. To build a Web Crypto Key, the JWK |
| 42 // values are parsed out and combined with the method input parameters to |
| 43 // build a Web Crypto Key: |
| 44 // Web Crypto Key type <-- (deduced) |
| 45 // Web Crypto Key extractable <-- JWK ext + input extractable |
| 46 // Web Crypto Key algorithm <-- JWK alg + input algorithm |
| 47 // Web Crypto Key keyUsage <-- JWK use, key_ops + input usage_mask |
| 48 // Web Crypto Key keying material <-- kty-specific parameters |
| 49 // |
| 50 // Values for each JWK entry are case-sensitive and defined in |
| 51 // http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18. |
| 52 // Note that not all values specified by JOSE are handled by this code. Only |
| 53 // handled values are listed. |
| 54 // - kty (Key Type) |
| 55 // +-------+--------------------------------------------------------------+ |
| 56 // | "RSA" | RSA [RFC3447] | |
| 57 // | "oct" | Octet sequence (used to represent symmetric keys) | |
| 58 // +-------+--------------------------------------------------------------+ |
| 59 // |
| 60 // - key_ops (Key Use Details) |
| 61 // The key_ops field is an array that contains one or more strings from |
| 62 // the table below, and describes the operations for which this key may be |
| 63 // used. |
| 64 // +-------+--------------------------------------------------------------+ |
| 65 // | "encrypt" | encrypt operations | |
| 66 // | "decrypt" | decrypt operations | |
| 67 // | "sign" | sign (MAC) operations | |
| 68 // | "verify" | verify (MAC) operations | |
| 69 // | "wrapKey" | key wrap | |
| 70 // | "unwrapKey" | key unwrap | |
| 71 // | "deriveKey" | key derivation | |
| 72 // | "deriveBits" | key derivation TODO(padolph): not currently supported | |
| 73 // +-------+--------------------------------------------------------------+ |
| 74 // |
| 75 // - use (Key Use) |
| 76 // The use field contains a single entry from the table below. |
| 77 // +-------+--------------------------------------------------------------+ |
| 78 // | "sig" | equivalent to key_ops of [sign, verify] | |
| 79 // | "enc" | equivalent to key_ops of [encrypt, decrypt, wrapKey, | |
| 80 // | | unwrapKey, deriveKey, deriveBits] | |
| 81 // +-------+--------------------------------------------------------------+ |
| 82 // |
| 83 // NOTE: If both "use" and "key_ops" JWK members are present, the usages |
| 84 // specified by them MUST be consistent. In particular, the "use" value |
| 85 // "sig" corresponds to "sign" and/or "verify". The "use" value "enc" |
| 86 // corresponds to all other values defined above. If "key_ops" values |
| 87 // corresponding to both "sig" and "enc" "use" values are present, the "use" |
| 88 // member SHOULD NOT be present, and if present, its value MUST NOT be |
| 89 // either "sig" or "enc". |
| 90 // |
| 91 // - ext (Key Exportability) |
| 92 // +-------+--------------------------------------------------------------+ |
| 93 // | true | Key may be exported from the trusted environment | |
| 94 // | false | Key cannot exit the trusted environment | |
| 95 // +-------+--------------------------------------------------------------+ |
| 96 // |
| 97 // - alg (Algorithm) |
| 98 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18 |
| 99 // +--------------+-------------------------------------------------------+ |
| 100 // | Digital Signature or MAC Algorithm | |
| 101 // +--------------+-------------------------------------------------------+ |
| 102 // | "HS1" | HMAC using SHA-1 hash algorithm | |
| 103 // | "HS256" | HMAC using SHA-256 hash algorithm | |
| 104 // | "HS384" | HMAC using SHA-384 hash algorithm | |
| 105 // | "HS512" | HMAC using SHA-512 hash algorithm | |
| 106 // | "RS1" | RSASSA using SHA-1 hash algorithm |
| 107 // | "RS256" | RSASSA using SHA-256 hash algorithm | |
| 108 // | "RS384" | RSASSA using SHA-384 hash algorithm | |
| 109 // | "RS512" | RSASSA using SHA-512 hash algorithm | |
| 110 // +--------------+-------------------------------------------------------| |
| 111 // | Key Management Algorithm | |
| 112 // +--------------+-------------------------------------------------------+ |
| 113 // | "RSA1_5" | RSAES-PKCS1-V1_5 [RFC3447] | |
| 114 // | "RSA-OAEP" | RSAES using Optimal Asymmetric Encryption Padding | |
| 115 // | | (OAEP) [RFC3447], with the default parameters | |
| 116 // | | specified by RFC3447 in Section A.2.1 | |
| 117 // | "A128KW" | Advanced Encryption Standard (AES) Key Wrap Algorithm | |
| 118 // | | [RFC3394] using 128 bit keys | |
| 119 // | "A192KW" | AES Key Wrap Algorithm using 192 bit keys | |
| 120 // | "A256KW" | AES Key Wrap Algorithm using 256 bit keys | |
| 121 // | "A128GCM" | AES in Galois/Counter Mode (GCM) [NIST.800-38D] using | |
| 122 // | | 128 bit keys | |
| 123 // | "A192GCM" | AES GCM using 192 bit keys | |
| 124 // | "A256GCM" | AES GCM using 256 bit keys | |
| 125 // | "A128CBC" | AES in Cipher Block Chaining Mode (CBC) with PKCS #5 | |
| 126 // | | padding [NIST.800-38A] | |
| 127 // | "A192CBC" | AES CBC using 192 bit keys | |
| 128 // | "A256CBC" | AES CBC using 256 bit keys | |
| 129 // +--------------+-------------------------------------------------------+ |
| 130 // |
| 131 // kty-specific parameters |
| 132 // The value of kty determines the type and content of the keying material |
| 133 // carried in the JWK to be imported. Currently only two possibilities are |
| 134 // supported: a raw key or an RSA public key. RSA private keys are not |
| 135 // supported because typical applications seldom need to import a private key, |
| 136 // and the large number of JWK parameters required to describe one. |
| 137 // - kty == "oct" (symmetric or other raw key) |
| 138 // +-------+--------------------------------------------------------------+ |
| 139 // | "k" | Contains the value of the symmetric (or other single-valued) | |
| 140 // | | key. It is represented as the base64url encoding of the | |
| 141 // | | octet sequence containing the key value. | |
| 142 // +-------+--------------------------------------------------------------+ |
| 143 // - kty == "RSA" (RSA public key) |
| 144 // +-------+--------------------------------------------------------------+ |
| 145 // | "n" | Contains the modulus value for the RSA public key. It is | |
| 146 // | | represented as the base64url encoding of the value's | |
| 147 // | | unsigned big endian representation as an octet sequence. | |
| 148 // +-------+--------------------------------------------------------------+ |
| 149 // | "e" | Contains the exponent value for the RSA public key. It is | |
| 150 // | | represented as the base64url encoding of the value's | |
| 151 // | | unsigned big endian representation as an octet sequence. | |
| 152 // +-------+--------------------------------------------------------------+ |
| 153 // |
| 154 // Consistency and conflict resolution |
| 155 // The 'algorithm', 'extractable', and 'usage_mask' input parameters |
| 156 // may be different than the corresponding values inside the JWK. The Web |
| 157 // Crypto spec says that if a JWK value is present but is inconsistent with |
| 158 // the input value, it is an error and the operation must fail. If no |
| 159 // inconsistency is found then the input parameters are used. |
| 160 // |
| 161 // algorithm |
| 162 // If the JWK algorithm is provided, it must match the web crypto input |
| 163 // algorithm (both the algorithm ID and inner hash if applicable). |
| 164 // |
| 165 // extractable |
| 166 // If the JWK ext field is true but the input parameter is false, make the |
| 167 // Web Crypto Key non-extractable. Conversely, if the JWK ext field is |
| 168 // false but the input parameter is true, it is an inconsistency. If both |
| 169 // are true or both are false, use that value. |
| 170 // |
| 171 // usage_mask |
| 172 // The input usage_mask must be a strict subset of the interpreted JWK use |
| 173 // value, else it is judged inconsistent. In all cases the input usage_mask |
| 174 // is used as the final usage_mask. |
| 175 // |
| 176 |
23 namespace content { | 177 namespace content { |
24 | 178 |
25 namespace webcrypto { | 179 namespace webcrypto { |
26 | 180 |
27 namespace { | 181 namespace { |
28 | 182 |
29 // Creates an RSASSA-PKCS1-v1_5 algorithm. It is an error to call this with a | 183 // Creates an RSASSA-PKCS1-v1_5 algorithm. It is an error to call this with a |
30 // hash_id that is not a SHA*. | 184 // hash_id that is not a SHA*. |
31 blink::WebCryptoAlgorithm CreateRsaSsaImportAlgorithm( | 185 blink::WebCryptoAlgorithm CreateRsaSsaImportAlgorithm( |
32 blink::WebCryptoAlgorithmId hash_id) { | 186 blink::WebCryptoAlgorithmId hash_id) { |
(...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
456 return Status::Success(); | 610 return Status::Success(); |
457 } | 611 } |
458 | 612 |
459 } // namespace | 613 } // namespace |
460 | 614 |
461 Status ImportKeyJwk(const CryptoData& key_data, | 615 Status ImportKeyJwk(const CryptoData& key_data, |
462 const blink::WebCryptoAlgorithm& algorithm, | 616 const blink::WebCryptoAlgorithm& algorithm, |
463 bool extractable, | 617 bool extractable, |
464 blink::WebCryptoKeyUsageMask usage_mask, | 618 blink::WebCryptoKeyUsageMask usage_mask, |
465 blink::WebCryptoKey* key) { | 619 blink::WebCryptoKey* key) { |
466 // TODO(padolph): Generalize this comment to include export, and move to top | |
467 // of file. | |
468 | |
469 // The goal of this method is to extract key material and meta data from the | |
470 // incoming JWK, combine them with the input parameters, and ultimately import | |
471 // a Web Crypto Key. | |
472 // | |
473 // JSON Web Key Format (JWK) | |
474 // http://tools.ietf.org/html/draft-ietf-jose-json-web-key-21 | |
475 // | |
476 // A JWK is a simple JSON dictionary with the following entries | |
477 // - "kty" (Key Type) Parameter, REQUIRED | |
478 // - <kty-specific parameters, see below>, REQUIRED | |
479 // - "use" (Key Use) Parameter, OPTIONAL | |
480 // - "key_ops" (Key Operations) Parameter, OPTIONAL | |
481 // - "alg" (Algorithm) Parameter, OPTIONAL | |
482 // - "ext" (Key Exportability), OPTIONAL | |
483 // (all other entries are ignored) | |
484 // | |
485 // OPTIONAL here means that this code does not require the entry to be present | |
486 // in the incoming JWK, because the method input parameters contain similar | |
487 // information. If the optional JWK entry is present, it will be validated | |
488 // against the corresponding input parameter for consistency and combined with | |
489 // it according to rules defined below. A special case is that the method | |
490 // input parameter 'algorithm' is also optional. If it is null, the JWK 'alg' | |
491 // value (if present) is used as a fallback. | |
492 // | |
493 // Input 'key_data' contains the JWK. To build a Web Crypto Key, the JWK | |
494 // values are parsed out and combined with the method input parameters to | |
495 // build a Web Crypto Key: | |
496 // Web Crypto Key type <-- (deduced) | |
497 // Web Crypto Key extractable <-- JWK ext + input extractable | |
498 // Web Crypto Key algorithm <-- JWK alg + input algorithm | |
499 // Web Crypto Key keyUsage <-- JWK use, key_ops + input usage_mask | |
500 // Web Crypto Key keying material <-- kty-specific parameters | |
501 // | |
502 // Values for each JWK entry are case-sensitive and defined in | |
503 // http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18. | |
504 // Note that not all values specified by JOSE are handled by this code. Only | |
505 // handled values are listed. | |
506 // - kty (Key Type) | |
507 // +-------+--------------------------------------------------------------+ | |
508 // | "RSA" | RSA [RFC3447] | | |
509 // | "oct" | Octet sequence (used to represent symmetric keys) | | |
510 // +-------+--------------------------------------------------------------+ | |
511 // | |
512 // - key_ops (Key Use Details) | |
513 // The key_ops field is an array that contains one or more strings from | |
514 // the table below, and describes the operations for which this key may be | |
515 // used. | |
516 // +-------+--------------------------------------------------------------+ | |
517 // | "encrypt" | encrypt operations | | |
518 // | "decrypt" | decrypt operations | | |
519 // | "sign" | sign (MAC) operations | | |
520 // | "verify" | verify (MAC) operations | | |
521 // | "wrapKey" | key wrap | | |
522 // | "unwrapKey" | key unwrap | | |
523 // | "deriveKey" | key derivation | | |
524 // | "deriveBits" | key derivation TODO(padolph): not currently supported | | |
525 // +-------+--------------------------------------------------------------+ | |
526 // | |
527 // - use (Key Use) | |
528 // The use field contains a single entry from the table below. | |
529 // +-------+--------------------------------------------------------------+ | |
530 // | "sig" | equivalent to key_ops of [sign, verify] | | |
531 // | "enc" | equivalent to key_ops of [encrypt, decrypt, wrapKey, | | |
532 // | | unwrapKey, deriveKey, deriveBits] | | |
533 // +-------+--------------------------------------------------------------+ | |
534 // | |
535 // NOTE: If both "use" and "key_ops" JWK members are present, the usages | |
536 // specified by them MUST be consistent. In particular, the "use" value | |
537 // "sig" corresponds to "sign" and/or "verify". The "use" value "enc" | |
538 // corresponds to all other values defined above. If "key_ops" values | |
539 // corresponding to both "sig" and "enc" "use" values are present, the "use" | |
540 // member SHOULD NOT be present, and if present, its value MUST NOT be | |
541 // either "sig" or "enc". | |
542 // | |
543 // - ext (Key Exportability) | |
544 // +-------+--------------------------------------------------------------+ | |
545 // | true | Key may be exported from the trusted environment | | |
546 // | false | Key cannot exit the trusted environment | | |
547 // +-------+--------------------------------------------------------------+ | |
548 // | |
549 // - alg (Algorithm) | |
550 // See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-18 | |
551 // +--------------+-------------------------------------------------------+ | |
552 // | Digital Signature or MAC Algorithm | | |
553 // +--------------+-------------------------------------------------------+ | |
554 // | "HS1" | HMAC using SHA-1 hash algorithm | | |
555 // | "HS256" | HMAC using SHA-256 hash algorithm | | |
556 // | "HS384" | HMAC using SHA-384 hash algorithm | | |
557 // | "HS512" | HMAC using SHA-512 hash algorithm | | |
558 // | "RS1" | RSASSA using SHA-1 hash algorithm | |
559 // | "RS256" | RSASSA using SHA-256 hash algorithm | | |
560 // | "RS384" | RSASSA using SHA-384 hash algorithm | | |
561 // | "RS512" | RSASSA using SHA-512 hash algorithm | | |
562 // +--------------+-------------------------------------------------------| | |
563 // | Key Management Algorithm | | |
564 // +--------------+-------------------------------------------------------+ | |
565 // | "RSA1_5" | RSAES-PKCS1-V1_5 [RFC3447] | | |
566 // | "RSA-OAEP" | RSAES using Optimal Asymmetric Encryption Padding | | |
567 // | | (OAEP) [RFC3447], with the default parameters | | |
568 // | | specified by RFC3447 in Section A.2.1 | | |
569 // | "A128KW" | Advanced Encryption Standard (AES) Key Wrap Algorithm | | |
570 // | | [RFC3394] using 128 bit keys | | |
571 // | "A192KW" | AES Key Wrap Algorithm using 192 bit keys | | |
572 // | "A256KW" | AES Key Wrap Algorithm using 256 bit keys | | |
573 // | "A128GCM" | AES in Galois/Counter Mode (GCM) [NIST.800-38D] using | | |
574 // | | 128 bit keys | | |
575 // | "A192GCM" | AES GCM using 192 bit keys | | |
576 // | "A256GCM" | AES GCM using 256 bit keys | | |
577 // | "A128CBC" | AES in Cipher Block Chaining Mode (CBC) with PKCS #5 | | |
578 // | | padding [NIST.800-38A] | | |
579 // | "A192CBC" | AES CBC using 192 bit keys | | |
580 // | "A256CBC" | AES CBC using 256 bit keys | | |
581 // +--------------+-------------------------------------------------------+ | |
582 // | |
583 // kty-specific parameters | |
584 // The value of kty determines the type and content of the keying material | |
585 // carried in the JWK to be imported. Currently only two possibilities are | |
586 // supported: a raw key or an RSA public key. RSA private keys are not | |
587 // supported because typical applications seldom need to import a private key, | |
588 // and the large number of JWK parameters required to describe one. | |
589 // - kty == "oct" (symmetric or other raw key) | |
590 // +-------+--------------------------------------------------------------+ | |
591 // | "k" | Contains the value of the symmetric (or other single-valued) | | |
592 // | | key. It is represented as the base64url encoding of the | | |
593 // | | octet sequence containing the key value. | | |
594 // +-------+--------------------------------------------------------------+ | |
595 // - kty == "RSA" (RSA public key) | |
596 // +-------+--------------------------------------------------------------+ | |
597 // | "n" | Contains the modulus value for the RSA public key. It is | | |
598 // | | represented as the base64url encoding of the value's | | |
599 // | | unsigned big endian representation as an octet sequence. | | |
600 // +-------+--------------------------------------------------------------+ | |
601 // | "e" | Contains the exponent value for the RSA public key. It is | | |
602 // | | represented as the base64url encoding of the value's | | |
603 // | | unsigned big endian representation as an octet sequence. | | |
604 // +-------+--------------------------------------------------------------+ | |
605 // | |
606 // Consistency and conflict resolution | |
607 // The 'algorithm', 'extractable', and 'usage_mask' input parameters | |
608 // may be different than the corresponding values inside the JWK. The Web | |
609 // Crypto spec says that if a JWK value is present but is inconsistent with | |
610 // the input value, it is an error and the operation must fail. If no | |
611 // inconsistency is found then the input parameters are used. | |
612 // | |
613 // algorithm | |
614 // If the JWK algorithm is provided, it must match the web crypto input | |
615 // algorithm (both the algorithm ID and inner hash if applicable). | |
616 // | |
617 // extractable | |
618 // If the JWK ext field is true but the input parameter is false, make the | |
619 // Web Crypto Key non-extractable. Conversely, if the JWK ext field is | |
620 // false but the input parameter is true, it is an inconsistency. If both | |
621 // are true or both are false, use that value. | |
622 // | |
623 // usage_mask | |
624 // The input usage_mask must be a strict subset of the interpreted JWK use | |
625 // value, else it is judged inconsistent. In all cases the input usage_mask | |
626 // is used as the final usage_mask. | |
627 // | |
628 | |
629 if (!key_data.byte_length()) | 620 if (!key_data.byte_length()) |
630 return Status::ErrorImportEmptyKeyData(); | 621 return Status::ErrorImportEmptyKeyData(); |
631 DCHECK(key); | 622 DCHECK(key); |
632 | 623 |
633 // Parse the incoming JWK JSON. | 624 // Parse the incoming JWK JSON. |
634 base::StringPiece json_string(reinterpret_cast<const char*>(key_data.bytes()), | 625 base::StringPiece json_string(reinterpret_cast<const char*>(key_data.bytes()), |
635 key_data.byte_length()); | 626 key_data.byte_length()); |
636 scoped_ptr<base::Value> value(base::JSONReader::Read(json_string)); | 627 scoped_ptr<base::Value> value(base::JSONReader::Read(json_string)); |
637 // Note, bare pointer dict_value is ok since it points into scoped value. | 628 // Note, bare pointer dict_value is ok since it points into scoped value. |
638 base::DictionaryValue* dict_value = NULL; | 629 base::DictionaryValue* dict_value = NULL; |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
835 | 826 |
836 std::string json; | 827 std::string json; |
837 base::JSONWriter::Write(&jwk_dict, &json); | 828 base::JSONWriter::Write(&jwk_dict, &json); |
838 buffer->assign(json.data(), json.data() + json.size()); | 829 buffer->assign(json.data(), json.data() + json.size()); |
839 return Status::Success(); | 830 return Status::Success(); |
840 } | 831 } |
841 | 832 |
842 } // namespace webcrypto | 833 } // namespace webcrypto |
843 | 834 |
844 } // namespace content | 835 } // namespace content |
OLD | NEW |