// Copyright (c) 2018, Google Inc. // SPDX-License-Identifier: ISC #include #include #include #include #include #include #include #include #include #include "../test/test_util.h" const char* SECRET = "test"; static int pem_password_callback(char *buf, int size, int rwflag, void *userdata) { char* data = (char *)userdata; if(size <= 0) { return 0; } return (int)BUF_strlcpy(buf, data, size); } // Test that implausible ciphers, notably an IV-less RC4, aren't allowed in PEM. // This is a regression test for https://github.com/openssl/openssl/issues/6347, // though our fix differs from upstream. TEST(PEMTest, NoRC4) { static const char kPEM[] = "-----BEGIN RSA PUBLIC KEY-----\n" "Proc-Type: 4,ENCRYPTED\n" "DEK-Info: RC4 -\n" "extra-info\n" "router-signature\n" "\n" "Z1w=\n" "-----END RSA PUBLIC KEY-----\n"; bssl::UniquePtr bio(BIO_new_mem_buf(kPEM, sizeof(kPEM) - 1)); ASSERT_TRUE(bio); bssl::UniquePtr rsa(PEM_read_bio_RSAPublicKey( bio.get(), nullptr, nullptr, const_cast("password"))); EXPECT_FALSE(rsa); EXPECT_TRUE( ErrorEquals(ERR_get_error(), ERR_LIB_PEM, PEM_R_UNSUPPORTED_ENCRYPTION)); } static void* d2i_ASN1_INTEGER_void(void ** out, const unsigned char **inp, long len) { return d2i_ASN1_INTEGER((ASN1_INTEGER **)out, inp, len); } static int i2d_ASN1_INTEGER_void(const void *a, unsigned char **out) { return i2d_ASN1_INTEGER((ASN1_INTEGER *)a, out); } TEST(PEMTest, WriteReadASN1IntegerPem) { #if defined(OPENSSL_ANDROID) // On Android, when running from an APK, |tmpfile| does not work. See // b/36991167#comment8. GTEST_SKIP(); #endif // Numbers for testing std::vector nums = { 0x00000001L, 0x00000100L, 0x00010000L, 0x01000000L, -2L}; for(long original_value: nums) { // Create an ASN1_INTEGER with value bssl::UniquePtr asn1_int(ASN1_INTEGER_new()); ASSERT_TRUE(asn1_int); ASSERT_TRUE(ASN1_INTEGER_set(asn1_int.get(), original_value)); // Create buffer for writing TempFILE pem_file = createTempFILE(); ASSERT_TRUE(pem_file); // Write the ASN1_INTEGER to a PEM-formatted string ASSERT_TRUE(PEM_ASN1_write(i2d_ASN1_INTEGER_void, "ASN1 INTEGER", pem_file.get(), asn1_int.get(), nullptr, nullptr, 0, nullptr, nullptr)); rewind(pem_file.get()); // Read the ASN1_INTEGER back from the PEM-formatted string bssl::UniquePtr read_integer((ASN1_INTEGER *)PEM_ASN1_read( d2i_ASN1_INTEGER_void, "ASN1 INTEGER", pem_file.get(), nullptr, nullptr, nullptr)); ASSERT_TRUE(read_integer); // Check if the read ASN1_INTEGER has the same value as the original long read_value = ASN1_INTEGER_get(read_integer.get()); ASSERT_EQ(original_value, read_value); } } const char* kPemRsaPrivateKey = "-----BEGIN ENCRYPTED PRIVATE KEY-----\n" "MIHsMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAhz3vU103jx3wICCAAw\n" "DAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEA6vMhRLgHZuHFa+eiecYCgEgZDB\n" "E8EOzjGQuu4D0TVAjOa3Peb9/MzQz3t09m5pvNBFKrEl96gefpZdni5qQk34ukj9\n" "/kryXymP72m4Ch7vbmew08x5x9L69BpfsQLF1yyvAJVtEZ0a1Zqcn5veuoH2WtJT\n" "ZTrZtc5Eb+tAjMVzRXPZ80cUwCbbpb9KHUX8spwtG10I1VxJ18X31FVpGORdr0A=\n" "-----END ENCRYPTED PRIVATE KEY-----"; TEST(PEMTest, ReadPrivateKeyPem) { bssl::UniquePtr read_bio(BIO_new_mem_buf(kPemRsaPrivateKey, BUF_strnlen(kPemRsaPrivateKey, 2048)) ); ASSERT_TRUE(read_bio); bssl::UniquePtr ec_key(PEM_read_bio_ECPrivateKey(read_bio.get(), nullptr, pem_password_callback, (void*)SECRET)); ASSERT_TRUE(ec_key); const EC_GROUP* p256 = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); ASSERT_EQ(p256, EC_KEY_get0_group(ec_key.get())); } TEST(PEMTest, WriteReadRSAPem) { bssl::UniquePtr rsa(RSA_new()); ASSERT_TRUE(rsa); bssl::UniquePtr bn(BN_new()); ASSERT_TRUE(bn); BN_set_u64(bn.get(), RSA_F4); #if defined(BORINGSSL_FIPS) ASSERT_TRUE(RSA_generate_key_fips(rsa.get(), 2048, nullptr)); #else ASSERT_TRUE(RSA_generate_key_ex(rsa.get(), 2048, bn.get(), nullptr)); #endif bssl::UniquePtr write_bio(BIO_new(BIO_s_mem())); ASSERT_TRUE(write_bio); const EVP_CIPHER* cipher = EVP_get_cipherbynid(NID_aes_256_cbc); ASSERT_TRUE(cipher); ASSERT_TRUE(PEM_write_bio_RSAPrivateKey(write_bio.get(), rsa.get(), cipher, (unsigned char*)SECRET, (int)BUF_strnlen(SECRET, 256), nullptr, nullptr)); const uint8_t* content; size_t content_len; BIO_mem_contents(write_bio.get(), &content, &content_len); bssl::UniquePtr read_bio(BIO_new_mem_buf(content, content_len) ); ASSERT_TRUE(read_bio); bssl::UniquePtr rsa_read(PEM_read_bio_RSAPrivateKey(read_bio.get(), nullptr, pem_password_callback, (void*)SECRET)); ASSERT_TRUE(rsa_read); ASSERT_EQ(0, BN_cmp(RSA_get0_n(rsa.get()), RSA_get0_n(rsa_read.get()))); } TEST(PEMTest, WriteReadECPem) { bssl::UniquePtr ec_key(EC_KEY_new()); ASSERT_TRUE(ec_key); bssl::UniquePtr ec_group(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)); ASSERT_TRUE(ec_group); ASSERT_TRUE(EC_KEY_set_group(ec_key.get(), ec_group.get())); #if defined(BORINGSSL_FIPS) ASSERT_TRUE(EC_KEY_generate_key_fips(ec_key.get())); #else ASSERT_TRUE(EC_KEY_generate_key(ec_key.get())); #endif bssl::UniquePtr write_bio(BIO_new(BIO_s_mem())); ASSERT_TRUE(write_bio); const EVP_CIPHER* cipher = EVP_get_cipherbynid(NID_aes_256_cbc); ASSERT_TRUE(cipher); ASSERT_TRUE(PEM_write_bio_ECPrivateKey(write_bio.get(), ec_key.get(), cipher, nullptr, 0, pem_password_callback, (void*)SECRET)); const uint8_t* content; size_t content_len; BIO_mem_contents(write_bio.get(), &content, &content_len); bssl::UniquePtr read_bio(BIO_new_mem_buf(content, content_len) ); ASSERT_TRUE(read_bio); bssl::UniquePtr ec_key_read(PEM_read_bio_ECPrivateKey(read_bio.get(), nullptr, pem_password_callback, (void*)"test")); ASSERT_TRUE(ec_key_read); const BIGNUM* orig_priv_key = EC_KEY_get0_private_key(ec_key.get()); const BIGNUM* read_priv_key = EC_KEY_get0_private_key(ec_key_read.get()); ASSERT_EQ(0, BN_cmp(orig_priv_key, read_priv_key)); } const char *kPemECPARAMETERS = "-----BEGIN EC PARAMETERS-----\n" "BgUrgQQAIw==\n" "-----END EC PARAMETERS-----\n"; const char *kPemExplictECPARAMETERS = "-----BEGIN EC PARAMETERS-----\n" "MIH3AgEBMCwGByqGSM49AQECIQD/////AAAAAQAAAAAAAAAAAAAAAP//////////" "/////zBbBCD/////AAAAAQAAAAAAAAAAAAAAAP///////////////AQgWsY12Ko6" "k+ez671VdpiGvGUdBrDMU7D2O848PifSYEsDFQDEnTYIhucEk2pmeOETnSa3gZ9+" "kARBBGsX0fLhLEJH+Lzm5WOkQPJ3A32BLeszoPShOUXYmMKWT+NC4v4af5uO5+tK" "fA+eFivOM1drMV7Oy7ZAaDe/UfUCIQD/////AAAAAP//////////vOb6racXnoTz" "ucrC/GMlUQIBAQ==\n" "-----END EC PARAMETERS-----\n"; TEST(PEMTest, WriteReadECPKPem) { // Check named curve can be outputted to a PEM file. bssl::UniquePtr group(EC_GROUP_new_by_curve_name(NID_secp521r1)); ASSERT_TRUE(group); bssl::UniquePtr write_bio(BIO_new(BIO_s_mem())); ASSERT_TRUE(write_bio); ASSERT_TRUE(PEM_write_bio_ECPKParameters(write_bio.get(), group.get())); const uint8_t *content; size_t content_len; BIO_mem_contents(write_bio.get(), &content, &content_len); EXPECT_EQ(Bytes(content, content_len), Bytes(kPemECPARAMETERS)); // Check named curve of a PEM file can be parsed. bssl::UniquePtr read_bio( BIO_new_mem_buf(kPemECPARAMETERS, strlen(kPemECPARAMETERS))); bssl::UniquePtr read_group( PEM_read_bio_ECPKParameters(read_bio.get(), nullptr, nullptr, nullptr)); ASSERT_TRUE(read_group); ASSERT_EQ(EC_GROUP_cmp(EC_group_p521(), read_group.get(), nullptr), 0); // Make an arbitrary curve which is identical to P-256. static const uint8_t kP[] = { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }; static const uint8_t kA[] = { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, }; static const uint8_t kB[] = { 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, 0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b, }; bssl::UniquePtr p(BN_bin2bn(kP, sizeof(kP), nullptr)), a(BN_bin2bn(kA, sizeof(kA), nullptr)), b(BN_bin2bn(kB, sizeof(kB), nullptr)); ASSERT_TRUE(p && a && b); // Writing custom curves, even if the parameters are identical to a named // curve, will result in an error bssl::UniquePtr custom_group( EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), nullptr)); write_bio.reset(BIO_new(BIO_s_mem())); ASSERT_TRUE(write_bio); EXPECT_FALSE( PEM_write_bio_ECPKParameters(write_bio.get(), custom_group.get())); // Check that explicitly-encoded versions of namedCurves can be correctly // parsed from a PEM file. read_bio.reset(BIO_new_mem_buf( kPemExplictECPARAMETERS, strlen(kPemExplictECPARAMETERS))); read_group.reset( PEM_read_bio_ECPKParameters(read_bio.get(), nullptr, nullptr, nullptr)); ASSERT_TRUE(read_group); ASSERT_EQ(EC_GROUP_cmp(EC_group_p256(), read_group.get(), nullptr), 0); } TEST(ParametersTest, PEMReadwrite) { // Test |PEM_read/write_bio_Parameters| with |EC_KEY|. bssl::UniquePtr ec_key(EC_KEY_new()); ASSERT_TRUE(ec_key); bssl::UniquePtr ec_group(EC_GROUP_new_by_curve_name(NID_secp384r1)); ASSERT_TRUE(ec_group); ASSERT_TRUE(EC_KEY_set_group(ec_key.get(), ec_group.get())); ASSERT_TRUE(EC_KEY_generate_key(ec_key.get())); bssl::UniquePtr write_bio(BIO_new(BIO_s_mem())); bssl::UniquePtr pkey(EVP_PKEY_new()); ASSERT_TRUE(EVP_PKEY_set1_EC_KEY(pkey.get(), ec_key.get())); EXPECT_TRUE(PEM_write_bio_Parameters(write_bio.get(), pkey.get())); const uint8_t *content; size_t content_len; BIO_mem_contents(write_bio.get(), &content, &content_len); bssl::UniquePtr read_bio(BIO_new_mem_buf(content, content_len)); ASSERT_TRUE(read_bio); bssl::UniquePtr pkey_read( PEM_read_bio_Parameters(read_bio.get(), nullptr)); ASSERT_TRUE(pkey_read); EC_KEY *pkey_eckey = EVP_PKEY_get0_EC_KEY(pkey.get()); ASSERT_TRUE(pkey_eckey); const EC_GROUP *orig_params = EC_KEY_get0_group(pkey_eckey); ASSERT_TRUE(orig_params); const EC_GROUP *read_params = EC_KEY_get0_group(pkey_eckey); ASSERT_TRUE(read_params); ASSERT_EQ(0, EC_GROUP_cmp(orig_params, read_params, nullptr)); // Test |PEM_read/write_bio_Parameters| with |DH|. bssl::UniquePtr p(BN_get_rfc3526_prime_1536(nullptr)); ASSERT_TRUE(p); bssl::UniquePtr g(BN_new()); ASSERT_TRUE(g); ASSERT_TRUE(BN_set_u64(g.get(), 2)); bssl::UniquePtr dh(DH_new()); ASSERT_TRUE(dh); ASSERT_TRUE(DH_set0_pqg(dh.get(), p.release(), nullptr, g.release())); write_bio.reset(BIO_new(BIO_s_mem())); pkey.reset(EVP_PKEY_new()); ASSERT_TRUE(EVP_PKEY_set1_DH(pkey.get(), dh.get())); EXPECT_TRUE(PEM_write_bio_Parameters(write_bio.get(), pkey.get())); BIO_mem_contents(write_bio.get(), &content, &content_len); read_bio.reset(BIO_new_mem_buf(content, content_len)); ASSERT_TRUE(read_bio); pkey_read.reset(PEM_read_bio_Parameters(read_bio.get(), nullptr)); ASSERT_TRUE(pkey_read); DH *pkey_dh = EVP_PKEY_get0_DH(pkey.get()); ASSERT_TRUE(pkey_dh); EXPECT_EQ(0, BN_cmp(DH_get0_p(pkey_dh), DH_get0_p(dh.get()))); EXPECT_EQ(0, BN_cmp(DH_get0_g(pkey_dh), DH_get0_g(dh.get()))); // Test |PEM_read/write_bio_Parameters| with |DSA|. bssl::UniquePtr dsa(DSA_new()); ASSERT_TRUE(dsa); uint8_t seed[20]; ASSERT_TRUE(RAND_bytes(seed, sizeof(seed))); ASSERT_TRUE(DSA_generate_parameters_ex(dsa.get(), 512, seed, sizeof(seed), nullptr, nullptr, nullptr)); ASSERT_TRUE(DSA_generate_key(dsa.get())); write_bio.reset(BIO_new(BIO_s_mem())); pkey.reset(EVP_PKEY_new()); ASSERT_TRUE(EVP_PKEY_set1_DSA(pkey.get(), dsa.get())); EXPECT_TRUE(PEM_write_bio_Parameters(write_bio.get(), pkey.get())); BIO_mem_contents(write_bio.get(), &content, &content_len); read_bio.reset(BIO_new_mem_buf(content, content_len)); ASSERT_TRUE(read_bio); pkey_read.reset(PEM_read_bio_Parameters(read_bio.get(), nullptr)); ASSERT_TRUE(pkey_read); DSA *pkey_dsa = EVP_PKEY_get0_DSA(pkey.get()); EXPECT_EQ(0, BN_cmp(DSA_get0_p(pkey_dsa), DSA_get0_p(dsa.get()))); EXPECT_EQ(0, BN_cmp(DSA_get0_g(pkey_dsa), DSA_get0_g(dsa.get()))); } const char *kRubyPemDHPARAMETERS = "-----BEGIN DH PARAMETERS-----\n" "MIIBCAKCAQEA7E6kBrYiyvmKAMzQ7i8WvwVk9Y/+f8S7sCTN712KkK3cqd1jhJDY" "JbrYeNV3kUIKhPxWHhObHKpD1R84UpL+s2b55+iMd6GmL7OYmNIT/FccKhTcveab" "VBmZT86BZKYyf45hUF9FOuUM9xPzuK3Vd8oJQvfYMCd7LPC0taAEljQLR4Edf8E6" "YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3" "1bNveX5wInh5GDx1FGhKBZ+s1H+aedudCm7sCgRwv8lKWYGiHzObSma8A86KG+MD" "7Lo5JquQ3DlBodj3IDyPrxIv96lvRPFtAwIBAg==\n" "-----END DH PARAMETERS-----\n"; TEST(ParametersTest, RubyDHFile) { bssl::UniquePtr read_bio( BIO_new_mem_buf(kRubyPemDHPARAMETERS, strlen(kRubyPemDHPARAMETERS))); ASSERT_TRUE(read_bio); bssl::UniquePtr pkey_read( PEM_read_bio_Parameters(read_bio.get(), nullptr)); ASSERT_TRUE(pkey_read); bssl::UniquePtr dh(EVP_PKEY_get1_DH(pkey_read.get())); EXPECT_TRUE(dh); EXPECT_EQ(DH_num_bits(dh.get()), 2048u); } TEST(PEMTest, WriteReadTraditionalPem) { // Test |PEM_write_bio_PrivateKey_traditional| with |EC_KEY|. bssl::UniquePtr ec_key(EC_KEY_new()); ASSERT_TRUE(ec_key); bssl::UniquePtr ec_group(EC_GROUP_new_by_curve_name(NID_secp256k1)); ASSERT_TRUE(ec_group); ASSERT_TRUE(EC_KEY_set_group(ec_key.get(), ec_group.get())); ASSERT_TRUE(EC_KEY_generate_key(ec_key.get())); bssl::UniquePtr write_bio(BIO_new(BIO_s_mem())); bssl::UniquePtr pkey(EVP_PKEY_new()); ASSERT_TRUE(EVP_PKEY_set1_EC_KEY(pkey.get(), ec_key.get())); EXPECT_TRUE(PEM_write_bio_PrivateKey_traditional( write_bio.get(), pkey.get(), nullptr, nullptr, 0, nullptr, nullptr)); const uint8_t *content; size_t content_len; BIO_mem_contents(write_bio.get(), &content, &content_len); bssl::UniquePtr read_bio(BIO_new_mem_buf(content, content_len)); ASSERT_TRUE(read_bio); bssl::UniquePtr pkey_read( PEM_read_bio_PrivateKey(read_bio.get(), nullptr, nullptr, nullptr)); ASSERT_TRUE(pkey_read); EC_KEY *pkey_eckey = EVP_PKEY_get0_EC_KEY(pkey.get()); ASSERT_TRUE(pkey_eckey); const BIGNUM *orig_priv_key = EC_KEY_get0_private_key(ec_key.get()); const BIGNUM *read_priv_key = EC_KEY_get0_private_key(pkey_eckey); ASSERT_EQ(0, BN_cmp(orig_priv_key, read_priv_key)); // Test |PEM_write_bio_PrivateKey_traditional| with |RSA|. bssl::UniquePtr e(BN_new()); ASSERT_TRUE(e); ASSERT_TRUE(BN_set_word(e.get(), RSA_F4)); bssl::UniquePtr rsa(RSA_new()); ASSERT_TRUE(rsa); ASSERT_TRUE(RSA_generate_key_ex(rsa.get(), 1024, e.get(), nullptr)); write_bio.reset(BIO_new(BIO_s_mem())); pkey.reset(EVP_PKEY_new()); ASSERT_TRUE(EVP_PKEY_set1_RSA(pkey.get(), rsa.get())); EXPECT_TRUE(PEM_write_bio_PrivateKey_traditional( write_bio.get(), pkey.get(), nullptr, nullptr, 0, nullptr, nullptr)); BIO_mem_contents(write_bio.get(), &content, &content_len); read_bio.reset(BIO_new_mem_buf(content, content_len)); ASSERT_TRUE(read_bio); pkey_read.reset( PEM_read_bio_PrivateKey(read_bio.get(), nullptr, nullptr, nullptr)); ASSERT_TRUE(pkey_read); RSA *pkey_rsa = EVP_PKEY_get0_RSA(pkey.get()); ASSERT_TRUE(pkey_rsa); EXPECT_EQ(0, BN_cmp(RSA_get0_d(pkey_rsa), RSA_get0_d(rsa.get()))); EXPECT_EQ(0, BN_cmp(RSA_get0_d(pkey_rsa), RSA_get0_d(rsa.get()))); // Test |PEM_write_bio_PrivateKey_traditional| with |DSA|. bssl::UniquePtr dsa(DSA_new()); ASSERT_TRUE(dsa); uint8_t seed[20]; ASSERT_TRUE(RAND_bytes(seed, sizeof(seed))); ASSERT_TRUE(DSA_generate_parameters_ex(dsa.get(), 512, seed, sizeof(seed), nullptr, nullptr, nullptr)); ASSERT_TRUE(DSA_generate_key(dsa.get())); write_bio.reset(BIO_new(BIO_s_mem())); pkey.reset(EVP_PKEY_new()); ASSERT_TRUE(EVP_PKEY_set1_DSA(pkey.get(), dsa.get())); EXPECT_TRUE(PEM_write_bio_PrivateKey_traditional( write_bio.get(), pkey.get(), nullptr, nullptr, 0, nullptr, nullptr)); BIO_mem_contents(write_bio.get(), &content, &content_len); read_bio.reset(BIO_new_mem_buf(content, content_len)); ASSERT_TRUE(read_bio); pkey_read.reset( PEM_read_bio_PrivateKey(read_bio.get(), nullptr, nullptr, nullptr)); ASSERT_TRUE(pkey_read); DSA *pkey_dsa = EVP_PKEY_get0_DSA(pkey.get()); EXPECT_EQ(0, BN_cmp(DSA_get0_priv_key(pkey_dsa), DSA_get0_priv_key(dsa.get()))); // Test |PEM_write_bio_PrivateKey_traditional| with |DH|. This should fail, // since it's not supported by the API. bssl::UniquePtr p(BN_get_rfc3526_prime_1536(nullptr)); ASSERT_TRUE(p); bssl::UniquePtr g(BN_new()); ASSERT_TRUE(g); ASSERT_TRUE(BN_set_u64(g.get(), 2)); bssl::UniquePtr dh(DH_new()); ASSERT_TRUE(dh); ASSERT_TRUE(DH_set0_pqg(dh.get(), p.release(), nullptr, g.release())); write_bio.reset(BIO_new(BIO_s_mem())); pkey.reset(EVP_PKEY_new()); ASSERT_TRUE(EVP_PKEY_set1_DH(pkey.get(), dh.get())); EXPECT_FALSE(PEM_write_bio_PrivateKey_traditional( write_bio.get(), pkey.get(), nullptr, nullptr, 0, nullptr, nullptr)); } TEST(PEMTest, WriteReadECPemEmptyPassword) { bssl::UniquePtr ec_key(EC_KEY_new()); ASSERT_TRUE(ec_key); bssl::UniquePtr ec_group(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)); ASSERT_TRUE(ec_group); ASSERT_TRUE(EC_KEY_set_group(ec_key.get(), ec_group.get())); #if defined(BORINGSSL_FIPS) ASSERT_TRUE(EC_KEY_generate_key_fips(ec_key.get())); #else ASSERT_TRUE(EC_KEY_generate_key(ec_key.get())); #endif bssl::UniquePtr write_bio(BIO_new(BIO_s_mem())); ASSERT_TRUE(write_bio); const EVP_CIPHER* cipher = EVP_get_cipherbynid(NID_aes_256_cbc); ASSERT_TRUE(cipher); ASSERT_TRUE(PEM_write_bio_ECPrivateKey(write_bio.get(), ec_key.get(), cipher, nullptr, 0, pem_password_callback, (void*)"")); const uint8_t* content = nullptr; size_t content_len = 0; BIO_mem_contents(write_bio.get(), &content, &content_len); bssl::UniquePtr read_bio(BIO_new_mem_buf(content, content_len) ); ASSERT_TRUE(read_bio); bssl::UniquePtr ec_key_read(PEM_read_bio_ECPrivateKey(read_bio.get(), nullptr, pem_password_callback, (void*)"")); ASSERT_TRUE(ec_key_read); const BIGNUM* orig_priv_key = EC_KEY_get0_private_key(ec_key.get()); const BIGNUM* read_priv_key = EC_KEY_get0_private_key(ec_key_read.get()); ASSERT_EQ(0, BN_cmp(orig_priv_key, read_priv_key)); } TEST(PEMTest, WriteReadPKCS8DerEmptyPassword) { bssl::UniquePtr ec_key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); ASSERT_TRUE(ec_key); ASSERT_TRUE(EC_KEY_generate_key(ec_key.get())); bssl::UniquePtr pkey(EVP_PKEY_new()); ASSERT_TRUE(pkey); ASSERT_TRUE(EVP_PKEY_set1_EC_KEY(pkey.get(), ec_key.get())); bssl::UniquePtr write_bio(BIO_new(BIO_s_mem())); ASSERT_TRUE(write_bio); ASSERT_TRUE(i2d_PKCS8PrivateKey_bio(write_bio.get(), pkey.get(), EVP_aes_256_cbc(), nullptr, 0, pem_password_callback, (void*)"")); const uint8_t* content = nullptr; size_t content_len = 0; BIO_mem_contents(write_bio.get(), &content, &content_len); bssl::UniquePtr read_bio(BIO_new_mem_buf(content, content_len) ); ASSERT_TRUE(read_bio); bssl::UniquePtr pkey_read(d2i_PKCS8PrivateKey_bio(read_bio.get(), nullptr, pem_password_callback, (void*)"")); ASSERT_TRUE(pkey_read); const EC_KEY* read_ec = EVP_PKEY_get0_EC_KEY(pkey_read.get()); ASSERT_TRUE(read_ec); ASSERT_EQ(0, BN_cmp(EC_KEY_get0_private_key(ec_key.get()), EC_KEY_get0_private_key(read_ec))); }