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

Commit 7c1972ff authored by Bo Zhu's avatar Bo Zhu
Browse files

Add CertPath to KeyChainSnapshot and startRecoverySession

CertPath will include a cert of the trusted hardware and necessary
intermediate certificates.

Bug: 73784851
Change-Id: Ic70616b8f119891a82402b91035456e404c5f6de
Test: adb shell am instrument -w -e package \
com.android.server.locksettings.recoverablekeystore \
com.android.frameworks.servicestests/android.support.test.runner.AndroidJUnitRunner
parent e05cd3dd
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -4271,7 +4271,7 @@ package android.security.keystore.recovery {
    method public int getMaxAttempts();
    method public byte[] getServerParams();
    method public int getSnapshotVersion();
    method public byte[] getTrustedHardwarePublicKey();
    method public java.security.cert.CertPath getTrustedHardwareCertPath();
    method public java.util.List<android.security.keystore.recovery.WrappedApplicationKey> getWrappedApplicationKeys();
    method public void writeToParcel(android.os.Parcel, int);
    field public static final android.os.Parcelable.Creator<android.security.keystore.recovery.KeyChainSnapshot> CREATOR;
@@ -4314,7 +4314,7 @@ package android.security.keystore.recovery {
  public class RecoverySession implements java.lang.AutoCloseable {
    method public void close();
    method public java.util.Map<java.lang.String, byte[]> recoverKeys(byte[], java.util.List<android.security.keystore.recovery.WrappedApplicationKey>) throws android.security.keystore.recovery.DecryptionFailedException, android.security.keystore.recovery.InternalRecoveryServiceException, android.security.keystore.recovery.SessionExpiredException;
    method public byte[] start(byte[], byte[], byte[], java.util.List<android.security.keystore.recovery.KeyChainProtectionParams>) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException;
    method public byte[] start(java.security.cert.CertPath, byte[], byte[], java.util.List<android.security.keystore.recovery.KeyChainProtectionParams>) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException;
  }

  public class SessionExpiredException extends java.security.GeneralSecurityException {
+8 −0
Original line number Diff line number Diff line
@@ -93,10 +93,18 @@ package android.os {

package android.security.keystore.recovery {

  public final class KeyChainSnapshot implements android.os.Parcelable {
    method public deprecated byte[] getTrustedHardwarePublicKey();
  }

  public class RecoveryController {
    method public deprecated void setRecoveryStatus(java.lang.String, java.lang.String, int) throws android.security.keystore.recovery.InternalRecoveryServiceException, android.content.pm.PackageManager.NameNotFoundException;
  }

  public class RecoverySession implements java.lang.AutoCloseable {
    method public deprecated byte[] start(byte[], byte[], byte[], java.util.List<android.security.keystore.recovery.KeyChainProtectionParams>) throws java.security.cert.CertificateException, android.security.keystore.recovery.InternalRecoveryServiceException;
  }

}

package android.service.notification {
+32 −3
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.os.Parcelable;

import com.android.internal.util.Preconditions;

import java.security.cert.CertPath;
import java.util.List;

/**
@@ -52,7 +53,8 @@ public final class KeyChainSnapshot implements Parcelable {
    private int mMaxAttempts = DEFAULT_MAX_ATTEMPTS;
    private long mCounterId = DEFAULT_COUNTER_ID;
    private byte[] mServerParams;
    private byte[] mPublicKey;
    private byte[] mPublicKey;  // The raw public key bytes used
    private CertPath mCertPath;  // The certificate path including the intermediate certificates
    private List<KeyChainProtectionParams> mKeyChainProtectionParams;
    private List<WrappedApplicationKey> mEntryRecoveryData;
    private byte[] mEncryptedRecoveryKeyBlob;
@@ -111,13 +113,24 @@ public final class KeyChainSnapshot implements Parcelable {
    /**
     * Public key used to encrypt {@code encryptedRecoveryKeyBlob}.
     *
     * See implementation for binary key format
     * See implementation for binary key format.
     *
     * @deprecated Use {@link #getTrustedHardwareCertPath} instead.
     * @removed
     */
    // TODO: document key format.
    @Deprecated
    public @NonNull byte[] getTrustedHardwarePublicKey() {
        return mPublicKey;
    }

    /**
     * CertPath containing the public key used to encrypt {@code encryptedRecoveryKeyBlob}.
     */
    // TODO: Change to @NonNull
    public CertPath getTrustedHardwareCertPath() {
        return mCertPath;
    }

    /**
     * UI and key derivation parameters. Note that combination of secrets may be used.
     */
@@ -207,12 +220,28 @@ public final class KeyChainSnapshot implements Parcelable {
         *
         * @param publicKey The public key
         * @return This builder.
         * @deprecated Use {@link #setTrustedHardwareCertPath} instead.
         * @removed
         */
        @Deprecated
        public Builder setTrustedHardwarePublicKey(byte[] publicKey) {
            mInstance.mPublicKey = publicKey;
            return this;
        }

        /**
         * Sets CertPath used to validate the trusted hardware public key. The CertPath should
         * contain a certificate of the trusted hardware public key and any necessary intermediate
         * certificates.
         *
         * @param certPath The public key
         * @return This builder.
         */
        public Builder setTrustedHardwareCertPath(CertPath certPath) {
            mInstance.mCertPath = certPath;
            return this;
        }

        /**
         * Sets UI and key derivation parameters
         *
+20 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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.
 */

package android.security.keystore.recovery;

/* @hide */
parcelable RecoveryCertPath;
+117 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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.
 */

package android.security.keystore.recovery;

import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;

import com.android.internal.util.Preconditions;

import java.io.ByteArrayInputStream;
import java.security.cert.CertPath;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;

/**
 * The certificate path of the recovery service.
 *
 * @hide
 */
public final class RecoveryCertPath implements Parcelable {

    private static final String CERT_PATH_ENCODING = "PkiPath";

    private final byte[] mEncodedCertPath;

    /**
     * Wraps a {@code CertPath} to create a {@code Parcelable} for Binder calls.
     *
     * @param certPath The certificate path to be wrapped.
     * @throws CertificateException if the given certificate path cannot be encoded properly.
     */
    public static RecoveryCertPath createRecoveryCertPath(@NonNull CertPath certPath)
            throws CertificateException {
        // Perform the encoding here to avoid throwing exceptions in writeToParcel
        try {
            return new RecoveryCertPath(encodeCertPath(certPath));
        } catch (CertificateEncodingException e) {
            throw new CertificateException("Failed to encode the given CertPath", e);
        }
    }

    /**
     * Obtains the {@code CertPath} wrapped in the Parcelable.
     *
     * @return the wrapped certificate path.
     * @throws CertificateException if the wrapped certificate path cannot be decoded properly.
     */
    public CertPath getCertPath() throws CertificateException {
        // Perform the decoding here to avoid throwing exceptions in createFromParcel
        return decodeCertPath(mEncodedCertPath);
    }

    private RecoveryCertPath(@NonNull byte[] encodedCertPath) {
        mEncodedCertPath = Preconditions.checkNotNull(encodedCertPath);
    }

    private RecoveryCertPath(Parcel in) {
        mEncodedCertPath = in.createByteArray();
    }

    public static final Parcelable.Creator<RecoveryCertPath> CREATOR =
            new Parcelable.Creator<RecoveryCertPath>() {
        public RecoveryCertPath createFromParcel(Parcel in) {
            return new RecoveryCertPath(in);
        }

        public RecoveryCertPath[] newArray(int length) {
            return new RecoveryCertPath[length];
        }
    };

    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeByteArray(mEncodedCertPath);
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @NonNull
    private static byte[] encodeCertPath(@NonNull CertPath certPath)
            throws CertificateEncodingException {
        Preconditions.checkNotNull(certPath);
        return certPath.getEncoded(CERT_PATH_ENCODING);
    }

    @NonNull
    private static CertPath decodeCertPath(@NonNull byte[] bytes) throws CertificateException {
        Preconditions.checkNotNull(bytes);
        CertificateFactory certFactory;
        try {
            certFactory = CertificateFactory.getInstance("X.509");
        } catch (CertificateException e) {
            // Should not happen, as X.509 is mandatory for all providers.
            throw new RuntimeException(e);
        }
        return certFactory.generateCertPath(new ByteArrayInputStream(bytes), CERT_PATH_ENCODING);
    }
}
Loading