David Zeuthen | 630de2a | 2020-05-11 14:04:54 -0400 | [diff] [blame] | 1 | /* |
| 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 | #if !defined(EIC_INSIDE_LIBEIC_H) && !defined(EIC_COMPILATION) |
| 18 | #error "Never include this file directly, include libeic.h instead." |
| 19 | #endif |
| 20 | |
| 21 | #ifndef ANDROID_HARDWARE_IDENTITY_EIC_OPS_H |
| 22 | #define ANDROID_HARDWARE_IDENTITY_EIC_OPS_H |
| 23 | |
| 24 | #include <stdarg.h> |
| 25 | #include <stdbool.h> |
| 26 | #include <stddef.h> |
| 27 | #include <stdlib.h> |
| 28 | |
| 29 | // Uncomment or define if debug messages are needed. |
| 30 | // |
| 31 | //#define EIC_DEBUG |
| 32 | |
| 33 | #ifdef __cplusplus |
| 34 | extern "C" { |
| 35 | #endif |
| 36 | |
| 37 | // The following defines must be set to something appropriate |
| 38 | // |
| 39 | // EIC_SHA256_CONTEXT_SIZE - the size of EicSha256Ctx |
| 40 | // EIC_HMAC_SHA256_CONTEXT_SIZE - the size of EicHmacSha256Ctx |
| 41 | // |
| 42 | // For example, if EicSha256Ctx is implemented using BoringSSL this would be defined |
| 43 | // as sizeof(SHA256_CTX). |
| 44 | // |
| 45 | // We expect the implementation to provide a header file with the name |
| 46 | // EicOpsImpl.h to do all this. |
| 47 | // |
| 48 | #include "EicOpsImpl.h" |
| 49 | |
| 50 | #define EIC_SHA256_DIGEST_SIZE 32 |
| 51 | |
| 52 | // The size of a P-256 private key. |
| 53 | // |
| 54 | #define EIC_P256_PRIV_KEY_SIZE 32 |
| 55 | |
| 56 | // The size of a P-256 public key in uncompressed form. |
| 57 | // |
| 58 | // The public key is stored in uncompressed form, first the X coordinate, then |
| 59 | // the Y coordinate. |
| 60 | // |
| 61 | #define EIC_P256_PUB_KEY_SIZE 64 |
| 62 | |
| 63 | // Size of one of the coordinates in a curve-point. |
| 64 | // |
| 65 | #define EIC_P256_COORDINATE_SIZE 32 |
| 66 | |
| 67 | // The size of an ECSDA signature using P-256. |
| 68 | // |
| 69 | // The R and S values are stored here, first R then S. |
| 70 | // |
| 71 | #define EIC_ECDSA_P256_SIGNATURE_SIZE 64 |
| 72 | |
| 73 | #define EIC_AES_128_KEY_SIZE 16 |
| 74 | |
| 75 | // The following are definitions of implementation functions the |
| 76 | // underlying platform must provide. |
| 77 | // |
| 78 | |
| 79 | struct EicSha256Ctx { |
| 80 | uint8_t reserved[EIC_SHA256_CONTEXT_SIZE]; |
| 81 | }; |
| 82 | typedef struct EicSha256Ctx EicSha256Ctx; |
| 83 | |
| 84 | struct EicHmacSha256Ctx { |
| 85 | uint8_t reserved[EIC_HMAC_SHA256_CONTEXT_SIZE]; |
| 86 | }; |
| 87 | typedef struct EicHmacSha256Ctx EicHmacSha256Ctx; |
| 88 | |
| 89 | #ifdef EIC_DEBUG |
| 90 | // Debug macro. Don't include a new-line in message. |
| 91 | // |
| 92 | #define eicDebug(...) \ |
| 93 | do { \ |
| 94 | eicPrint("%s:%d: ", __FILE__, __LINE__); \ |
| 95 | eicPrint(__VA_ARGS__); \ |
| 96 | eicPrint("\n"); \ |
| 97 | } while (0) |
| 98 | #else |
| 99 | #define eicDebug(...) \ |
| 100 | do { \ |
| 101 | } while (0) |
| 102 | #endif |
| 103 | |
| 104 | // Prints message which should include new-line character. Can be no-op. |
| 105 | // |
| 106 | // Don't use this from code, use eicDebug() instead. |
| 107 | // |
| 108 | #ifdef EIC_DEBUG |
| 109 | void eicPrint(const char* format, ...); |
| 110 | #else |
| 111 | inline void eicPrint(const char*, ...) {} |
| 112 | #endif |
| 113 | |
| 114 | // Dumps data as pretty-printed hex. Can be no-op. |
| 115 | // |
| 116 | #ifdef EIC_DEBUG |
| 117 | void eicHexdump(const char* message, const uint8_t* data, size_t dataSize); |
| 118 | #else |
| 119 | inline void eicHexdump(const char*, const uint8_t*, size_t) {} |
| 120 | #endif |
| 121 | |
| 122 | // Pretty-prints encoded CBOR. Can be no-op. |
| 123 | // |
| 124 | // If a byte-string is larger than |maxBStrSize| its contents will not be |
| 125 | // printed, instead the value of the form "<bstr size=1099016 |
| 126 | // sha1=ef549cca331f73dfae2090e6a37c04c23f84b07b>" will be printed. Pass zero |
| 127 | // for |maxBStrSize| to disable this. |
| 128 | // |
| 129 | #ifdef EIC_DEBUG |
| 130 | void eicCborPrettyPrint(const uint8_t* cborData, size_t cborDataSize, size_t maxBStrSize); |
| 131 | #else |
| 132 | inline void eicCborPrettyPrint(const uint8_t*, size_t, size_t) {} |
| 133 | #endif |
| 134 | |
| 135 | // Memory setting, see memset(3). |
| 136 | void* eicMemSet(void* s, int c, size_t n); |
| 137 | |
| 138 | // Memory copying, see memcpy(3). |
| 139 | void* eicMemCpy(void* dest, const void* src, size_t n); |
| 140 | |
| 141 | // String length, see strlen(3). |
| 142 | size_t eicStrLen(const char* s); |
| 143 | |
David Zeuthen | 1eb12b2 | 2021-09-11 13:59:43 -0400 | [diff] [blame] | 144 | // Locate a substring, see memmem(3) |
| 145 | void* eicMemMem(const uint8_t* haystack, size_t haystackLen, const uint8_t* needle, |
| 146 | size_t needleLen); |
| 147 | |
David Zeuthen | 630de2a | 2020-05-11 14:04:54 -0400 | [diff] [blame] | 148 | // Memory compare, see CRYPTO_memcmp(3SSL) |
| 149 | // |
| 150 | // It takes an amount of time dependent on len, but independent of the contents of the |
| 151 | // memory regions pointed to by s1 and s2. |
| 152 | // |
| 153 | int eicCryptoMemCmp(const void* s1, const void* s2, size_t n); |
| 154 | |
| 155 | // Random number generation. |
| 156 | bool eicOpsRandom(uint8_t* buf, size_t numBytes); |
| 157 | |
David Zeuthen | 1eb12b2 | 2021-09-11 13:59:43 -0400 | [diff] [blame] | 158 | // Creates a new non-zero identifier in |id|. |
| 159 | // |
| 160 | // Is guaranteed to be non-zero and different than what is already in |id|. |
| 161 | // |
| 162 | bool eicNextId(uint32_t* id); |
| 163 | |
David Zeuthen | 630de2a | 2020-05-11 14:04:54 -0400 | [diff] [blame] | 164 | // If |testCredential| is true, returns the 128-bit AES Hardware-Bound Key (16 bytes). |
| 165 | // |
| 166 | // Otherwise returns all zeroes (16 bytes). |
| 167 | // |
| 168 | const uint8_t* eicOpsGetHardwareBoundKey(bool testCredential); |
| 169 | |
| 170 | // Encrypts |data| with |key| and |additionalAuthenticatedData| using |nonce|, |
| 171 | // returns the resulting (nonce || ciphertext || tag) in |encryptedData| which |
| 172 | // must be of size |dataSize| + 28. |
| 173 | bool eicOpsEncryptAes128Gcm( |
| 174 | const uint8_t* key, // Must be 16 bytes |
| 175 | const uint8_t* nonce, // Must be 12 bytes |
| 176 | const uint8_t* data, // May be NULL if size is 0 |
| 177 | size_t dataSize, |
| 178 | const uint8_t* additionalAuthenticationData, // May be NULL if size is 0 |
| 179 | size_t additionalAuthenticationDataSize, uint8_t* encryptedData); |
| 180 | |
| 181 | // Decrypts |encryptedData| using |key| and |additionalAuthenticatedData|, |
| 182 | // returns resulting plaintext in |data| must be of size |encryptedDataSize| - 28. |
| 183 | // |
| 184 | // The format of |encryptedData| must be as specified in the |
| 185 | // encryptAes128Gcm() function. |
| 186 | bool eicOpsDecryptAes128Gcm(const uint8_t* key, // Must be 16 bytes |
| 187 | const uint8_t* encryptedData, size_t encryptedDataSize, |
| 188 | const uint8_t* additionalAuthenticationData, |
| 189 | size_t additionalAuthenticationDataSize, uint8_t* data); |
| 190 | |
| 191 | // Creates an EC key using the P-256 curve. The private key is written to |
| 192 | // |privateKey|. The public key is written to |publicKey|. |
| 193 | // |
| 194 | bool eicOpsCreateEcKey(uint8_t privateKey[EIC_P256_PRIV_KEY_SIZE], |
| 195 | uint8_t publicKey[EIC_P256_PUB_KEY_SIZE]); |
| 196 | |
| 197 | // Generates CredentialKey plus an attestation certificate. |
| 198 | // |
Seth Moore | 1bf823c | 2022-01-25 23:04:37 +0000 | [diff] [blame] | 199 | // If |attestationKeyBlob| is non-NULL, the certificate must be signed by the |
| 200 | // the provided attestation key. Else, the certificate must be signed by the |
| 201 | // attestation key that the secure area has been factory provisioned with. The |
| 202 | // given |challenge|, |applicationId|, and |testCredential| must be signed |
| 203 | // into the attestation. |
David Zeuthen | 630de2a | 2020-05-11 14:04:54 -0400 | [diff] [blame] | 204 | // |
Seth Moore | 1bf823c | 2022-01-25 23:04:37 +0000 | [diff] [blame] | 205 | // When |attestationKeyBlob| is non-NULL, then |attestationKeyCert| must |
| 206 | // also be passed so that the underlying implementation can properly chain up |
| 207 | // the newly-generated certificate to the existing chain. |
| 208 | // |
| 209 | // The generated certificate must be in X.509 format and returned in |cert| |
| 210 | // and |certSize| must be set to the size of this array. This function must |
| 211 | // set |certSize| to the size of the certification chain on successfully return. |
David Zeuthen | 630de2a | 2020-05-11 14:04:54 -0400 | [diff] [blame] | 212 | // |
| 213 | // This may return either a single certificate or an entire certificate |
| 214 | // chain. If it returns only a single certificate, the implementation of |
| 215 | // SecureHardwareProvisioningProxy::createCredentialKey() should amend the |
| 216 | // remainder of the certificate chain on the HAL side. |
| 217 | // |
| 218 | bool eicOpsCreateCredentialKey(uint8_t privateKey[EIC_P256_PRIV_KEY_SIZE], const uint8_t* challenge, |
| 219 | size_t challengeSize, const uint8_t* applicationId, |
Seth Moore | 1bf823c | 2022-01-25 23:04:37 +0000 | [diff] [blame] | 220 | size_t applicationIdSize, bool testCredential, |
| 221 | const uint8_t* attestationKeyBlob, size_t attestationKeyBlobSize, |
| 222 | const uint8_t* attestationKeyCert, size_t attestationKeyCertSize, |
| 223 | uint8_t* /*out*/ cert, size_t* /*inout*/ certSize); |
David Zeuthen | 630de2a | 2020-05-11 14:04:54 -0400 | [diff] [blame] | 224 | |
| 225 | // Generate an X.509 certificate for the key identified by |publicKey| which |
| 226 | // must be of the form returned by eicOpsCreateEcKey(). |
| 227 | // |
David Zeuthen | 49f2d25 | 2020-10-16 11:27:24 -0400 | [diff] [blame] | 228 | // If proofOfBinding is not NULL, it will be included as an OCTET_STRING |
| 229 | // X.509 extension at OID 1.3.6.1.4.1.11129.2.1.26. |
| 230 | // |
David Zeuthen | 630de2a | 2020-05-11 14:04:54 -0400 | [diff] [blame] | 231 | // The certificate will be signed by the key identified by |signingKey| which |
| 232 | // must be of the form returned by eicOpsCreateEcKey(). |
| 233 | // |
| 234 | bool eicOpsSignEcKey(const uint8_t publicKey[EIC_P256_PUB_KEY_SIZE], |
| 235 | const uint8_t signingKey[EIC_P256_PRIV_KEY_SIZE], unsigned int serial, |
| 236 | const char* issuerName, const char* subjectName, time_t validityNotBefore, |
David Zeuthen | 49f2d25 | 2020-10-16 11:27:24 -0400 | [diff] [blame] | 237 | time_t validityNotAfter, const uint8_t* proofOfBinding, |
| 238 | size_t proofOfBindingSize, uint8_t* cert, size_t* certSize); // inout |
David Zeuthen | 630de2a | 2020-05-11 14:04:54 -0400 | [diff] [blame] | 239 | |
| 240 | // Uses |privateKey| to create an ECDSA signature of some data (the SHA-256 must |
| 241 | // be given by |digestOfData|). Returns the signature in |signature|. |
| 242 | // |
| 243 | bool eicOpsEcDsa(const uint8_t privateKey[EIC_P256_PRIV_KEY_SIZE], |
| 244 | const uint8_t digestOfData[EIC_SHA256_DIGEST_SIZE], |
| 245 | uint8_t signature[EIC_ECDSA_P256_SIGNATURE_SIZE]); |
| 246 | |
| 247 | // Performs Elliptic Curve Diffie-Helman. |
| 248 | // |
| 249 | bool eicOpsEcdh(const uint8_t publicKey[EIC_P256_PUB_KEY_SIZE], |
| 250 | const uint8_t privateKey[EIC_P256_PRIV_KEY_SIZE], |
| 251 | uint8_t sharedSecret[EIC_P256_COORDINATE_SIZE]); |
| 252 | |
| 253 | // Performs HKDF. |
| 254 | // |
| 255 | bool eicOpsHkdf(const uint8_t* sharedSecret, size_t sharedSecretSize, const uint8_t* salt, |
| 256 | size_t saltSize, const uint8_t* info, size_t infoSize, uint8_t* output, |
| 257 | size_t outputSize); |
| 258 | |
| 259 | // SHA-256 functions. |
| 260 | void eicOpsSha256Init(EicSha256Ctx* ctx); |
| 261 | void eicOpsSha256Update(EicSha256Ctx* ctx, const uint8_t* data, size_t len); |
| 262 | void eicOpsSha256Final(EicSha256Ctx* ctx, uint8_t digest[EIC_SHA256_DIGEST_SIZE]); |
| 263 | |
| 264 | // HMAC SHA-256 functions. |
| 265 | void eicOpsHmacSha256Init(EicHmacSha256Ctx* ctx, const uint8_t* key, size_t keySize); |
| 266 | void eicOpsHmacSha256Update(EicHmacSha256Ctx* ctx, const uint8_t* data, size_t len); |
| 267 | void eicOpsHmacSha256Final(EicHmacSha256Ctx* ctx, uint8_t digest[EIC_SHA256_DIGEST_SIZE]); |
| 268 | |
| 269 | // Extracts the public key in the given X.509 certificate. |
| 270 | // |
| 271 | // If the key is not an EC key, this function fails. |
| 272 | // |
| 273 | // Otherwise the public key is stored in uncompressed form in |publicKey| which |
| 274 | // size should be set in |publicKeySize|. On successful return |publicKeySize| |
| 275 | // is set to the length of the key. If there is not enough space, the function |
| 276 | // fails. |
| 277 | // |
| 278 | // (The public key returned is not necessarily a P-256 key, even if it is note |
| 279 | // that its size is not EIC_P256_PUBLIC_KEY_SIZE because of the leading 0x04.) |
| 280 | // |
| 281 | bool eicOpsX509GetPublicKey(const uint8_t* x509Cert, size_t x509CertSize, uint8_t* publicKey, |
| 282 | size_t* publicKeySize); |
| 283 | |
| 284 | // Checks that the X.509 certificate given by |x509Cert| is signed by the public |
| 285 | // key given by |publicKey| which must be an EC key in uncompressed form (e.g. |
| 286 | // same formatt as returned by eicOpsX509GetPublicKey()). |
| 287 | // |
| 288 | bool eicOpsX509CertSignedByPublicKey(const uint8_t* x509Cert, size_t x509CertSize, |
| 289 | const uint8_t* publicKey, size_t publicKeySize); |
| 290 | |
| 291 | // Checks that |signature| is a signature of some data (given by |digest|), |
| 292 | // signed by the public key given by |publicKey|. |
| 293 | // |
| 294 | // The key must be an EC key in uncompressed form (e.g. same format as returned |
| 295 | // by eicOpsX509GetPublicKey()). |
| 296 | // |
| 297 | // The format of the signature is the same encoding as the 'signature' field of |
| 298 | // COSE_Sign1 - that is, it's the R and S integers both with the same length as |
| 299 | // the key-size. |
| 300 | // |
| 301 | // The size of digest must match the size of the key. |
| 302 | // |
| 303 | bool eicOpsEcDsaVerifyWithPublicKey(const uint8_t* digest, size_t digestSize, |
| 304 | const uint8_t* signature, size_t signatureSize, |
| 305 | const uint8_t* publicKey, size_t publicKeySize); |
| 306 | |
| 307 | // Validates that the passed in data constitutes a valid auth- and verification tokens. |
| 308 | // |
| 309 | bool eicOpsValidateAuthToken(uint64_t challenge, uint64_t secureUserId, uint64_t authenticatorId, |
| 310 | int hardwareAuthenticatorType, uint64_t timeStamp, const uint8_t* mac, |
| 311 | size_t macSize, uint64_t verificationTokenChallenge, |
| 312 | uint64_t verificationTokenTimeStamp, |
| 313 | int verificationTokenSecurityLevel, |
| 314 | const uint8_t* verificationTokenMac, size_t verificationTokenMacSize); |
| 315 | |
David Zeuthen | 1eb12b2 | 2021-09-11 13:59:43 -0400 | [diff] [blame] | 316 | // Also see eicOpsLookupActiveSessionFromId() defined in EicSession.h |
| 317 | |
David Zeuthen | 630de2a | 2020-05-11 14:04:54 -0400 | [diff] [blame] | 318 | #ifdef __cplusplus |
| 319 | } |
| 320 | #endif |
| 321 | |
| 322 | #endif // ANDROID_HARDWARE_IDENTITY_EIC_OPS_H |