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