Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: net/android/keystore_unittest.cc

Issue 11571059: Add net/android/keystore.h (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: addressing ryan's remarks. Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <openssl/bn.h>
6 #include <openssl/dsa.h>
7 #include <openssl/ecdsa.h>
8 #include <openssl/err.h>
9 #include <openssl/evp.h>
10 #include <openssl/pem.h>
11 #include <openssl/rsa.h>
12 #include <openssl/x509.h>
13
14 #include "base/android/build_info.h"
15 #include "base/android/jni_android.h"
16 #include "base/android/jni_array.h"
17 #include "base/android/scoped_java_ref.h"
18 #include "base/basictypes.h"
19 #include "base/bind.h"
20 #include "base/callback.h"
21 #include "base/compiler_specific.h"
22 #include "base/file_path.h"
23 #include "base/file_util.h"
24 #include "base/memory/scoped_handle.h"
25 #include "base/string_util.h"
26 #include "crypto/openssl_util.h"
27 #include "jni/AndroidKeyStoreTestUtil_jni.h"
28 #include "net/android/keystore.h"
29 #include "net/android/keystore_openssl.h"
30 #include "net/base/test_data_directory.h"
31 #include "testing/gtest/include/gtest/gtest.h"
32
33 // Technical note:
34 //
35 // This source file not only checks that signing with
36 // RawSignDigestWithPrivateKey() works correctly, it also verifies that
37 // the generated signature matches 100% of what OpenSSL generates when
38 // calling RSA_sign(NID_md5_sha1,...), DSA_sign(0, ...) or
39 // ECDSA_sign(0, ...).
40 //
41 // That's crucial to ensure that this function can later be used to
42 // implement client certificate support. More specifically, that it is
43 // possible to create a custom EVP_PKEY that uses
44 // RawSignDigestWithPrivateKey() internally to perform RSA/DSA/ECDSA
45 // signing, as invoked by the OpenSSL code at
46 // openssl/ssl/s3_clnt.c:ssl3_send_client_verify().
47 //
48 // For more details, read the comments in AndroidKeyStore.java.
49 //
50 // Finally, it also checks that using the EVP_PKEY generated with
51 // GetOpenSSLPrivateKeyWrapper() works correctly.
52
53 namespace net {
54 namespace android {
55
56 namespace {
57
58 typedef crypto::ScopedOpenSSL<EVP_PKEY, EVP_PKEY_free> ScopedEVP_PKEY;
59 typedef crypto::ScopedOpenSSL<RSA, RSA_free> ScopedRSA;
60 typedef crypto::ScopedOpenSSL<DSA, DSA_free> ScopedDSA;
61 typedef crypto::ScopedOpenSSL<EC_KEY, EC_KEY_free> ScopedEC_KEY;
62 typedef crypto::ScopedOpenSSL<BIGNUM, BN_free> ScopedBIGNUM;
63
64 typedef crypto::ScopedOpenSSL<
65 PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free>
66 ScopedPKCS8_PRIV_KEY_INFO;
67
68 typedef base::android::ScopedJavaLocalRef<jobject> ScopedJava;
69
70 JNIEnv* InitEnv() {
71 JNIEnv* env = base::android::AttachCurrentThread();
72 static bool inited = false;
73 if (!inited) {
74 RegisterNativesImpl(env);
75 inited = true;
76 }
77 return env;
78 }
79
80 // Returns true if running on an Android version older than 4.2
81 bool IsOnAndroidOlderThan_4_2(void) {
82 const int kAndroid42ApiLevel = 17;
83 int level = base::android::BuildInfo::GetInstance()->sdk_int();
84 return level < kAndroid42ApiLevel;
85 }
86
87 // Implements the callback expected by ERR_print_errors_cb().
88 // used by GetOpenSSLErrorString below.
89 int openssl_print_error_callback(const char* msg, size_t msglen, void* u) {
90 std::string* result = reinterpret_cast<std::string*>(u);
91 result->append(msg, msglen);
92 return 1;
93 }
94
95 // Retrieves the OpenSSL error as a string
96 std::string GetOpenSSLErrorString(void) {
97 std::string result;
98 ERR_print_errors_cb(openssl_print_error_callback, &result);
99 return result;
100 }
101
102 // Resize a string to |size| bytes of data, and return its data buffer
103 // address cast as an 'unsigned char*', as expected by OpenSSL functions.
104 // This is similar to the WriteInto in base/string_util.h, except for
105 // the extra type cast, and the fact that |size| is the size of the
106 // data, not the length of a string + 1.
107 // |str| the target string.
108 // |size| the number of bytes to write into the string.
109 // Return the string's new buffer in memory, as an 'unsigned char*'
110 // pointer.
111 unsigned char* OpenSSLWriteInto(std::string* str, size_t size) {
Ryan Sleevi 2013/02/06 22:48:02 NACK on this. The point of using WriteInto was to
digit1 2013/02/07 17:05:51 I see, I've fixed this, thanks for the clarificati
112 str->reserve(size+1);
113 str->resize(size);
114 return reinterpret_cast<unsigned char*>(&(*str)[0]);
115 }
116
117 // Load a given private key file into an EVP_PKEY.
118 // |filename| is the key file path.
119 // Returns a new EVP_PKEY on success, NULL on failure.
120 EVP_PKEY* ImportPrivateKeyFile(const char* filename) {
121 // Load file in memory.
122 FilePath certs_dir = GetTestCertsDirectory();
123 FilePath file_path = certs_dir.AppendASCII(filename);
124 ScopedStdioHandle handle(
125 file_util::OpenFile(file_path, "rb"));
126 if (!handle.get()) {
127 LOG(ERROR) << "Could not open private key file: " << filename;
128 return NULL;
129 }
130 // Assume it is PEM_encoded. Load it as an EVP_PKEY.
131 EVP_PKEY* pkey = PEM_read_PrivateKey(handle.get(), NULL, NULL, NULL);
132 if (!pkey) {
133 LOG(ERROR) << "Could not load public key file: " << filename
134 << ", " << GetOpenSSLErrorString();
135 return NULL;
136 }
137 return pkey;
138 }
139
140 // Convert a private key into its PKCS#8 encoded representation.
141 // |pkey| is the EVP_PKEY handle for the private key.
142 // |pkcs8| will receive the PKCS#8 bytes.
143 // Returns true on success, false otherwise.
144 bool GetPrivateKeyPkcs8Bytes(const ScopedEVP_PKEY& pkey,
145 std::string* pkcs8) {
146 // Convert to PKCS#8 object.
147 ScopedPKCS8_PRIV_KEY_INFO p8_info(EVP_PKEY2PKCS8(pkey.get()));
148 if (!p8_info.get()) {
149 LOG(ERROR) << "Can't get PKCS#8 private key from EVP_PKEY: "
150 << GetOpenSSLErrorString();
151 return false;
152 }
153
154 // Then convert it
155 int len = i2d_PKCS8_PRIV_KEY_INFO(p8_info.get(), NULL);
156 unsigned char* p = OpenSSLWriteInto(pkcs8, static_cast<size_t>(len));
157 i2d_PKCS8_PRIV_KEY_INFO(p8_info.get(), &p);
158 return true;
159 }
160
161 bool ImportPrivateKeyFileAsPkcs8(const char* filename,
162 std::string* pkcs8) {
163 ScopedEVP_PKEY pkey(ImportPrivateKeyFile(filename));
164 if (!pkey.get())
165 return false;
166 return GetPrivateKeyPkcs8Bytes(pkey, pkcs8);
167 }
168
169 // Same as ImportPrivateKey, but for public ones.
170 EVP_PKEY* ImportPublicKeyFile(const char* filename) {
171 // Load file as PEM data.
172 FilePath certs_dir = GetTestCertsDirectory();
173 FilePath file_path = certs_dir.AppendASCII(filename);
174 ScopedStdioHandle handle(file_util::OpenFile(file_path, "rb"));
175 if (!handle.get()) {
176 LOG(ERROR) << "Could not open public key file: " << filename;
177 return NULL;
178 }
179 EVP_PKEY* pkey = PEM_read_PUBKEY(handle.get(), NULL, NULL, NULL);
180 if (!pkey) {
181 LOG(ERROR) << "Could not load public key file: " << filename
182 << ", " << GetOpenSSLErrorString();
183 return NULL;
184 }
185 return pkey;
186 }
187
188 // Retrieve a JNI local ref from encoded PKCS#8 data.
189 ScopedJava GetPKCS8PrivateKeyJava(PrivateKeyType key_type,
190 const std::string& pkcs8_key) {
191 JNIEnv* env = InitEnv();
192 base::android::ScopedJavaLocalRef<jbyteArray> bytes(
193 base::android::ToJavaByteArray(
194 env,
195 reinterpret_cast<const uint8*>(pkcs8_key.data()),
196 pkcs8_key.size()));
197
198 ScopedJava key(
199 Java_AndroidKeyStoreTestUtil_createPrivateKeyFromPKCS8(
200 env, key_type, bytes.obj()));
201
202 return key;
203 }
204
205 const char kTestRsaKeyFile[] = "android-test-key-rsa.pem";
206
207 // The RSA test hash must be 36 bytes exactly.
208 const char kTestRsaHash[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
209
210 // Retrieve a JNI local ref for our test RSA key.
211 ScopedJava GetRSATestKeyJava() {
212 std::string key;
213 if (!ImportPrivateKeyFileAsPkcs8(kTestRsaKeyFile, &key))
214 return ScopedJava();
215 return GetPKCS8PrivateKeyJava(PRIVATE_KEY_TYPE_RSA, key);
216 }
217
218 const char kTestDsaKeyFile[] = "android-test-key-dsa.pem";
219 const char kTestDsaPublicKeyFile[] = "android-test-key-dsa-public.pem";
220
221 // The DSA test hash must be 20 bytes exactly.
222 const char kTestDsaHash[] = "0123456789ABCDEFGHIJ";
223
224 // Retrieve a JNI local ref for our test DSA key.
225 ScopedJava GetDSATestKeyJava() {
226 std::string key;
227 if (!ImportPrivateKeyFileAsPkcs8(kTestDsaKeyFile, &key))
228 return ScopedJava();
229 return GetPKCS8PrivateKeyJava(PRIVATE_KEY_TYPE_DSA, key);
230 }
231
232 // Call this function to verify that one message signed with our
233 // test DSA private key is correct. Since DSA signing introduces
234 // random elements in the signature, it is not possible to compare
235 // signature bits directly. However, one can use the public key
236 // to do the check.
237 bool VerifyTestDSASignature(const base::StringPiece& message,
238 const base::StringPiece& signature) {
239 ScopedEVP_PKEY pkey(ImportPublicKeyFile(kTestDsaPublicKeyFile));
240 if (!pkey.get())
241 return false;
242
243 ScopedDSA pub_key(EVP_PKEY_get1_DSA(pkey.get()));
244 if (!pub_key.get()) {
245 LOG(ERROR) << "Could not get DSA public key: "
246 << GetOpenSSLErrorString();
247 return false;
248 }
249
250 const unsigned char* digest =
251 reinterpret_cast<const unsigned char*>(message.data());
252 int digest_len = static_cast<int>(message.size());
253 const unsigned char* sigbuf =
254 reinterpret_cast<const unsigned char*>(signature.data());
255 int siglen = static_cast<int>(signature.size());
256
257 int ret = DSA_verify(
258 0, digest, digest_len, sigbuf, siglen, pub_key.get());
259 if (ret != 1) {
260 LOG(ERROR) << "DSA_verify() failed: " << GetOpenSSLErrorString();
261 return false;
262 }
263 return true;
264 }
265
266 const char kTestEcdsaKeyFile[] = "android-test-key-ecdsa.pem";
267 const char kTestEcdsaPublicKeyFile[] = "android-test-key-ecdsa-public.pem";
268
269 // The test hash for ECDSA keys must be 20 bytes exactly.
270 const char kTestEcdsaHash[] = "0123456789ABCDEFGHIJ";
271
272 // Retrieve a JNI local ref for our test ECDSA key.
273 ScopedJava GetECDSATestKeyJava() {
274 std::string key;
275 if (!ImportPrivateKeyFileAsPkcs8(kTestEcdsaKeyFile, &key))
276 return ScopedJava();
277 return GetPKCS8PrivateKeyJava(PRIVATE_KEY_TYPE_ECDSA, key);
278 }
279
280 // Call this function to verify that one message signed with our
281 // test DSA private key is correct. Since DSA signing introduces
282 // random elements in the signature, it is not possible to compare
283 // signature bits directly. However, one can use the public key
284 // to do the check.
285 bool VerifyTestECDSASignature(const base::StringPiece& message,
286 const base::StringPiece& signature) {
287 ScopedEVP_PKEY pkey(ImportPublicKeyFile(kTestEcdsaPublicKeyFile));
288 if (!pkey.get())
289 return false;
290 ScopedEC_KEY pub_key(EVP_PKEY_get1_EC_KEY(pkey.get()));
291 if (!pub_key.get()) {
292 LOG(ERROR) << "Could not get ECDSA public key: "
293 << GetOpenSSLErrorString();
294 return false;
295 }
296
297 const unsigned char* digest =
298 reinterpret_cast<const unsigned char*>(message.data());
299 int digest_len = static_cast<int>(message.size());
300 const unsigned char* sigbuf =
301 reinterpret_cast<const unsigned char*>(signature.data());
302 int siglen = static_cast<int>(signature.size());
303
304 int ret = ECDSA_verify(
305 0, digest, digest_len, sigbuf, siglen, pub_key.get());
306 if (ret != 1) {
307 LOG(ERROR) << "ECDSA_verify() failed: " << GetOpenSSLErrorString();
308 return false;
309 }
310 return true;
311 }
312
313 // Sign a message with OpenSSL, return the result as a string.
314 // |message| is the message to be signed.
315 // |openssl_key| is an OpenSSL EVP_PKEY to use.
316 // |result| receives the result.
317 // Returns true on success, false otherwise.
318 bool SignWithOpenSSL(const base::StringPiece& message,
319 EVP_PKEY* openssl_key,
320 std::string* result) {
321 const unsigned char* digest =
322 reinterpret_cast<const unsigned char*>(message.data());
323 unsigned int digest_len = static_cast<unsigned int>(message.size());
324 std::string signature;
325 size_t signature_size;
326 size_t max_signature_size;
327 int key_type = EVP_PKEY_id(openssl_key);
328 switch (key_type) {
329 case EVP_PKEY_RSA:
330 {
331 ScopedRSA rsa(EVP_PKEY_get1_RSA(openssl_key));
332 if (!rsa.get()) {
333 LOG(ERROR) << "Could not get RSA from EVP_PKEY: "
334 << GetOpenSSLErrorString();
335 return false;
336 }
337 // With RSA, the signature will always be RSA_size() bytes.
338 max_signature_size = static_cast<size_t>(RSA_size(rsa.get()));
339 unsigned char* p = OpenSSLWriteInto(&signature,
340 max_signature_size);
341 unsigned int p_len = 0;
342 int ret = RSA_sign(
343 NID_md5_sha1, digest, digest_len, p, &p_len, rsa.get());
344 if (ret != 1) {
345 LOG(ERROR) << "RSA_sign() failed: " << GetOpenSSLErrorString();
346 return false;
347 }
348 signature_size = static_cast<size_t>(p_len);
349 }
350 break;
351 case EVP_PKEY_DSA:
352 {
353 ScopedDSA dsa(EVP_PKEY_get1_DSA(openssl_key));
354 if (!dsa.get()) {
355 LOG(ERROR) << "Could not get DSA from EVP_PKEY: "
356 << GetOpenSSLErrorString();
357 return false;
358 }
359 // Note, the actual signature can be smaller than DSA_size()
360 max_signature_size = static_cast<size_t>(DSA_size(dsa.get()));
361 unsigned char* p = OpenSSLWriteInto(&signature,
362 max_signature_size);
363 unsigned int p_len = 0;
364 // Note: first parameter is ignored by function.
365 int ret = DSA_sign(0, digest, digest_len, p, &p_len, dsa.get());
366 if (ret != 1) {
367 LOG(ERROR) << "DSA_sign() failed: " << GetOpenSSLErrorString();
368 return false;
369 }
370 signature_size = static_cast<size_t>(p_len);
371 }
372 break;
373 case EVP_PKEY_EC:
374 {
375 ScopedEC_KEY ecdsa(EVP_PKEY_get1_EC_KEY(openssl_key));
376 if (!ecdsa.get()) {
377 LOG(ERROR) << "Could not get EC_KEY from EVP_PKEY: "
378 << GetOpenSSLErrorString();
379 return false;
380 }
381 // Note, the actual signature can be smaller than ECDSA_size()
382 max_signature_size = ECDSA_size(ecdsa.get());
383 unsigned char* p = OpenSSLWriteInto(&signature,
384 max_signature_size);
385 unsigned int p_len = 0;
386 // Note: first parameter is ignored by function.
387 int ret = ECDSA_sign(
388 0, digest, digest_len, p, &p_len, ecdsa.get());
389 if (ret != 1) {
390 LOG(ERROR) << "ECDSA_sign() fialed: " << GetOpenSSLErrorString();
391 return false;
392 }
393 signature_size = static_cast<size_t>(p_len);
394 }
395 break;
396 default:
397 LOG(WARNING) << "Invalid OpenSSL key type: " << key_type;
398 return false;
399 }
400
401 if (signature_size == 0) {
402 LOG(ERROR) << "Signature is empty!";
403 return false;
404 }
405 if (signature_size > max_signature_size) {
406 LOG(ERROR) << "Signature size mismatch, actual " << signature_size
407 << ", expected <= " << max_signature_size;
408 return false;
409 }
410 signature.resize(signature_size);
411 result->swap(signature);
412 return true;
413 }
414
415 // Check that a generated signature for a given message matches
416 // OpenSSL output byte-by-byte.
417 // |message| is the input message.
418 // |signature| is the generated signature for the message.
419 // |openssl_key| is a raw EVP_PKEY for the same private key than the
420 // one which was used to generate the signature.
421 // Returns true on success, false otherwise.
422 bool CompareSignatureWithOpenSSL(const base::StringPiece& message,
423 const base::StringPiece& signature,
424 EVP_PKEY* openssl_key) {
425 std::string openssl_signature;
426 SignWithOpenSSL(message, openssl_key, &openssl_signature);
427
428 if (signature.size() != openssl_signature.size()) {
429 LOG(ERROR) << "Signature size mismatch, actual "
430 << signature.size() << ", expected "
431 << openssl_signature.size();
432 return false;
433 }
434 for (size_t n = 0; n < signature.size(); ++n) {
435 if (openssl_signature[n] != signature[n]) {
436 LOG(ERROR) << "Signature byte mismatch at index " << n
437 << "actual " << signature[n] << ", expected "
438 << openssl_signature[n];
439 return false;
440 }
441 }
442 return true;
443 }
444
445 // Sign a message with our platform API.
446 //
447 // |android_key| is a JNI reference to the platform PrivateKey object.
448 // |openssl_key| is a pointer to an OpenSSL key object for the exact
449 // same key content.
450 // |message| is a message.
451 // |result| will receive the result.
452 void DoKeySigning(jobject android_key,
453 EVP_PKEY* openssl_key,
454 const base::StringPiece& message,
455 std::string* result) {
456 // First, get the platform signature.
457 std::vector<uint8> android_signature;
458 ASSERT_TRUE(
459 RawSignDigestWithPrivateKey(android_key,
460 message,
461 &android_signature));
462
463 result->assign(
464 reinterpret_cast<const char*>(&android_signature[0]),
465 android_signature.size());
466 }
467
468 // Sign a message with our OpenSSL EVP_PKEY wrapper around platform
469 // APIS.
470 //
471 // |android_key| is a JNI reference to the platform PrivateKey object.
472 // |openssl_key| is a pointer to an OpenSSL key object for the exact
473 // same key content.
474 // |message| is a message.
475 // |result| will receive the result.
476 void DoKeySigningWithWrapper(EVP_PKEY* wrapper_key,
477 EVP_PKEY* openssl_key,
478 const base::StringPiece& message,
479 std::string* result) {
480 // First, get the platform signature.
481 std::string wrapper_signature;
482 SignWithOpenSSL(message, wrapper_key, &wrapper_signature);
483 ASSERT_NE(0U, wrapper_signature.size());
484
485 result->assign(
486 reinterpret_cast<const char*>(&wrapper_signature[0]),
487 wrapper_signature.size());
488 }
489
490 } // namespace
491
492 TEST(AndroidKeyStore,GetRSAKeyModulus) {
493 crypto::OpenSSLErrStackTracer err_trace(FROM_HERE);
494 InitEnv();
495
496 // Load the test RSA key.
497 ScopedEVP_PKEY pkey(ImportPrivateKeyFile(kTestRsaKeyFile));
498 ASSERT_TRUE(pkey.get());
499
500 // Convert it to encoded PKCS#8 bytes.
501 std::string pkcs8_data;
502 ASSERT_TRUE(GetPrivateKeyPkcs8Bytes(pkey, &pkcs8_data));
503
504 // Create platform PrivateKey object from it.
505 ScopedJava key_java = GetPKCS8PrivateKeyJava(PRIVATE_KEY_TYPE_RSA,
506 pkcs8_data);
507 ASSERT_FALSE(key_java.is_null());
508
509 // Retrieve the corresponding modulus through JNI
510 std::vector<uint8> modulus_java;
511 ASSERT_TRUE(GetRSAKeyModulus(key_java.obj(), &modulus_java));
512
513 // Create an OpenSSL BIGNUM from it.
514 ScopedBIGNUM bn(
515 BN_bin2bn(
516 reinterpret_cast<const unsigned char*>(&modulus_java[0]),
517 static_cast<int>(modulus_java.size()),
518 NULL));
519 ASSERT_TRUE(bn.get());
520
521 // Compare it to the one in the RSA key, they must be identical.
522 ScopedRSA rsa(EVP_PKEY_get1_RSA(pkey.get()));
523 ASSERT_TRUE(rsa.get()) << GetOpenSSLErrorString();
524
525 ASSERT_EQ(0, BN_cmp(bn.get(), rsa.get()->n));
526 }
527
528 TEST(AndroidKeyStore,GetDSAKeyParamQ) {
529 crypto::OpenSSLErrStackTracer err_trace(FROM_HERE);
530 InitEnv();
531
532 // Load the test DSA key.
533 ScopedEVP_PKEY pkey(ImportPrivateKeyFile(kTestDsaKeyFile));
534 ASSERT_TRUE(pkey.get());
535
536 // Convert it to encoded PKCS#8 bytes.
537 std::string pkcs8_data;
538 ASSERT_TRUE(GetPrivateKeyPkcs8Bytes(pkey, &pkcs8_data));
539
540 // Create platform PrivateKey object from it.
541 ScopedJava key_java = GetPKCS8PrivateKeyJava(PRIVATE_KEY_TYPE_DSA,
542 pkcs8_data);
543 ASSERT_FALSE(key_java.is_null());
544
545 // Retrieve the corresponding Q parameter through JNI
546 std::vector<uint8> q_java;
547 ASSERT_TRUE(GetDSAKeyParamQ(key_java.obj(), &q_java));
548
549 // Create an OpenSSL BIGNUM from it.
550 ScopedBIGNUM bn(
551 BN_bin2bn(
552 reinterpret_cast<const unsigned char*>(&q_java[0]),
553 static_cast<int>(q_java.size()),
554 NULL));
555 ASSERT_TRUE(bn.get());
556
557 // Compare it to the one in the RSA key, they must be identical.
558 ScopedDSA dsa(EVP_PKEY_get1_DSA(pkey.get()));
559 ASSERT_TRUE(dsa.get()) << GetOpenSSLErrorString();
560
561 ASSERT_EQ(0, BN_cmp(bn.get(), dsa.get()->q));
562 }
563
564 TEST(AndroidKeyStore,GetPrivateKeyTypeRSA) {
565 crypto::OpenSSLErrStackTracer err_trace(FROM_HERE);
566
567 ScopedJava rsa_key = GetRSATestKeyJava();
568 ASSERT_FALSE(rsa_key.is_null());
569 EXPECT_EQ(PRIVATE_KEY_TYPE_RSA,
570 GetPrivateKeyType(rsa_key.obj()));
571 }
572
573 TEST(AndroidKeyStore,SignWithPrivateKeyRSA) {
574 ScopedJava rsa_key = GetRSATestKeyJava();
575 ASSERT_FALSE(rsa_key.is_null());
576
577 if (IsOnAndroidOlderThan_4_2()) {
578 LOG(INFO) << "This test can't run on Android < 4.2";
579 return;
580 }
581
582 ScopedEVP_PKEY openssl_key(ImportPrivateKeyFile(kTestRsaKeyFile));
583 ASSERT_TRUE(openssl_key.get());
584
585 std::string message = kTestRsaHash;
586 ASSERT_EQ(36U, message.size());
587
588 std::string signature;
589 DoKeySigning(rsa_key.obj(), openssl_key.get(), message, &signature);
590 ASSERT_TRUE(
591 CompareSignatureWithOpenSSL(message, signature, openssl_key.get()));
592 // All good.
593 }
594
595 TEST(AndroidKeyStore,SignWithWrapperKeyRSA) {
596 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
597
598 ScopedJava rsa_key = GetRSATestKeyJava();
599 ASSERT_FALSE(rsa_key.is_null());
600
601 ScopedEVP_PKEY wrapper_key(GetOpenSSLPrivateKeyWrapper(rsa_key.obj()));
602 ASSERT_TRUE(wrapper_key.get() != NULL);
603
604 ScopedEVP_PKEY openssl_key(ImportPrivateKeyFile(kTestRsaKeyFile));
605 ASSERT_TRUE(openssl_key.get());
606
607 // Check that RSA_size() works properly on the wrapper key.
608 EXPECT_EQ(EVP_PKEY_size(openssl_key.get()),
609 EVP_PKEY_size(wrapper_key.get()));
610
611 // Message size must be 36 for RSA_sign(NID_md5_sha1,...) to return
612 // without an error.
613 std::string message = kTestRsaHash;
614 ASSERT_EQ(36U, message.size());
615
616 std::string signature;
617 DoKeySigningWithWrapper(wrapper_key.get(),
618 openssl_key.get(),
619 message,
620 &signature);
621 ASSERT_TRUE(
622 CompareSignatureWithOpenSSL(message, signature, openssl_key.get()));
623 }
624
625 TEST(AndroidKeyStore,GetPrivateKeyTypeDSA) {
626 crypto::OpenSSLErrStackTracer err_trace(FROM_HERE);
627
628 ScopedJava dsa_key = GetDSATestKeyJava();
629 ASSERT_FALSE(dsa_key.is_null());
630 EXPECT_EQ(PRIVATE_KEY_TYPE_DSA,
631 GetPrivateKeyType(dsa_key.obj()));
632 }
633
634 TEST(AndroidKeyStore,SignWithPrivateKeyDSA) {
635 ScopedJava dsa_key = GetDSATestKeyJava();
636 ASSERT_FALSE(dsa_key.is_null());
637
638 ScopedEVP_PKEY openssl_key(ImportPrivateKeyFile(kTestDsaKeyFile));
639 ASSERT_TRUE(openssl_key.get());
640
641 std::string message = kTestDsaHash;
642 ASSERT_EQ(20U, message.size());
643
644 std::string signature;
645 DoKeySigning(dsa_key.obj(), openssl_key.get(), message, &signature);
646 ASSERT_TRUE(VerifyTestDSASignature(message, signature));
647 }
648
649 TEST(AndroidKeyStore,SignWithWrapperKeyDSA) {
650 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
651
652 ScopedJava dsa_key = GetDSATestKeyJava();
653 ASSERT_FALSE(dsa_key.is_null());
654
655 ScopedEVP_PKEY wrapper_key(
656 GetOpenSSLPrivateKeyWrapper(dsa_key.obj()));
657 ASSERT_TRUE(wrapper_key.get());
658
659 ScopedEVP_PKEY openssl_key(ImportPrivateKeyFile(kTestDsaKeyFile));
660 ASSERT_TRUE(openssl_key.get());
661
662 // Check that DSA_size() works correctly on the wrapper.
663 EXPECT_EQ(EVP_PKEY_size(openssl_key.get()),
664 EVP_PKEY_size(wrapper_key.get()));
665
666 std::string message = kTestDsaHash;
667 std::string signature;
668 DoKeySigningWithWrapper(wrapper_key.get(),
669 openssl_key.get(),
670 message,
671 &signature);
672 ASSERT_TRUE(VerifyTestDSASignature(message, signature));
673 }
674
675 TEST(AndroidKeyStore,GetPrivateKeyTypeECDSA) {
676 crypto::OpenSSLErrStackTracer err_trace(FROM_HERE);
677
678 ScopedJava ecdsa_key = GetECDSATestKeyJava();
679 ASSERT_FALSE(ecdsa_key.is_null());
680 EXPECT_EQ(PRIVATE_KEY_TYPE_ECDSA,
681 GetPrivateKeyType(ecdsa_key.obj()));
682 }
683
684 TEST(AndroidKeyStore,SignWithPrivateKeyECDSA) {
685 ScopedJava ecdsa_key = GetECDSATestKeyJava();
686 ASSERT_FALSE(ecdsa_key.is_null());
687
688 ScopedEVP_PKEY openssl_key(ImportPrivateKeyFile(kTestEcdsaKeyFile));
689 ASSERT_TRUE(openssl_key.get());
690
691 std::string message = kTestEcdsaHash;
692 std::string signature;
693 DoKeySigning(ecdsa_key.obj(), openssl_key.get(), message, &signature);
694 ASSERT_TRUE(VerifyTestECDSASignature(message, signature));
695 }
696
697 TEST(AndroidKeyStore, SignWithWrapperKeyECDSA) {
698 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
699
700 ScopedJava ecdsa_key = GetECDSATestKeyJava();
701 ASSERT_FALSE(ecdsa_key.is_null());
702
703 ScopedEVP_PKEY wrapper_key(
704 GetOpenSSLPrivateKeyWrapper(ecdsa_key.obj()));
705 ASSERT_TRUE(wrapper_key.get());
706
707 ScopedEVP_PKEY openssl_key(ImportPrivateKeyFile(kTestEcdsaKeyFile));
708 ASSERT_TRUE(openssl_key.get());
709
710 // Check that ECDSA size works correctly on the wrapper.
711 EXPECT_EQ(EVP_PKEY_size(openssl_key.get()),
712 EVP_PKEY_size(wrapper_key.get()));
713
714 std::string message = kTestEcdsaHash;
715 std::string signature;
716 DoKeySigningWithWrapper(wrapper_key.get(),
717 openssl_key.get(),
718 message,
719 &signature);
720 ASSERT_TRUE(VerifyTestECDSASignature(message, signature));
721 }
722
723 } // namespace android
724 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698