1*60b67249SAndroid Build Coastguard Worker // Copyright 2020 Google LLC
2*60b67249SAndroid Build Coastguard Worker //
3*60b67249SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*60b67249SAndroid Build Coastguard Worker // use this file except in compliance with the License. You may obtain a copy of
5*60b67249SAndroid Build Coastguard Worker // the License at
6*60b67249SAndroid Build Coastguard Worker //
7*60b67249SAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0
8*60b67249SAndroid Build Coastguard Worker //
9*60b67249SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*60b67249SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*60b67249SAndroid Build Coastguard Worker // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*60b67249SAndroid Build Coastguard Worker // License for the specific language governing permissions and limitations under
13*60b67249SAndroid Build Coastguard Worker // the License.
14*60b67249SAndroid Build Coastguard Worker
15*60b67249SAndroid Build Coastguard Worker #include "dice/test_utils.h"
16*60b67249SAndroid Build Coastguard Worker
17*60b67249SAndroid Build Coastguard Worker #include <stddef.h>
18*60b67249SAndroid Build Coastguard Worker #include <stdint.h>
19*60b67249SAndroid Build Coastguard Worker #include <string.h>
20*60b67249SAndroid Build Coastguard Worker
21*60b67249SAndroid Build Coastguard Worker #include <functional>
22*60b67249SAndroid Build Coastguard Worker #include <memory>
23*60b67249SAndroid Build Coastguard Worker #include <span>
24*60b67249SAndroid Build Coastguard Worker #include <vector>
25*60b67249SAndroid Build Coastguard Worker
26*60b67249SAndroid Build Coastguard Worker #include "cose/cose.h"
27*60b67249SAndroid Build Coastguard Worker #include "dice/boringssl_ecdsa_utils.h"
28*60b67249SAndroid Build Coastguard Worker #include "dice/dice.h"
29*60b67249SAndroid Build Coastguard Worker #include "dice/utils.h"
30*60b67249SAndroid Build Coastguard Worker #include "openssl/asn1.h"
31*60b67249SAndroid Build Coastguard Worker #include "openssl/bn.h"
32*60b67249SAndroid Build Coastguard Worker #include "openssl/curve25519.h"
33*60b67249SAndroid Build Coastguard Worker #include "openssl/evp.h"
34*60b67249SAndroid Build Coastguard Worker #include "openssl/is_boringssl.h"
35*60b67249SAndroid Build Coastguard Worker #include "openssl/mem.h"
36*60b67249SAndroid Build Coastguard Worker #include "openssl/sha.h"
37*60b67249SAndroid Build Coastguard Worker #include "openssl/x509.h"
38*60b67249SAndroid Build Coastguard Worker #include "openssl/x509_vfy.h"
39*60b67249SAndroid Build Coastguard Worker #include "openssl/x509v3.h"
40*60b67249SAndroid Build Coastguard Worker #include "pw_string/format.h"
41*60b67249SAndroid Build Coastguard Worker
42*60b67249SAndroid Build Coastguard Worker // The largest possible public key size among ECDSA P-384, P-256, and ED25519
43*60b67249SAndroid Build Coastguard Worker #define MAX_PUBLIC_KEY_SIZE 96
44*60b67249SAndroid Build Coastguard Worker
45*60b67249SAndroid Build Coastguard Worker namespace {
46*60b67249SAndroid Build Coastguard Worker
47*60b67249SAndroid Build Coastguard Worker // A scoped pointer for cn_cbor.
48*60b67249SAndroid Build Coastguard Worker struct CborDeleter {
operator ()__anonad3d27450111::CborDeleter49*60b67249SAndroid Build Coastguard Worker void operator()(cn_cbor* c) { cn_cbor_free(c); }
50*60b67249SAndroid Build Coastguard Worker };
51*60b67249SAndroid Build Coastguard Worker using ScopedCbor = std::unique_ptr<cn_cbor, CborDeleter>;
52*60b67249SAndroid Build Coastguard Worker
GetCertTypeStr(dice::test::CertificateType cert_type)53*60b67249SAndroid Build Coastguard Worker const char* GetCertTypeStr(dice::test::CertificateType cert_type) {
54*60b67249SAndroid Build Coastguard Worker switch (cert_type) {
55*60b67249SAndroid Build Coastguard Worker case dice::test::CertificateType_Cbor:
56*60b67249SAndroid Build Coastguard Worker return "CBOR";
57*60b67249SAndroid Build Coastguard Worker case dice::test::CertificateType_X509:
58*60b67249SAndroid Build Coastguard Worker return "X509";
59*60b67249SAndroid Build Coastguard Worker }
60*60b67249SAndroid Build Coastguard Worker return "";
61*60b67249SAndroid Build Coastguard Worker }
62*60b67249SAndroid Build Coastguard Worker
GetKeyTypeStr(dice::test::KeyType key_type)63*60b67249SAndroid Build Coastguard Worker const char* GetKeyTypeStr(dice::test::KeyType key_type) {
64*60b67249SAndroid Build Coastguard Worker switch (key_type) {
65*60b67249SAndroid Build Coastguard Worker case dice::test::KeyType_Ed25519:
66*60b67249SAndroid Build Coastguard Worker return "Ed25519";
67*60b67249SAndroid Build Coastguard Worker case dice::test::KeyType_P256:
68*60b67249SAndroid Build Coastguard Worker case dice::test::KeyType_P256_COMPRESSED:
69*60b67249SAndroid Build Coastguard Worker return "P256";
70*60b67249SAndroid Build Coastguard Worker case dice::test::KeyType_P384:
71*60b67249SAndroid Build Coastguard Worker return "P384";
72*60b67249SAndroid Build Coastguard Worker }
73*60b67249SAndroid Build Coastguard Worker return "";
74*60b67249SAndroid Build Coastguard Worker }
75*60b67249SAndroid Build Coastguard Worker
ParseX509Certificate(const uint8_t * certificate,size_t certificate_size)76*60b67249SAndroid Build Coastguard Worker bssl::UniquePtr<X509> ParseX509Certificate(const uint8_t* certificate,
77*60b67249SAndroid Build Coastguard Worker size_t certificate_size) {
78*60b67249SAndroid Build Coastguard Worker const uint8_t* asn1 = certificate;
79*60b67249SAndroid Build Coastguard Worker return bssl::UniquePtr<X509>(
80*60b67249SAndroid Build Coastguard Worker d2i_X509(/*X509=*/nullptr, &asn1, certificate_size));
81*60b67249SAndroid Build Coastguard Worker }
82*60b67249SAndroid Build Coastguard Worker
DumpToFile(const char * filename,const uint8_t * data,size_t size)83*60b67249SAndroid Build Coastguard Worker void DumpToFile(const char* filename, const uint8_t* data, size_t size) {
84*60b67249SAndroid Build Coastguard Worker FILE* fp = fopen(filename, "w");
85*60b67249SAndroid Build Coastguard Worker if (fp) {
86*60b67249SAndroid Build Coastguard Worker fwrite(data, size, 1, fp);
87*60b67249SAndroid Build Coastguard Worker fclose(fp);
88*60b67249SAndroid Build Coastguard Worker } else {
89*60b67249SAndroid Build Coastguard Worker printf("WARNING: Failed to dump to file.\n");
90*60b67249SAndroid Build Coastguard Worker }
91*60b67249SAndroid Build Coastguard Worker }
92*60b67249SAndroid Build Coastguard Worker
EcKeyFromCoords(int nid,uint8_t raw_public_key[MAX_PUBLIC_KEY_SIZE],size_t public_key_size)93*60b67249SAndroid Build Coastguard Worker bssl::UniquePtr<EVP_PKEY> EcKeyFromCoords(
94*60b67249SAndroid Build Coastguard Worker int nid, uint8_t raw_public_key[MAX_PUBLIC_KEY_SIZE],
95*60b67249SAndroid Build Coastguard Worker size_t public_key_size) {
96*60b67249SAndroid Build Coastguard Worker bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(nid));
97*60b67249SAndroid Build Coastguard Worker BIGNUM* x = BN_new();
98*60b67249SAndroid Build Coastguard Worker BN_bin2bn(&raw_public_key[0], public_key_size / 2, x);
99*60b67249SAndroid Build Coastguard Worker BIGNUM* y = BN_new();
100*60b67249SAndroid Build Coastguard Worker BN_bin2bn(&raw_public_key[public_key_size / 2], public_key_size / 2, y);
101*60b67249SAndroid Build Coastguard Worker EC_KEY_set_public_key_affine_coordinates(key.get(), x, y);
102*60b67249SAndroid Build Coastguard Worker BN_clear_free(y);
103*60b67249SAndroid Build Coastguard Worker BN_clear_free(x);
104*60b67249SAndroid Build Coastguard Worker bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
105*60b67249SAndroid Build Coastguard Worker EVP_PKEY_set1_EC_KEY(pkey.get(), key.get());
106*60b67249SAndroid Build Coastguard Worker return pkey;
107*60b67249SAndroid Build Coastguard Worker }
108*60b67249SAndroid Build Coastguard Worker
KeyFromRawKey(const uint8_t raw_key[DICE_PRIVATE_KEY_SEED_SIZE],dice::test::KeyType key_type,uint8_t raw_public_key[MAX_PUBLIC_KEY_SIZE],size_t * raw_public_key_size)109*60b67249SAndroid Build Coastguard Worker bssl::UniquePtr<EVP_PKEY> KeyFromRawKey(
110*60b67249SAndroid Build Coastguard Worker const uint8_t raw_key[DICE_PRIVATE_KEY_SEED_SIZE],
111*60b67249SAndroid Build Coastguard Worker dice::test::KeyType key_type, uint8_t raw_public_key[MAX_PUBLIC_KEY_SIZE],
112*60b67249SAndroid Build Coastguard Worker size_t* raw_public_key_size) {
113*60b67249SAndroid Build Coastguard Worker if (key_type == dice::test::KeyType_Ed25519) {
114*60b67249SAndroid Build Coastguard Worker bssl::UniquePtr<EVP_PKEY> key(
115*60b67249SAndroid Build Coastguard Worker EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, /*unused=*/nullptr,
116*60b67249SAndroid Build Coastguard Worker raw_key, DICE_PRIVATE_KEY_SEED_SIZE));
117*60b67249SAndroid Build Coastguard Worker *raw_public_key_size = 32;
118*60b67249SAndroid Build Coastguard Worker EVP_PKEY_get_raw_public_key(key.get(), raw_public_key, raw_public_key_size);
119*60b67249SAndroid Build Coastguard Worker return key;
120*60b67249SAndroid Build Coastguard Worker } else if (key_type == dice::test::KeyType_P256 ||
121*60b67249SAndroid Build Coastguard Worker key_type == dice::test::KeyType_P256_COMPRESSED) {
122*60b67249SAndroid Build Coastguard Worker const size_t kPublicKeySize = 64;
123*60b67249SAndroid Build Coastguard Worker const size_t kPrivateKeySize = 32;
124*60b67249SAndroid Build Coastguard Worker uint8_t pk[kPrivateKeySize];
125*60b67249SAndroid Build Coastguard Worker P256KeypairFromSeed(raw_public_key, pk, raw_key);
126*60b67249SAndroid Build Coastguard Worker bssl::UniquePtr<EVP_PKEY> pkey =
127*60b67249SAndroid Build Coastguard Worker EcKeyFromCoords(NID_X9_62_prime256v1, raw_public_key, kPublicKeySize);
128*60b67249SAndroid Build Coastguard Worker if (key_type == dice::test::KeyType_P256_COMPRESSED) {
129*60b67249SAndroid Build Coastguard Worker const EC_KEY* key = EVP_PKEY_get0_EC_KEY(pkey.get());
130*60b67249SAndroid Build Coastguard Worker const EC_GROUP* group = EC_KEY_get0_group(key);
131*60b67249SAndroid Build Coastguard Worker const EC_POINT* pub = EC_KEY_get0_public_key(key);
132*60b67249SAndroid Build Coastguard Worker *raw_public_key_size = EC_POINT_point2oct(
133*60b67249SAndroid Build Coastguard Worker group, pub, POINT_CONVERSION_COMPRESSED, raw_public_key,
134*60b67249SAndroid Build Coastguard Worker MAX_PUBLIC_KEY_SIZE, /*ctx=*/nullptr);
135*60b67249SAndroid Build Coastguard Worker } else {
136*60b67249SAndroid Build Coastguard Worker *raw_public_key_size = kPublicKeySize;
137*60b67249SAndroid Build Coastguard Worker }
138*60b67249SAndroid Build Coastguard Worker return pkey;
139*60b67249SAndroid Build Coastguard Worker } else if (key_type == dice::test::KeyType_P384) {
140*60b67249SAndroid Build Coastguard Worker const size_t kPublicKeySize = 96;
141*60b67249SAndroid Build Coastguard Worker const size_t kPrivateKeySize = 48;
142*60b67249SAndroid Build Coastguard Worker uint8_t pk[kPrivateKeySize];
143*60b67249SAndroid Build Coastguard Worker P384KeypairFromSeed(raw_public_key, pk, raw_key);
144*60b67249SAndroid Build Coastguard Worker *raw_public_key_size = kPublicKeySize;
145*60b67249SAndroid Build Coastguard Worker return EcKeyFromCoords(NID_secp384r1, raw_public_key, kPublicKeySize);
146*60b67249SAndroid Build Coastguard Worker }
147*60b67249SAndroid Build Coastguard Worker
148*60b67249SAndroid Build Coastguard Worker printf("ERROR: Unsupported key type.\n");
149*60b67249SAndroid Build Coastguard Worker return nullptr;
150*60b67249SAndroid Build Coastguard Worker }
151*60b67249SAndroid Build Coastguard Worker
CreateX509UdsCertificate(EVP_PKEY * key,const uint8_t id[DICE_ID_SIZE],uint8_t certificate[dice::test::kTestCertSize],size_t * certificate_size)152*60b67249SAndroid Build Coastguard Worker void CreateX509UdsCertificate(EVP_PKEY* key, const uint8_t id[DICE_ID_SIZE],
153*60b67249SAndroid Build Coastguard Worker uint8_t certificate[dice::test::kTestCertSize],
154*60b67249SAndroid Build Coastguard Worker size_t* certificate_size) {
155*60b67249SAndroid Build Coastguard Worker bssl::UniquePtr<X509> x509(X509_new());
156*60b67249SAndroid Build Coastguard Worker X509_set_version(x509.get(), 2);
157*60b67249SAndroid Build Coastguard Worker
158*60b67249SAndroid Build Coastguard Worker bssl::UniquePtr<ASN1_INTEGER> serial(ASN1_INTEGER_new());
159*60b67249SAndroid Build Coastguard Worker ASN1_INTEGER_set_uint64(serial.get(), 1);
160*60b67249SAndroid Build Coastguard Worker X509_set_serialNumber(x509.get(), serial.get());
161*60b67249SAndroid Build Coastguard Worker
162*60b67249SAndroid Build Coastguard Worker uint8_t id_hex[40];
163*60b67249SAndroid Build Coastguard Worker DiceHexEncode(id, DICE_ID_SIZE, id_hex, sizeof(id_hex));
164*60b67249SAndroid Build Coastguard Worker bssl::UniquePtr<X509_NAME> issuer_name(X509_NAME_new());
165*60b67249SAndroid Build Coastguard Worker X509_NAME_add_entry_by_NID(issuer_name.get(), NID_serialNumber, MBSTRING_UTF8,
166*60b67249SAndroid Build Coastguard Worker id_hex, sizeof(id_hex), 0, 0);
167*60b67249SAndroid Build Coastguard Worker X509_set_issuer_name(x509.get(), issuer_name.get());
168*60b67249SAndroid Build Coastguard Worker X509_set_subject_name(x509.get(), issuer_name.get());
169*60b67249SAndroid Build Coastguard Worker
170*60b67249SAndroid Build Coastguard Worker bssl::UniquePtr<ASN1_TIME> not_before(ASN1_TIME_new());
171*60b67249SAndroid Build Coastguard Worker ASN1_TIME_set_string(not_before.get(), "180322235959Z");
172*60b67249SAndroid Build Coastguard Worker X509_set_notBefore(x509.get(), not_before.get());
173*60b67249SAndroid Build Coastguard Worker bssl::UniquePtr<ASN1_TIME> not_after(ASN1_TIME_new());
174*60b67249SAndroid Build Coastguard Worker ASN1_TIME_set_string(not_after.get(), "99991231235959Z");
175*60b67249SAndroid Build Coastguard Worker X509_set_notAfter(x509.get(), not_after.get());
176*60b67249SAndroid Build Coastguard Worker
177*60b67249SAndroid Build Coastguard Worker bssl::UniquePtr<ASN1_OCTET_STRING> subject_key_id(ASN1_OCTET_STRING_new());
178*60b67249SAndroid Build Coastguard Worker ASN1_OCTET_STRING_set(subject_key_id.get(), id, DICE_ID_SIZE);
179*60b67249SAndroid Build Coastguard Worker bssl::UniquePtr<X509_EXTENSION> subject_key_id_ext(X509V3_EXT_i2d(
180*60b67249SAndroid Build Coastguard Worker NID_subject_key_identifier, /*crit=*/0, subject_key_id.get()));
181*60b67249SAndroid Build Coastguard Worker X509_add_ext(x509.get(), subject_key_id_ext.get(), /*loc=*/-1);
182*60b67249SAndroid Build Coastguard Worker
183*60b67249SAndroid Build Coastguard Worker bssl::UniquePtr<AUTHORITY_KEYID> authority_key_id(AUTHORITY_KEYID_new());
184*60b67249SAndroid Build Coastguard Worker authority_key_id->keyid = ASN1_OCTET_STRING_dup(subject_key_id.get());
185*60b67249SAndroid Build Coastguard Worker bssl::UniquePtr<X509_EXTENSION> authority_key_id_ext(X509V3_EXT_i2d(
186*60b67249SAndroid Build Coastguard Worker NID_authority_key_identifier, /*crit=*/0, authority_key_id.get()));
187*60b67249SAndroid Build Coastguard Worker X509_add_ext(x509.get(), authority_key_id_ext.get(), /*loc=*/-1);
188*60b67249SAndroid Build Coastguard Worker
189*60b67249SAndroid Build Coastguard Worker bssl::UniquePtr<ASN1_BIT_STRING> key_usage(ASN1_BIT_STRING_new());
190*60b67249SAndroid Build Coastguard Worker ASN1_BIT_STRING_set_bit(key_usage.get(), 5 /*keyCertSign*/, 1);
191*60b67249SAndroid Build Coastguard Worker bssl::UniquePtr<X509_EXTENSION> key_usage_ext(
192*60b67249SAndroid Build Coastguard Worker X509V3_EXT_i2d(NID_key_usage, /*crit=*/1, key_usage.get()));
193*60b67249SAndroid Build Coastguard Worker X509_add_ext(x509.get(), key_usage_ext.get(), /*loc=*/-1);
194*60b67249SAndroid Build Coastguard Worker
195*60b67249SAndroid Build Coastguard Worker bssl::UniquePtr<BASIC_CONSTRAINTS> basic_constraints(BASIC_CONSTRAINTS_new());
196*60b67249SAndroid Build Coastguard Worker basic_constraints->ca = 1;
197*60b67249SAndroid Build Coastguard Worker bssl::UniquePtr<X509_EXTENSION> basic_constraints_ext(X509V3_EXT_i2d(
198*60b67249SAndroid Build Coastguard Worker NID_basic_constraints, /*crit=*/1, basic_constraints.get()));
199*60b67249SAndroid Build Coastguard Worker X509_add_ext(x509.get(), basic_constraints_ext.get(), /*loc=*/-1);
200*60b67249SAndroid Build Coastguard Worker
201*60b67249SAndroid Build Coastguard Worker X509_set_pubkey(x509.get(), key);
202*60b67249SAndroid Build Coastguard Worker // ED25519 always uses SHA-512 so md must be NULL.
203*60b67249SAndroid Build Coastguard Worker const EVP_MD* md =
204*60b67249SAndroid Build Coastguard Worker (EVP_PKEY_id(key) == EVP_PKEY_ED25519) ? nullptr : EVP_sha512();
205*60b67249SAndroid Build Coastguard Worker X509_sign(x509.get(), key, md);
206*60b67249SAndroid Build Coastguard Worker if (i2d_X509(x509.get(), /*out=*/nullptr) <=
207*60b67249SAndroid Build Coastguard Worker static_cast<int>(dice::test::kTestCertSize)) {
208*60b67249SAndroid Build Coastguard Worker uint8_t* p = certificate;
209*60b67249SAndroid Build Coastguard Worker *certificate_size = i2d_X509(x509.get(), &p);
210*60b67249SAndroid Build Coastguard Worker } else {
211*60b67249SAndroid Build Coastguard Worker *certificate_size = 0;
212*60b67249SAndroid Build Coastguard Worker }
213*60b67249SAndroid Build Coastguard Worker }
214*60b67249SAndroid Build Coastguard Worker
VerifyX509CertificateChain(const uint8_t * root_certificate,size_t root_certificate_size,const dice::test::DiceStateForTest states[],size_t num_dice_states,bool is_partial_chain)215*60b67249SAndroid Build Coastguard Worker bool VerifyX509CertificateChain(const uint8_t* root_certificate,
216*60b67249SAndroid Build Coastguard Worker size_t root_certificate_size,
217*60b67249SAndroid Build Coastguard Worker const dice::test::DiceStateForTest states[],
218*60b67249SAndroid Build Coastguard Worker size_t num_dice_states, bool is_partial_chain) {
219*60b67249SAndroid Build Coastguard Worker bssl::UniquePtr<STACK_OF(X509)> trusted_certs(sk_X509_new_null());
220*60b67249SAndroid Build Coastguard Worker bssl::PushToStack(trusted_certs.get(),
221*60b67249SAndroid Build Coastguard Worker bssl::UpRef(ParseX509Certificate(root_certificate,
222*60b67249SAndroid Build Coastguard Worker root_certificate_size)));
223*60b67249SAndroid Build Coastguard Worker bssl::UniquePtr<STACK_OF(X509)> untrusted_certs(sk_X509_new_null());
224*60b67249SAndroid Build Coastguard Worker for (size_t i = 0; i < num_dice_states - 1; ++i) {
225*60b67249SAndroid Build Coastguard Worker bssl::PushToStack(untrusted_certs.get(),
226*60b67249SAndroid Build Coastguard Worker bssl::UpRef(ParseX509Certificate(
227*60b67249SAndroid Build Coastguard Worker states[i].certificate, states[i].certificate_size)));
228*60b67249SAndroid Build Coastguard Worker }
229*60b67249SAndroid Build Coastguard Worker bssl::UniquePtr<X509> leaf_cert(
230*60b67249SAndroid Build Coastguard Worker ParseX509Certificate(states[num_dice_states - 1].certificate,
231*60b67249SAndroid Build Coastguard Worker states[num_dice_states - 1].certificate_size));
232*60b67249SAndroid Build Coastguard Worker bssl::UniquePtr<X509_STORE> x509_store(X509_STORE_new());
233*60b67249SAndroid Build Coastguard Worker bssl::UniquePtr<X509_STORE_CTX> x509_store_ctx(X509_STORE_CTX_new());
234*60b67249SAndroid Build Coastguard Worker X509_STORE_CTX_init(x509_store_ctx.get(), x509_store.get(), leaf_cert.get(),
235*60b67249SAndroid Build Coastguard Worker untrusted_certs.get());
236*60b67249SAndroid Build Coastguard Worker X509_STORE_CTX_trusted_stack(x509_store_ctx.get(), trusted_certs.get());
237*60b67249SAndroid Build Coastguard Worker X509_VERIFY_PARAM* param = X509_VERIFY_PARAM_new();
238*60b67249SAndroid Build Coastguard Worker X509_VERIFY_PARAM_set_time(param, 1577923199 /*1/1/2020*/);
239*60b67249SAndroid Build Coastguard Worker X509_VERIFY_PARAM_set_depth(param, 10);
240*60b67249SAndroid Build Coastguard Worker if (is_partial_chain) {
241*60b67249SAndroid Build Coastguard Worker X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_PARTIAL_CHAIN);
242*60b67249SAndroid Build Coastguard Worker }
243*60b67249SAndroid Build Coastguard Worker // Boringssl doesn't support custom extensions, so ignore them.
244*60b67249SAndroid Build Coastguard Worker X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_IGNORE_CRITICAL);
245*60b67249SAndroid Build Coastguard Worker X509_STORE_CTX_set0_param(x509_store_ctx.get(), param);
246*60b67249SAndroid Build Coastguard Worker return (1 == X509_verify_cert(x509_store_ctx.get()));
247*60b67249SAndroid Build Coastguard Worker }
248*60b67249SAndroid Build Coastguard Worker
CreateEd25519CborUdsCertificate(const uint8_t private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE],const uint8_t id[DICE_ID_SIZE],uint8_t certificate[dice::test::kTestCertSize],size_t * certificate_size)249*60b67249SAndroid Build Coastguard Worker void CreateEd25519CborUdsCertificate(
250*60b67249SAndroid Build Coastguard Worker const uint8_t private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE],
251*60b67249SAndroid Build Coastguard Worker const uint8_t id[DICE_ID_SIZE],
252*60b67249SAndroid Build Coastguard Worker uint8_t certificate[dice::test::kTestCertSize], size_t* certificate_size) {
253*60b67249SAndroid Build Coastguard Worker const uint8_t kProtectedAttributesCbor[3] = {
254*60b67249SAndroid Build Coastguard Worker 0xa1 /* map(1) */, 0x01 /* alg(1) */, 0x27 /* EdDSA(-8) */};
255*60b67249SAndroid Build Coastguard Worker const int64_t kCwtIssuerLabel = 1;
256*60b67249SAndroid Build Coastguard Worker const int64_t kCwtSubjectLabel = 2;
257*60b67249SAndroid Build Coastguard Worker const int64_t kUdsPublicKeyLabel = -4670552;
258*60b67249SAndroid Build Coastguard Worker const int64_t kUdsKeyUsageLabel = -4670553;
259*60b67249SAndroid Build Coastguard Worker const uint8_t kKeyUsageCertSign = 32; // Bit 5.
260*60b67249SAndroid Build Coastguard Worker
261*60b67249SAndroid Build Coastguard Worker // Public key encoded as a COSE_Key.
262*60b67249SAndroid Build Coastguard Worker uint8_t public_key[32];
263*60b67249SAndroid Build Coastguard Worker uint8_t bssl_private_key[64];
264*60b67249SAndroid Build Coastguard Worker ED25519_keypair_from_seed(public_key, bssl_private_key, private_key_seed);
265*60b67249SAndroid Build Coastguard Worker cn_cbor_errback error;
266*60b67249SAndroid Build Coastguard Worker ScopedCbor public_key_cbor(cn_cbor_map_create(&error));
267*60b67249SAndroid Build Coastguard Worker // kty = okp
268*60b67249SAndroid Build Coastguard Worker cn_cbor_mapput_int(public_key_cbor.get(), 1, cn_cbor_int_create(1, &error),
269*60b67249SAndroid Build Coastguard Worker &error);
270*60b67249SAndroid Build Coastguard Worker // crv = ed25519
271*60b67249SAndroid Build Coastguard Worker cn_cbor_mapput_int(public_key_cbor.get(), -1, cn_cbor_int_create(6, &error),
272*60b67249SAndroid Build Coastguard Worker &error);
273*60b67249SAndroid Build Coastguard Worker // x = public_key
274*60b67249SAndroid Build Coastguard Worker cn_cbor_mapput_int(public_key_cbor.get(), -2,
275*60b67249SAndroid Build Coastguard Worker cn_cbor_data_create(public_key, 32, &error), &error);
276*60b67249SAndroid Build Coastguard Worker uint8_t encoded_public_key[100];
277*60b67249SAndroid Build Coastguard Worker size_t encoded_public_key_size =
278*60b67249SAndroid Build Coastguard Worker cn_cbor_encoder_write(encoded_public_key, 0, 100, public_key_cbor.get());
279*60b67249SAndroid Build Coastguard Worker
280*60b67249SAndroid Build Coastguard Worker // Simple CWT payload with issuer, subject, and use the same subject public
281*60b67249SAndroid Build Coastguard Worker // key field as a CDI certificate to make verification easy.
282*60b67249SAndroid Build Coastguard Worker char id_hex[41];
283*60b67249SAndroid Build Coastguard Worker DiceHexEncode(id, DICE_ID_SIZE, id_hex, sizeof(id_hex));
284*60b67249SAndroid Build Coastguard Worker id_hex[40] = '\0';
285*60b67249SAndroid Build Coastguard Worker ScopedCbor cwt(cn_cbor_map_create(&error));
286*60b67249SAndroid Build Coastguard Worker cn_cbor_mapput_int(cwt.get(), kCwtIssuerLabel,
287*60b67249SAndroid Build Coastguard Worker cn_cbor_string_create(id_hex, &error), &error);
288*60b67249SAndroid Build Coastguard Worker cn_cbor_mapput_int(cwt.get(), kCwtSubjectLabel,
289*60b67249SAndroid Build Coastguard Worker cn_cbor_string_create(id_hex, &error), &error);
290*60b67249SAndroid Build Coastguard Worker cn_cbor_mapput_int(
291*60b67249SAndroid Build Coastguard Worker cwt.get(), kUdsPublicKeyLabel,
292*60b67249SAndroid Build Coastguard Worker cn_cbor_data_create(encoded_public_key, encoded_public_key_size, &error),
293*60b67249SAndroid Build Coastguard Worker &error);
294*60b67249SAndroid Build Coastguard Worker uint8_t key_usage_byte = kKeyUsageCertSign;
295*60b67249SAndroid Build Coastguard Worker cn_cbor_mapput_int(cwt.get(), kUdsKeyUsageLabel,
296*60b67249SAndroid Build Coastguard Worker cn_cbor_data_create(&key_usage_byte, 1, &error), &error);
297*60b67249SAndroid Build Coastguard Worker uint8_t payload[dice::test::kTestCertSize];
298*60b67249SAndroid Build Coastguard Worker size_t payload_size =
299*60b67249SAndroid Build Coastguard Worker cn_cbor_encoder_write(payload, 0, dice::test::kTestCertSize, cwt.get());
300*60b67249SAndroid Build Coastguard Worker
301*60b67249SAndroid Build Coastguard Worker // Signature over COSE Sign1 TBS.
302*60b67249SAndroid Build Coastguard Worker ScopedCbor tbs_cbor(cn_cbor_array_create(&error));
303*60b67249SAndroid Build Coastguard Worker cn_cbor_array_append(tbs_cbor.get(),
304*60b67249SAndroid Build Coastguard Worker cn_cbor_string_create("Signature1", &error), &error);
305*60b67249SAndroid Build Coastguard Worker cn_cbor_array_append(tbs_cbor.get(),
306*60b67249SAndroid Build Coastguard Worker cn_cbor_data_create(kProtectedAttributesCbor, 3, &error),
307*60b67249SAndroid Build Coastguard Worker &error);
308*60b67249SAndroid Build Coastguard Worker cn_cbor_array_append(tbs_cbor.get(), cn_cbor_data_create(NULL, 0, &error),
309*60b67249SAndroid Build Coastguard Worker &error);
310*60b67249SAndroid Build Coastguard Worker cn_cbor_array_append(tbs_cbor.get(),
311*60b67249SAndroid Build Coastguard Worker cn_cbor_data_create(payload, payload_size, &error),
312*60b67249SAndroid Build Coastguard Worker &error);
313*60b67249SAndroid Build Coastguard Worker uint8_t tbs[dice::test::kTestCertSize];
314*60b67249SAndroid Build Coastguard Worker size_t tbs_size =
315*60b67249SAndroid Build Coastguard Worker cn_cbor_encoder_write(tbs, 0, dice::test::kTestCertSize, tbs_cbor.get());
316*60b67249SAndroid Build Coastguard Worker uint8_t signature[64];
317*60b67249SAndroid Build Coastguard Worker ED25519_sign(signature, tbs, tbs_size, bssl_private_key);
318*60b67249SAndroid Build Coastguard Worker
319*60b67249SAndroid Build Coastguard Worker // COSE Sign1.
320*60b67249SAndroid Build Coastguard Worker ScopedCbor sign1(cn_cbor_array_create(&error));
321*60b67249SAndroid Build Coastguard Worker cn_cbor_array_append(sign1.get(),
322*60b67249SAndroid Build Coastguard Worker cn_cbor_data_create(kProtectedAttributesCbor, 3, &error),
323*60b67249SAndroid Build Coastguard Worker &error);
324*60b67249SAndroid Build Coastguard Worker cn_cbor_array_append(sign1.get(), cn_cbor_map_create(&error), &error);
325*60b67249SAndroid Build Coastguard Worker cn_cbor_array_append(
326*60b67249SAndroid Build Coastguard Worker sign1.get(), cn_cbor_data_create(payload, payload_size, &error), &error);
327*60b67249SAndroid Build Coastguard Worker cn_cbor_array_append(sign1.get(), cn_cbor_data_create(signature, 64, &error),
328*60b67249SAndroid Build Coastguard Worker &error);
329*60b67249SAndroid Build Coastguard Worker *certificate_size = cn_cbor_encoder_write(
330*60b67249SAndroid Build Coastguard Worker certificate, 0, dice::test::kTestCertSize, sign1.get());
331*60b67249SAndroid Build Coastguard Worker }
332*60b67249SAndroid Build Coastguard Worker
CreateEcdsaCborUdsCertificate(std::span<uint8_t> public_key,std::function<std::vector<uint8_t> (std::span<uint8_t>)> sign,const uint8_t id[DICE_ID_SIZE],int8_t alg,uint8_t crv,uint8_t certificate[dice::test::kTestCertSize],size_t * certificate_size)333*60b67249SAndroid Build Coastguard Worker void CreateEcdsaCborUdsCertificate(
334*60b67249SAndroid Build Coastguard Worker std::span<uint8_t> public_key,
335*60b67249SAndroid Build Coastguard Worker std::function<std::vector<uint8_t>(std::span<uint8_t>)> sign,
336*60b67249SAndroid Build Coastguard Worker const uint8_t id[DICE_ID_SIZE], int8_t alg, uint8_t crv,
337*60b67249SAndroid Build Coastguard Worker uint8_t certificate[dice::test::kTestCertSize], size_t* certificate_size) {
338*60b67249SAndroid Build Coastguard Worker const int64_t kCwtIssuerLabel = 1;
339*60b67249SAndroid Build Coastguard Worker const int64_t kCwtSubjectLabel = 2;
340*60b67249SAndroid Build Coastguard Worker const int64_t kUdsPublicKeyLabel = -4670552;
341*60b67249SAndroid Build Coastguard Worker const int64_t kUdsKeyUsageLabel = -4670553;
342*60b67249SAndroid Build Coastguard Worker const uint8_t kKeyUsageCertSign = 32; // Bit 5.
343*60b67249SAndroid Build Coastguard Worker const uint8_t kProtectedAttributesCbor[4] = {0xa1 /* map(1) */,
344*60b67249SAndroid Build Coastguard Worker 0x01 /* alg(1) */, 0x38,
345*60b67249SAndroid Build Coastguard Worker static_cast<uint8_t>(-alg - 1)};
346*60b67249SAndroid Build Coastguard Worker
347*60b67249SAndroid Build Coastguard Worker cn_cbor_errback error;
348*60b67249SAndroid Build Coastguard Worker ScopedCbor public_key_cbor(cn_cbor_map_create(&error));
349*60b67249SAndroid Build Coastguard Worker // kty = ec2
350*60b67249SAndroid Build Coastguard Worker cn_cbor_mapput_int(public_key_cbor.get(), 1, cn_cbor_int_create(2, &error),
351*60b67249SAndroid Build Coastguard Worker &error);
352*60b67249SAndroid Build Coastguard Worker // crv
353*60b67249SAndroid Build Coastguard Worker cn_cbor_mapput_int(public_key_cbor.get(), -1, cn_cbor_int_create(crv, &error),
354*60b67249SAndroid Build Coastguard Worker &error);
355*60b67249SAndroid Build Coastguard Worker // x = public_key X
356*60b67249SAndroid Build Coastguard Worker size_t coord_size = public_key.size() / 2;
357*60b67249SAndroid Build Coastguard Worker cn_cbor_mapput_int(public_key_cbor.get(), -2,
358*60b67249SAndroid Build Coastguard Worker cn_cbor_data_create(&public_key[0], coord_size, &error),
359*60b67249SAndroid Build Coastguard Worker &error);
360*60b67249SAndroid Build Coastguard Worker // y = public_key Y
361*60b67249SAndroid Build Coastguard Worker cn_cbor_mapput_int(
362*60b67249SAndroid Build Coastguard Worker public_key_cbor.get(), -3,
363*60b67249SAndroid Build Coastguard Worker cn_cbor_data_create(&public_key[coord_size], coord_size, &error), &error);
364*60b67249SAndroid Build Coastguard Worker uint8_t encoded_public_key[200];
365*60b67249SAndroid Build Coastguard Worker size_t encoded_public_key_size =
366*60b67249SAndroid Build Coastguard Worker cn_cbor_encoder_write(encoded_public_key, 0, 200, public_key_cbor.get());
367*60b67249SAndroid Build Coastguard Worker
368*60b67249SAndroid Build Coastguard Worker // Simple CWT payload with issuer, subject, and use the same subject public
369*60b67249SAndroid Build Coastguard Worker // key field as a CDI certificate to make verification easy.
370*60b67249SAndroid Build Coastguard Worker char id_hex[41];
371*60b67249SAndroid Build Coastguard Worker DiceHexEncode(id, DICE_ID_SIZE, id_hex, sizeof(id_hex));
372*60b67249SAndroid Build Coastguard Worker id_hex[40] = '\0';
373*60b67249SAndroid Build Coastguard Worker ScopedCbor cwt(cn_cbor_map_create(&error));
374*60b67249SAndroid Build Coastguard Worker cn_cbor_mapput_int(cwt.get(), kCwtIssuerLabel,
375*60b67249SAndroid Build Coastguard Worker cn_cbor_string_create(id_hex, &error), &error);
376*60b67249SAndroid Build Coastguard Worker cn_cbor_mapput_int(cwt.get(), kCwtSubjectLabel,
377*60b67249SAndroid Build Coastguard Worker cn_cbor_string_create(id_hex, &error), &error);
378*60b67249SAndroid Build Coastguard Worker cn_cbor_mapput_int(
379*60b67249SAndroid Build Coastguard Worker cwt.get(), kUdsPublicKeyLabel,
380*60b67249SAndroid Build Coastguard Worker cn_cbor_data_create(encoded_public_key, encoded_public_key_size, &error),
381*60b67249SAndroid Build Coastguard Worker &error);
382*60b67249SAndroid Build Coastguard Worker uint8_t key_usage_byte = kKeyUsageCertSign;
383*60b67249SAndroid Build Coastguard Worker cn_cbor_mapput_int(cwt.get(), kUdsKeyUsageLabel,
384*60b67249SAndroid Build Coastguard Worker cn_cbor_data_create(&key_usage_byte, 1, &error), &error);
385*60b67249SAndroid Build Coastguard Worker uint8_t payload[dice::test::kTestCertSize];
386*60b67249SAndroid Build Coastguard Worker size_t payload_size =
387*60b67249SAndroid Build Coastguard Worker cn_cbor_encoder_write(payload, 0, dice::test::kTestCertSize, cwt.get());
388*60b67249SAndroid Build Coastguard Worker
389*60b67249SAndroid Build Coastguard Worker // Signature over COSE Sign1 TBS.
390*60b67249SAndroid Build Coastguard Worker ScopedCbor tbs_cbor(cn_cbor_array_create(&error));
391*60b67249SAndroid Build Coastguard Worker cn_cbor_array_append(tbs_cbor.get(),
392*60b67249SAndroid Build Coastguard Worker cn_cbor_string_create("Signature1", &error), &error);
393*60b67249SAndroid Build Coastguard Worker cn_cbor_array_append(tbs_cbor.get(),
394*60b67249SAndroid Build Coastguard Worker cn_cbor_data_create(kProtectedAttributesCbor, 4, &error),
395*60b67249SAndroid Build Coastguard Worker &error);
396*60b67249SAndroid Build Coastguard Worker cn_cbor_array_append(tbs_cbor.get(), cn_cbor_data_create(NULL, 0, &error),
397*60b67249SAndroid Build Coastguard Worker &error);
398*60b67249SAndroid Build Coastguard Worker cn_cbor_array_append(tbs_cbor.get(),
399*60b67249SAndroid Build Coastguard Worker cn_cbor_data_create(payload, payload_size, &error),
400*60b67249SAndroid Build Coastguard Worker &error);
401*60b67249SAndroid Build Coastguard Worker uint8_t tbs[dice::test::kTestCertSize];
402*60b67249SAndroid Build Coastguard Worker size_t tbs_size =
403*60b67249SAndroid Build Coastguard Worker cn_cbor_encoder_write(tbs, 0, dice::test::kTestCertSize, tbs_cbor.get());
404*60b67249SAndroid Build Coastguard Worker std::vector signature = sign({tbs, tbs_size});
405*60b67249SAndroid Build Coastguard Worker
406*60b67249SAndroid Build Coastguard Worker // COSE Sign1.
407*60b67249SAndroid Build Coastguard Worker ScopedCbor sign1(cn_cbor_array_create(&error));
408*60b67249SAndroid Build Coastguard Worker cn_cbor_array_append(sign1.get(),
409*60b67249SAndroid Build Coastguard Worker cn_cbor_data_create(kProtectedAttributesCbor, 4, &error),
410*60b67249SAndroid Build Coastguard Worker &error);
411*60b67249SAndroid Build Coastguard Worker cn_cbor_array_append(sign1.get(), cn_cbor_map_create(&error), &error);
412*60b67249SAndroid Build Coastguard Worker cn_cbor_array_append(
413*60b67249SAndroid Build Coastguard Worker sign1.get(), cn_cbor_data_create(payload, payload_size, &error), &error);
414*60b67249SAndroid Build Coastguard Worker cn_cbor_array_append(
415*60b67249SAndroid Build Coastguard Worker sign1.get(),
416*60b67249SAndroid Build Coastguard Worker cn_cbor_data_create(signature.data(), signature.size(), &error), &error);
417*60b67249SAndroid Build Coastguard Worker *certificate_size = cn_cbor_encoder_write(
418*60b67249SAndroid Build Coastguard Worker certificate, 0, dice::test::kTestCertSize, sign1.get());
419*60b67249SAndroid Build Coastguard Worker }
420*60b67249SAndroid Build Coastguard Worker
CreateP256CborUdsCertificate(const uint8_t private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE],const uint8_t id[DICE_ID_SIZE],uint8_t certificate[dice::test::kTestCertSize],size_t * certificate_size)421*60b67249SAndroid Build Coastguard Worker void CreateP256CborUdsCertificate(
422*60b67249SAndroid Build Coastguard Worker const uint8_t private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE],
423*60b67249SAndroid Build Coastguard Worker const uint8_t id[DICE_ID_SIZE],
424*60b67249SAndroid Build Coastguard Worker uint8_t certificate[dice::test::kTestCertSize], size_t* certificate_size) {
425*60b67249SAndroid Build Coastguard Worker const int8_t kAlgEs256 = -7;
426*60b67249SAndroid Build Coastguard Worker const uint8_t kCrvP256 = 1;
427*60b67249SAndroid Build Coastguard Worker const size_t kPublicKeySize = 64;
428*60b67249SAndroid Build Coastguard Worker const size_t kPrivateKeySize = 32;
429*60b67249SAndroid Build Coastguard Worker const size_t kSignatureSize = 64;
430*60b67249SAndroid Build Coastguard Worker
431*60b67249SAndroid Build Coastguard Worker // Public key encoded as a COSE_Key.
432*60b67249SAndroid Build Coastguard Worker uint8_t public_key[kPublicKeySize];
433*60b67249SAndroid Build Coastguard Worker uint8_t private_key[kPrivateKeySize];
434*60b67249SAndroid Build Coastguard Worker P256KeypairFromSeed(public_key, private_key, private_key_seed);
435*60b67249SAndroid Build Coastguard Worker
436*60b67249SAndroid Build Coastguard Worker auto sign = [&](std::span<uint8_t> tbs) {
437*60b67249SAndroid Build Coastguard Worker std::vector<uint8_t> signature(kSignatureSize);
438*60b67249SAndroid Build Coastguard Worker P256Sign(signature.data(), tbs.data(), tbs.size(), private_key);
439*60b67249SAndroid Build Coastguard Worker return signature;
440*60b67249SAndroid Build Coastguard Worker };
441*60b67249SAndroid Build Coastguard Worker
442*60b67249SAndroid Build Coastguard Worker CreateEcdsaCborUdsCertificate(public_key, sign, id, kAlgEs256, kCrvP256,
443*60b67249SAndroid Build Coastguard Worker certificate, certificate_size);
444*60b67249SAndroid Build Coastguard Worker }
445*60b67249SAndroid Build Coastguard Worker
CreateP384CborUdsCertificate(const uint8_t private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE],const uint8_t id[DICE_ID_SIZE],uint8_t certificate[dice::test::kTestCertSize],size_t * certificate_size)446*60b67249SAndroid Build Coastguard Worker void CreateP384CborUdsCertificate(
447*60b67249SAndroid Build Coastguard Worker const uint8_t private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE],
448*60b67249SAndroid Build Coastguard Worker const uint8_t id[DICE_ID_SIZE],
449*60b67249SAndroid Build Coastguard Worker uint8_t certificate[dice::test::kTestCertSize], size_t* certificate_size) {
450*60b67249SAndroid Build Coastguard Worker const int8_t kAlgEs384 = -35;
451*60b67249SAndroid Build Coastguard Worker const uint8_t kCrvP384 = 2;
452*60b67249SAndroid Build Coastguard Worker const size_t kPublicKeySize = 96;
453*60b67249SAndroid Build Coastguard Worker const size_t kPrivateKeySize = 48;
454*60b67249SAndroid Build Coastguard Worker const size_t kSignatureSize = 96;
455*60b67249SAndroid Build Coastguard Worker
456*60b67249SAndroid Build Coastguard Worker // Public key encoded as a COSE_Key.
457*60b67249SAndroid Build Coastguard Worker uint8_t public_key[kPublicKeySize];
458*60b67249SAndroid Build Coastguard Worker uint8_t private_key[kPrivateKeySize];
459*60b67249SAndroid Build Coastguard Worker P384KeypairFromSeed(public_key, private_key, private_key_seed);
460*60b67249SAndroid Build Coastguard Worker
461*60b67249SAndroid Build Coastguard Worker auto sign = [&](std::span<uint8_t> tbs) {
462*60b67249SAndroid Build Coastguard Worker std::vector<uint8_t> signature(kSignatureSize);
463*60b67249SAndroid Build Coastguard Worker P384Sign(signature.data(), tbs.data(), tbs.size(), private_key);
464*60b67249SAndroid Build Coastguard Worker return signature;
465*60b67249SAndroid Build Coastguard Worker };
466*60b67249SAndroid Build Coastguard Worker
467*60b67249SAndroid Build Coastguard Worker CreateEcdsaCborUdsCertificate(public_key, sign, id, kAlgEs384, kCrvP384,
468*60b67249SAndroid Build Coastguard Worker certificate, certificate_size);
469*60b67249SAndroid Build Coastguard Worker }
470*60b67249SAndroid Build Coastguard Worker
CreateCborUdsCertificate(const uint8_t private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE],dice::test::KeyType key_type,const uint8_t id[DICE_ID_SIZE],uint8_t certificate[dice::test::kTestCertSize],size_t * certificate_size)471*60b67249SAndroid Build Coastguard Worker void CreateCborUdsCertificate(
472*60b67249SAndroid Build Coastguard Worker const uint8_t private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE],
473*60b67249SAndroid Build Coastguard Worker dice::test::KeyType key_type, const uint8_t id[DICE_ID_SIZE],
474*60b67249SAndroid Build Coastguard Worker uint8_t certificate[dice::test::kTestCertSize], size_t* certificate_size) {
475*60b67249SAndroid Build Coastguard Worker switch (key_type) {
476*60b67249SAndroid Build Coastguard Worker case dice::test::KeyType_Ed25519:
477*60b67249SAndroid Build Coastguard Worker CreateEd25519CborUdsCertificate(private_key_seed, id, certificate,
478*60b67249SAndroid Build Coastguard Worker certificate_size);
479*60b67249SAndroid Build Coastguard Worker break;
480*60b67249SAndroid Build Coastguard Worker case dice::test::KeyType_P256:
481*60b67249SAndroid Build Coastguard Worker CreateP256CborUdsCertificate(private_key_seed, id, certificate,
482*60b67249SAndroid Build Coastguard Worker certificate_size);
483*60b67249SAndroid Build Coastguard Worker break;
484*60b67249SAndroid Build Coastguard Worker case dice::test::KeyType_P256_COMPRESSED:
485*60b67249SAndroid Build Coastguard Worker fprintf(stderr, "ERROR: Unsupported key type.\n");
486*60b67249SAndroid Build Coastguard Worker abort();
487*60b67249SAndroid Build Coastguard Worker case dice::test::KeyType_P384:
488*60b67249SAndroid Build Coastguard Worker CreateP384CborUdsCertificate(private_key_seed, id, certificate,
489*60b67249SAndroid Build Coastguard Worker certificate_size);
490*60b67249SAndroid Build Coastguard Worker break;
491*60b67249SAndroid Build Coastguard Worker }
492*60b67249SAndroid Build Coastguard Worker }
493*60b67249SAndroid Build Coastguard Worker
ExtractCwtFromCborCertificate(const uint8_t * certificate,size_t certificate_size)494*60b67249SAndroid Build Coastguard Worker ScopedCbor ExtractCwtFromCborCertificate(const uint8_t* certificate,
495*60b67249SAndroid Build Coastguard Worker size_t certificate_size) {
496*60b67249SAndroid Build Coastguard Worker cn_cbor_errback error;
497*60b67249SAndroid Build Coastguard Worker ScopedCbor sign1(cn_cbor_decode(certificate, certificate_size, &error));
498*60b67249SAndroid Build Coastguard Worker if (!sign1 || sign1->type != CN_CBOR_ARRAY || sign1->length != 4) {
499*60b67249SAndroid Build Coastguard Worker return nullptr;
500*60b67249SAndroid Build Coastguard Worker }
501*60b67249SAndroid Build Coastguard Worker cn_cbor* payload = cn_cbor_index(sign1.get(), 2);
502*60b67249SAndroid Build Coastguard Worker if (!payload || payload->type != CN_CBOR_BYTES) {
503*60b67249SAndroid Build Coastguard Worker return nullptr;
504*60b67249SAndroid Build Coastguard Worker }
505*60b67249SAndroid Build Coastguard Worker ScopedCbor cwt(cn_cbor_decode(payload->v.bytes, payload->length, &error));
506*60b67249SAndroid Build Coastguard Worker if (!cwt || cwt->type != CN_CBOR_MAP) {
507*60b67249SAndroid Build Coastguard Worker return nullptr;
508*60b67249SAndroid Build Coastguard Worker }
509*60b67249SAndroid Build Coastguard Worker return cwt;
510*60b67249SAndroid Build Coastguard Worker }
511*60b67249SAndroid Build Coastguard Worker
ExtractPublicKeyFromCwt(const cn_cbor * cwt)512*60b67249SAndroid Build Coastguard Worker ScopedCbor ExtractPublicKeyFromCwt(const cn_cbor* cwt) {
513*60b67249SAndroid Build Coastguard Worker cn_cbor_errback error;
514*60b67249SAndroid Build Coastguard Worker cn_cbor* key_bytes = cn_cbor_mapget_int(cwt, -4670552);
515*60b67249SAndroid Build Coastguard Worker if (!key_bytes || key_bytes->type != CN_CBOR_BYTES) {
516*60b67249SAndroid Build Coastguard Worker return nullptr;
517*60b67249SAndroid Build Coastguard Worker }
518*60b67249SAndroid Build Coastguard Worker ScopedCbor key(cn_cbor_decode(key_bytes->v.bytes, key_bytes->length, &error));
519*60b67249SAndroid Build Coastguard Worker if (key && key->type != CN_CBOR_MAP) {
520*60b67249SAndroid Build Coastguard Worker return nullptr;
521*60b67249SAndroid Build Coastguard Worker }
522*60b67249SAndroid Build Coastguard Worker return key;
523*60b67249SAndroid Build Coastguard Worker }
524*60b67249SAndroid Build Coastguard Worker
ExtractIdsFromCwt(const cn_cbor * cwt,char authority_id_hex[40],char subject_id_hex[40])525*60b67249SAndroid Build Coastguard Worker bool ExtractIdsFromCwt(const cn_cbor* cwt, char authority_id_hex[40],
526*60b67249SAndroid Build Coastguard Worker char subject_id_hex[40]) {
527*60b67249SAndroid Build Coastguard Worker cn_cbor* authority_id_cbor = cn_cbor_mapget_int(cwt, 1);
528*60b67249SAndroid Build Coastguard Worker cn_cbor* subject_id_cbor = cn_cbor_mapget_int(cwt, 2);
529*60b67249SAndroid Build Coastguard Worker if (!authority_id_cbor || !subject_id_cbor) {
530*60b67249SAndroid Build Coastguard Worker return false;
531*60b67249SAndroid Build Coastguard Worker }
532*60b67249SAndroid Build Coastguard Worker if (authority_id_cbor->type != CN_CBOR_TEXT ||
533*60b67249SAndroid Build Coastguard Worker authority_id_cbor->length != 40 ||
534*60b67249SAndroid Build Coastguard Worker subject_id_cbor->type != CN_CBOR_TEXT || subject_id_cbor->length != 40) {
535*60b67249SAndroid Build Coastguard Worker return false;
536*60b67249SAndroid Build Coastguard Worker }
537*60b67249SAndroid Build Coastguard Worker memcpy(authority_id_hex, authority_id_cbor->v.str, 40);
538*60b67249SAndroid Build Coastguard Worker memcpy(subject_id_hex, subject_id_cbor->v.str, 40);
539*60b67249SAndroid Build Coastguard Worker return true;
540*60b67249SAndroid Build Coastguard Worker }
541*60b67249SAndroid Build Coastguard Worker
ExtractKeyUsageFromCwt(const cn_cbor * cwt,uint64_t * key_usage)542*60b67249SAndroid Build Coastguard Worker bool ExtractKeyUsageFromCwt(const cn_cbor* cwt, uint64_t* key_usage) {
543*60b67249SAndroid Build Coastguard Worker cn_cbor* key_usage_bytes = cn_cbor_mapget_int(cwt, -4670553);
544*60b67249SAndroid Build Coastguard Worker if (!key_usage_bytes || key_usage_bytes->type != CN_CBOR_BYTES) {
545*60b67249SAndroid Build Coastguard Worker return false;
546*60b67249SAndroid Build Coastguard Worker }
547*60b67249SAndroid Build Coastguard Worker // The highest key usage bit defined in RFC 5280 is 8.
548*60b67249SAndroid Build Coastguard Worker if (key_usage_bytes->length > 2) {
549*60b67249SAndroid Build Coastguard Worker return false;
550*60b67249SAndroid Build Coastguard Worker }
551*60b67249SAndroid Build Coastguard Worker if (key_usage_bytes->length == 0) {
552*60b67249SAndroid Build Coastguard Worker *key_usage = 0;
553*60b67249SAndroid Build Coastguard Worker return true;
554*60b67249SAndroid Build Coastguard Worker }
555*60b67249SAndroid Build Coastguard Worker *key_usage = key_usage_bytes->v.bytes[0];
556*60b67249SAndroid Build Coastguard Worker if (key_usage_bytes->length == 2) {
557*60b67249SAndroid Build Coastguard Worker uint64_t tmp = key_usage_bytes->v.bytes[1];
558*60b67249SAndroid Build Coastguard Worker *key_usage += tmp >> 8;
559*60b67249SAndroid Build Coastguard Worker }
560*60b67249SAndroid Build Coastguard Worker return true;
561*60b67249SAndroid Build Coastguard Worker }
562*60b67249SAndroid Build Coastguard Worker
ValidateCborCertificateCdiFields(const cn_cbor * cwt,bool expect_cdi_certificate)563*60b67249SAndroid Build Coastguard Worker bool ValidateCborCertificateCdiFields(const cn_cbor* cwt,
564*60b67249SAndroid Build Coastguard Worker bool expect_cdi_certificate) {
565*60b67249SAndroid Build Coastguard Worker cn_cbor* code_hash_bytes = cn_cbor_mapget_int(cwt, -4670545);
566*60b67249SAndroid Build Coastguard Worker cn_cbor* code_desc_bytes = cn_cbor_mapget_int(cwt, -4670546);
567*60b67249SAndroid Build Coastguard Worker cn_cbor* conf_hash_bytes = cn_cbor_mapget_int(cwt, -4670547);
568*60b67249SAndroid Build Coastguard Worker cn_cbor* conf_desc_bytes = cn_cbor_mapget_int(cwt, -4670548);
569*60b67249SAndroid Build Coastguard Worker cn_cbor* auth_hash_bytes = cn_cbor_mapget_int(cwt, -4670549);
570*60b67249SAndroid Build Coastguard Worker cn_cbor* auth_desc_bytes = cn_cbor_mapget_int(cwt, -4670550);
571*60b67249SAndroid Build Coastguard Worker cn_cbor* mode_bytes = cn_cbor_mapget_int(cwt, -4670551);
572*60b67249SAndroid Build Coastguard Worker if (!expect_cdi_certificate) {
573*60b67249SAndroid Build Coastguard Worker return (!code_hash_bytes && !code_desc_bytes && !conf_hash_bytes &&
574*60b67249SAndroid Build Coastguard Worker !conf_desc_bytes && !auth_hash_bytes && !auth_desc_bytes &&
575*60b67249SAndroid Build Coastguard Worker !mode_bytes);
576*60b67249SAndroid Build Coastguard Worker }
577*60b67249SAndroid Build Coastguard Worker if (!code_hash_bytes || !conf_desc_bytes || !auth_hash_bytes || !mode_bytes) {
578*60b67249SAndroid Build Coastguard Worker return false;
579*60b67249SAndroid Build Coastguard Worker }
580*60b67249SAndroid Build Coastguard Worker if (code_hash_bytes->length != 64) {
581*60b67249SAndroid Build Coastguard Worker return false;
582*60b67249SAndroid Build Coastguard Worker }
583*60b67249SAndroid Build Coastguard Worker if (conf_hash_bytes) {
584*60b67249SAndroid Build Coastguard Worker if (conf_hash_bytes->length != 64) {
585*60b67249SAndroid Build Coastguard Worker return false;
586*60b67249SAndroid Build Coastguard Worker }
587*60b67249SAndroid Build Coastguard Worker } else if (conf_desc_bytes->length != 64) {
588*60b67249SAndroid Build Coastguard Worker return false;
589*60b67249SAndroid Build Coastguard Worker }
590*60b67249SAndroid Build Coastguard Worker if (auth_hash_bytes->length != 64) {
591*60b67249SAndroid Build Coastguard Worker return false;
592*60b67249SAndroid Build Coastguard Worker }
593*60b67249SAndroid Build Coastguard Worker if (mode_bytes->length != 1) {
594*60b67249SAndroid Build Coastguard Worker return false;
595*60b67249SAndroid Build Coastguard Worker }
596*60b67249SAndroid Build Coastguard Worker return true;
597*60b67249SAndroid Build Coastguard Worker }
598*60b67249SAndroid Build Coastguard Worker
VerifyCoseSign1Signature(const uint8_t * certificate,size_t certificate_size,const uint8_t * external_aad,size_t external_aad_size,const cn_cbor * authority_public_key)599*60b67249SAndroid Build Coastguard Worker bool VerifyCoseSign1Signature(const uint8_t* certificate,
600*60b67249SAndroid Build Coastguard Worker size_t certificate_size,
601*60b67249SAndroid Build Coastguard Worker const uint8_t* external_aad,
602*60b67249SAndroid Build Coastguard Worker size_t external_aad_size,
603*60b67249SAndroid Build Coastguard Worker const cn_cbor* authority_public_key) {
604*60b67249SAndroid Build Coastguard Worker // Use the COSE-C library to decode and validate.
605*60b67249SAndroid Build Coastguard Worker cose_errback error;
606*60b67249SAndroid Build Coastguard Worker int struct_type = 0;
607*60b67249SAndroid Build Coastguard Worker HCOSE_SIGN1 sign1 = (HCOSE_SIGN1)COSE_Decode(
608*60b67249SAndroid Build Coastguard Worker certificate, certificate_size, &struct_type, COSE_sign1_object, &error);
609*60b67249SAndroid Build Coastguard Worker if (!sign1) {
610*60b67249SAndroid Build Coastguard Worker return false;
611*60b67249SAndroid Build Coastguard Worker }
612*60b67249SAndroid Build Coastguard Worker COSE_Sign1_SetExternal(sign1, external_aad, external_aad_size, &error);
613*60b67249SAndroid Build Coastguard Worker bool result = COSE_Sign1_validate(sign1, authority_public_key, &error);
614*60b67249SAndroid Build Coastguard Worker COSE_Sign1_Free(sign1);
615*60b67249SAndroid Build Coastguard Worker if (!result) {
616*60b67249SAndroid Build Coastguard Worker return false;
617*60b67249SAndroid Build Coastguard Worker }
618*60b67249SAndroid Build Coastguard Worker return true;
619*60b67249SAndroid Build Coastguard Worker }
620*60b67249SAndroid Build Coastguard Worker
VerifySingleCborCertificate(const uint8_t * certificate,size_t certificate_size,const cn_cbor * authority_public_key,const char authority_id_hex[40],bool expect_cdi_certificate,ScopedCbor * subject_public_key,char subject_id_hex[40])621*60b67249SAndroid Build Coastguard Worker bool VerifySingleCborCertificate(const uint8_t* certificate,
622*60b67249SAndroid Build Coastguard Worker size_t certificate_size,
623*60b67249SAndroid Build Coastguard Worker const cn_cbor* authority_public_key,
624*60b67249SAndroid Build Coastguard Worker const char authority_id_hex[40],
625*60b67249SAndroid Build Coastguard Worker bool expect_cdi_certificate,
626*60b67249SAndroid Build Coastguard Worker ScopedCbor* subject_public_key,
627*60b67249SAndroid Build Coastguard Worker char subject_id_hex[40]) {
628*60b67249SAndroid Build Coastguard Worker if (!VerifyCoseSign1Signature(certificate, certificate_size, /*aad=*/NULL,
629*60b67249SAndroid Build Coastguard Worker /*aad_size=*/0, authority_public_key)) {
630*60b67249SAndroid Build Coastguard Worker return false;
631*60b67249SAndroid Build Coastguard Worker }
632*60b67249SAndroid Build Coastguard Worker
633*60b67249SAndroid Build Coastguard Worker ScopedCbor cwt(ExtractCwtFromCborCertificate(certificate, certificate_size));
634*60b67249SAndroid Build Coastguard Worker if (!cwt) {
635*60b67249SAndroid Build Coastguard Worker return false;
636*60b67249SAndroid Build Coastguard Worker }
637*60b67249SAndroid Build Coastguard Worker char actual_authority_id[40];
638*60b67249SAndroid Build Coastguard Worker char tmp_subject_id_hex[40];
639*60b67249SAndroid Build Coastguard Worker if (!ExtractIdsFromCwt(cwt.get(), actual_authority_id, tmp_subject_id_hex)) {
640*60b67249SAndroid Build Coastguard Worker return false;
641*60b67249SAndroid Build Coastguard Worker }
642*60b67249SAndroid Build Coastguard Worker if (0 != memcmp(authority_id_hex, actual_authority_id, 40)) {
643*60b67249SAndroid Build Coastguard Worker return false;
644*60b67249SAndroid Build Coastguard Worker }
645*60b67249SAndroid Build Coastguard Worker memcpy(subject_id_hex, tmp_subject_id_hex, 40);
646*60b67249SAndroid Build Coastguard Worker *subject_public_key = ExtractPublicKeyFromCwt(cwt.get());
647*60b67249SAndroid Build Coastguard Worker if (!subject_public_key) {
648*60b67249SAndroid Build Coastguard Worker return false;
649*60b67249SAndroid Build Coastguard Worker }
650*60b67249SAndroid Build Coastguard Worker uint64_t key_usage = 0;
651*60b67249SAndroid Build Coastguard Worker const uint64_t kKeyUsageCertSign = 1 << 5; // Bit 5.
652*60b67249SAndroid Build Coastguard Worker if (!ExtractKeyUsageFromCwt(cwt.get(), &key_usage)) {
653*60b67249SAndroid Build Coastguard Worker return false;
654*60b67249SAndroid Build Coastguard Worker }
655*60b67249SAndroid Build Coastguard Worker if (key_usage != kKeyUsageCertSign) {
656*60b67249SAndroid Build Coastguard Worker return false;
657*60b67249SAndroid Build Coastguard Worker }
658*60b67249SAndroid Build Coastguard Worker if (!ValidateCborCertificateCdiFields(cwt.get(), expect_cdi_certificate)) {
659*60b67249SAndroid Build Coastguard Worker return false;
660*60b67249SAndroid Build Coastguard Worker }
661*60b67249SAndroid Build Coastguard Worker return true;
662*60b67249SAndroid Build Coastguard Worker }
663*60b67249SAndroid Build Coastguard Worker
VerifyCborCertificateChain(const uint8_t * root_certificate,size_t root_certificate_size,const dice::test::DiceStateForTest states[],size_t num_dice_states,bool is_partial_chain)664*60b67249SAndroid Build Coastguard Worker bool VerifyCborCertificateChain(const uint8_t* root_certificate,
665*60b67249SAndroid Build Coastguard Worker size_t root_certificate_size,
666*60b67249SAndroid Build Coastguard Worker const dice::test::DiceStateForTest states[],
667*60b67249SAndroid Build Coastguard Worker size_t num_dice_states, bool is_partial_chain) {
668*60b67249SAndroid Build Coastguard Worker ScopedCbor root_cwt =
669*60b67249SAndroid Build Coastguard Worker ExtractCwtFromCborCertificate(root_certificate, root_certificate_size);
670*60b67249SAndroid Build Coastguard Worker if (!root_cwt) {
671*60b67249SAndroid Build Coastguard Worker return false;
672*60b67249SAndroid Build Coastguard Worker }
673*60b67249SAndroid Build Coastguard Worker ScopedCbor authority_public_key = ExtractPublicKeyFromCwt(root_cwt.get());
674*60b67249SAndroid Build Coastguard Worker if (!authority_public_key) {
675*60b67249SAndroid Build Coastguard Worker return false;
676*60b67249SAndroid Build Coastguard Worker }
677*60b67249SAndroid Build Coastguard Worker char expected_authority_id_hex[40];
678*60b67249SAndroid Build Coastguard Worker char not_used[40];
679*60b67249SAndroid Build Coastguard Worker if (!ExtractIdsFromCwt(root_cwt.get(), not_used, expected_authority_id_hex)) {
680*60b67249SAndroid Build Coastguard Worker return false;
681*60b67249SAndroid Build Coastguard Worker }
682*60b67249SAndroid Build Coastguard Worker if (!is_partial_chain) {
683*60b67249SAndroid Build Coastguard Worker // We can't verify the root certificate in a partial chain, we can only
684*60b67249SAndroid Build Coastguard Worker // check that its public key certifies the other certificates. But with a
685*60b67249SAndroid Build Coastguard Worker // full chain, we can expect the root to be self-signed.
686*60b67249SAndroid Build Coastguard Worker if (!VerifySingleCborCertificate(
687*60b67249SAndroid Build Coastguard Worker root_certificate, root_certificate_size, authority_public_key.get(),
688*60b67249SAndroid Build Coastguard Worker expected_authority_id_hex, /*expect_cdi_certificate=*/false,
689*60b67249SAndroid Build Coastguard Worker &authority_public_key, expected_authority_id_hex)) {
690*60b67249SAndroid Build Coastguard Worker return false;
691*60b67249SAndroid Build Coastguard Worker }
692*60b67249SAndroid Build Coastguard Worker }
693*60b67249SAndroid Build Coastguard Worker for (size_t i = 0; i < num_dice_states; ++i) {
694*60b67249SAndroid Build Coastguard Worker if (!VerifySingleCborCertificate(
695*60b67249SAndroid Build Coastguard Worker states[i].certificate, states[i].certificate_size,
696*60b67249SAndroid Build Coastguard Worker authority_public_key.get(), expected_authority_id_hex,
697*60b67249SAndroid Build Coastguard Worker /*expect_cdi_certificate=*/true, &authority_public_key,
698*60b67249SAndroid Build Coastguard Worker expected_authority_id_hex)) {
699*60b67249SAndroid Build Coastguard Worker return false;
700*60b67249SAndroid Build Coastguard Worker }
701*60b67249SAndroid Build Coastguard Worker }
702*60b67249SAndroid Build Coastguard Worker return true;
703*60b67249SAndroid Build Coastguard Worker }
704*60b67249SAndroid Build Coastguard Worker
705*60b67249SAndroid Build Coastguard Worker } // namespace
706*60b67249SAndroid Build Coastguard Worker
707*60b67249SAndroid Build Coastguard Worker namespace dice {
708*60b67249SAndroid Build Coastguard Worker namespace test {
709*60b67249SAndroid Build Coastguard Worker
DumpState(CertificateType cert_type,KeyType key_type,const char * suffix,const DiceStateForTest & state)710*60b67249SAndroid Build Coastguard Worker void DumpState(CertificateType cert_type, KeyType key_type, const char* suffix,
711*60b67249SAndroid Build Coastguard Worker const DiceStateForTest& state) {
712*60b67249SAndroid Build Coastguard Worker char filename[100];
713*60b67249SAndroid Build Coastguard Worker pw::string::Format(filename, "_attest_cdi_%s.bin", suffix);
714*60b67249SAndroid Build Coastguard Worker DumpToFile(filename, state.cdi_attest, DICE_CDI_SIZE);
715*60b67249SAndroid Build Coastguard Worker pw::string::Format(filename, "_seal_cdi_%s.bin", suffix);
716*60b67249SAndroid Build Coastguard Worker DumpToFile(filename, state.cdi_seal, DICE_CDI_SIZE);
717*60b67249SAndroid Build Coastguard Worker pw::string::Format(filename, "_%s_%s_cert_%s.cert", GetCertTypeStr(cert_type),
718*60b67249SAndroid Build Coastguard Worker GetKeyTypeStr(key_type), suffix);
719*60b67249SAndroid Build Coastguard Worker DumpToFile(filename, state.certificate, state.certificate_size);
720*60b67249SAndroid Build Coastguard Worker }
721*60b67249SAndroid Build Coastguard Worker
DeriveFakeInputValue(const char * seed,size_t length,uint8_t * output)722*60b67249SAndroid Build Coastguard Worker void DeriveFakeInputValue(const char* seed, size_t length, uint8_t* output) {
723*60b67249SAndroid Build Coastguard Worker union {
724*60b67249SAndroid Build Coastguard Worker uint8_t buffer[64];
725*60b67249SAndroid Build Coastguard Worker uint64_t counter;
726*60b67249SAndroid Build Coastguard Worker } context;
727*60b67249SAndroid Build Coastguard Worker SHA512(reinterpret_cast<const uint8_t*>(seed), strlen(seed), context.buffer);
728*60b67249SAndroid Build Coastguard Worker size_t output_pos = 0;
729*60b67249SAndroid Build Coastguard Worker while (output_pos < length) {
730*60b67249SAndroid Build Coastguard Worker uint8_t tmp[64];
731*60b67249SAndroid Build Coastguard Worker SHA512(context.buffer, 64, tmp);
732*60b67249SAndroid Build Coastguard Worker context.counter++;
733*60b67249SAndroid Build Coastguard Worker size_t remaining = length - output_pos;
734*60b67249SAndroid Build Coastguard Worker size_t to_copy = remaining < 64 ? remaining : 64;
735*60b67249SAndroid Build Coastguard Worker memcpy(&output[output_pos], tmp, to_copy);
736*60b67249SAndroid Build Coastguard Worker output_pos += to_copy;
737*60b67249SAndroid Build Coastguard Worker }
738*60b67249SAndroid Build Coastguard Worker }
739*60b67249SAndroid Build Coastguard Worker
CreateFakeUdsCertificate(void * context,const uint8_t uds[32],CertificateType cert_type,KeyType key_type,uint8_t certificate[kTestCertSize],size_t * certificate_size)740*60b67249SAndroid Build Coastguard Worker void CreateFakeUdsCertificate(void* context, const uint8_t uds[32],
741*60b67249SAndroid Build Coastguard Worker CertificateType cert_type, KeyType key_type,
742*60b67249SAndroid Build Coastguard Worker uint8_t certificate[kTestCertSize],
743*60b67249SAndroid Build Coastguard Worker size_t* certificate_size) {
744*60b67249SAndroid Build Coastguard Worker uint8_t raw_key[DICE_PRIVATE_KEY_SEED_SIZE];
745*60b67249SAndroid Build Coastguard Worker DiceDeriveCdiPrivateKeySeed(context, uds, raw_key);
746*60b67249SAndroid Build Coastguard Worker
747*60b67249SAndroid Build Coastguard Worker uint8_t raw_public_key[MAX_PUBLIC_KEY_SIZE];
748*60b67249SAndroid Build Coastguard Worker size_t raw_public_key_size = 0;
749*60b67249SAndroid Build Coastguard Worker bssl::UniquePtr<EVP_PKEY> key(
750*60b67249SAndroid Build Coastguard Worker KeyFromRawKey(raw_key, key_type, raw_public_key, &raw_public_key_size));
751*60b67249SAndroid Build Coastguard Worker
752*60b67249SAndroid Build Coastguard Worker uint8_t id[DICE_ID_SIZE];
753*60b67249SAndroid Build Coastguard Worker DiceDeriveCdiCertificateId(context, raw_public_key, raw_public_key_size, id);
754*60b67249SAndroid Build Coastguard Worker
755*60b67249SAndroid Build Coastguard Worker if (cert_type == CertificateType_X509) {
756*60b67249SAndroid Build Coastguard Worker CreateX509UdsCertificate(key.get(), id, certificate, certificate_size);
757*60b67249SAndroid Build Coastguard Worker } else {
758*60b67249SAndroid Build Coastguard Worker CreateCborUdsCertificate(raw_key, key_type, id, certificate,
759*60b67249SAndroid Build Coastguard Worker certificate_size);
760*60b67249SAndroid Build Coastguard Worker }
761*60b67249SAndroid Build Coastguard Worker
762*60b67249SAndroid Build Coastguard Worker char filename[100];
763*60b67249SAndroid Build Coastguard Worker pw::string::Format(filename, "_%s_%s_uds_cert.cert",
764*60b67249SAndroid Build Coastguard Worker GetCertTypeStr(cert_type), GetKeyTypeStr(key_type));
765*60b67249SAndroid Build Coastguard Worker DumpToFile(filename, certificate, *certificate_size);
766*60b67249SAndroid Build Coastguard Worker }
767*60b67249SAndroid Build Coastguard Worker
VerifyCoseSign1(const uint8_t * certificate,size_t certificate_size,const uint8_t * external_aad,size_t external_aad_size,const uint8_t * encoded_public_key,size_t encoded_public_key_size,const uint8_t * expected_cwt,size_t expected_cwt_size)768*60b67249SAndroid Build Coastguard Worker [[maybe_unused]] bool VerifyCoseSign1(
769*60b67249SAndroid Build Coastguard Worker const uint8_t* certificate, size_t certificate_size,
770*60b67249SAndroid Build Coastguard Worker const uint8_t* external_aad, size_t external_aad_size,
771*60b67249SAndroid Build Coastguard Worker const uint8_t* encoded_public_key, size_t encoded_public_key_size,
772*60b67249SAndroid Build Coastguard Worker const uint8_t* expected_cwt, size_t expected_cwt_size) {
773*60b67249SAndroid Build Coastguard Worker cn_cbor_errback error;
774*60b67249SAndroid Build Coastguard Worker ScopedCbor public_key(
775*60b67249SAndroid Build Coastguard Worker cn_cbor_decode(encoded_public_key, encoded_public_key_size, &error));
776*60b67249SAndroid Build Coastguard Worker if (!public_key) {
777*60b67249SAndroid Build Coastguard Worker return false;
778*60b67249SAndroid Build Coastguard Worker }
779*60b67249SAndroid Build Coastguard Worker
780*60b67249SAndroid Build Coastguard Worker if (!VerifyCoseSign1Signature(certificate, certificate_size, external_aad,
781*60b67249SAndroid Build Coastguard Worker external_aad_size, public_key.get())) {
782*60b67249SAndroid Build Coastguard Worker return false;
783*60b67249SAndroid Build Coastguard Worker }
784*60b67249SAndroid Build Coastguard Worker
785*60b67249SAndroid Build Coastguard Worker ScopedCbor sign1(cn_cbor_decode(certificate, certificate_size, &error));
786*60b67249SAndroid Build Coastguard Worker if (!sign1 || sign1->type != CN_CBOR_ARRAY || sign1->length != 4) {
787*60b67249SAndroid Build Coastguard Worker return false;
788*60b67249SAndroid Build Coastguard Worker }
789*60b67249SAndroid Build Coastguard Worker cn_cbor* payload = cn_cbor_index(sign1.get(), 2);
790*60b67249SAndroid Build Coastguard Worker if (!payload || payload->type != CN_CBOR_BYTES) {
791*60b67249SAndroid Build Coastguard Worker return false;
792*60b67249SAndroid Build Coastguard Worker }
793*60b67249SAndroid Build Coastguard Worker
794*60b67249SAndroid Build Coastguard Worker if (payload->length != expected_cwt_size) {
795*60b67249SAndroid Build Coastguard Worker return false;
796*60b67249SAndroid Build Coastguard Worker }
797*60b67249SAndroid Build Coastguard Worker
798*60b67249SAndroid Build Coastguard Worker if (memcmp(payload->v.bytes, expected_cwt, expected_cwt_size) != 0) {
799*60b67249SAndroid Build Coastguard Worker return false;
800*60b67249SAndroid Build Coastguard Worker }
801*60b67249SAndroid Build Coastguard Worker return true;
802*60b67249SAndroid Build Coastguard Worker }
803*60b67249SAndroid Build Coastguard Worker
VerifyCertificateChain(CertificateType cert_type,const uint8_t * root_certificate,size_t root_certificate_size,const DiceStateForTest states[],size_t num_dice_states,bool is_partial_chain)804*60b67249SAndroid Build Coastguard Worker bool VerifyCertificateChain(CertificateType cert_type,
805*60b67249SAndroid Build Coastguard Worker const uint8_t* root_certificate,
806*60b67249SAndroid Build Coastguard Worker size_t root_certificate_size,
807*60b67249SAndroid Build Coastguard Worker const DiceStateForTest states[],
808*60b67249SAndroid Build Coastguard Worker size_t num_dice_states, bool is_partial_chain) {
809*60b67249SAndroid Build Coastguard Worker switch (cert_type) {
810*60b67249SAndroid Build Coastguard Worker case CertificateType_Cbor:
811*60b67249SAndroid Build Coastguard Worker return VerifyCborCertificateChain(root_certificate, root_certificate_size,
812*60b67249SAndroid Build Coastguard Worker states, num_dice_states,
813*60b67249SAndroid Build Coastguard Worker is_partial_chain);
814*60b67249SAndroid Build Coastguard Worker case CertificateType_X509:
815*60b67249SAndroid Build Coastguard Worker return VerifyX509CertificateChain(root_certificate, root_certificate_size,
816*60b67249SAndroid Build Coastguard Worker states, num_dice_states,
817*60b67249SAndroid Build Coastguard Worker is_partial_chain);
818*60b67249SAndroid Build Coastguard Worker }
819*60b67249SAndroid Build Coastguard Worker return false;
820*60b67249SAndroid Build Coastguard Worker }
821*60b67249SAndroid Build Coastguard Worker } // namespace test
822*60b67249SAndroid Build Coastguard Worker } // namespace dice
823