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

Commit 70376a77 authored by Alex Klyubin's avatar Alex Klyubin
Browse files

Add more digests to AndroidKeyStore API.

This adds MD5, SHA-1, SHA-224, SHA-384, and SHA-512. SHA-256 was
already there.

MD5 is not exposed for HMAC on purpose, because MD5 has been
deprecated for years.

Bug: 18088752
Change-Id: I4df3d3f6cf10805c7910a1bdb577a91c85055945
parent c0d6b7cb
Loading
Loading
Loading
Loading
+17 −2
Original line number Original line Diff line number Diff line
@@ -49,14 +49,25 @@ public class AndroidKeyStoreProvider extends Provider {


        // javax.crypto.KeyGenerator
        // javax.crypto.KeyGenerator
        put("KeyGenerator.AES", PACKAGE_NAME + ".KeyStoreKeyGeneratorSpi$AES");
        put("KeyGenerator.AES", PACKAGE_NAME + ".KeyStoreKeyGeneratorSpi$AES");
        put("KeyGenerator.HmacSHA1", PACKAGE_NAME + ".KeyStoreKeyGeneratorSpi$HmacSHA1");
        put("KeyGenerator.HmacSHA224", PACKAGE_NAME + ".KeyStoreKeyGeneratorSpi$HmacSHA224");
        put("KeyGenerator.HmacSHA256", PACKAGE_NAME + ".KeyStoreKeyGeneratorSpi$HmacSHA256");
        put("KeyGenerator.HmacSHA256", PACKAGE_NAME + ".KeyStoreKeyGeneratorSpi$HmacSHA256");
        put("KeyGenerator.HmacSHA384", PACKAGE_NAME + ".KeyStoreKeyGeneratorSpi$HmacSHA384");
        put("KeyGenerator.HmacSHA512", PACKAGE_NAME + ".KeyStoreKeyGeneratorSpi$HmacSHA512");


        // java.security.SecretKeyFactory
        // java.security.SecretKeyFactory
        put("SecretKeyFactory.AES", PACKAGE_NAME + ".KeyStoreSecretKeyFactorySpi");
        putSecretKeyFactoryImpl("AES");
        put("SecretKeyFactory.HmacSHA256", PACKAGE_NAME + ".KeyStoreSecretKeyFactorySpi");
        putSecretKeyFactoryImpl("HmacSHA1");
        putSecretKeyFactoryImpl("HmacSHA224");
        putSecretKeyFactoryImpl("HmacSHA256");
        putSecretKeyFactoryImpl("HmacSHA384");
        putSecretKeyFactoryImpl("HmacSHA512");


        // javax.crypto.Mac
        // javax.crypto.Mac
        putMacImpl("HmacSHA224", PACKAGE_NAME + ".KeyStoreHmacSpi$HmacSHA224");
        putMacImpl("HmacSHA256", PACKAGE_NAME + ".KeyStoreHmacSpi$HmacSHA256");
        putMacImpl("HmacSHA256", PACKAGE_NAME + ".KeyStoreHmacSpi$HmacSHA256");
        putMacImpl("HmacSHA384", PACKAGE_NAME + ".KeyStoreHmacSpi$HmacSHA384");
        putMacImpl("HmacSHA512", PACKAGE_NAME + ".KeyStoreHmacSpi$HmacSHA512");


        // javax.crypto.Cipher
        // javax.crypto.Cipher
        putSymmetricCipherImpl("AES/ECB/NoPadding",
        putSymmetricCipherImpl("AES/ECB/NoPadding",
@@ -73,6 +84,10 @@ public class AndroidKeyStoreProvider extends Provider {
                PACKAGE_NAME + ".KeyStoreCipherSpi$AES$CTR$NoPadding");
                PACKAGE_NAME + ".KeyStoreCipherSpi$AES$CTR$NoPadding");
    }
    }


    private void putSecretKeyFactoryImpl(String algorithm) {
        put("SecretKeyFactory." + algorithm, PACKAGE_NAME + ".KeyStoreSecretKeyFactorySpi");
    }

    private void putMacImpl(String algorithm, String implClass) {
    private void putMacImpl(String algorithm, String implClass) {
        put("Mac." + algorithm, implClass);
        put("Mac." + algorithm, implClass);
        put("Mac." + algorithm + " SupportedKeyClasses", KEYSTORE_SECRET_KEY_CLASS_NAME);
        put("Mac." + algorithm + " SupportedKeyClasses", KEYSTORE_SECRET_KEY_CLASS_NAME);
+27 −3
Original line number Original line Diff line number Diff line
@@ -35,9 +35,33 @@ import javax.crypto.MacSpi;
 */
 */
public abstract class KeyStoreHmacSpi extends MacSpi implements KeyStoreCryptoOperation {
public abstract class KeyStoreHmacSpi extends MacSpi implements KeyStoreCryptoOperation {


    public static class HmacSHA1 extends KeyStoreHmacSpi {
        public HmacSHA1() {
            super(KeyStoreKeyConstraints.Digest.SHA1);
        }
    }

    public static class HmacSHA224 extends KeyStoreHmacSpi {
        public HmacSHA224() {
            super(KeyStoreKeyConstraints.Digest.SHA224);
        }
    }

    public static class HmacSHA256 extends KeyStoreHmacSpi {
    public static class HmacSHA256 extends KeyStoreHmacSpi {
        public HmacSHA256() {
        public HmacSHA256() {
            super(KeyStoreKeyConstraints.Digest.SHA256, 256 / 8);
            super(KeyStoreKeyConstraints.Digest.SHA256);
        }
    }

    public static class HmacSHA384 extends KeyStoreHmacSpi {
        public HmacSHA384() {
            super(KeyStoreKeyConstraints.Digest.SHA384);
        }
    }

    public static class HmacSHA512 extends KeyStoreHmacSpi {
        public HmacSHA512() {
            super(KeyStoreKeyConstraints.Digest.SHA512);
        }
        }
    }
    }


@@ -52,9 +76,9 @@ public abstract class KeyStoreHmacSpi extends MacSpi implements KeyStoreCryptoOp
    private IBinder mOperationToken;
    private IBinder mOperationToken;
    private Long mOperationHandle;
    private Long mOperationHandle;


    protected KeyStoreHmacSpi(@KeyStoreKeyConstraints.DigestEnum int digest, int macSizeBytes) {
    protected KeyStoreHmacSpi(@KeyStoreKeyConstraints.DigestEnum int digest) {
        mDigest = digest;
        mDigest = digest;
        mMacSizeBytes = macSizeBytes;
        mMacSizeBytes = KeyStoreKeyConstraints.Digest.getOutputSizeBytes(digest);
    }
    }


    @Override
    @Override
+112 −13
Original line number Original line Diff line number Diff line
@@ -327,7 +327,15 @@ public abstract class KeyStoreKeyConstraints {


    @Retention(RetentionPolicy.SOURCE)
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(flag = true,
    @IntDef(flag = true,
            value = {Digest.NONE, Digest.SHA256})
            value = {
                Digest.NONE,
                Digest.MD5,
                Digest.SHA1,
                Digest.SHA224,
                Digest.SHA256,
                Digest.SHA384,
                Digest.SHA512,
                })
    public @interface DigestEnum {}
    public @interface DigestEnum {}


    /**
    /**
@@ -343,9 +351,34 @@ public abstract class KeyStoreKeyConstraints {
        public static final int NONE = 1 << 0;
        public static final int NONE = 1 << 0;


        /**
        /**
         * SHA-256 digest.
         * MD5 digest.
         */
         */
        public static final int SHA256 = 1 << 1;
        public static final int MD5 = 1 << 1;

        /**
         * SHA-1 digest.
         */
        public static final int SHA1 = 1 << 2;

        /**
         * SHA-2 224 (aka SHA-224) digest.
         */
        public static final int SHA224 = 1 << 3;

        /**
         * SHA-2 256 (aka SHA-256) digest.
         */
        public static final int SHA256 = 1 << 4;

        /**
         * SHA-2 384 (aka SHA-384) digest.
         */
        public static final int SHA384 = 1 << 5;

        /**
         * SHA-2 512 (aka SHA-512) digest.
         */
        public static final int SHA512 = 1 << 6;


        /**
        /**
         * @hide
         * @hide
@@ -354,8 +387,18 @@ public abstract class KeyStoreKeyConstraints {
            switch (digest) {
            switch (digest) {
                case NONE:
                case NONE:
                    return "NONE";
                    return "NONE";
                case MD5:
                    return "MD5";
                case SHA1:
                    return "SHA-1";
                case SHA224:
                    return "SHA-224";
                case SHA256:
                case SHA256:
                    return "SHA256";
                    return "SHA-256";
                case SHA384:
                    return "SHA-384";
                case SHA512:
                    return "SHA-512";
                default:
                default:
                    throw new IllegalArgumentException("Unknown digest: " + digest);
                    throw new IllegalArgumentException("Unknown digest: " + digest);
            }
            }
@@ -364,13 +407,19 @@ public abstract class KeyStoreKeyConstraints {
        /**
        /**
         * @hide
         * @hide
         */
         */
        public static String[] allToString(@DigestEnum int digests) {
        public static String allToString(@DigestEnum int digests) {
            int[] values = getSetFlags(digests);
            StringBuilder result = new StringBuilder("[");
            String[] result = new String[values.length];
            boolean firstValue = true;
            for (int i = 0; i < values.length; i++) {
            for (@DigestEnum int digest : getSetFlags(digests)) {
                result[i] = toString(values[i]);
                if (firstValue) {
                    firstValue = false;
                } else {
                    result.append(", ");
                }
                }
            return result;
                result.append(toString(digest));
            }
            result.append(']');
            return result.toString();
        }
        }


        /**
        /**
@@ -380,8 +429,18 @@ public abstract class KeyStoreKeyConstraints {
            switch (digest) {
            switch (digest) {
                case NONE:
                case NONE:
                    return KeymasterDefs.KM_DIGEST_NONE;
                    return KeymasterDefs.KM_DIGEST_NONE;
                case MD5:
                    return KeymasterDefs.KM_DIGEST_MD5;
                case SHA1:
                    return KeymasterDefs.KM_DIGEST_SHA1;
                case SHA224:
                    return KeymasterDefs.KM_DIGEST_SHA_2_224;
                case SHA256:
                case SHA256:
                    return KeymasterDefs.KM_DIGEST_SHA_2_256;
                    return KeymasterDefs.KM_DIGEST_SHA_2_256;
                case SHA384:
                    return KeymasterDefs.KM_DIGEST_SHA_2_384;
                case SHA512:
                    return KeymasterDefs.KM_DIGEST_SHA_2_512;
                default:
                default:
                    throw new IllegalArgumentException("Unknown digest: " + digest);
                    throw new IllegalArgumentException("Unknown digest: " + digest);
            }
            }
@@ -394,8 +453,18 @@ public abstract class KeyStoreKeyConstraints {
            switch (digest) {
            switch (digest) {
                case KeymasterDefs.KM_DIGEST_NONE:
                case KeymasterDefs.KM_DIGEST_NONE:
                    return NONE;
                    return NONE;
                case KeymasterDefs.KM_DIGEST_MD5:
                    return MD5;
                case KeymasterDefs.KM_DIGEST_SHA1:
                    return SHA1;
                case KeymasterDefs.KM_DIGEST_SHA_2_224:
                    return SHA224;
                case KeymasterDefs.KM_DIGEST_SHA_2_256:
                case KeymasterDefs.KM_DIGEST_SHA_2_256:
                    return SHA256;
                    return SHA256;
                case KeymasterDefs.KM_DIGEST_SHA_2_384:
                    return SHA384;
                case KeymasterDefs.KM_DIGEST_SHA_2_512:
                    return SHA512;
                default:
                default:
                    throw new IllegalArgumentException("Unknown digest: " + digest);
                    throw new IllegalArgumentException("Unknown digest: " + digest);
            }
            }
@@ -429,11 +498,21 @@ public abstract class KeyStoreKeyConstraints {
        public static @DigestEnum Integer fromJCASecretKeyAlgorithm(String algorithm) {
        public static @DigestEnum Integer fromJCASecretKeyAlgorithm(String algorithm) {
            String algorithmLower = algorithm.toLowerCase(Locale.US);
            String algorithmLower = algorithm.toLowerCase(Locale.US);
            if (algorithmLower.startsWith("hmac")) {
            if (algorithmLower.startsWith("hmac")) {
                if ("hmacsha256".equals(algorithmLower)) {
                String digestLower = algorithmLower.substring("hmac".length());
                if ("md5".equals(digestLower)) {
                    return MD5;
                } else if ("sha1".equals(digestLower)) {
                    return SHA1;
                } else if ("sha224".equals(digestLower)) {
                    return SHA224;
                } else if ("sha256".equals(digestLower)) {
                    return SHA256;
                    return SHA256;
                } else if ("sha384".equals(digestLower)) {
                    return SHA384;
                } else if ("sha512".equals(digestLower)) {
                    return SHA512;
                } else {
                } else {
                    throw new IllegalArgumentException("Unsupported digest: "
                    throw new IllegalArgumentException("Unsupported digest: " + digestLower);
                            + algorithmLower.substring("hmac".length()));
                }
                }
            } else {
            } else {
                return null;
                return null;
@@ -447,8 +526,18 @@ public abstract class KeyStoreKeyConstraints {
            switch (digest) {
            switch (digest) {
                case NONE:
                case NONE:
                    return "NONE";
                    return "NONE";
                case MD5:
                    return "MD5";
                case SHA1:
                    return "SHA1";
                case SHA224:
                    return "SHA224";
                case SHA256:
                case SHA256:
                    return "SHA256";
                    return "SHA256";
                case SHA384:
                    return "SHA384";
                case SHA512:
                    return "SHA512";
                default:
                default:
                    throw new IllegalArgumentException("Unknown digest: " + digest);
                    throw new IllegalArgumentException("Unknown digest: " + digest);
            }
            }
@@ -461,8 +550,18 @@ public abstract class KeyStoreKeyConstraints {
            switch (digest) {
            switch (digest) {
                case NONE:
                case NONE:
                    return null;
                    return null;
                case MD5:
                    return 128 / 8;
                case SHA1:
                    return 160 / 8;
                case SHA224:
                    return 224 / 8;
                case SHA256:
                case SHA256:
                    return 256 / 8;
                    return 256 / 8;
                case SHA384:
                    return 384 / 8;
                case SHA512:
                    return 512 / 8;
                default:
                default:
                    throw new IllegalArgumentException("Unknown digest: " + digest);
                    throw new IllegalArgumentException("Unknown digest: " + digest);
            }
            }
+34 −5
Original line number Original line Diff line number Diff line
@@ -41,12 +41,41 @@ public abstract class KeyStoreKeyGeneratorSpi extends KeyGeneratorSpi {
        }
        }
    }
    }


    public static class HmacSHA256 extends KeyStoreKeyGeneratorSpi {
    protected static abstract class HmacBase extends KeyStoreKeyGeneratorSpi {
        public HmacSHA256() {
        protected HmacBase(@KeyStoreKeyConstraints.DigestEnum int digest) {
            super(KeyStoreKeyConstraints.Algorithm.HMAC,
            super(KeyStoreKeyConstraints.Algorithm.HMAC,
                    KeyStoreKeyConstraints.Digest.SHA256,
                    digest,
                    KeyStoreKeyConstraints.Digest.getOutputSizeBytes(
                    KeyStoreKeyConstraints.Digest.getOutputSizeBytes(digest) * 8);
                            KeyStoreKeyConstraints.Digest.SHA256) * 8);
        }
    }

    public static class HmacSHA1 extends HmacBase {
        public HmacSHA1() {
            super(KeyStoreKeyConstraints.Digest.SHA1);
        }
    }

    public static class HmacSHA224 extends HmacBase {
        public HmacSHA224() {
            super(KeyStoreKeyConstraints.Digest.SHA224);
        }
    }

    public static class HmacSHA256 extends HmacBase {
        public HmacSHA256() {
            super(KeyStoreKeyConstraints.Digest.SHA256);
        }
    }

    public static class HmacSHA384 extends HmacBase {
        public HmacSHA384() {
            super(KeyStoreKeyConstraints.Digest.SHA384);
        }
    }

    public static class HmacSHA512 extends HmacBase {
        public HmacSHA512() {
            super(KeyStoreKeyConstraints.Digest.SHA512);
        }
        }
    }
    }