1 /*
2  * Copyright (C) 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.security.keystore2;
18 
19 import android.annotation.NonNull;
20 import android.hardware.security.keymint.KeyParameter;
21 import android.security.keymaster.KeymasterDefs;
22 import android.security.keystore.KeyProperties;
23 
24 import java.security.InvalidKeyException;
25 import java.security.SignatureSpi;
26 import java.util.List;
27 
28 /**
29  * Base class for {@link SignatureSpi} providing Android KeyStore backed RSA signatures.
30  *
31  * @hide
32  */
33 abstract class AndroidKeyStoreRSASignatureSpi extends AndroidKeyStoreSignatureSpiBase {
34 
35     abstract static class PKCS1Padding extends AndroidKeyStoreRSASignatureSpi {
PKCS1Padding(int keymasterDigest)36         PKCS1Padding(int keymasterDigest) {
37             super(keymasterDigest, KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN);
38         }
39 
40         @Override
getAdditionalEntropyAmountForSign()41         protected final int getAdditionalEntropyAmountForSign() {
42             // No entropy required for this deterministic signature scheme.
43             return 0;
44         }
45     }
46 
47     public static final class NONEWithPKCS1Padding extends PKCS1Padding {
NONEWithPKCS1Padding()48         public NONEWithPKCS1Padding() {
49             super(KeymasterDefs.KM_DIGEST_NONE);
50         }
51         @Override
getAlgorithm()52         protected String getAlgorithm() {
53             return "NONEwithRSA";
54         }
55     }
56 
57     public static final class MD5WithPKCS1Padding extends PKCS1Padding {
MD5WithPKCS1Padding()58         public MD5WithPKCS1Padding() {
59             super(KeymasterDefs.KM_DIGEST_MD5);
60         }
61         @Override
getAlgorithm()62         protected String getAlgorithm() {
63             return "MD5withRSA";
64         }
65     }
66 
67     public static final class SHA1WithPKCS1Padding extends PKCS1Padding {
SHA1WithPKCS1Padding()68         public SHA1WithPKCS1Padding() {
69             super(KeymasterDefs.KM_DIGEST_SHA1);
70         }
71         @Override
getAlgorithm()72         protected String getAlgorithm() {
73             return "SHA1withRSA";
74         }
75     }
76 
77     public static final class SHA224WithPKCS1Padding extends PKCS1Padding {
SHA224WithPKCS1Padding()78         public SHA224WithPKCS1Padding() {
79             super(KeymasterDefs.KM_DIGEST_SHA_2_224);
80         }
81         @Override
getAlgorithm()82         protected String getAlgorithm() {
83             return "SHA224withRSA";
84         }
85     }
86 
87     public static final class SHA256WithPKCS1Padding extends PKCS1Padding {
SHA256WithPKCS1Padding()88         public SHA256WithPKCS1Padding() {
89             super(KeymasterDefs.KM_DIGEST_SHA_2_256);
90         }
91         @Override
getAlgorithm()92         protected String getAlgorithm() {
93             return "SHA256withRSA";
94         }
95     }
96 
97     public static final class SHA384WithPKCS1Padding extends PKCS1Padding {
SHA384WithPKCS1Padding()98         public SHA384WithPKCS1Padding() {
99             super(KeymasterDefs.KM_DIGEST_SHA_2_384);
100         }
101         @Override
getAlgorithm()102         protected String getAlgorithm() {
103             return "SHA384withRSA";
104         }
105     }
106 
107     public static final class SHA512WithPKCS1Padding extends PKCS1Padding {
SHA512WithPKCS1Padding()108         public SHA512WithPKCS1Padding() {
109             super(KeymasterDefs.KM_DIGEST_SHA_2_512);
110         }
111         @Override
getAlgorithm()112         protected String getAlgorithm() {
113             return "SHA512withRSA";
114         }
115     }
116 
117     abstract static class PSSPadding extends AndroidKeyStoreRSASignatureSpi {
118         private static final int SALT_LENGTH_BYTES = 20;
119 
PSSPadding(int keymasterDigest)120         PSSPadding(int keymasterDigest) {
121             super(keymasterDigest, KeymasterDefs.KM_PAD_RSA_PSS);
122         }
123 
124         @Override
getAdditionalEntropyAmountForSign()125         protected final int getAdditionalEntropyAmountForSign() {
126             return SALT_LENGTH_BYTES;
127         }
128     }
129 
130     public static final class SHA1WithPSSPadding extends PSSPadding {
SHA1WithPSSPadding()131         public SHA1WithPSSPadding() {
132             super(KeymasterDefs.KM_DIGEST_SHA1);
133         }
134         @Override
getAlgorithm()135         protected String getAlgorithm() {
136             return "SHA1withRSA/PSS";
137         }
138     }
139 
140     public static final class SHA224WithPSSPadding extends PSSPadding {
SHA224WithPSSPadding()141         public SHA224WithPSSPadding() {
142             super(KeymasterDefs.KM_DIGEST_SHA_2_224);
143         }
144         @Override
getAlgorithm()145         protected String getAlgorithm() {
146             return "SHA224withRSA/PSS";
147         }
148     }
149 
150     public static final class SHA256WithPSSPadding extends PSSPadding {
SHA256WithPSSPadding()151         public SHA256WithPSSPadding() {
152             super(KeymasterDefs.KM_DIGEST_SHA_2_256);
153         }
154         @Override
getAlgorithm()155         protected String getAlgorithm() {
156             return "SHA256withRSA/PSS";
157         }
158     }
159 
160     public static final class SHA384WithPSSPadding extends PSSPadding {
SHA384WithPSSPadding()161         public SHA384WithPSSPadding() {
162             super(KeymasterDefs.KM_DIGEST_SHA_2_384);
163         }
164         @Override
getAlgorithm()165         protected String getAlgorithm() {
166             return "SHA384withRSA/PSS";
167         }
168     }
169 
170     public static final class SHA512WithPSSPadding extends PSSPadding {
SHA512WithPSSPadding()171         public SHA512WithPSSPadding() {
172             super(KeymasterDefs.KM_DIGEST_SHA_2_512);
173         }
174         @Override
getAlgorithm()175         protected String getAlgorithm() {
176             return "SHA512withRSA/PSS";
177         }
178     }
179 
180     private final int mKeymasterDigest;
181     private final int mKeymasterPadding;
182 
AndroidKeyStoreRSASignatureSpi(int keymasterDigest, int keymasterPadding)183     AndroidKeyStoreRSASignatureSpi(int keymasterDigest, int keymasterPadding) {
184         mKeymasterDigest = keymasterDigest;
185         mKeymasterPadding = keymasterPadding;
186     }
187 
188     @Override
initKey(AndroidKeyStoreKey key)189     protected final void initKey(AndroidKeyStoreKey key) throws InvalidKeyException {
190         if (!KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(key.getAlgorithm())) {
191             throw new InvalidKeyException("Unsupported key algorithm: " + key.getAlgorithm()
192                     + ". Only" + KeyProperties.KEY_ALGORITHM_RSA + " supported");
193         }
194         super.initKey(key);
195     }
196 
197     @Override
resetAll()198     protected final void resetAll() {
199         super.resetAll();
200     }
201 
202     @Override
resetWhilePreservingInitState()203     protected final void resetWhilePreservingInitState() {
204         super.resetWhilePreservingInitState();
205     }
206 
207     @Override
addAlgorithmSpecificParametersToBegin( @onNull List<KeyParameter> parameters)208     protected final void addAlgorithmSpecificParametersToBegin(
209             @NonNull List<KeyParameter> parameters) {
210         parameters.add(KeyStore2ParameterUtils.makeEnum(
211                 KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_RSA
212         ));
213         parameters.add(KeyStore2ParameterUtils.makeEnum(
214                 KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest
215         ));
216         parameters.add(KeyStore2ParameterUtils.makeEnum(
217                 KeymasterDefs.KM_TAG_PADDING, mKeymasterPadding
218         ));
219     }
220 }
221