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