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