diff options
author | David Zeuthen <zeuthen@google.com> | 2020-10-16 11:27:24 -0400 |
---|---|---|
committer | David Zeuthen <zeuthen@google.com> | 2021-01-23 13:35:57 -0500 |
commit | 49f2d2558ac417d090dfae9c78ab372d71e5140c (patch) | |
tree | be240ccdfb0fa1e45aa03648cb385ff7ce82d84f /identity/aidl/default/libeic/EicProvisioning.c | |
parent | eafa06164d1e1bafbe20562d540ab5420bb0f825 (diff) |
Identity Credential changes for Android 12
- Add IIdentityCredential.deleteCredentialWithChallenge()
- Deprecate IIdentityCredential.deleteCredential()
- Add IIdentityCredential.proveOwership()
- Add IIdentityCredential.updateCredential()
- Add ProofOfBinding CBOR to AuthenticationKey X.509 certificate
- Document which API versions new methods/features appeared in.
- Mention need to declare android.hardware.identity_credential system
feature (w/ feature version number) and do this for the default
implementation.
Bug: 170146643
Test: atest VtsHalIdentityTargetTest
Change-Id: Ib47c7caa5f3d6fff6919f019eee44a735dba9cf8
Diffstat (limited to 'identity/aidl/default/libeic/EicProvisioning.c')
-rw-r--r-- | identity/aidl/default/libeic/EicProvisioning.c | 93 |
1 files changed, 90 insertions, 3 deletions
diff --git a/identity/aidl/default/libeic/EicProvisioning.c b/identity/aidl/default/libeic/EicProvisioning.c index f16605cfad..3b4148e571 100644 --- a/identity/aidl/default/libeic/EicProvisioning.c +++ b/identity/aidl/default/libeic/EicProvisioning.c @@ -26,10 +26,84 @@ bool eicProvisioningInit(EicProvisioning* ctx, bool testCredential) { return true; } +bool eicProvisioningInitForUpdate(EicProvisioning* ctx, bool testCredential, const char* docType, + const uint8_t* encryptedCredentialKeys, + size_t encryptedCredentialKeysSize) { + uint8_t credentialKeys[86]; + + // For feature version 202009 it's 52 bytes long and for feature version 202101 it's 86 + // bytes (the additional data is the ProofOfProvisioning SHA-256). We need + // to support loading all feature versions. + // + bool expectPopSha256 = false; + if (encryptedCredentialKeysSize == 52 + 28) { + /* do nothing */ + } else if (encryptedCredentialKeysSize == 86 + 28) { + expectPopSha256 = true; + } else { + eicDebug("Unexpected size %zd for encryptedCredentialKeys", encryptedCredentialKeysSize); + return false; + } + + eicMemSet(ctx, '\0', sizeof(EicProvisioning)); + ctx->testCredential = testCredential; + + if (!eicOpsDecryptAes128Gcm(eicOpsGetHardwareBoundKey(testCredential), encryptedCredentialKeys, + encryptedCredentialKeysSize, + // DocType is the additionalAuthenticatedData + (const uint8_t*)docType, eicStrLen(docType), credentialKeys)) { + eicDebug("Error decrypting CredentialKeys"); + return false; + } + + // It's supposed to look like this; + // + // Feature version 202009: + // + // CredentialKeys = [ + // bstr, ; storageKey, a 128-bit AES key + // bstr, ; credentialPrivKey, the private key for credentialKey + // ] + // + // Feature version 202101: + // + // CredentialKeys = [ + // bstr, ; storageKey, a 128-bit AES key + // bstr, ; credentialPrivKey, the private key for credentialKey + // bstr ; proofOfProvisioning SHA-256 + // ] + // + // where storageKey is 16 bytes, credentialPrivateKey is 32 bytes, and proofOfProvisioning + // SHA-256 is 32 bytes. + // + if (credentialKeys[0] != (expectPopSha256 ? 0x83 : 0x82) || // array of two or three elements + credentialKeys[1] != 0x50 || // 16-byte bstr + credentialKeys[18] != 0x58 || credentialKeys[19] != 0x20) { // 32-byte bstr + eicDebug("Invalid CBOR for CredentialKeys"); + return false; + } + if (expectPopSha256) { + if (credentialKeys[52] != 0x58 || credentialKeys[53] != 0x20) { // 32-byte bstr + eicDebug("Invalid CBOR for CredentialKeys"); + return false; + } + } + eicMemCpy(ctx->storageKey, credentialKeys + 2, EIC_AES_128_KEY_SIZE); + eicMemCpy(ctx->credentialPrivateKey, credentialKeys + 20, EIC_P256_PRIV_KEY_SIZE); + // Note: We don't care about the previous ProofOfProvisioning SHA-256 + ctx->isUpdate = true; + return true; +} + bool eicProvisioningCreateCredentialKey(EicProvisioning* ctx, const uint8_t* challenge, size_t challengeSize, const uint8_t* applicationId, size_t applicationIdSize, uint8_t* publicKeyCert, size_t* publicKeyCertSize) { + if (ctx->isUpdate) { + eicDebug("Cannot create CredentialKey on update"); + return false; + } + if (!eicOpsCreateCredentialKey(ctx->credentialPrivateKey, challenge, challengeSize, applicationId, applicationIdSize, ctx->testCredential, publicKeyCert, publicKeyCertSize)) { @@ -96,6 +170,9 @@ bool eicProvisioningStartPersonalization(EicProvisioning* ctx, int accessControl eicCborBegin(&ctx->cbor, EIC_CBOR_MAJOR_TYPE_BYTE_STRING, expectedProofOfProvisioningSize); ctx->expectedCborSizeAtEnd = expectedProofOfProvisioningSize + ctx->cbor.size; + eicOpsSha256Init(&ctx->proofOfProvisioningDigester); + eicCborEnableSecondaryDigesterSha256(&ctx->cbor, &ctx->proofOfProvisioningDigester); + eicCborAppendArray(&ctx->cbor, 5); eicCborAppendString(&ctx->cbor, "ProofOfProvisioning"); eicCborAppendString(&ctx->cbor, docType); @@ -260,14 +337,23 @@ bool eicProvisioningFinishAddingEntries( } bool eicProvisioningFinishGetCredentialData(EicProvisioning* ctx, const char* docType, - uint8_t encryptedCredentialKeys[80]) { + uint8_t* encryptedCredentialKeys, + size_t* encryptedCredentialKeysSize) { EicCbor cbor; - uint8_t cborBuf[52]; + uint8_t cborBuf[86]; + + if (*encryptedCredentialKeysSize < 86 + 28) { + eicDebug("encryptedCredentialKeysSize is %zd which is insufficient"); + return false; + } eicCborInit(&cbor, cborBuf, sizeof(cborBuf)); - eicCborAppendArray(&cbor, 2); + eicCborAppendArray(&cbor, 3); eicCborAppendByteString(&cbor, ctx->storageKey, EIC_AES_128_KEY_SIZE); eicCborAppendByteString(&cbor, ctx->credentialPrivateKey, EIC_P256_PRIV_KEY_SIZE); + uint8_t popSha256[EIC_SHA256_DIGEST_SIZE]; + eicOpsSha256Final(&ctx->proofOfProvisioningDigester, popSha256); + eicCborAppendByteString(&cbor, popSha256, EIC_SHA256_DIGEST_SIZE); if (cbor.size > sizeof(cborBuf)) { eicDebug("Exceeded buffer size"); return false; @@ -285,6 +371,7 @@ bool eicProvisioningFinishGetCredentialData(EicProvisioning* ctx, const char* do eicDebug("Error encrypting CredentialKeys"); return false; } + *encryptedCredentialKeysSize = cbor.size + 28; return true; } |