Skip to content

Commit

Permalink
OpenVPN error codes, SSL_get_peer_signature_* funcs, and first patch …
Browse files Browse the repository at this point in the history
…file (#1584)

### Issues
CryptoAlg-2477
CryptoAlg-2478

### Description of changes: 
1. Added three new aliases for AES-128-GCM, AES-192-GCM, and AES-256-GCM
as required by OpenVPN
2. Added an error and function code. Error code points to our equivalent
of the OpenSSL PKCS12_R_MAC_VERIFY_FAILURE error
3. Added SSL_get_peer_signature_nid and SSL_get_peer_signature_type_nid.
No new state is stored for these in the SSL connection.
4. Generated a patch file to use OpenVPNs internal ASSERT function
instead of OpenSSL_assert, SSL_get_ciphers instead of
SSL_get1_supported_ciphers, and point SSL_get_peer_tmp_key to
SSL_get_server_tmp_key (which we define as a no-op)
5. Added pkcs8.h to doc.config

### Call-outs:
The patch file is temporary and will likely change with future PRs

### Testing:
1. SSL_get_peer_signature_nid and SSL_get_peer_signature_type_nid are
tested in a TLS 1.2 connection (with renegotiation) and in a TLS 1.3
connection (with mTLS configured to test both the client and server
side).

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.
  • Loading branch information
smittals2 authored Jun 18, 2024
1 parent e3d34d7 commit 6a949d8
Show file tree
Hide file tree
Showing 8 changed files with 167 additions and 2 deletions.
5 changes: 4 additions & 1 deletion crypto/cipher_extra/cipher_extra.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
5 changes: 5 additions & 0 deletions include/openssl/pkcs8.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 4 additions & 0 deletions include/openssl/rsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
12 changes: 12 additions & 0 deletions include/openssl/ssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
35 changes: 35 additions & 0 deletions ssl/ssl_lib.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
62 changes: 62 additions & 0 deletions ssl/ssl_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<X509> 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()));

Expand All @@ -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<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
ASSERT_TRUE(ctx);
bssl::UniquePtr<X509> cert = GetECDSATestCertificate();
ASSERT_TRUE(cert);
bssl::UniquePtr<EVP_PKEY> 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<SSL> 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) {
Expand Down
43 changes: 43 additions & 0 deletions tests/ci/integration/openvpn_patch/aws-lc-openvpn.patch
Original file line number Diff line number Diff line change
@@ -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);
3 changes: 2 additions & 1 deletion util/doc.config
Original file line number Diff line number Diff line change
Expand Up @@ -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)",
Expand Down

0 comments on commit 6a949d8

Please sign in to comment.