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#include "openssl_utils.h" 18 19#include <keymaster/android_keymaster_utils.h> 20 21#include "openssl_err.h" 22 23namespace keymaster { 24 25keymaster_error_t ec_get_group_size(const EC_GROUP* group, size_t* key_size_bits) { 26 switch (EC_GROUP_get_curve_name(group)) { 27 case NID_secp224r1: 28 *key_size_bits = 224; 29 break; 30 case NID_X9_62_prime256v1: 31 *key_size_bits = 256; 32 break; 33 case NID_secp384r1: 34 *key_size_bits = 384; 35 break; 36 case NID_secp521r1: 37 *key_size_bits = 521; 38 break; 39 default: 40 return KM_ERROR_UNSUPPORTED_EC_FIELD; 41 } 42 return KM_ERROR_OK; 43} 44 45EC_GROUP* ec_get_group(keymaster_ec_curve_t curve) { 46 switch (curve) { 47 case KM_EC_CURVE_P_224: 48 return EC_GROUP_new_by_curve_name(NID_secp224r1); 49 break; 50 case KM_EC_CURVE_P_256: 51 return EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); 52 break; 53 case KM_EC_CURVE_P_384: 54 return EC_GROUP_new_by_curve_name(NID_secp384r1); 55 break; 56 case KM_EC_CURVE_P_521: 57 return EC_GROUP_new_by_curve_name(NID_secp521r1); 58 break; 59 default: 60 return nullptr; 61 break; 62 } 63} 64 65void convert_bn_to_blob(BIGNUM* bn, keymaster_blob_t* blob) { 66 blob->data_length = BN_num_bytes(bn); 67 blob->data = new uint8_t[blob->data_length]; 68 BN_bn2bin(bn, const_cast<uint8_t*>(blob->data)); 69} 70 71static int convert_to_evp(keymaster_algorithm_t algorithm) { 72 switch (algorithm) { 73 case KM_ALGORITHM_RSA: 74 return EVP_PKEY_RSA; 75 case KM_ALGORITHM_EC: 76 return EVP_PKEY_EC; 77 default: 78 return -1; 79 }; 80} 81 82keymaster_error_t convert_pkcs8_blob_to_evp(const uint8_t* key_data, size_t key_length, 83 keymaster_algorithm_t expected_algorithm, 84 UniquePtr<EVP_PKEY, EVP_PKEY_Delete>* pkey) { 85 if (key_data == NULL || key_length <= 0) 86 return KM_ERROR_INVALID_KEY_BLOB; 87 88 UniquePtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> pkcs8( 89 d2i_PKCS8_PRIV_KEY_INFO(NULL, &key_data, key_length)); 90 if (pkcs8.get() == NULL) 91 return TranslateLastOpenSslError(true /* log_message */); 92 93 pkey->reset(EVP_PKCS82PKEY(pkcs8.get())); 94 if (!pkey->get()) 95 return TranslateLastOpenSslError(true /* log_message */); 96 97 if (EVP_PKEY_type((*pkey)->type) != convert_to_evp(expected_algorithm)) { 98 LOG_E("EVP key algorithm was %d, not the expected %d", EVP_PKEY_type((*pkey)->type), 99 convert_to_evp(expected_algorithm)); 100 return KM_ERROR_INVALID_KEY_BLOB; 101 } 102 103 return KM_ERROR_OK; 104} 105 106keymaster_error_t KeyMaterialToEvpKey(keymaster_key_format_t key_format, 107 const KeymasterKeyBlob& key_material, 108 keymaster_algorithm_t expected_algorithm, 109 UniquePtr<EVP_PKEY, EVP_PKEY_Delete>* pkey) { 110 if (key_format != KM_KEY_FORMAT_PKCS8) 111 return KM_ERROR_UNSUPPORTED_KEY_FORMAT; 112 113 return convert_pkcs8_blob_to_evp(key_material.key_material, key_material.key_material_size, 114 expected_algorithm, pkey); 115} 116 117keymaster_error_t EvpKeyToKeyMaterial(const EVP_PKEY* pkey, KeymasterKeyBlob* key_blob) { 118 int key_data_size = i2d_PrivateKey(pkey, NULL /* key_data*/); 119 if (key_data_size <= 0) 120 return TranslateLastOpenSslError(); 121 122 if (!key_blob->Reset(key_data_size)) 123 return KM_ERROR_MEMORY_ALLOCATION_FAILED; 124 125 uint8_t* tmp = key_blob->writable_data(); 126 i2d_PrivateKey(pkey, &tmp); 127 128 return KM_ERROR_OK; 129} 130 131size_t ec_group_size_bits(EC_KEY* ec_key) { 132 const EC_GROUP* group = EC_KEY_get0_group(ec_key); 133 UniquePtr<BN_CTX, BN_CTX_Delete> bn_ctx(BN_CTX_new()); 134 UniquePtr<BIGNUM, BIGNUM_Delete> order(BN_new()); 135 if (!EC_GROUP_get_order(group, order.get(), bn_ctx.get())) { 136 LOG_E("Failed to get EC group order", 0); 137 return 0; 138 } 139 return BN_num_bits(order.get()); 140} 141 142} // namespace keymaster 143