1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 * in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the License 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 * or implied. See the License for the specific language governing permissions and limitations under 12 * the License. 13 */ 14 15 package android.keystore.cts; 16 17 import java.security.InvalidKeyException; 18 import java.security.KeyPair; 19 import java.security.PrivateKey; 20 import java.security.Provider; 21 import java.security.PublicKey; 22 import java.security.Security; 23 import java.security.Signature; 24 import java.security.SignatureException; 25 import java.security.interfaces.RSAKey; 26 import java.util.ArrayList; 27 import java.util.Arrays; 28 import java.util.Collection; 29 import java.util.List; 30 31 import android.keystore.cts.R; 32 33 import android.content.Context; 34 import android.security.keystore.KeyProperties; 35 import android.security.keystore.KeyProtection; 36 import android.test.AndroidTestCase; 37 38 public class RSASignatureTest extends AndroidTestCase { 39 40 private static final String EXPECTED_PROVIDER_NAME = SignatureTest.EXPECTED_PROVIDER_NAME; 41 42 private static final String[] SIGNATURE_ALGORITHMS; 43 44 static { 45 List<String> sigAlgs = new ArrayList<>(); 46 for (String algorithm : SignatureTest.EXPECTED_SIGNATURE_ALGORITHMS) { 47 String keyAlgorithm = TestUtils.getSignatureAlgorithmKeyAlgorithm(algorithm); 48 if (KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(keyAlgorithm)) { 49 sigAlgs.add(algorithm); 50 } 51 } 52 SIGNATURE_ALGORITHMS = sigAlgs.toArray(new String[sigAlgs.size()]); 53 } 54 testMaxMessageSizeWhenNoDigestUsed()55 public void testMaxMessageSizeWhenNoDigestUsed() throws Exception { 56 Provider provider = Security.getProvider(EXPECTED_PROVIDER_NAME); 57 assertNotNull(provider); 58 59 for (ImportedKey keyPair : importKatKeyPairs("NONEwithRSA")) { 60 PublicKey publicKey = keyPair.getKeystoreBackedKeyPair().getPublic(); 61 PrivateKey privateKey = keyPair.getKeystoreBackedKeyPair().getPrivate(); 62 int modulusSizeBits = ((RSAKey) publicKey).getModulus().bitLength(); 63 try { 64 int modulusSizeBytes = (modulusSizeBits + 7) / 8; 65 // PKCS#1 signature padding must be at least 11 bytes long (00 || 01 || PS || 00) 66 // where PS must be at least 8 bytes long). 67 int expectedMaxMessageSizeBytes = modulusSizeBytes - 11; 68 byte[] msg = new byte[expectedMaxMessageSizeBytes + 1]; 69 Arrays.fill(msg, (byte) 0xf0); 70 71 // Assert that a message of expected maximum length is accepted 72 Signature signature = Signature.getInstance("NONEwithRSA", provider); 73 signature.initSign(privateKey); 74 signature.update(msg, 0, expectedMaxMessageSizeBytes); 75 byte[] sigBytes = signature.sign(); 76 77 signature.initVerify(publicKey); 78 signature.update(msg, 0, expectedMaxMessageSizeBytes); 79 assertTrue(signature.verify(sigBytes)); 80 81 // Assert that a message longer than expected maximum length is rejected 82 signature = Signature.getInstance(signature.getAlgorithm(), provider); 83 signature.initSign(privateKey); 84 try { 85 signature.update(msg, 0, expectedMaxMessageSizeBytes + 1); 86 signature.sign(); 87 fail(); 88 } catch (SignatureException expected) { 89 } 90 91 signature.initVerify(publicKey); 92 try { 93 signature.update(msg, 0, expectedMaxMessageSizeBytes + 1); 94 signature.verify(sigBytes); 95 fail(); 96 } catch (SignatureException expected) { 97 } 98 } catch (Throwable e) { 99 throw new RuntimeException("Failed for " + modulusSizeBits + " bit key", e); 100 } 101 } 102 } 103 testSmallKeyRejected()104 public void testSmallKeyRejected() throws Exception { 105 // Use a 512 bit key which should prevent the use of any digests larger than SHA-256 106 // because the padded form of the digested message will be larger than modulus size. 107 Provider provider = Security.getProvider(EXPECTED_PROVIDER_NAME); 108 assertNotNull(provider); 109 110 for (String algorithm : SIGNATURE_ALGORITHMS) { 111 try { 112 String digest = TestUtils.getSignatureAlgorithmDigest(algorithm); 113 if (KeyProperties.DIGEST_NONE.equalsIgnoreCase(digest)) { 114 // Ignore signature algorithms without digest -- this is tested in a separate 115 // test above. 116 continue; 117 } 118 int digestOutputSizeBits = TestUtils.getDigestOutputSizeBits(digest); 119 if (digestOutputSizeBits <= 256) { 120 // 256-bit and shorter digests are short enough to work with a 512 bit key. 121 continue; 122 } 123 124 KeyPair keyPair = TestUtils.importIntoAndroidKeyStore("test1", 125 getContext(), 126 R.raw.rsa_key5_512_pkcs8, 127 R.raw.rsa_key5_512_cert, 128 TestUtils.getMinimalWorkingImportParametersForSigningingWith(algorithm)) 129 .getKeystoreBackedKeyPair(); 130 assertEquals(512, ((RSAKey) keyPair.getPrivate()).getModulus().bitLength()); 131 assertEquals(512, ((RSAKey) keyPair.getPublic()).getModulus().bitLength()); 132 133 Signature signature = Signature.getInstance(algorithm, provider); 134 // Assert that either initSign or sign fails. We don't expect all keymaster 135 // implementations to fail early, during initSign. 136 try { 137 signature.initSign(keyPair.getPrivate()); 138 signature.update("A message".getBytes("UTF-8")); 139 byte[] sigBytes = signature.sign(); 140 fail("Unexpectedly generated a signature (" + sigBytes.length + " bytes): " 141 + HexEncoding.encode(sigBytes)); 142 } catch (InvalidKeyException | SignatureException expected) { 143 } 144 } catch (Throwable e) { 145 throw new RuntimeException("Failed for " + algorithm, e); 146 } 147 } 148 } 149 importKatKeyPairs(String signatureAlgorithm)150 private Collection<ImportedKey> importKatKeyPairs(String signatureAlgorithm) 151 throws Exception { 152 KeyProtection params = 153 TestUtils.getMinimalWorkingImportParametersForSigningingWith(signatureAlgorithm); 154 return importKatKeyPairs(getContext(), params); 155 } 156 importKatKeyPairs( Context context, KeyProtection importParams)157 static Collection<ImportedKey> importKatKeyPairs( 158 Context context, KeyProtection importParams) throws Exception { 159 return Arrays.asList(new ImportedKey[] { 160 TestUtils.importIntoAndroidKeyStore("testRSA512", context, 161 R.raw.rsa_key5_512_pkcs8, R.raw.rsa_key5_512_cert, importParams), 162 TestUtils.importIntoAndroidKeyStore("testRSA768", context, 163 R.raw.rsa_key6_768_pkcs8, R.raw.rsa_key6_768_cert, importParams), 164 TestUtils.importIntoAndroidKeyStore("testRSA1024", context, 165 R.raw.rsa_key3_1024_pkcs8, R.raw.rsa_key3_1024_cert, importParams), 166 TestUtils.importIntoAndroidKeyStore("testRSA2048", context, 167 R.raw.rsa_key8_2048_pkcs8, R.raw.rsa_key8_2048_cert, importParams), 168 TestUtils.importIntoAndroidKeyStore("testRSA3072", context, 169 R.raw.rsa_key7_3072_pksc8, R.raw.rsa_key7_3072_cert, importParams), 170 TestUtils.importIntoAndroidKeyStore("testRSA4096", context, 171 R.raw.rsa_key4_4096_pkcs8, R.raw.rsa_key4_4096_cert, importParams), 172 }); 173 } 174 } 175