summaryrefslogtreecommitdiffstats
path: root/components/webcrypto/jwk.h
blob: 67d271d289f323f3cb328253fff56397e7952c08 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_WEBCRYPTO_JWK_H_
#define COMPONENTS_WEBCRYPTO_JWK_H_

#include <stdint.h>
#include <vector>

#include "base/values.h"
#include "third_party/WebKit/public/platform/WebCrypto.h"

namespace webcrypto {

class CryptoData;
class Status;

// Helper class for parsing a JWK from JSON.
//
// This primarily exists to ensure strict enforcement of the JWK schema, as the
// type and presence of particular members is security relevant. For example,
// GetString() will ensure a given JSON member is present and is a string type,
// and will fail if these conditions aren't met.
//
// Users of JwkReader must call Init() successfully before any other method can
// be called.
class JwkReader {
 public:
  JwkReader();
  ~JwkReader();

  // Initializes a JWK reader by parsing the JSON |bytes|. To succeed, the JWK
  // must:
  //   * Have "kty" matching |expected_kty|
  //   * Have "ext" compatible with |expected_extractable|
  //   * Have usages ("use", "key_ops") compatible with |expected_usages|
  //   * Have an "alg" matching |expected_alg|
  //
  // NOTE: If |expected_alg| is empty, then the test on "alg" is skipped.
  Status Init(const CryptoData& bytes,
              bool expected_extractable,
              blink::WebCryptoKeyUsageMask expected_usages,
              const std::string& expected_kty,
              const std::string& expected_alg);

  // Returns true if the member |member_name| is present.
  bool HasMember(const std::string& member_name) const;

  // Extracts the required string member |member_name| and saves the result to
  // |*result|. If the member does not exist or is not a string, returns an
  // error.
  Status GetString(const std::string& member_name, std::string* result) const;

  // Extracts the optional string member |member_name| and saves the result to
  // |*result| if it was found. If the member exists and is not a string,
  // returns an error. Otherwise returns success, and sets |*member_exists| if
  // it was found.
  Status GetOptionalString(const std::string& member_name,
                           std::string* result,
                           bool* member_exists) const;

  // Extracts the optional array member |member_name| and saves the result to
  // |*result| if it was found. If the member exists and is not an array,
  // returns an error. Otherwise returns success, and sets |*member_exists| if
  // it was found.
  //
  // NOTE: |*result| is owned by the JwkReader.
  Status GetOptionalList(const std::string& member_name,
                         base::ListValue** result,
                         bool* member_exists) const;

  // Extracts the required string member |member_name| and saves the
  // base64url-decoded bytes to |*result|. If the member does not exist or is
  // not a string, or could not be base64url-decoded, returns an error.
  Status GetBytes(const std::string& member_name, std::string* result) const;

  // Extracts the required base64url member, which is interpreted as being a
  // big-endian unsigned integer.
  //
  // Sequences that contain leading zeros will be rejected.
  Status GetBigInteger(const std::string& member_name,
                       std::string* result) const;

  // Extracts the optional boolean member |member_name| and saves the result to
  // |*result| if it was found. If the member exists and is not a boolean,
  // returns an error. Otherwise returns success, and sets |*member_exists| if
  // it was found.
  Status GetOptionalBool(const std::string& member_name,
                         bool* result,
                         bool* member_exists) const;

  // Gets the optional algorithm ("alg") string.
  Status GetAlg(std::string* alg, bool* has_alg) const;

  // Checks if the "alg" member matches |expected_alg|.
  Status VerifyAlg(const std::string& expected_alg) const;

 private:
  scoped_ptr<base::DictionaryValue> dict_;
};

// Helper class for building the JSON for a JWK.
class JwkWriter {
 public:
  // Initializes a writer, and sets the standard JWK members as indicated.
  // |algorithm| is optional, and is only written if the provided |algorithm| is
  // non-empty.
  JwkWriter(const std::string& algorithm,
            bool extractable,
            blink::WebCryptoKeyUsageMask usages,
            const std::string& kty);

  // Sets a string member |member_name| to |value|.
  void SetString(const std::string& member_name, const std::string& value);

  // Sets a bytes member |value| to |value| by base64 url-safe encoding it.
  void SetBytes(const std::string& member_name, const CryptoData& value);

  // Flattens the JWK to JSON (UTF-8 encoded if necessary, however in practice
  // it will be ASCII).
  void ToJson(std::vector<uint8_t>* utf8_bytes) const;

 private:
  base::DictionaryValue dict_;
};

// Converts a JWK "key_ops" array to the corresponding WebCrypto usages. Used by
// testing.
Status GetWebCryptoUsagesFromJwkKeyOpsForTest(
    const base::ListValue* key_ops,
    blink::WebCryptoKeyUsageMask* usages);

}  // namespace webcrypto

#endif  // COMPONENTS_WEBCRYPTO_JWK_H_