diff --git a/crypto/pem/pem_test.cc b/crypto/pem/pem_test.cc index aed523cd81..1e94ba6d34 100644 --- a/crypto/pem/pem_test.cc +++ b/crypto/pem/pem_test.cc @@ -16,10 +16,22 @@ #include +#include #include #include #include +#include +#include +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, @@ -43,3 +55,140 @@ TEST(PEMTest, NoRC4) { EXPECT_EQ(ERR_LIB_PEM, ERR_GET_LIB(err)); EXPECT_EQ(PEM_R_UNSUPPORTED_ENCRYPTION, ERR_GET_REASON(err)); } + +struct TmpFileDeleter { + void operator()(FILE *f) const { fclose(f); } +}; + +using TmpFilePtr = std::unique_ptr; + +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 + TmpFilePtr pem_file(tmpfile()); + 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)); + +} diff --git a/crypto/x509/x509_test.cc b/crypto/x509/x509_test.cc index 1eb15b52d2..910fc63022 100644 --- a/crypto/x509/x509_test.cc +++ b/crypto/x509/x509_test.cc @@ -5711,6 +5711,34 @@ TEST(X509Test, SetSerialNumberChecksASN1StringType) { EXPECT_EQ(-1, val); } +TEST(X509Test, SetSerialNumberCheckEndian) { + bssl::UniquePtr root = CertFromPEM(kRootCAPEM); + ASSERT_TRUE(root); + + // Numbers for testing + std::vector nums = { + 0x0000000000000001LL, + 0x0000000000000100LL, + 0x0000000000010000LL, + 0x0000000001000000LL, + 0x0000000100000000LL, + 0x0000010000000000LL, + 0x0001000000000000LL, + -2LL}; + + for(int64_t num: nums) { + bssl::UniquePtr serial(ASN1_INTEGER_new()); + ASSERT_TRUE(serial); + // Set serial number for cert + ASSERT_TRUE(ASN1_INTEGER_set_int64(serial.get(), num)); + ASSERT_TRUE(X509_set_serialNumber(root.get(), serial.get())); + // Get serial number for cert + int64_t val; + ASSERT_TRUE(ASN1_INTEGER_get_int64(&val, X509_get0_serialNumber(root.get()))); + EXPECT_EQ(num, val); + } +} + TEST(X509Test, Policy) { bssl::UniquePtr oid1( OBJ_txt2obj("1.2.840.113554.4.1.72585.2.1", /*dont_search_names=*/1));