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
export_key_der(const ExportKeyResponse & response,hidl_vec<uint8_t> * der)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 CBB_cleanup(&cbb);
83 } else {
84 EcCurve ec_curve;
85 /* TODO: eliminate this type-cast. */
86 if (translate_ec_curve(
87 (nosapp::EcCurve)response.ec().curve_id(),
88 &ec_curve) != ErrorCode::OK) {
89 LOG(ERROR) << "Failed to parse response device ec curve_id: "
90 << response.ec().curve_id();
91 return ErrorCode::UNKNOWN_ERROR;
92 }
93 int curve_nid;
94 switch (ec_curve) {
95 case EcCurve::P_224:
96 curve_nid = NID_secp224r1;
97 break;
98 case EcCurve::P_256:
99 curve_nid = NID_X9_62_prime256v1;
100 break;
101 case EcCurve::P_384:
102 curve_nid = NID_secp384r1;
103 break;
104 case EcCurve::P_521:
105 curve_nid = NID_secp521r1;
106 break;
107 default:
108 LOG(ERROR) << "ExportKey: received invalid EcCurve id: "
109 << (uint32_t) ec_curve;
110 return ErrorCode::UNKNOWN_ERROR;
111 }
112
113 bssl::UniquePtr<EC_GROUP> ec_group(EC_GROUP_new_by_curve_name(curve_nid));
114 if (!ec_group.get()) {
115 LOG(ERROR) << "EC_GROUP_new_by_name("
116 << (uint32_t)curve_nid << ") failed";
117 return ErrorCode::UNKNOWN_ERROR;
118 }
119 bssl::UniquePtr<EC_POINT> ec_point(EC_POINT_new(ec_group.get()));
120 if (!ec_point.get()) {
121 LOG(ERROR) << "EC_POINT_new() failed";
122 return ErrorCode::UNKNOWN_ERROR;
123 }
124 bssl::UniquePtr<BIGNUM> x(BN_new());
125 BN_le2bn(
126 reinterpret_cast<const uint8_t *>(response.ec().x().data()),
127 response.ec().x().size(), x.get());
128 bssl::UniquePtr<BIGNUM> y(BN_new());
129 BN_le2bn(
130 reinterpret_cast<const uint8_t *>(response.ec().y().data()),
131 response.ec().y().size(), y.get());
132 if (!EC_POINT_set_affine_coordinates_GFp(
133 ec_group.get(), ec_point.get(), x.get(), y.get(), NULL)) {
134 LOG(ERROR) << "EC_POINT_set_affine_coordinates() failed";
135 return ErrorCode::UNKNOWN_ERROR;
136 }
137
138 bssl::UniquePtr<EC_KEY> ec_key(EC_KEY_new_by_curve_name(curve_nid));
139 if (!ec_key.get()) {
140 LOG(ERROR) << "EC_KEY_new() failed";
141 return ErrorCode::UNKNOWN_ERROR;
142 }
143
144 if (!EC_KEY_set_public_key(ec_key.get(), ec_point.get())) {
145 LOG(ERROR) << "EC_KEY_set_public_key() failed";
146 return ErrorCode::UNKNOWN_ERROR;
147 }
148
149 bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
150 if (!pkey.get()) {
151 LOG(ERROR) << "EVP_PKEY_new() failed";
152 return ErrorCode::UNKNOWN_ERROR;
153 }
154 if (!EVP_PKEY_set1_EC_KEY(pkey.get(), ec_key.get())) {
155 LOG(ERROR) << "EVP_PKEY_set1_EC_KEY() failed";
156 return ErrorCode::UNKNOWN_ERROR;
157 }
158 CBB cbb;
159 uint8_t *data = new uint8_t[256]; /* Plenty for EC-521. */
160 CBB_init_fixed(&cbb, data, 256);
161 if (!EVP_marshal_public_key(&cbb, pkey.get())) {
162 LOG(ERROR) << "ExportKey: EVP_marshal_public_key failed";
163 return ErrorCode::UNKNOWN_ERROR;
164 }
165
166 der->setToExternal(
167 const_cast<uint8_t*>(
168 data), CBB_len(&cbb), true /* Transfer ownership. */);
169 CBB_cleanup(&cbb);
170 }
171
172 return ErrorCode::OK;
173 }
174
175 } // namespace keymaster
176 } // hardware
177 } // android
178