@@ -13637,5 +13637,164 @@ TEST(SSLTest, MixContextAndConnection) {
13637
13637
EXPECT_FALSE(SSL_get_privatekey(ssl2.get()));
13638
13638
}
13639
13639
13640
+ static size_t test_ecc_privkey_calls = 0;
13641
+
13642
+ static enum ssl_private_key_result_t test_ecc_privkey_complete(SSL *ssl,
13643
+ uint8_t *out,
13644
+ size_t *out_len,
13645
+ size_t max_out) {
13646
+ test_ecc_privkey_calls += 1;
13647
+ return ssl_private_key_success;
13648
+ }
13649
+
13650
+ static enum ssl_private_key_result_t test_ecc_privkey_sign(
13651
+ SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
13652
+ uint16_t signature_algorithm, const uint8_t *in, size_t in_len) {
13653
+ bssl::UniquePtr<EVP_PKEY> pkey(GetECDSATestKey());
13654
+
13655
+ if (EVP_PKEY_id(pkey.get()) !=
13656
+ SSL_get_signature_algorithm_key_type(signature_algorithm)) {
13657
+ return ssl_private_key_failure;
13658
+ }
13659
+
13660
+ const EVP_MD *md = SSL_get_signature_algorithm_digest(signature_algorithm);
13661
+ bssl::ScopedEVP_MD_CTX ctx;
13662
+ EVP_PKEY_CTX *pctx = nullptr;
13663
+ if (!EVP_DigestSignInit(ctx.get(), &pctx, md, nullptr,
13664
+ pkey.get())) {
13665
+ return ssl_private_key_failure;
13666
+ }
13667
+
13668
+ size_t len = 0;
13669
+ if (!EVP_DigestSign(ctx.get(), nullptr, &len, in, in_len) || len > max_out) {
13670
+ return ssl_private_key_failure;
13671
+ }
13672
+
13673
+ *out_len = max_out;
13674
+
13675
+ if (!EVP_DigestSign(ctx.get(), out, out_len, in, in_len)) {
13676
+ return ssl_private_key_failure;
13677
+ }
13678
+
13679
+ return test_ecc_privkey_complete(ssl, out, out_len, max_out);
13680
+ }
13681
+
13682
+ static enum ssl_private_key_result_t test_ecc_privkey_decrypt(
13683
+ SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, const uint8_t *in,
13684
+ size_t in_len) {
13685
+ return ssl_private_key_failure;
13686
+ }
13687
+
13688
+ static const SSL_PRIVATE_KEY_METHOD test_ecc_private_key_method = {
13689
+ test_ecc_privkey_sign,
13690
+ test_ecc_privkey_decrypt,
13691
+ test_ecc_privkey_complete,
13692
+ };
13693
+
13694
+ static bssl::UniquePtr<CRYPTO_BUFFER> x509_to_buffer(X509 *x509) {
13695
+ uint8_t *buf = NULL;
13696
+ int cert_len = i2d_X509(x509, &buf);
13697
+ if (cert_len <= 0) {
13698
+ return 0;
13699
+ }
13700
+
13701
+ UniquePtr<CRYPTO_BUFFER> buffer(CRYPTO_BUFFER_new(buf, cert_len, NULL));
13702
+ OPENSSL_free(buf);
13703
+
13704
+ return buffer;
13705
+ }
13706
+
13707
+ TEST(SSLTest, SSLPrivateKeyMethod) {
13708
+ {
13709
+ bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(TLS_method()));
13710
+ bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(TLS_method()));
13711
+
13712
+ bssl::UniquePtr<X509> ecdsa_cert(GetECDSATestCertificate());
13713
+ bssl::UniquePtr<CRYPTO_BUFFER> ecdsa_leaf =
13714
+ x509_to_buffer(ecdsa_cert.get());
13715
+ std::vector<CRYPTO_BUFFER *> chain = {
13716
+ ecdsa_leaf.get(),
13717
+ };
13718
+
13719
+ // Index should be have been set to default, 0, but no key loaded
13720
+ EXPECT_EQ(server_ctx->cert->cert_private_key_idx, SSL_PKEY_RSA);
13721
+ EXPECT_EQ(
13722
+ server_ctx->cert->cert_private_keys[SSL_PKEY_RSA].privatekey.get(),
13723
+ nullptr);
13724
+ EXPECT_EQ(server_ctx->cert->key_method, nullptr);
13725
+
13726
+
13727
+ // Load a certificate chain containg the leaf but set private key method
13728
+ ASSERT_TRUE(SSL_CTX_set_chain_and_key(server_ctx.get(), &chain[0],
13729
+ chain.size(), nullptr,
13730
+ &test_ecc_private_key_method));
13731
+
13732
+ // Index must be ECC key now, but key_method must be set.
13733
+ ASSERT_EQ(server_ctx->cert->cert_private_key_idx, SSL_PKEY_ECC);
13734
+ ASSERT_EQ(server_ctx->cert->key_method, &test_ecc_private_key_method);
13735
+
13736
+ bssl::UniquePtr<SSL> client, server;
13737
+ ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
13738
+ server_ctx.get(), ClientConfig(),
13739
+ false));
13740
+
13741
+ ASSERT_TRUE(CompleteHandshakes(client.get(), server.get()));
13742
+
13743
+ // Check the internal slot index to verify that the correct slot was used
13744
+ // during the handshake.
13745
+ ASSERT_EQ(server->config->cert->cert_private_key_idx, SSL_PKEY_ECC);
13746
+ ASSERT_EQ(server->config->cert->key_method, &test_ecc_private_key_method);
13747
+ }
13748
+
13749
+ {
13750
+ bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(TLS_method()));
13751
+ bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(TLS_method()));
13752
+
13753
+ // Index should be have been set to default, 0, but no key loaded
13754
+ EXPECT_EQ(server_ctx->cert->cert_private_key_idx, SSL_PKEY_RSA);
13755
+ EXPECT_EQ(
13756
+ server_ctx->cert->cert_private_keys[SSL_PKEY_RSA].privatekey.get(),
13757
+ nullptr);
13758
+ EXPECT_EQ(server_ctx->cert->key_method, nullptr);
13759
+
13760
+ bssl::UniquePtr<X509> ed_cert(GetED25519TestCertificate());
13761
+ bssl::UniquePtr<EVP_PKEY> ed_key(GetED25519TestKey());
13762
+ bssl::UniquePtr<CRYPTO_BUFFER> ed_leaf = x509_to_buffer(ed_cert.get());
13763
+ std::vector<CRYPTO_BUFFER *> ed_chain = {
13764
+ ed_leaf.get(),
13765
+ };
13766
+
13767
+ // Load a certificate chain containg the leaf but set private key method
13768
+ ASSERT_TRUE(SSL_CTX_set_chain_and_key(server_ctx.get(), &ed_chain[0],
13769
+ ed_chain.size(), ed_key.get(),
13770
+ nullptr));
13771
+
13772
+ // Index must be ECC key now, but key_method must be set.
13773
+ ASSERT_EQ(server_ctx->cert->cert_private_key_idx, SSL_PKEY_ED25519);
13774
+ ASSERT_EQ(server_ctx->cert->key_method, nullptr);
13775
+
13776
+ std::vector<uint16_t> sigalgs = {SSL_SIGN_ED25519};
13777
+
13778
+ ASSERT_TRUE(SSL_CTX_set_signing_algorithm_prefs(
13779
+ client_ctx.get(), sigalgs.data(), sigalgs.size()));
13780
+ ASSERT_TRUE(SSL_CTX_set_verify_algorithm_prefs(
13781
+ client_ctx.get(), sigalgs.data(), sigalgs.size()));
13782
+
13783
+ bssl::UniquePtr<SSL> client, server;
13784
+ ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
13785
+ server_ctx.get(), ClientConfig(),
13786
+ false));
13787
+
13788
+ ASSERT_TRUE(CompleteHandshakes(client.get(), server.get()));
13789
+
13790
+ ASSERT_EQ(test_ecc_privkey_calls, (size_t)1);
13791
+
13792
+ // Check the internal slot index to verify that the correct slot was used
13793
+ // during the handshake.
13794
+ ASSERT_EQ(server->config->cert->cert_private_key_idx, SSL_PKEY_ED25519);
13795
+ ASSERT_EQ(server->config->cert->key_method, nullptr);
13796
+ }
13797
+ }
13798
+
13640
13799
} // namespace
13641
13800
BSSL_NAMESPACE_END
0 commit comments