1 /* 2 * Copyright (C) 2021 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.security.keymaster.KeymasterDefs; 20 21 import java.security.AlgorithmParameters; 22 import java.security.NoSuchAlgorithmException; 23 import java.security.spec.ECGenParameterSpec; 24 import java.security.spec.ECParameterSpec; 25 import java.security.spec.InvalidParameterSpecException; 26 27 /** 28 * @hide 29 */ 30 public final class KeymasterUtils { 31 KeymasterUtils()32 private KeymasterUtils() {} 33 34 /** @hide */ getDigestOutputSizeBits(int keymasterDigest)35 static int getDigestOutputSizeBits(int keymasterDigest) { 36 switch (keymasterDigest) { 37 case KeymasterDefs.KM_DIGEST_NONE: 38 return -1; 39 case KeymasterDefs.KM_DIGEST_MD5: 40 return 128; 41 case KeymasterDefs.KM_DIGEST_SHA1: 42 return 160; 43 case KeymasterDefs.KM_DIGEST_SHA_2_224: 44 return 224; 45 case KeymasterDefs.KM_DIGEST_SHA_2_256: 46 return 256; 47 case KeymasterDefs.KM_DIGEST_SHA_2_384: 48 return 384; 49 case KeymasterDefs.KM_DIGEST_SHA_2_512: 50 return 512; 51 default: 52 throw new IllegalArgumentException("Unknown digest: " + keymasterDigest); 53 } 54 } 55 56 /** @hide */ isKeymasterBlockModeIndCpaCompatibleWithSymmetricCrypto( int keymasterBlockMode)57 static boolean isKeymasterBlockModeIndCpaCompatibleWithSymmetricCrypto( 58 int keymasterBlockMode) { 59 switch (keymasterBlockMode) { 60 case KeymasterDefs.KM_MODE_ECB: 61 return false; 62 case KeymasterDefs.KM_MODE_CBC: 63 case KeymasterDefs.KM_MODE_CTR: 64 case KeymasterDefs.KM_MODE_GCM: 65 return true; 66 default: 67 throw new IllegalArgumentException("Unsupported block mode: " + keymasterBlockMode); 68 } 69 } 70 71 /** @hide */ isKeymasterPaddingSchemeIndCpaCompatibleWithAsymmetricCrypto( int keymasterPadding)72 static boolean isKeymasterPaddingSchemeIndCpaCompatibleWithAsymmetricCrypto( 73 int keymasterPadding) { 74 switch (keymasterPadding) { 75 case KeymasterDefs.KM_PAD_NONE: 76 return false; 77 case KeymasterDefs.KM_PAD_RSA_OAEP: 78 case KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_ENCRYPT: 79 return true; 80 default: 81 throw new IllegalArgumentException( 82 "Unsupported asymmetric encryption padding scheme: " + keymasterPadding); 83 } 84 } 85 getEcCurveFromKeymaster(int ecCurve)86 static String getEcCurveFromKeymaster(int ecCurve) { 87 switch (ecCurve) { 88 case android.hardware.security.keymint.EcCurve.P_224: 89 return "secp224r1"; 90 case android.hardware.security.keymint.EcCurve.P_256: 91 return "secp256r1"; 92 case android.hardware.security.keymint.EcCurve.P_384: 93 return "secp384r1"; 94 case android.hardware.security.keymint.EcCurve.P_521: 95 return "secp521r1"; 96 } 97 return ""; 98 } 99 getKeymasterEcCurve(String ecCurveName)100 static int getKeymasterEcCurve(String ecCurveName) { 101 if (ecCurveName.equals("secp224r1")) { 102 return android.hardware.security.keymint.EcCurve.P_224; 103 } else if (ecCurveName.equals("secp256r1")) { 104 return android.hardware.security.keymint.EcCurve.P_256; 105 } else if (ecCurveName.equals("secp384r1")) { 106 return android.hardware.security.keymint.EcCurve.P_384; 107 } else if (ecCurveName.equals("secp521r1")) { 108 return android.hardware.security.keymint.EcCurve.P_521; 109 } 110 return -1; 111 } 112 getCurveSpec(String name)113 static ECParameterSpec getCurveSpec(String name) 114 throws NoSuchAlgorithmException, InvalidParameterSpecException { 115 AlgorithmParameters parameters = AlgorithmParameters.getInstance("EC"); 116 parameters.init(new ECGenParameterSpec(name)); 117 return parameters.getParameterSpec(ECParameterSpec.class); 118 } 119 getCurveName(ECParameterSpec spec)120 static String getCurveName(ECParameterSpec spec) { 121 if (KeymasterUtils.isECParameterSpecOfCurve(spec, "secp224r1")) { 122 return "secp224r1"; 123 } else if (KeymasterUtils.isECParameterSpecOfCurve(spec, "secp256r1")) { 124 return "secp256r1"; 125 } else if (KeymasterUtils.isECParameterSpecOfCurve(spec, "secp384r1")) { 126 return "secp384r1"; 127 } else if (KeymasterUtils.isECParameterSpecOfCurve(spec, "secp521r1")) { 128 return "secp521r1"; 129 } 130 return null; 131 } 132 isECParameterSpecOfCurve(ECParameterSpec spec, String curveName)133 private static boolean isECParameterSpecOfCurve(ECParameterSpec spec, String curveName) { 134 try { 135 ECParameterSpec curveSpec = KeymasterUtils.getCurveSpec(curveName); 136 if (curveSpec.getCurve().equals(spec.getCurve()) 137 && curveSpec.getOrder().equals(spec.getOrder()) 138 && curveSpec.getGenerator().equals(spec.getGenerator())) { 139 return true; 140 } 141 } catch (NoSuchAlgorithmException | InvalidParameterSpecException e) { 142 return false; 143 } 144 return false; 145 } 146 } 147