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