diff --git a/tests/tlsctx.c b/tests/tlsctx.c index 8e159430..f63d023b 100644 --- a/tests/tlsctx.c +++ b/tests/tlsctx.c @@ -5,6 +5,10 @@ #include #include #include +#include +#include +#include +#include static void ossl_err_print(void) { @@ -33,6 +37,185 @@ static void ossl_err_print(void) } } +static EVP_PKEY *load_key(const char *uri) +{ + OSSL_STORE_CTX *store; + OSSL_STORE_INFO *info; + EVP_PKEY *key = NULL; + + if (!uri) { + fprintf(stderr, "Invalid NULL uri"); + ossl_err_print(); + exit(EXIT_FAILURE); + } + + store = OSSL_STORE_open(uri, NULL, NULL, NULL, NULL); + if (store == NULL) { + fprintf(stderr, "Failed to open store: %s\n", uri); + ossl_err_print(); + exit(EXIT_FAILURE); + } + + if (strncmp(uri, "pkcs11:", 7) && strstr(uri, "type=private") == NULL) { + /* This is a workaround for OpenSSL < 3.2.0 where the code fails + * to correctly source public keys unless explicitly requested + * via an expect hint */ + if (OSSL_STORE_expect(store, OSSL_STORE_INFO_PUBKEY) != 1) { + fprintf(stderr, "Failed to expect Public Key File\n"); + exit(EXIT_FAILURE); + } + } + + for (info = OSSL_STORE_load(store); info != NULL; + info = OSSL_STORE_load(store)) { + int type = OSSL_STORE_INFO_get_type(info); + + if (key != NULL) { + fprintf(stderr, "Multiple keys matching URI: %s\n", uri); + exit(EXIT_FAILURE); + } + + switch (type) { + case OSSL_STORE_INFO_PUBKEY: + key = OSSL_STORE_INFO_get1_PUBKEY(info); + break; + case OSSL_STORE_INFO_PKEY: + key = OSSL_STORE_INFO_get1_PKEY(info); + break; + } + OSSL_STORE_INFO_free(info); + } + + if (key == NULL) { + fprintf(stderr, "Failed to load key from URI: %s\n", uri); + ossl_err_print(); + exit(EXIT_FAILURE); + } + OSSL_STORE_close(store); + + return key; +} + +static void test_pkcs1_with_tls_padding(void) +{ + EVP_PKEY_CTX *ctx; + EVP_PKEY *prikey; + EVP_PKEY *pubkey; + unsigned char plain[SSL_MAX_MASTER_KEY_LENGTH + 2] = { 0x03, 0x03, 0x01 }; + unsigned char *enc; + unsigned char *dec; + size_t enclen; + size_t declen; + unsigned int ver = 0x0303; + const OSSL_PARAM ver_params[] = { + OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION, &ver), + OSSL_PARAM_END + }; + int err; + + pubkey = load_key(getenv("PUBURI")); + + ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pubkey, NULL); + if (!ctx) { + fprintf(stderr, "Failed to init pkey ctx for puburi\n"); + ossl_err_print(); + exit(EXIT_FAILURE); + } + err = EVP_PKEY_encrypt_init(ctx); + if (err != 1) { + fprintf(stderr, "Failed to init encrypt ctx\n"); + ossl_err_print(); + exit(EXIT_FAILURE); + } + err = EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING); + if (err != 1) { + fprintf(stderr, "Failed to set padding on encrypt ctx\n"); + ossl_err_print(); + exit(EXIT_FAILURE); + } + + err = EVP_PKEY_encrypt(ctx, NULL, &enclen, plain, sizeof(plain)); + if (err != 1) { + fprintf(stderr, "Failed to get buffer length\n"); + ossl_err_print(); + exit(EXIT_FAILURE); + } + + enc = OPENSSL_malloc(enclen); + if (!enc) { + fprintf(stderr, "Failed to allocate buffer\n"); + ossl_err_print(); + exit(EXIT_FAILURE); + } + + err = EVP_PKEY_encrypt(ctx, enc, &enclen, plain, sizeof(plain)); + if (err != 1) { + fprintf(stderr, "Failed to encrypt TLS master key\n"); + ossl_err_print(); + exit(EXIT_FAILURE); + } + + EVP_PKEY_CTX_free(ctx); + + prikey = load_key(getenv("PRIURI")); + + ctx = EVP_PKEY_CTX_new_from_pkey(NULL, prikey, NULL); + if (!ctx) { + fprintf(stderr, "Failed to init pkey ctx for priuri\n"); + ossl_err_print(); + exit(EXIT_FAILURE); + } + err = EVP_PKEY_decrypt_init(ctx); + if (err != 1) { + fprintf(stderr, "Failed to init decrypt ctx\n"); + ossl_err_print(); + exit(EXIT_FAILURE); + } + err = EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_WITH_TLS_PADDING); + if (err != 1) { + fprintf(stderr, "Failed to set padding on decrypt ctx\n"); + ossl_err_print(); + exit(EXIT_FAILURE); + } + + err = EVP_PKEY_CTX_set_params(ctx, ver_params); + if (err != 1) { + fprintf(stderr, "Failed to set version params\n"); + ossl_err_print(); + exit(EXIT_FAILURE); + } + + err = EVP_PKEY_decrypt(ctx, NULL, &declen, enc, enclen); + if (err != 1) { + fprintf(stderr, "Failed to get buffer length\n"); + ossl_err_print(); + exit(EXIT_FAILURE); + } + + dec = OPENSSL_malloc(declen); + if (!dec) { + fprintf(stderr, "Failed to allocate buffer\n"); + ossl_err_print(); + exit(EXIT_FAILURE); + } + + err = EVP_PKEY_decrypt(ctx, dec, &declen, enc, enclen); + if (err != 1) { + fprintf(stderr, "Failed to decrypt TLS master key\n"); + ossl_err_print(); + exit(EXIT_FAILURE); + } + + EVP_PKEY_CTX_free(ctx); + + if ((declen != sizeof(plain) - 2) + || (memcmp(plain + 2, dec, declen) != 0)) { + fprintf(stderr, "Fail, decrypted master secret differs from input\n"); + ossl_err_print(); + exit(EXIT_FAILURE); + } +} + int main(int argc, char *argv[]) { SSL_CTX *ctx; @@ -48,5 +231,7 @@ int main(int argc, char *argv[]) SSL_CTX_free(ctx); + test_pkcs1_with_tls_padding(); + exit(EXIT_SUCCESS); }