blob: ea022f573608e9c1cdc64acf6dfbb112db8ae8f3 [file] [log] [blame]
[email protected]c263fbe2014-03-26 09:50:571// 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
erg56f12322015-04-17 00:51:485#ifndef COMPONENTS_WEBCRYPTO_JWK_H_
6#define COMPONENTS_WEBCRYPTO_JWK_H_
[email protected]c263fbe2014-03-26 09:50:577
[email protected]53b6c9d22014-07-19 05:08:388#include <stdint.h>
Daniel Cheng556abd12016-04-02 01:13:089
dcheng7036d1e52016-04-21 23:13:0310#include <memory>
[email protected]88be98562014-04-30 11:18:5911#include <vector>
12
[email protected]38409aec2014-07-19 00:54:5113#include "base/values.h"
Blink Reformata30d4232018-04-07 15:31:0614#include "third_party/blink/public/platform/web_crypto.h"
[email protected]c263fbe2014-03-26 09:50:5715
[email protected]c263fbe2014-03-26 09:50:5716namespace webcrypto {
17
18class CryptoData;
19class Status;
20
eroman4ccb5e42014-11-04 23:05:1621// 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.
30class 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:
dcheng7036d1e52016-04-21 23:13:03102 std::unique_ptr<base::DictionaryValue> dict_;
eroman4ccb5e42014-11-04 23:05:16103};
104
105// Helper class for building the JSON for a JWK.
106class JwkWriter {
107 public:
108 // Initializes a writer, and sets the standard JWK members as indicated.
eromanb2ead6d2014-11-14 02:26:14109 // |algorithm| is optional, and is only written if the provided |algorithm| is
110 // non-empty.
eroman4ccb5e42014-11-04 23:05:16111 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
eromand34fd992014-12-30 03:27:02130// Converts a JWK "key_ops" array to the corresponding WebCrypto usages. Used by
131// testing.
erg56f12322015-04-17 00:51:48132Status GetWebCryptoUsagesFromJwkKeyOpsForTest(
133 const base::ListValue* key_ops,
134 blink::WebCryptoKeyUsageMask* usages);
eromand34fd992014-12-30 03:27:02135
[email protected]c263fbe2014-03-26 09:50:57136} // namespace webcrypto
137
erg56f12322015-04-17 00:51:48138#endif // COMPONENTS_WEBCRYPTO_JWK_H_