blob: 3f2ec8b7633cc4927602215bf6ec095e3e314d7d [file] [log] [blame]
David Zeuthen630de2a2020-05-11 14:04:54 -04001/*
2 * Copyright 2020, 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#define LOG_TAG "EicOpsImpl"
18
19#include <optional>
20#include <tuple>
21#include <vector>
22
23#include <android-base/logging.h>
24#include <android-base/stringprintf.h>
25#include <string.h>
26
27#include <android/hardware/identity/support/IdentityCredentialSupport.h>
28
29#include <openssl/sha.h>
30
31#include <openssl/aes.h>
32#include <openssl/bn.h>
33#include <openssl/crypto.h>
34#include <openssl/ec.h>
35#include <openssl/err.h>
36#include <openssl/evp.h>
37#include <openssl/hkdf.h>
38#include <openssl/hmac.h>
39#include <openssl/objects.h>
40#include <openssl/pem.h>
41#include <openssl/pkcs12.h>
42#include <openssl/rand.h>
43#include <openssl/x509.h>
44#include <openssl/x509_vfy.h>
45
46#include "EicOps.h"
47
48using ::std::optional;
49using ::std::string;
50using ::std::tuple;
51using ::std::vector;
52
53void* eicMemSet(void* s, int c, size_t n) {
54 return memset(s, c, n);
55}
56
57void* eicMemCpy(void* dest, const void* src, size_t n) {
58 return memcpy(dest, src, n);
59}
60
61size_t eicStrLen(const char* s) {
62 return strlen(s);
63}
64
65int eicCryptoMemCmp(const void* s1, const void* s2, size_t n) {
66 return CRYPTO_memcmp(s1, s2, n);
67}
68
69void eicOpsHmacSha256Init(EicHmacSha256Ctx* ctx, const uint8_t* key, size_t keySize) {
70 HMAC_CTX* realCtx = (HMAC_CTX*)ctx;
71 HMAC_CTX_init(realCtx);
72 if (HMAC_Init_ex(realCtx, key, keySize, EVP_sha256(), nullptr /* impl */) != 1) {
73 LOG(ERROR) << "Error initializing HMAC_CTX";
74 }
75}
76
77void eicOpsHmacSha256Update(EicHmacSha256Ctx* ctx, const uint8_t* data, size_t len) {
78 HMAC_CTX* realCtx = (HMAC_CTX*)ctx;
79 if (HMAC_Update(realCtx, data, len) != 1) {
80 LOG(ERROR) << "Error updating HMAC_CTX";
81 }
82}
83
84void eicOpsHmacSha256Final(EicHmacSha256Ctx* ctx, uint8_t digest[EIC_SHA256_DIGEST_SIZE]) {
85 HMAC_CTX* realCtx = (HMAC_CTX*)ctx;
86 unsigned int size = 0;
87 if (HMAC_Final(realCtx, digest, &size) != 1) {
88 LOG(ERROR) << "Error finalizing HMAC_CTX";
89 }
90 if (size != EIC_SHA256_DIGEST_SIZE) {
91 LOG(ERROR) << "Expected 32 bytes from HMAC_Final, got " << size;
92 }
93}
94
95void eicOpsSha256Init(EicSha256Ctx* ctx) {
96 SHA256_CTX* realCtx = (SHA256_CTX*)ctx;
97 SHA256_Init(realCtx);
98}
99
100void eicOpsSha256Update(EicSha256Ctx* ctx, const uint8_t* data, size_t len) {
101 SHA256_CTX* realCtx = (SHA256_CTX*)ctx;
102 SHA256_Update(realCtx, data, len);
103}
104
105void eicOpsSha256Final(EicSha256Ctx* ctx, uint8_t digest[EIC_SHA256_DIGEST_SIZE]) {
106 SHA256_CTX* realCtx = (SHA256_CTX*)ctx;
107 SHA256_Final(digest, realCtx);
108}
109
110bool eicOpsRandom(uint8_t* buf, size_t numBytes) {
111 optional<vector<uint8_t>> bytes = ::android::hardware::identity::support::getRandom(numBytes);
112 if (!bytes.has_value()) {
113 return false;
114 }
115 memcpy(buf, bytes.value().data(), numBytes);
116 return true;
117}
118
119bool eicOpsEncryptAes128Gcm(
120 const uint8_t* key, // Must be 16 bytes
121 const uint8_t* nonce, // Must be 12 bytes
122 const uint8_t* data, // May be NULL if size is 0
123 size_t dataSize,
124 const uint8_t* additionalAuthenticationData, // May be NULL if size is 0
125 size_t additionalAuthenticationDataSize, uint8_t* encryptedData) {
126 vector<uint8_t> cppKey;
127 cppKey.resize(16);
128 memcpy(cppKey.data(), key, 16);
129
130 vector<uint8_t> cppData;
131 cppData.resize(dataSize);
132 if (dataSize > 0) {
133 memcpy(cppData.data(), data, dataSize);
134 }
135
136 vector<uint8_t> cppAAD;
137 cppAAD.resize(additionalAuthenticationDataSize);
138 if (additionalAuthenticationDataSize > 0) {
139 memcpy(cppAAD.data(), additionalAuthenticationData, additionalAuthenticationDataSize);
140 }
141
142 vector<uint8_t> cppNonce;
143 cppNonce.resize(12);
144 memcpy(cppNonce.data(), nonce, 12);
145
146 optional<vector<uint8_t>> cppEncryptedData =
147 android::hardware::identity::support::encryptAes128Gcm(cppKey, cppNonce, cppData,
148 cppAAD);
149 if (!cppEncryptedData.has_value()) {
150 return false;
151 }
152
153 memcpy(encryptedData, cppEncryptedData.value().data(), cppEncryptedData.value().size());
154 return true;
155}
156
157// Decrypts |encryptedData| using |key| and |additionalAuthenticatedData|,
158// returns resulting plaintext in |data| must be of size |encryptedDataSize| - 28.
159//
160// The format of |encryptedData| must be as specified in the
161// encryptAes128Gcm() function.
162bool eicOpsDecryptAes128Gcm(const uint8_t* key, // Must be 16 bytes
163 const uint8_t* encryptedData, size_t encryptedDataSize,
164 const uint8_t* additionalAuthenticationData,
165 size_t additionalAuthenticationDataSize, uint8_t* data) {
166 vector<uint8_t> keyVec;
167 keyVec.resize(16);
168 memcpy(keyVec.data(), key, 16);
169
170 vector<uint8_t> encryptedDataVec;
171 encryptedDataVec.resize(encryptedDataSize);
172 if (encryptedDataSize > 0) {
173 memcpy(encryptedDataVec.data(), encryptedData, encryptedDataSize);
174 }
175
176 vector<uint8_t> aadVec;
177 aadVec.resize(additionalAuthenticationDataSize);
178 if (additionalAuthenticationDataSize > 0) {
179 memcpy(aadVec.data(), additionalAuthenticationData, additionalAuthenticationDataSize);
180 }
181
182 optional<vector<uint8_t>> decryptedDataVec =
183 android::hardware::identity::support::decryptAes128Gcm(keyVec, encryptedDataVec,
184 aadVec);
185 if (!decryptedDataVec.has_value()) {
186 eicDebug("Error decrypting data");
187 return false;
188 }
189 if (decryptedDataVec.value().size() != encryptedDataSize - 28) {
190 eicDebug("Decrypted data is size %zd, expected %zd", decryptedDataVec.value().size(),
191 encryptedDataSize - 28);
192 return false;
193 }
194
195 if (decryptedDataVec.value().size() > 0) {
196 memcpy(data, decryptedDataVec.value().data(), decryptedDataVec.value().size());
197 }
198 return true;
199}
200
201bool eicOpsCreateEcKey(uint8_t privateKey[EIC_P256_PRIV_KEY_SIZE],
202 uint8_t publicKey[EIC_P256_PUB_KEY_SIZE]) {
203 optional<vector<uint8_t>> keyPair = android::hardware::identity::support::createEcKeyPair();
204 if (!keyPair) {
205 eicDebug("Error creating EC keypair");
206 return false;
207 }
208 optional<vector<uint8_t>> privKey =
209 android::hardware::identity::support::ecKeyPairGetPrivateKey(keyPair.value());
210 if (!privKey) {
211 eicDebug("Error extracting private key");
212 return false;
213 }
214 if (privKey.value().size() != EIC_P256_PRIV_KEY_SIZE) {
215 eicDebug("Private key is not %zd bytes long as expected", (size_t)EIC_P256_PRIV_KEY_SIZE);
216 return false;
217 }
218
219 optional<vector<uint8_t>> pubKey =
220 android::hardware::identity::support::ecKeyPairGetPublicKey(keyPair.value());
221 if (!pubKey) {
222 eicDebug("Error extracting public key");
223 return false;
224 }
225 // ecKeyPairGetPublicKey() returns 0x04 | x | y, we don't want the leading 0x04.
226 if (pubKey.value().size() != EIC_P256_PUB_KEY_SIZE + 1) {
227 eicDebug("Private key is %zd bytes long, expected %zd", pubKey.value().size(),
228 (size_t)EIC_P256_PRIV_KEY_SIZE + 1);
229 return false;
230 }
231
232 memcpy(privateKey, privKey.value().data(), EIC_P256_PRIV_KEY_SIZE);
233 memcpy(publicKey, pubKey.value().data() + 1, EIC_P256_PUB_KEY_SIZE);
234
235 return true;
236}
237
238bool eicOpsCreateCredentialKey(uint8_t privateKey[EIC_P256_PRIV_KEY_SIZE], const uint8_t* challenge,
239 size_t challengeSize, const uint8_t* applicationId,
240 size_t applicationIdSize, bool testCredential, uint8_t* cert,
241 size_t* certSize) {
242 vector<uint8_t> challengeVec(challengeSize);
243 memcpy(challengeVec.data(), challenge, challengeSize);
244
245 vector<uint8_t> applicationIdVec(applicationIdSize);
246 memcpy(applicationIdVec.data(), applicationId, applicationIdSize);
247
248 optional<std::pair<vector<uint8_t>, vector<vector<uint8_t>>>> ret =
249 android::hardware::identity::support::createEcKeyPairAndAttestation(
250 challengeVec, applicationIdVec, testCredential);
251 if (!ret) {
252 eicDebug("Error generating CredentialKey and attestation");
253 return false;
254 }
255
256 // Extract certificate chain.
257 vector<uint8_t> flatChain =
258 android::hardware::identity::support::certificateChainJoin(ret.value().second);
259 if (*certSize < flatChain.size()) {
260 eicDebug("Buffer for certificate is only %zd bytes long, need %zd bytes", *certSize,
261 flatChain.size());
262 return false;
263 }
264 memcpy(cert, flatChain.data(), flatChain.size());
265 *certSize = flatChain.size();
266
267 // Extract private key.
268 optional<vector<uint8_t>> privKey =
269 android::hardware::identity::support::ecKeyPairGetPrivateKey(ret.value().first);
270 if (!privKey) {
271 eicDebug("Error extracting private key");
272 return false;
273 }
274 if (privKey.value().size() != EIC_P256_PRIV_KEY_SIZE) {
275 eicDebug("Private key is not %zd bytes long as expected", (size_t)EIC_P256_PRIV_KEY_SIZE);
276 return false;
277 }
278
279 memcpy(privateKey, privKey.value().data(), EIC_P256_PRIV_KEY_SIZE);
280
281 return true;
282}
283
284bool eicOpsSignEcKey(const uint8_t publicKey[EIC_P256_PUB_KEY_SIZE],
285 const uint8_t signingKey[EIC_P256_PRIV_KEY_SIZE], unsigned int serial,
286 const char* issuerName, const char* subjectName, time_t validityNotBefore,
287 time_t validityNotAfter, uint8_t* cert,
288 size_t* certSize) { // inout
289 vector<uint8_t> signingKeyVec(EIC_P256_PRIV_KEY_SIZE);
290 memcpy(signingKeyVec.data(), signingKey, EIC_P256_PRIV_KEY_SIZE);
291
292 vector<uint8_t> pubKeyVec(EIC_P256_PUB_KEY_SIZE + 1);
293 pubKeyVec[0] = 0x04;
294 memcpy(pubKeyVec.data() + 1, publicKey, EIC_P256_PUB_KEY_SIZE);
295
296 std::string serialDecimal = android::base::StringPrintf("%d", serial);
297
298 optional<vector<uint8_t>> certVec =
299 android::hardware::identity::support::ecPublicKeyGenerateCertificate(
300 pubKeyVec, signingKeyVec, serialDecimal, issuerName, subjectName,
301 validityNotBefore, validityNotAfter);
302 if (!certVec) {
303 eicDebug("Error generating certificate");
304 return false;
305 }
306
307 if (*certSize < certVec.value().size()) {
308 eicDebug("Buffer for certificate is only %zd bytes long, need %zd bytes", *certSize,
309 certVec.value().size());
310 return false;
311 }
312 memcpy(cert, certVec.value().data(), certVec.value().size());
313 *certSize = certVec.value().size();
314
315 return true;
316}
317
318bool eicOpsEcDsa(const uint8_t privateKey[EIC_P256_PRIV_KEY_SIZE],
319 const uint8_t digestOfData[EIC_SHA256_DIGEST_SIZE],
320 uint8_t signature[EIC_ECDSA_P256_SIGNATURE_SIZE]) {
321 vector<uint8_t> privKeyVec(EIC_P256_PRIV_KEY_SIZE);
322 memcpy(privKeyVec.data(), privateKey, EIC_P256_PRIV_KEY_SIZE);
323
324 vector<uint8_t> digestVec(EIC_SHA256_DIGEST_SIZE);
325 memcpy(digestVec.data(), digestOfData, EIC_SHA256_DIGEST_SIZE);
326
327 optional<vector<uint8_t>> derSignature =
328 android::hardware::identity::support::signEcDsaDigest(privKeyVec, digestVec);
329 if (!derSignature) {
330 eicDebug("Error signing data");
331 return false;
332 }
333
334 ECDSA_SIG* sig;
335 const unsigned char* p = derSignature.value().data();
336 sig = d2i_ECDSA_SIG(nullptr, &p, derSignature.value().size());
337 if (sig == nullptr) {
338 eicDebug("Error decoding DER signature");
339 return false;
340 }
341
342 if (BN_bn2binpad(sig->r, signature, 32) != 32) {
343 eicDebug("Error encoding r");
344 return false;
345 }
346 if (BN_bn2binpad(sig->s, signature + 32, 32) != 32) {
347 eicDebug("Error encoding s");
348 return false;
349 }
350
351 return true;
352}
353
354static const uint8_t hbkTest[16] = {0};
355static const uint8_t hbkReal[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
356
357const uint8_t* eicOpsGetHardwareBoundKey(bool testCredential) {
358 if (testCredential) {
359 return hbkTest;
360 }
361 return hbkReal;
362}
363
364bool eicOpsValidateAuthToken(uint64_t /* challenge */, uint64_t /* secureUserId */,
365 uint64_t /* authenticatorId */, int /* hardwareAuthenticatorType */,
366 uint64_t /* timeStamp */, const uint8_t* /* mac */,
367 size_t /* macSize */, uint64_t /* verificationTokenChallenge */,
368 uint64_t /* verificationTokenTimeStamp */,
369 int /* verificationTokenSecurityLevel */,
370 const uint8_t* /* verificationTokenMac */,
371 size_t /* verificationTokenMacSize */) {
372 // Here's where we would validate the passed-in |authToken| to assure ourselves
373 // that it comes from the e.g. biometric hardware and wasn't made up by an attacker.
374 //
375 // However this involves calculating the MAC which requires access to the to
376 // a pre-shared key which we don't have...
377 //
378 return true;
379}
380
381bool eicOpsX509GetPublicKey(const uint8_t* x509Cert, size_t x509CertSize, uint8_t* publicKey,
382 size_t* publicKeySize) {
383 vector<uint8_t> chain;
384 chain.resize(x509CertSize);
385 memcpy(chain.data(), x509Cert, x509CertSize);
386 optional<vector<uint8_t>> res =
387 android::hardware::identity::support::certificateChainGetTopMostKey(chain);
388 if (!res) {
389 return false;
390 }
391 if (res.value().size() > *publicKeySize) {
392 eicDebug("Public key size is %zd but buffer only has room for %zd bytes",
393 res.value().size(), *publicKeySize);
394 return false;
395 }
396 *publicKeySize = res.value().size();
397 memcpy(publicKey, res.value().data(), *publicKeySize);
398 eicDebug("Extracted %zd bytes public key from %zd bytes X.509 cert", *publicKeySize,
399 x509CertSize);
400 return true;
401}
402
403bool eicOpsX509CertSignedByPublicKey(const uint8_t* x509Cert, size_t x509CertSize,
404 const uint8_t* publicKey, size_t publicKeySize) {
405 vector<uint8_t> certVec(x509Cert, x509Cert + x509CertSize);
406 vector<uint8_t> publicKeyVec(publicKey, publicKey + publicKeySize);
407 return android::hardware::identity::support::certificateSignedByPublicKey(certVec,
408 publicKeyVec);
409}
410
411bool eicOpsEcDsaVerifyWithPublicKey(const uint8_t* digest, size_t digestSize,
412 const uint8_t* signature, size_t signatureSize,
413 const uint8_t* publicKey, size_t publicKeySize) {
414 vector<uint8_t> digestVec(digest, digest + digestSize);
415 vector<uint8_t> signatureVec(signature, signature + signatureSize);
416 vector<uint8_t> publicKeyVec(publicKey, publicKey + publicKeySize);
417
418 vector<uint8_t> derSignature;
419 if (!android::hardware::identity::support::ecdsaSignatureCoseToDer(signatureVec,
420 derSignature)) {
421 LOG(ERROR) << "Error convering signature to DER format";
422 return false;
423 }
424
425 if (!android::hardware::identity::support::checkEcDsaSignature(digestVec, derSignature,
426 publicKeyVec)) {
427 LOG(ERROR) << "Signature check failed";
428 return false;
429 }
430 return true;
431}
432
433bool eicOpsEcdh(const uint8_t publicKey[EIC_P256_PUB_KEY_SIZE],
434 const uint8_t privateKey[EIC_P256_PUB_KEY_SIZE],
435 uint8_t sharedSecret[EIC_P256_COORDINATE_SIZE]) {
436 vector<uint8_t> pubKeyVec(EIC_P256_PUB_KEY_SIZE + 1);
437 pubKeyVec[0] = 0x04;
438 memcpy(pubKeyVec.data() + 1, publicKey, EIC_P256_PUB_KEY_SIZE);
439
440 vector<uint8_t> privKeyVec(EIC_P256_PRIV_KEY_SIZE);
441 memcpy(privKeyVec.data(), privateKey, EIC_P256_PRIV_KEY_SIZE);
442
443 optional<vector<uint8_t>> shared =
444 android::hardware::identity::support::ecdh(pubKeyVec, privKeyVec);
445 if (!shared) {
446 LOG(ERROR) << "Error performing ECDH";
447 return false;
448 }
449 if (shared.value().size() != EIC_P256_COORDINATE_SIZE) {
450 LOG(ERROR) << "Unexpected size of shared secret " << shared.value().size() << " expected "
451 << EIC_P256_COORDINATE_SIZE << " bytes";
452 return false;
453 }
454 memcpy(sharedSecret, shared.value().data(), EIC_P256_COORDINATE_SIZE);
455 return true;
456}
457
458bool eicOpsHkdf(const uint8_t* sharedSecret, size_t sharedSecretSize, const uint8_t* salt,
459 size_t saltSize, const uint8_t* info, size_t infoSize, uint8_t* output,
460 size_t outputSize) {
461 vector<uint8_t> sharedSecretVec(sharedSecretSize);
462 memcpy(sharedSecretVec.data(), sharedSecret, sharedSecretSize);
463 vector<uint8_t> saltVec(saltSize);
464 memcpy(saltVec.data(), salt, saltSize);
465 vector<uint8_t> infoVec(infoSize);
466 memcpy(infoVec.data(), info, infoSize);
467
468 optional<vector<uint8_t>> result = android::hardware::identity::support::hkdf(
469 sharedSecretVec, saltVec, infoVec, outputSize);
470 if (!result) {
471 LOG(ERROR) << "Error performing HKDF";
472 return false;
473 }
474 if (result.value().size() != outputSize) {
475 LOG(ERROR) << "Unexpected size of HKDF " << result.value().size() << " expected "
476 << outputSize;
477 return false;
478 }
479 memcpy(output, result.value().data(), outputSize);
480 return true;
481}
482
483#ifdef EIC_DEBUG
484
485void eicPrint(const char* format, ...) {
486 va_list args;
487 va_start(args, format);
488 vfprintf(stderr, format, args);
489 va_end(args);
490}
491
492void eicHexdump(const char* message, const uint8_t* data, size_t dataSize) {
493 vector<uint8_t> dataVec(dataSize);
494 memcpy(dataVec.data(), data, dataSize);
495 android::hardware::identity::support::hexdump(message, dataVec);
496}
497
498void eicCborPrettyPrint(const uint8_t* cborData, size_t cborDataSize, size_t maxBStrSize) {
499 vector<uint8_t> cborDataVec(cborDataSize);
500 memcpy(cborDataVec.data(), cborData, cborDataSize);
501 string str =
502 android::hardware::identity::support::cborPrettyPrint(cborDataVec, maxBStrSize, {});
503 fprintf(stderr, "%s\n", str.c_str());
504}
505
506#endif // EIC_DEBUG