| /* |
| * Copyright 2020, The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #if !defined(EIC_INSIDE_LIBEIC_H) && !defined(EIC_COMPILATION) |
| #error "Never include this file directly, include libeic.h instead." |
| #endif |
| |
| #ifndef ANDROID_HARDWARE_IDENTITY_EIC_OPS_H |
| #define ANDROID_HARDWARE_IDENTITY_EIC_OPS_H |
| |
| #include <stdarg.h> |
| #include <stdbool.h> |
| #include <stddef.h> |
| #include <stdlib.h> |
| |
| // Uncomment or define if debug messages are needed. |
| // |
| //#define EIC_DEBUG |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| // The following defines must be set to something appropriate |
| // |
| // EIC_SHA256_CONTEXT_SIZE - the size of EicSha256Ctx |
| // EIC_HMAC_SHA256_CONTEXT_SIZE - the size of EicHmacSha256Ctx |
| // |
| // For example, if EicSha256Ctx is implemented using BoringSSL this would be defined |
| // as sizeof(SHA256_CTX). |
| // |
| // We expect the implementation to provide a header file with the name |
| // EicOpsImpl.h to do all this. |
| // |
| #include "EicOpsImpl.h" |
| |
| #define EIC_SHA256_DIGEST_SIZE 32 |
| |
| // The size of a P-256 private key. |
| // |
| #define EIC_P256_PRIV_KEY_SIZE 32 |
| |
| // The size of a P-256 public key in uncompressed form. |
| // |
| // The public key is stored in uncompressed form, first the X coordinate, then |
| // the Y coordinate. |
| // |
| #define EIC_P256_PUB_KEY_SIZE 64 |
| |
| // Size of one of the coordinates in a curve-point. |
| // |
| #define EIC_P256_COORDINATE_SIZE 32 |
| |
| // The size of an ECSDA signature using P-256. |
| // |
| // The R and S values are stored here, first R then S. |
| // |
| #define EIC_ECDSA_P256_SIGNATURE_SIZE 64 |
| |
| #define EIC_AES_128_KEY_SIZE 16 |
| |
| // The following are definitions of implementation functions the |
| // underlying platform must provide. |
| // |
| |
| struct EicSha256Ctx { |
| uint8_t reserved[EIC_SHA256_CONTEXT_SIZE]; |
| }; |
| typedef struct EicSha256Ctx EicSha256Ctx; |
| |
| struct EicHmacSha256Ctx { |
| uint8_t reserved[EIC_HMAC_SHA256_CONTEXT_SIZE]; |
| }; |
| typedef struct EicHmacSha256Ctx EicHmacSha256Ctx; |
| |
| #ifdef EIC_DEBUG |
| // Debug macro. Don't include a new-line in message. |
| // |
| #define eicDebug(...) \ |
| do { \ |
| eicPrint("%s:%d: ", __FILE__, __LINE__); \ |
| eicPrint(__VA_ARGS__); \ |
| eicPrint("\n"); \ |
| } while (0) |
| #else |
| #define eicDebug(...) \ |
| do { \ |
| } while (0) |
| #endif |
| |
| // Prints message which should include new-line character. Can be no-op. |
| // |
| // Don't use this from code, use eicDebug() instead. |
| // |
| #ifdef EIC_DEBUG |
| void eicPrint(const char* format, ...); |
| #else |
| inline void eicPrint(const char*, ...) {} |
| #endif |
| |
| // Dumps data as pretty-printed hex. Can be no-op. |
| // |
| #ifdef EIC_DEBUG |
| void eicHexdump(const char* message, const uint8_t* data, size_t dataSize); |
| #else |
| inline void eicHexdump(const char*, const uint8_t*, size_t) {} |
| #endif |
| |
| // Pretty-prints encoded CBOR. Can be no-op. |
| // |
| // If a byte-string is larger than |maxBStrSize| its contents will not be |
| // printed, instead the value of the form "<bstr size=1099016 |
| // sha1=ef549cca331f73dfae2090e6a37c04c23f84b07b>" will be printed. Pass zero |
| // for |maxBStrSize| to disable this. |
| // |
| #ifdef EIC_DEBUG |
| void eicCborPrettyPrint(const uint8_t* cborData, size_t cborDataSize, size_t maxBStrSize); |
| #else |
| inline void eicCborPrettyPrint(const uint8_t*, size_t, size_t) {} |
| #endif |
| |
| // Memory setting, see memset(3). |
| void* eicMemSet(void* s, int c, size_t n); |
| |
| // Memory copying, see memcpy(3). |
| void* eicMemCpy(void* dest, const void* src, size_t n); |
| |
| // String length, see strlen(3). |
| size_t eicStrLen(const char* s); |
| |
| // Locate a substring, see memmem(3) |
| void* eicMemMem(const uint8_t* haystack, size_t haystackLen, const uint8_t* needle, |
| size_t needleLen); |
| |
| // Memory compare, see CRYPTO_memcmp(3SSL) |
| // |
| // It takes an amount of time dependent on len, but independent of the contents of the |
| // memory regions pointed to by s1 and s2. |
| // |
| int eicCryptoMemCmp(const void* s1, const void* s2, size_t n); |
| |
| // Random number generation. |
| bool eicOpsRandom(uint8_t* buf, size_t numBytes); |
| |
| // Creates a new non-zero identifier in |id|. |
| // |
| // Is guaranteed to be non-zero and different than what is already in |id|. |
| // |
| bool eicNextId(uint32_t* id); |
| |
| // If |testCredential| is true, returns the 128-bit AES Hardware-Bound Key (16 bytes). |
| // |
| // Otherwise returns all zeroes (16 bytes). |
| // |
| const uint8_t* eicOpsGetHardwareBoundKey(bool testCredential); |
| |
| // Encrypts |data| with |key| and |additionalAuthenticatedData| using |nonce|, |
| // returns the resulting (nonce || ciphertext || tag) in |encryptedData| which |
| // must be of size |dataSize| + 28. |
| bool eicOpsEncryptAes128Gcm( |
| const uint8_t* key, // Must be 16 bytes |
| const uint8_t* nonce, // Must be 12 bytes |
| const uint8_t* data, // May be NULL if size is 0 |
| size_t dataSize, |
| const uint8_t* additionalAuthenticationData, // May be NULL if size is 0 |
| size_t additionalAuthenticationDataSize, uint8_t* encryptedData); |
| |
| // Decrypts |encryptedData| using |key| and |additionalAuthenticatedData|, |
| // returns resulting plaintext in |data| must be of size |encryptedDataSize| - 28. |
| // |
| // The format of |encryptedData| must be as specified in the |
| // encryptAes128Gcm() function. |
| bool eicOpsDecryptAes128Gcm(const uint8_t* key, // Must be 16 bytes |
| const uint8_t* encryptedData, size_t encryptedDataSize, |
| const uint8_t* additionalAuthenticationData, |
| size_t additionalAuthenticationDataSize, uint8_t* data); |
| |
| // Creates an EC key using the P-256 curve. The private key is written to |
| // |privateKey|. The public key is written to |publicKey|. |
| // |
| bool eicOpsCreateEcKey(uint8_t privateKey[EIC_P256_PRIV_KEY_SIZE], |
| uint8_t publicKey[EIC_P256_PUB_KEY_SIZE]); |
| |
| // Generates CredentialKey plus an attestation certificate. |
| // |
| // If |attestationKeyBlob| is non-NULL, the certificate must be signed by the |
| // the provided attestation key. Else, the certificate must be signed by the |
| // attestation key that the secure area has been factory provisioned with. The |
| // given |challenge|, |applicationId|, and |testCredential| must be signed |
| // into the attestation. |
| // |
| // When |attestationKeyBlob| is non-NULL, then |attestationKeyCert| must |
| // also be passed so that the underlying implementation can properly chain up |
| // the newly-generated certificate to the existing chain. |
| // |
| // The generated certificate must be in X.509 format and returned in |cert| |
| // and |certSize| must be set to the size of this array. This function must |
| // set |certSize| to the size of the certification chain on successfully return. |
| // |
| // This may return either a single certificate or an entire certificate |
| // chain. If it returns only a single certificate, the implementation of |
| // SecureHardwareProvisioningProxy::createCredentialKey() should amend the |
| // remainder of the certificate chain on the HAL side. |
| // |
| bool eicOpsCreateCredentialKey(uint8_t privateKey[EIC_P256_PRIV_KEY_SIZE], const uint8_t* challenge, |
| size_t challengeSize, const uint8_t* applicationId, |
| size_t applicationIdSize, bool testCredential, |
| const uint8_t* attestationKeyBlob, size_t attestationKeyBlobSize, |
| const uint8_t* attestationKeyCert, size_t attestationKeyCertSize, |
| uint8_t* /*out*/ cert, size_t* /*inout*/ certSize); |
| |
| // Generate an X.509 certificate for the key identified by |publicKey| which |
| // must be of the form returned by eicOpsCreateEcKey(). |
| // |
| // If proofOfBinding is not NULL, it will be included as an OCTET_STRING |
| // X.509 extension at OID 1.3.6.1.4.1.11129.2.1.26. |
| // |
| // The certificate will be signed by the key identified by |signingKey| which |
| // must be of the form returned by eicOpsCreateEcKey(). |
| // |
| bool eicOpsSignEcKey(const uint8_t publicKey[EIC_P256_PUB_KEY_SIZE], |
| const uint8_t signingKey[EIC_P256_PRIV_KEY_SIZE], unsigned int serial, |
| const char* issuerName, const char* subjectName, time_t validityNotBefore, |
| time_t validityNotAfter, const uint8_t* proofOfBinding, |
| size_t proofOfBindingSize, uint8_t* cert, size_t* certSize); // inout |
| |
| // Uses |privateKey| to create an ECDSA signature of some data (the SHA-256 must |
| // be given by |digestOfData|). Returns the signature in |signature|. |
| // |
| bool eicOpsEcDsa(const uint8_t privateKey[EIC_P256_PRIV_KEY_SIZE], |
| const uint8_t digestOfData[EIC_SHA256_DIGEST_SIZE], |
| uint8_t signature[EIC_ECDSA_P256_SIGNATURE_SIZE]); |
| |
| // Performs Elliptic Curve Diffie-Helman. |
| // |
| bool eicOpsEcdh(const uint8_t publicKey[EIC_P256_PUB_KEY_SIZE], |
| const uint8_t privateKey[EIC_P256_PRIV_KEY_SIZE], |
| uint8_t sharedSecret[EIC_P256_COORDINATE_SIZE]); |
| |
| // Performs HKDF. |
| // |
| bool eicOpsHkdf(const uint8_t* sharedSecret, size_t sharedSecretSize, const uint8_t* salt, |
| size_t saltSize, const uint8_t* info, size_t infoSize, uint8_t* output, |
| size_t outputSize); |
| |
| // SHA-256 functions. |
| void eicOpsSha256Init(EicSha256Ctx* ctx); |
| void eicOpsSha256Update(EicSha256Ctx* ctx, const uint8_t* data, size_t len); |
| void eicOpsSha256Final(EicSha256Ctx* ctx, uint8_t digest[EIC_SHA256_DIGEST_SIZE]); |
| |
| // HMAC SHA-256 functions. |
| void eicOpsHmacSha256Init(EicHmacSha256Ctx* ctx, const uint8_t* key, size_t keySize); |
| void eicOpsHmacSha256Update(EicHmacSha256Ctx* ctx, const uint8_t* data, size_t len); |
| void eicOpsHmacSha256Final(EicHmacSha256Ctx* ctx, uint8_t digest[EIC_SHA256_DIGEST_SIZE]); |
| |
| // Extracts the public key in the given X.509 certificate. |
| // |
| // If the key is not an EC key, this function fails. |
| // |
| // Otherwise the public key is stored in uncompressed form in |publicKey| which |
| // size should be set in |publicKeySize|. On successful return |publicKeySize| |
| // is set to the length of the key. If there is not enough space, the function |
| // fails. |
| // |
| // (The public key returned is not necessarily a P-256 key, even if it is note |
| // that its size is not EIC_P256_PUBLIC_KEY_SIZE because of the leading 0x04.) |
| // |
| bool eicOpsX509GetPublicKey(const uint8_t* x509Cert, size_t x509CertSize, uint8_t* publicKey, |
| size_t* publicKeySize); |
| |
| // Checks that the X.509 certificate given by |x509Cert| is signed by the public |
| // key given by |publicKey| which must be an EC key in uncompressed form (e.g. |
| // same formatt as returned by eicOpsX509GetPublicKey()). |
| // |
| bool eicOpsX509CertSignedByPublicKey(const uint8_t* x509Cert, size_t x509CertSize, |
| const uint8_t* publicKey, size_t publicKeySize); |
| |
| // Checks that |signature| is a signature of some data (given by |digest|), |
| // signed by the public key given by |publicKey|. |
| // |
| // The key must be an EC key in uncompressed form (e.g. same format as returned |
| // by eicOpsX509GetPublicKey()). |
| // |
| // The format of the signature is the same encoding as the 'signature' field of |
| // COSE_Sign1 - that is, it's the R and S integers both with the same length as |
| // the key-size. |
| // |
| // The size of digest must match the size of the key. |
| // |
| bool eicOpsEcDsaVerifyWithPublicKey(const uint8_t* digest, size_t digestSize, |
| const uint8_t* signature, size_t signatureSize, |
| const uint8_t* publicKey, size_t publicKeySize); |
| |
| // Validates that the passed in data constitutes a valid auth- and verification tokens. |
| // |
| bool eicOpsValidateAuthToken(uint64_t challenge, uint64_t secureUserId, uint64_t authenticatorId, |
| int hardwareAuthenticatorType, uint64_t timeStamp, const uint8_t* mac, |
| size_t macSize, uint64_t verificationTokenChallenge, |
| uint64_t verificationTokenTimeStamp, |
| int verificationTokenSecurityLevel, |
| const uint8_t* verificationTokenMac, size_t verificationTokenMacSize); |
| |
| // Also see eicOpsLookupActiveSessionFromId() defined in EicSession.h |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif // ANDROID_HARDWARE_IDENTITY_EIC_OPS_H |