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
|
// 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 CHROMEOS_ASH_COMPONENTS_KCER_KCER_NSS_TEST_UTILS_H_
#define CHROMEOS_ASH_COMPONENTS_KCER_KCER_NSS_TEST_UTILS_H_
#include <stdint.h>
#include <memory>
#include <optional>
#include <vector>
#include "base/containers/span.h"
#include "base/files/file_path.h"
#include "base/memory/weak_ptr.h"
#include "chromeos/ash/components/kcer/kcer.h"
#include "chromeos/ash/components/kcer/kcer_impl.h"
#include "chromeos/ash/components/kcer/kcer_nss/kcer_token_impl_nss.h"
#include "chromeos/ash/components/kcer/key_permissions.pb.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 // CHROMEOS_ASH_COMPONENTS_KCER_KCER_NSS_TEST_UTILS_H_
|