1 /* 2 * Copyright 2018 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 "export_key.h" 18 #include "proto_utils.h" 19 20 #include <android-base/logging.h> 21 22 #include <openssl/bn.h> 23 #include <openssl/bytestring.h> 24 #include <openssl/ec.h> 25 #include <openssl/evp.h> 26 #include <openssl/rsa.h> 27 28 namespace android { 29 namespace hardware { 30 namespace keymaster { 31 32 // HAL 33 using ::android::hardware::keymaster::V4_0::Algorithm; 34 using ::android::hardware::keymaster::V4_0::EcCurve; 35 using ::android::hardware::keymaster::V4_0::KeyFormat; 36 using ::android::hardware::keymaster::V4_0::Tag; 37 using ::android::hardware::keymaster::V4_0::TagType; 38 39 // App 40 namespace nosapp = nugget::app::keymaster; 41 42 // BoringSSL 43 using bssl::UniquePtr; 44 45 // std 46 using std::unique_ptr; 47 48 ErrorCode export_key_der(const ExportKeyResponse& response, 49 hidl_vec<uint8_t> *der) { 50 51 if (response.algorithm() == nosapp::Algorithm::RSA) { 52 bssl::UniquePtr<BIGNUM> n(BN_new()); 53 BN_le2bn( 54 reinterpret_cast<const uint8_t *>(response.rsa().n().data()), 55 response.rsa().n().size(), n.get()); 56 57 bssl::UniquePtr<BIGNUM> e(BN_new()); 58 if (!BN_set_word(e.get(), response.rsa().e())) { 59 LOG(ERROR) << "ExportKey: BN_set_word failed"; 60 return ErrorCode::UNKNOWN_ERROR; 61 } 62 63 bssl::UniquePtr<RSA> rsa(RSA_new()); 64 if (!RSA_set0_key(rsa.get(), n.get(), e.get(), NULL)) { 65 LOG(ERROR) << "ExportKey: RSA_set0_key failed"; 66 return ErrorCode::UNKNOWN_ERROR; 67 } 68 69 CBB cbb; 70 uint8_t *data = new uint8_t[1024]; /* Plenty for RSA 4-k. */ 71 CBB_init_fixed(&cbb, data, 1024); 72 bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new()); 73 EVP_PKEY_set1_RSA(pkey.get(), rsa.get()); 74 if (!EVP_marshal_public_key(&cbb, pkey.get())) { 75 LOG(ERROR) << "ExportKey: EVP_marshal_public_key failed"; 76 return ErrorCode::UNKNOWN_ERROR; 77 } 78 79 der->setToExternal( 80 const_cast<uint8_t*>( 81 data), CBB_len(&cbb), true /* Transfer ownership. */); 82 for (size_t i = 0; i < der->size(); i++) { 83 LOG(ERROR) << "exporting: " << std::hex << (int)der->data()[i]; 84 } 85 CBB_cleanup(&cbb); 86 } else { 87 EcCurve ec_curve; 88 /* TODO: eliminate this type-cast. */ 89 if (translate_ec_curve( 90 (nosapp::EcCurve)response.ec().curve_id(), 91 &ec_curve) != ErrorCode::OK) { 92 LOG(ERROR) << "Failed to parse response device ec curve_id: " 93 << response.ec().curve_id(); 94 return ErrorCode::UNKNOWN_ERROR; 95 } 96 int curve_nid; 97 switch (ec_curve) { 98 case EcCurve::P_224: 99 curve_nid = NID_secp224r1; 100 break; 101 case EcCurve::P_256: 102 curve_nid = NID_X9_62_prime256v1; 103 break; 104 case EcCurve::P_384: 105 curve_nid = NID_secp384r1; 106 break; 107 case EcCurve::P_521: 108 curve_nid = NID_secp521r1; 109 break; 110 default: 111 LOG(ERROR) << "ExportKey: received invalid EcCurve id: " 112 << (uint32_t) ec_curve; 113 return ErrorCode::UNKNOWN_ERROR; 114 } 115 116 bssl::UniquePtr<EC_GROUP> ec_group(EC_GROUP_new_by_curve_name(curve_nid)); 117 if (!ec_group.get()) { 118 LOG(ERROR) << "EC_GROUP_new_by_name(" 119 << (uint32_t)curve_nid << ") failed"; 120 return ErrorCode::UNKNOWN_ERROR; 121 } 122 bssl::UniquePtr<EC_POINT> ec_point(EC_POINT_new(ec_group.get())); 123 if (!ec_point.get()) { 124 LOG(ERROR) << "EC_POINT_new() failed"; 125 return ErrorCode::UNKNOWN_ERROR; 126 } 127 bssl::UniquePtr<BIGNUM> x(BN_new()); 128 BN_le2bn( 129 reinterpret_cast<const uint8_t *>(response.ec().x().data()), 130 response.ec().x().size(), x.get()); 131 bssl::UniquePtr<BIGNUM> y(BN_new()); 132 BN_le2bn( 133 reinterpret_cast<const uint8_t *>(response.ec().y().data()), 134 response.ec().y().size(), y.get()); 135 if (!EC_POINT_set_affine_coordinates_GFp( 136 ec_group.get(), ec_point.get(), x.get(), y.get(), NULL)) { 137 LOG(ERROR) << "EC_POINT_set_affine_coordinates() failed"; 138 return ErrorCode::UNKNOWN_ERROR; 139 } 140 141 bssl::UniquePtr<EC_KEY> ec_key(EC_KEY_new_by_curve_name(curve_nid)); 142 if (!ec_key.get()) { 143 LOG(ERROR) << "EC_KEY_new() failed"; 144 return ErrorCode::UNKNOWN_ERROR; 145 } 146 147 if (!EC_KEY_set_public_key(ec_key.get(), ec_point.get())) { 148 LOG(ERROR) << "EC_KEY_set_public_key() failed"; 149 return ErrorCode::UNKNOWN_ERROR; 150 } 151 152 bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new()); 153 if (!pkey.get()) { 154 LOG(ERROR) << "EVP_PKEY_new() failed"; 155 return ErrorCode::UNKNOWN_ERROR; 156 } 157 if (!EVP_PKEY_set1_EC_KEY(pkey.get(), ec_key.get())) { 158 LOG(ERROR) << "EVP_PKEY_set1_EC_KEY() failed"; 159 return ErrorCode::UNKNOWN_ERROR; 160 } 161 CBB cbb; 162 uint8_t *data = new uint8_t[256]; /* Plenty for EC-521. */ 163 CBB_init_fixed(&cbb, data, 256); 164 if (!EVP_marshal_public_key(&cbb, pkey.get())) { 165 LOG(ERROR) << "ExportKey: EVP_marshal_public_key failed"; 166 return ErrorCode::UNKNOWN_ERROR; 167 } 168 169 der->setToExternal( 170 const_cast<uint8_t*>( 171 data), CBB_len(&cbb), true /* Transfer ownership. */); 172 for (size_t i = 0; i < der->size(); i++) { 173 LOG(ERROR) << "exporting: " << std::hex << (int)der->data()[i]; 174 } 175 CBB_cleanup(&cbb); 176 } 177 178 return ErrorCode::OK; 179 } 180 181 } // namespace keymaster 182 } // hardware 183 } // android 184