Loading identity/aidl/android/hardware/identity/IIdentityCredential.aidl +10 −9 Original line number Diff line number Diff line Loading @@ -55,7 +55,7 @@ interface IIdentityCredential { * This method may only be called once per instance. If called more than once, STATUS_FAILED * will be returned. * * @return the unencrypted key-pair in PKCS#8 format. * @return the private key, in DER format as specified in RFC 5915. */ byte[] createEphemeralKeyPair(); Loading Loading @@ -88,10 +88,10 @@ interface IIdentityCredential { * The setRequestedNamespaces() and setVerificationToken() methods will be called before * this method is called. * * This method be called after createEphemeralKeyPair(), setReaderEphemeralPublicKey(), * createAuthChallenge() and before startRetrieveEntry(). This method call is followed by * multiple calls of startRetrieveEntryValue(), retrieveEntryValue(), and finally * finishRetrieval(). * This method is called after createEphemeralKeyPair(), setReaderEphemeralPublicKey(), * createAuthChallenge() (note that those calls are optional) and before startRetrieveEntry(). * This method call is followed by multiple calls of startRetrieveEntryValue(), * retrieveEntryValue(), and finally finishRetrieval(). * * It is permissible to perform data retrievals multiple times using the same instance (e.g. * startRetrieval(), then multiple calls of startRetrieveEntryValue(), retrieveEntryValue(), Loading Loading @@ -343,12 +343,13 @@ interface IIdentityCredential { * * - signature: must be set to ECDSA. * * - subject: CN shall be set to "Android Identity Credential Authentication Key". * - subject: CN shall be set to "Android Identity Credential Authentication Key". (fixed * value: same on all certs) * * - issuer: shall be set to "credentialStoreName (credentialStoreAuthorName)" using the * values returned in HardwareInformation. * - issuer: CN shall be set to "Android Identity Credential Key". (fixed value: * same on all certs) * * - validity: should be from current time and one year in the future. * - validity: should be from current time and one year in the future (365 days). * * - subjectPublicKeyInfo: must contain attested public key. * Loading identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl +19 −20 Original line number Diff line number Diff line Loading @@ -37,12 +37,12 @@ interface IWritableIdentityCredential { * * - signature: must be set to ECDSA. * * - subject: CN shall be set to "Android Identity Credential Key". * - subject: CN shall be set to "Android Identity Credential Key". (fixed value: * same on all certs) * * - issuer: shall be set to "credentialStoreName (credentialStoreAuthorName)" using the * values returned in HardwareInformation. * - issuer: Same as the subject field of the batch attestation key. * * - validity: should be from current time and expire at the same time as the * - validity: Should be set to current time and expire at the same time as the * attestation batch certificate used. * * - subjectPublicKeyInfo: must contain attested public key. Loading @@ -55,19 +55,14 @@ interface IWritableIdentityCredential { * * - The attestationSecurityLevel field must be set to either Software (0), * TrustedEnvironment (1), or StrongBox (2) depending on how attestation is * implemented. Only the default AOSP implementation of this HAL may use * value 0 (additionally, this implementation must not be used on production * devices). * implemented. * * - The keymasterVersion field in the attestation extension must be set to (10*major + minor) * where major and minor are the Identity Credential interface major and minor versions. * Specifically for this version of the interface (1.0) this value is 10. * - The keymasterVersion field in the attestation extension must be set to the. * same value as used for Android Keystore keys. * * - The keymasterSecurityLevel field in the attestation extension must be set to * either Software (0), TrustedEnvironment (1), or StrongBox (2) depending on how * the Trusted Application backing the HAL implementation is implemented. Only * the default AOSP implementation of this HAL may use value 0 (additionally, this * implementation must not be used on production devices) * the Trusted Application backing the HAL implementation is implemented. * * - The attestationChallenge field must be set to the passed-in challenge. * Loading @@ -81,7 +76,8 @@ interface IWritableIdentityCredential { * * - Tag::IDENTITY_CREDENTIAL_KEY which indicates that the key is an Identity * Credential key (which can only sign/MAC very specific messages) and not an Android * Keystore key (which can be used to sign/MAC anything). * Keystore key (which can be used to sign/MAC anything). This must not be set * for test credentials. * * - Tag::PURPOSE must be set to SIGN * Loading @@ -95,10 +91,13 @@ interface IWritableIdentityCredential { * * - Tag::EC_CURVE must be set to P_256 * * Additional authorizations may be needed in the softwareEnforced and teeEnforced * fields - the above is not an exhaustive list. Specifically, authorizations containing * information about the root of trust, OS version, verified boot state, and so on should * be included. * - Tag::ROOT_OF_TRUST must be set * * - Tag::OS_VERSION and Tag::OS_PATCHLEVEL must be set * * Additional authorizations may be appear in the softwareEnforced and teeEnforced * fields. For example if the device has a boot or vendor partitions, then BOOT_PATCHLEVEL * and VENDOR_PATCHLEVEL should be set. * * Since the chain is required to be generated using Keymaster Attestation, the returned * certificate chain has the following properties: Loading @@ -112,8 +111,8 @@ interface IWritableIdentityCredential { * As with any user of attestation, the Issuing Authority (as a relying party) wishing * to issue a credential to a device using these APIs, must carefully examine the * returned certificate chain for all of the above (and more). In particular, the Issuing * Authority should check the root of trust, verified boot state, patch level, * application id, etc. * Authority should check the root of trust (which include verified boot state), patch level, * attestation application id, etc. * * This all depends on the needs of the Issuing Authority and the kind of credential but * in general an Issuing Authority should never issue a credential to a device without Loading identity/aidl/default/IdentityCredential.cpp +12 −34 Original line number Diff line number Diff line Loading @@ -272,6 +272,7 @@ ndk::ScopedAStatus IdentityCredential::startRetrieval( const HardwareAuthToken& authToken, const vector<uint8_t>& itemsRequest, const vector<uint8_t>& signingKeyBlob, const vector<uint8_t>& sessionTranscript, const vector<uint8_t>& readerSignature, const vector<int32_t>& requestCounts) { std::unique_ptr<cppbor::Item> sessionTranscriptItem; if (sessionTranscript.size() > 0) { auto [item, _, message] = cppbor::parse(sessionTranscript); if (item == nullptr) { Loading @@ -279,7 +280,7 @@ ndk::ScopedAStatus IdentityCredential::startRetrieval( IIdentityCredentialStore::STATUS_INVALID_DATA, "SessionTranscript contains invalid CBOR")); } sessionTranscriptItem_ = std::move(item); sessionTranscriptItem = std::move(item); } if (numStartRetrievalCalls_ > 0) { if (sessionTranscript_ != sessionTranscript) { Loading Loading @@ -319,7 +320,7 @@ ndk::ScopedAStatus IdentityCredential::startRetrieval( vector<uint8_t> encodedReaderAuthentication = cppbor::Array() .add("ReaderAuthentication") .add(sessionTranscriptItem_->clone()) .add(std::move(sessionTranscriptItem)) .add(cppbor::Semantic(24, itemsRequestBytes)) .encode(); vector<uint8_t> encodedReaderAuthenticationBytes = Loading Loading @@ -776,13 +777,6 @@ ndk::ScopedAStatus IdentityCredential::finishRetrieval(vector<uint8_t>* outMac, optional<vector<uint8_t>> mac; if (signingKeyBlob_.size() > 0 && sessionTranscript_.size() > 0 && readerPublicKey_.size() > 0) { cppbor::Array array; array.add("DeviceAuthentication"); array.add(sessionTranscriptItem_->clone()); array.add(docType_); array.add(cppbor::Semantic(24, encodedDeviceNameSpaces)); vector<uint8_t> deviceAuthenticationBytes = cppbor::Semantic(24, array.encode()).encode(); vector<uint8_t> docTypeAsBlob(docType_.begin(), docType_.end()); optional<vector<uint8_t>> signingKey = support::decryptAes128Gcm(storageKey_, signingKeyBlob_, docTypeAsBlob); Loading @@ -792,31 +786,15 @@ ndk::ScopedAStatus IdentityCredential::finishRetrieval(vector<uint8_t>* outMac, "Error decrypting signingKeyBlob")); } optional<vector<uint8_t>> sharedSecret = support::ecdh(readerPublicKey_, signingKey.value()); if (!sharedSecret) { return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage( IIdentityCredentialStore::STATUS_FAILED, "Error doing ECDH")); } // Mix-in SessionTranscriptBytes vector<uint8_t> sessionTranscriptBytes = cppbor::Semantic(24, sessionTranscript_).encode(); vector<uint8_t> sharedSecretWithSessionTranscriptBytes = sharedSecret.value(); std::copy(sessionTranscriptBytes.begin(), sessionTranscriptBytes.end(), std::back_inserter(sharedSecretWithSessionTranscriptBytes)); vector<uint8_t> salt = {0x00}; vector<uint8_t> info = {}; optional<vector<uint8_t>> derivedKey = support::hkdf(sharedSecretWithSessionTranscriptBytes, salt, info, 32); if (!derivedKey) { optional<vector<uint8_t>> eMacKey = support::calcEMacKey(signingKey.value(), readerPublicKey_, sessionTranscriptBytes); if (!eMacKey) { return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage( IIdentityCredentialStore::STATUS_FAILED, "Error deriving key from shared secret")); IIdentityCredentialStore::STATUS_FAILED, "Error calculating EMacKey")); } mac = support::coseMac0(derivedKey.value(), {}, // payload deviceAuthenticationBytes); // detached content mac = support::calcMac(sessionTranscript_, docType_, encodedDeviceNameSpaces, eMacKey.value()); if (!mac) { return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage( IIdentityCredentialStore::STATUS_FAILED, "Error MACing data")); Loading @@ -830,9 +808,9 @@ ndk::ScopedAStatus IdentityCredential::finishRetrieval(vector<uint8_t>* outMac, ndk::ScopedAStatus IdentityCredential::generateSigningKeyPair( vector<uint8_t>* outSigningKeyBlob, Certificate* outSigningKeyCertificate) { string serialDecimal = "0"; // TODO: set serial to something unique string issuer = "Android Open Source Project"; string subject = "Android IdentityCredential Reference Implementation"; string serialDecimal = "1"; string issuer = "Android Identity Credential Key"; string subject = "Android Identity Credential Authentication Key"; time_t validityNotBefore = time(nullptr); time_t validityNotAfter = validityNotBefore + 365 * 24 * 3600; Loading identity/aidl/default/IdentityCredential.h +0 −1 Original line number Diff line number Diff line Loading @@ -103,7 +103,6 @@ class IdentityCredential : public BnIdentityCredential { map<int32_t, int> profileIdToAccessCheckResult_; vector<uint8_t> signingKeyBlob_; vector<uint8_t> sessionTranscript_; std::unique_ptr<cppbor::Item> sessionTranscriptItem_; vector<uint8_t> itemsRequest_; vector<int32_t> requestCountsRemaining_; map<string, set<string>> requestedNameSpacesAndNames_; Loading identity/aidl/default/WritableIdentityCredential.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -74,7 +74,7 @@ ndk::ScopedAStatus WritableIdentityCredential::getAttestationCertificate( vector<uint8_t> appId(attestationApplicationId.begin(), attestationApplicationId.end()); optional<std::pair<vector<uint8_t>, vector<vector<uint8_t>>>> keyAttestationPair = support::createEcKeyPairAndAttestation(challenge, appId); support::createEcKeyPairAndAttestation(challenge, appId, testCredential_); if (!keyAttestationPair) { LOG(ERROR) << "Error creating credentialKey and attestation"; return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage( Loading Loading
identity/aidl/android/hardware/identity/IIdentityCredential.aidl +10 −9 Original line number Diff line number Diff line Loading @@ -55,7 +55,7 @@ interface IIdentityCredential { * This method may only be called once per instance. If called more than once, STATUS_FAILED * will be returned. * * @return the unencrypted key-pair in PKCS#8 format. * @return the private key, in DER format as specified in RFC 5915. */ byte[] createEphemeralKeyPair(); Loading Loading @@ -88,10 +88,10 @@ interface IIdentityCredential { * The setRequestedNamespaces() and setVerificationToken() methods will be called before * this method is called. * * This method be called after createEphemeralKeyPair(), setReaderEphemeralPublicKey(), * createAuthChallenge() and before startRetrieveEntry(). This method call is followed by * multiple calls of startRetrieveEntryValue(), retrieveEntryValue(), and finally * finishRetrieval(). * This method is called after createEphemeralKeyPair(), setReaderEphemeralPublicKey(), * createAuthChallenge() (note that those calls are optional) and before startRetrieveEntry(). * This method call is followed by multiple calls of startRetrieveEntryValue(), * retrieveEntryValue(), and finally finishRetrieval(). * * It is permissible to perform data retrievals multiple times using the same instance (e.g. * startRetrieval(), then multiple calls of startRetrieveEntryValue(), retrieveEntryValue(), Loading Loading @@ -343,12 +343,13 @@ interface IIdentityCredential { * * - signature: must be set to ECDSA. * * - subject: CN shall be set to "Android Identity Credential Authentication Key". * - subject: CN shall be set to "Android Identity Credential Authentication Key". (fixed * value: same on all certs) * * - issuer: shall be set to "credentialStoreName (credentialStoreAuthorName)" using the * values returned in HardwareInformation. * - issuer: CN shall be set to "Android Identity Credential Key". (fixed value: * same on all certs) * * - validity: should be from current time and one year in the future. * - validity: should be from current time and one year in the future (365 days). * * - subjectPublicKeyInfo: must contain attested public key. * Loading
identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl +19 −20 Original line number Diff line number Diff line Loading @@ -37,12 +37,12 @@ interface IWritableIdentityCredential { * * - signature: must be set to ECDSA. * * - subject: CN shall be set to "Android Identity Credential Key". * - subject: CN shall be set to "Android Identity Credential Key". (fixed value: * same on all certs) * * - issuer: shall be set to "credentialStoreName (credentialStoreAuthorName)" using the * values returned in HardwareInformation. * - issuer: Same as the subject field of the batch attestation key. * * - validity: should be from current time and expire at the same time as the * - validity: Should be set to current time and expire at the same time as the * attestation batch certificate used. * * - subjectPublicKeyInfo: must contain attested public key. Loading @@ -55,19 +55,14 @@ interface IWritableIdentityCredential { * * - The attestationSecurityLevel field must be set to either Software (0), * TrustedEnvironment (1), or StrongBox (2) depending on how attestation is * implemented. Only the default AOSP implementation of this HAL may use * value 0 (additionally, this implementation must not be used on production * devices). * implemented. * * - The keymasterVersion field in the attestation extension must be set to (10*major + minor) * where major and minor are the Identity Credential interface major and minor versions. * Specifically for this version of the interface (1.0) this value is 10. * - The keymasterVersion field in the attestation extension must be set to the. * same value as used for Android Keystore keys. * * - The keymasterSecurityLevel field in the attestation extension must be set to * either Software (0), TrustedEnvironment (1), or StrongBox (2) depending on how * the Trusted Application backing the HAL implementation is implemented. Only * the default AOSP implementation of this HAL may use value 0 (additionally, this * implementation must not be used on production devices) * the Trusted Application backing the HAL implementation is implemented. * * - The attestationChallenge field must be set to the passed-in challenge. * Loading @@ -81,7 +76,8 @@ interface IWritableIdentityCredential { * * - Tag::IDENTITY_CREDENTIAL_KEY which indicates that the key is an Identity * Credential key (which can only sign/MAC very specific messages) and not an Android * Keystore key (which can be used to sign/MAC anything). * Keystore key (which can be used to sign/MAC anything). This must not be set * for test credentials. * * - Tag::PURPOSE must be set to SIGN * Loading @@ -95,10 +91,13 @@ interface IWritableIdentityCredential { * * - Tag::EC_CURVE must be set to P_256 * * Additional authorizations may be needed in the softwareEnforced and teeEnforced * fields - the above is not an exhaustive list. Specifically, authorizations containing * information about the root of trust, OS version, verified boot state, and so on should * be included. * - Tag::ROOT_OF_TRUST must be set * * - Tag::OS_VERSION and Tag::OS_PATCHLEVEL must be set * * Additional authorizations may be appear in the softwareEnforced and teeEnforced * fields. For example if the device has a boot or vendor partitions, then BOOT_PATCHLEVEL * and VENDOR_PATCHLEVEL should be set. * * Since the chain is required to be generated using Keymaster Attestation, the returned * certificate chain has the following properties: Loading @@ -112,8 +111,8 @@ interface IWritableIdentityCredential { * As with any user of attestation, the Issuing Authority (as a relying party) wishing * to issue a credential to a device using these APIs, must carefully examine the * returned certificate chain for all of the above (and more). In particular, the Issuing * Authority should check the root of trust, verified boot state, patch level, * application id, etc. * Authority should check the root of trust (which include verified boot state), patch level, * attestation application id, etc. * * This all depends on the needs of the Issuing Authority and the kind of credential but * in general an Issuing Authority should never issue a credential to a device without Loading
identity/aidl/default/IdentityCredential.cpp +12 −34 Original line number Diff line number Diff line Loading @@ -272,6 +272,7 @@ ndk::ScopedAStatus IdentityCredential::startRetrieval( const HardwareAuthToken& authToken, const vector<uint8_t>& itemsRequest, const vector<uint8_t>& signingKeyBlob, const vector<uint8_t>& sessionTranscript, const vector<uint8_t>& readerSignature, const vector<int32_t>& requestCounts) { std::unique_ptr<cppbor::Item> sessionTranscriptItem; if (sessionTranscript.size() > 0) { auto [item, _, message] = cppbor::parse(sessionTranscript); if (item == nullptr) { Loading @@ -279,7 +280,7 @@ ndk::ScopedAStatus IdentityCredential::startRetrieval( IIdentityCredentialStore::STATUS_INVALID_DATA, "SessionTranscript contains invalid CBOR")); } sessionTranscriptItem_ = std::move(item); sessionTranscriptItem = std::move(item); } if (numStartRetrievalCalls_ > 0) { if (sessionTranscript_ != sessionTranscript) { Loading Loading @@ -319,7 +320,7 @@ ndk::ScopedAStatus IdentityCredential::startRetrieval( vector<uint8_t> encodedReaderAuthentication = cppbor::Array() .add("ReaderAuthentication") .add(sessionTranscriptItem_->clone()) .add(std::move(sessionTranscriptItem)) .add(cppbor::Semantic(24, itemsRequestBytes)) .encode(); vector<uint8_t> encodedReaderAuthenticationBytes = Loading Loading @@ -776,13 +777,6 @@ ndk::ScopedAStatus IdentityCredential::finishRetrieval(vector<uint8_t>* outMac, optional<vector<uint8_t>> mac; if (signingKeyBlob_.size() > 0 && sessionTranscript_.size() > 0 && readerPublicKey_.size() > 0) { cppbor::Array array; array.add("DeviceAuthentication"); array.add(sessionTranscriptItem_->clone()); array.add(docType_); array.add(cppbor::Semantic(24, encodedDeviceNameSpaces)); vector<uint8_t> deviceAuthenticationBytes = cppbor::Semantic(24, array.encode()).encode(); vector<uint8_t> docTypeAsBlob(docType_.begin(), docType_.end()); optional<vector<uint8_t>> signingKey = support::decryptAes128Gcm(storageKey_, signingKeyBlob_, docTypeAsBlob); Loading @@ -792,31 +786,15 @@ ndk::ScopedAStatus IdentityCredential::finishRetrieval(vector<uint8_t>* outMac, "Error decrypting signingKeyBlob")); } optional<vector<uint8_t>> sharedSecret = support::ecdh(readerPublicKey_, signingKey.value()); if (!sharedSecret) { return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage( IIdentityCredentialStore::STATUS_FAILED, "Error doing ECDH")); } // Mix-in SessionTranscriptBytes vector<uint8_t> sessionTranscriptBytes = cppbor::Semantic(24, sessionTranscript_).encode(); vector<uint8_t> sharedSecretWithSessionTranscriptBytes = sharedSecret.value(); std::copy(sessionTranscriptBytes.begin(), sessionTranscriptBytes.end(), std::back_inserter(sharedSecretWithSessionTranscriptBytes)); vector<uint8_t> salt = {0x00}; vector<uint8_t> info = {}; optional<vector<uint8_t>> derivedKey = support::hkdf(sharedSecretWithSessionTranscriptBytes, salt, info, 32); if (!derivedKey) { optional<vector<uint8_t>> eMacKey = support::calcEMacKey(signingKey.value(), readerPublicKey_, sessionTranscriptBytes); if (!eMacKey) { return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage( IIdentityCredentialStore::STATUS_FAILED, "Error deriving key from shared secret")); IIdentityCredentialStore::STATUS_FAILED, "Error calculating EMacKey")); } mac = support::coseMac0(derivedKey.value(), {}, // payload deviceAuthenticationBytes); // detached content mac = support::calcMac(sessionTranscript_, docType_, encodedDeviceNameSpaces, eMacKey.value()); if (!mac) { return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage( IIdentityCredentialStore::STATUS_FAILED, "Error MACing data")); Loading @@ -830,9 +808,9 @@ ndk::ScopedAStatus IdentityCredential::finishRetrieval(vector<uint8_t>* outMac, ndk::ScopedAStatus IdentityCredential::generateSigningKeyPair( vector<uint8_t>* outSigningKeyBlob, Certificate* outSigningKeyCertificate) { string serialDecimal = "0"; // TODO: set serial to something unique string issuer = "Android Open Source Project"; string subject = "Android IdentityCredential Reference Implementation"; string serialDecimal = "1"; string issuer = "Android Identity Credential Key"; string subject = "Android Identity Credential Authentication Key"; time_t validityNotBefore = time(nullptr); time_t validityNotAfter = validityNotBefore + 365 * 24 * 3600; Loading
identity/aidl/default/IdentityCredential.h +0 −1 Original line number Diff line number Diff line Loading @@ -103,7 +103,6 @@ class IdentityCredential : public BnIdentityCredential { map<int32_t, int> profileIdToAccessCheckResult_; vector<uint8_t> signingKeyBlob_; vector<uint8_t> sessionTranscript_; std::unique_ptr<cppbor::Item> sessionTranscriptItem_; vector<uint8_t> itemsRequest_; vector<int32_t> requestCountsRemaining_; map<string, set<string>> requestedNameSpacesAndNames_; Loading
identity/aidl/default/WritableIdentityCredential.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -74,7 +74,7 @@ ndk::ScopedAStatus WritableIdentityCredential::getAttestationCertificate( vector<uint8_t> appId(attestationApplicationId.begin(), attestationApplicationId.end()); optional<std::pair<vector<uint8_t>, vector<vector<uint8_t>>>> keyAttestationPair = support::createEcKeyPairAndAttestation(challenge, appId); support::createEcKeyPairAndAttestation(challenge, appId, testCredential_); if (!keyAttestationPair) { LOG(ERROR) << "Error creating credentialKey and attestation"; return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage( Loading