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