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

Commit 6f1d0d13 authored by Alex Klyubin's avatar Alex Klyubin Committed by Android Git Automerger
Browse files

am 174da4e3: am e8ce2144: am f7592b23: Merge "HMAC keys are authorized for...

am 174da4e3: am e8ce2144: am f7592b23: Merge "HMAC keys are authorized for exactly one digest." into mnc-dev

* commit '174da4e3':
  HMAC keys are authorized for exactly one digest.
parents 475858c3 174da4e3
Loading
Loading
Loading
Loading
+21 −33
Original line number Diff line number Diff line
@@ -197,48 +197,36 @@ public abstract class AndroidKeyStoreKeyGeneratorSpi extends KeyGeneratorSpi {
                        }
                    }
                }

                if (mKeymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) {
                    // JCA HMAC key algorithm implies a digest (e.g., HmacSHA256 key algorithm
                    // implies SHA-256 digest). Because keymaster HMAC key is authorized only for
                    // one digest, we don't let algorithm parameter spec override the digest implied
                    // by the key. If the spec specifies digests at all, it must specify only one
                    // digest, the only implied by key algorithm.
                    mKeymasterDigests = new int[] {mKeymasterDigest};
                    if (spec.isDigestsSpecified()) {
                    // Digest(s) explicitly specified in the spec
                    mKeymasterDigests = KeyProperties.Digest.allToKeymaster(spec.getDigests());
                    if (mKeymasterDigest != -1) {
                        // Key algorithm implies a digest -- ensure it's specified in the spec as
                        // first digest.
                        if (!com.android.internal.util.ArrayUtils.contains(
                                mKeymasterDigests, mKeymasterDigest)) {
                        // Digest(s) explicitly specified in the spec. Check that the list
                        // consists of exactly one digest, the one implied by key algorithm.
                        int[] keymasterDigestsFromSpec =
                                KeyProperties.Digest.allToKeymaster(spec.getDigests());
                        if ((keymasterDigestsFromSpec.length != 1)
                                || (keymasterDigestsFromSpec[0] != mKeymasterDigest)) {
                            throw new InvalidAlgorithmParameterException(
                                    "Digests specified in algorithm parameters ("
                                    + Arrays.asList(spec.getDigests()) + ") must include "
                                    + " the digest "
                                    "Unsupported digests specification: "
                                    + Arrays.asList(spec.getDigests()) + ". Only "
                                    + KeyProperties.Digest.fromKeymaster(mKeymasterDigest)
                                    + " implied by key algorithm");
                        }
                        if (mKeymasterDigests[0] != mKeymasterDigest) {
                            // The first digest is not the one implied by the key algorithm.
                            // Swap the implied digest with the first one.
                            for (int i = 0; i < mKeymasterDigests.length; i++) {
                                if (mKeymasterDigests[i] == mKeymasterDigest) {
                                    mKeymasterDigests[i] = mKeymasterDigests[0];
                                    mKeymasterDigests[0] = mKeymasterDigest;
                                    break;
                                }
                            }
                                    + " supported for this HMAC key algorithm");
                        }
                    }
                } else {
                    // No digest specified in the spec
                    if (mKeymasterDigest != -1) {
                        // Key algorithm implies a digest -- use that digest
                        mKeymasterDigests = new int[] {mKeymasterDigest};
                    // Key algorithm does not imply a digest.
                    if (spec.isDigestsSpecified()) {
                        mKeymasterDigests = KeyProperties.Digest.allToKeymaster(spec.getDigests());
                    } else {
                        mKeymasterDigests = EmptyArray.INT;
                    }
                }
                if (mKeymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) {
                    if (mKeymasterDigests.length == 0) {
                        throw new InvalidAlgorithmParameterException(
                                "At least one digest algorithm must be specified");
                    }
                }

                // Check that user authentication related parameters are acceptable. This method
                // will throw an IllegalStateException if there are issues (e.g., secure lock screen
+30 −36
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import java.security.KeyStoreException;
import java.security.KeyStoreSpi;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.ProviderException;
import java.security.PublicKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
@@ -605,50 +606,43 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
            args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, keymasterAlgorithm);

            int[] keymasterDigests;
            int keymasterDigest = KeyProperties.KeyAlgorithm.toKeymasterDigest(key.getAlgorithm());
            if (keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) {
                // JCA HMAC key algorithm implies a digest (e.g., HmacSHA256 key algorithm
                // implies SHA-256 digest). Because keymaster HMAC key is authorized only for one
                // digest, we don't let import parameters override the digest implied by the key.
                // If the parameters specify digests at all, they must specify only one digest, the
                // only implied by key algorithm.
                int keymasterImpliedDigest =
                        KeyProperties.KeyAlgorithm.toKeymasterDigest(key.getAlgorithm());
                if (keymasterImpliedDigest == -1) {
                    throw new ProviderException(
                            "HMAC key algorithm digest unknown for key algorithm "
                                    + key.getAlgorithm());
                }
                keymasterDigests = new int[] {keymasterImpliedDigest};
                if (params.isDigestsSpecified()) {
                // Digest(s) specified in parameters
                keymasterDigests = KeyProperties.Digest.allToKeymaster(params.getDigests());
                if (keymasterDigest != -1) {
                    // Digest also specified in the JCA key algorithm name.
                    if (!com.android.internal.util.ArrayUtils.contains(
                            keymasterDigests, keymasterDigest)) {
                        throw new KeyStoreException("Digest specified in key algorithm "
                                + key.getAlgorithm() + " not specified in protection parameters: "
                                + Arrays.asList(params.getDigests()));
                    }
                    // When the key is read back from keystore we reconstruct the JCA key algorithm
                    // name from the KM_TAG_ALGORITHM and the first KM_TAG_DIGEST. Thus we need to
                    // ensure that the digest reflected in the JCA key algorithm name is the first
                    // KM_TAG_DIGEST tag.
                    if (keymasterDigests[0] != keymasterDigest) {
                        // The first digest is not the one implied by the JCA key algorithm name.
                        // Swap the implied digest with the first one.
                        for (int i = 0; i < keymasterDigests.length; i++) {
                            if (keymasterDigests[i] == keymasterDigest) {
                                keymasterDigests[i] = keymasterDigests[0];
                                keymasterDigests[0] = keymasterDigest;
                                break;
                            }
                        }
                    // Digest(s) explicitly specified in params -- check that the list consists of
                    // exactly one digest, the one implied by key algorithm.
                    int[] keymasterDigestsFromParams =
                            KeyProperties.Digest.allToKeymaster(params.getDigests());
                    if ((keymasterDigestsFromParams.length != 1)
                            || (keymasterDigestsFromParams[0] != keymasterImpliedDigest)) {
                        throw new KeyStoreException(
                                "Unsupported digests specification: "
                                + Arrays.asList(params.getDigests()) + ". Only "
                                + KeyProperties.Digest.fromKeymaster(keymasterImpliedDigest)
                                + " supported for HMAC key algorithm " + key.getAlgorithm());
                    }
                }
            } else {
                // No digest specified in parameters
                if (keymasterDigest != -1) {
                    // Digest specified in the JCA key algorithm name.
                    keymasterDigests = new int[] {keymasterDigest};
                // Key algorithm does not imply a digest.
                if (params.isDigestsSpecified()) {
                    keymasterDigests = KeyProperties.Digest.allToKeymaster(params.getDigests());
                } else {
                    keymasterDigests = EmptyArray.INT;
                }
            }
            args.addEnums(KeymasterDefs.KM_TAG_DIGEST, keymasterDigests);
            if (keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) {
                if (keymasterDigests.length == 0) {
                    throw new KeyStoreException("At least one digest algorithm must be specified"
                            + " for key algorithm " + key.getAlgorithm());
                }
            }

            @KeyProperties.PurposeEnum int purposes = params.getPurposes();
            int[] keymasterBlockModes =
+2 −1
Original line number Diff line number Diff line
@@ -642,7 +642,8 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec {
         * <p>This must be specified for signing/verification keys and RSA encryption/decryption
         * keys used with RSA OAEP padding scheme because these operations involve a digest. For
         * HMAC keys, the default is the digest associated with the key algorithm (e.g.,
         * {@code SHA-256} for key algorithm {@code HmacSHA256}).
         * {@code SHA-256} for key algorithm {@code HmacSHA256}). HMAC keys cannot be authorized
         * for more than one digest.
         *
         * <p>For private keys used for TLS/SSL client or server authentication it is usually
         * necessary to authorize the use of no digest ({@link KeyProperties#DIGEST_NONE}). This is
+2 −1
Original line number Diff line number Diff line
@@ -423,7 +423,8 @@ public final class KeyProtection implements ProtectionParameter {
         * <p>This must be specified for signing/verification keys and RSA encryption/decryption
         * keys used with RSA OAEP padding scheme because these operations involve a digest. For
         * HMAC keys, the default is the digest specified in {@link Key#getAlgorithm()} (e.g.,
         * {@code SHA-256} for key algorithm {@code HmacSHA256}).
         * {@code SHA-256} for key algorithm {@code HmacSHA256}). HMAC keys cannot be authorized
         * for more than one digest.
         *
         * <p>For private keys used for TLS/SSL client or server authentication it is usually
         * necessary to authorize the use of no digest ({@link KeyProperties#DIGEST_NONE}). This is