Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 55f62fc1 authored by David Zeuthen's avatar David Zeuthen
Browse files

identity: Add support for ECDSA auth and don't require session encryption.

This adds a new method which allows applications to use mdoc ECDSA
authentication instead of mdoc MAC authentication. Additionally, also
relax requirements on SessionTranscript so the APIs can be used even
when mdoc session encryption isn't being used.

Bug: 241912421
Test: atest VtsHalIdentityTargetTest
Test: atest android.security.identity.cts

Change-Id: I25336f1352102208887531d066ec432a9ae3cd36
parent 9375c9ce
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -37682,6 +37682,7 @@ package android.security.identity {
  public abstract class CredentialDataResult {
    method @Nullable public abstract byte[] getDeviceMac();
    method @NonNull public abstract byte[] getDeviceNameSpaces();
    method @Nullable public byte[] getDeviceSignature();
    method @NonNull public abstract android.security.identity.CredentialDataResult.Entries getDeviceSignedEntries();
    method @NonNull public abstract android.security.identity.CredentialDataResult.Entries getIssuerSignedEntries();
    method @NonNull public abstract byte[] getStaticAuthenticationData();
+24 −0
Original line number Diff line number Diff line
@@ -105,6 +105,30 @@ public abstract class CredentialDataResult {
     */
    public abstract @Nullable byte[] getDeviceMac();

    /**
     * Returns a signature over the {@code DeviceAuthenticationBytes} CBOR
     * specified in {@link #getDeviceNameSpaces()}, to prove to the reader that the data
     * is from a trusted credential.
     *
     * <p>The signature is made using the authentication private key. See section 9.1.3.4 of
     * ISO/IEC 18013-5:2021 for details of this operation.
     *
     * <p>If the session transcript or reader ephemeral key wasn't set on the {@link
     * PresentationSession} used to obtain this data no signature will be produced and this method
     * will return {@code null}.
     *
     * <p>This is only implemented in feature version 202301 or later. If not implemented, the call
     * fails with {@link UnsupportedOperationException}. See
     * {@link android.content.pm.PackageManager#FEATURE_IDENTITY_CREDENTIAL_HARDWARE} for known
     * feature versions.
     *
     * @return A COSE_Sign1 structure as described above or {@code null} if the conditions
     *     specified above are not met.
     */
    public @Nullable byte[] getDeviceSignature() {
        throw new UnsupportedOperationException();
    }

    /**
     * Returns the static authentication data associated with the dynamic authentication
     * key used to MAC the data returned by {@link #getDeviceNameSpaces()}.
+5 −0
Original line number Diff line number Diff line
@@ -46,6 +46,11 @@ class CredstoreCredentialDataResult extends CredentialDataResult {
        return mDeviceSignedResult.getMessageAuthenticationCode();
    }

    @Override
    public @Nullable byte[] getDeviceSignature() {
        return mDeviceSignedResult.getSignature();
    }

    @Override
    public @NonNull byte[] getStaticAuthenticationData() {
        return mDeviceSignedResult.getStaticAuthenticationData();
+11 −2
Original line number Diff line number Diff line
@@ -60,16 +60,19 @@ class CredstoreIdentityCredential extends IdentityCredential {
    private Context mContext;
    private ICredential mBinder;
    private CredstorePresentationSession mSession;
    private int mFeatureVersion;

    CredstoreIdentityCredential(Context context, String credentialName,
            @IdentityCredentialStore.Ciphersuite int cipherSuite,
            ICredential binder,
            @Nullable CredstorePresentationSession session) {
            @Nullable CredstorePresentationSession session,
            int featureVersion) {
        mContext = context;
        mCredentialName = credentialName;
        mCipherSuite = cipherSuite;
        mBinder = binder;
        mSession = session;
        mFeatureVersion = featureVersion;
    }

    private KeyPair mEphemeralKeyPair = null;
@@ -347,12 +350,18 @@ class CredstoreIdentityCredential extends IdentityCredential {
            }
        }

        byte[] signature = resultParcel.signature;
        if (signature != null && signature.length == 0) {
            signature = null;
        }

        byte[] mac = resultParcel.mac;
        if (mac != null && mac.length == 0) {
            mac = null;
        }
        CredstoreResultData.Builder resultDataBuilder = new CredstoreResultData.Builder(
                resultParcel.staticAuthenticationData, resultParcel.deviceNameSpaces, mac);
                mFeatureVersion, resultParcel.staticAuthenticationData,
                resultParcel.deviceNameSpaces, mac, signature);

        for (ResultNamespaceParcel resultNamespaceParcel : resultParcel.resultNamespaces) {
            for (ResultEntryParcel resultEntryParcel : resultNamespaceParcel.entries) {
+23 −3
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@ package android.security.identity;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.FeatureInfo;
import android.content.pm.PackageManager;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.security.GenerateRkpKey;
@@ -30,10 +32,28 @@ class CredstoreIdentityCredentialStore extends IdentityCredentialStore {

    private Context mContext = null;
    private ICredentialStore mStore = null;
    private int mFeatureVersion;

    static int getFeatureVersion(@NonNull Context context) {
        PackageManager pm = context.getPackageManager();
        if (pm.hasSystemFeature(PackageManager.FEATURE_IDENTITY_CREDENTIAL_HARDWARE)) {
            FeatureInfo[] infos = pm.getSystemAvailableFeatures();
            for (int n = 0; n < infos.length; n++) {
                FeatureInfo info = infos[n];
                if (info.name.equals(PackageManager.FEATURE_IDENTITY_CREDENTIAL_HARDWARE)) {
                    return info.version;
                }
            }
        }
        // Use of the system feature is not required since Android 12. So for Android 11
        // return 202009 which is the feature version shipped with Android 11.
        return 202009;
    }

    private CredstoreIdentityCredentialStore(@NonNull Context context, ICredentialStore store) {
        mContext = context;
        mStore = store;
        mFeatureVersion = getFeatureVersion(mContext);
    }

    static CredstoreIdentityCredentialStore getInstanceForType(@NonNull Context context,
@@ -139,8 +159,7 @@ class CredstoreIdentityCredentialStore extends IdentityCredentialStore {
            ICredential credstoreCredential;
            credstoreCredential = mStore.getCredentialByName(credentialName, cipherSuite);
            return new CredstoreIdentityCredential(mContext, credentialName, cipherSuite,
                    credstoreCredential,
                    null);
                    credstoreCredential, null, mFeatureVersion);
        } catch (android.os.RemoteException e) {
            throw new RuntimeException("Unexpected RemoteException ", e);
        } catch (android.os.ServiceSpecificException e) {
@@ -182,7 +201,8 @@ class CredstoreIdentityCredentialStore extends IdentityCredentialStore {
            throws CipherSuiteNotSupportedException {
        try {
            ISession credstoreSession = mStore.createPresentationSession(cipherSuite);
            return new CredstorePresentationSession(mContext, cipherSuite, this, credstoreSession);
            return new CredstorePresentationSession(mContext, cipherSuite, this, credstoreSession,
                                                    mFeatureVersion);
        } catch (android.os.RemoteException e) {
            throw new RuntimeException("Unexpected RemoteException ", e);
        } catch (android.os.ServiceSpecificException e) {
Loading