1 /*
2 * Copyright (C) 2017 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 <../proto_utils.h>
18
19 #include <MockKeymaster.client.h>
20 #include <KeymasterDevice.h>
21
22 #include <keymasterV4_0/keymaster_tags.h>
23
24 #include <android-base/logging.h>
25 #include <gtest/gtest.h>
26
27 #include <openssl/evp.h>
28 #include <openssl/rsa.h>
29 #include <openssl/pkcs8.h>
30
31 #include <string>
32
33 using ::std::string;
34 using ::std::unique_ptr;
35
36 using ::testing::_;
37 using ::testing::DoAll;
38 using ::testing::Eq;
39 using ::testing::Matcher;
40 using ::testing::MatcherInterface;
41 using ::testing::MatchResultListener;
42 using ::testing::Return;
43 using ::testing::SetArgPointee;
44
45 // Hardware
46 using ::android::hardware::hidl_vec;
47 using ::android::hardware::keymaster::KeymasterDevice;
48
49 // HAL
50 using ::android::hardware::keymaster::V4_0::Algorithm;
51 using ::android::hardware::keymaster::V4_0::EcCurve;
52 using ::android::hardware::keymaster::V4_0::ErrorCode;
53 using ::android::hardware::keymaster::V4_0::KeyFormat;
54 using ::android::hardware::keymaster::V4_0::KeyParameter;
55 using ::android::hardware::keymaster::V4_0::KeyCharacteristics;
56 using ::android::hardware::keymaster::V4_0::Tag;
57 using android::hardware::keymaster::pb_to_hidl_params;
58
59 // App
60 //using namespace ::nugget::app::keymaster;
61 namespace nosapp = ::nugget::app::keymaster;
62 using ::nugget::app::keymaster::MockKeymaster;
63 using ::nugget::app::keymaster::ImportKeyRequest;
64 using ::nugget::app::keymaster::ImportKeyResponse;
65
66 // ImportKey
67
68 static uint8_t TEST_RSA1024_KEY[] = {
69 0x30, 0x82, 0x02, 0x5c, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0xba,
70 0x9f, 0x5e, 0xf0, 0x58, 0xda, 0x49, 0xbe, 0x6b, 0x3c, 0xef, 0x17, 0x6f,
71 0x2f, 0x4f, 0x81, 0x18, 0x21, 0x4f, 0xbd, 0x6c, 0x17, 0xaa, 0x74, 0x99,
72 0xcc, 0x55, 0x94, 0x0f, 0xee, 0xa4, 0x0e, 0xae, 0x68, 0x4c, 0xaf, 0x11,
73 0x86, 0xdd, 0x50, 0xbf, 0x5c, 0x0f, 0x22, 0xad, 0xfa, 0xd1, 0x42, 0xab,
74 0xb8, 0x01, 0x7c, 0x2f, 0x54, 0xc7, 0xd9, 0xac, 0x47, 0xe3, 0xe1, 0x6b,
75 0x51, 0x48, 0xb6, 0xbb, 0x33, 0xab, 0xba, 0x9f, 0x86, 0x1b, 0xdf, 0xea,
76 0x9f, 0x2d, 0xb6, 0x40, 0xe3, 0x22, 0xbe, 0x90, 0xd6, 0x0d, 0xca, 0x2e,
77 0xb7, 0x8d, 0x8f, 0xf9, 0xd7, 0xeb, 0xa5, 0x74, 0x69, 0xc0, 0x87, 0x9b,
78 0x73, 0x17, 0x65, 0xde, 0x90, 0xb9, 0x5a, 0xde, 0xe0, 0xa4, 0xf3, 0xde,
79 0xeb, 0x9d, 0x3d, 0xb3, 0x12, 0x84, 0xf0, 0xdb, 0x43, 0x82, 0x0a, 0x8c,
80 0x64, 0x48, 0x4e, 0x9d, 0xd8, 0x13, 0x6d, 0x02, 0x03, 0x01, 0x00, 0x01,
81 0x02, 0x81, 0x80, 0x48, 0x20, 0xc7, 0x8f, 0x4a, 0x30, 0x17, 0xf7, 0x5e,
82 0x38, 0x1f, 0x4a, 0x65, 0xe1, 0x19, 0xaf, 0xd1, 0xd5, 0x32, 0x1e, 0x0a,
83 0x74, 0x7d, 0x1f, 0x72, 0xbf, 0xdc, 0x45, 0x8d, 0x00, 0xd5, 0x6c, 0x8d,
84 0x30, 0xe7, 0x8e, 0x74, 0x4e, 0x35, 0x24, 0x7b, 0xc9, 0x47, 0x5a, 0x46,
85 0x76, 0xdd, 0xc1, 0x10, 0x60, 0x5e, 0x46, 0x92, 0x7e, 0x88, 0x7d, 0x53,
86 0x4e, 0x37, 0xbf, 0x8c, 0x7c, 0x4e, 0x87, 0x12, 0x97, 0x5a, 0xbc, 0x4a,
87 0x13, 0x56, 0xf4, 0x6f, 0xd7, 0x85, 0xd8, 0xe9, 0xed, 0x86, 0x6e, 0xc0,
88 0x7b, 0xe5, 0x9e, 0x0e, 0x2a, 0xd2, 0x55, 0x60, 0x5c, 0x79, 0x36, 0xe0,
89 0x09, 0x46, 0xf2, 0xf3, 0x61, 0x87, 0xc5, 0x53, 0xb0, 0x83, 0x6c, 0x9b,
90 0x16, 0x37, 0x6e, 0x23, 0xb7, 0xfb, 0x37, 0xef, 0x53, 0xd8, 0x2b, 0xca,
91 0x2d, 0x6e, 0x53, 0x91, 0xb4, 0x79, 0xf0, 0x1c, 0x5b, 0xa8, 0x5b, 0x02,
92 0x41, 0x00, 0xfe, 0x93, 0x73, 0x43, 0xab, 0xd9, 0x38, 0xbe, 0x6e, 0x54,
93 0x38, 0x2b, 0x01, 0x45, 0x77, 0x18, 0xa6, 0x40, 0x84, 0xa0, 0x7c, 0x74,
94 0x76, 0x6d, 0x9e, 0x1d, 0xa0, 0x36, 0xc6, 0xb2, 0x3d, 0x6f, 0xd4, 0xa8,
95 0xb0, 0xac, 0xfc, 0x8e, 0x3d, 0xfd, 0x81, 0xea, 0x52, 0x0f, 0x1b, 0x08,
96 0x3f, 0xe5, 0x32, 0x9e, 0xa2, 0x77, 0x7d, 0x3b, 0x7f, 0x41, 0x24, 0x74,
97 0xea, 0xce, 0xd2, 0x80, 0xb8, 0x77, 0x02, 0x41, 0x00, 0xbb, 0xaa, 0x9c,
98 0xb2, 0x83, 0x5a, 0x29, 0xae, 0xfb, 0x90, 0x20, 0xcd, 0x39, 0x0d, 0x5a,
99 0x1a, 0x8c, 0xb0, 0xc5, 0xc7, 0x62, 0x7a, 0xf4, 0xa5, 0xd8, 0x80, 0xac,
100 0xd1, 0x5f, 0xb9, 0xea, 0xea, 0xeb, 0x53, 0xae, 0x27, 0x45, 0x07, 0x0d,
101 0xd7, 0x5b, 0x68, 0x55, 0x53, 0x64, 0x83, 0xa0, 0xf0, 0xd7, 0x4a, 0xdf,
102 0x0e, 0x7f, 0xe6, 0xe7, 0xf2, 0xba, 0x30, 0x4e, 0x13, 0x4a, 0x32, 0xf0,
103 0x3b, 0x02, 0x40, 0x6f, 0xce, 0x74, 0x8e, 0x20, 0xf8, 0x6b, 0x0a, 0x7f,
104 0xcc, 0x2f, 0x4a, 0xfb, 0xe8, 0xf5, 0x50, 0x77, 0x1b, 0xd8, 0xe3, 0xdf,
105 0x25, 0x0b, 0x2a, 0x43, 0x8a, 0x41, 0x66, 0x2d, 0x47, 0xf4, 0xe1, 0x9b,
106 0xa5, 0x66, 0xca, 0xe2, 0xb4, 0xda, 0x16, 0xef, 0xaa, 0xe8, 0xd5, 0x47,
107 0x8b, 0x0c, 0xfc, 0xed, 0x89, 0x6c, 0x53, 0x4c, 0x46, 0x08, 0x32, 0xa4,
108 0xff, 0x50, 0x6c, 0xfb, 0x58, 0x9b, 0x2b, 0x02, 0x40, 0x49, 0x49, 0x3a,
109 0x42, 0x38, 0x2b, 0x68, 0xa5, 0xcd, 0xd5, 0x9e, 0x09, 0xa6, 0xa3, 0x01,
110 0x31, 0xe7, 0x09, 0x4d, 0x63, 0x2c, 0xa1, 0x29, 0x92, 0xee, 0x76, 0x69,
111 0x86, 0xa6, 0x24, 0x5b, 0x89, 0xfb, 0xf6, 0x44, 0xc7, 0x4f, 0x1c, 0x8f,
112 0x1a, 0x2f, 0xb7, 0x11, 0xc3, 0x2c, 0x38, 0x7f, 0x0c, 0x2e, 0x77, 0x2d,
113 0x9e, 0x62, 0xf2, 0x50, 0x58, 0x28, 0xbf, 0x9e, 0x6d, 0xc8, 0x07, 0x16,
114 0x6b, 0x02, 0x41, 0x00, 0xe8, 0x72, 0x7b, 0xce, 0x08, 0x27, 0x0a, 0xf5,
115 0x1b, 0xf6, 0x1a, 0xec, 0x66, 0x5b, 0x65, 0x60, 0x7f, 0xcc, 0x5e, 0xcf,
116 0x8e, 0xa6, 0xe4, 0x48, 0xcd, 0x82, 0x87, 0x59, 0xee, 0x9f, 0x22, 0x9e,
117 0x81, 0x32, 0x34, 0x0c, 0x14, 0x7f, 0x89, 0xab, 0xc7, 0xe8, 0xab, 0x0a,
118 0x1f, 0xdd, 0x99, 0x2c, 0xa9, 0xa3, 0xf1, 0x64, 0xa2, 0x1a, 0x93, 0xa6,
119 0x2a, 0xfe, 0x68, 0x42, 0xea, 0x5f, 0xab, 0x93
120 };
121
122 class ImportKeyRequestMatcher
123 : public MatcherInterface<const ImportKeyRequest&> {
124 public:
ImportKeyRequestMatcher(const hidl_vec<KeyParameter> & params,const RSA * rsa)125 explicit ImportKeyRequestMatcher(
126 const hidl_vec<KeyParameter>& params, const RSA *rsa)
127 : params_(params),
128 rsa_(rsa),
129 ec_key_(NULL),
130 symmetric_key_(NULL),
131 symmetric_key_size_(0) {
132 }
133
ImportKeyRequestMatcher(const hidl_vec<KeyParameter> & params,const EC_KEY * ec)134 explicit ImportKeyRequestMatcher(
135 const hidl_vec<KeyParameter>& params, const EC_KEY *ec)
136 : params_(params),
137 rsa_(NULL),
138 ec_key_(ec),
139 symmetric_key_(NULL),
140 symmetric_key_size_(0) {
141 }
142
ImportKeyRequestMatcher(const hidl_vec<KeyParameter> & params,const uint8_t * symmetric_key,size_t symmetric_key_size)143 explicit ImportKeyRequestMatcher(
144 const hidl_vec<KeyParameter>& params,
145 const uint8_t *symmetric_key, size_t symmetric_key_size)
146 : params_(params),
147 rsa_(NULL),
148 ec_key_(NULL),
149 symmetric_key_(symmetric_key),
150 symmetric_key_size_(symmetric_key_size) {
151 }
152
DescribeTo(::std::ostream * os) const153 virtual void DescribeTo(::std::ostream* os) const {
154 *os << "ImportKeyRequest matched expectation";
155 }
156
DescribeNegationTo(::std::ostream * os) const157 virtual void DescribeNegationTo(::std::ostream* os) const {
158 *os << "ImportKeyRequest mis-matched expectation";
159 }
160
MatchAndExplain(const ImportKeyRequest & request,MatchResultListener * listener) const161 virtual bool MatchAndExplain(const ImportKeyRequest& request,
162 MatchResultListener* listener) const {
163 (void)listener;
164
165 if (rsa_ != nullptr) {
166 return this->MatchAndExplainRSA(request);
167 } else if (ec_key_ != nullptr) {
168 return this->MatchAndExplainEC(request);
169 } else {
170 return this->MatchAndExplainSymmetricKey(request);
171 }
172 }
173
174 private:
MatchAndExplainRSA(const ImportKeyRequest & request) const175 bool MatchAndExplainRSA(const ImportKeyRequest& request) const {
176 if (params_.size() != (size_t)request.params().params().size()) {
177 LOG(ERROR) << "test: KeyParameters len mis-match";
178 return false;
179 }
180
181 hidl_vec<KeyParameter> params;
182 if (pb_to_hidl_params(request.params(), ¶ms) != ErrorCode::OK) {
183 LOG(ERROR) << "test: pb_to_hidl_params failed";
184 return false;
185 }
186
187 for (size_t i = 0; i < params_.size(); i++) {
188 if(!(params[i] == params_[i])) {
189 LOG(ERROR) << "test: KeyParameters mis-match";
190 return false;
191 }
192 }
193
194 const BIGNUM *n;
195 const BIGNUM *e;
196 const BIGNUM *d;
197 RSA_get0_key(rsa_, &n, &e, &d);
198
199 if (request.rsa().e() != BN_get_word(e)) {
200 LOG(ERROR) << "e mismatch, expected: "
201 << BN_get_word(e)
202 << " got "
203 << request.rsa().e();
204 return false;
205 }
206
207 unique_ptr<uint8_t[]> d_buf(new uint8_t[BN_num_bytes(n)]);
208 if (!BN_bn2le_padded(d_buf.get(), BN_num_bytes(n), d)) {
209 LOG(ERROR) << "bn2le(d) failed";
210 return false;
211 }
212 // Expect d to be zero-padded to sizeof n if necessary.
213 if (request.rsa().d().size() != BN_num_bytes(n) &&
214 memcmp(request.rsa().d().data(), d_buf.get(),
215 BN_num_bytes(n)) != 0) {
216 LOG(ERROR) << "d-bytes mis-matched";
217 return false;
218 }
219
220 unique_ptr<uint8_t[]> n_buf(new uint8_t[BN_num_bytes(n)]);
221 if (!BN_bn2le_padded(n_buf.get(), BN_num_bytes(n), n)) {
222 LOG(ERROR) << "bn2le(n) failed";
223 return false;
224 }
225 if (request.rsa().n().size() != BN_num_bytes(n) &&
226 memcmp(request.rsa().n().data(), n_buf.get(),
227 BN_num_bytes(n)) != 0) {
228 LOG(ERROR) << "n-bytes mis-matched";
229 return false;
230 }
231
232 return true;
233 }
234
MatchAndExplainEC(const ImportKeyRequest & request) const235 bool MatchAndExplainEC(const ImportKeyRequest& request) const {
236 // Curve parameter.
237 uint32_t expected_curve_id = (uint32_t)-1;
238 const EC_GROUP *group = EC_KEY_get0_group(ec_key_);
239 switch (EC_GROUP_get_curve_name(group)) {
240 case NID_secp224r1:
241 expected_curve_id = (uint32_t)EcCurve::P_224;
242 break;
243 case NID_X9_62_prime256v1:
244 expected_curve_id = (uint32_t)EcCurve::P_256;
245 break;
246 case NID_secp384r1:
247 expected_curve_id = (uint32_t)EcCurve::P_384;
248 break;
249 case NID_secp521r1:
250 expected_curve_id = (uint32_t)EcCurve::P_521;
251 break;
252 }
253
254 if (request.ec().curve_id() != expected_curve_id) {
255 LOG(ERROR) << "Curve-id mismatch, got: "
256 << request.ec().curve_id()
257 << " expected "
258 << expected_curve_id;
259 return false;
260 }
261
262 const BIGNUM *d = EC_KEY_get0_private_key(ec_key_);
263 const EC_POINT *pub_key = EC_KEY_get0_public_key(ec_key_);
264 bssl::UniquePtr<BIGNUM> x(BN_new());
265 bssl::UniquePtr<BIGNUM> y(BN_new());
266
267 if (!EC_POINT_get_affine_coordinates_GFp(
268 EC_KEY_get0_group(ec_key_),
269 pub_key, x.get(), y.get(), NULL)) {
270 LOG(ERROR) << "failed to get public key in affine coordinates";
271 return false;
272 }
273
274 // Private key.
275 const size_t field_size = (EC_GROUP_get_degree(group) + 7) >> 3;
276 unique_ptr<uint8_t[]> d_buf(new uint8_t[field_size]);
277 if (!BN_bn2le_padded(d_buf.get(), field_size, d)) {
278 LOG(ERROR) << "bn2le(d) failed";
279 return false;
280 }
281 if (request.ec().d().size() != field_size ||
282 memcmp(request.ec().d().data(), d_buf.get(), field_size) != 0) {
283 LOG(ERROR) << "d-bytes mis-matched";
284 return false;
285 }
286
287 // Public key.
288 unique_ptr<uint8_t[]> x_buf(new uint8_t[field_size]);
289 if (!BN_bn2le_padded(x_buf.get(), field_size, x.get())) {
290 LOG(ERROR) << "bn2le(x) failed";
291 return false;
292 }
293 if (request.ec().x().size() != field_size ||
294 memcmp(request.ec().x().data(), x_buf.get(), field_size) != 0) {
295 LOG(ERROR) << "x-bytes mis-matched";
296 return false;
297 }
298
299 unique_ptr<uint8_t[]> y_buf(new uint8_t[field_size]);
300 if (!BN_bn2le_padded(y_buf.get(), field_size, y.get())) {
301 LOG(ERROR) << "bn2le(y) failed";
302 return false;
303 }
304 if (request.ec().y().size() != field_size ||
305 memcmp(request.ec().y().data(), y_buf.get(), field_size) != 0) {
306 LOG(ERROR) << "y-bytes mis-matched";
307 return false;
308 }
309
310 return false;
311 }
312
MatchAndExplainSymmetricKey(const ImportKeyRequest & request) const313 bool MatchAndExplainSymmetricKey(const ImportKeyRequest& request) const {
314 if (request.symmetric_key().material().size() != symmetric_key_size_ ||
315 memcmp(request.symmetric_key().material().data(),
316 symmetric_key_, symmetric_key_size_) != 0) {
317 LOG(ERROR) << "symmetric key bytes mis-match";
318 return false;
319 }
320
321 return true;
322 }
323
324 private:
325 const hidl_vec<KeyParameter> params_;
326 const RSA *rsa_;
327 const EC_KEY *ec_key_;
328 const uint8_t *symmetric_key_;
329 size_t symmetric_key_size_;
330 };
331
ImportKeyRequestEq(const hidl_vec<KeyParameter> & params,const RSA * rsa)332 static Matcher<const ImportKeyRequest&> ImportKeyRequestEq(
333 const hidl_vec<KeyParameter>& params, const RSA *rsa) {
334 return MakeMatcher(new ImportKeyRequestMatcher(params, rsa));
335 }
336
TEST(KeymasterHalTest,importKeyPKCS8Success)337 TEST(KeymasterHalTest, importKeyPKCS8Success) {
338 MockKeymaster mockService;
339 ImportKeyResponse response;
340
341 KeyParameter kp;
342 kp.tag = Tag::ALGORITHM;
343 kp.f.algorithm = Algorithm::RSA;
344
345 bssl::UniquePtr<RSA> rsa;
346 bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
347 bssl::UniquePtr<PKCS8_PRIV_KEY_INFO> pkcs8;
348
349 // TODO: Avoid parsing in the validator, use known values instead.
350 rsa.reset(RSA_private_key_from_bytes(TEST_RSA1024_KEY,
351 sizeof(TEST_RSA1024_KEY)));
352 EXPECT_NE(rsa.get(), nullptr);
353 EXPECT_EQ(EVP_PKEY_set1_RSA(pkey.get(), rsa.get()), 1);
354 pkcs8.reset(EVP_PKEY2PKCS8(pkey.get()));
355 EXPECT_NE(pkcs8.get(), nullptr);
356
357 int len = i2d_PKCS8_PRIV_KEY_INFO(pkcs8.get(), NULL);
358 std::unique_ptr<uint8_t[]> der(new uint8_t[len]);
359 uint8_t *tmp = der.get();
360 EXPECT_EQ(i2d_PKCS8_PRIV_KEY_INFO(pkcs8.get(), &tmp), len);
361
362 hidl_vec<uint8_t> der_vec;
363 der_vec.setToExternal(const_cast<uint8_t*>(der.get()), len);
364
365 // response
366 string dummy_blob("Dummy");
367 response.mutable_blob()->set_blob(dummy_blob);
368 nosapp::KeyParameter *noskp =
369 response.mutable_characteristics()->
370 mutable_tee_enforced()->add_params();
371 noskp->set_tag(nosapp::Tag::ALGORITHM);
372 noskp->set_integer((uint32_t)nosapp::Algorithm::RSA);
373
374 EXPECT_CALL(
375 mockService,
376 ImportKey(ImportKeyRequestEq(hidl_vec<KeyParameter>{kp}, rsa.get()), _))
377 .WillOnce(DoAll(SetArgPointee<1>(response), Return(APP_SUCCESS)));
378
379 KeymasterDevice hal{mockService};
380 hal.importKey(
381 hidl_vec<KeyParameter>{kp}, KeyFormat::PKCS8, der_vec,
382 [&](ErrorCode error, hidl_vec<uint8_t> blob,
383 KeyCharacteristics characteristics) {
384 EXPECT_EQ(error, ErrorCode::OK);
385 EXPECT_THAT(blob, Eq(hidl_vec<uint8_t>{'D', 'u', 'm', 'm', 'y'}));;
386
387 EXPECT_EQ(characteristics.hardwareEnforced.size(), 1u);
388 EXPECT_EQ(characteristics.hardwareEnforced[0].tag, Tag::ALGORITHM);
389 EXPECT_EQ(characteristics.hardwareEnforced[0].f.algorithm,
390 Algorithm::RSA);
391 });
392 }
393
394 // TODO: add negative tests for PKCS8 RSA
395 // TODO: add tests for EC
396 // TODO: add tests for AES / HMAC
397