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 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
|
// 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_HELPERS_PKCS12_READER_H_
#define CHROMEOS_ASH_COMPONENTS_KCER_HELPERS_PKCS12_READER_H_
#include <nss/certt.h>
#include <stdint.h>
#include <string>
#include <vector>
#include "base/component_export.h"
#include "base/containers/span.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "chromeos/ash/components/kcer/kcer.h"
#include "net/cert/x509_certificate.h"
#include "third_party/boringssl/src/include/openssl/base.h"
#include "third_party/boringssl/src/include/openssl/pkcs7.h"
#include "third_party/boringssl/src/include/openssl/stack.h"
#include "third_party/boringssl/src/include/openssl/x509.h"
namespace kcer::internal {
// Used for logging, the values should never be reordered or reused.
// TODO(miersh): Merge this into kcer::Error.
enum class Pkcs12ReaderStatusCode {
kSuccess = 0,
kCreateKeyFailed = 1,
kCertificateDataMissed = 2,
kCreateCertFailed = 3,
kKeyDataMissed = 4,
kKeyExtractionFailed = 5,
kChapsSessionMissed = 6,
kPkcs12CertDerMissed = 7,
kPkcs12CertDerFailed = 8,
kPkcs12CertIssuerNameMissed = 9,
kPkcs12CertIssuerDerNameFailed = 10,
kPkcs12CertSubjectNameMissed = 11,
kPkcs12CertSubjectNameDerFailed = 12,
kPkcs12CertSerialNumberMissed = 13,
kPkcs12CertSerialNumberDerFailed = 14,
kKeyAttrDataMissing = 15,
kFailureDuringCertImport = 16,
kFailedToParsePkcs12Data = 17,
kMissedPkcs12Data = 18,
kPkcs12LabelCreationFailed = 19,
kPkcs12FindCertsWithSubjectFailed = 20,
kPkcs12NoValidCertificatesFound = 21,
kPkcs12NoNicknamesWasExtracted = 22,
kPkcs12ReachedMaxAttemptForUniqueness = 23,
kPkcs12MissedNickname = 24,
kMissedSlotInfo = 25,
kPkcs12NotSupportedKeyType = 26,
kPkcs12CNExtractionFailed = 27,
kEcKeyExtractionFailed = 28,
kRsaCkaIdExtractionFailed = 29,
kPKeyExtractionFailed = 30,
kRsaKeyExtractionFailed = 31,
kPkcs12RsaModulusEmpty = 32,
kEcKeyBytesEmpty = 33,
kEcCkaIdExtractionFailed = 34,
kPkeyComparisonFailure = 35,
kPkcs12WrongPassword = 36,
kPkcs12InvalidMac = 37,
kPkcs12InvalidFile = 38,
kPkcs12UnsupportedFile = 39,
kAlreadyExists = 40,
};
enum class Pkcs12ReaderCertSearchType {
kDerType,
kPlainType,
};
struct COMPONENT_EXPORT(KCER) CertData {
CertData();
CertData(CertData&& other);
~CertData();
bssl::UniquePtr<X509> x509;
std::string nickname;
CertDer cert_der;
};
struct COMPONENT_EXPORT(KCER) KeyData {
KeyData();
KeyData(KeyData&&);
KeyData& operator=(KeyData&&) = default;
~KeyData();
bssl::UniquePtr<EVP_PKEY> key;
std::vector<uint8_t> cka_id_value;
};
// A helper for std::unique_ptr to call X509_free.
struct X509Deleter {
void operator()(X509* cert) { X509_free(cert); }
};
using ScopedX509 = std::unique_ptr<X509, X509Deleter>;
// Helper class for working with boringssl and related objects.
// TODO(miersh): Rename, don't mention PKCS#12.
class COMPONENT_EXPORT(KCER) Pkcs12Reader {
public:
Pkcs12Reader();
virtual ~Pkcs12Reader() = default;
// Populates key and certificates (`key`, `certs`) from the PKCS#12 object
// `pkcs12_data` protected by the `password`. Returns status code.
virtual Pkcs12ReaderStatusCode GetPkcs12KeyAndCerts(
const std::vector<uint8_t>& pkcs12_data,
const std::string& password,
bssl::UniquePtr<EVP_PKEY>& key,
bssl::UniquePtr<STACK_OF(X509)>& certs) const;
// Populates der encoded certificate and its size (`cert_der`,
// `cert_der_size`) from X509 (`cert`). Returns status code.
virtual Pkcs12ReaderStatusCode GetDerEncodedCert(
X509* cert,
bssl::UniquePtr<uint8_t>& cert_der,
int& cert_der_size) const;
// Populates der encoded issuer name and its size (`issuer_name_data`) from
// X509 (`cert`). `issuer_name_data` remains valid only as long as the cert is
// alive because it is only referencing data. Returns status code.
virtual Pkcs12ReaderStatusCode GetIssuerNameDer(
X509* cert,
base::span<const uint8_t>& issuer_name_data) const;
// Populates der encoded subject name and its size (`subject_name_data`) from
// X509 (`cert`). `subject_name_data` remains valid only as long as the cert
// is alive because it is only referencing data. Returns status code.
virtual Pkcs12ReaderStatusCode GetSubjectNameDer(
X509* cert,
base::span<const uint8_t>& subject_name_data) const;
// Populates der encoded serial number and its size (`serial_number_der`,
// `serial_number_der_size`) from X509 (`cert`). Returns status code.
virtual Pkcs12ReaderStatusCode GetSerialNumberDer(
X509* cert,
bssl::UniquePtr<uint8_t>& serial_number_der,
int& serial_number_der_size) const;
// Populates label (`label`) from X509 (`cert`). Returns status code.
virtual Pkcs12ReaderStatusCode GetLabel(X509* cert, std::string& label) const;
// Converts BIGNUM (`bignum`) to bytes.
virtual std::vector<uint8_t> BignumToBytes(const BIGNUM* bignum) const;
// Fetches X509 certificates (`found_certs`) with required Subject name
// (`required_subject_name`) from the provided slot (`slot`).
// Returns status code.
virtual Pkcs12ReaderStatusCode FindRawCertsWithSubject(
PK11SlotInfo* slot,
base::span<const uint8_t> required_subject_name,
CERTCertificateList** found_certs) const;
// Check if there are certificates with the same nickname (`nickname_in`) is
// present in any PK11 slots. Set (`is_nickname_present`) to true or false.
// Returns status code.
virtual Pkcs12ReaderStatusCode IsCertWithNicknameInSlots(
const std::string& nickname_in,
bool& is_nickname_present) const;
// Search if private key is already present in slot (`slot`) using
// related X509 certificate (`cert`) and certificates type (`cert_type`).
// Returns Pkcs12ReaderStatusCode::kSuccess
// if key found, Pkcs12ReaderStatusCode::kKeyDataMissed if key is missed or
// a status code.
virtual Pkcs12ReaderStatusCode DoesKeyForCertExist(
PK11SlotInfo* slot,
const Pkcs12ReaderCertSearchType cert_type,
const scoped_refptr<net::X509Certificate>& cert) const;
// Calculates additional data which can be used for checking key to
// certificate relation from (`key`). For RSA key it will be modulus. Returns
// status code.
virtual Pkcs12ReaderStatusCode EnrichKeyData(KeyData& key_data) const;
// Check if certificate (`cert`) is related to private key which was used for
// the calculation of key_data (`key_data`), sets boolean (`is_related`).
// Returns status code.
virtual Pkcs12ReaderStatusCode CheckRelation(const KeyData& key_data,
X509* cert,
bool& is_related) const;
// Converts certificates data from DER representation (`der_cert_data`) and
// (`der_cert_len`) to X509 (`x509`).
// Returns status code.
virtual Pkcs12ReaderStatusCode GetCertFromDerData(
const unsigned char* der_cert_data,
int der_cert_len,
bssl::UniquePtr<X509>& x509) const;
// Check if certificate (`cert`) is present in specific 'slot'.
// Returns status code.
virtual Pkcs12ReaderStatusCode IsCertInSlot(
PK11SlotInfo* slot,
const scoped_refptr<net::X509Certificate>& cert,
bool& is_cert_present) const;
};
} // namespace kcer::internal
#endif // CHROMEOS_ASH_COMPONENTS_KCER_HELPERS_PKCS12_READER_H_
|