[email protected] | c263fbe | 2014-03-26 09:50:57 | [diff] [blame] | 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 |
| 3 | // found in the LICENSE file. |
| 4 | |
erg | 56f1232 | 2015-04-17 00:51:48 | [diff] [blame] | 5 | #ifndef COMPONENTS_WEBCRYPTO_JWK_H_ |
| 6 | #define COMPONENTS_WEBCRYPTO_JWK_H_ |
[email protected] | c263fbe | 2014-03-26 09:50:57 | [diff] [blame] | 7 | |
[email protected] | 53b6c9d2 | 2014-07-19 05:08:38 | [diff] [blame] | 8 | #include <stdint.h> |
Daniel Cheng | 556abd1 | 2016-04-02 01:13:08 | [diff] [blame] | 9 | |
dcheng | 7036d1e5 | 2016-04-21 23:13:03 | [diff] [blame] | 10 | #include <memory> |
[email protected] | 88be9856 | 2014-04-30 11:18:59 | [diff] [blame] | 11 | #include <vector> |
| 12 | |
[email protected] | 38409aec | 2014-07-19 00:54:51 | [diff] [blame] | 13 | #include "base/values.h" |
Blink Reformat | a30d423 | 2018-04-07 15:31:06 | [diff] [blame] | 14 | #include "third_party/blink/public/platform/web_crypto.h" |
[email protected] | c263fbe | 2014-03-26 09:50:57 | [diff] [blame] | 15 | |
[email protected] | c263fbe | 2014-03-26 09:50:57 | [diff] [blame] | 16 | namespace webcrypto { |
| 17 | |
| 18 | class CryptoData; |
| 19 | class Status; |
| 20 | |
eroman | 4ccb5e4 | 2014-11-04 23:05:16 | [diff] [blame] | 21 | // Helper class for parsing a JWK from JSON. |
| 22 | // |
| 23 | // This primarily exists to ensure strict enforcement of the JWK schema, as the |
| 24 | // type and presence of particular members is security relevant. For example, |
| 25 | // GetString() will ensure a given JSON member is present and is a string type, |
| 26 | // and will fail if these conditions aren't met. |
| 27 | // |
| 28 | // Users of JwkReader must call Init() successfully before any other method can |
| 29 | // be called. |
| 30 | class JwkReader { |
| 31 | public: |
| 32 | JwkReader(); |
| 33 | ~JwkReader(); |
| 34 | |
| 35 | // Initializes a JWK reader by parsing the JSON |bytes|. To succeed, the JWK |
| 36 | // must: |
| 37 | // * Have "kty" matching |expected_kty| |
| 38 | // * Have "ext" compatible with |expected_extractable| |
| 39 | // * Have usages ("use", "key_ops") compatible with |expected_usages| |
| 40 | // * Have an "alg" matching |expected_alg| |
| 41 | // |
| 42 | // NOTE: If |expected_alg| is empty, then the test on "alg" is skipped. |
| 43 | Status Init(const CryptoData& bytes, |
| 44 | bool expected_extractable, |
| 45 | blink::WebCryptoKeyUsageMask expected_usages, |
| 46 | const std::string& expected_kty, |
| 47 | const std::string& expected_alg); |
| 48 | |
| 49 | // Returns true if the member |member_name| is present. |
| 50 | bool HasMember(const std::string& member_name) const; |
| 51 | |
| 52 | // Extracts the required string member |member_name| and saves the result to |
| 53 | // |*result|. If the member does not exist or is not a string, returns an |
| 54 | // error. |
| 55 | Status GetString(const std::string& member_name, std::string* result) const; |
| 56 | |
| 57 | // Extracts the optional string member |member_name| and saves the result to |
| 58 | // |*result| if it was found. If the member exists and is not a string, |
| 59 | // returns an error. Otherwise returns success, and sets |*member_exists| if |
| 60 | // it was found. |
| 61 | Status GetOptionalString(const std::string& member_name, |
| 62 | std::string* result, |
| 63 | bool* member_exists) const; |
| 64 | |
| 65 | // Extracts the optional array member |member_name| and saves the result to |
| 66 | // |*result| if it was found. If the member exists and is not an array, |
| 67 | // returns an error. Otherwise returns success, and sets |*member_exists| if |
| 68 | // it was found. |
| 69 | // |
| 70 | // NOTE: |*result| is owned by the JwkReader. |
| 71 | Status GetOptionalList(const std::string& member_name, |
| 72 | base::ListValue** result, |
| 73 | bool* member_exists) const; |
| 74 | |
| 75 | // Extracts the required string member |member_name| and saves the |
| 76 | // base64url-decoded bytes to |*result|. If the member does not exist or is |
| 77 | // not a string, or could not be base64url-decoded, returns an error. |
| 78 | Status GetBytes(const std::string& member_name, std::string* result) const; |
| 79 | |
| 80 | // Extracts the required base64url member, which is interpreted as being a |
| 81 | // big-endian unsigned integer. |
| 82 | // |
| 83 | // Sequences that contain leading zeros will be rejected. |
| 84 | Status GetBigInteger(const std::string& member_name, |
| 85 | std::string* result) const; |
| 86 | |
| 87 | // Extracts the optional boolean member |member_name| and saves the result to |
| 88 | // |*result| if it was found. If the member exists and is not a boolean, |
| 89 | // returns an error. Otherwise returns success, and sets |*member_exists| if |
| 90 | // it was found. |
| 91 | Status GetOptionalBool(const std::string& member_name, |
| 92 | bool* result, |
| 93 | bool* member_exists) const; |
| 94 | |
| 95 | // Gets the optional algorithm ("alg") string. |
| 96 | Status GetAlg(std::string* alg, bool* has_alg) const; |
| 97 | |
| 98 | // Checks if the "alg" member matches |expected_alg|. |
| 99 | Status VerifyAlg(const std::string& expected_alg) const; |
| 100 | |
| 101 | private: |
dcheng | 7036d1e5 | 2016-04-21 23:13:03 | [diff] [blame] | 102 | std::unique_ptr<base::DictionaryValue> dict_; |
eroman | 4ccb5e4 | 2014-11-04 23:05:16 | [diff] [blame] | 103 | }; |
| 104 | |
| 105 | // Helper class for building the JSON for a JWK. |
| 106 | class JwkWriter { |
| 107 | public: |
| 108 | // Initializes a writer, and sets the standard JWK members as indicated. |
eroman | b2ead6d | 2014-11-14 02:26:14 | [diff] [blame] | 109 | // |algorithm| is optional, and is only written if the provided |algorithm| is |
| 110 | // non-empty. |
eroman | 4ccb5e4 | 2014-11-04 23:05:16 | [diff] [blame] | 111 | JwkWriter(const std::string& algorithm, |
| 112 | bool extractable, |
| 113 | blink::WebCryptoKeyUsageMask usages, |
| 114 | const std::string& kty); |
| 115 | |
| 116 | // Sets a string member |member_name| to |value|. |
| 117 | void SetString(const std::string& member_name, const std::string& value); |
| 118 | |
| 119 | // Sets a bytes member |value| to |value| by base64 url-safe encoding it. |
| 120 | void SetBytes(const std::string& member_name, const CryptoData& value); |
| 121 | |
| 122 | // Flattens the JWK to JSON (UTF-8 encoded if necessary, however in practice |
| 123 | // it will be ASCII). |
| 124 | void ToJson(std::vector<uint8_t>* utf8_bytes) const; |
| 125 | |
| 126 | private: |
| 127 | base::DictionaryValue dict_; |
| 128 | }; |
| 129 | |
eroman | d34fd99 | 2014-12-30 03:27:02 | [diff] [blame] | 130 | // Converts a JWK "key_ops" array to the corresponding WebCrypto usages. Used by |
| 131 | // testing. |
erg | 56f1232 | 2015-04-17 00:51:48 | [diff] [blame] | 132 | Status GetWebCryptoUsagesFromJwkKeyOpsForTest( |
| 133 | const base::ListValue* key_ops, |
| 134 | blink::WebCryptoKeyUsageMask* usages); |
eroman | d34fd99 | 2014-12-30 03:27:02 | [diff] [blame] | 135 | |
[email protected] | c263fbe | 2014-03-26 09:50:57 | [diff] [blame] | 136 | } // namespace webcrypto |
| 137 | |
erg | 56f1232 | 2015-04-17 00:51:48 | [diff] [blame] | 138 | #endif // COMPONENTS_WEBCRYPTO_JWK_H_ |