@@ -13637,5 +13637,160 @@ 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
+ TEST(SSLTest, SSLPrivateKeyMethod) {
13695
+ {
13696
+ bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(TLS_method()));
13697
+ bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(TLS_method()));
13698
+
13699
+ bssl::UniquePtr<X509> ecdsa_cert(GetECDSATestCertificate());
13700
+ bssl::UniquePtr<CRYPTO_BUFFER> ecdsa_leaf =
13701
+ x509_to_buffer(ecdsa_cert.get());
13702
+ std::vector<CRYPTO_BUFFER *> chain = {
13703
+ ecdsa_leaf.get(),
13704
+ };
13705
+
13706
+ // Index should be have been set to default, 0, but no key loaded
13707
+ EXPECT_EQ(server_ctx->cert->cert_private_key_idx, SSL_PKEY_RSA);
13708
+ EXPECT_EQ(
13709
+ server_ctx->cert->cert_private_keys[SSL_PKEY_RSA].privatekey.get(),
13710
+ nullptr);
13711
+ EXPECT_EQ(server_ctx->cert->key_method, nullptr);
13712
+
13713
+
13714
+ // Load a certificate chain containg the leaf but set private key method
13715
+ ASSERT_TRUE(SSL_CTX_set_chain_and_key(server_ctx.get(), &chain[0],
13716
+ chain.size(), nullptr,
13717
+ &test_ecc_private_key_method));
13718
+
13719
+ // Should be initiall zero
13720
+ ASSERT_EQ(test_ecc_privkey_calls, (size_t)0);
13721
+
13722
+ // Index must be ECC key now, but key_method must be set.
13723
+ ASSERT_EQ(server_ctx->cert->cert_private_key_idx, SSL_PKEY_ECC);
13724
+ ASSERT_EQ(server_ctx->cert->key_method, &test_ecc_private_key_method);
13725
+
13726
+ bssl::UniquePtr<SSL> client, server;
13727
+ ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
13728
+ server_ctx.get(), ClientConfig(),
13729
+ false));
13730
+
13731
+ ASSERT_TRUE(CompleteHandshakes(client.get(), server.get()));
13732
+
13733
+ ASSERT_EQ(test_ecc_privkey_calls, (size_t)1);
13734
+
13735
+ // Check the internal slot index to verify that the correct slot was used
13736
+ // during the handshake.
13737
+ ASSERT_EQ(server->config->cert->cert_private_key_idx, SSL_PKEY_ECC);
13738
+ ASSERT_EQ(server->config->cert->key_method, &test_ecc_private_key_method);
13739
+ }
13740
+
13741
+ {
13742
+ size_t current_invoke_count = test_ecc_privkey_calls;
13743
+
13744
+ bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(TLS_method()));
13745
+ bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(TLS_method()));
13746
+
13747
+ // Index should be have been set to default, 0, but no key loaded
13748
+ EXPECT_EQ(server_ctx->cert->cert_private_key_idx, SSL_PKEY_RSA);
13749
+ EXPECT_EQ(
13750
+ server_ctx->cert->cert_private_keys[SSL_PKEY_RSA].privatekey.get(),
13751
+ nullptr);
13752
+ EXPECT_EQ(server_ctx->cert->key_method, nullptr);
13753
+
13754
+ bssl::UniquePtr<X509> ed_cert(GetED25519TestCertificate());
13755
+ bssl::UniquePtr<EVP_PKEY> ed_key(GetED25519TestKey());
13756
+ bssl::UniquePtr<CRYPTO_BUFFER> ed_leaf = x509_to_buffer(ed_cert.get());
13757
+ std::vector<CRYPTO_BUFFER *> ed_chain = {
13758
+ ed_leaf.get(),
13759
+ };
13760
+
13761
+ // Load a certificate chain containg the leaf but set private key method
13762
+ ASSERT_TRUE(SSL_CTX_set_chain_and_key(server_ctx.get(), &ed_chain[0],
13763
+ ed_chain.size(), ed_key.get(),
13764
+ nullptr));
13765
+
13766
+ // Index must be ECC key now, but key_method must not be set.
13767
+ ASSERT_EQ(server_ctx->cert->cert_private_key_idx, SSL_PKEY_ED25519);
13768
+ ASSERT_EQ(server_ctx->cert->key_method, nullptr);
13769
+
13770
+ std::vector<uint16_t> sigalgs = {SSL_SIGN_ED25519};
13771
+
13772
+ ASSERT_TRUE(SSL_CTX_set_signing_algorithm_prefs(
13773
+ client_ctx.get(), sigalgs.data(), sigalgs.size()));
13774
+ ASSERT_TRUE(SSL_CTX_set_verify_algorithm_prefs(
13775
+ client_ctx.get(), sigalgs.data(), sigalgs.size()));
13776
+
13777
+ bssl::UniquePtr<SSL> client, server;
13778
+ ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
13779
+ server_ctx.get(), ClientConfig(),
13780
+ false));
13781
+
13782
+ ASSERT_TRUE(CompleteHandshakes(client.get(), server.get()));
13783
+
13784
+ // This should still be the same, as we didn't use the private key method
13785
+ // functionality, so it shouldn't have incremented.
13786
+ ASSERT_EQ(test_ecc_privkey_calls, current_invoke_count);
13787
+
13788
+ // Check the internal slot index to verify that the correct slot was used
13789
+ // during the handshake and that key_method was not set.
13790
+ ASSERT_EQ(server->config->cert->cert_private_key_idx, SSL_PKEY_ED25519);
13791
+ ASSERT_EQ(server->config->cert->key_method, nullptr);
13792
+ }
13793
+ }
13794
+
13640
13795
} // namespace
13641
13796
BSSL_NAMESPACE_END
0 commit comments