14f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin/*
24f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin * Copyright (C) 2015 The Android Open Source Project
34f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin *
44f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin * Licensed under the Apache License, Version 2.0 (the "License");
54f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin * you may not use this file except in compliance with the License.
64f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin * You may obtain a copy of the License at
74f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin *
84f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin *      http://www.apache.org/licenses/LICENSE-2.0
94f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin *
104f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin * Unless required by applicable law or agreed to in writing, software
114f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin * distributed under the License is distributed on an "AS IS" BASIS,
124f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin * See the License for the specific language governing permissions and
144f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin * limitations under the License.
154f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin */
164f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
174f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubinpackage android.security.keystore;
184f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
194f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubinimport android.annotation.NonNull;
204f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubinimport android.annotation.Nullable;
214f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubinimport android.security.KeyStore;
224f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubinimport android.security.keymaster.KeyCharacteristics;
234f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubinimport android.security.keymaster.KeymasterArguments;
244f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubinimport android.security.keymaster.KeymasterDefs;
254f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
264f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubinimport java.security.AlgorithmParameters;
274f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubinimport java.security.InvalidAlgorithmParameterException;
284f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubinimport java.security.InvalidKeyException;
294f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubinimport java.security.Key;
304f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubinimport java.security.NoSuchAlgorithmException;
314f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubinimport java.security.PrivateKey;
324f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubinimport java.security.ProviderException;
334f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubinimport java.security.spec.AlgorithmParameterSpec;
344f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubinimport java.security.spec.InvalidParameterSpecException;
354f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubinimport java.security.spec.MGF1ParameterSpec;
364f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
374f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubinimport javax.crypto.Cipher;
384f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubinimport javax.crypto.CipherSpi;
394f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubinimport javax.crypto.spec.OAEPParameterSpec;
404f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubinimport javax.crypto.spec.PSource;
414f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
424f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin/**
434f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin * Base class for {@link CipherSpi} providing Android KeyStore backed RSA encryption/decryption.
444f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin *
454f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin * @hide
464f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin */
474f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubinabstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase {
484f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
494f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    /**
504f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin     * Raw RSA cipher without any padding.
514f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin     */
524f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    public static final class NoPadding extends AndroidKeyStoreRSACipherSpi {
534f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        public NoPadding() {
544f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            super(KeymasterDefs.KM_PAD_NONE);
554f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        }
564f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
574f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        @Override
5825d2270704e246d897596c991a36233cdc620790Alex Klyubin        protected boolean adjustConfigForEncryptingWithPrivateKey() {
5925d2270704e246d897596c991a36233cdc620790Alex Klyubin            // RSA encryption with no padding using private key is a way to implement raw RSA
6025d2270704e246d897596c991a36233cdc620790Alex Klyubin            // signatures which JCA does not expose via Signature. We thus have to support this.
6125d2270704e246d897596c991a36233cdc620790Alex Klyubin            setKeymasterPurposeOverride(KeymasterDefs.KM_PURPOSE_SIGN);
625552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin            return true;
635552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin        }
645552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin
655552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin        @Override
664f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        protected void initAlgorithmSpecificParameters() throws InvalidKeyException {}
674f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
684f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        @Override
694f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        protected void initAlgorithmSpecificParameters(@Nullable AlgorithmParameterSpec params)
704f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                throws InvalidAlgorithmParameterException {
714f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            if (params != null) {
724f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                throw new InvalidAlgorithmParameterException(
734f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                        "Unexpected parameters: " + params + ". No parameters supported");
744f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            }
754f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        }
764f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
774f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        @Override
784f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        protected void initAlgorithmSpecificParameters(@Nullable AlgorithmParameters params)
794f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                throws InvalidAlgorithmParameterException {
804f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
814f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            if (params != null) {
824f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                throw new InvalidAlgorithmParameterException(
834f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                        "Unexpected parameters: " + params + ". No parameters supported");
844f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            }
854f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        }
864f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
874f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        @Override
884f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        protected AlgorithmParameters engineGetParameters() {
894f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            return null;
904f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        }
914f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
924f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        @Override
934f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        protected final int getAdditionalEntropyAmountForBegin() {
944f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            return 0;
954f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        }
964f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
974f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        @Override
98a72b55195c23fc06d1600efe8f6aac85290c7f8fAlex Klyubin        protected final int getAdditionalEntropyAmountForFinish() {
99a72b55195c23fc06d1600efe8f6aac85290c7f8fAlex Klyubin            return 0;
100a72b55195c23fc06d1600efe8f6aac85290c7f8fAlex Klyubin        }
1014f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    }
1024f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
1034f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    /**
1044f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin     * RSA cipher with PKCS#1 v1.5 encryption padding.
1054f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin     */
1064f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    public static final class PKCS1Padding extends AndroidKeyStoreRSACipherSpi {
1074f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        public PKCS1Padding() {
1084f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            super(KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
1094f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        }
1104f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
1114f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        @Override
11225d2270704e246d897596c991a36233cdc620790Alex Klyubin        protected boolean adjustConfigForEncryptingWithPrivateKey() {
11325d2270704e246d897596c991a36233cdc620790Alex Klyubin            // RSA encryption with PCKS#1 padding using private key is a way to implement RSA
11425d2270704e246d897596c991a36233cdc620790Alex Klyubin            // signatures with PKCS#1 padding. We have to support this for legacy reasons.
11525d2270704e246d897596c991a36233cdc620790Alex Klyubin            setKeymasterPurposeOverride(KeymasterDefs.KM_PURPOSE_SIGN);
11625d2270704e246d897596c991a36233cdc620790Alex Klyubin            setKeymasterPaddingOverride(KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN);
11725d2270704e246d897596c991a36233cdc620790Alex Klyubin            return true;
11825d2270704e246d897596c991a36233cdc620790Alex Klyubin        }
11925d2270704e246d897596c991a36233cdc620790Alex Klyubin
12025d2270704e246d897596c991a36233cdc620790Alex Klyubin        @Override
1214f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        protected void initAlgorithmSpecificParameters() throws InvalidKeyException {}
1224f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
1234f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        @Override
1244f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        protected void initAlgorithmSpecificParameters(@Nullable AlgorithmParameterSpec params)
1254f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                throws InvalidAlgorithmParameterException {
1264f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            if (params != null) {
1274f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                throw new InvalidAlgorithmParameterException(
1284f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                        "Unexpected parameters: " + params + ". No parameters supported");
1294f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            }
1304f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        }
1314f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
1324f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        @Override
1334f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        protected void initAlgorithmSpecificParameters(@Nullable AlgorithmParameters params)
1344f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                throws InvalidAlgorithmParameterException {
1354f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
1364f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            if (params != null) {
1374f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                throw new InvalidAlgorithmParameterException(
1384f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                        "Unexpected parameters: " + params + ". No parameters supported");
1394f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            }
1404f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        }
1414f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
1424f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        @Override
1434f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        protected AlgorithmParameters engineGetParameters() {
1444f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            return null;
1454f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        }
1464f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
1474f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        @Override
1484f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        protected final int getAdditionalEntropyAmountForBegin() {
149a72b55195c23fc06d1600efe8f6aac85290c7f8fAlex Klyubin            return 0;
150a72b55195c23fc06d1600efe8f6aac85290c7f8fAlex Klyubin        }
151a72b55195c23fc06d1600efe8f6aac85290c7f8fAlex Klyubin
152a72b55195c23fc06d1600efe8f6aac85290c7f8fAlex Klyubin        @Override
153a72b55195c23fc06d1600efe8f6aac85290c7f8fAlex Klyubin        protected final int getAdditionalEntropyAmountForFinish() {
1544f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            return (isEncrypting()) ? getModulusSizeBytes() : 0;
1554f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        }
1564f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    }
1574f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
1584f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    /**
1594f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin     * RSA cipher with OAEP encryption padding. Only SHA-1 based MGF1 is supported as MGF.
1604f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin     */
1614f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    abstract static class OAEPWithMGF1Padding extends AndroidKeyStoreRSACipherSpi {
1624f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
1634f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        private static final String MGF_ALGORITGM_MGF1 = "MGF1";
1644f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
1654f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        private int mKeymasterDigest = -1;
1664f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        private int mDigestOutputSizeBytes;
1674f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
1684f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        OAEPWithMGF1Padding(int keymasterDigest) {
1694f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            super(KeymasterDefs.KM_PAD_RSA_OAEP);
1704f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            mKeymasterDigest = keymasterDigest;
1714f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            mDigestOutputSizeBytes =
1724f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                    (KeymasterUtils.getDigestOutputSizeBits(keymasterDigest) + 7) / 8;
1734f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        }
1744f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
1754f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        @Override
1764f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        protected final void initAlgorithmSpecificParameters() throws InvalidKeyException {}
1774f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
1784f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        @Override
1794f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        protected final void initAlgorithmSpecificParameters(
1804f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                @Nullable AlgorithmParameterSpec params) throws InvalidAlgorithmParameterException {
1814f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            if (params == null) {
1824f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                return;
1834f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            }
1844f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
1854f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            if (!(params instanceof OAEPParameterSpec)) {
1864f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                throw new InvalidAlgorithmParameterException(
1874f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                        "Unsupported parameter spec: " + params
1884f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                        + ". Only OAEPParameterSpec supported");
1894f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            }
1904f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            OAEPParameterSpec spec = (OAEPParameterSpec) params;
1914f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            if (!MGF_ALGORITGM_MGF1.equalsIgnoreCase(spec.getMGFAlgorithm())) {
1924f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                throw new InvalidAlgorithmParameterException(
1934f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                        "Unsupported MGF: " + spec.getMGFAlgorithm()
1944f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                        + ". Only " + MGF_ALGORITGM_MGF1 + " supported");
1954f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            }
1964f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            String jcaDigest = spec.getDigestAlgorithm();
1974f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            int keymasterDigest;
1984f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            try {
1994f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                keymasterDigest = KeyProperties.Digest.toKeymaster(jcaDigest);
2004f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            } catch (IllegalArgumentException e) {
2014f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                throw new InvalidAlgorithmParameterException(
2024f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                        "Unsupported digest: " + jcaDigest, e);
2034f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            }
2044f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            switch (keymasterDigest) {
2054f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                case KeymasterDefs.KM_DIGEST_SHA1:
2064f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                case KeymasterDefs.KM_DIGEST_SHA_2_224:
2074f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                case KeymasterDefs.KM_DIGEST_SHA_2_256:
2084f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                case KeymasterDefs.KM_DIGEST_SHA_2_384:
2094f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                case KeymasterDefs.KM_DIGEST_SHA_2_512:
2104f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                    // Permitted.
2114f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                    break;
2124f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                default:
2134f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                    throw new InvalidAlgorithmParameterException(
2144f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                            "Unsupported digest: " + jcaDigest);
2154f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            }
2164f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            AlgorithmParameterSpec mgfParams = spec.getMGFParameters();
2174f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            if (mgfParams == null) {
2184f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                throw new InvalidAlgorithmParameterException("MGF parameters must be provided");
2194f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            }
2204f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            // Check whether MGF parameters match the OAEPParameterSpec
2214f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            if (!(mgfParams instanceof MGF1ParameterSpec)) {
2224f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                throw new InvalidAlgorithmParameterException("Unsupported MGF parameters"
2234f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                        + ": " + mgfParams + ". Only MGF1ParameterSpec supported");
2244f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            }
2254f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            MGF1ParameterSpec mgfSpec = (MGF1ParameterSpec) mgfParams;
2264f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            String mgf1JcaDigest = mgfSpec.getDigestAlgorithm();
2274f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            if (!KeyProperties.DIGEST_SHA1.equalsIgnoreCase(mgf1JcaDigest)) {
2284f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                throw new InvalidAlgorithmParameterException(
2294f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                        "Unsupported MGF1 digest: " + mgf1JcaDigest
2304f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                        + ". Only " + KeyProperties.DIGEST_SHA1 + " supported");
2314f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            }
2324f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            PSource pSource = spec.getPSource();
2334f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            if (!(pSource instanceof PSource.PSpecified)) {
2344f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                throw new InvalidAlgorithmParameterException(
2354f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                        "Unsupported source of encoding input P: " + pSource
2364f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                        + ". Only pSpecifiedEmpty (PSource.PSpecified.DEFAULT) supported");
2374f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            }
2384f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            PSource.PSpecified pSourceSpecified = (PSource.PSpecified) pSource;
2394f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            byte[] pSourceValue = pSourceSpecified.getValue();
2404f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            if ((pSourceValue != null) && (pSourceValue.length > 0)) {
2414f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                throw new InvalidAlgorithmParameterException(
2424f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                        "Unsupported source of encoding input P: " + pSource
2434f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                        + ". Only pSpecifiedEmpty (PSource.PSpecified.DEFAULT) supported");
2444f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            }
2454f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            mKeymasterDigest = keymasterDigest;
2464f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            mDigestOutputSizeBytes =
2474f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                    (KeymasterUtils.getDigestOutputSizeBits(keymasterDigest) + 7) / 8;
2484f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        }
2494f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
2504f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        @Override
2514f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        protected final void initAlgorithmSpecificParameters(@Nullable AlgorithmParameters params)
2524f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                throws InvalidAlgorithmParameterException {
2534f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            if (params == null) {
2544f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                return;
2554f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            }
2564f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
2574f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            OAEPParameterSpec spec;
2584f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            try {
2594f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                spec = params.getParameterSpec(OAEPParameterSpec.class);
2604f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            } catch (InvalidParameterSpecException e) {
2614f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                throw new InvalidAlgorithmParameterException("OAEP parameters required"
2624f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                        + ", but not found in parameters: " + params, e);
2634f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            }
2644f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            if (spec == null) {
2654f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                throw new InvalidAlgorithmParameterException("OAEP parameters required"
2664f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                        + ", but not provided in parameters: " + params);
2674f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            }
2684f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            initAlgorithmSpecificParameters(spec);
2694f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        }
2704f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
2714f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        @Override
2724f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        protected final AlgorithmParameters engineGetParameters() {
2734f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            OAEPParameterSpec spec =
2744f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                    new OAEPParameterSpec(
2754f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                            KeyProperties.Digest.fromKeymaster(mKeymasterDigest),
2764f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                            MGF_ALGORITGM_MGF1,
2774f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                            MGF1ParameterSpec.SHA1,
2784f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                            PSource.PSpecified.DEFAULT);
2794f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            try {
2804f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                AlgorithmParameters params = AlgorithmParameters.getInstance("OAEP");
2814f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                params.init(spec);
2824f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                return params;
2834f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            } catch (NoSuchAlgorithmException e) {
2844f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                throw new ProviderException(
2854f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                        "Failed to obtain OAEP AlgorithmParameters", e);
2864f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            } catch (InvalidParameterSpecException e) {
2874f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                throw new ProviderException(
2884f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                        "Failed to initialize OAEP AlgorithmParameters with an IV",
2894f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                        e);
2904f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            }
2914f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        }
2924f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
2934f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        @Override
2944f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        protected final void addAlgorithmSpecificParametersToBegin(
2954f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                KeymasterArguments keymasterArgs) {
2964f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            super.addAlgorithmSpecificParametersToBegin(keymasterArgs);
297ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin            keymasterArgs.addEnum(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest);
2984f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        }
2994f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
3004f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        @Override
3014f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        protected final void loadAlgorithmSpecificParametersFromBeginResult(
3024f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                @NonNull KeymasterArguments keymasterArgs) {
3034f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            super.loadAlgorithmSpecificParametersFromBeginResult(keymasterArgs);
3044f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        }
3054f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
3064f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        @Override
3074f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        protected final int getAdditionalEntropyAmountForBegin() {
308a72b55195c23fc06d1600efe8f6aac85290c7f8fAlex Klyubin            return 0;
309a72b55195c23fc06d1600efe8f6aac85290c7f8fAlex Klyubin        }
310a72b55195c23fc06d1600efe8f6aac85290c7f8fAlex Klyubin
311a72b55195c23fc06d1600efe8f6aac85290c7f8fAlex Klyubin        @Override
312a72b55195c23fc06d1600efe8f6aac85290c7f8fAlex Klyubin        protected final int getAdditionalEntropyAmountForFinish() {
3134f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            return (isEncrypting()) ? mDigestOutputSizeBytes : 0;
3144f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        }
3154f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    }
3164f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
3174f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    public static class OAEPWithSHA1AndMGF1Padding extends OAEPWithMGF1Padding {
3184f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        public OAEPWithSHA1AndMGF1Padding() {
3194f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            super(KeymasterDefs.KM_DIGEST_SHA1);
3204f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        }
3214f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    }
3224f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
3234f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    public static class OAEPWithSHA224AndMGF1Padding extends OAEPWithMGF1Padding {
3244f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        public OAEPWithSHA224AndMGF1Padding() {
3254f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            super(KeymasterDefs.KM_DIGEST_SHA_2_224);
3264f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        }
3274f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    }
3284f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
3294f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    public static class OAEPWithSHA256AndMGF1Padding extends OAEPWithMGF1Padding {
3304f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        public OAEPWithSHA256AndMGF1Padding() {
3314f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            super(KeymasterDefs.KM_DIGEST_SHA_2_256);
3324f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        }
3334f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    }
3344f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
3354f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    public static class OAEPWithSHA384AndMGF1Padding extends OAEPWithMGF1Padding {
3364f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        public OAEPWithSHA384AndMGF1Padding() {
3374f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            super(KeymasterDefs.KM_DIGEST_SHA_2_384);
3384f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        }
3394f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    }
3404f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
3414f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    public static class OAEPWithSHA512AndMGF1Padding extends OAEPWithMGF1Padding {
3424f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        public OAEPWithSHA512AndMGF1Padding() {
3434f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            super(KeymasterDefs.KM_DIGEST_SHA_2_512);
3444f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        }
3454f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    }
3464f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
3474f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    private final int mKeymasterPadding;
34825d2270704e246d897596c991a36233cdc620790Alex Klyubin    private int mKeymasterPaddingOverride;
3494f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
3504f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    private int mModulusSizeBytes = -1;
3514f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
3524f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    AndroidKeyStoreRSACipherSpi(int keymasterPadding) {
3534f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        mKeymasterPadding = keymasterPadding;
3544f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    }
3554f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
3564f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    @Override
3574f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    protected final void initKey(int opmode, Key key) throws InvalidKeyException {
3584f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        if (key == null) {
3594f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            throw new InvalidKeyException("Unsupported key: null");
3604f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        }
3614f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        if (!KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(key.getAlgorithm())) {
3624f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            throw new InvalidKeyException("Unsupported key algorithm: " + key.getAlgorithm()
3634f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                    + ". Only " + KeyProperties.KEY_ALGORITHM_RSA + " supported");
3644f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        }
3654f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        AndroidKeyStoreKey keystoreKey;
3664f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        if (key instanceof AndroidKeyStorePrivateKey) {
3674f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            keystoreKey = (AndroidKeyStoreKey) key;
3684f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        } else if (key instanceof AndroidKeyStorePublicKey) {
3694f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            keystoreKey = (AndroidKeyStoreKey) key;
3704f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        } else {
3714f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            throw new InvalidKeyException("Unsupported key type: " + key);
3724f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        }
3734f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
3744f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        if (keystoreKey instanceof PrivateKey) {
3755552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin            // Private key
3765552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin            switch (opmode) {
3775552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin                case Cipher.DECRYPT_MODE:
3785552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin                case Cipher.UNWRAP_MODE:
3795552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin                    // Permitted
3805552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin                    break;
3815552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin                case Cipher.ENCRYPT_MODE:
38225d2270704e246d897596c991a36233cdc620790Alex Klyubin                case Cipher.WRAP_MODE:
38325d2270704e246d897596c991a36233cdc620790Alex Klyubin                    if (!adjustConfigForEncryptingWithPrivateKey()) {
3845552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin                        throw new InvalidKeyException(
38525d2270704e246d897596c991a36233cdc620790Alex Klyubin                                "RSA private keys cannot be used with " + opmodeToString(opmode)
38625d2270704e246d897596c991a36233cdc620790Alex Klyubin                                + " and padding "
38725d2270704e246d897596c991a36233cdc620790Alex Klyubin                                + KeyProperties.EncryptionPadding.fromKeymaster(mKeymasterPadding)
3885552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin                                + ". Only RSA public keys supported for this mode");
3895552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin                    }
3905552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin                    break;
3915552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin                default:
3925552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin                    throw new InvalidKeyException(
3935552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin                            "RSA private keys cannot be used with opmode: " + opmode);
3944f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            }
3954f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        } else {
3965552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin            // Public key
3975552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin            switch (opmode) {
3985552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin                case Cipher.ENCRYPT_MODE:
3995552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin                case Cipher.WRAP_MODE:
4005552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin                    // Permitted
401508e665ceaee3e973c17588e8830030662f24b1fAlex Klyubin                    break;
4025552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin                case Cipher.DECRYPT_MODE:
4035552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin                case Cipher.UNWRAP_MODE:
40425d2270704e246d897596c991a36233cdc620790Alex Klyubin                    throw new InvalidKeyException(
40525d2270704e246d897596c991a36233cdc620790Alex Klyubin                            "RSA public keys cannot be used with " + opmodeToString(opmode)
40625d2270704e246d897596c991a36233cdc620790Alex Klyubin                            + " and padding "
40725d2270704e246d897596c991a36233cdc620790Alex Klyubin                            + KeyProperties.EncryptionPadding.fromKeymaster(mKeymasterPadding)
40825d2270704e246d897596c991a36233cdc620790Alex Klyubin                            + ". Only RSA private keys supported for this opmode.");
4095552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin                    // break;
4105552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin                default:
4115552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin                    throw new InvalidKeyException(
41225d2270704e246d897596c991a36233cdc620790Alex Klyubin                            "RSA public keys cannot be used with " + opmodeToString(opmode));
4134f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            }
4144f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        }
4154f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
4164f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        KeyCharacteristics keyCharacteristics = new KeyCharacteristics();
4174f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        int errorCode = getKeyStore().getKeyCharacteristics(
4184f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin                keystoreKey.getAlias(), null, null, keyCharacteristics);
4194f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        if (errorCode != KeyStore.NO_ERROR) {
4204f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            throw getKeyStore().getInvalidKeyException(keystoreKey.getAlias(), errorCode);
4214f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        }
422ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin        long keySizeBits = keyCharacteristics.getUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, -1);
4234f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        if (keySizeBits == -1) {
4244f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            throw new InvalidKeyException("Size of key not known");
425ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin        } else if (keySizeBits > Integer.MAX_VALUE) {
426ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin            throw new InvalidKeyException("Key too large: " + keySizeBits + " bits");
4274f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        }
428ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin        mModulusSizeBytes = (int) ((keySizeBits + 7) / 8);
4294f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
4304f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        setKey(keystoreKey);
4314f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    }
4324f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
43325d2270704e246d897596c991a36233cdc620790Alex Klyubin    /**
43425d2270704e246d897596c991a36233cdc620790Alex Klyubin     * Adjusts the configuration of this cipher for encrypting using the private key.
43525d2270704e246d897596c991a36233cdc620790Alex Klyubin     *
43625d2270704e246d897596c991a36233cdc620790Alex Klyubin     * <p>The default implementation does nothing and refuses to adjust the configuration.
43725d2270704e246d897596c991a36233cdc620790Alex Klyubin     *
43825d2270704e246d897596c991a36233cdc620790Alex Klyubin     * @return {@code true} if the configuration has been adjusted, {@code false} if encrypting
43925d2270704e246d897596c991a36233cdc620790Alex Klyubin     *         using private key is not permitted for this cipher.
44025d2270704e246d897596c991a36233cdc620790Alex Klyubin     */
44125d2270704e246d897596c991a36233cdc620790Alex Klyubin    protected boolean adjustConfigForEncryptingWithPrivateKey() {
4425552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin        return false;
4435552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin    }
4445552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin
4454f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    @Override
4464f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    protected final void resetAll() {
4474f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        mModulusSizeBytes = -1;
44825d2270704e246d897596c991a36233cdc620790Alex Klyubin        mKeymasterPaddingOverride = -1;
4494f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        super.resetAll();
4504f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    }
4514f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
4524f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    @Override
4534f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    protected final void resetWhilePreservingInitState() {
4544f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        super.resetWhilePreservingInitState();
4554f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    }
4564f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
4574f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    @Override
4584f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    protected void addAlgorithmSpecificParametersToBegin(
4594f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            @NonNull KeymasterArguments keymasterArgs) {
460ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin        keymasterArgs.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_RSA);
46125d2270704e246d897596c991a36233cdc620790Alex Klyubin        int keymasterPadding = getKeymasterPaddingOverride();
46225d2270704e246d897596c991a36233cdc620790Alex Klyubin        if (keymasterPadding == -1) {
46325d2270704e246d897596c991a36233cdc620790Alex Klyubin            keymasterPadding = mKeymasterPadding;
46425d2270704e246d897596c991a36233cdc620790Alex Klyubin        }
46525d2270704e246d897596c991a36233cdc620790Alex Klyubin        keymasterArgs.addEnum(KeymasterDefs.KM_TAG_PADDING, keymasterPadding);
4665552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin        int purposeOverride = getKeymasterPurposeOverride();
4675552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin        if ((purposeOverride != -1)
4685552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin                && ((purposeOverride == KeymasterDefs.KM_PURPOSE_SIGN)
4695552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin                || (purposeOverride == KeymasterDefs.KM_PURPOSE_VERIFY))) {
4705552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin            // Keymaster sign/verify requires digest to be specified. For raw sign/verify it's NONE.
471ae6cb7aad56bb006769cd8a69b92af7236644fc1Alex Klyubin            keymasterArgs.addEnum(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_NONE);
4725552c89fa9cb5ac72edbbcb5a71ef14a07f5ea11Alex Klyubin        }
4734f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    }
4744f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
4754f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    @Override
4764f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    protected void loadAlgorithmSpecificParametersFromBeginResult(
4774f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            @NonNull KeymasterArguments keymasterArgs) {
4784f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    }
4794f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
4804f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    @Override
4814f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    protected final int engineGetBlockSize() {
4824f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        // Not a block cipher, according to the RI
4834f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        return 0;
4844f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    }
4854f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
4864f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    @Override
4874f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    protected final byte[] engineGetIV() {
4884f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        // IV never used
4894f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        return null;
4904f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    }
4914f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
4924f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    @Override
4934f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    protected final int engineGetOutputSize(int inputLen) {
4944f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        return getModulusSizeBytes();
4954f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    }
4964f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin
4974f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    protected final int getModulusSizeBytes() {
4984f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        if (mModulusSizeBytes == -1) {
4994f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin            throw new IllegalStateException("Not initialized");
5004f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        }
5014f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin        return mModulusSizeBytes;
5024f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin    }
50325d2270704e246d897596c991a36233cdc620790Alex Klyubin
50425d2270704e246d897596c991a36233cdc620790Alex Klyubin    /**
50525d2270704e246d897596c991a36233cdc620790Alex Klyubin     * Overrides the default padding of the crypto operation.
50625d2270704e246d897596c991a36233cdc620790Alex Klyubin     */
50725d2270704e246d897596c991a36233cdc620790Alex Klyubin    protected final void setKeymasterPaddingOverride(int keymasterPadding) {
50825d2270704e246d897596c991a36233cdc620790Alex Klyubin        mKeymasterPaddingOverride = keymasterPadding;
50925d2270704e246d897596c991a36233cdc620790Alex Klyubin    }
51025d2270704e246d897596c991a36233cdc620790Alex Klyubin
51125d2270704e246d897596c991a36233cdc620790Alex Klyubin    protected final int getKeymasterPaddingOverride() {
51225d2270704e246d897596c991a36233cdc620790Alex Klyubin        return mKeymasterPaddingOverride;
51325d2270704e246d897596c991a36233cdc620790Alex Klyubin    }
5144f389fd200fee9e055d3f28b20bee3132329a056Alex Klyubin}
515