diff --git a/crypto/cipher_extra/cipher_extra.c b/crypto/cipher_extra/cipher_extra.c index 6ef657dcb4..f9a7e10cdb 100644 --- a/crypto/cipher_extra/cipher_extra.c +++ b/crypto/cipher_extra/cipher_extra.c @@ -103,7 +103,10 @@ static const struct { } kCipherAliases[] = { {"3des", "des-ede3-cbc"}, {"aes256", "aes-256-cbc"}, - {"aes128", "aes-128-cbc"} + {"aes128", "aes-128-cbc"}, + {"id-aes128-gcm", "aes-128-gcm"}, + {"id-aes192-gcm", "aes-192-gcm"}, + {"id-aes256-gcm", "aes-256-gcm"} }; const EVP_CIPHER *EVP_get_cipherbynid(int nid) { diff --git a/include/openssl/pkcs8.h b/include/openssl/pkcs8.h index e93724135b..a6fd1c4cfe 100644 --- a/include/openssl/pkcs8.h +++ b/include/openssl/pkcs8.h @@ -290,4 +290,9 @@ BSSL_NAMESPACE_END #define PKCS8_R_UNSUPPORTED_OPTIONS 132 #define PKCS8_R_AMBIGUOUS_FRIENDLY_NAME 133 +// PKCS12_R_MAC_VERIFY_FAILURE is an error code defined for +// compatability. It points to our equivalent for this OpenSSL error, +// |PKCS8_R_INCORRECT_PASSWORD| +#define PKCS12_R_MAC_VERIFY_FAILURE PKCS8_R_INCORRECT_PASSWORD + #endif // OPENSSL_HEADER_PKCS8_H diff --git a/include/openssl/rsa.h b/include/openssl/rsa.h index 894a008e5d..ba7f6fa2d3 100644 --- a/include/openssl/rsa.h +++ b/include/openssl/rsa.h @@ -935,4 +935,8 @@ BSSL_NAMESPACE_END #define RSA_R_BLOCK_TYPE_IS_NOT_02 148 #define RSA_R_MISMATCHED_SIGNATURE 248 +// RSA_F_RSA_OSSL_PRIVATE_ENCRYPT is a function code defined +// for compatibility. AWS-LC does not support function codes +#define RSA_F_RSA_OSSL_PRIVATE_ENCRYPT 0 + #endif // OPENSSL_HEADER_RSA_H diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index eccdf28a96..37e03d2042 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -4898,6 +4898,18 @@ OPENSSL_EXPORT int SSL_get_shutdown(const SSL *ssl); // peer. If not applicable, it returns zero. OPENSSL_EXPORT uint16_t SSL_get_peer_signature_algorithm(const SSL *ssl); +// SSL_get_peer_signature_nid sets |psig_nid| to the NID of the digest used by +// the peer to sign their TLS messages. Returns one on success and zero on +// failure. +OPENSSL_EXPORT int SSL_get_peer_signature_nid(const SSL *ssl, int *psig_nid); + +// SSL_get_peer_signature_type_nid sets |psigtype_nid| to the signature type +// used by the peer to sign their TLS messages. The signature type is the NID of +// the public key type used for signing. Returns one on success and zero on +// failure. +OPENSSL_EXPORT int SSL_get_peer_signature_type_nid(const SSL *ssl, + int *psigtype_nid); + // SSL_get_client_random writes up to |max_out| bytes of the most recent // handshake's client_random to |out| and returns the number of bytes written. // If |max_out| is zero, it returns the size of the client_random. diff --git a/ssl/ssl_lib.cc b/ssl/ssl_lib.cc index 13d0050ca9..4e07eac7df 100644 --- a/ssl/ssl_lib.cc +++ b/ssl/ssl_lib.cc @@ -3047,6 +3047,41 @@ uint16_t SSL_get_peer_signature_algorithm(const SSL *ssl) { return session->peer_signature_algorithm; } +int SSL_get_peer_signature_nid(const SSL *ssl, int *psig_nid) { + GUARD_PTR(psig_nid); + + uint16_t sig_alg = SSL_get_peer_signature_algorithm(ssl); + if (sig_alg == 0) { + return 0; + } + + const EVP_MD *digest_type = SSL_get_signature_algorithm_digest(sig_alg); + if (digest_type == NULL) { + return 0; + } + + *psig_nid = EVP_MD_nid(digest_type); + return 1; +} + +int SSL_get_peer_signature_type_nid(const SSL *ssl, int *psigtype_nid) { + GUARD_PTR(psigtype_nid); + + uint16_t sig_alg = SSL_get_peer_signature_algorithm(ssl); + if (sig_alg == 0) { + return 0; + } + + int sig_type = SSL_get_signature_algorithm_key_type(sig_alg); + + if (sig_type == EVP_PKEY_NONE) { + return 0; + } + + *psigtype_nid = sig_type; + return 1; +} + size_t SSL_get_client_random(const SSL *ssl, uint8_t *out, size_t max_out) { if (max_out == 0) { return sizeof(ssl->s3->client_random); diff --git a/ssl/ssl_test.cc b/ssl/ssl_test.cc index 754412ca8e..52f87ce6de 100644 --- a/ssl/ssl_test.cc +++ b/ssl/ssl_test.cc @@ -9905,12 +9905,24 @@ TEST(SSLTest, ConnectionPropertiesDuringRenegotiate) { EXPECT_EQ(SSL_get_group_id(client.get()), SSL_GROUP_X25519); EXPECT_EQ(SSL_get_peer_signature_algorithm(client.get()), SSL_SIGN_RSA_PKCS1_SHA256); + + int psig_nid; + EXPECT_TRUE(SSL_get_peer_signature_type_nid(client.get(), &psig_nid)); + EXPECT_EQ(psig_nid, EVP_PKEY_RSA); + int digest_nid; + EXPECT_TRUE(SSL_get_peer_signature_nid(client.get(), &digest_nid)); + EXPECT_EQ(digest_nid, NID_sha256); + bssl::UniquePtr peer(SSL_get_peer_certificate(client.get())); ASSERT_TRUE(peer); EXPECT_EQ(X509_cmp(cert.get(), peer.get()), 0); }; check_properties(); + // Client has not signed any TLS messages yet + EXPECT_FALSE(SSL_get_peer_signature_type_nid(server.get(), nullptr)); + EXPECT_FALSE(SSL_get_peer_signature_nid(server.get(), nullptr)); + // The server sends a HelloRequest. ASSERT_NO_FATAL_FAILURE(WriteHelloRequest(server.get())); @@ -9925,6 +9937,56 @@ TEST(SSLTest, ConnectionPropertiesDuringRenegotiate) { check_properties(); EXPECT_EQ(SSL_CTX_sess_connect_renegotiate(ctx.get()), 1); EXPECT_EQ(SSL_CTX_sess_accept_renegotiate(ctx.get()), 0); + + // Client does not sign any messages in renegotiation either + EXPECT_FALSE(SSL_get_peer_signature_type_nid(server.get(), nullptr)); + EXPECT_FALSE(SSL_get_peer_signature_nid(server.get(), nullptr)); +} + +TEST(SSLTest, SSLGetSignatureData) { + bssl::UniquePtr ctx(SSL_CTX_new(TLS_method())); + ASSERT_TRUE(ctx); + bssl::UniquePtr cert = GetECDSATestCertificate(); + ASSERT_TRUE(cert); + bssl::UniquePtr key = GetECDSATestKey(); + ASSERT_TRUE(key); + ASSERT_TRUE(SSL_CTX_use_certificate(ctx.get(), cert.get())); + ASSERT_TRUE(SSL_CTX_use_PrivateKey(ctx.get(), key.get())); + + // Explicitly configure |SSL_VERIFY_PEER| so both the client and server + // verify each other + SSL_CTX_set_custom_verify( + ctx.get(), SSL_VERIFY_PEER, + [](SSL *ssl, uint8_t *out_alert) { return ssl_verify_ok; }); + + ASSERT_TRUE(SSL_CTX_set_min_proto_version(ctx.get(), TLS1_3_VERSION)); + ASSERT_TRUE(SSL_CTX_set_max_proto_version(ctx.get(), TLS1_3_VERSION)); + ASSERT_TRUE(SSL_CTX_set1_sigalgs_list(ctx.get(), "ECDSA+SHA256")); + + bssl::UniquePtr client, server; + ASSERT_TRUE(CreateClientAndServer(&client, &server, ctx.get(), ctx.get())); + + // Before handshake, neither client nor server has signed any messages + ASSERT_FALSE(SSL_get_peer_signature_nid(client.get(), nullptr)); + ASSERT_FALSE(SSL_get_peer_signature_nid(server.get(), nullptr)); + ASSERT_FALSE(SSL_get_peer_signature_type_nid(client.get(), nullptr)); + ASSERT_FALSE(SSL_get_peer_signature_type_nid(server.get(), nullptr)); + + ASSERT_TRUE(CompleteHandshakes(client.get(), server.get())); + + // Both client and server verified each other, both have signed TLS messages + // now + int client_digest, client_sigtype; + ASSERT_TRUE(SSL_get_peer_signature_nid(server.get(), &client_digest)); + ASSERT_TRUE(SSL_get_peer_signature_type_nid(server.get(), &client_sigtype)); + ASSERT_EQ(client_sigtype, EVP_PKEY_EC); + ASSERT_EQ(client_digest, NID_sha256); + + int server_digest, server_sigtype; + ASSERT_TRUE(SSL_get_peer_signature_nid(client.get(), &server_digest)); + ASSERT_TRUE(SSL_get_peer_signature_type_nid(client.get(), &server_sigtype)); + ASSERT_EQ(server_sigtype, EVP_PKEY_EC); + ASSERT_EQ(server_digest, NID_sha256); } TEST(SSLTest, CopyWithoutEarlyData) { diff --git a/tests/ci/integration/openvpn_patch/aws-lc-openvpn.patch b/tests/ci/integration/openvpn_patch/aws-lc-openvpn.patch new file mode 100644 index 0000000000..6328b11768 --- /dev/null +++ b/tests/ci/integration/openvpn_patch/aws-lc-openvpn.patch @@ -0,0 +1,43 @@ +diff --git a/src/openvpn/crypto_openssl.c b/src/openvpn/crypto_openssl.c +index 50683b67..eef80d54 100644 +--- a/src/openvpn/crypto_openssl.c ++++ b/src/openvpn/crypto_openssl.c +@@ -1460,7 +1460,12 @@ tls1_P_hash(const EVP_MD *md, const unsigned char *sec, + int ret = false; + + chunk = EVP_MD_size(md); ++ ++#if !defined(OPENSSL_IS_AWSLC) + OPENSSL_assert(chunk >= 0); ++#else ++ ASSERT(chunk >= 0); ++#endif + + ctx = md_ctx_new(); + ctx_tmp = md_ctx_new(); +diff --git a/src/openvpn/openssl_compat.h b/src/openvpn/openssl_compat.h +index c9fa7196..a48ef391 100644 +--- a/src/openvpn/openssl_compat.h ++++ b/src/openvpn/openssl_compat.h +@@ -75,7 +75,7 @@ X509_OBJECT_free(X509_OBJECT *obj) + #define RSA_F_RSA_OSSL_PRIVATE_ENCRYPT RSA_F_RSA_EAY_PRIVATE_ENCRYPT + #endif + +-#if (OPENSSL_VERSION_NUMBER < 0x10100000L && !defined(ENABLE_CRYPTO_WOLFSSL)) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x3050400fL) ++#if (OPENSSL_VERSION_NUMBER < 0x10100000L && !defined(ENABLE_CRYPTO_WOLFSSL)) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x3050400fL) || defined(OPENSSL_IS_AWSLC) + #define SSL_get_peer_tmp_key SSL_get_server_tmp_key + #endif + +diff --git a/src/openvpn/ssl_openssl.c b/src/openvpn/ssl_openssl.c +index 4383e981..bd2039d3 100644 +--- a/src/openvpn/ssl_openssl.c ++++ b/src/openvpn/ssl_openssl.c +@@ -2314,7 +2314,7 @@ show_available_tls_ciphers_list(const char *cipher_list, + crypto_msg(M_FATAL, "Cannot create SSL object"); + } + +-#if OPENSSL_VERSION_NUMBER < 0x1010000fL ++#if OPENSSL_VERSION_NUMBER < 0x1010000fL || defined(OPENSSL_IS_AWSLC) + STACK_OF(SSL_CIPHER) *sk = SSL_get_ciphers(ssl); + #else + STACK_OF(SSL_CIPHER) *sk = SSL_get1_supported_ciphers(ssl); diff --git a/util/doc.config b/util/doc.config index 9663eb5b07..63c8bdca06 100644 --- a/util/doc.config +++ b/util/doc.config @@ -53,7 +53,8 @@ "include/openssl/evp.h", "include/openssl/hpke.h", "include/openssl/kdf.h", - "include/openssl/ocsp.h" + "include/openssl/ocsp.h", + "include/openssl/pkcs8.h" ] },{ "Name": "Legacy ASN.1 and X.509 implementation (documentation in progress)",