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

Commit 60bef2a8 authored by Eran Messeri's avatar Eran Messeri Committed by Automerger Merge Worker
Browse files

Merge "MGF1 Digest: Add separate setter" into main am: 32b5cf1b am: 3b167877 am: 51b238ea

parents 6cfbd96e 51b238ea
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -39528,6 +39528,7 @@ package android.security.keystore {
    method @Nullable public java.util.Date getKeyValidityStart();
    method @NonNull public String getKeystoreAlias();
    method public int getMaxUsageCount();
    method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public java.util.Set<java.lang.String> getMgf1Digests();
    method public int getPurposes();
    method @NonNull public String[] getSignaturePaddings();
    method public int getUserAuthenticationType();
@@ -39535,6 +39536,7 @@ package android.security.keystore {
    method public boolean isDevicePropertiesAttestationIncluded();
    method @NonNull public boolean isDigestsSpecified();
    method public boolean isInvalidatedByBiometricEnrollment();
    method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public boolean isMgf1DigestsSpecified();
    method public boolean isRandomizedEncryptionRequired();
    method public boolean isStrongBoxBacked();
    method public boolean isUnlockedDeviceRequired();
@@ -39566,6 +39568,7 @@ package android.security.keystore {
    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setKeyValidityForOriginationEnd(java.util.Date);
    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setKeyValidityStart(java.util.Date);
    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setMaxUsageCount(int);
    method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setMgf1Digests(@Nullable java.lang.String...);
    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setRandomizedEncryptionRequired(boolean);
    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setSignaturePaddings(java.lang.String...);
    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setUnlockedDeviceRequired(boolean);
@@ -39670,12 +39673,14 @@ package android.security.keystore {
    method @Nullable public java.util.Date getKeyValidityForOriginationEnd();
    method @Nullable public java.util.Date getKeyValidityStart();
    method public int getMaxUsageCount();
    method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public java.util.Set<java.lang.String> getMgf1Digests();
    method public int getPurposes();
    method @NonNull public String[] getSignaturePaddings();
    method public int getUserAuthenticationType();
    method public int getUserAuthenticationValidityDurationSeconds();
    method public boolean isDigestsSpecified();
    method public boolean isInvalidatedByBiometricEnrollment();
    method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public boolean isMgf1DigestsSpecified();
    method public boolean isRandomizedEncryptionRequired();
    method public boolean isUnlockedDeviceRequired();
    method public boolean isUserAuthenticationRequired();
@@ -39697,6 +39702,7 @@ package android.security.keystore {
    method @NonNull public android.security.keystore.KeyProtection.Builder setKeyValidityForOriginationEnd(java.util.Date);
    method @NonNull public android.security.keystore.KeyProtection.Builder setKeyValidityStart(java.util.Date);
    method @NonNull public android.security.keystore.KeyProtection.Builder setMaxUsageCount(int);
    method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public android.security.keystore.KeyProtection.Builder setMgf1Digests(@Nullable java.lang.String...);
    method @NonNull public android.security.keystore.KeyProtection.Builder setRandomizedEncryptionRequired(boolean);
    method @NonNull public android.security.keystore.KeyProtection.Builder setSignaturePaddings(java.lang.String...);
    method @NonNull public android.security.keystore.KeyProtection.Builder setUnlockedDeviceRequired(boolean);
+74 −1
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.security.keystore;

import android.annotation.FlaggedApi;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -34,7 +35,10 @@ import java.security.KeyPairGenerator;
import java.security.Signature;
import java.security.cert.Certificate;
import java.security.spec.AlgorithmParameterSpec;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
@@ -300,6 +304,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
    private final Date mKeyValidityForConsumptionEnd;
    private final @KeyProperties.PurposeEnum int mPurposes;
    private final @KeyProperties.DigestEnum String[] mDigests;
    private final @NonNull @KeyProperties.DigestEnum Set<String> mMgf1Digests;
    private final @KeyProperties.EncryptionPaddingEnum String[] mEncryptionPaddings;
    private final @KeyProperties.SignaturePaddingEnum String[] mSignaturePaddings;
    private final @KeyProperties.BlockModeEnum String[] mBlockModes;
@@ -345,6 +350,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
            Date keyValidityForConsumptionEnd,
            @KeyProperties.PurposeEnum int purposes,
            @KeyProperties.DigestEnum String[] digests,
            @KeyProperties.DigestEnum Set<String> mgf1Digests,
            @KeyProperties.EncryptionPaddingEnum String[] encryptionPaddings,
            @KeyProperties.SignaturePaddingEnum String[] signaturePaddings,
            @KeyProperties.BlockModeEnum String[] blockModes,
@@ -404,6 +410,9 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
        mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(keyValidityForConsumptionEnd);
        mPurposes = purposes;
        mDigests = ArrayUtils.cloneIfNotEmpty(digests);
        // No need to copy the input parameter because the Builder class passes in an immutable
        // collection.
        mMgf1Digests = mgf1Digests != null ? mgf1Digests : Collections.emptySet();
        mEncryptionPaddings =
                ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(encryptionPaddings));
        mSignaturePaddings = ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(signaturePaddings));
@@ -566,7 +575,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu

    /**
     * Returns the set of digest algorithms (e.g., {@code SHA-256}, {@code SHA-384} with which the
     * key can be used or {@code null} if not specified.
     * key can be used.
     *
     * <p>See {@link KeyProperties}.{@code DIGEST} constants.
     *
@@ -593,6 +602,40 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
        return mDigests != null;
    }

    /**
     * Returns the set of digests that can be used by the MGF1 mask generation function
     * (e.g., {@code SHA-256}, {@code SHA-384}) with the key. Useful with the {@code RSA-OAEP}
     * scheme.
     * If not explicitly specified during key generation, the default {@code SHA-1} digest is
     * used and may be specified when using the key.
     *
     * <p>See {@link KeyProperties}.{@code DIGEST} constants.
     *
     * @throws IllegalStateException if this set has not been specified.
     *
     * @see #isMgf1DigestsSpecified()
     */
    @NonNull
    @FlaggedApi("MGF1_DIGEST_SETTER")
    public @KeyProperties.DigestEnum Set<String> getMgf1Digests() {
        if (mMgf1Digests.isEmpty()) {
            throw new IllegalStateException("Mask generation function (MGF) not specified");
        }
        return new HashSet(mMgf1Digests);
    }

    /**
     * Returns {@code true} if the set of digests for the MGF1 mask generation function,
     * with which the key can be used, has been specified. Useful with the {@code RSA-OAEP} scheme.
     *
     * @see #getMgf1Digests()
     */
    @NonNull
    @FlaggedApi("MGF1_DIGEST_SETTER")
    public boolean isMgf1DigestsSpecified() {
        return !mMgf1Digests.isEmpty();
    }

    /**
     * Returns the set of padding schemes (e.g., {@code PKCS7Padding}, {@code OEAPPadding},
     * {@code PKCS1Padding}, {@code NoPadding}) with which the key can be used when
@@ -913,6 +956,8 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
        private Date mKeyValidityForOriginationEnd;
        private Date mKeyValidityForConsumptionEnd;
        private @KeyProperties.DigestEnum String[] mDigests;
        private @NonNull @KeyProperties.DigestEnum Set<String> mMgf1Digests =
                Collections.emptySet();
        private @KeyProperties.EncryptionPaddingEnum String[] mEncryptionPaddings;
        private @KeyProperties.SignaturePaddingEnum String[] mSignaturePaddings;
        private @KeyProperties.BlockModeEnum String[] mBlockModes;
@@ -983,6 +1028,9 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
            if (sourceSpec.isDigestsSpecified()) {
                mDigests = sourceSpec.getDigests();
            }
            if (sourceSpec.isMgf1DigestsSpecified()) {
                mMgf1Digests = sourceSpec.getMgf1Digests();
            }
            mEncryptionPaddings = sourceSpec.getEncryptionPaddings();
            mSignaturePaddings = sourceSpec.getSignaturePaddings();
            mBlockModes = sourceSpec.getBlockModes();
@@ -1229,6 +1277,30 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
            return this;
        }

        /**
         * Sets the set of hash functions (e.g., {@code SHA-256}, {@code SHA-384}) which could be
         * used by the mask generation function MGF1 (which is used for certain operations with
         * the key). Attempts to use the key with any other digest for the mask generation
         * function will be rejected.
         *
         * <p>This can only be specified for signing/verification keys and RSA encryption/decryption
         * keys used with RSA OAEP padding scheme because these operations involve a mask generation
         * function (MGF1) with a digest.
         * The default digest for MGF1 is {@code SHA-1}, which will be specified during key creation
         * time if no digests have been explicitly provided.
         * When using the key, the caller may not specify any digests that were not provided during
         * key creation time. The caller may specify the default digest, {@code SHA-1}, if no
         * digests were explicitly provided during key creation (but it is not necessary to do so).
         *
         * <p>See {@link KeyProperties}.{@code DIGEST} constants.
         */
        @NonNull
        @FlaggedApi("MGF1_DIGEST_SETTER")
        public Builder setMgf1Digests(@Nullable @KeyProperties.DigestEnum String... mgf1Digests) {
            mMgf1Digests = Set.of(mgf1Digests);
            return this;
        }

        /**
         * Sets the set of padding schemes (e.g., {@code PKCS7Padding}, {@code OAEPPadding},
         * {@code PKCS1Padding}, {@code NoPadding}) with which the key can be used when
@@ -1782,6 +1854,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
                    mKeyValidityForConsumptionEnd,
                    mPurposes,
                    mDigests,
                    mMgf1Digests,
                    mEncryptionPaddings,
                    mSignaturePaddings,
                    mBlockModes,
+68 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.security.keystore;

import android.annotation.FlaggedApi;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -30,7 +31,10 @@ import java.security.Key;
import java.security.KeyStore.ProtectionParameter;
import java.security.Signature;
import java.security.cert.Certificate;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.crypto.Cipher;
import javax.crypto.Mac;
@@ -223,6 +227,7 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs {
    private final @KeyProperties.EncryptionPaddingEnum String[] mEncryptionPaddings;
    private final @KeyProperties.SignaturePaddingEnum String[] mSignaturePaddings;
    private final @KeyProperties.DigestEnum String[] mDigests;
    private final @NonNull @KeyProperties.DigestEnum Set<String> mMgf1Digests;
    private final @KeyProperties.BlockModeEnum String[] mBlockModes;
    private final boolean mRandomizedEncryptionRequired;
    private final boolean mUserAuthenticationRequired;
@@ -247,6 +252,7 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs {
            @KeyProperties.EncryptionPaddingEnum String[] encryptionPaddings,
            @KeyProperties.SignaturePaddingEnum String[] signaturePaddings,
            @KeyProperties.DigestEnum String[] digests,
            @KeyProperties.DigestEnum Set<String> mgf1Digests,
            @KeyProperties.BlockModeEnum String[] blockModes,
            boolean randomizedEncryptionRequired,
            boolean userAuthenticationRequired,
@@ -271,6 +277,7 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs {
        mSignaturePaddings =
                ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(signaturePaddings));
        mDigests = ArrayUtils.cloneIfNotEmpty(digests);
        mMgf1Digests = mgf1Digests;
        mBlockModes = ArrayUtils.cloneIfNotEmpty(ArrayUtils.nullToEmpty(blockModes));
        mRandomizedEncryptionRequired = randomizedEncryptionRequired;
        mUserAuthenticationRequired = userAuthenticationRequired;
@@ -380,6 +387,40 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs {
        return mDigests != null;
    }

    /**
     * Returns the set of digests that can be used by the MGF1 mask generation function
     * (e.g., {@code SHA-256}, {@code SHA-384}) with the key. Useful with the {@code RSA-OAEP}
     * scheme.
     * If not explicitly specified  during key generation, the default {@code SHA-1} digest is
     * used and may be specified.
     *
     * <p>See {@link KeyProperties}.{@code DIGEST} constants.
     *
     * @throws IllegalStateException if this set has not been specified.
     *
     * @see #isMgf1DigestsSpecified()
     */
    @NonNull
    @FlaggedApi("MGF1_DIGEST_SETTER")
    public @KeyProperties.DigestEnum Set<String> getMgf1Digests() {
        if (mMgf1Digests.isEmpty()) {
            throw new IllegalStateException("Mask generation function (MGF) not specified");
        }
        return new HashSet(mMgf1Digests);
    }

    /**
     * Returns {@code true} if the set of digests for the MGF1 mask generation function,
     * with which the key can be used, has been specified. Useful with the {@code RSA-OAEP} scheme.
     *
     * @see #getMgf1Digests()
     */
    @NonNull
    @FlaggedApi("MGF1_DIGEST_SETTER")
    public boolean isMgf1DigestsSpecified() {
        return !mMgf1Digests.isEmpty();
    }

    /**
     * Gets the set of block modes (e.g., {@code GCM}, {@code CBC}) with which the key can be used
     * when encrypting/decrypting. Attempts to use the key with any other block modes will be
@@ -588,6 +629,8 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs {
        private @KeyProperties.EncryptionPaddingEnum String[] mEncryptionPaddings;
        private @KeyProperties.SignaturePaddingEnum String[] mSignaturePaddings;
        private @KeyProperties.DigestEnum String[] mDigests;
        private @NonNull @KeyProperties.DigestEnum Set<String> mMgf1Digests =
                Collections.emptySet();
        private @KeyProperties.BlockModeEnum String[] mBlockModes;
        private boolean mRandomizedEncryptionRequired = true;
        private boolean mUserAuthenticationRequired;
@@ -738,6 +781,30 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs {
            return this;
        }

        /**
         * Sets the set of hash functions (e.g., {@code SHA-256}, {@code SHA-384}) which could be
         * used by the mask generation function MGF1 (which is used for certain operations with
         * the key). Attempts to use the key with any other digest for the mask generation
         * function will be rejected.
         *
         * <p>This can only be specified for signing/verification keys and RSA encryption/decryption
         * keys used with RSA OAEP padding scheme because these operations involve a mask generation
         * function (MGF1) with a digest.
         * The default digest for MGF1 is {@code SHA-1}, which will be specified during key import
         * time if no digests have been explicitly provided.
         * When using the key, the caller may not specify any digests that were not provided during
         * key import time. The caller may specify the default digest, {@code SHA-1}, if no
         * digests were explicitly provided during key import (but it is not necessary to do so).
         *
         * <p>See {@link KeyProperties}.{@code DIGEST} constants.
         */
        @NonNull
        @FlaggedApi("MGF1_DIGEST_SETTER")
        public Builder setMgf1Digests(@Nullable @KeyProperties.DigestEnum String... mgf1Digests) {
            mMgf1Digests = Set.of(mgf1Digests);
            return this;
        }

        /**
         * Sets the set of block modes (e.g., {@code GCM}, {@code CBC}) with which the key can be
         * used when encrypting/decrypting. Attempts to use the key with any other block modes will
@@ -1141,6 +1208,7 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs {
                    mEncryptionPaddings,
                    mSignaturePaddings,
                    mDigests,
                    mMgf1Digests,
                    mBlockModes,
                    mRandomizedEncryptionRequired,
                    mUserAuthenticationRequired,
+11 −0
Original line number Diff line number Diff line
@@ -23,7 +23,11 @@ import java.math.BigInteger;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.RSAKeyGenParameterSpec;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Set;

import javax.security.auth.x500.X500Principal;

@@ -91,6 +95,11 @@ public final class ParcelableKeyGenParameterSpec implements Parcelable {
        } else {
            out.writeStringArray(null);
        }
        if (mSpec.isMgf1DigestsSpecified()) {
            out.writeStringList(List.copyOf(mSpec.getMgf1Digests()));
        } else {
            out.writeStringList(null);
        }
        out.writeStringArray(mSpec.getEncryptionPaddings());
        out.writeStringArray(mSpec.getSignaturePaddings());
        out.writeStringArray(mSpec.getBlockModes());
@@ -153,6 +162,7 @@ public final class ParcelableKeyGenParameterSpec implements Parcelable {
        final Date keyValidityForOriginationEnd = readDateOrNull(in);
        final Date keyValidityForConsumptionEnd = readDateOrNull(in);
        final String[] digests = in.createStringArray();
        final ArrayList<String> mgf1Digests = in.createStringArrayList();
        final String[] encryptionPaddings = in.createStringArray();
        final String[] signaturePaddings = in.createStringArray();
        final String[] blockModes = in.createStringArray();
@@ -191,6 +201,7 @@ public final class ParcelableKeyGenParameterSpec implements Parcelable {
                keyValidityForConsumptionEnd,
                purposes,
                digests,
                mgf1Digests != null ? Set.copyOf(mgf1Digests) : Collections.emptySet(),
                encryptionPaddings,
                signaturePaddings,
                blockModes,
+2 −1
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.os.StrictMode;
import android.security.KeyStoreException;
import android.security.KeyStoreOperation;
import android.security.keymaster.KeymasterDefs;
import android.security.keystore.KeyProperties;
import android.security.keystore.KeyStoreCryptoOperation;
import android.system.keystore2.Authorization;

@@ -71,7 +72,7 @@ import javax.crypto.spec.SecretKeySpec;
 */
abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStoreCryptoOperation {
    private static final String TAG = "AndroidKeyStoreCipherSpiBase";
    public static final String DEFAULT_MGF1_DIGEST = "SHA-1";
    public static final String DEFAULT_MGF1_DIGEST = KeyProperties.DIGEST_SHA1;

    // Fields below are populated by Cipher.init and KeyStore.begin and should be preserved after
    // doFinal finishes.
Loading