xref: /aosp_15_r20/external/open-dice/src/test_utils.cc (revision 60b67249c2e226f42f35cc6cfe66c6048e0bae6b)
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