diff options
-rw-r--r-- | identity/aidl/default/FakeSecureHardwareProxy.cpp | 82 | ||||
-rw-r--r-- | identity/aidl/default/libeic/EicCbor.c | 44 | ||||
-rw-r--r-- | identity/aidl/default/libeic/EicCbor.h | 24 | ||||
-rw-r--r-- | identity/aidl/default/libeic/EicCommon.h | 44 | ||||
-rw-r--r-- | identity/aidl/default/libeic/EicPresentation.c | 105 | ||||
-rw-r--r-- | identity/aidl/default/libeic/EicPresentation.h | 36 | ||||
-rw-r--r-- | identity/aidl/default/libeic/EicProvisioning.c | 69 | ||||
-rw-r--r-- | identity/aidl/default/libeic/EicProvisioning.h | 24 | ||||
-rw-r--r-- | identity/aidl/default/libeic/libeic.h | 1 |
9 files changed, 268 insertions, 161 deletions
diff --git a/identity/aidl/default/FakeSecureHardwareProxy.cpp b/identity/aidl/default/FakeSecureHardwareProxy.cpp index 287ffb82e1..f0307dc324 100644 --- a/identity/aidl/default/FakeSecureHardwareProxy.cpp +++ b/identity/aidl/default/FakeSecureHardwareProxy.cpp @@ -70,6 +70,7 @@ bool FakeSecureHardwareProvisioningProxy::initialize(bool testCredential) { bool FakeSecureHardwareProvisioningProxy::initializeForUpdate( bool testCredential, string docType, vector<uint8_t> encryptedCredentialKeys) { return eicProvisioningInitForUpdate(&ctx_, testCredential, docType.c_str(), + docType.size(), encryptedCredentialKeys.data(), encryptedCredentialKeys.size()); } @@ -92,8 +93,11 @@ optional<vector<uint8_t>> FakeSecureHardwareProvisioningProxy::createCredentialK bool FakeSecureHardwareProvisioningProxy::startPersonalization( int accessControlProfileCount, vector<int> entryCounts, const string& docType, size_t expectedProofOfProvisioningSize) { - if (!eicProvisioningStartPersonalization(&ctx_, accessControlProfileCount, entryCounts.data(), - entryCounts.size(), docType.c_str(), + + if (!eicProvisioningStartPersonalization(&ctx_, accessControlProfileCount, + entryCounts.data(), + entryCounts.size(), + docType.c_str(), docType.size(), expectedProofOfProvisioningSize)) { return false; } @@ -105,9 +109,11 @@ optional<vector<uint8_t>> FakeSecureHardwareProvisioningProxy::addAccessControlP int id, const vector<uint8_t>& readerCertificate, bool userAuthenticationRequired, uint64_t timeoutMillis, uint64_t secureUserId) { vector<uint8_t> mac(28); + uint8_t scratchSpace[512]; if (!eicProvisioningAddAccessControlProfile( &ctx_, id, readerCertificate.data(), readerCertificate.size(), - userAuthenticationRequired, timeoutMillis, secureUserId, mac.data())) { + userAuthenticationRequired, timeoutMillis, secureUserId, mac.data(), + scratchSpace, sizeof(scratchSpace))) { return {}; } return mac; @@ -117,9 +123,15 @@ bool FakeSecureHardwareProvisioningProxy::beginAddEntry(const vector<int>& acces const string& nameSpace, const string& name, uint64_t entrySize) { uint8_t scratchSpace[512]; - return eicProvisioningBeginAddEntry(&ctx_, accessControlProfileIds.data(), - accessControlProfileIds.size(), nameSpace.c_str(), - name.c_str(), entrySize, scratchSpace, sizeof scratchSpace); + vector<uint8_t> uint8AccessControlProfileIds; + for (size_t i = 0; i < accessControlProfileIds.size(); i++) { + uint8AccessControlProfileIds.push_back(accessControlProfileIds[i] & 0xFF); + } + + return eicProvisioningBeginAddEntry(&ctx_, uint8AccessControlProfileIds.data(), + uint8AccessControlProfileIds.size(), nameSpace.c_str(), + nameSpace.size(), name.c_str(), name.size(), entrySize, + scratchSpace, sizeof(scratchSpace)); } // Returns encryptedContent. @@ -128,11 +140,16 @@ optional<vector<uint8_t>> FakeSecureHardwareProvisioningProxy::addEntryValue( const vector<uint8_t>& content) { vector<uint8_t> eicEncryptedContent; uint8_t scratchSpace[512]; + vector<uint8_t> uint8AccessControlProfileIds; + for (size_t i = 0; i < accessControlProfileIds.size(); i++) { + uint8AccessControlProfileIds.push_back(accessControlProfileIds[i] & 0xFF); + } + eicEncryptedContent.resize(content.size() + 28); if (!eicProvisioningAddEntryValue( - &ctx_, accessControlProfileIds.data(), accessControlProfileIds.size(), - nameSpace.c_str(), name.c_str(), content.data(), content.size(), - eicEncryptedContent.data(), scratchSpace, sizeof scratchSpace)) { + &ctx_, uint8AccessControlProfileIds.data(), uint8AccessControlProfileIds.size(), + nameSpace.c_str(), nameSpace.size(), name.c_str(), name.size(), content.data(), + content.size(), eicEncryptedContent.data(), scratchSpace, sizeof(scratchSpace))) { return {}; } return eicEncryptedContent; @@ -152,7 +169,7 @@ optional<vector<uint8_t>> FakeSecureHardwareProvisioningProxy::finishGetCredenti const string& docType) { vector<uint8_t> encryptedCredentialKeys(116); size_t size = encryptedCredentialKeys.size(); - if (!eicProvisioningFinishGetCredentialData(&ctx_, docType.c_str(), + if (!eicProvisioningFinishGetCredentialData(&ctx_, docType.c_str(), docType.size(), encryptedCredentialKeys.data(), &size)) { return {}; } @@ -170,7 +187,7 @@ bool FakeSecureHardwarePresentationProxy::initialize(bool testCredential, string vector<uint8_t> encryptedCredentialKeys) { LOG(INFO) << "FakeSecureHardwarePresentationProxy created, sizeof(EicPresentation): " << sizeof(EicPresentation); - return eicPresentationInit(&ctx_, testCredential, docType.c_str(), + return eicPresentationInit(&ctx_, testCredential, docType.c_str(), docType.size(), encryptedCredentialKeys.data(), encryptedCredentialKeys.size()); } @@ -181,8 +198,9 @@ FakeSecureHardwarePresentationProxy::generateSigningKeyPair(string docType, time size_t publicKeyCertSize = sizeof(publicKeyCert); vector<uint8_t> signingKeyBlob(60); - if (!eicPresentationGenerateSigningKeyPair(&ctx_, docType.c_str(), now, publicKeyCert, - &publicKeyCertSize, signingKeyBlob.data())) { + if (!eicPresentationGenerateSigningKeyPair(&ctx_, docType.c_str(), docType.size(), now, + publicKeyCert, &publicKeyCertSize, + signingKeyBlob.data())) { return {}; } @@ -244,10 +262,12 @@ optional<bool> FakeSecureHardwarePresentationProxy::validateAccessControlProfile int id, const vector<uint8_t>& readerCertificate, bool userAuthenticationRequired, int timeoutMillis, uint64_t secureUserId, const vector<uint8_t>& mac) { bool accessGranted = false; + uint8_t scratchSpace[512]; if (!eicPresentationValidateAccessControlProfile(&ctx_, id, readerCertificate.data(), readerCertificate.size(), userAuthenticationRequired, timeoutMillis, - secureUserId, mac.data(), &accessGranted)) { + secureUserId, mac.data(), &accessGranted, + scratchSpace, sizeof(scratchSpace))) { return {}; } return accessGranted; @@ -267,7 +287,7 @@ bool FakeSecureHardwarePresentationProxy::calcMacKey( } return eicPresentationCalcMacKey(&ctx_, sessionTranscript.data(), sessionTranscript.size(), readerEphemeralPublicKey.data(), signingKeyBlob.data(), - docType.c_str(), numNamespacesWithValues, + docType.c_str(), docType.size(), numNamespacesWithValues, expectedProofOfProvisioningSize); } @@ -275,10 +295,16 @@ AccessCheckResult FakeSecureHardwarePresentationProxy::startRetrieveEntryValue( const string& nameSpace, const string& name, unsigned int newNamespaceNumEntries, int32_t entrySize, const vector<int32_t>& accessControlProfileIds) { uint8_t scratchSpace[512]; + vector<uint8_t> uint8AccessControlProfileIds; + for (size_t i = 0; i < accessControlProfileIds.size(); i++) { + uint8AccessControlProfileIds.push_back(accessControlProfileIds[i] & 0xFF); + } + EicAccessCheckResult result = eicPresentationStartRetrieveEntryValue( - &ctx_, nameSpace.c_str(), name.c_str(), newNamespaceNumEntries, entrySize, - accessControlProfileIds.data(), accessControlProfileIds.size(), scratchSpace, - sizeof scratchSpace); + &ctx_, nameSpace.c_str(), nameSpace.size(), name.c_str(), name.size(), + newNamespaceNumEntries, entrySize, uint8AccessControlProfileIds.data(), + uint8AccessControlProfileIds.size(), scratchSpace, + sizeof(scratchSpace)); switch (result) { case EIC_ACCESS_CHECK_RESULT_OK: return AccessCheckResult::kOk; @@ -299,12 +325,18 @@ optional<vector<uint8_t>> FakeSecureHardwarePresentationProxy::retrieveEntryValu const vector<uint8_t>& encryptedContent, const string& nameSpace, const string& name, const vector<int32_t>& accessControlProfileIds) { uint8_t scratchSpace[512]; + vector<uint8_t> uint8AccessControlProfileIds; + for (size_t i = 0; i < accessControlProfileIds.size(); i++) { + uint8AccessControlProfileIds.push_back(accessControlProfileIds[i] & 0xFF); + } + vector<uint8_t> content; content.resize(encryptedContent.size() - 28); if (!eicPresentationRetrieveEntryValue( &ctx_, encryptedContent.data(), encryptedContent.size(), content.data(), - nameSpace.c_str(), name.c_str(), accessControlProfileIds.data(), - accessControlProfileIds.size(), scratchSpace, sizeof scratchSpace)) { + nameSpace.c_str(), nameSpace.size(), name.c_str(), name.size(), + uint8AccessControlProfileIds.data(), uint8AccessControlProfileIds.size(), + scratchSpace, sizeof(scratchSpace))) { return {}; } return content; @@ -324,9 +356,9 @@ optional<vector<uint8_t>> FakeSecureHardwarePresentationProxy::deleteCredential( const string& docType, const vector<uint8_t>& challenge, bool includeChallenge, size_t proofOfDeletionCborSize) { vector<uint8_t> signatureOfToBeSigned(EIC_ECDSA_P256_SIGNATURE_SIZE); - if (!eicPresentationDeleteCredential(&ctx_, docType.c_str(), challenge.data(), challenge.size(), - includeChallenge, proofOfDeletionCborSize, - signatureOfToBeSigned.data())) { + if (!eicPresentationDeleteCredential(&ctx_, docType.c_str(), docType.size(), challenge.data(), + challenge.size(), includeChallenge, + proofOfDeletionCborSize, signatureOfToBeSigned.data())) { return {}; } return signatureOfToBeSigned; @@ -336,8 +368,8 @@ optional<vector<uint8_t>> FakeSecureHardwarePresentationProxy::proveOwnership( const string& docType, bool testCredential, const vector<uint8_t>& challenge, size_t proofOfOwnershipCborSize) { vector<uint8_t> signatureOfToBeSigned(EIC_ECDSA_P256_SIGNATURE_SIZE); - if (!eicPresentationProveOwnership(&ctx_, docType.c_str(), testCredential, challenge.data(), - challenge.size(), proofOfOwnershipCborSize, + if (!eicPresentationProveOwnership(&ctx_, docType.c_str(), docType.size(), testCredential, + challenge.data(), challenge.size(), proofOfOwnershipCborSize, signatureOfToBeSigned.data())) { return {}; } diff --git a/identity/aidl/default/libeic/EicCbor.c b/identity/aidl/default/libeic/EicCbor.c index 0e2684fec4..b9304bcacb 100644 --- a/identity/aidl/default/libeic/EicCbor.c +++ b/identity/aidl/default/libeic/EicCbor.c @@ -91,7 +91,7 @@ size_t eicCborAdditionalLengthBytesFor(size_t size) { return 8; } -void eicCborBegin(EicCbor* cbor, int majorType, size_t size) { +void eicCborBegin(EicCbor* cbor, int majorType, uint64_t size) { uint8_t data[9]; if (size < 24) { @@ -132,10 +132,13 @@ void eicCborAppendByteString(EicCbor* cbor, const uint8_t* data, size_t dataSize eicCborAppend(cbor, data, dataSize); } -void eicCborAppendString(EicCbor* cbor, const char* str) { - size_t length = eicStrLen(str); - eicCborBegin(cbor, EIC_CBOR_MAJOR_TYPE_STRING, length); - eicCborAppend(cbor, (const uint8_t*)str, length); +void eicCborAppendString(EicCbor* cbor, const char* str, size_t strLength) { + eicCborBegin(cbor, EIC_CBOR_MAJOR_TYPE_STRING, strLength); + eicCborAppend(cbor, (const uint8_t*)str, strLength); +} + +void eicCborAppendStringZ(EicCbor* cbor, const char* str) { + eicCborAppendString(cbor, str, eicStrLen(str)); } void eicCborAppendSimple(EicCbor* cbor, uint8_t simpleValue) { @@ -153,13 +156,13 @@ void eicCborAppendSemantic(EicCbor* cbor, uint64_t value) { } void eicCborAppendUnsigned(EicCbor* cbor, uint64_t value) { - size_t encoded = value; + uint64_t encoded = value; eicCborBegin(cbor, EIC_CBOR_MAJOR_TYPE_UNSIGNED, encoded); } void eicCborAppendNumber(EicCbor* cbor, int64_t value) { if (value < 0) { - size_t encoded = -1 - value; + uint64_t encoded = -1 - value; eicCborBegin(cbor, EIC_CBOR_MAJOR_TYPE_NEGATIVE, encoded); } else { eicCborAppendUnsigned(cbor, value); @@ -188,19 +191,19 @@ bool eicCborCalcAccessControl(EicCbor* cborBuilder, int id, const uint8_t* reade } } eicCborAppendMap(cborBuilder, numPairs); - eicCborAppendString(cborBuilder, "id"); + eicCborAppendStringZ(cborBuilder, "id"); eicCborAppendUnsigned(cborBuilder, id); if (readerCertificateSize > 0) { - eicCborAppendString(cborBuilder, "readerCertificate"); + eicCborAppendStringZ(cborBuilder, "readerCertificate"); eicCborAppendByteString(cborBuilder, readerCertificate, readerCertificateSize); } if (userAuthenticationRequired) { - eicCborAppendString(cborBuilder, "userAuthenticationRequired"); + eicCborAppendStringZ(cborBuilder, "userAuthenticationRequired"); eicCborAppendBool(cborBuilder, userAuthenticationRequired); - eicCborAppendString(cborBuilder, "timeoutMillis"); + eicCborAppendStringZ(cborBuilder, "timeoutMillis"); eicCborAppendUnsigned(cborBuilder, timeoutMillis); if (secureUserId > 0) { - eicCborAppendString(cborBuilder, "secureUserId"); + eicCborAppendStringZ(cborBuilder, "secureUserId"); eicCborAppendUnsigned(cborBuilder, secureUserId); } } @@ -214,20 +217,21 @@ bool eicCborCalcAccessControl(EicCbor* cborBuilder, int id, const uint8_t* reade return true; } -bool eicCborCalcEntryAdditionalData(const int* accessControlProfileIds, +bool eicCborCalcEntryAdditionalData(const uint8_t* accessControlProfileIds, size_t numAccessControlProfileIds, const char* nameSpace, - const char* name, uint8_t* cborBuffer, size_t cborBufferSize, - size_t* outAdditionalDataCborSize, + size_t nameSpaceLength, const char* name, + size_t nameLength, uint8_t* cborBuffer, + size_t cborBufferSize, size_t* outAdditionalDataCborSize, uint8_t additionalDataSha256[EIC_SHA256_DIGEST_SIZE]) { EicCbor cborBuilder; eicCborInit(&cborBuilder, cborBuffer, cborBufferSize); eicCborAppendMap(&cborBuilder, 3); - eicCborAppendString(&cborBuilder, "Namespace"); - eicCborAppendString(&cborBuilder, nameSpace); - eicCborAppendString(&cborBuilder, "Name"); - eicCborAppendString(&cborBuilder, name); - eicCborAppendString(&cborBuilder, "AccessControlProfileIds"); + eicCborAppendStringZ(&cborBuilder, "Namespace"); + eicCborAppendString(&cborBuilder, nameSpace, nameSpaceLength); + eicCborAppendStringZ(&cborBuilder, "Name"); + eicCborAppendString(&cborBuilder, name, nameLength); + eicCborAppendStringZ(&cborBuilder, "AccessControlProfileIds"); eicCborAppendArray(&cborBuilder, numAccessControlProfileIds); for (size_t n = 0; n < numAccessControlProfileIds; n++) { eicCborAppendNumber(&cborBuilder, accessControlProfileIds[n]); diff --git a/identity/aidl/default/libeic/EicCbor.h b/identity/aidl/default/libeic/EicCbor.h index 9c0f531e4a..16f7ab6619 100644 --- a/identity/aidl/default/libeic/EicCbor.h +++ b/identity/aidl/default/libeic/EicCbor.h @@ -102,13 +102,16 @@ void eicCborAppend(EicCbor* cbor, const uint8_t* data, size_t size); #define EIC_CBOR_SEMANTIC_TAG_ENCODED_CBOR 24 /* Begins a new CBOR value. */ -void eicCborBegin(EicCbor* cbor, int majorType, size_t size); +void eicCborBegin(EicCbor* cbor, int majorType, uint64_t size); /* Appends a bytestring. */ void eicCborAppendByteString(EicCbor* cbor, const uint8_t* data, size_t dataSize); +/* Appends a UTF-8 string. */ +void eicCborAppendString(EicCbor* cbor, const char* str, size_t strLength); + /* Appends a NUL-terminated UTF-8 string. */ -void eicCborAppendString(EicCbor* cbor, const char* str); +void eicCborAppendStringZ(EicCbor* cbor, const char* str); /* Appends a simple value. */ void eicCborAppendSimple(EicCbor* cbor, uint8_t simpleValue); @@ -144,22 +147,13 @@ bool eicCborCalcAccessControl(EicCbor* cborBuilder, int id, const uint8_t* reade size_t readerCertificateSize, bool userAuthenticationRequired, uint64_t timeoutMillis, uint64_t secureUserId); -bool eicCborCalcEntryAdditionalData(const int* accessControlProfileIds, +bool eicCborCalcEntryAdditionalData(const uint8_t* accessControlProfileIds, size_t numAccessControlProfileIds, const char* nameSpace, - const char* name, uint8_t* cborBuffer, size_t cborBufferSize, - size_t* outAdditionalDataCborSize, + size_t nameSpaceLength, const char* name, + size_t nameLength, uint8_t* cborBuffer, + size_t cborBufferSize, size_t* outAdditionalDataCborSize, uint8_t additionalDataSha256[EIC_SHA256_DIGEST_SIZE]); -// The maximum size of an encoded Secure Access Control Profile that we -// support. Since the SACP may contain a reader certificate chain these can get -// pretty big. -// -// Currently we allocate space on the stack for this structure which is why we -// have a maximum size. We can get rid of the maximum size by incrementally -// building/verifying the SACP. TODO: actually do this. -// -#define EIC_MAX_CBOR_SIZE_FOR_ACCESS_CONTROL_PROFILE 512 - #ifdef __cplusplus } #endif diff --git a/identity/aidl/default/libeic/EicCommon.h b/identity/aidl/default/libeic/EicCommon.h new file mode 100644 index 0000000000..476276ebcf --- /dev/null +++ b/identity/aidl/default/libeic/EicCommon.h @@ -0,0 +1,44 @@ +/* + * 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_COMMON_H +#define ANDROID_HARDWARE_IDENTITY_EIC_COMMON_H + +// 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. +#define EIC_CREDENTIAL_KEYS_CBOR_SIZE_FEATURE_VERSION_202009 52 +#define EIC_CREDENTIAL_KEYS_CBOR_SIZE_FEATURE_VERSION_202101 86 + +#endif // ANDROID_HARDWARE_IDENTITY_EIC_COMMON_H diff --git a/identity/aidl/default/libeic/EicPresentation.c b/identity/aidl/default/libeic/EicPresentation.c index 3d13766f1e..0d03ae9620 100644 --- a/identity/aidl/default/libeic/EicPresentation.c +++ b/identity/aidl/default/libeic/EicPresentation.c @@ -15,22 +15,23 @@ */ #include "EicPresentation.h" +#include "EicCommon.h" #include <inttypes.h> bool eicPresentationInit(EicPresentation* ctx, bool testCredential, const char* docType, - const uint8_t* encryptedCredentialKeys, + size_t docTypeLength, const uint8_t* encryptedCredentialKeys, size_t encryptedCredentialKeysSize) { - uint8_t credentialKeys[86]; + uint8_t credentialKeys[EIC_CREDENTIAL_KEYS_CBOR_SIZE_FEATURE_VERSION_202101]; bool expectPopSha256 = false; // 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. // - if (encryptedCredentialKeysSize == 52 + 28) { + if (encryptedCredentialKeysSize == EIC_CREDENTIAL_KEYS_CBOR_SIZE_FEATURE_VERSION_202009 + 28) { /* do nothing */ - } else if (encryptedCredentialKeysSize == 86 + 28) { + } else if (encryptedCredentialKeysSize == EIC_CREDENTIAL_KEYS_CBOR_SIZE_FEATURE_VERSION_202101 + 28) { expectPopSha256 = true; } else { eicDebug("Unexpected size %zd for encryptedCredentialKeys", encryptedCredentialKeysSize); @@ -42,7 +43,7 @@ bool eicPresentationInit(EicPresentation* ctx, bool testCredential, const char* if (!eicOpsDecryptAes128Gcm(eicOpsGetHardwareBoundKey(testCredential), encryptedCredentialKeys, encryptedCredentialKeysSize, // DocType is the additionalAuthenticatedData - (const uint8_t*)docType, eicStrLen(docType), credentialKeys)) { + (const uint8_t*)docType, docTypeLength, credentialKeys)) { eicDebug("Error decrypting CredentialKeys"); return false; } @@ -88,7 +89,8 @@ bool eicPresentationInit(EicPresentation* ctx, bool testCredential, const char* return true; } -bool eicPresentationGenerateSigningKeyPair(EicPresentation* ctx, const char* docType, time_t now, +bool eicPresentationGenerateSigningKeyPair(EicPresentation* ctx, const char* docType, + size_t docTypeLength, time_t now, uint8_t* publicKeyCert, size_t* publicKeyCertSize, uint8_t signingKeyBlob[60]) { uint8_t signingKeyPriv[EIC_P256_PRIV_KEY_SIZE]; @@ -114,7 +116,7 @@ bool eicPresentationGenerateSigningKeyPair(EicPresentation* ctx, const char* doc EicCbor cbor; eicCborInit(&cbor, cborBuf, sizeof cborBuf); eicCborAppendArray(&cbor, 2); - eicCborAppendString(&cbor, "ProofOfBinding"); + eicCborAppendStringZ(&cbor, "ProofOfBinding"); eicCborAppendByteString(&cbor, ctx->proofOfProvisioningSha256, EIC_SHA256_DIGEST_SIZE); if (cbor.size > sizeof(cborBuf)) { eicDebug("Exceeded buffer size"); @@ -147,7 +149,7 @@ bool eicPresentationGenerateSigningKeyPair(EicPresentation* ctx, const char* doc } if (!eicOpsEncryptAes128Gcm(ctx->storageKey, nonce, signingKeyPriv, sizeof(signingKeyPriv), // DocType is the additionalAuthenticatedData - (const uint8_t*)docType, eicStrLen(docType), signingKeyBlob)) { + (const uint8_t*)docType, docTypeLength, signingKeyBlob)) { eicDebug("Error encrypting signing key"); return false; } @@ -219,7 +221,7 @@ bool eicPresentationValidateRequestMessage(EicPresentation* ctx, const uint8_t* EicCbor cbor; eicCborInit(&cbor, NULL, 0); eicCborAppendArray(&cbor, 4); - eicCborAppendString(&cbor, "Signature1"); + eicCborAppendStringZ(&cbor, "Signature1"); // The COSE Encoded protected headers is just a single field with // COSE_LABEL_ALG (1) -> coseSignAlg (e.g. -7). For simplicitly we just @@ -277,7 +279,7 @@ bool eicPresentationValidateRequestMessage(EicPresentation* ctx, const uint8_t* // size_t payloadOffset = cbor.size; eicCborBegin(&cbor, EIC_CBOR_MAJOR_TYPE_ARRAY, 3); - eicCborAppendString(&cbor, "ReaderAuthentication"); + eicCborAppendStringZ(&cbor, "ReaderAuthentication"); eicCborAppend(&cbor, sessionTranscript, sessionTranscriptSize); eicCborAppendSemantic(&cbor, EIC_CBOR_SEMANTIC_TAG_ENCODED_CBOR); eicCborBegin(&cbor, EIC_CBOR_MAJOR_TYPE_BYTE_STRING, requestMessageSize); @@ -438,18 +440,18 @@ bool eicPresentationValidateAccessControlProfile(EicPresentation* ctx, int id, size_t readerCertificateSize, bool userAuthenticationRequired, int timeoutMillis, uint64_t secureUserId, const uint8_t mac[28], - bool* accessGranted) { + bool* accessGranted, + uint8_t* scratchSpace, + size_t scratchSpaceSize) { *accessGranted = false; - if (id < 0 || id >= 32) { eicDebug("id value of %d is out of allowed range [0, 32[", id); return false; } // Validate the MAC - uint8_t cborBuffer[EIC_MAX_CBOR_SIZE_FOR_ACCESS_CONTROL_PROFILE]; EicCbor cborBuilder; - eicCborInit(&cborBuilder, cborBuffer, EIC_MAX_CBOR_SIZE_FOR_ACCESS_CONTROL_PROFILE); + eicCborInit(&cborBuilder, scratchSpace, scratchSpaceSize); if (!eicCborCalcAccessControl(&cborBuilder, id, readerCertificate, readerCertificateSize, userAuthenticationRequired, timeoutMillis, secureUserId)) { return false; @@ -464,15 +466,15 @@ bool eicPresentationValidateAccessControlProfile(EicPresentation* ctx, int id, checkUserAuth(ctx, userAuthenticationRequired, timeoutMillis, secureUserId); bool passedReaderAuth = checkReaderAuth(ctx, readerCertificate, readerCertificateSize); - ctx->accessControlProfileMaskValidated |= (1 << id); + ctx->accessControlProfileMaskValidated |= (1U << id); if (readerCertificateSize > 0) { - ctx->accessControlProfileMaskUsesReaderAuth |= (1 << id); + ctx->accessControlProfileMaskUsesReaderAuth |= (1U << id); } if (!passedReaderAuth) { - ctx->accessControlProfileMaskFailedReaderAuth |= (1 << id); + ctx->accessControlProfileMaskFailedReaderAuth |= (1U << id); } if (!passedUserAuth) { - ctx->accessControlProfileMaskFailedUserAuth |= (1 << id); + ctx->accessControlProfileMaskFailedUserAuth |= (1U << id); } if (passedUserAuth && passedReaderAuth) { @@ -486,11 +488,11 @@ bool eicPresentationCalcMacKey(EicPresentation* ctx, const uint8_t* sessionTrans 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 docTypeLength, unsigned int numNamespacesWithValues, size_t expectedDeviceNamespacesSize) { uint8_t signingKeyPriv[EIC_P256_PRIV_KEY_SIZE]; if (!eicOpsDecryptAes128Gcm(ctx->storageKey, signingKeyBlob, 60, (const uint8_t*)docType, - eicStrLen(docType), signingKeyPriv)) { + docTypeLength, signingKeyPriv)) { eicDebug("Error decrypting signingKeyBlob"); return false; } @@ -530,7 +532,7 @@ bool eicPresentationCalcMacKey(EicPresentation* ctx, const uint8_t* sessionTrans // ] // eicCborAppendArray(&ctx->cbor, 4); - eicCborAppendString(&ctx->cbor, "MAC0"); + eicCborAppendStringZ(&ctx->cbor, "MAC0"); // The COSE Encoded protected headers is just a single field with // COSE_LABEL_ALG (1) -> COSE_ALG_HMAC_256_256 (5). For simplicitly we just @@ -566,8 +568,7 @@ bool eicPresentationCalcMacKey(EicPresentation* ctx, const uint8_t* sessionTrans calculatedSize += 1; // "DeviceAuthentication" less than 24 bytes calculatedSize += sizeof("DeviceAuthentication") - 1; // Don't include trailing NUL calculatedSize += sessionTranscriptSize; // Already CBOR encoded - size_t docTypeLen = eicStrLen(docType); - calculatedSize += 1 + eicCborAdditionalLengthBytesFor(docTypeLen) + docTypeLen; + calculatedSize += 1 + eicCborAdditionalLengthBytesFor(docTypeLength) + docTypeLength; calculatedSize += 2; // Semantic tag EIC_CBOR_SEMANTIC_TAG_ENCODED_CBOR (24) calculatedSize += 1 + eicCborAdditionalLengthBytesFor(expectedDeviceNamespacesSize); calculatedSize += expectedDeviceNamespacesSize; @@ -589,9 +590,9 @@ bool eicPresentationCalcMacKey(EicPresentation* ctx, const uint8_t* sessionTrans eicCborBegin(&ctx->cbor, EIC_CBOR_MAJOR_TYPE_BYTE_STRING, calculatedSize); eicCborAppendArray(&ctx->cbor, 4); - eicCborAppendString(&ctx->cbor, "DeviceAuthentication"); + eicCborAppendStringZ(&ctx->cbor, "DeviceAuthentication"); eicCborAppend(&ctx->cbor, sessionTranscript, sessionTranscriptSize); - eicCborAppendString(&ctx->cbor, docType); + eicCborAppendString(&ctx->cbor, docType, docTypeLength); // For the payload, the _encoded_ form follows here. We handle this by simply // opening a bstr, and then writing the CBOR. This requires us to know the @@ -618,16 +619,18 @@ bool eicPresentationStartRetrieveEntries(EicPresentation* ctx) { } EicAccessCheckResult eicPresentationStartRetrieveEntryValue( - EicPresentation* ctx, const char* nameSpace, const char* name, - unsigned int newNamespaceNumEntries, int32_t /* entrySize */, - const int* accessControlProfileIds, size_t numAccessControlProfileIds, + EicPresentation* ctx, const char* nameSpace, size_t nameSpaceLength, + const char* name, size_t nameLength, + unsigned int newNamespaceNumEntries, int32_t entrySize, + const uint8_t* accessControlProfileIds, size_t numAccessControlProfileIds, uint8_t* scratchSpace, size_t scratchSpaceSize) { + (void)entrySize; uint8_t* additionalDataCbor = scratchSpace; - const size_t additionalDataCborBufSize = scratchSpaceSize; + size_t additionalDataCborBufferSize = scratchSpaceSize; size_t additionalDataCborSize; if (newNamespaceNumEntries > 0) { - eicCborAppendString(&ctx->cbor, nameSpace); + eicCborAppendString(&ctx->cbor, nameSpace, nameSpaceLength); eicCborAppendMap(&ctx->cbor, newNamespaceNumEntries); } @@ -636,8 +639,9 @@ EicAccessCheckResult eicPresentationStartRetrieveEntryValue( // ctx->accessCheckOk = false; if (!eicCborCalcEntryAdditionalData(accessControlProfileIds, numAccessControlProfileIds, - nameSpace, name, additionalDataCbor, - additionalDataCborBufSize, &additionalDataCborSize, + nameSpace, nameSpaceLength, name, nameLength, + additionalDataCbor, additionalDataCborBufferSize, + &additionalDataCborSize, ctx->additionalDataSha256)) { return EIC_ACCESS_CHECK_RESULT_FAILED; } @@ -681,7 +685,7 @@ EicAccessCheckResult eicPresentationStartRetrieveEntryValue( eicDebug("Result %d for name %s", result, name); if (result == EIC_ACCESS_CHECK_RESULT_OK) { - eicCborAppendString(&ctx->cbor, name); + eicCborAppendString(&ctx->cbor, name, nameLength); ctx->accessCheckOk = true; } return result; @@ -690,18 +694,21 @@ EicAccessCheckResult eicPresentationStartRetrieveEntryValue( // Note: |content| must be big enough to hold |encryptedContentSize| - 28 bytes. 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, + const char* nameSpace, size_t nameSpaceLength, + const char* name, size_t nameLength, + const uint8_t* accessControlProfileIds, + size_t numAccessControlProfileIds, + uint8_t* scratchSpace, size_t scratchSpaceSize) { uint8_t* additionalDataCbor = scratchSpace; - const size_t additionalDataCborBufSize = scratchSpaceSize; + size_t additionalDataCborBufferSize = scratchSpaceSize; size_t additionalDataCborSize; uint8_t calculatedSha256[EIC_SHA256_DIGEST_SIZE]; if (!eicCborCalcEntryAdditionalData(accessControlProfileIds, numAccessControlProfileIds, - nameSpace, name, additionalDataCbor, - additionalDataCborBufSize, &additionalDataCborSize, + nameSpace, nameSpaceLength, name, nameLength, + additionalDataCbor, additionalDataCborBufferSize, + &additionalDataCborSize, calculatedSha256)) { return false; } @@ -746,9 +753,10 @@ bool eicPresentationFinishRetrieval(EicPresentation* ctx, uint8_t* digestToBeMac return true; } -bool eicPresentationDeleteCredential(EicPresentation* ctx, const char* docType, +bool eicPresentationDeleteCredential(EicPresentation* ctx, const char* docType, size_t docTypeLength, const uint8_t* challenge, size_t challengeSize, - bool includeChallenge, size_t proofOfDeletionCborSize, + bool includeChallenge, + size_t proofOfDeletionCborSize, uint8_t signatureOfToBeSigned[EIC_ECDSA_P256_SIGNATURE_SIZE]) { EicCbor cbor; @@ -766,7 +774,7 @@ bool eicPresentationDeleteCredential(EicPresentation* ctx, const char* docType, // ] // eicCborAppendArray(&cbor, 4); - eicCborAppendString(&cbor, "Signature1"); + eicCborAppendStringZ(&cbor, "Signature1"); // The COSE Encoded protected headers is just a single field with // COSE_LABEL_ALG (1) -> COSE_ALG_ECSDA_256 (-7). For simplicitly we just @@ -787,8 +795,8 @@ bool eicPresentationDeleteCredential(EicPresentation* ctx, const char* docType, // Finally, the CBOR that we're actually signing. eicCborAppendArray(&cbor, includeChallenge ? 4 : 3); - eicCborAppendString(&cbor, "ProofOfDeletion"); - eicCborAppendString(&cbor, docType); + eicCborAppendStringZ(&cbor, "ProofOfDeletion"); + eicCborAppendString(&cbor, docType, docTypeLength); if (includeChallenge) { eicCborAppendByteString(&cbor, challenge, challengeSize); } @@ -804,7 +812,8 @@ bool eicPresentationDeleteCredential(EicPresentation* ctx, const char* docType, return true; } -bool eicPresentationProveOwnership(EicPresentation* ctx, const char* docType, bool testCredential, +bool eicPresentationProveOwnership(EicPresentation* ctx, const char* docType, + size_t docTypeLength, bool testCredential, const uint8_t* challenge, size_t challengeSize, size_t proofOfOwnershipCborSize, uint8_t signatureOfToBeSigned[EIC_ECDSA_P256_SIGNATURE_SIZE]) { @@ -824,7 +833,7 @@ bool eicPresentationProveOwnership(EicPresentation* ctx, const char* docType, bo // ] // eicCborAppendArray(&cbor, 4); - eicCborAppendString(&cbor, "Signature1"); + eicCborAppendStringZ(&cbor, "Signature1"); // The COSE Encoded protected headers is just a single field with // COSE_LABEL_ALG (1) -> COSE_ALG_ECSDA_256 (-7). For simplicitly we just @@ -845,8 +854,8 @@ bool eicPresentationProveOwnership(EicPresentation* ctx, const char* docType, bo // Finally, the CBOR that we're actually signing. eicCborAppendArray(&cbor, 4); - eicCborAppendString(&cbor, "ProofOfOwnership"); - eicCborAppendString(&cbor, docType); + eicCborAppendStringZ(&cbor, "ProofOfOwnership"); + eicCborAppendString(&cbor, docType, docTypeLength); eicCborAppendByteString(&cbor, challenge, challengeSize); eicCborAppendBool(&cbor, testCredential); diff --git a/identity/aidl/default/libeic/EicPresentation.h b/identity/aidl/default/libeic/EicPresentation.h index c888049dbe..6f7f432960 100644 --- a/identity/aidl/default/libeic/EicPresentation.h +++ b/identity/aidl/default/libeic/EicPresentation.h @@ -94,10 +94,11 @@ typedef struct { } EicPresentation; bool eicPresentationInit(EicPresentation* ctx, bool testCredential, const char* docType, - const uint8_t* encryptedCredentialKeys, + size_t docTypeLength, const uint8_t* encryptedCredentialKeys, size_t encryptedCredentialKeysSize); -bool eicPresentationGenerateSigningKeyPair(EicPresentation* ctx, const char* docType, time_t now, +bool eicPresentationGenerateSigningKeyPair(EicPresentation* ctx, const char* docType, + size_t docTypeLength, time_t now, uint8_t* publicKeyCert, size_t* publicKeyCertSize, uint8_t signingKeyBlob[60]); @@ -148,12 +149,17 @@ bool eicPresentationPushReaderCert(EicPresentation* ctx, const uint8_t* certX509 // be called after pushing that certificate using // eicPresentationPushReaderCert(). // +// The scratchSpace should be set to a buffer at least 512 bytes. It's done +// this way to avoid allocating stack space. +// 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); + bool* accessGranted, + uint8_t* scratchSpace, + size_t scratchSpaceSize); // Validates that the given requestMessage is signed by the public key in the // certificate last set with eicPresentationPushReaderCert(). @@ -196,7 +202,7 @@ bool eicPresentationCalcMacKey(EicPresentation* ctx, const uint8_t* sessionTrans 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 docTypeLength, unsigned int numNamespacesWithValues, size_t expectedDeviceNamespacesSize); // The scratchSpace should be set to a buffer at least 512 bytes (ideally 1024 @@ -204,9 +210,11 @@ bool eicPresentationCalcMacKey(EicPresentation* ctx, const uint8_t* sessionTrans // 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); + EicPresentation* ctx, const char* nameSpace, size_t nameSpaceLength, + const char* name, size_t nameLength, + unsigned int newNamespaceNumEntries, int32_t entrySize, + const uint8_t* accessControlProfileIds, size_t numAccessControlProfileIds, + uint8_t* scratchSpace, size_t scratchSpaceSize); // Note: |content| must be big enough to hold |encryptedContentSize| - 28 bytes. // @@ -215,9 +223,11 @@ EicAccessCheckResult eicPresentationStartRetrieveEntryValue( // 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, + const char* nameSpace, size_t nameSpaceLength, + const char* name, size_t nameLength, + const uint8_t* 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 @@ -229,7 +239,7 @@ bool eicPresentationFinishRetrieval(EicPresentation* ctx, uint8_t* digestToBeMac // 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, +bool eicPresentationDeleteCredential(EicPresentation* ctx, const char* docType, size_t docTypeLength, const uint8_t* challenge, size_t challengeSize, bool includeChallenge, size_t proofOfDeletionCborSize, uint8_t signatureOfToBeSigned[EIC_ECDSA_P256_SIGNATURE_SIZE]); @@ -238,8 +248,8 @@ bool eicPresentationDeleteCredential(EicPresentation* ctx, const char* docType, // the ToBeSigned CBOR from RFC 8051 "4.4. Signing and Verification Process" // where content is set to the ProofOfOwnership CBOR. // -bool eicPresentationProveOwnership(EicPresentation* ctx, const char* docType, bool testCredential, - const uint8_t* challenge, size_t challengeSize, +bool eicPresentationProveOwnership(EicPresentation* ctx, const char* docType, size_t docTypeLength, + bool testCredential, const uint8_t* challenge, size_t challengeSize, size_t proofOfOwnershipCborSize, uint8_t signatureOfToBeSigned[EIC_ECDSA_P256_SIGNATURE_SIZE]); diff --git a/identity/aidl/default/libeic/EicProvisioning.c b/identity/aidl/default/libeic/EicProvisioning.c index 3b4148e571..c9df4fd74f 100644 --- a/identity/aidl/default/libeic/EicProvisioning.c +++ b/identity/aidl/default/libeic/EicProvisioning.c @@ -15,6 +15,7 @@ */ #include "EicProvisioning.h" +#include "EicCommon.h" bool eicProvisioningInit(EicProvisioning* ctx, bool testCredential) { eicMemSet(ctx, '\0', sizeof(EicProvisioning)); @@ -27,18 +28,18 @@ bool eicProvisioningInit(EicProvisioning* ctx, bool testCredential) { } bool eicProvisioningInitForUpdate(EicProvisioning* ctx, bool testCredential, const char* docType, - const uint8_t* encryptedCredentialKeys, + size_t docTypeLength, const uint8_t* encryptedCredentialKeys, size_t encryptedCredentialKeysSize) { - uint8_t credentialKeys[86]; + uint8_t credentialKeys[EIC_CREDENTIAL_KEYS_CBOR_SIZE_FEATURE_VERSION_202101]; // 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) { + if (encryptedCredentialKeysSize == EIC_CREDENTIAL_KEYS_CBOR_SIZE_FEATURE_VERSION_202009 + 28) { /* do nothing */ - } else if (encryptedCredentialKeysSize == 86 + 28) { + } else if (encryptedCredentialKeysSize == EIC_CREDENTIAL_KEYS_CBOR_SIZE_FEATURE_VERSION_202101 + 28) { expectPopSha256 = true; } else { eicDebug("Unexpected size %zd for encryptedCredentialKeys", encryptedCredentialKeysSize); @@ -51,7 +52,7 @@ bool eicProvisioningInitForUpdate(EicProvisioning* ctx, bool testCredential, con if (!eicOpsDecryptAes128Gcm(eicOpsGetHardwareBoundKey(testCredential), encryptedCredentialKeys, encryptedCredentialKeysSize, // DocType is the additionalAuthenticatedData - (const uint8_t*)docType, eicStrLen(docType), credentialKeys)) { + (const uint8_t*)docType, docTypeLength, credentialKeys)) { eicDebug("Error decrypting CredentialKeys"); return false; } @@ -114,7 +115,7 @@ bool eicProvisioningCreateCredentialKey(EicProvisioning* ctx, const uint8_t* cha bool eicProvisioningStartPersonalization(EicProvisioning* ctx, int accessControlProfileCount, const int* entryCounts, size_t numEntryCounts, - const char* docType, + const char* docType, size_t docTypeLength, size_t expectedProofOfProvisioningSize) { if (numEntryCounts >= EIC_MAX_NUM_NAMESPACES) { return false; @@ -150,7 +151,7 @@ bool eicProvisioningStartPersonalization(EicProvisioning* ctx, int accessControl // ] // eicCborAppendArray(&ctx->cbor, 4); - eicCborAppendString(&ctx->cbor, "Signature1"); + eicCborAppendStringZ(&ctx->cbor, "Signature1"); // The COSE Encoded protected headers is just a single field with // COSE_LABEL_ALG (1) -> COSE_ALG_ECSDA_256 (-7). For simplicitly we just @@ -174,8 +175,8 @@ bool eicProvisioningStartPersonalization(EicProvisioning* ctx, int accessControl eicCborEnableSecondaryDigesterSha256(&ctx->cbor, &ctx->proofOfProvisioningDigester); eicCborAppendArray(&ctx->cbor, 5); - eicCborAppendString(&ctx->cbor, "ProofOfProvisioning"); - eicCborAppendString(&ctx->cbor, docType); + eicCborAppendStringZ(&ctx->cbor, "ProofOfProvisioning"); + eicCborAppendString(&ctx->cbor, docType, docTypeLength); eicCborAppendArray(&ctx->cbor, accessControlProfileCount); @@ -185,12 +186,12 @@ bool eicProvisioningStartPersonalization(EicProvisioning* ctx, int accessControl bool eicProvisioningAddAccessControlProfile(EicProvisioning* ctx, int id, const uint8_t* readerCertificate, size_t readerCertificateSize, - bool userAuthenticationRequired, uint64_t timeoutMillis, - uint64_t secureUserId, uint8_t outMac[28]) { - uint8_t cborBuffer[EIC_MAX_CBOR_SIZE_FOR_ACCESS_CONTROL_PROFILE]; + bool userAuthenticationRequired, + uint64_t timeoutMillis, uint64_t secureUserId, + uint8_t outMac[28], uint8_t* scratchSpace, + size_t scratchSpaceSize) { EicCbor cborBuilder; - - eicCborInit(&cborBuilder, cborBuffer, EIC_MAX_CBOR_SIZE_FOR_ACCESS_CONTROL_PROFILE); + eicCborInit(&cborBuilder, scratchSpace, scratchSpaceSize); if (!eicCborCalcAccessControl(&cborBuilder, id, readerCertificate, readerCertificateSize, userAuthenticationRequired, timeoutMillis, secureUserId)) { @@ -209,7 +210,7 @@ bool eicProvisioningAddAccessControlProfile(EicProvisioning* ctx, int id, // The ACP CBOR in the provisioning receipt doesn't include secureUserId so build // it again. - eicCborInit(&cborBuilder, cborBuffer, EIC_MAX_CBOR_SIZE_FOR_ACCESS_CONTROL_PROFILE); + eicCborInit(&cborBuilder, scratchSpace, scratchSpaceSize); if (!eicCborCalcAccessControl(&cborBuilder, id, readerCertificate, readerCertificateSize, userAuthenticationRequired, timeoutMillis, 0 /* secureUserId */)) { @@ -222,9 +223,10 @@ bool eicProvisioningAddAccessControlProfile(EicProvisioning* ctx, int id, return true; } -bool eicProvisioningBeginAddEntry(EicProvisioning* ctx, const int* accessControlProfileIds, +bool eicProvisioningBeginAddEntry(EicProvisioning* ctx, const uint8_t* accessControlProfileIds, size_t numAccessControlProfileIds, const char* nameSpace, - const char* name, uint64_t entrySize, uint8_t* scratchSpace, + size_t nameSpaceLength, const char* name, size_t nameLength, + uint64_t entrySize, uint8_t* scratchSpace, size_t scratchSpaceSize) { uint8_t* additionalDataCbor = scratchSpace; const size_t additionalDataCborBufSize = scratchSpaceSize; @@ -233,9 +235,9 @@ bool eicProvisioningBeginAddEntry(EicProvisioning* ctx, const int* accessControl // We'll need to calc and store a digest of additionalData to check that it's the same // additionalData being passed in for every eicProvisioningAddEntryValue() call... if (!eicCborCalcEntryAdditionalData(accessControlProfileIds, numAccessControlProfileIds, - nameSpace, name, additionalDataCbor, - additionalDataCborBufSize, &additionalDataCborSize, - ctx->additionalDataSha256)) { + nameSpace, nameSpaceLength, name, nameLength, + additionalDataCbor, additionalDataCborBufSize, + &additionalDataCborSize, ctx->additionalDataSha256)) { return false; } @@ -244,7 +246,7 @@ bool eicProvisioningBeginAddEntry(EicProvisioning* ctx, const int* accessControl ctx->curNamespaceNumProcessed = 0; // Opens the main map: { * Namespace => [ + Entry ] } eicCborAppendMap(&ctx->cbor, ctx->numEntryCounts); - eicCborAppendString(&ctx->cbor, nameSpace); + eicCborAppendString(&ctx->cbor, nameSpace, nameSpaceLength); // Opens the per-namespace array: [ + Entry ] eicCborAppendArray(&ctx->cbor, ctx->entryCounts[ctx->curNamespace]); } @@ -252,37 +254,39 @@ bool eicProvisioningBeginAddEntry(EicProvisioning* ctx, const int* accessControl if (ctx->curNamespaceNumProcessed == ctx->entryCounts[ctx->curNamespace]) { ctx->curNamespace += 1; ctx->curNamespaceNumProcessed = 0; - eicCborAppendString(&ctx->cbor, nameSpace); + eicCborAppendString(&ctx->cbor, nameSpace, nameSpaceLength); // Opens the per-namespace array: [ + Entry ] eicCborAppendArray(&ctx->cbor, ctx->entryCounts[ctx->curNamespace]); } eicCborAppendMap(&ctx->cbor, 3); - eicCborAppendString(&ctx->cbor, "name"); - eicCborAppendString(&ctx->cbor, name); + eicCborAppendStringZ(&ctx->cbor, "name"); + eicCborAppendString(&ctx->cbor, name, nameLength); ctx->curEntrySize = entrySize; ctx->curEntryNumBytesReceived = 0; - eicCborAppendString(&ctx->cbor, "value"); + eicCborAppendStringZ(&ctx->cbor, "value"); ctx->curNamespaceNumProcessed += 1; return true; } -bool eicProvisioningAddEntryValue(EicProvisioning* ctx, const int* accessControlProfileIds, +bool eicProvisioningAddEntryValue(EicProvisioning* ctx, const uint8_t* accessControlProfileIds, size_t numAccessControlProfileIds, const char* nameSpace, - const char* name, const uint8_t* content, size_t contentSize, + size_t nameSpaceLength, const char* name, size_t nameLength, + const uint8_t* content, size_t contentSize, uint8_t* outEncryptedContent, uint8_t* scratchSpace, size_t scratchSpaceSize) { uint8_t* additionalDataCbor = scratchSpace; const size_t additionalDataCborBufSize = scratchSpaceSize; size_t additionalDataCborSize; - uint8_t calculatedSha256[EIC_SHA256_DIGEST_SIZE]; + if (!eicCborCalcEntryAdditionalData(accessControlProfileIds, numAccessControlProfileIds, - nameSpace, name, additionalDataCbor, - additionalDataCborBufSize, &additionalDataCborSize, + nameSpace, nameSpaceLength, name, nameLength, + additionalDataCbor, additionalDataCborBufSize, + &additionalDataCborSize, calculatedSha256)) { return false; } @@ -305,7 +309,7 @@ bool eicProvisioningAddEntryValue(EicProvisioning* ctx, const int* accessControl // If done with this entry, close the map ctx->curEntryNumBytesReceived += contentSize; if (ctx->curEntryNumBytesReceived == ctx->curEntrySize) { - eicCborAppendString(&ctx->cbor, "accessControlProfiles"); + eicCborAppendStringZ(&ctx->cbor, "accessControlProfiles"); eicCborAppendArray(&ctx->cbor, numAccessControlProfileIds); for (size_t n = 0; n < numAccessControlProfileIds; n++) { eicCborAppendNumber(&ctx->cbor, accessControlProfileIds[n]); @@ -337,6 +341,7 @@ bool eicProvisioningFinishAddingEntries( } bool eicProvisioningFinishGetCredentialData(EicProvisioning* ctx, const char* docType, + size_t docTypeLength, uint8_t* encryptedCredentialKeys, size_t* encryptedCredentialKeysSize) { EicCbor cbor; @@ -367,7 +372,7 @@ bool eicProvisioningFinishGetCredentialData(EicProvisioning* ctx, const char* do if (!eicOpsEncryptAes128Gcm( eicOpsGetHardwareBoundKey(ctx->testCredential), nonce, cborBuf, cbor.size, // DocType is the additionalAuthenticatedData - (const uint8_t*)docType, eicStrLen(docType), encryptedCredentialKeys)) { + (const uint8_t*)docType, docTypeLength, encryptedCredentialKeys)) { eicDebug("Error encrypting CredentialKeys"); return false; } diff --git a/identity/aidl/default/libeic/EicProvisioning.h b/identity/aidl/default/libeic/EicProvisioning.h index f064787b1b..92f1e4a2a0 100644 --- a/identity/aidl/default/libeic/EicProvisioning.h +++ b/identity/aidl/default/libeic/EicProvisioning.h @@ -65,7 +65,7 @@ typedef struct { bool eicProvisioningInit(EicProvisioning* ctx, bool testCredential); bool eicProvisioningInitForUpdate(EicProvisioning* ctx, bool testCredential, const char* docType, - const uint8_t* encryptedCredentialKeys, + size_t docTypeLength, const uint8_t* encryptedCredentialKeys, size_t encryptedCredentialKeysSize); bool eicProvisioningCreateCredentialKey(EicProvisioning* ctx, const uint8_t* challenge, @@ -75,21 +75,27 @@ bool eicProvisioningCreateCredentialKey(EicProvisioning* ctx, const uint8_t* cha bool eicProvisioningStartPersonalization(EicProvisioning* ctx, int accessControlProfileCount, const int* entryCounts, size_t numEntryCounts, - const char* docType, + const char* docType, size_t docTypeLength, size_t expectedProofOfProvisioningingSize); +// The scratchSpace should be set to a buffer at least 512 bytes. It's done this way to +// avoid allocating stack space. +// bool eicProvisioningAddAccessControlProfile(EicProvisioning* ctx, int id, const uint8_t* readerCertificate, size_t readerCertificateSize, - bool userAuthenticationRequired, uint64_t timeoutMillis, - uint64_t secureUserId, uint8_t outMac[28]); + bool userAuthenticationRequired, + uint64_t timeoutMillis, uint64_t secureUserId, + uint8_t outMac[28], uint8_t* scratchSpace, + size_t scratchSpaceSize); // The scratchSpace should be set to a buffer at least 512 bytes. It's done this way to // avoid allocating stack space. // -bool eicProvisioningBeginAddEntry(EicProvisioning* ctx, const int* accessControlProfileIds, +bool eicProvisioningBeginAddEntry(EicProvisioning* ctx, const uint8_t* accessControlProfileIds, size_t numAccessControlProfileIds, const char* nameSpace, - const char* name, uint64_t entrySize, uint8_t* scratchSpace, + size_t nameSpaceLength, const char* name, size_t nameLength, + uint64_t entrySize, uint8_t* scratchSpace, size_t scratchSpaceSize); // The outEncryptedContent array must be contentSize + 28 bytes long. @@ -97,9 +103,10 @@ bool eicProvisioningBeginAddEntry(EicProvisioning* ctx, const int* accessControl // The scratchSpace should be set to a buffer at least 512 bytes. It's done this way to // avoid allocating stack space. // -bool eicProvisioningAddEntryValue(EicProvisioning* ctx, const int* accessControlProfileIds, +bool eicProvisioningAddEntryValue(EicProvisioning* ctx, const uint8_t* accessControlProfileIds, size_t numAccessControlProfileIds, const char* nameSpace, - const char* name, const uint8_t* content, size_t contentSize, + size_t nameSpaceLength, const char* name, size_t nameLength, + const uint8_t* content, size_t contentSize, uint8_t* outEncryptedContent, uint8_t* scratchSpace, size_t scratchSpaceSize); @@ -128,6 +135,7 @@ bool eicProvisioningFinishAddingEntries( // |encryptedCredentialKeys| will be no longer than 86 + 28 = 114 bytes. // bool eicProvisioningFinishGetCredentialData(EicProvisioning* ctx, const char* docType, + size_t docTypeLength, uint8_t* encryptedCredentialKeys, size_t* encryptedCredentialKeysSize); diff --git a/identity/aidl/default/libeic/libeic.h b/identity/aidl/default/libeic/libeic.h index 88abef808f..20c889660f 100644 --- a/identity/aidl/default/libeic/libeic.h +++ b/identity/aidl/default/libeic/libeic.h @@ -30,6 +30,7 @@ extern "C" { #include "EicOps.h" #include "EicPresentation.h" #include "EicProvisioning.h" +#include "EicCommon.h" #undef EIC_INSIDE_LIBEIC_H #ifdef __cplusplus |