diff options
Diffstat (limited to 'identity/aidl/default/libeic/EicPresentation.h')
-rw-r--r-- | identity/aidl/default/libeic/EicPresentation.h | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/identity/aidl/default/libeic/EicPresentation.h b/identity/aidl/default/libeic/EicPresentation.h new file mode 100644 index 0000000000..d79896212e --- /dev/null +++ b/identity/aidl/default/libeic/EicPresentation.h @@ -0,0 +1,229 @@ +/* + * 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_PRESENTATION_H +#define ANDROID_HARDWARE_IDENTITY_EIC_PRESENTATION_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "EicCbor.h" + +// The maximum size we support for public keys in reader certificates. +#define EIC_PRESENTATION_MAX_READER_PUBLIC_KEY_SIZE 65 + +typedef struct { + uint8_t storageKey[EIC_AES_128_KEY_SIZE]; + uint8_t credentialPrivateKey[EIC_P256_PRIV_KEY_SIZE]; + + uint8_t ephemeralPrivateKey[EIC_P256_PRIV_KEY_SIZE]; + + // The challenge generated with eicPresentationCreateAuthChallenge() + uint64_t authChallenge; + + // Set by eicPresentationSetAuthToken() and contains the fields + // from the passed in authToken and verificationToken. + // + uint64_t authTokenChallenge; + uint64_t authTokenSecureUserId; + uint64_t authTokenTimestamp; + uint64_t verificationTokenTimestamp; + + // The public key for the reader. + // + // (During the process of pushing reader certificates, this is also used to store + // the public key of the previously pushed certificate.) + // + uint8_t readerPublicKey[EIC_PRESENTATION_MAX_READER_PUBLIC_KEY_SIZE]; + size_t readerPublicKeySize; + + // This is set to true only if eicPresentationValidateRequestMessage() successfully + // validated the requestMessage. + // + // Why even record this? Because there's no requirement the HAL actually calls that + // function and we validate ACPs before it's called... so it's possible that a + // compromised HAL could trick us into marking ACPs as authorized while they in fact + // aren't. + bool requestMessageValidated; + bool buildCbor; + + // Set to true initialized as a test credential. + bool testCredential; + + // These are bitmasks indicating which of the possible 32 access control profiles are + // authorized. They are built up by eicPresentationValidateAccessControlProfile(). + // + uint32_t accessControlProfileMaskValidated; // True if the profile was validated. + uint32_t accessControlProfileMaskUsesReaderAuth; // True if the ACP is using reader auth + uint32_t accessControlProfileMaskFailedReaderAuth; // True if failed reader auth + uint32_t accessControlProfileMaskFailedUserAuth; // True if failed user auth + + // SHA-256 for AdditionalData, updated for each entry. + uint8_t additionalDataSha256[EIC_SHA256_DIGEST_SIZE]; + + size_t expectedCborSizeAtEnd; + EicCbor cbor; +} EicPresentation; + +bool eicPresentationInit(EicPresentation* ctx, bool testCredential, const char* docType, + const uint8_t encryptedCredentialKeys[80]); + +bool eicPresentationGenerateSigningKeyPair(EicPresentation* ctx, const char* docType, time_t now, + uint8_t* publicKeyCert, size_t* publicKeyCertSize, + uint8_t signingKeyBlob[60]); + +// Create an ephemeral key-pair. +// +// The private key is stored in |ctx->ephemeralPrivateKey| and also returned in +// |ephemeralPrivateKey|. +// +bool eicPresentationCreateEphemeralKeyPair(EicPresentation* ctx, + uint8_t ephemeralPrivateKey[EIC_P256_PRIV_KEY_SIZE]); + +// Returns a non-zero challenge in |authChallenge|. +bool eicPresentationCreateAuthChallenge(EicPresentation* ctx, uint64_t* authChallenge); + +// Starts retrieveing entries. +// +bool eicPresentationStartRetrieveEntries(EicPresentation* ctx); + +// Sets the auth-token. +bool eicPresentationSetAuthToken(EicPresentation* ctx, 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); + +// Function to push certificates in the reader certificate chain. +// +// This should start with the root certificate (e.g. the last in the chain) and +// continue up the chain, ending with the certificate for the reader. +// +// Calls to this function should be interleaved with calls to the +// eicPresentationValidateAccessControlProfile() function, see below. +// +bool eicPresentationPushReaderCert(EicPresentation* ctx, const uint8_t* certX509, + size_t certX509Size); + +// Checks an access control profile. +// +// Returns false if an error occurred while checking the profile (e.g. MAC doesn't check out). +// +// Returns in |accessGranted| whether access is granted. +// +// If |readerCertificate| is non-empty and the public key of one of those +// certificates appear in the chain presented by the reader, this function must +// be called after pushing that certificate using +// eicPresentationPushReaderCert(). +// +bool eicPresentationValidateAccessControlProfile(EicPresentation* ctx, int id, + const uint8_t* readerCertificate, + size_t readerCertificateSize, + bool userAuthenticationRequired, int timeoutMillis, + uint64_t secureUserId, const uint8_t mac[28], + bool* accessGranted); + +// Validates that the given requestMessage is signed by the public key in the +// certificate last set with eicPresentationPushReaderCert(). +// +// 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. +// +// Must be called after eicPresentationPushReaderCert() have been used to push +// the final certificate. Which is the certificate of the reader itself. +// +bool eicPresentationValidateRequestMessage(EicPresentation* ctx, const uint8_t* sessionTranscript, + size_t sessionTranscriptSize, + const uint8_t* requestMessage, size_t requestMessageSize, + int coseSignAlg, + const uint8_t* readerSignatureOfToBeSigned, + size_t readerSignatureOfToBeSignedSize); + +typedef enum { + // Returned if access is granted. + EIC_ACCESS_CHECK_RESULT_OK, + + // Returned if an error occurred checking for access. + EIC_ACCESS_CHECK_RESULT_FAILED, + + // Returned if access was denied because item is configured without any + // access control profiles. + EIC_ACCESS_CHECK_RESULT_NO_ACCESS_CONTROL_PROFILES, + + // Returned if access was denied because of user authentication. + EIC_ACCESS_CHECK_RESULT_USER_AUTHENTICATION_FAILED, + + // Returned if access was denied because of reader authentication. + EIC_ACCESS_CHECK_RESULT_READER_AUTHENTICATION_FAILED, +} EicAccessCheckResult; + +// Passes enough information to calculate the MACing key +// +bool eicPresentationCalcMacKey(EicPresentation* ctx, const uint8_t* sessionTranscript, + size_t sessionTranscriptSize, + const uint8_t readerEphemeralPublicKey[EIC_P256_PUB_KEY_SIZE], + const uint8_t signingKeyBlob[60], const char* docType, + unsigned int numNamespacesWithValues, + size_t expectedDeviceNamespacesSize); + +// The scratchSpace should be set to a buffer at least 512 bytes (ideally 1024 +// bytes, the bigger the better). It's done this way to avoid allocating stack +// space. +// +EicAccessCheckResult eicPresentationStartRetrieveEntryValue( + EicPresentation* ctx, const char* nameSpace, const char* name, + unsigned int newNamespaceNumEntries, int32_t entrySize, const int* accessControlProfileIds, + size_t numAccessControlProfileIds, uint8_t* scratchSpace, size_t scratchSpaceSize); + +// Note: |content| must be big enough to hold |encryptedContentSize| - 28 bytes. +// +// The scratchSpace should be set to a buffer at least 512 bytes. It's done this way to +// avoid allocating stack space. +// +bool eicPresentationRetrieveEntryValue(EicPresentation* ctx, const uint8_t* encryptedContent, + size_t encryptedContentSize, uint8_t* content, + const char* nameSpace, const char* name, + const int* accessControlProfileIds, + size_t numAccessControlProfileIds, uint8_t* scratchSpace, + size_t scratchSpaceSize); + +// Returns the HMAC-SHA256 of |ToBeMaced| as per RFC 8051 "6.3. How to Compute +// and Verify a MAC". +bool eicPresentationFinishRetrieval(EicPresentation* ctx, uint8_t* digestToBeMaced, + size_t* digestToBeMacedSize); + +// The data returned in |signatureOfToBeSigned| contains the ECDSA signature of +// the ToBeSigned CBOR from RFC 8051 "4.4. Signing and Verification Process" +// where content is set to the ProofOfDeletion CBOR. +// +bool eicPresentationDeleteCredential(EicPresentation* ctx, const char* docType, + size_t proofOfDeletionCborSize, + uint8_t signatureOfToBeSigned[EIC_ECDSA_P256_SIGNATURE_SIZE]); + +#ifdef __cplusplus +} +#endif + +#endif // ANDROID_HARDWARE_IDENTITY_EIC_PRESENTATION_H |