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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
ash / components / kcer / kcer_nss / test_utils.h [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef ASH_COMPONENTS_KCER_KCER_NSS_TEST_UTILS_H_
#define ASH_COMPONENTS_KCER_KCER_NSS_TEST_UTILS_H_
#include <stdint.h>
#include <memory>
#include <optional>
#include <vector>
#include "ash/components/kcer/kcer.h"
#include "ash/components/kcer/kcer_impl.h"
#include "ash/components/kcer/kcer_nss/kcer_token_impl_nss.h"
#include "ash/components/kcer/key_permissions.pb.h"
#include "base/containers/span.h"
#include "base/files/file_path.h"
#include "base/memory/weak_ptr.h"
#include "crypto/scoped_test_nss_db.h"
#include "net/test/cert_builder.h"
namespace kcer {
struct KeyAndCert {
KeyAndCert(PublicKey key, scoped_refptr<const Cert> cert);
KeyAndCert(KeyAndCert&&);
KeyAndCert& operator=(KeyAndCert&&);
~KeyAndCert();
PublicKey key;
scoped_refptr<const Cert> cert;
};
//==============================================================================
// A helper class to work with tokens (that exist on the IO thread) from the UI
// thread.
class TokenHolder {
public:
// Creates a KcerToken of the type `token` and moves it to the IO thread. If
// `initialize` then the KcerToken will be ready to process requests
// immediately.
TokenHolder(Token token,
HighLevelChapsClient* chaps_client,
bool initialize_token);
TokenHolder(Token token,
HighLevelChapsClient* chaps_client,
bool initialize_token,
crypto::ScopedPK11Slot nss_slot);
~TokenHolder();
// If KcerToken was not initialized on construction, this method makes it
// initialized. Can be used to simulate delayed initialization.
void InitializeToken();
// If KcerToken was not initialized on construction, this method simulates
// initialization failure.
void FailTokenInitialization();
// Returns a weak pointer to the token that can be used to post requests for
// it. The pointer should only be dereferenced on the IO thread.
base::WeakPtr<internal::KcerToken> GetWeakPtr() { return weak_ptr_; }
uint32_t GetSlotId();
private:
void Initialize(Token token,
HighLevelChapsClient* chaps_client,
bool initialize,
crypto::ScopedPK11Slot nss_slot);
base::WeakPtr<internal::KcerToken> weak_ptr_;
std::unique_ptr<internal::KcerTokenImplNss> io_token_;
crypto::ScopedTestNSSDB nss_db_;
crypto::ScopedPK11Slot nss_slot_;
bool is_initialized_ = false;
};
//==============================================================================
// A test helper class that creates and initializes a Kcer instances with a user
// and device NSS slots. In the current implementation the HighLevelChapsClient
// is not configured, so certain functionality will not work (mainly PKCS#12
// import).
class TestKcerHolder {
public:
// nullptr can be passed for any/all slots to emulate that Kcer doesn't have
// access to them.
TestKcerHolder(PK11SlotInfo* user_slot, PK11SlotInfo* device_slot);
~TestKcerHolder();
base::WeakPtr<Kcer> GetKcer();
private:
TokenHolder user_token_;
TokenHolder device_token_;
std::unique_ptr<kcer::internal::KcerImpl> kcer_;
};
//==============================================================================
// Compares two KerPermissions, returns true if they are equal.
bool ExpectKeyPermissionsEqual(const std::optional<chaps::KeyPermissions>& a,
const std::optional<chaps::KeyPermissions>& b);
// Verifies `signature` created with `signing_scheme` and the public key from
// `spki` for `data_to_sign`. By default (with `strict` == true) only returns
// true if the signature is correct. With `strict` == false, silently ignores
// schemes for which the verification is not implemented yet and also returns
// true for them. Returns false if signature is incorrect.
bool VerifySignature(SigningScheme signing_scheme,
PublicKeySpki spki,
DataToSign data_to_sign,
Signature signature,
bool strict = true);
// Returns |hash| prefixed with DER-encoded PKCS#1 DigestInfo with
// AlgorithmIdentifier=id-sha256.
// This is useful for testing Kcer::SignRsaPkcs1Raw which only
// appends PKCS#1 v1.5 padding before signing.
std::vector<uint8_t> PrependSHA256DigestInfo(base::span<const uint8_t> hash);
// Reads a file in the PEM format, decodes it, returns the content of the first
// PEM block in the DER format. Currently supports CERTIFICATE and PRIVATE KEY
// block types.
std::optional<std::vector<uint8_t>> ReadPemFileReturnDer(
const base::FilePath& path);
// Can be used together with MakeCertBuilder().
std::unique_ptr<net::CertBuilder> MakeCertIssuer();
// Creates a certificate builder that can generate a self-signed certificate for
// the `public_key`. Requires an `issuer` that can be created using
// MakeCertIssuer().
std::unique_ptr<net::CertBuilder> MakeCertBuilder(
net::CertBuilder* issuer,
const std::vector<uint8_t>& public_key);
// Reads a file with the `file_name` from net::GetTestCertsDirectory()
// directory.
std::vector<uint8_t> ReadTestFile(const std::string& file_name);
// Reads the key and the cert from disk and imports them into Kcer.
base::expected<KeyAndCert, Error> ImportTestKeyAndCert(
base::WeakPtr<Kcer> kcer,
Token token,
std::string_view key_filename,
std::string_view cert_filename);
} // namespace kcer
#endif // ASH_COMPONENTS_KCER_KCER_NSS_TEST_UTILS_H_