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.annotation.Nullable;
21 import android.hardware.security.keymint.KeyParameter;
22 import android.security.keymaster.KeymasterDefs;
23 import android.security.keystore.KeyProperties;
24 import android.system.keystore2.Authorization;
25 
26 import java.security.AlgorithmParameters;
27 import java.security.InvalidAlgorithmParameterException;
28 import java.security.InvalidKeyException;
29 import java.security.Key;
30 import java.security.NoSuchAlgorithmException;
31 import java.security.PrivateKey;
32 import java.security.ProviderException;
33 import java.security.spec.AlgorithmParameterSpec;
34 import java.security.spec.InvalidParameterSpecException;
35 import java.security.spec.MGF1ParameterSpec;
36 import java.util.List;
37 
38 import javax.crypto.Cipher;
39 import javax.crypto.CipherSpi;
40 import javax.crypto.spec.OAEPParameterSpec;
41 import javax.crypto.spec.PSource;
42 
43 /**
44  * Base class for {@link CipherSpi} providing Android KeyStore backed RSA encryption/decryption.
45  *
46  * @hide
47  */
48 abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase {
49 
50     /**
51      * Raw RSA cipher without any padding.
52      */
53     public static final class NoPadding extends AndroidKeyStoreRSACipherSpi {
NoPadding()54         public NoPadding() {
55             super(KeymasterDefs.KM_PAD_NONE);
56         }
57 
58         @Override
adjustConfigForEncryptingWithPrivateKey()59         protected boolean adjustConfigForEncryptingWithPrivateKey() {
60             // RSA encryption with no padding using private key is a way to implement raw RSA
61             // signatures which JCA does not expose via Signature. We thus have to support this.
62             setKeymasterPurposeOverride(KeymasterDefs.KM_PURPOSE_SIGN);
63             return true;
64         }
65 
66         @Override
initAlgorithmSpecificParameters()67         protected void initAlgorithmSpecificParameters() throws InvalidKeyException {}
68 
69         @Override
initAlgorithmSpecificParameters(@ullable AlgorithmParameterSpec params)70         protected void initAlgorithmSpecificParameters(@Nullable AlgorithmParameterSpec params)
71                 throws InvalidAlgorithmParameterException {
72             if (params != null) {
73                 throw new InvalidAlgorithmParameterException(
74                         "Unexpected parameters: " + params + ". No parameters supported");
75             }
76         }
77 
78         @Override
initAlgorithmSpecificParameters(@ullable AlgorithmParameters params)79         protected void initAlgorithmSpecificParameters(@Nullable AlgorithmParameters params)
80                 throws InvalidAlgorithmParameterException {
81 
82             if (params != null) {
83                 throw new InvalidAlgorithmParameterException(
84                         "Unexpected parameters: " + params + ". No parameters supported");
85             }
86         }
87 
88         @Override
engineGetParameters()89         protected AlgorithmParameters engineGetParameters() {
90             return null;
91         }
92 
93         @Override
getAdditionalEntropyAmountForBegin()94         protected final int getAdditionalEntropyAmountForBegin() {
95             return 0;
96         }
97 
98         @Override
getAdditionalEntropyAmountForFinish()99         protected final int getAdditionalEntropyAmountForFinish() {
100             return 0;
101         }
102     }
103 
104     /**
105      * RSA cipher with PKCS#1 v1.5 encryption padding.
106      */
107     public static final class PKCS1Padding extends AndroidKeyStoreRSACipherSpi {
PKCS1Padding()108         public PKCS1Padding() {
109             super(KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
110         }
111 
112         @Override
adjustConfigForEncryptingWithPrivateKey()113         protected boolean adjustConfigForEncryptingWithPrivateKey() {
114             // RSA encryption with PCKS#1 padding using private key is a way to implement RSA
115             // signatures with PKCS#1 padding. We have to support this for legacy reasons.
116             setKeymasterPurposeOverride(KeymasterDefs.KM_PURPOSE_SIGN);
117             setKeymasterPaddingOverride(KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN);
118             return true;
119         }
120 
121         @Override
initAlgorithmSpecificParameters()122         protected void initAlgorithmSpecificParameters() throws InvalidKeyException {}
123 
124         @Override
initAlgorithmSpecificParameters(@ullable AlgorithmParameterSpec params)125         protected void initAlgorithmSpecificParameters(@Nullable AlgorithmParameterSpec params)
126                 throws InvalidAlgorithmParameterException {
127             if (params != null) {
128                 throw new InvalidAlgorithmParameterException(
129                         "Unexpected parameters: " + params + ". No parameters supported");
130             }
131         }
132 
133         @Override
initAlgorithmSpecificParameters(@ullable AlgorithmParameters params)134         protected void initAlgorithmSpecificParameters(@Nullable AlgorithmParameters params)
135                 throws InvalidAlgorithmParameterException {
136 
137             if (params != null) {
138                 throw new InvalidAlgorithmParameterException(
139                         "Unexpected parameters: " + params + ". No parameters supported");
140             }
141         }
142 
143         @Override
engineGetParameters()144         protected AlgorithmParameters engineGetParameters() {
145             return null;
146         }
147 
148         @Override
getAdditionalEntropyAmountForBegin()149         protected final int getAdditionalEntropyAmountForBegin() {
150             return 0;
151         }
152 
153         @Override
getAdditionalEntropyAmountForFinish()154         protected final int getAdditionalEntropyAmountForFinish() {
155             return (isEncrypting()) ? getModulusSizeBytes() : 0;
156         }
157     }
158 
159     /**
160      * RSA cipher with OAEP encryption padding.
161      */
162     abstract static class OAEPWithMGF1Padding extends AndroidKeyStoreRSACipherSpi {
163 
164         private static final String MGF_ALGORITHM_MGF1 = "MGF1";
165 
166         private int mKeymasterDigest = -1;
167         private int mDigestOutputSizeBytes;
168         private int mKeymasterMgf1Digest = KeymasterDefs.KM_DIGEST_SHA1; // Default MGF1 digest
169 
OAEPWithMGF1Padding(int keymasterDigest)170         OAEPWithMGF1Padding(int keymasterDigest) {
171             super(KeymasterDefs.KM_PAD_RSA_OAEP);
172             mKeymasterDigest = keymasterDigest;
173             mDigestOutputSizeBytes =
174                     (KeymasterUtils.getDigestOutputSizeBits(keymasterDigest) + 7) / 8;
175         }
176 
177         @Override
initAlgorithmSpecificParameters()178         protected final void initAlgorithmSpecificParameters() throws InvalidKeyException {}
179 
180         @Override
initAlgorithmSpecificParameters( @ullable AlgorithmParameterSpec params)181         protected final void initAlgorithmSpecificParameters(
182                 @Nullable AlgorithmParameterSpec params) throws InvalidAlgorithmParameterException {
183             if (params == null) {
184                 return;
185             }
186 
187             if (!(params instanceof OAEPParameterSpec)) {
188                 throw new InvalidAlgorithmParameterException(
189                         "Unsupported parameter spec: " + params
190                         + ". Only OAEPParameterSpec supported");
191             }
192             OAEPParameterSpec spec = (OAEPParameterSpec) params;
193             if (!MGF_ALGORITHM_MGF1.equalsIgnoreCase(spec.getMGFAlgorithm())) {
194                 throw new InvalidAlgorithmParameterException(
195                         "Unsupported MGF: " + spec.getMGFAlgorithm()
196                         + ". Only " + MGF_ALGORITHM_MGF1 + " supported");
197             }
198             String jcaDigest = spec.getDigestAlgorithm();
199             int keymasterDigest;
200             try {
201                 keymasterDigest = KeyProperties.Digest.toKeymaster(jcaDigest);
202             } catch (IllegalArgumentException e) {
203                 throw new InvalidAlgorithmParameterException(
204                         "Unsupported digest: " + jcaDigest, e);
205             }
206             switch (keymasterDigest) {
207                 case KeymasterDefs.KM_DIGEST_SHA1:
208                 case KeymasterDefs.KM_DIGEST_SHA_2_224:
209                 case KeymasterDefs.KM_DIGEST_SHA_2_256:
210                 case KeymasterDefs.KM_DIGEST_SHA_2_384:
211                 case KeymasterDefs.KM_DIGEST_SHA_2_512:
212                     // Permitted.
213                     break;
214                 default:
215                     throw new InvalidAlgorithmParameterException(
216                             "Unsupported digest: " + jcaDigest);
217             }
218             AlgorithmParameterSpec mgfParams = spec.getMGFParameters();
219             if (mgfParams == null) {
220                 throw new InvalidAlgorithmParameterException("MGF parameters must be provided");
221             }
222             // Check whether MGF parameters match the OAEPParameterSpec
223             if (!(mgfParams instanceof MGF1ParameterSpec)) {
224                 throw new InvalidAlgorithmParameterException("Unsupported MGF parameters"
225                         + ": " + mgfParams + ". Only MGF1ParameterSpec supported");
226             }
227             MGF1ParameterSpec mgfSpec = (MGF1ParameterSpec) mgfParams;
228             String mgf1JcaDigest = mgfSpec.getDigestAlgorithm();
229             PSource pSource = spec.getPSource();
230             if (!(pSource instanceof PSource.PSpecified)) {
231                 throw new InvalidAlgorithmParameterException(
232                         "Unsupported source of encoding input P: " + pSource
233                         + ". Only pSpecifiedEmpty (PSource.PSpecified.DEFAULT) supported");
234             }
235             PSource.PSpecified pSourceSpecified = (PSource.PSpecified) pSource;
236             byte[] pSourceValue = pSourceSpecified.getValue();
237             if ((pSourceValue != null) && (pSourceValue.length > 0)) {
238                 throw new InvalidAlgorithmParameterException(
239                         "Unsupported source of encoding input P: " + pSource
240                         + ". Only pSpecifiedEmpty (PSource.PSpecified.DEFAULT) supported");
241             }
242             mKeymasterDigest = keymasterDigest;
243             mKeymasterMgf1Digest = KeyProperties.Digest.toKeymaster(mgf1JcaDigest);
244             mDigestOutputSizeBytes =
245                     (KeymasterUtils.getDigestOutputSizeBits(keymasterDigest) + 7) / 8;
246         }
247 
248         @Override
initAlgorithmSpecificParameters(@ullable AlgorithmParameters params)249         protected final void initAlgorithmSpecificParameters(@Nullable AlgorithmParameters params)
250                 throws InvalidAlgorithmParameterException {
251             if (params == null) {
252                 return;
253             }
254 
255             OAEPParameterSpec spec;
256             try {
257                 spec = params.getParameterSpec(OAEPParameterSpec.class);
258             } catch (InvalidParameterSpecException e) {
259                 throw new InvalidAlgorithmParameterException("OAEP parameters required"
260                         + ", but not found in parameters: " + params, e);
261             }
262             if (spec == null) {
263                 throw new InvalidAlgorithmParameterException("OAEP parameters required"
264                         + ", but not provided in parameters: " + params);
265             }
266             initAlgorithmSpecificParameters(spec);
267         }
268 
269         @Override
engineGetParameters()270         protected final AlgorithmParameters engineGetParameters() {
271             OAEPParameterSpec spec =
272                     new OAEPParameterSpec(
273                         KeyProperties.Digest.fromKeymaster(mKeymasterDigest),
274                         MGF_ALGORITHM_MGF1,
275                         KeyProperties.Digest.fromKeymasterToMGF1ParameterSpec(mKeymasterMgf1Digest),
276                         PSource.PSpecified.DEFAULT);
277             try {
278                 AlgorithmParameters params = AlgorithmParameters.getInstance("OAEP");
279                 params.init(spec);
280                 return params;
281             } catch (NoSuchAlgorithmException e) {
282                 throw new ProviderException(
283                         "Failed to obtain OAEP AlgorithmParameters", e);
284             } catch (InvalidParameterSpecException e) {
285                 throw new ProviderException(
286                         "Failed to initialize OAEP AlgorithmParameters with an IV",
287                         e);
288             }
289         }
290 
isMgfDigestTagPresentInKeyProperties( Authorization[] keyCharacteristics)291         private static boolean isMgfDigestTagPresentInKeyProperties(
292                 Authorization[] keyCharacteristics) {
293             for (Authorization authorization : keyCharacteristics) {
294                 if (authorization.keyParameter.tag == KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST) {
295                     return true;
296                 }
297             }
298 
299             return false;
300         }
301 
302         @Override
addAlgorithmSpecificParametersToBegin( @onNull List<KeyParameter> parameters, Authorization[] keyCharacteristics)303         protected final void addAlgorithmSpecificParametersToBegin(
304                 @NonNull List<KeyParameter> parameters, Authorization[] keyCharacteristics) {
305             super.addAlgorithmSpecificParametersToBegin(parameters, keyCharacteristics);
306             parameters.add(KeyStore2ParameterUtils.makeEnum(
307                     KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest
308             ));
309             // Only add the KM_TAG_RSA_OAEP_MGF_DIGEST tag to begin() if the MGF Digest is
310             // present in the key properties. Keys generated prior to Android 14 did not have
311             // this tag (Keystore didn't add it) so specifying any MGF digest tag would cause
312             // a begin() operation (on an Android 14 device) to fail (with a key that was generated
313             // on Android 13 or below).
314             if (isMgfDigestTagPresentInKeyProperties(keyCharacteristics)) {
315                 parameters.add(KeyStore2ParameterUtils.makeEnum(
316                         KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST, mKeymasterMgf1Digest
317                 ));
318             }
319         }
320 
321         @Override
loadAlgorithmSpecificParametersFromBeginResult( KeyParameter[] parameters)322         protected final void loadAlgorithmSpecificParametersFromBeginResult(
323                 KeyParameter[] parameters) {
324             super.loadAlgorithmSpecificParametersFromBeginResult(parameters);
325         }
326 
327         @Override
getAdditionalEntropyAmountForBegin()328         protected final int getAdditionalEntropyAmountForBegin() {
329             return 0;
330         }
331 
332         @Override
getAdditionalEntropyAmountForFinish()333         protected final int getAdditionalEntropyAmountForFinish() {
334             return (isEncrypting()) ? mDigestOutputSizeBytes : 0;
335         }
336 
337         @Override
getTransform()338         protected final String getTransform() {
339             switch (mKeymasterDigest) {
340                 case KeymasterDefs.KM_DIGEST_SHA1:
341                     return "RSA/ECB/OAEPWithSHA-1AndMGF1Padding";
342                 case KeymasterDefs.KM_DIGEST_SHA_2_224:
343                     return "RSA/ECB/OAEPWithSHA-224AndMGF1Padding";
344                 case KeymasterDefs.KM_DIGEST_SHA_2_256:
345                     return "RSA/ECB/OAEPWithSHA-256AndMGF1Padding";
346                 case KeymasterDefs.KM_DIGEST_SHA_2_384:
347                     return "RSA/ECB/OAEPWithSHA-384AndMGF1Padding";
348                 case KeymasterDefs.KM_DIGEST_SHA_2_512:
349                     return "RSA/ECB/OAEPWithSHA-512AndMGF1Padding";
350                 default:
351                     return "RSA/ECB/OAEPPadding";
352             }
353         }
354 
355     }
356 
357     public static class OAEPWithSHA1AndMGF1Padding extends OAEPWithMGF1Padding {
OAEPWithSHA1AndMGF1Padding()358         public OAEPWithSHA1AndMGF1Padding() {
359             super(KeymasterDefs.KM_DIGEST_SHA1);
360         }
361     }
362 
363     public static class OAEPWithSHA224AndMGF1Padding extends OAEPWithMGF1Padding {
OAEPWithSHA224AndMGF1Padding()364         public OAEPWithSHA224AndMGF1Padding() {
365             super(KeymasterDefs.KM_DIGEST_SHA_2_224);
366         }
367     }
368 
369     public static class OAEPWithSHA256AndMGF1Padding extends OAEPWithMGF1Padding {
OAEPWithSHA256AndMGF1Padding()370         public OAEPWithSHA256AndMGF1Padding() {
371             super(KeymasterDefs.KM_DIGEST_SHA_2_256);
372         }
373     }
374 
375     public static class OAEPWithSHA384AndMGF1Padding extends OAEPWithMGF1Padding {
OAEPWithSHA384AndMGF1Padding()376         public OAEPWithSHA384AndMGF1Padding() {
377             super(KeymasterDefs.KM_DIGEST_SHA_2_384);
378         }
379     }
380 
381     public static class OAEPWithSHA512AndMGF1Padding extends OAEPWithMGF1Padding {
OAEPWithSHA512AndMGF1Padding()382         public OAEPWithSHA512AndMGF1Padding() {
383             super(KeymasterDefs.KM_DIGEST_SHA_2_512);
384         }
385     }
386 
387     private final int mKeymasterPadding;
388     private int mKeymasterPaddingOverride;
389 
390     private int mModulusSizeBytes = -1;
391 
AndroidKeyStoreRSACipherSpi(int keymasterPadding)392     AndroidKeyStoreRSACipherSpi(int keymasterPadding) {
393         mKeymasterPadding = keymasterPadding;
394     }
395 
396     @Override
getTransform()397     protected String getTransform() {
398         return "RSA/ECB/" + KeyProperties.EncryptionPadding.fromKeymaster(mKeymasterPadding);
399     }
400 
401     @Override
initKey(int opmode, Key key)402     protected final void initKey(int opmode, Key key) throws InvalidKeyException {
403         if (key == null) {
404             throw new InvalidKeyException("Unsupported key: null");
405         }
406         if (!KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(key.getAlgorithm())) {
407             throw new InvalidKeyException("Unsupported key algorithm: " + key.getAlgorithm()
408                     + ". Only " + KeyProperties.KEY_ALGORITHM_RSA + " supported");
409         }
410         AndroidKeyStoreKey keystoreKey;
411         if (key instanceof AndroidKeyStorePrivateKey) {
412             keystoreKey = (AndroidKeyStoreKey) key;
413         } else if (key instanceof AndroidKeyStorePublicKey) {
414             keystoreKey = (AndroidKeyStoreKey) key;
415         } else {
416             throw new InvalidKeyException("Unsupported key type: " + key);
417         }
418 
419         if (keystoreKey instanceof PrivateKey) {
420             // Private key
421             switch (opmode) {
422                 case Cipher.DECRYPT_MODE:
423                 case Cipher.UNWRAP_MODE:
424                     // Permitted
425                     break;
426                 case Cipher.ENCRYPT_MODE:
427                 case Cipher.WRAP_MODE:
428                     if (!adjustConfigForEncryptingWithPrivateKey()) {
429                         throw new InvalidKeyException(
430                                 "RSA private keys cannot be used with " + opmodeToString(opmode)
431                                 + " and padding "
432                                 + KeyProperties.EncryptionPadding.fromKeymaster(mKeymasterPadding)
433                                 + ". Only RSA public keys supported for this mode");
434                     }
435                     break;
436                 default:
437                     throw new InvalidKeyException(
438                             "RSA private keys cannot be used with opmode: " + opmode);
439             }
440         } else {
441             // Public key
442             switch (opmode) {
443                 case Cipher.ENCRYPT_MODE:
444                 case Cipher.WRAP_MODE:
445                     // Permitted
446                     break;
447                 case Cipher.DECRYPT_MODE:
448                 case Cipher.UNWRAP_MODE:
449                     throw new InvalidKeyException(
450                             "RSA public keys cannot be used with " + opmodeToString(opmode)
451                             + " and padding "
452                             + KeyProperties.EncryptionPadding.fromKeymaster(mKeymasterPadding)
453                             + ". Only RSA private keys supported for this opmode.");
454                     // break;
455                 default:
456                     throw new InvalidKeyException(
457                             "RSA public keys cannot be used with " + opmodeToString(opmode));
458             }
459         }
460 
461         long keySizeBits = -1;
462         for (Authorization a : keystoreKey.getAuthorizations()) {
463             if (a.keyParameter.tag == KeymasterDefs.KM_TAG_KEY_SIZE) {
464                 keySizeBits = KeyStore2ParameterUtils.getUnsignedInt(a);
465             }
466         }
467 
468         if (keySizeBits == -1) {
469             throw new InvalidKeyException("Size of key not known");
470         } else if (keySizeBits > Integer.MAX_VALUE) {
471             throw new InvalidKeyException("Key too large: " + keySizeBits + " bits");
472         }
473         mModulusSizeBytes = (int) ((keySizeBits + 7) / 8);
474 
475         setKey(keystoreKey);
476     }
477 
478     /**
479      * Adjusts the configuration of this cipher for encrypting using the private key.
480      *
481      * <p>The default implementation does nothing and refuses to adjust the configuration.
482      *
483      * @return {@code true} if the configuration has been adjusted, {@code false} if encrypting
484      *         using private key is not permitted for this cipher.
485      */
adjustConfigForEncryptingWithPrivateKey()486     protected boolean adjustConfigForEncryptingWithPrivateKey() {
487         return false;
488     }
489 
490     @Override
resetAll()491     protected final void resetAll() {
492         mModulusSizeBytes = -1;
493         mKeymasterPaddingOverride = -1;
494         super.resetAll();
495     }
496 
497     @Override
resetWhilePreservingInitState()498     protected final void resetWhilePreservingInitState() {
499         super.resetWhilePreservingInitState();
500     }
501 
502     @Override
addAlgorithmSpecificParametersToBegin( @onNull List<KeyParameter> parameters)503     protected void addAlgorithmSpecificParametersToBegin(
504             @NonNull List<KeyParameter> parameters) {
505         parameters.add(KeyStore2ParameterUtils.makeEnum(
506                 KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_RSA
507         ));
508         int keymasterPadding = getKeymasterPaddingOverride();
509         if (keymasterPadding == -1) {
510             keymasterPadding = mKeymasterPadding;
511         }
512         parameters.add(KeyStore2ParameterUtils.makeEnum(
513                 KeymasterDefs.KM_TAG_PADDING, keymasterPadding
514         ));
515         int purposeOverride = getKeymasterPurposeOverride();
516         if ((purposeOverride != -1)
517                 && ((purposeOverride == KeymasterDefs.KM_PURPOSE_SIGN)
518                 || (purposeOverride == KeymasterDefs.KM_PURPOSE_VERIFY))) {
519             // Keymaster sign/verify requires digest to be specified.
520             // For raw sign/verify it's NONE.
521             parameters.add(KeyStore2ParameterUtils.makeEnum(
522                     KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_NONE
523             ));
524         }
525     }
526 
527     @Override
loadAlgorithmSpecificParametersFromBeginResult( KeyParameter[] parameters)528     protected void loadAlgorithmSpecificParametersFromBeginResult(
529             KeyParameter[] parameters) {
530     }
531 
532     @Override
engineGetBlockSize()533     protected final int engineGetBlockSize() {
534         // Not a block cipher, according to the RI
535         return 0;
536     }
537 
538     @Override
engineGetIV()539     protected final byte[] engineGetIV() {
540         // IV never used
541         return null;
542     }
543 
544     @Override
engineGetOutputSize(int inputLen)545     protected final int engineGetOutputSize(int inputLen) {
546         return getModulusSizeBytes();
547     }
548 
getModulusSizeBytes()549     protected final int getModulusSizeBytes() {
550         if (mModulusSizeBytes == -1) {
551             throw new IllegalStateException("Not initialized");
552         }
553         return mModulusSizeBytes;
554     }
555 
556     /**
557      * Overrides the default padding of the crypto operation.
558      */
setKeymasterPaddingOverride(int keymasterPadding)559     protected final void setKeymasterPaddingOverride(int keymasterPadding) {
560         mKeymasterPaddingOverride = keymasterPadding;
561     }
562 
getKeymasterPaddingOverride()563     protected final int getKeymasterPaddingOverride() {
564         return mKeymasterPaddingOverride;
565     }
566 }
567