1 /*
2  * Copyright (c) 2019, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <iomanip>
18 #include <iostream>
19 #include <sstream>
20 
21 #include <gmock/gmock.h>
22 #include <gtest/gtest.h>
23 
24 #include <android/hardware/identity/support/IdentityCredentialSupport.h>
25 
26 #include <cppbor.h>
27 #include <cppbor_parse.h>
28 
29 using std::optional;
30 using std::string;
31 using std::vector;
32 
33 namespace android {
34 namespace hardware {
35 namespace identity {
36 
TEST(IdentityCredentialSupport,encodeHex)37 TEST(IdentityCredentialSupport, encodeHex) {
38     EXPECT_EQ("", support::encodeHex(vector<uint8_t>({})));
39     EXPECT_EQ("01", support::encodeHex(vector<uint8_t>({1})));
40     EXPECT_EQ("000102030405060708090a0b0c0d0e0f10",
41               support::encodeHex(
42                       vector<uint8_t>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16})));
43     EXPECT_EQ("0102ffe060", support::encodeHex(vector<uint8_t>({1, 2, 255, 224, 96})));
44 }
45 
TEST(IdentityCredentialSupport,decodeHex)46 TEST(IdentityCredentialSupport, decodeHex) {
47     EXPECT_EQ(vector<uint8_t>({}), support::decodeHex(""));
48     EXPECT_EQ(vector<uint8_t>({1}), support::decodeHex("01"));
49 
50     EXPECT_EQ(vector<uint8_t>({0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}),
51               support::decodeHex("000102030405060708090a0b0c0d0e0f10"));
52 
53     EXPECT_FALSE(support::decodeHex("0g"));
54     EXPECT_FALSE(support::decodeHex("0"));
55     EXPECT_FALSE(support::decodeHex("012"));
56 }
57 
TEST(IdentityCredentialSupport,Signatures)58 TEST(IdentityCredentialSupport, Signatures) {
59     vector<uint8_t> data = {1, 2, 3};
60 
61     optional<vector<uint8_t>> keyPair = support::createEcKeyPair();
62     ASSERT_TRUE(keyPair);
63     optional<vector<uint8_t>> privKey = support::ecKeyPairGetPrivateKey(keyPair.value());
64     ASSERT_TRUE(privKey);
65     optional<vector<uint8_t>> pubKey = support::ecKeyPairGetPublicKey(keyPair.value());
66     ASSERT_TRUE(pubKey);
67 
68     optional<vector<uint8_t>> signature = support::signEcDsa(privKey.value(), data);
69     ASSERT_TRUE(
70             support::checkEcDsaSignature(support::sha256(data), signature.value(), pubKey.value()));
71 
72     // Manipulate the signature, check that verification fails.
73     vector<uint8_t> modifiedSignature = signature.value();
74     modifiedSignature[0] ^= 0xff;
75     ASSERT_FALSE(
76             support::checkEcDsaSignature(support::sha256(data), modifiedSignature, pubKey.value()));
77 
78     // Manipulate the data being checked, check that verification fails.
79     vector<uint8_t> modifiedDigest = support::sha256(data);
80     modifiedDigest[0] ^= 0xff;
81     ASSERT_FALSE(support::checkEcDsaSignature(modifiedDigest, signature.value(), pubKey.value()));
82 }
83 
replaceLine(const string & str,ssize_t lineNumber,const string & replacement)84 string replaceLine(const string& str, ssize_t lineNumber, const string& replacement) {
85     vector<string> lines;
86     std::istringstream f(str);
87     string s;
88     while (std::getline(f, s, '\n')) {
89         lines.push_back(s);
90     }
91 
92     size_t numLines = lines.size();
93     if (lineNumber < 0) {
94         lineNumber = numLines - (-lineNumber);
95     }
96 
97     string ret;
98     size_t n = 0;
99     for (const string& line : lines) {
100         if (n == lineNumber) {
101             ret += replacement + "\n";
102         } else {
103             ret += line + "\n";
104         }
105         n++;
106     }
107     return ret;
108 }
109 
TEST(IdentityCredentialSupport,CoseSignatures)110 TEST(IdentityCredentialSupport, CoseSignatures) {
111     optional<vector<uint8_t>> keyPair = support::createEcKeyPair();
112     ASSERT_TRUE(keyPair);
113     optional<vector<uint8_t>> privKey = support::ecKeyPairGetPrivateKey(keyPair.value());
114     ASSERT_TRUE(privKey);
115     optional<vector<uint8_t>> pubKey = support::ecKeyPairGetPublicKey(keyPair.value());
116     ASSERT_TRUE(pubKey);
117 
118     vector<uint8_t> data = {1, 2, 3};
119     optional<vector<uint8_t>> coseSign1 = support::coseSignEcDsa(
120             privKey.value(), data, {} /* detachedContent */, {} /* x5chain */);
121     ASSERT_TRUE(support::coseCheckEcDsaSignature(coseSign1.value(), {} /* detachedContent */,
122                                                  pubKey.value()));
123 
124     optional<vector<uint8_t>> payload = support::coseSignGetPayload(coseSign1.value());
125     ASSERT_TRUE(payload);
126     ASSERT_EQ(data, payload.value());
127 
128     // Finally, check that |coseSign1| are the bytes of a valid COSE_Sign1 message
129     string out = cppbor::prettyPrint(coseSign1.value());
130     out = replaceLine(out, -2, "  [] // Signature Removed");
131     EXPECT_EQ(
132             "[\n"
133             "  {0xa1, 0x01, 0x26},\n"  // Bytes of {1:-7} 1 is 'alg' label and -7 is "ECDSA 256"
134             "  {},\n"
135             "  {0x01, 0x02, 0x03},\n"
136             "  [] // Signature Removed\n"
137             "]\n",
138             out);
139 }
140 
TEST(IdentityCredentialSupport,CoseSignaturesAdditionalData)141 TEST(IdentityCredentialSupport, CoseSignaturesAdditionalData) {
142     optional<vector<uint8_t>> keyPair = support::createEcKeyPair();
143     ASSERT_TRUE(keyPair);
144     optional<vector<uint8_t>> privKey = support::ecKeyPairGetPrivateKey(keyPair.value());
145     ASSERT_TRUE(privKey);
146     optional<vector<uint8_t>> pubKey = support::ecKeyPairGetPublicKey(keyPair.value());
147     ASSERT_TRUE(pubKey);
148 
149     vector<uint8_t> detachedContent = {1, 2, 3};
150     optional<vector<uint8_t>> coseSign1 = support::coseSignEcDsa(privKey.value(), {} /* data */,
151                                                                  detachedContent, {} /* x5chain */);
152     ASSERT_TRUE(
153             support::coseCheckEcDsaSignature(coseSign1.value(), detachedContent, pubKey.value()));
154 
155     optional<vector<uint8_t>> payload = support::coseSignGetPayload(coseSign1.value());
156     ASSERT_TRUE(payload);
157     ASSERT_EQ(0, payload.value().size());
158 
159     // Finally, check that |coseSign1| are the bytes of a valid COSE_Sign1 message
160     string out = cppbor::prettyPrint(coseSign1.value());
161     out = replaceLine(out, -2, "  [] // Signature Removed");
162     EXPECT_EQ(
163             "[\n"
164             "  {0xa1, 0x01, 0x26},\n"  // Bytes of {1:-7} 1 is 'alg' label and -7 is "ECDSA 256"
165             "  {},\n"
166             "  null,\n"
167             "  [] // Signature Removed\n"
168             "]\n",
169             out);
170 }
171 
generateCertChain(size_t numCerts)172 vector<uint8_t> generateCertChain(size_t numCerts) {
173     vector<vector<uint8_t>> certs;
174 
175     for (size_t n = 0; n < numCerts; n++) {
176         optional<vector<uint8_t>> keyPair = support::createEcKeyPair();
177         optional<vector<uint8_t>> privKey = support::ecKeyPairGetPrivateKey(keyPair.value());
178         optional<vector<uint8_t>> pubKey = support::ecKeyPairGetPublicKey(keyPair.value());
179 
180         optional<vector<uint8_t>> cert = support::ecPublicKeyGenerateCertificate(
181                 pubKey.value(), privKey.value(), "0001", "someIssuer", "someSubject", 0, 0, {});
182         certs.push_back(cert.value());
183     }
184     return support::certificateChainJoin(certs);
185 }
186 
TEST(IdentityCredentialSupport,CoseSignaturesX5ChainWithSingleCert)187 TEST(IdentityCredentialSupport, CoseSignaturesX5ChainWithSingleCert) {
188     optional<vector<uint8_t>> keyPair = support::createEcKeyPair();
189     ASSERT_TRUE(keyPair);
190     optional<vector<uint8_t>> privKey = support::ecKeyPairGetPrivateKey(keyPair.value());
191     ASSERT_TRUE(privKey);
192     optional<vector<uint8_t>> pubKey = support::ecKeyPairGetPublicKey(keyPair.value());
193     ASSERT_TRUE(pubKey);
194 
195     vector<uint8_t> certChain = generateCertChain(1);
196     optional<vector<vector<uint8_t>>> splitCerts = support::certificateChainSplit(certChain);
197     ASSERT_EQ(1, splitCerts.value().size());
198 
199     vector<uint8_t> detachedContent = {1, 2, 3};
200     optional<vector<uint8_t>> coseSign1 =
201             support::coseSignEcDsa(privKey.value(), {} /* data */, detachedContent, certChain);
202     ASSERT_TRUE(
203             support::coseCheckEcDsaSignature(coseSign1.value(), detachedContent, pubKey.value()));
204 
205     optional<vector<uint8_t>> payload = support::coseSignGetPayload(coseSign1.value());
206     ASSERT_TRUE(payload);
207     ASSERT_EQ(0, payload.value().size());
208 
209     optional<vector<uint8_t>> certsRecovered = support::coseSignGetX5Chain(coseSign1.value());
210     EXPECT_EQ(certsRecovered.value(), certChain);
211 }
212 
TEST(IdentityCredentialSupport,CoseSignaturesX5ChainWithMultipleCerts)213 TEST(IdentityCredentialSupport, CoseSignaturesX5ChainWithMultipleCerts) {
214     optional<vector<uint8_t>> keyPair = support::createEcKeyPair();
215     ASSERT_TRUE(keyPair);
216     optional<vector<uint8_t>> privKey = support::ecKeyPairGetPrivateKey(keyPair.value());
217     ASSERT_TRUE(privKey);
218     optional<vector<uint8_t>> pubKey = support::ecKeyPairGetPublicKey(keyPair.value());
219     ASSERT_TRUE(pubKey);
220 
221     vector<uint8_t> certChain = generateCertChain(5);
222     optional<vector<vector<uint8_t>>> splitCerts = support::certificateChainSplit(certChain);
223     ASSERT_EQ(5, splitCerts.value().size());
224 
225     vector<uint8_t> detachedContent = {1, 2, 3};
226     optional<vector<uint8_t>> coseSign1 =
227             support::coseSignEcDsa(privKey.value(), {} /* data */, detachedContent, certChain);
228     ASSERT_TRUE(
229             support::coseCheckEcDsaSignature(coseSign1.value(), detachedContent, pubKey.value()));
230 
231     optional<vector<uint8_t>> payload = support::coseSignGetPayload(coseSign1.value());
232     ASSERT_TRUE(payload);
233     ASSERT_EQ(0, payload.value().size());
234 
235     optional<vector<uint8_t>> certsRecovered = support::coseSignGetX5Chain(coseSign1.value());
236     EXPECT_EQ(certsRecovered.value(), certChain);
237 }
238 
TEST(IdentityCredentialSupport,CertificateChain)239 TEST(IdentityCredentialSupport, CertificateChain) {
240     optional<vector<uint8_t>> keyPair = support::createEcKeyPair();
241     ASSERT_TRUE(keyPair);
242     optional<vector<uint8_t>> privKey = support::ecKeyPairGetPrivateKey(keyPair.value());
243     ASSERT_TRUE(privKey);
244     optional<vector<uint8_t>> pubKey = support::ecKeyPairGetPublicKey(keyPair.value());
245     ASSERT_TRUE(pubKey);
246 
247     optional<vector<uint8_t>> cert = support::ecPublicKeyGenerateCertificate(
248             pubKey.value(), privKey.value(), "0001", "someIssuer", "someSubject", 0, 0, {});
249 
250     optional<vector<uint8_t>> extractedPubKey =
251             support::certificateChainGetTopMostKey(cert.value());
252     ASSERT_TRUE(extractedPubKey);
253     ASSERT_EQ(pubKey.value(), extractedPubKey.value());
254 
255     // We expect to the chain returned by ecPublicKeyGenerateCertificate() to only have a
256     // single element
257     optional<vector<vector<uint8_t>>> splitCerts = support::certificateChainSplit(cert.value());
258     ASSERT_EQ(1, splitCerts.value().size());
259     ASSERT_EQ(splitCerts.value()[0], cert.value());
260 
261     optional<vector<uint8_t>> otherKeyPair = support::createEcKeyPair();
262     ASSERT_TRUE(otherKeyPair);
263     optional<vector<uint8_t>> otherPrivKey = support::ecKeyPairGetPrivateKey(keyPair.value());
264     ASSERT_TRUE(otherPrivKey);
265     optional<vector<uint8_t>> otherPubKey = support::ecKeyPairGetPublicKey(keyPair.value());
266     ASSERT_TRUE(otherPubKey);
267     optional<vector<uint8_t>> otherCert = support::ecPublicKeyGenerateCertificate(
268             otherPubKey.value(), privKey.value(), "0001", "someIssuer", "someSubject", 0, 0, {});
269 
270     // Now both cert and otherCert are two distinct certificates. Let's make a
271     // chain and check that certificateChainSplit() works as expected.
272     ASSERT_NE(cert.value(), otherCert.value());
273     const vector<vector<uint8_t>> certs2 = {cert.value(), otherCert.value()};
274     vector<uint8_t> certs2combined = support::certificateChainJoin(certs2);
275     ASSERT_EQ(certs2combined.size(), cert.value().size() + otherCert.value().size());
276     optional<vector<vector<uint8_t>>> splitCerts2 = support::certificateChainSplit(certs2combined);
277     ASSERT_EQ(certs2, splitCerts2.value());
278 }
279 
strToVec(const string & str)280 vector<uint8_t> strToVec(const string& str) {
281     vector<uint8_t> ret;
282     size_t size = str.size();
283     ret.resize(size);
284     memcpy(ret.data(), str.data(), size);
285     return ret;
286 }
287 
288 // Test vector from https://en.wikipedia.org/wiki/HMAC
TEST(IdentityCredentialSupport,hmacSha256)289 TEST(IdentityCredentialSupport, hmacSha256) {
290     vector<uint8_t> key = strToVec("key");
291     vector<uint8_t> data = strToVec("The quick brown fox jumps over the lazy dog");
292 
293     vector<uint8_t> expected =
294             support::decodeHex("f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8")
295                     .value();
296 
297     optional<vector<uint8_t>> hmac = support::hmacSha256(key, data);
298     ASSERT_TRUE(hmac);
299     ASSERT_EQ(expected, hmac.value());
300 }
301 
302 // See also CoseMac0 test in UtilUnitTest.java inside cts/tests/tests/identity/
TEST(IdentityCredentialSupport,CoseMac0)303 TEST(IdentityCredentialSupport, CoseMac0) {
304     vector<uint8_t> key;
305     key.resize(32);
306     vector<uint8_t> data = {0x10, 0x11, 0x12, 0x13};
307     vector<uint8_t> detachedContent = {};
308 
309     optional<vector<uint8_t>> mac = support::coseMac0(key, data, detachedContent);
310     ASSERT_TRUE(mac);
311 
312     EXPECT_EQ(
313             "[\n"
314             "  {0xa1, 0x01, 0x05},\n"
315             "  {},\n"
316             "  {0x10, 0x11, 0x12, 0x13},\n"
317             "  {0x6c, 0xec, 0xb5, 0x6a, 0xc9, 0x5c, 0xae, 0x3b, 0x41, 0x13, 0xde, 0xa4, 0xd8, "
318             "0x86, 0x5c, 0x28, 0x2c, 0xd5, 0xa5, 0x13, 0xff, 0x3b, 0xd1, 0xde, 0x70, 0x5e, 0xbb, "
319             "0xe2, 0x2d, 0x42, 0xbe, 0x53},\n"
320             "]",
321             cppbor::prettyPrint(mac.value()));
322 }
323 
TEST(IdentityCredentialSupport,CoseMac0DetachedContent)324 TEST(IdentityCredentialSupport, CoseMac0DetachedContent) {
325     vector<uint8_t> key;
326     key.resize(32);
327     vector<uint8_t> data = {};
328     vector<uint8_t> detachedContent = {0x10, 0x11, 0x12, 0x13};
329 
330     optional<vector<uint8_t>> mac = support::coseMac0(key, data, detachedContent);
331     ASSERT_TRUE(mac);
332 
333     // Same HMAC as in CoseMac0 test, only difference is that payload is null.
334     EXPECT_EQ(
335             "[\n"
336             "  {0xa1, 0x01, 0x05},\n"
337             "  {},\n"
338             "  null,\n"
339             "  {0x6c, 0xec, 0xb5, 0x6a, 0xc9, 0x5c, 0xae, 0x3b, 0x41, 0x13, 0xde, 0xa4, 0xd8, "
340             "0x86, 0x5c, 0x28, 0x2c, 0xd5, 0xa5, 0x13, 0xff, 0x3b, 0xd1, 0xde, 0x70, 0x5e, 0xbb, "
341             "0xe2, 0x2d, 0x42, 0xbe, 0x53},\n"
342             "]",
343             cppbor::prettyPrint(mac.value()));
344 }
345 
346 // Generates a private key in DER format for a small value of 'd'.
347 //
348 // Used for test vectors.
349 //
p256PrivateKeyFromD(uint8_t d)350 vector<uint8_t> p256PrivateKeyFromD(uint8_t d) {
351     vector<uint8_t> privateUncompressed;
352     privateUncompressed.resize(32);
353     privateUncompressed[31] = d;
354     optional<vector<uint8_t>> privateKey = support::ecPrivateKeyToKeyPair(privateUncompressed);
355     return privateKey.value();
356 }
357 
p256PrivateKeyGetXandY(const vector<uint8_t> privateKey)358 std::pair<vector<uint8_t>, vector<uint8_t>> p256PrivateKeyGetXandY(
359         const vector<uint8_t> privateKey) {
360     optional<vector<uint8_t>> publicUncompressed = support::ecKeyPairGetPublicKey(privateKey);
361     vector<uint8_t> x = vector<uint8_t>(publicUncompressed.value().begin() + 1,
362                                         publicUncompressed.value().begin() + 33);
363     vector<uint8_t> y = vector<uint8_t>(publicUncompressed.value().begin() + 33,
364                                         publicUncompressed.value().begin() + 65);
365     return std::make_pair(x, y);
366 }
367 
findValueForTstr(const cppbor::Map * map,const string & keyValue)368 const cppbor::Item* findValueForTstr(const cppbor::Map* map, const string& keyValue) {
369     // TODO: Need cast until libcppbor's Map::get() is marked as const
370     const auto& item = map->get(keyValue);
371     if (!item) {
372         return nullptr;
373     }
374     return item.get();
375 }
376 
findArrayValueForTstr(const cppbor::Map * map,const string & keyValue)377 const cppbor::Array* findArrayValueForTstr(const cppbor::Map* map, const string& keyValue) {
378     const cppbor::Item* item = findValueForTstr(map, keyValue);
379     if (item == nullptr) {
380         return nullptr;
381     }
382     return item->asArray();
383 }
384 
findMapValueForTstr(const cppbor::Map * map,const string & keyValue)385 const cppbor::Map* findMapValueForTstr(const cppbor::Map* map, const string& keyValue) {
386     const cppbor::Item* item = findValueForTstr(map, keyValue);
387     if (item == nullptr) {
388         return nullptr;
389     }
390     return item->asMap();
391 }
392 
findSemanticValueForTstr(const cppbor::Map * map,const string & keyValue)393 const cppbor::SemanticTag* findSemanticValueForTstr(const cppbor::Map* map,
394                                                     const string& keyValue) {
395     const cppbor::Item* item = findValueForTstr(map, keyValue);
396     if (item == nullptr) {
397         return nullptr;
398     }
399     return item->asSemanticTag();
400 }
401 
findStringValueForTstr(const cppbor::Map * map,const string & keyValue)402 const std::string findStringValueForTstr(const cppbor::Map* map, const string& keyValue) {
403     const cppbor::Item* item = findValueForTstr(map, keyValue);
404     if (item == nullptr) {
405         return nullptr;
406     }
407     const cppbor::Tstr* tstr = item->asTstr();
408     if (tstr == nullptr) {
409         return "";
410     }
411     return tstr->value();
412 }
413 
TEST(IdentityCredentialSupport,testVectors_18013_5)414 TEST(IdentityCredentialSupport, testVectors_18013_5) {
415     // This is a test against known vectors for ISO 18013-5.
416     //
417     // The objective of this test is to verify that support::calcEMacKey() and
418     // support::calcMac() agree with the given test vectors.
419     //
420 
421     // We're given static device key:
422     //
423     //     x: 28412803729898893058558238221310261427084375743576167377786533380249859400145
424     //     y: 65403602826180996396520286939226973026599920614829401631985882360676038096704
425     //     d: 11
426     //
427     vector<uint8_t> deviceKey = p256PrivateKeyFromD(11);
428     auto [deviceKeyX, deviceKeyY] = p256PrivateKeyGetXandY(deviceKey);
429     EXPECT_EQ(support::encodeHex(deviceKeyX),
430               "3ed113b7883b4c590638379db0c21cda16742ed0255048bf433391d374bc21d1");
431     EXPECT_EQ(support::encodeHex(deviceKeyY),
432               "9099209accc4c8a224c843afa4f4c68a090d04da5e9889dae2f8eefce82a3740");
433 
434     // We're given Ephemeral reader key:
435     //
436     //   x: 59535862115950685744176693329402396749019581632805653266809849538337418304154
437     //   y: 53776829996815113213100700404832701936765102413212294632483274374518863708344
438     //   d: 20
439     //
440     vector<uint8_t> ephemeralReaderKey = p256PrivateKeyFromD(20);
441     auto [ephemeralReaderKeyX, ephemeralReaderKeyY] = p256PrivateKeyGetXandY(ephemeralReaderKey);
442     EXPECT_EQ(support::encodeHex(ephemeralReaderKeyX),
443               "83a01a9378395bab9bcd6a0ad03cc56d56e6b19250465a94a234dc4c6b28da9a");
444     EXPECT_EQ(support::encodeHex(ephemeralReaderKeyY),
445               "76e49b6de2f73234ae6a5eb9d612b75c9f2202bb6923f54ff8240aaa86f640b8");
446     vector<uint8_t> ephemeralReaderKeyPublic =
447             support::ecKeyPairGetPublicKey(ephemeralReaderKey).value();
448 
449     // We're given SessionEstablishment.
450     //
451     //   SessionEstablishment = {
452     //     "eReaderKey" : EReaderKeyBytes,
453     //     "data" : bstr ; Encrypted mdoc request
454     //   }
455     //
456     // Fish out EReaderKey from this.
457     //
458     // Note that the test vector below is incorrect insofar that it uses
459     // "eReaderKeyBytes" instead of just "eReaderKey". This will be corrected in
460     // the future.
461     //
462     optional<vector<uint8_t>> sessionEstablishmentEncoded = support::decodeHex(
463             "a26f655265616465724b65794279746573d818584ba40102200121582083a01a9378395bab9bcd6a0ad03c"
464             "c56d56e6b19250465a94a234dc4c6b28da9a22582076e49b6de2f73234ae6a5eb9d612b75c9f2202bb6923"
465             "f54ff8240aaa86f640b864646174615902d945b31040c57491acb6d46a71f6c1f67a0b837df1bda9089fd0"
466             "3d0b1fdac3eeb2874a4ef6f90c97d03397186ba00a91102faae7e992e15f761d5662c3c37e3c6c2cfd2ebc"
467             "0bf59dbb8795e377bd7dd353230a41ba2d82294b45871a39b42ca531f26b52f46e356fbaf5075c8fd5b8b0"
468             "8a0df4a1d2e1bdd2e5d69169c1efbb51e393e608d833d325bebfbccb2e15ec08f94b264582fa7b93f7cebc"
469             "aa69f4f0cac2744d4fe35b04df26b2ae69273eed33024949080c1c95a6ef046beede959e9494297dd770af"
470             "4ac6fdd56783aa012555c213dc05cf0f41d1c95119720fcfe1621027f80e2ddd56ea3c1fc596f7b2579333"
471             "5a887ec788092b4a69d23b6219e27d0249b50b3fdcb95b5227007689362e0416b3bae3dae7cb56b4394666"
472             "4e3a3f60dce8d0b678fcd754bebf87bd2b0278dd782d952488a46f2874e34c2dd97bb74084a62b850e9719"
473             "252cd1dca7dbf1858193f6cf093cb3735312bbe1138cf29d8f350e285923f8ef07065299926720b42264e8"
474             "fd5d4b133e72f47c4e999ea689c353f8b41e50a59838e1a0d09eca4a557f77a9c389a0591ad1639119ce86"
475             "edc3320130480ee5101effae6066e8c85aac9ead2ae83e49c1e508aab02f753decbb522ea2200d62fd5d26"
476             "094bd35100bffaa1cdc6af9f7e9cfe7b63da6b5671cd5ac2cf5da450c72addc64cde441f3b7f7fdaf930ad"
477             "1e13388e8a7308d8ca4607e59e082db431a232e7e12cb692baeb4b2127e110ff24cea322ffdbc2e4d9c4c6"
478             "bed27753137d07897c8613627a799a560cf1a2d1edb3de029442862940a5ed7785eea8b6ace93aa6af0792"
479             "fd82877f62d07b757d0179ecbb7347004ecc9c0690d41f75f188cb17ffd2cec2ad8c9675466bb33b737a2a"
480             "e7592b2dcb8132aced2e572266f3f5413a5f9d6d4339a1e4662622af2e7e157a4ea3bfd5c4247e2ec91d8c"
481             "5c3c17427d5edfae673d0e0f782a8d40fa805fd8bc82ae3cb21a65cdad863e02309f6b01d1753fa884b778"
482             "f6e019a2004d8964deeb11f1fd478fcb");
483     ASSERT_TRUE(sessionEstablishmentEncoded);
484     auto [sessionEstablishmentItem, _se, _se2] = cppbor::parse(sessionEstablishmentEncoded.value());
485     const cppbor::Map* sessionEstablishment = sessionEstablishmentItem->asMap();
486     ASSERT_NE(sessionEstablishment, nullptr);
487     const cppbor::SemanticTag* eReaderKeyBytes =
488             findSemanticValueForTstr(sessionEstablishment, "eReaderKeyBytes");
489     ASSERT_NE(eReaderKeyBytes, nullptr);
490     ASSERT_EQ(eReaderKeyBytes->semanticTag(), 24);
491     const cppbor::Bstr* eReaderKeyBstr = eReaderKeyBytes->asBstr();
492     ASSERT_NE(eReaderKeyBstr, nullptr);
493     vector<uint8_t> eReaderKeyEncoded = eReaderKeyBstr->value();
494     // TODO: verify this agrees with ephemeralReaderKeyX and ephemeralReaderKeyY
495 
496     // We're given DeviceEngagement.
497     //
498     vector<uint8_t> deviceEngagementEncoded =
499             support::decodeHex(
500                     "a20063312e30018201d818584ba401022001215820cef66d6b2a3a993e591214d1ea223fb545ca"
501                     "6c471c48306e4c36069404c5723f225820878662a229aaae906e123cdd9d3b4c10590ded29fe75"
502                     "1eeeca34bbaa44af0773")
503                     .value();
504 
505     // Now calculate SessionTranscriptBytes. It is defined as
506     //
507     //   SessionTranscript = [
508     //      DeviceEngagementBytes,
509     //      EReaderKeyBytes,
510     //      Handover
511     //   ]
512     //
513     //   SessionTranscriptBytes = #6.24(bstr .cbor SessionTranscript)
514     //
515     cppbor::Array sessionTranscript;
516     sessionTranscript.add(cppbor::SemanticTag(24, deviceEngagementEncoded));
517     sessionTranscript.add(cppbor::SemanticTag(24, eReaderKeyEncoded));
518     sessionTranscript.add(cppbor::Null());
519     vector<uint8_t> sessionTranscriptEncoded = sessionTranscript.encode();
520     vector<uint8_t> sessionTranscriptBytes =
521             cppbor::SemanticTag(24, sessionTranscriptEncoded).encode();
522 
523     // The expected EMacKey is 4c1ebb8aacc633465390fa44edfdb49cb57f2e079aaa771d812584699c0b97e2
524     //
525     // Verify that support::calcEMacKey() gets the same result.
526     //
527     optional<vector<uint8_t>> eMacKey =
528             support::calcEMacKey(support::ecKeyPairGetPrivateKey(deviceKey).value(),  // private key
529                                  ephemeralReaderKeyPublic,                            // public key
530                                  sessionTranscriptBytes);  // sessionTranscriptBytes
531     ASSERT_TRUE(eMacKey);
532     ASSERT_EQ(support::encodeHex(eMacKey.value()),
533               "4c1ebb8aacc633465390fa44edfdb49cb57f2e079aaa771d812584699c0b97e2");
534 
535     // Also do it the other way around
536     //
537     optional<vector<uint8_t>> eMacKey2 = support::calcEMacKey(
538             support::ecKeyPairGetPrivateKey(ephemeralReaderKey).value(),  // private key
539             support::ecKeyPairGetPublicKey(deviceKey).value(),            // public key
540             sessionTranscriptBytes);                                      // sessionTranscriptBytes
541     ASSERT_TRUE(eMacKey2);
542     ASSERT_EQ(support::encodeHex(eMacKey2.value()),
543               "4c1ebb8aacc633465390fa44edfdb49cb57f2e079aaa771d812584699c0b97e2");
544 
545     // We're given DeviceResponse
546     //
547     vector<uint8_t> deviceResponseEncoded =
548             support::decodeHex(
549                     "a36776657273696f6e63312e3069646f63756d656e747381a367646f6354797065756f72672e69"
550                     "736f2e31383031332e352e312e6d444c6c6973737565725369676e6564a26a6e616d6553706163"
551                     "6573a2716f72672e69736f2e31383031332e352e3181d8185863a4686469676573744944016672"
552                     "616e646f6d58208798645b20ea200e19ffabac92624bee6aec63aceedecfb1b80077d22bfc20e9"
553                     "71656c656d656e744964656e7469666965726b66616d696c795f6e616d656c656c656d656e7456"
554                     "616c756563446f656b636f6d2e6578616d706c6581d8185864a468646967657374494401667261"
555                     "6e646f6d5820218ecf13521b53f4b96abaebe56417afec0e4c91fc8fb26086cd1e5cdc1a94ff71"
556                     "656c656d656e744964656e7469666965726f616e6f746865725f656c656d656e746c656c656d65"
557                     "6e7456616c75650a6a697373756572417574688443a10126a118215901d2308201ce30820174a0"
558                     "0302010202141f7d44f4f107c5ee3f566049cf5d72de294b0d23300a06082a8648ce3d04030230"
559                     "233114301206035504030c0b75746f7069612069616361310b3009060355040613025553301e17"
560                     "0d3230313030313030303030305a170d3231313030313030303030305a30213112301006035504"
561                     "030c0975746f706961206473310b30090603550406130255533059301306072a8648ce3d020106"
562                     "082a8648ce3d03010703420004301d9e502dc7e05da85da026a7ae9aa0fac9db7d52a95b3e3e3f"
563                     "9aa0a1b45b8b6551b6f6b3061223e0d23c026b017d72298d9ae46887ca61d58db6aea17ee267a3"
564                     "8187308184301e0603551d120417301581136578616d706c65406578616d706c652e636f6d301c"
565                     "0603551d1f041530133011a00fa00d820b6578616d706c652e636f6d301d0603551d0e04160414"
566                     "7bef4db59a1ffb07592bfc57f4743b8a73aea792300e0603551d0f0101ff040403020780301506"
567                     "03551d250101ff040b3009060728818c5d050102300a06082a8648ce3d04030203480030450220"
568                     "21d52fb1fbda80e5bfda1e8dfb1bc7bf0acb7261d5c9ff54425af76eb21571c602210082bf301f"
569                     "89e0a2cb9ca9c9050352de80b47956764f7a3e07bf6a8cd87528a3b55901d2d8185901cda66776"
570                     "657273696f6e63312e306f646967657374416c676f726974686d675348412d3235366c76616c75"
571                     "6544696765737473a2716f72672e69736f2e31383031332e352e31a20058203b22af1126771f02"
572                     "f0ea0d546d4ee3c5b51637381154f5211b79daf5f9facaa8015820f2cba0ce3cde5df901a3da75"
573                     "13a4d7f7225fdfe5a306544529bf3dbcce655ca06b636f6d2e6578616d706c65a200582072636d"
574                     "ddc282424a63499f4b3927aaa3b74da7b9c0134178bf735e949e4a761e01582006322d3cbe6603"
575                     "876bdacc5b6679b51b0fc53d029c244fd5ea719d9028459c916d6465766963654b6579496e666f"
576                     "a1696465766963654b6579a4010220012158203ed113b7883b4c590638379db0c21cda16742ed0"
577                     "255048bf433391d374bc21d12258209099209accc4c8a224c843afa4f4c68a090d04da5e9889da"
578                     "e2f8eefce82a374067646f6354797065756f72672e69736f2e31383031332e352e312e6d444c6c"
579                     "76616c6964697479496e666fa3667369676e6564c074323032302d31302d30315431333a33303a"
580                     "30325a6976616c696446726f6dc074323032302d31302d30315431333a33303a30325a6a76616c"
581                     "6964556e74696cc074323032312d31302d30315431333a33303a30325a5840273ec1b59817d571"
582                     "b5a2c5c0ab0ea213d42acb18547fd7097afcc888a22ecbb863c6461ce0e240880895b4aaa84308"
583                     "784571c7be7aa3a2e7e3a2ea1a145ed1966c6465766963655369676e6564a26a6e616d65537061"
584                     "636573d81841a06a64657669636541757468a1696465766963654d61638443a10105a0f6582009"
585                     "da7c964ac004ec36ec64edd0c1abf50c03433c215c3ddb144768abcdf20a60667374617475730"
586                     "0")
587                     .value();
588     auto [deviceResponseItem, _, _2] = cppbor::parse(deviceResponseEncoded);
589     const cppbor::Map* deviceResponse = deviceResponseItem->asMap();
590     ASSERT_NE(deviceResponse, nullptr);
591     const cppbor::Array* documents = findArrayValueForTstr(deviceResponse, "documents");
592     ASSERT_NE(documents, nullptr);
593     ASSERT_EQ(documents->size(), 1);
594     const cppbor::Map* document = ((*documents)[0])->asMap();
595     ASSERT_NE(document, nullptr);
596 
597     // Get docType
598     string docType = findStringValueForTstr(document, "docType");
599     ASSERT_EQ(docType, "org.iso.18013.5.1.mDL");
600 
601     // Drill down...
602     const cppbor::Map* deviceSigned = findMapValueForTstr(document, "deviceSigned");
603     ASSERT_NE(deviceSigned, nullptr);
604 
605     // Dig out the encoded form of DeviceNameSpaces
606     //
607     const cppbor::SemanticTag* deviceNameSpacesBytes =
608             findSemanticValueForTstr(deviceSigned, "nameSpaces");
609     ASSERT_NE(deviceNameSpacesBytes, nullptr);
610     ASSERT_EQ(deviceNameSpacesBytes->semanticTag(), 24);
611     const cppbor::Bstr* deviceNameSpacesBstr = deviceNameSpacesBytes->asBstr();
612     ASSERT_NE(deviceNameSpacesBstr, nullptr);
613     vector<uint8_t> deviceNameSpacesEncoded = deviceNameSpacesBstr->value();
614 
615     // (For this version of 18013-5, DeviceNameSpaces is always supposed to be empty, check that.)
616     EXPECT_EQ(deviceNameSpacesEncoded, cppbor::Map().encode());
617 
618     const cppbor::Map* deviceAuth = findMapValueForTstr(deviceSigned, "deviceAuth");
619     ASSERT_NE(deviceAuth, nullptr);
620     // deviceMac is is the COSE_Mac0.. dig out the encoded form to check that
621     // support::calcMac() gives exactly the same bytes.
622     //
623     const cppbor::Array* deviceMac = findArrayValueForTstr(deviceAuth, "deviceMac");
624     ASSERT_NE(deviceMac, nullptr);
625     vector<uint8_t> deviceMacEncoded = deviceMac->encode();
626 
627     // Now we calculate what it should be..
628     optional<vector<uint8_t>> calculatedMac =
629             support::calcMac(sessionTranscriptEncoded,  // SessionTranscript
630                              docType,                   // DocType
631                              deviceNameSpacesEncoded,   // DeviceNamespaces
632                              eMacKey.value());          // EMacKey
633     ASSERT_TRUE(calculatedMac);
634 
635     // ... and hopefully it's the same!
636     ASSERT_EQ(calculatedMac.value().size(), deviceMacEncoded.size());
637     EXPECT_TRUE(memcmp(calculatedMac.value().data(), deviceMacEncoded.data(),
638                        deviceMacEncoded.size()) == 0);
639 }
640 
641 }  // namespace identity
642 }  // namespace hardware
643 }  // namespace android
644 
main(int argc,char ** argv)645 int main(int argc, char** argv) {
646     ::testing::InitGoogleTest(&argc, argv);
647     return RUN_ALL_TESTS();
648 }
649