1 /*
2  * Copyright 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.keystore.cts;
18 
19 import static org.junit.Assert.assertArrayEquals;
20 import static org.junit.Assert.assertEquals;
21 import static org.junit.Assert.assertFalse;
22 import static org.junit.Assert.assertNotNull;
23 import static org.junit.Assert.assertSame;
24 import static org.junit.Assert.assertTrue;
25 import static org.junit.Assert.fail;
26 
27 import android.content.Context;
28 import android.keystore.cts.util.EmptyArray;
29 import android.keystore.cts.util.ImportedKey;
30 import android.keystore.cts.util.StrictModeDetector;
31 import android.keystore.cts.util.TestUtils;
32 import android.security.keystore.KeyInfo;
33 import android.security.keystore.KeyPermanentlyInvalidatedException;
34 import android.security.keystore.KeyProperties;
35 import android.security.keystore.KeyProtection;
36 
37 import androidx.test.InstrumentationRegistry;
38 import androidx.test.runner.AndroidJUnit4;
39 
40 import org.junit.Test;
41 import org.junit.runner.RunWith;
42 
43 import java.security.InvalidKeyException;
44 import java.security.KeyFactory;
45 import java.security.KeyPair;
46 import java.security.KeyStore;
47 import java.security.PrivateKey;
48 import java.security.Provider;
49 import java.security.Provider.Service;
50 import java.security.PublicKey;
51 import java.security.Security;
52 import java.security.Signature;
53 import java.security.SignatureException;
54 import java.util.Arrays;
55 import java.util.Collection;
56 import java.util.Date;
57 import java.util.HashSet;
58 import java.util.Locale;
59 import java.util.Map;
60 import java.util.Set;
61 import java.util.TreeMap;
62 
63 /**
64  * Tests for algorithm-agnostic functionality of {@code Signature} implementations backed by Android
65  * Keystore.
66  */
67 @RunWith(AndroidJUnit4.class)
68 public class SignatureTest {
69 
70     static final String EXPECTED_PROVIDER_NAME = TestUtils.EXPECTED_CRYPTO_OP_PROVIDER_NAME;
71 
72     static final String[] EXPECTED_SIGNATURE_ALGORITHMS = {
73         "NONEwithRSA",
74         "MD5withRSA",
75         "SHA1withRSA",
76         "SHA224withRSA",
77         "SHA256withRSA",
78         "SHA384withRSA",
79         "SHA512withRSA",
80         "SHA1withRSA/PSS",
81         "SHA224withRSA/PSS",
82         "SHA256withRSA/PSS",
83         "SHA384withRSA/PSS",
84         "SHA512withRSA/PSS",
85         "NONEwithECDSA",
86         "SHA1withECDSA",
87         "SHA224withECDSA",
88         "SHA256withECDSA",
89         "SHA384withECDSA",
90         "SHA512withECDSA"
91     };
92 
93     private static final Map<String, String> SIG_ALG_TO_CANONICAL_NAME_CASE_INSENSITIVE =
94             new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);
95     static {
96         // For an unknown legacy reason, libcore's ProviderTest#test_Provider_getServices insists
97         // that a Service with algorithm "ECDSA" be exposed, despite the RI not exposing any such
98         // services. Thus, our provider has to expose the "ECDSA" service whose actual proper
99         // name is SHA1withECDSA.
100         SIG_ALG_TO_CANONICAL_NAME_CASE_INSENSITIVE.put("ECDSA", "SHA1withECDSA");
101     }
102 
103     private static final byte[] SHORT_MSG_KAT_MESSAGE =
104             HexEncoding.decode("ec174729c4f5c570ba0de4c424cdcbf0362a7718039464");
105     private static final byte[] LONG_MSG_KAT_SEED = SHORT_MSG_KAT_MESSAGE;
106     private static final int LONG_MSG_KAT_SIZE_BYTES = 3 * 1024 * 1024 + 123;
107 
108     private static final Map<String, byte[]> SHORT_MSG_KAT_SIGNATURES =
109             new TreeMap<String, byte[]>(String.CASE_INSENSITIVE_ORDER);
110     static {
111         // From RI
112         SHORT_MSG_KAT_SIGNATURES.put("NONEwithECDSA", HexEncoding.decode(
113                 "304402201ea57c2fb571991639d103bfec658ee7f359b60664e400a5834cfc20d28b588902202433f5"
114                 + "eb07d2b03bf8d238ea256ea399d0913a6cfcae2c3b00e2efd50aebc967"));
115         SHORT_MSG_KAT_SIGNATURES.put("SHA1withECDSA", HexEncoding.decode(
116                 "30440220742d71a013564ab196789322b9231ac5ff26460c2d6b1ab8ccb45eec254cc8ba0220780a86"
117                 + "5ddc2334fae23d563e3142b04660c2ab1b875c4ff8c557a1d1accc43e1"));
118         SHORT_MSG_KAT_SIGNATURES.put("SHA224withECDSA", HexEncoding.decode(
119                 "304502200f74966078b34317daa69e487c3163dbb4e0391cd74191cc3e95b33fc60966e3022100ebdc"
120                 + "be19c516d550609f73fb37557a406e397bc1725a1baba50cdfc3537bd377"));
121         SHORT_MSG_KAT_SIGNATURES.put("SHA256withECDSA", HexEncoding.decode(
122                 "304402204443b560d888beeae729155b0d9410fef2ec78607d9166af6144346fba8ce45d02205b0727"
123                 + "bfa630050f1395c8bcf46c614c14eb15f2a6abbd3bc7c0e83b41819281"));
124         SHORT_MSG_KAT_SIGNATURES.put("SHA384withECDSA", HexEncoding.decode(
125                 "3045022025ade03446ce95aa525a51aedd16baf12a2b8b9c1f4c87224c38e48c84cbbbf8022100ad21"
126                 + "8424c3671bc1513e1da7e7186dbc6bf67bec434c95863a48e79f53684971"));
127         SHORT_MSG_KAT_SIGNATURES.put("SHA512withECDSA", HexEncoding.decode(
128                 "3045022100969e8fed2dc4ddcdf341368e057efe4e3a00eda66bbb127dec31bb0144c5334602201087"
129                 + "2b7f9ab9c06a07053e0641e6adc18a87a1d7807550a19e872e78e5c7f0dd"));
130 
131         // From RI
132         SHORT_MSG_KAT_SIGNATURES.put("NONEwithRSA", HexEncoding.decode(
133                 "257d0704e514ead29a5c45576adb2d5a7d7738e6a83b5d6463a5306788015d14580fee340e78e00d39"
134                 + "f56ae616083ac929e5daf9eeab40b908eb05d0cd1036d9e92799587df0d4c5304c9b27f913e1c891"
135                 + "919eff0df3b5d9c0d8cc4cd843795840799cc0353192c3868b3f8cad96d04bb566ca53e1146aa2a3"
136                 + "4b890ce917680bbdea1dee417a89630224d2ee79d66d38c7c77e50b45e1dd1b8b63eb98ecd60426b"
137                 + "c9fb30917e78ae4dd7cbfa9475f9be53bf45e7032add52681553679252f4f74de77831c95ea69f30"
138                 + "2f0fd28867de058728455e3537680c86a001236e70c7680c78b4dc98942d233b968635a0debccb41"
139                 + "fbc17ece7172631f5ab6d578d70eb0"));
140         SHORT_MSG_KAT_SIGNATURES.put("MD5withRSA", HexEncoding.decode(
141                 "1e1edefc9a6a4e61fcef0d4b202cc2b53ab9043b1a0b21117d122d4c5399182998ec66608e1ab13513"
142                 + "08fbb23f92d5d970f7fb1a0691f8d1e682ff4f5e394ef2dfcbdc2de5c2c33372aec9a0c7fba982c5"
143                 + "c0f1a5f65677d9294d54a2e613cc0e5feb919135e883827da0e1c222bf31336afa63a837c57c0b70"
144                 + "70ceb8a24492a42afa6750cc9fe3a9586aa15507a65410db973a4b26734624d323dc700928717789"
145                 + "fb1f970d57326eef49e012fcebcfbbfd18fb4d6feff03587d0f2b0a556fe467437a44a2283ea5027"
146                 + "6efda4fd427365687960e0c289c5853a7b300ff081511a2f52899e6f6a569b30e07adfd52e9d9d7e"
147                 + "ab33999da0da1dd16d4e88bd980fcd"));
148         SHORT_MSG_KAT_SIGNATURES.put("SHA1withRSA", HexEncoding.decode(
149                 "280977b4ee18cbe27d3e452c9b90174f5d81dd518018ce52ff1cd1e8d4d0626afca85be14a43fa3b76"
150                 + "a80e818b4bc10abc62180fa15619d78be98ccd8fa642ea05355aa84f2924e041c2b594b1cf31d42b"
151                 + "f11c78dd3cbb6cc2cbfe151792985e6e5cf73c2e600a38f31e26e84c3e4a434f67a625fefe712d17"
152                 + "b34125ea91d333cfe1c4ac914b6c411b08e64700885325e07510c4f49ef3648252736f17d3ae7705"
153                 + "0054ceb07ab04b5ecaa5fc4556328bad4f97eba37f9bf079506e0eb136c9eadf9e466ccb18d65b4d"
154                 + "ef2ba3ca5c2f33354a2040dfb646423f96ba43d1d8f3dcf91c0c2c14e7958159d2ac3ebc0b6b87e6"
155                 + "6efbdda046ce8a766fecc3f905d6ff"));
156         SHORT_MSG_KAT_SIGNATURES.put("SHA224withRSA", HexEncoding.decode(
157                 "490af9e685ef44da9528d9271d00e09a3e688012bf3f63fd924a06cb4db747a28cdf924c2d51620165"
158                 + "33985abf4b91d64c17ff7e2b4f0de5a28375dddf556cd9e5dcebd112f766f07cb867e8d5710ce79a"
159                 + "1c3d5244cbd16618b0fedc2b9015d51a98d453747fb320b97995ea9579adbc8bf6042b2f4252cef1"
160                 + "787207fefaf4b9c7212fe0ff8b22ae12ffc888f0a1e6923455577e82b58608dabc2acba05be693ff"
161                 + "ae7da263d6c83cb13d59a083f177578d11030f8974bdb301f6135ecd5ec18dd68dc453c5963e94b6"
162                 + "2d89bcda0ff63ac7394030f79b59139e1d51573f0d4a1e85d22502c9b0d29412f7eb277fb42fa4db"
163                 + "18875baffa7719b700e4830edbcd6f"));
164         SHORT_MSG_KAT_SIGNATURES.put("SHA256withRSA", HexEncoding.decode(
165                 "1f1adcd6edbf4c50777c932db6e99a577853fbc9c71c692e921291c5aa73eb0155e30c8d4f3aff828f"
166                 + "2040c84e10b1ba729ccc23899650451022fcd3574df5454b01112adec5f01565b578bbc7c32810c9"
167                 + "407106054ad8f4f640b589ddef264d028ad906536d61c8053ef0dba8e10ca2e30a9dd6ccc9a9ec3e"
168                 + "76c10d36029820865b2d01095987af4a29369ffc6f70fa7e1de2b8e28f41894df4225cf966454096"
169                 + "7fb7ecff443948c8a0ee6a1be51e0f8e8887ff512dbdc4fc81636e69ae698000ce3899c2ec999b68"
170                 + "691adfb53092380264b27d91bd64561fee9d2e622919cf6b472fd764dc2065ae6a67df2c7b5ec855"
171                 + "099bdb6bb104ee41fa129c9da99745"));
172         SHORT_MSG_KAT_SIGNATURES.put("SHA384withRSA", HexEncoding.decode(
173                 "3b5e8baa62803569642fa8c3255249709c9f1d69bd31f7b531d5071c07cd9bac29273097666d96b2e3"
174                 + "2db13529b6414be5aee0c8a90c3f3b2a5c815f37fac16a3527fa45903f847416ed218eee2fef5b87"
175                 + "5f0c97576f58b3467e83497c1cdeea44d0ea151e9c4d27b85eef75d612b1fc16731859738e95bdf1"
176                 + "2f2098ebd501d8493c66585e8545fb13d736f7dbbb530fb06f6f157cd10c332ca498b379336efdaf"
177                 + "a8f940552da2dbb047c33e87f699068eaadd6d47c92a299f35483ba3ae09f7e52a205f202c1af997"
178                 + "c9bdc40f423b3767292c7fcea3eaf338a76f9db07a53d7f8d084bf1ceac38ec0509e442b1283cd8f"
179                 + "013c4c7a9189fe4ef9ab00c80cb470"));
180         SHORT_MSG_KAT_SIGNATURES.put("SHA512withRSA", HexEncoding.decode(
181                 "23eb7577d2ffefed10780c2a26f79f64abe08203e900db2333413f30bbc81f800857857c8b0e02c3e8"
182                 + "8fe3cf5514130d6216ef7c4a86b1012594c7cb07a293159b92bf40291224386a84e607e0a8389c8a"
183                 + "a0c45cc553037517c52f61fe0ea51dba184e890db7d9517760724c038018330c0a9450c280430e6f"
184                 + "9e4cdd4545c3f6684485cd6e27203735ff4be76420071920b18c54d98c0e3eb7ae7d1f01f5171ace"
185                 + "87885c6185f66d947d51a441a756bc953458f7d3a1714226899562478ebf91ab18d8e7556a966661"
186                 + "31de37bc2e399b366877f53c1d88f93c989aeb64a43f0f6cbc2a29587230f7e3e90ea18868d79584"
187                 + "3e62b49f5df78e355b437ec2f882f9"));
188 
189         // From Bouncy Castle
190         SHORT_MSG_KAT_SIGNATURES.put("SHA1withRSA/PSS", HexEncoding.decode(
191                 "17e483781695067a25bc7cb204429a8754af36032038460e1938c28cd058025b14d2cffe5d3da39e76"
192                 + "6542014e5419f1d4c4d7d8e3ebcd2221dde04d24bbbad657f6782b7a0fada3c3ea595bc21054b0ab"
193                 + "d1eb1ada86276ed31dbcce58be7407cbbb924d595fbf44f2bb6e3eab92296076e291439107e67912"
194                 + "b4fac3a27ff84af7cd2db1385a8340b2e49c7c2ec96a6b657a1641da80799cb88734cca35a2b3a2c"
195                 + "4af832a34ac8d3134ccc8b61150dc1b64391888a3a84bdb5184b48e8509e8ba726ba8847e4ca0640"
196                 + "ce615e3adf5248ce08adb6484f6f29caf6c65308ec6351d97369ae005a7c762f76f0ddc0becc3e45"
197                 + "529aa9c8391473e392c9a60c2d0834"));
198         SHORT_MSG_KAT_SIGNATURES.put("SHA224withRSA/PSS", HexEncoding.decode(
199                 "3b7641a49e7766ed879f2b0e33ceb3d935678a7deffbd855a97abf00a65c981814ac54a71150b2ffea"
200                 + "d5db83aa96d0939267b3c5e2fcf958e9c6fdf7d90908e6139f7f330a16dc625d8268ffd324659f6c"
201                 + "e36798ef3b71a92f1d2237e3ce1e281aacc1d5370ae63c9b75e7134ad15cca1410746bf259ac4519"
202                 + "c407877503900ec8f3b71edce727e9d0275c9cd48385f89ce76ed17a2bf246578f183bb6577d6942"
203                 + "2056c7d9145528fc8ca036926a9fafe819f37c1a4a0a69b17f3d4b0a116106f94a5d2a5f8ce6981c"
204                 + "d6e5c2f858dcb0823e725fffe6be14ca882c81fa993bebda549fcf983eb7f8a87eccd545951dcdc9"
205                 + "d8055ae4f4067de997cfd89952c905"));
206         SHORT_MSG_KAT_SIGNATURES.put("SHA256withRSA/PSS", HexEncoding.decode(
207                 "6f0f744fa8e813b4c7caa0c395c1aa8aee0d61e621b4daae305c759b5b5972311ad691f8867821efba"
208                 + "d57995cc8ff38f33393293e94e1c484e94de4816b0fd986f5710a02d80e62461cc6f87f1f3742268"
209                 + "c28a54870f290d136aa629cbe00a1bf243fab1674c04cd5910a786b2ac5e71d9c6f4c41daa4c584d"
210                 + "46ba7ee768d2d2559be587a7b2009f3b7497d556a0da8a8ae80ce91152c81ffba62720d36b699d1f"
211                 + "157137ff7ee7239fc4baf611d01582346e201900f7a4f2617cdf574653e124fb895c6cb76d4ed5a8"
212                 + "aca97d1e408e8011eba649d5617bae8b27c1b946dcff7b29151d8632ad128f22907e8b83b9149e16"
213                 + "fbb9e9b87600a2f90c1fd6dc164c52"));
214         SHORT_MSG_KAT_SIGNATURES.put("SHA384withRSA/PSS", HexEncoding.decode(
215                 "8e57992362ad4b0487a707b2f8811d953f5aaf800978859981e7dcddad6f9f411fb162859115577c53"
216                 + "7a3524e26bf069508185848d6e29e7da1f9660a49771533e43853e02232314afd2928a1ff1824345"
217                 + "a5a90309a59d213ff6a4d04520f95a976342e6ac529ec6a6821157f4fee3bdae30d836d3ab44386d"
218                 + "3914e6aacd6a6a63e1d63b4d9bfb93b343b6c1f28d60042ffbe1e46fb692a381456e84b3328dbcae"
219                 + "ed6fc577cb1c5f86a38c5c34d439eeee7e798edc9f2bcd4fc217b1630e45b8df67def2c2cdb9fea0"
220                 + "5d67aa6cce6e9a72e9a114e2e620a54c05755e32685ffc7e50487c3cd00888c09492fad8c461c338"
221                 + "e7d099b275deaf184b7d6689385f7c"));
222         SHORT_MSG_KAT_SIGNATURES.put("SHA512withRSA/PSS", HexEncoding.decode(
223                 "7a40f9f2797beda0702df0520c7138269295a0f0328aab4eba123ebf178ea4abc745ed42d3b175dc70"
224                 + "c8dcc98f46f2234b392dbb3e939f30888715c4fbb47fbb5bb7c0557c140c579f48226710e5b3da0d"
225                 + "9511337cde5626df586b4004100dd45490e5f8ae23307b5d1054c97e9ef58f9c385ca55b6db4f58d"
226                 + "2e19bc8ca9d8c2b4922fb3325b6fb61fc40a359e9196aa9388845b136d2790d71410e20371dcf0a7"
227                 + "0425ee1854c5c3d7de976b28de0ee9b1048ed99b2a957edc97466cc4c87e36224fd323605228f61a"
228                 + "1aad30253b0698f9a358491138027d325d46bdfdf72171c57a2dab0a9cddaad8e170b8275c172e42"
229                 + "33b29ed81c0f4de9fe9f0670106aad"));
230     }
231 
232     private static final Map<String, byte[]> LONG_MSG_KAT_SIGNATURES =
233             new TreeMap<String, byte[]>(String.CASE_INSENSITIVE_ORDER);
234     static {
235         // From RI
236         LONG_MSG_KAT_SIGNATURES.put("NONEwithECDSA", HexEncoding.decode(
237                 "304502206e4039608a66ce118821eeca3e2af7f530f51d1ce8089685a13f49010e3cd58b02210083a5"
238                 + "fe62a171f1b1d775fad712128a223d6b63336e0248783652474221cb3193"));
239         LONG_MSG_KAT_SIGNATURES.put("SHA1withECDSA", HexEncoding.decode(
240                 "3044022075f09bb5c87d883c088ca2ad263bbe1754ab614f727465bc43695d3521eaccf80220460e4e"
241                 + "32421e6f4398cd9b7fbb31a1d1f2961f26b9783620f6413f0e6f7efb84"));
242         LONG_MSG_KAT_SIGNATURES.put("SHA224withECDSA", HexEncoding.decode(
243                 "3045022100d6b24250b7d3cbd329913705f4990cfd1000f338f7332a44f07d7731bd8e1ff602200565"
244                 + "0951e14d0d21c4344a449843ef65ac3a3f831dc7f304c0fa068c996f7d34"));
245         LONG_MSG_KAT_SIGNATURES.put("SHA256withECDSA", HexEncoding.decode(
246                 "30440220501946a2c373e8da19b36e3c7718e3f2f2f16395d5026ac4fbbc7b2d53f9f21a0220347d7a"
247                 + "46685282f308bacd5fb25ae92b351228ea39082784789696580f27eed1"));
248         LONG_MSG_KAT_SIGNATURES.put("SHA384withECDSA", HexEncoding.decode(
249                 "30450220576836de4ab94a869e867b2360a71dc5a0b3351ea1c896b163206db7c3507dc2022100c1a6"
250                 + "719052a175e023bca7f3b9bb7a379fc6b51864cb28a195076d2f3c79ed2e"));
251         LONG_MSG_KAT_SIGNATURES.put("SHA512withECDSA", HexEncoding.decode(
252                 "304402204ca46bac4e43e8694d1af38854c96024a4e9bcc55c6904c1f8fea0d1927f69f7022054662e"
253                 + "84b4d16b9f7e8164f4896212dec3c7c1e7fd108f69b0dff5bc15399eeb"));
254 
255         // From RI
256         LONG_MSG_KAT_SIGNATURES.put("MD5withRSA", HexEncoding.decode(
257                 "7040f3e0d95f4d22719d26e5e684dbcd5ed52ab4a7c5aa51b938b2c060c79eb600f9c9771c2fcda7e3"
258                 + "55e7c7b5e2ba9fe9a2a3621881c0fe51702781ffcde6ce7013218c04bb05988346c2bed99afb97a8"
259                 + "113fb50697adf93791c9129e938040f91178e35d6f323cfa515ea6d2112e8cce1302201b51333794"
260                 + "4a5c425cecc8181842ace89163d84784599ea688060ad0d61ac92b673feabe01ae5e6b85d8b5e8f0"
261                 + "519aea3c29781e82df9153404d027d75df8370658898ed348acf4e13fd8f79c8a545881fbbf585e1"
262                 + "c666be3805e808819e2cc730379f35a207f9e0e646c7ab6d598c75b1901f0c5ca7099e34f7f01579"
263                 + "3b57dfb5c2a32e8423bfed6215f9d0"));
264         LONG_MSG_KAT_SIGNATURES.put("SHA1withRSA", HexEncoding.decode(
265                 "187d7689206c9dd03861009c6cb62c7752fd2bbc354f0bea4e76059fe582744c80027175112a3df4b6"
266                 + "3b4a5626ed3051192e3c9b6d906497472f6df81171064b59114ff5d7c60f66943549634461cfadd8"
267                 + "a033cba2b8781fb7936ea1ca0043da119856a21e533afa999f095cf87604bb33a14e8f82fab01998"
268                 + "9ef3133e8069708670645ddd5cdc86bbe19fbf672b409fb6d7cae2f913814cd3dc8d5ae8e4037ccf"
269                 + "4a3ef97db8c8a08516716258c4b767607c51dfb289d90af014d3cfc64dbadb2135ed59728b78fda0"
270                 + "823fe7e68e84280c283d21ab660364a9bf035afa9a7262bade87057a63aa1d7e2c09bb9dd037bcbd"
271                 + "7b98356793bc32be81623833c6ab62"));
272         LONG_MSG_KAT_SIGNATURES.put("SHA224withRSA", HexEncoding.decode(
273                 "31ff68ddfafcf3ff6e651c93649bf9cc06f4138493317606d8676a8676f9d9f3a1d5e418358f79d143"
274                 + "a922a3cfc5e1ad6765dc829b556c9019a6d9389144cc6a7571011c024c0514891970508dac5f0d26"
275                 + "f26b536cf3e4511b5e72cd9f60590b387d8a351a9f28839a1c5be5272cb75a9062aa313f3d095074"
276                 + "6d0a21d4f8c9a94d3bb4715c3ef0207cf1335653161a8f78972329f3ec2fa5cfe05318221cb1f535"
277                 + "8151dde5410f6c36f32287a2d5e76bf36134d7103fc6810a1bb8627de37d6b9efde347242d08b0b6"
278                 + "2b1d73bacd243ccc8546536080b42a82b7162afeb4151315746a14b64e45226c9f5b35cf1577fc6b"
279                 + "f5c882b71deb7f0e375db5c0196446"));
280         LONG_MSG_KAT_SIGNATURES.put("SHA256withRSA", HexEncoding.decode(
281                 "529c70877dedf3eb1abda98a2f2b0fc899e1edece70da79f8f8bbceb98de5c85263bef2ef8a7322624"
282                 + "5ed2767045ea6965f35cb53e6ac1d6c62e8007a79962507d3e01c77d4e96674344438519adae67d9"
283                 + "6357da5c4527969c939fd86f3b8685338c2be4bf6f1f85527b11fcaa4708f925e8bb9b877bda179b"
284                 + "d1b45153ef22834cf593ecc5b6eca3deddbe5d05894e4e5707d71bc35ea879ccb6e8ffc32e0cdc5e"
285                 + "88a30eef7a608d9ea80b5cefec2aa493a3b1354ad20e88ab1f8bfda3bd9961e10f0736d1bc090d57"
286                 + "b93fbce3e6e2fc99e67c7b466188d1615b4150c206472e48a9253b7549cebf6c7cbb558b54e10b73"
287                 + "c8b1747c18d1890a24d0a835ee710a"));
288         LONG_MSG_KAT_SIGNATURES.put("SHA384withRSA", HexEncoding.decode(
289                 "5dd3553bc594c541937dac9a8ac119407712da7564816bcdc0ca4e14bc6059b9f9bd72e99be8a3df3e"
290                 + "0a3c4e8ed643db9ed528b43a396dba470ad3307815bd7c75fa5b08775a378cc4203341379087dcb3"
291                 + "62a5e9f5c979744e4498a6aafd1b1a8069caf4ef437f2743754861fcc96d67a0f1dd3397bb65ede3"
292                 + "18d2b3628eb2c3ec5db8a3e21fbbe2629f1030641e420963abc4da99e24dd497337c8149a52d97da"
293                 + "7176c0767d72e18f8c9a49e6808509837f719fd16ba27b19a2b32bd19b9b14818e0b9be81062be77"
294                 + "4fb1b3105a1528170822391915a5cd12b8e79aaab7943c34094da4c4f8d56f52177db953d3bf7846"
295                 + "f0e5f22f2311054a1daba4fec6b589"));
296         LONG_MSG_KAT_SIGNATURES.put("SHA512withRSA", HexEncoding.decode(
297                 "971d6350337866fbcb48c49446c50cac1995b822cfec8f2a3e2c8206158a2ddfc8fc7b38f5174b3288"
298                 + "91489e7b379829bac5e48cd41e9713ea7e2dc9c61cf90d255387d31818d2f161ec5c3a977b4ce121"
299                 + "62fb11ede30d1e63c0fbba8a4094e6ad39e64176a033e7130bbed71a67ff1713b45f0bedeb1ee532"
300                 + "15690f169452c061cd7d15e71cc754a2f233f5647af8373d2b583e98e4242c0a0581e0ce2b22e15a"
301                 + "443b0ff23d516ed39664f8b8ab5ca98a44af500407941fae97f37cb1becbcbff453608cb94a176d9"
302                 + "e702947fff80bc8d1e9bcdef2b7bbe681e15327cee50a72649aed0d730df7b3c9c31b165416d9c9f"
303                 + "1fcb04edbf96514f5758b9e90ebc0e"));
304 
305         // From Bouncy Castle
306         LONG_MSG_KAT_SIGNATURES.put("SHA1withRSA/PSS", HexEncoding.decode(
307                 "54a2050b22f6182b65d790da80ea16bfbc34b0c7e564d1a3ce4450e9b7785d9eaa14814dee8699977a"
308                 + "e8da5cfb3c55c9a623ca55abcc0ef4b3b515ce31d49a78db442f9db270d35a179baf71057fe8d6d2"
309                 + "d3f7e4fd5f5c80e11dc059c72a1a0373f527d88089c230525f895ee19e45f5547572083418c9e542"
310                 + "5ff44e407500d1c49159484f38e4b00523c2fa45b7b9b38a2c1ad676b36f02a06db6fca52bd79ba1"
311                 + "94d5062f5035a12a1f026ac216789844a5da0caa4d481386a12ca635c06b877515ce3782d9189d87"
312                 + "d1ff5ec6ec7c39437071c8db7d1c2702205da4cfb01805ca7fec5595dba2234602ca5347d30538cb"
313                 + "4b5286c151609afcca890a6276d5e8"));
314         LONG_MSG_KAT_SIGNATURES.put("SHA224withRSA/PSS", HexEncoding.decode(
315                 "7e95c1e4f700ceaf9ce72fd3f9f245ba80f2e1341341c49521779c8a79004f9c534297441330b9df36"
316                 + "bb23467eb560e5e5538612cecc27953336a0d4d8044d5a80f6bcef5299830215258c574d271ea6cd"
317                 + "7117c2723189385435b0f06951ff3d6a700b23bc7ed3298cfb6aa65e8f540717d57f8b55290a4862"
318                 + "034d9f73e8d9cb6ae7fa55a8b4c127535b5690122d6405cb0c9a313808327cfd4fb763eae875acd1"
319                 + "b60e1920ecf1116102cc5f7d776ed88e666962f759258d6f5454c29cb99b8f9ccad07d209671b607"
320                 + "014d19009e392bfb08247acf7f354458dc51196d84b492798dd829b7300c7591d42c58f21bd2c3d1"
321                 + "e5ce0a0d3e0aa8aa4b090b6a619fc6"));
322         LONG_MSG_KAT_SIGNATURES.put("SHA256withRSA/PSS", HexEncoding.decode(
323                 "5a8c0ae593a6714207b3ad83398b38b93da18cfda73139ea9f02c88a989368ae6901357194a873dd2e"
324                 + "8cd1bb86d1f81fbc8bf725538dc2ad60759f8caab6a98a6baa6014874a92d4b92ed72e73f2721ba2"
325                 + "86e545924860d27210b53f9308c4fec622fdfca7dd6d51a5b092184114e9dcf57636cdabaca17b49"
326                 + "70cd5e93ce12c30af6d09d6964c5ad173095ea000529620d94a25b4cc977deefd25cc810a7b11cd5"
327                 + "e5b71c9276b0bd33c53db01304b359a4a88f3fe8bc3335669f7609b0f6da17e49ad87f38468fa2c6"
328                 + "8134ba6df407207559355b6e486a745009931796ab0567c9bd61788073aa00113b324fa25bd32b4d"
329                 + "3521e98e0b4905c6dce30d70387a2e"));
330         LONG_MSG_KAT_SIGNATURES.put("SHA384withRSA/PSS", HexEncoding.decode(
331                 "7913f13dc399adb07cd96c1bb484f999d047efcd96501c92477d2234a1da94db9c6fd65a8031bd3040"
332                 + "82d90ef4a4f388e670795d144ef72a160583d4a2c805415542fa16ffd8760d2f28bdc82f63db0900"
333                 + "a3554bc9175dafa1899249abd49591216ba2965a4862d0f59d8b8c8d1042ed7ac43a3a15650d578a"
334                 + "2ea53696e462f757b326b7f0f7610fb9934aee7d954a45ca03ef66464a5611433e1224d05f783cd1"
335                 + "935eff90015140cb35e15f2bbf491a0d6342ccef57e453f3462412c5ff4dfdc44527ea76c6b05b1d"
336                 + "1330869aec1b2f41e7d975eba6b056e7c2f75dd73b1eff6d853b9507f410279b02f9244b656a1aca"
337                 + "befcc5e1167df3a49c4a7d8479c30f"));
338         LONG_MSG_KAT_SIGNATURES.put("SHA512withRSA/PSS", HexEncoding.decode(
339                 "43ffefe9c96014312679a2e3803eb7c58a2a4ab8bb659c12fec7fb574c82aed673e21ed86ac309cf6c"
340                 + "e567e47b7c6c83dcd72e3ee946067c2004689420528174d028e3d32b2b306bcbcb6a9c8e8b83918f"
341                 + "7415d792f9d6417769def3316ed61898443d3ffa4dc160e5b5ecf4a11a9dfed6b4a7aa65f0f2c653"
342                 + "4f7e514aed73be441609ffca29207b4ced249058543fd6e13a02ef42babe2cdf4aaba66b42e9d47f"
343                 + "c79b4ed54fbc28d9d732f2e468d43f0ca1de6fd5312fad2c4e3eaf3e9586bca6a8bab24b4dfab8b3"
344                 + "9a4057c8ed27024b61b425036bea5e23689cd9db2450be47ec2c30bb6707740c70a53b3e7a1c7ecf"
345                 + "f04e3de1460e60e9be7a42b1ddff0c"));
346     }
347 
348     private static final long DAY_IN_MILLIS = TestUtils.DAY_IN_MILLIS;
349 
getContext()350     private Context getContext() {
351         return InstrumentationRegistry.getInstrumentation().getTargetContext();
352     }
353 
354     @Test
testAlgorithmList()355     public void testAlgorithmList() {
356         // Assert that Android Keystore Provider exposes exactly the expected signature algorithms.
357         // We don't care whether the algorithms are exposed via aliases, as long as the canonical
358         // names of algorithms are accepted.
359         // If the Provider exposes extraneous algorithms, it'll be caught because it'll have to
360         // expose at least one Service for such an algorithm, and this Service's algorithm will
361         // not be in the expected set.
362 
363         Provider provider = Security.getProvider(EXPECTED_PROVIDER_NAME);
364         Set<Service> services = provider.getServices();
365         Set<String> actualSigAlgsLowerCase = new HashSet<String>();
366         Set<String> expectedSigAlgsLowerCase = new HashSet<String>(
367                 Arrays.asList(TestUtils.toLowerCase(EXPECTED_SIGNATURE_ALGORITHMS)));
368         //TODO(b/233037333): Move this value to the EXPECTED_SIGNATURE_ALGORITHMS array, once
369         //we have confirmed key import is working for Ed25519 and have a key to import.
370         expectedSigAlgsLowerCase.add("ed25519");
371         for (Service service : services) {
372             if ("Signature".equalsIgnoreCase(service.getType())) {
373                 String algLowerCase = service.getAlgorithm().toLowerCase(Locale.US);
374                 if (!expectedSigAlgsLowerCase.contains(algLowerCase)) {
375                     // Unexpected algorithm -- check whether it's an alias for an expected one
376                     String canonicalAlgorithm =
377                             SIG_ALG_TO_CANONICAL_NAME_CASE_INSENSITIVE.get(algLowerCase);
378                     if (canonicalAlgorithm != null) {
379                         // Use the canonical name instead
380                         algLowerCase = canonicalAlgorithm.toLowerCase();
381                     }
382                 }
383                 actualSigAlgsLowerCase.add(algLowerCase);
384             }
385         }
386 
387         TestUtils.assertContentsInAnyOrder(actualSigAlgsLowerCase,
388                 expectedSigAlgsLowerCase.toArray(new String[0]));
389     }
390 
391     @Test
testAndroidKeyStoreKeysHandledByAndroidKeyStoreProviderWhenSigning()392     public void testAndroidKeyStoreKeysHandledByAndroidKeyStoreProviderWhenSigning()
393             throws Exception {
394         Provider provider = Security.getProvider(EXPECTED_PROVIDER_NAME);
395         assertNotNull(provider);
396         for (String sigAlgorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
397             try {
398                 KeyPair keyPair = importDefaultKatKeyPair(sigAlgorithm).getKeystoreBackedKeyPair();
399                 Signature signature = Signature.getInstance(sigAlgorithm);
400                 signature.initSign(keyPair.getPrivate());
401                 assertSame(provider, signature.getProvider());
402             } catch (Throwable e) {
403                 throw new RuntimeException(sigAlgorithm + " failed", e);
404             }
405         }
406     }
407 
408     @Test
testAndroidKeyStorePublicKeysAcceptedByHighestPriorityProviderWhenVerifying()409     public void testAndroidKeyStorePublicKeysAcceptedByHighestPriorityProviderWhenVerifying()
410             throws Exception {
411         Provider provider = Security.getProvider(EXPECTED_PROVIDER_NAME);
412         assertNotNull(provider);
413         for (String sigAlgorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
414             try {
415                 KeyPair keyPair = importDefaultKatKeyPair(sigAlgorithm).getKeystoreBackedKeyPair();
416                 Signature signature = Signature.getInstance(sigAlgorithm);
417                 signature.initVerify(keyPair.getPublic());
418             } catch (Throwable e) {
419                 throw new RuntimeException(sigAlgorithm + " failed", e);
420             }
421         }
422     }
423 
424     @Test
testValidSignatureGeneratedForEmptyMessage()425     public void testValidSignatureGeneratedForEmptyMessage()
426             throws Exception {
427         Provider provider = Security.getProvider(EXPECTED_PROVIDER_NAME);
428         assertNotNull(provider);
429         for (String sigAlgorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
430             for (ImportedKey key : importKatKeyPairsForSigning(getContext(), sigAlgorithm)) {
431                 if (!TestUtils.isKeyLongEnoughForSignatureAlgorithm(
432                         sigAlgorithm, key.getOriginalSigningKey())) {
433                     continue;
434                 }
435                 try {
436                     KeyPair keyPair = key.getKeystoreBackedKeyPair();
437 
438                     // Generate a signature
439                     Signature signature = Signature.getInstance(sigAlgorithm, provider);
440                     signature.initSign(keyPair.getPrivate());
441                     byte[] sigBytes = signature.sign();
442 
443                     // Assert that it verifies using our own Provider
444                     signature.initVerify(keyPair.getPublic());
445                     assertTrue(signature.verify(sigBytes));
446                 } catch (Throwable e) {
447                     throw new RuntimeException(
448                             "Failed for " + sigAlgorithm + " with key " + key.getAlias(), e);
449                 }
450             }
451         }
452     }
453 
454     @Test
testValidSignatureGeneratedForEmptyMessageByLimitedUseKey()455     public void testValidSignatureGeneratedForEmptyMessageByLimitedUseKey()
456             throws Exception {
457         Provider provider = Security.getProvider(EXPECTED_PROVIDER_NAME);
458         assertNotNull(provider);
459         int maxUsageCount = 2;
460         for (String sigAlgorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
461             for (ImportedKey key : importLimitedUseKatKeyPairsForSigning(getContext(), sigAlgorithm, maxUsageCount)) {
462                 if (!TestUtils.isKeyLongEnoughForSignatureAlgorithm(
463                         sigAlgorithm, key.getOriginalSigningKey())) {
464                     continue;
465                 }
466                 try {
467                     KeyPair keyPair = key.getKeystoreBackedKeyPair();
468                     KeyFactory keyFactory = KeyFactory.getInstance(
469                             keyPair.getPrivate().getAlgorithm(), "AndroidKeyStore");
470                     KeyInfo info = keyFactory.getKeySpec(keyPair.getPrivate(), KeyInfo.class);
471                     assertEquals(maxUsageCount, info.getRemainingUsageCount());
472 
473                     // The first usage of the limited use key.
474                     // Generate a signature
475                     Signature signature = Signature.getInstance(sigAlgorithm, provider);
476                     signature.initSign(keyPair.getPrivate());
477                     byte[] sigBytes = signature.sign();
478                     // Assert that it verifies using our own Provider
479                     signature.initVerify(keyPair.getPublic());
480                     assertTrue(signature.verify(sigBytes));
481 
482                     // After using the key, the remaining usage count should be decreased. But this
483                     // will not be reflected unless we loads the key entry again.
484                     info = keyFactory.getKeySpec(keyPair.getPrivate(), KeyInfo.class);
485                     assertEquals(maxUsageCount, info.getRemainingUsageCount());
486 
487                     // Reloads the key entry again, the remaining usage count is decreased.
488                     KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
489                     keyStore.load(null);
490                     KeyStore.PrivateKeyEntry entry =
491                             (KeyStore.PrivateKeyEntry) keyStore.getEntry(key.getAlias(), null);
492                     info = keyFactory.getKeySpec(entry.getPrivateKey(), KeyInfo.class);
493                     assertEquals(maxUsageCount - 1, info.getRemainingUsageCount());
494 
495                     // The second usage of the limited use key.
496                     signature.initSign(keyPair.getPrivate());
497                     signature.sign();
498 
499                     // After the usage of limited use key is exhausted, the key will be deleted.
500                     try {
501                         signature.initSign(keyPair.getPrivate());
502                     } catch (KeyPermanentlyInvalidatedException expected) {}
503                 } catch (Throwable e) {
504                     throw new RuntimeException(
505                             "Failed for " + sigAlgorithm + " with key " + key.getAlias(), e);
506                 }
507             }
508         }
509     }
510 
511     @Test
testEmptySignatureDoesNotVerify()512     public void testEmptySignatureDoesNotVerify()
513             throws Exception {
514         Provider provider = Security.getProvider(EXPECTED_PROVIDER_NAME);
515         assertNotNull(provider);
516         for (String sigAlgorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
517             for (ImportedKey key : importKatKeyPairsForSigning(getContext(), sigAlgorithm)) {
518                 if (!TestUtils.isKeyLongEnoughForSignatureAlgorithm(
519                         sigAlgorithm, key.getOriginalSigningKey())) {
520                     continue;
521                 }
522                 try {
523                     KeyPair keyPair = key.getKeystoreBackedKeyPair();
524                     Signature signature = Signature.getInstance(sigAlgorithm, provider);
525                     signature.initVerify(keyPair.getPublic());
526                     assertFalse(signature.verify(EmptyArray.BYTE));
527                 } catch (Throwable e) {
528                     throw new RuntimeException(
529                             "Failed for " + sigAlgorithm + " with key " + key.getAlias(), e);
530                 }
531             }
532         }
533     }
534 
535     @Test
testSignatureGeneratedByAndroidKeyStoreVerifiesByAndroidKeyStore()536     public void testSignatureGeneratedByAndroidKeyStoreVerifiesByAndroidKeyStore()
537             throws Exception {
538         Provider provider = Security.getProvider(EXPECTED_PROVIDER_NAME);
539         assertNotNull(provider);
540         for (String sigAlgorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
541             for (ImportedKey key : importKatKeyPairsForSigning(getContext(), sigAlgorithm)) {
542                 if (!TestUtils.isKeyLongEnoughForSignatureAlgorithm(
543                         sigAlgorithm, key.getOriginalSigningKey())) {
544                     continue;
545                 }
546                 try {
547                     KeyPair keyPair = key.getKeystoreBackedKeyPair();
548 
549                     // Generate a signature
550                     Signature signature = Signature.getInstance(sigAlgorithm, provider);
551                     signature.initSign(keyPair.getPrivate());
552                     byte[] message = "This is a test".getBytes("UTF-8");
553                     signature.update(message);
554                     byte[] sigBytes = signature.sign();
555 
556                     // Assert that it verifies using our own Provider
557                     assertSignatureVerifiesOneShot(
558                             sigAlgorithm, provider, keyPair.getPublic(), message, sigBytes);
559                 } catch (Throwable e) {
560                     throw new RuntimeException(
561                             "Failed for " + sigAlgorithm + " with key " + key.getAlias(), e);
562                 }
563             }
564         }
565     }
566 
567     @Test
testSignatureGeneratedByAndroidKeyStoreVerifiesByHighestPriorityProvider()568     public void testSignatureGeneratedByAndroidKeyStoreVerifiesByHighestPriorityProvider()
569             throws Exception {
570         Provider keystoreProvider = Security.getProvider(EXPECTED_PROVIDER_NAME);
571         assertNotNull(keystoreProvider);
572         for (String sigAlgorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
573             for (ImportedKey key : importKatKeyPairsForSigning(getContext(), sigAlgorithm)) {
574                 if (!TestUtils.isKeyLongEnoughForSignatureAlgorithm(
575                         sigAlgorithm, key.getOriginalSigningKey())) {
576                     continue;
577                 }
578                 Provider verificationProvider = null;
579                 try {
580                     PrivateKey keystorePrivateKey = key.getKeystoreBackedKeyPair().getPrivate();
581 
582                     // Generate a signature
583                     Signature signature = Signature.getInstance(sigAlgorithm, keystoreProvider);
584                     signature.initSign(keystorePrivateKey);
585                     byte[] message = "This is a test".getBytes("UTF-8");
586                     signature.update(message);
587                     byte[] sigBytes = signature.sign();
588 
589                     // Assert that it verifies using whatever Provider is chosen by JCA by default
590                     // for this signature algorithm and public key.
591                     PublicKey publicKey = key.getOriginalKeyPair().getPublic();
592                     try {
593                         signature = Signature.getInstance(sigAlgorithm);
594                         signature.initVerify(publicKey);
595                         verificationProvider = signature.getProvider();
596                     } catch (InvalidKeyException e) {
597                         // No providers support verifying signatures using this algorithm and key.
598                         continue;
599                     }
600                     assertSignatureVerifiesOneShot(
601                             sigAlgorithm, verificationProvider, publicKey, message, sigBytes);
602                 } catch (Throwable e) {
603                     throw new RuntimeException(
604                             "Failed for " + sigAlgorithm + " with key " + key.getAlias()
605                                     + ", verification provider: " + verificationProvider,
606                             e);
607                 }
608             }
609         }
610     }
611 
612     @Test
testSignatureGeneratedByHighestPriorityProviderVerifiesByAndroidKeyStore()613     public void testSignatureGeneratedByHighestPriorityProviderVerifiesByAndroidKeyStore()
614             throws Exception {
615 
616         Provider keystoreProvider = Security.getProvider(EXPECTED_PROVIDER_NAME);
617         assertNotNull(keystoreProvider);
618         for (String sigAlgorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
619             for (ImportedKey key : importKatKeyPairsForSigning(getContext(), sigAlgorithm)) {
620                 if (!TestUtils.isKeyLongEnoughForSignatureAlgorithm(
621                         sigAlgorithm, key.getOriginalSigningKey())) {
622                     continue;
623                 }
624                 Provider signingProvider = null;
625                 try {
626                     PrivateKey privateKey = key.getOriginalKeyPair().getPrivate();
627 
628                     // Generate a signature
629                     Signature signature;
630                     try {
631                         signature = Signature.getInstance(sigAlgorithm);
632                         signature.initSign(privateKey);
633                         signingProvider = signature.getProvider();
634                     } catch (InvalidKeyException e) {
635                         // No providers support signing using this algorithm and key.
636                         continue;
637                     }
638                     byte[] message = "This is a test".getBytes("UTF-8");
639                     signature.update(message);
640                     byte[] sigBytes = signature.sign();
641 
642                     // Assert that the signature verifies using the Android Keystore provider.
643                     PublicKey keystorePublicKey = key.getKeystoreBackedKeyPair().getPublic();
644                     assertSignatureVerifiesOneShot(
645                             sigAlgorithm, keystoreProvider, keystorePublicKey, message, sigBytes);
646                 } catch (Throwable e) {
647                     throw new RuntimeException(
648                             "Failed for " + sigAlgorithm + " with key " + key.getAlias()
649                                     + ", signing provider: " + signingProvider,
650                             e);
651                 }
652             }
653         }
654     }
655 
656     @Test
testSmallMsgKat()657     public void testSmallMsgKat() throws Exception {
658         byte[] message = SHORT_MSG_KAT_MESSAGE;
659 
660         Provider provider = Security.getProvider(EXPECTED_PROVIDER_NAME);
661         assertNotNull(provider);
662         for (String algorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
663             try {
664                 byte[] goodSigBytes = SHORT_MSG_KAT_SIGNATURES.get(algorithm);
665                 assertNotNull(goodSigBytes);
666                 KeyPair keyPair = importDefaultKatKeyPair(algorithm).getKeystoreBackedKeyPair();
667                 // Assert that AndroidKeyStore provider can verify the known good signature.
668                 assertSignatureVerifiesOneShot(
669                         algorithm, provider, keyPair.getPublic(), message, goodSigBytes);
670                 assertSignatureVerifiesFedOneByteAtATime(
671                         algorithm, provider, keyPair.getPublic(), message, goodSigBytes);
672                 assertSignatureVerifiesFedUsingFixedSizeChunks(
673                         algorithm, provider, keyPair.getPublic(), message, goodSigBytes, 3);
674 
675                 byte[] messageWithBitFlip = message.clone();
676                 messageWithBitFlip[messageWithBitFlip.length / 2] ^= 1;
677                 assertSignatureDoesNotVerifyOneShot(
678                         algorithm, provider, keyPair.getPublic(), messageWithBitFlip, goodSigBytes);
679 
680                 byte[] goodSigWithBitFlip = goodSigBytes.clone();
681                 goodSigWithBitFlip[goodSigWithBitFlip.length / 2] ^= 1;
682                 assertSignatureDoesNotVerifyOneShot(
683                         algorithm, provider, keyPair.getPublic(), message, goodSigWithBitFlip);
684 
685                 // Sign the message in one go
686                 Signature signature = Signature.getInstance(algorithm, provider);
687                 signature.initSign(keyPair.getPrivate());
688                 signature.update(message);
689                 byte[] generatedSigBytes = signature.sign();
690                 boolean deterministicSignatureScheme =
691                         algorithm.toLowerCase().endsWith("withrsa");
692                 if (deterministicSignatureScheme) {
693                     assertArrayEquals(goodSigBytes, generatedSigBytes);
694                 } else {
695                     if (Math.abs(goodSigBytes.length - generatedSigBytes.length) > 2) {
696                         fail("Generated signature expected to be between "
697                                 + (goodSigBytes.length - 2) + " and "
698                                 + (goodSigBytes.length + 2) + " bytes long, but was: "
699                                 + generatedSigBytes.length + " bytes: "
700                                 + HexEncoding.encode(generatedSigBytes));
701                     }
702 
703                     // Assert that the signature verifies using our own Provider
704                     assertSignatureVerifiesOneShot(
705                             algorithm, provider, keyPair.getPublic(), message, generatedSigBytes);
706                     assertSignatureVerifiesFedOneByteAtATime(
707                             algorithm, provider, keyPair.getPublic(), message, generatedSigBytes);
708                     assertSignatureVerifiesFedUsingFixedSizeChunks(
709                             algorithm, provider, keyPair.getPublic(), message, generatedSigBytes,
710                             3);
711 
712                     // Assert that the signature verifies using whatever Provider is chosen by JCA
713                     // by default for this signature algorithm and public key.
714                     assertSignatureVerifiesOneShot(
715                             algorithm, keyPair.getPublic(), message, generatedSigBytes);
716                 }
717 
718                 // Sign the message by feeding it into the Signature one byte at a time
719                 signature = Signature.getInstance(signature.getAlgorithm(), provider);
720                 signature.initSign(keyPair.getPrivate());
721                 for (int i = 0; i < message.length; i++) {
722                     signature.update(message[i]);
723                 }
724                 generatedSigBytes = signature.sign();
725                 if (deterministicSignatureScheme) {
726                     assertArrayEquals(goodSigBytes, generatedSigBytes);
727                 } else {
728                     if (Math.abs(goodSigBytes.length - generatedSigBytes.length) > 2) {
729                         fail("Generated signature expected to be between "
730                                 + (goodSigBytes.length - 2) + " and "
731                                 + (goodSigBytes.length + 2) + " bytes long, but was: "
732                                 + generatedSigBytes.length + " bytes: "
733                                 + HexEncoding.encode(generatedSigBytes));
734                     }
735                     // Assert that the signature verifies using our own Provider
736                     assertSignatureVerifiesOneShot(
737                             algorithm, provider, keyPair.getPublic(), message, generatedSigBytes);
738                     assertSignatureVerifiesFedOneByteAtATime(
739                             algorithm, provider, keyPair.getPublic(), message, generatedSigBytes);
740                     assertSignatureVerifiesFedUsingFixedSizeChunks(
741                             algorithm, provider, keyPair.getPublic(), message, generatedSigBytes,
742                             3);
743 
744                     // Assert that the signature verifies using whatever Provider is chosen by JCA
745                     // by default for this signature algorithm and public key.
746                     assertSignatureVerifiesOneShot(
747                             algorithm, keyPair.getPublic(), message, generatedSigBytes);
748                 }
749             } catch (Throwable e) {
750                 throw new RuntimeException("Failed for " + algorithm, e);
751             }
752         }
753     }
754 
755     @Test
testLongMsgKat()756     public void testLongMsgKat() throws Exception {
757         StrictModeDetector strict = new StrictModeDetector(getContext());
758         byte[] message = TestUtils.generateLargeKatMsg(LONG_MSG_KAT_SEED, LONG_MSG_KAT_SIZE_BYTES);
759 
760         Provider provider = Security.getProvider(EXPECTED_PROVIDER_NAME);
761         assertNotNull(provider);
762         for (String algorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
763             try {
764                 KeyPair keyPair = importDefaultKatKeyPair(algorithm).getKeystoreBackedKeyPair();
765                 String digest = TestUtils.getSignatureAlgorithmDigest(algorithm);
766                 String keyAlgorithm = TestUtils.getSignatureAlgorithmKeyAlgorithm(algorithm);
767                 if ((KeyProperties.DIGEST_NONE.equalsIgnoreCase(digest))
768                         && (!KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(keyAlgorithm))) {
769                     // This algorithm does not accept large messages
770                     Signature signature = Signature.getInstance(algorithm, provider);
771                     signature.initSign(keyPair.getPrivate());
772                     try {
773                         signature.update(message);
774                         byte[] sigBytes = signature.sign();
775                         fail("Unexpectedly generated signature (" + sigBytes.length + "): "
776                                 + HexEncoding.encode(sigBytes));
777                     } catch (SignatureException expected) {}
778 
779                     // Bogus signature generated using SHA-256 digest -- shouldn't because the
780                     // message is too long (and should not be digested/hashed) and because the
781                     // signature uses the wrong digest/hash.
782                     byte[] sigBytes = SHORT_MSG_KAT_SIGNATURES.get(
783                             "SHA256" + algorithm.substring("NONE".length()));
784                     assertNotNull(sigBytes);
785                     signature = Signature.getInstance(algorithm, provider);
786                     signature.initVerify(keyPair.getPublic());
787                     try {
788                         signature.update(message);
789                         if (signature.verify(sigBytes)) {
790                             fail();
791                         }
792                     } catch (SignatureException expected) {}
793                     continue;
794                 }
795 
796                 byte[] goodSigBytes = LONG_MSG_KAT_SIGNATURES.get(algorithm);
797                 assertNotNull(goodSigBytes);
798 
799                 // Assert that AndroidKeyStore provider can verify the known good signature.
800                 assertSignatureVerifiesOneShot(
801                         algorithm, provider, keyPair.getPublic(), message, goodSigBytes);
802                 assertSignatureVerifiesFedUsingFixedSizeChunks(
803                         algorithm, provider, keyPair.getPublic(), message, goodSigBytes, 718871);
804 
805                 // Sign the message in one go
806                 strict.clear();
807                 Signature signature = Signature.getInstance(algorithm, provider);
808                 signature.initSign(keyPair.getPrivate());
809                 signature.update(message);
810                 byte[] generatedSigBytes = signature.sign();
811                 strict.check("signature with " + algorithm);
812                 String paddingScheme = TestUtils.getSignatureAlgorithmPadding(algorithm);
813                 boolean deterministicSignatureScheme =
814                         KeyProperties.SIGNATURE_PADDING_RSA_PKCS1.equalsIgnoreCase(paddingScheme);
815                 if (deterministicSignatureScheme) {
816                     assertArrayEquals(goodSigBytes, generatedSigBytes);
817                 } else {
818                     if (Math.abs(goodSigBytes.length - generatedSigBytes.length) > 2) {
819                         fail("Generated signature expected to be between "
820                                 + (goodSigBytes.length - 2) + " and "
821                                 + (goodSigBytes.length + 2) + " bytes long, but was: "
822                                 + generatedSigBytes.length + " bytes: "
823                                 + HexEncoding.encode(generatedSigBytes));
824                     }
825 
826                     // Assert that the signature verifies using our own Provider
827                     assertSignatureVerifiesOneShot(
828                             algorithm, provider, keyPair.getPublic(), message, generatedSigBytes);
829                     assertSignatureVerifiesFedUsingFixedSizeChunks(
830                             algorithm, provider, keyPair.getPublic(), message, generatedSigBytes,
831                             718871);
832 
833                     // Assert that the signature verifies using whatever Provider is chosen by JCA
834                     // by default for this signature algorithm and public key.
835                     assertSignatureVerifiesOneShot(
836                             algorithm, keyPair.getPublic(), message, generatedSigBytes);
837                 }
838 
839                 // Sign the message by feeding it into the Signature one byte at a time
840                 generatedSigBytes = generateSignatureFedUsingFixedSizeChunks(
841                         algorithm, provider, keyPair.getPrivate(), message, 444307);
842                 if (deterministicSignatureScheme) {
843                     assertArrayEquals(goodSigBytes, generatedSigBytes);
844                 } else {
845                     if (Math.abs(goodSigBytes.length - generatedSigBytes.length) > 2) {
846                         fail("Generated signature expected to be between "
847                                 + (goodSigBytes.length - 2) + " and "
848                                 + (goodSigBytes.length + 2) + " bytes long, but was: "
849                                 + generatedSigBytes.length + " bytes: "
850                                 + HexEncoding.encode(generatedSigBytes));
851                     }
852                     // Assert that the signature verifies using our own Provider
853                     assertSignatureVerifiesOneShot(
854                             algorithm, provider, keyPair.getPublic(), message, generatedSigBytes);
855                     assertSignatureVerifiesFedUsingFixedSizeChunks(
856                             algorithm, provider, keyPair.getPublic(), message, generatedSigBytes,
857                             718871);
858 
859                     // Assert that the signature verifies using whatever Provider is chosen by JCA
860                     // by default for this signature algorithm and public key.
861                     assertSignatureVerifiesOneShot(
862                             algorithm, keyPair.getPublic(), message, generatedSigBytes);
863                 }
864             } catch (Throwable e) {
865                 throw new RuntimeException("Failed for " + algorithm, e);
866             }
867         }
868     }
869 
870     @Test
testInitVerifySucceedsDespiteMissingAuthorizations()871     public void testInitVerifySucceedsDespiteMissingAuthorizations() throws Exception {
872         KeyProtection spec = new KeyProtection.Builder(0).build();
873 
874         for (String algorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
875             try {
876                 assertInitVerifySucceeds(algorithm, spec);
877             } catch (Throwable e) {
878                 throw new RuntimeException("Failed for " + algorithm, e);
879             }
880         }
881     }
882 
883     @Test
testInitSignFailsWhenNotAuthorizedToSign()884     public void testInitSignFailsWhenNotAuthorizedToSign() throws Exception {
885         int badPurposes = KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT
886                 | KeyProperties.PURPOSE_VERIFY;
887 
888         for (String algorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
889             try {
890                 KeyProtection good = getMinimalWorkingImportParamsForSigning(algorithm);
891                 assertInitSignSucceeds(algorithm, good);
892                 assertInitSignThrowsInvalidKeyException(algorithm,
893                         TestUtils.buildUpon(good, badPurposes).build());
894             } catch (Throwable e) {
895                 throw new RuntimeException("Failed for " + algorithm, e);
896             }
897         }
898     }
899 
900     @Test
testInitVerifyIgnoresThatNotAuthorizedToVerify()901     public void testInitVerifyIgnoresThatNotAuthorizedToVerify() throws Exception {
902         int badPurposes = KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT
903                 | KeyProperties.PURPOSE_SIGN;
904 
905         for (String algorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
906             try {
907                 KeyProtection good = getMinimalWorkingImportParamsForVerifying(algorithm);
908                 assertInitVerifySucceeds(algorithm, good);
909                 assertInitVerifySucceeds(algorithm,
910                         TestUtils.buildUpon(good, badPurposes).build());
911             } catch (Throwable e) {
912                 throw new RuntimeException("Failed for " + algorithm, e);
913             }
914         }
915     }
916 
917     @Test
testInitSignFailsWhenDigestNotAuthorized()918     public void testInitSignFailsWhenDigestNotAuthorized() throws Exception {
919         for (String algorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
920             try {
921                 KeyProtection good = getMinimalWorkingImportParamsForSigning(algorithm);
922                 assertInitSignSucceeds(algorithm, good);
923 
924                 String digest = TestUtils.getSignatureAlgorithmDigest(algorithm);
925                 String badDigest =
926                         (KeyProperties.DIGEST_SHA256.equalsIgnoreCase(digest))
927                         ? KeyProperties.DIGEST_SHA384 : KeyProperties.DIGEST_SHA256;
928                 assertInitSignThrowsInvalidKeyException(algorithm,
929                         TestUtils.buildUpon(good).setDigests(badDigest).build());
930 
931                 // Check that digest NONE is not treated as ANY.
932                 if (!KeyProperties.DIGEST_NONE.equalsIgnoreCase(digest)) {
933                     assertInitSignThrowsInvalidKeyException(algorithm,
934                             TestUtils.buildUpon(good)
935                                     .setDigests(KeyProperties.DIGEST_NONE)
936                                     .build());
937                 }
938             } catch (Throwable e) {
939                 throw new RuntimeException("Failed for " + algorithm, e);
940             }
941         }
942     }
943 
944     @Test
testInitVerifyIgnoresThatDigestNotAuthorized()945     public void testInitVerifyIgnoresThatDigestNotAuthorized() throws Exception {
946         for (String algorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
947             try {
948                 KeyProtection good = getMinimalWorkingImportParamsForVerifying(algorithm);
949                 assertInitVerifySucceeds(algorithm, good);
950 
951                 String digest = TestUtils.getSignatureAlgorithmDigest(algorithm);
952                 String badDigest =
953                         (KeyProperties.DIGEST_SHA256.equalsIgnoreCase(digest))
954                         ? KeyProperties.DIGEST_SHA384 : KeyProperties.DIGEST_SHA256;
955                 assertInitVerifySucceeds(algorithm,
956                         TestUtils.buildUpon(good).setDigests(badDigest).build());
957             } catch (Throwable e) {
958                 throw new RuntimeException("Failed for " + algorithm, e);
959             }
960         }
961     }
962 
963     @Test
testInitSignFailsWhenPaddingNotAuthorized()964     public void testInitSignFailsWhenPaddingNotAuthorized() throws Exception {
965         for (String algorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
966             try {
967                 String paddingScheme = TestUtils.getSignatureAlgorithmPadding(algorithm);
968                 String badPaddingScheme;
969                 if (paddingScheme == null) {
970                     // No padding scheme used by this algorithm -- ignore.
971                     continue;
972                 } else if (KeyProperties.SIGNATURE_PADDING_RSA_PKCS1.equalsIgnoreCase(
973                         paddingScheme)) {
974                     badPaddingScheme = KeyProperties.SIGNATURE_PADDING_RSA_PSS;
975                 } else if (KeyProperties.SIGNATURE_PADDING_RSA_PSS.equalsIgnoreCase(
976                         paddingScheme)) {
977                     badPaddingScheme = KeyProperties.SIGNATURE_PADDING_RSA_PKCS1;
978                 } else {
979                     throw new IllegalArgumentException("Unsupported algorithm: " + algorithm);
980                 }
981 
982                 KeyProtection good = getMinimalWorkingImportParamsForSigning(algorithm);
983                 assertInitSignSucceeds(algorithm, good);
984                 assertInitSignThrowsInvalidKeyException(algorithm,
985                         TestUtils.buildUpon(good).setSignaturePaddings(badPaddingScheme).build());
986             } catch (Throwable e) {
987                 throw new RuntimeException("Failed for " + algorithm, e);
988             }
989         }
990     }
991 
992     @Test
testInitVerifyIgnoresThatPaddingNotAuthorized()993     public void testInitVerifyIgnoresThatPaddingNotAuthorized() throws Exception {
994         for (String algorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
995             try {
996                 String paddingScheme = TestUtils.getSignatureAlgorithmPadding(algorithm);
997                 String badPaddingScheme;
998                 if (paddingScheme == null) {
999                     // No padding scheme used by this algorithm -- ignore.
1000                     continue;
1001                 } else if (KeyProperties.SIGNATURE_PADDING_RSA_PKCS1.equalsIgnoreCase(
1002                         paddingScheme)) {
1003                     badPaddingScheme = KeyProperties.SIGNATURE_PADDING_RSA_PSS;
1004                 } else if (KeyProperties.SIGNATURE_PADDING_RSA_PSS.equalsIgnoreCase(
1005                         paddingScheme)) {
1006                     badPaddingScheme = KeyProperties.SIGNATURE_PADDING_RSA_PKCS1;
1007                 } else {
1008                     throw new IllegalArgumentException("Unsupported algorithm: " + algorithm);
1009                 }
1010 
1011                 KeyProtection good = getMinimalWorkingImportParamsForVerifying(algorithm);
1012                 assertInitVerifySucceeds(algorithm, good);
1013                 assertInitVerifySucceeds(algorithm,
1014                         TestUtils.buildUpon(good).setSignaturePaddings(badPaddingScheme).build());
1015             } catch (Throwable e) {
1016                 throw new RuntimeException("Failed for " + algorithm, e);
1017             }
1018         }
1019     }
1020 
1021     @Test
testInitSignFailsWhenKeyNotYetValid()1022     public void testInitSignFailsWhenKeyNotYetValid() throws Exception {
1023         Date badStartDate = new Date(System.currentTimeMillis() + DAY_IN_MILLIS);
1024         for (String algorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
1025             try {
1026                 KeyProtection good = getMinimalWorkingImportParamsForSigning(algorithm);
1027                 assertInitSignSucceeds(algorithm, good);
1028                 assertInitSignThrowsInvalidKeyException(algorithm,
1029                         TestUtils.buildUpon(good).setKeyValidityStart(badStartDate).build());
1030             } catch (Throwable e) {
1031                 throw new RuntimeException("Failed for " + algorithm, e);
1032             }
1033         }
1034     }
1035 
1036     @Test
testInitVerifyIgnoresThatKeyNotYetValid()1037     public void testInitVerifyIgnoresThatKeyNotYetValid() throws Exception {
1038         Date badStartDate = new Date(System.currentTimeMillis() + DAY_IN_MILLIS);
1039         for (String algorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
1040             try {
1041                 KeyProtection good = getMinimalWorkingImportParamsForVerifying(algorithm);
1042                 assertInitVerifySucceeds(algorithm, good);
1043                 assertInitVerifySucceeds(algorithm,
1044                         TestUtils.buildUpon(good).setKeyValidityStart(badStartDate).build());
1045             } catch (Throwable e) {
1046                 throw new RuntimeException("Failed for " + algorithm, e);
1047             }
1048         }
1049     }
1050 
1051     @Test
testInitSignFailsWhenKeyNoLongerValidForOrigination()1052     public void testInitSignFailsWhenKeyNoLongerValidForOrigination() throws Exception {
1053         Date badEndDate = new Date(System.currentTimeMillis() - DAY_IN_MILLIS);
1054         for (String algorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
1055             try {
1056                 KeyProtection good = getMinimalWorkingImportParamsForSigning(algorithm);
1057                 assertInitSignSucceeds(algorithm, good);
1058                 assertInitSignThrowsInvalidKeyException(algorithm,
1059                         TestUtils.buildUpon(good)
1060                                 .setKeyValidityForOriginationEnd(badEndDate)
1061                                 .build());
1062             } catch (Throwable e) {
1063                 throw new RuntimeException("Failed for " + algorithm, e);
1064             }
1065         }
1066     }
1067 
1068     @Test
testInitVerifyIgnoresThatKeyNoLongerValidForOrigination()1069     public void testInitVerifyIgnoresThatKeyNoLongerValidForOrigination() throws Exception {
1070         Date badEndDate = new Date(System.currentTimeMillis() - DAY_IN_MILLIS);
1071         for (String algorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
1072             try {
1073                 KeyProtection good = getMinimalWorkingImportParamsForVerifying(algorithm);
1074                 assertInitVerifySucceeds(algorithm, good);
1075                 assertInitVerifySucceeds(algorithm,
1076                         TestUtils.buildUpon(good)
1077                                 .setKeyValidityForOriginationEnd(badEndDate)
1078                                 .build());
1079             } catch (Throwable e) {
1080                 throw new RuntimeException("Failed for " + algorithm, e);
1081             }
1082         }
1083     }
1084 
1085     @Test
testInitSignIgnoresThatKeyNoLongerValidForConsumption()1086     public void testInitSignIgnoresThatKeyNoLongerValidForConsumption() throws Exception {
1087         Date badEndDate = new Date(System.currentTimeMillis() - DAY_IN_MILLIS);
1088         for (String algorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
1089             try {
1090                 KeyProtection good = getMinimalWorkingImportParamsForSigning(algorithm);
1091                 assertInitSignSucceeds(algorithm, good);
1092                 assertInitSignSucceeds(algorithm,
1093                         TestUtils.buildUpon(good)
1094                                 .setKeyValidityForConsumptionEnd(badEndDate)
1095                                 .build());
1096             } catch (Throwable e) {
1097                 throw new RuntimeException("Failed for " + algorithm, e);
1098             }
1099         }
1100     }
1101 
1102     @Test
testInitVerifyIgnoresThatKeyNoLongerValidForConsumption()1103     public void testInitVerifyIgnoresThatKeyNoLongerValidForConsumption() throws Exception {
1104         Date badEndDate = new Date(System.currentTimeMillis() - DAY_IN_MILLIS);
1105         for (String algorithm : EXPECTED_SIGNATURE_ALGORITHMS) {
1106             try {
1107                 KeyProtection good = getMinimalWorkingImportParamsForVerifying(algorithm);
1108                 assertInitVerifySucceeds(algorithm, good);
1109                 assertInitVerifySucceeds(algorithm,
1110                         TestUtils.buildUpon(good)
1111                                 .setKeyValidityForConsumptionEnd(badEndDate)
1112                                 .build());
1113             } catch (Throwable e) {
1114                 throw new RuntimeException("Failed for " + algorithm, e);
1115             }
1116         }
1117     }
1118 
assertInitVerifySucceeds( String signatureAlgorithm, KeyProtection keyProtection)1119     private void assertInitVerifySucceeds(
1120             String signatureAlgorithm,
1121             KeyProtection keyProtection) throws Exception {
1122         int[] resIds = getDefaultKeyAndCertResIds(signatureAlgorithm);
1123         assertInitVerifySucceeds(
1124                 signatureAlgorithm,
1125                 resIds[0],
1126                 resIds[1],
1127                 keyProtection);
1128     }
1129 
assertInitVerifySucceeds( String signatureAlgorithm, int privateKeyResId, int certResId, KeyProtection keyProtection)1130     private void assertInitVerifySucceeds(
1131             String signatureAlgorithm,
1132             int privateKeyResId,
1133             int certResId,
1134             KeyProtection keyProtection) throws Exception {
1135         PublicKey publicKey = TestUtils.importIntoAndroidKeyStore(
1136                 "test1", getContext(), privateKeyResId, certResId, keyProtection)
1137                 .getKeystoreBackedKeyPair()
1138                 .getPublic();
1139         Signature signature = Signature.getInstance(signatureAlgorithm, EXPECTED_PROVIDER_NAME);
1140         signature.initVerify(publicKey);
1141     }
1142 
assertInitSignSucceeds( String signatureAlgorithm, KeyProtection keyProtection)1143     private void assertInitSignSucceeds(
1144             String signatureAlgorithm,
1145             KeyProtection keyProtection) throws Exception {
1146         int[] resIds = getDefaultKeyAndCertResIds(signatureAlgorithm);
1147         assertInitSignSucceeds(
1148                 signatureAlgorithm,
1149                 resIds[0],
1150                 resIds[1],
1151                 keyProtection);
1152     }
1153 
assertInitSignSucceeds( String signatureAlgorithm, int privateKeyResId, int certResId, KeyProtection keyProtection)1154     private void assertInitSignSucceeds(
1155             String signatureAlgorithm,
1156             int privateKeyResId,
1157             int certResId,
1158             KeyProtection keyProtection) throws Exception {
1159         PrivateKey privateKey = TestUtils.importIntoAndroidKeyStore(
1160                 "test1", getContext(), privateKeyResId, certResId, keyProtection)
1161                 .getKeystoreBackedKeyPair()
1162                 .getPrivate();
1163         Signature signature = Signature.getInstance(signatureAlgorithm, EXPECTED_PROVIDER_NAME);
1164         signature.initSign(privateKey);
1165     }
1166 
assertInitSignThrowsInvalidKeyException( String signatureAlgorithm, KeyProtection keyProtection)1167     private void assertInitSignThrowsInvalidKeyException(
1168             String signatureAlgorithm,
1169             KeyProtection keyProtection) throws Exception {
1170         assertInitSignThrowsInvalidKeyException(null, signatureAlgorithm, keyProtection);
1171     }
1172 
assertInitSignThrowsInvalidKeyException( String message, String signatureAlgorithm, KeyProtection keyProtection)1173     private void assertInitSignThrowsInvalidKeyException(
1174             String message,
1175             String signatureAlgorithm,
1176             KeyProtection keyProtection) throws Exception {
1177         int[] resIds = getDefaultKeyAndCertResIds(signatureAlgorithm);
1178         assertInitSignThrowsInvalidKeyException(
1179                 message,
1180                 signatureAlgorithm,
1181                 resIds[0],
1182                 resIds[1],
1183                 keyProtection);
1184     }
1185 
assertInitSignThrowsInvalidKeyException( String message, String signatureAlgorithm, int privateKeyResId, int certResId, KeyProtection keyProtection)1186     private void assertInitSignThrowsInvalidKeyException(
1187             String message,
1188             String signatureAlgorithm,
1189             int privateKeyResId,
1190             int certResId,
1191             KeyProtection keyProtection) throws Exception {
1192         PrivateKey privateKey = TestUtils.importIntoAndroidKeyStore(
1193                 "test1", getContext(), privateKeyResId, certResId, keyProtection)
1194                 .getKeystoreBackedKeyPair()
1195                 .getPrivate();
1196         Signature signature = Signature.getInstance(signatureAlgorithm, EXPECTED_PROVIDER_NAME);
1197         try {
1198             signature.initSign(privateKey);
1199             fail(message);
1200         } catch (InvalidKeyException expected) {}
1201     }
1202 
getDefaultKeyAndCertResIds(String signatureAlgorithm)1203     static int[] getDefaultKeyAndCertResIds(String signatureAlgorithm) {
1204         String keyAlgorithm = TestUtils.getSignatureAlgorithmKeyAlgorithm(signatureAlgorithm);
1205         if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(keyAlgorithm)) {
1206             return new int[] {R.raw.ec_key1_pkcs8, R.raw.ec_key1_cert};
1207         } else if (KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(keyAlgorithm)) {
1208             return new int[] {R.raw.rsa_key1_pkcs8, R.raw.rsa_key1_cert};
1209         } else {
1210             throw new IllegalArgumentException("Unknown key algorithm: " + keyAlgorithm);
1211         }
1212     }
1213 
importDefaultKatKeyPair(String signatureAlgorithm)1214     private ImportedKey importDefaultKatKeyPair(String signatureAlgorithm) throws Exception {
1215         String keyAlgorithm = TestUtils.getSignatureAlgorithmKeyAlgorithm(signatureAlgorithm);
1216         KeyProtection importParams =
1217                 TestUtils.getMinimalWorkingImportParametersForSigningingWith(signatureAlgorithm);
1218         if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(keyAlgorithm)) {
1219             return TestUtils.importIntoAndroidKeyStore(
1220                     "testEc",
1221                     getContext(),
1222                     R.raw.ec_key1_pkcs8,
1223                     R.raw.ec_key1_cert,
1224                     importParams);
1225         } else if (KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(keyAlgorithm)) {
1226             return TestUtils.importIntoAndroidKeyStore(
1227                     "testRsa",
1228                     getContext(),
1229                     R.raw.rsa_key1_pkcs8,
1230                     R.raw.rsa_key1_cert,
1231                     importParams);
1232         } else {
1233             throw new IllegalArgumentException("Unsupported key algorithm: " + keyAlgorithm);
1234         }
1235     }
1236 
assertSignatureVerifiesOneShot( String algorithm, PublicKey publicKey, byte[] message, byte[] signature)1237     private void assertSignatureVerifiesOneShot(
1238             String algorithm,
1239             PublicKey publicKey,
1240             byte[] message,
1241             byte[] signature) throws Exception {
1242         assertSignatureVerifiesOneShot(algorithm, null, publicKey, message, signature);
1243     }
1244 
assertSignatureVerifiesOneShot( String algorithm, Provider provider, PublicKey publicKey, byte[] message, byte[] signature)1245     private void assertSignatureVerifiesOneShot(
1246             String algorithm,
1247             Provider provider,
1248             PublicKey publicKey,
1249             byte[] message,
1250             byte[] signature) throws Exception {
1251         Signature sig = (provider != null)
1252                 ? Signature.getInstance(algorithm, provider) : Signature.getInstance(algorithm);
1253         sig.initVerify(publicKey);
1254         sig.update(message);
1255         if (!sig.verify(signature)) {
1256             fail("Signature did not verify. algorithm: " + algorithm
1257                     + ", provider: " + sig.getProvider().getName()
1258                     + ", signature (" + signature.length + " bytes): "
1259                     + HexEncoding.encode(signature));
1260         }
1261     }
1262 
assertSignatureDoesNotVerifyOneShot( String algorithm, Provider provider, PublicKey publicKey, byte[] message, byte[] signature)1263     private void assertSignatureDoesNotVerifyOneShot(
1264             String algorithm,
1265             Provider provider,
1266             PublicKey publicKey,
1267             byte[] message,
1268             byte[] signature) throws Exception {
1269         Signature sig = (provider != null)
1270                 ? Signature.getInstance(algorithm, provider) : Signature.getInstance(algorithm);
1271         sig.initVerify(publicKey);
1272         sig.update(message);
1273         if (sig.verify(signature)) {
1274             fail("Signature verified unexpectedly. algorithm: " + algorithm
1275                     + ", provider: " + sig.getProvider().getName()
1276                     + ", signature (" + signature.length + " bytes): "
1277                     + HexEncoding.encode(signature));
1278         }
1279     }
1280 
assertSignatureVerifiesFedOneByteAtATime( String algorithm, Provider provider, PublicKey publicKey, byte[] message, byte[] signature)1281     private void assertSignatureVerifiesFedOneByteAtATime(
1282             String algorithm,
1283             Provider provider,
1284             PublicKey publicKey,
1285             byte[] message,
1286             byte[] signature) throws Exception {
1287         Signature sig = (provider != null)
1288                 ? Signature.getInstance(algorithm, provider) : Signature.getInstance(algorithm);
1289         sig.initVerify(publicKey);
1290         for (int i = 0; i < message.length; i++) {
1291             sig.update(message[i]);
1292         }
1293         if (!sig.verify(signature)) {
1294             fail("Signature did not verify. algorithm: " + algorithm
1295                     + ", provider: " + sig.getProvider().getName()
1296                     + ", signature (" + signature.length + " bytes): "
1297                     + HexEncoding.encode(signature));
1298         }
1299     }
1300 
generateSignatureFedUsingFixedSizeChunks( String algorithm, Provider expectedProvider, PrivateKey privateKey, byte[] message, int chunkSizeBytes)1301     private byte[] generateSignatureFedUsingFixedSizeChunks(
1302             String algorithm,
1303             Provider expectedProvider,
1304             PrivateKey privateKey,
1305             byte[] message,
1306             int chunkSizeBytes) throws Exception {
1307         Signature signature = Signature.getInstance(algorithm);
1308         signature.initSign(privateKey);
1309         assertSame(expectedProvider, signature.getProvider());
1310         int messageRemaining = message.length;
1311         int messageOffset = 0;
1312         while (messageRemaining > 0) {
1313             int actualChunkSizeBytes =  Math.min(chunkSizeBytes, messageRemaining);
1314             signature.update(message, messageOffset, actualChunkSizeBytes);
1315             messageOffset += actualChunkSizeBytes;
1316             messageRemaining -= actualChunkSizeBytes;
1317         }
1318         return signature.sign();
1319     }
1320 
assertSignatureVerifiesFedUsingFixedSizeChunks( String algorithm, Provider provider, PublicKey publicKey, byte[] message, byte[] signature, int chunkSizeBytes)1321     private void assertSignatureVerifiesFedUsingFixedSizeChunks(
1322             String algorithm,
1323             Provider provider,
1324             PublicKey publicKey,
1325             byte[] message,
1326             byte[] signature,
1327             int chunkSizeBytes) throws Exception {
1328         Signature sig = (provider != null)
1329                 ? Signature.getInstance(algorithm, provider) : Signature.getInstance(algorithm);
1330         sig.initVerify(publicKey);
1331         int messageRemaining = message.length;
1332         int messageOffset = 0;
1333         while (messageRemaining > 0) {
1334             int actualChunkSizeBytes =  Math.min(chunkSizeBytes, messageRemaining);
1335             sig.update(message, messageOffset, actualChunkSizeBytes);
1336             messageOffset += actualChunkSizeBytes;
1337             messageRemaining -= actualChunkSizeBytes;
1338         }
1339         if (!sig.verify(signature)) {
1340             fail("Signature did not verify. algorithm: " + algorithm
1341                     + ", provider: " + sig.getProvider().getName()
1342                     + ", signature (" + signature.length + " bytes): "
1343                     + HexEncoding.encode(signature));
1344         }
1345     }
1346 
getMinimalWorkingImportParamsForSigning(String algorithm)1347     private static KeyProtection getMinimalWorkingImportParamsForSigning(String algorithm) {
1348         return TestUtils.getMinimalWorkingImportParametersForSigningingWith(algorithm);
1349     }
1350 
getMinimalWorkingImportParamsForVerifying( @uppressWarnings"unused") String algorithm)1351     private static KeyProtection getMinimalWorkingImportParamsForVerifying(
1352             @SuppressWarnings("unused") String algorithm) {
1353         // No need to authorize anything because verification does not use the private key.
1354         // Operations using public keys do not need authorization.
1355         return new KeyProtection.Builder(0).build();
1356     }
1357 
importKatKeyPairsForSigning( Context context, String signatureAlgorithm)1358     static Collection<ImportedKey> importKatKeyPairsForSigning(
1359             Context context, String signatureAlgorithm) throws Exception {
1360         String keyAlgorithm = TestUtils.getSignatureAlgorithmKeyAlgorithm(signatureAlgorithm);
1361         KeyProtection importParams =
1362                 TestUtils.getMinimalWorkingImportParametersForSigningingWith(signatureAlgorithm);
1363         if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(keyAlgorithm)) {
1364             return ECDSASignatureTest.importKatKeyPairs(context, importParams);
1365         } else if (KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(keyAlgorithm)) {
1366             return RSASignatureTest.importKatKeyPairs(context, importParams);
1367         } else {
1368             throw new IllegalArgumentException("Unsupported key algorithm: " + keyAlgorithm);
1369         }
1370     }
1371 
importLimitedUseKatKeyPairsForSigning( Context context, String signatureAlgorithm, int maxUsageCount)1372     static Collection<ImportedKey> importLimitedUseKatKeyPairsForSigning(
1373             Context context, String signatureAlgorithm, int maxUsageCount) throws Exception {
1374         String keyAlgorithm = TestUtils.getSignatureAlgorithmKeyAlgorithm(signatureAlgorithm);
1375         KeyProtection importParams =
1376                 TestUtils.getMinimalWorkingImportParametersWithLimitedUsageForSigningingWith(
1377                         signatureAlgorithm, maxUsageCount);
1378         if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(keyAlgorithm)) {
1379             return ECDSASignatureTest.importKatKeyPairs(context, importParams);
1380         } else if (KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(keyAlgorithm)) {
1381             return RSASignatureTest.importKatKeyPairs(context, importParams);
1382         } else {
1383             throw new IllegalArgumentException("Unsupported key algorithm: " + keyAlgorithm);
1384         }
1385     }
1386 }
1387