X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=test%2Fevp_extra_test.c;h=8ee41ab5ce8d0c1a2f2af61f011040ec52d2119a;hp=f07ae94ad31113d1b657a2cc81d5d3332bfb2812;hb=b425001010044adbdbcd98f8682694b30b73bbf4;hpb=cad8347be23c5e0c0d9eea02d090d42daf2dd7a9 diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c index f07ae94ad3..8ee41ab5ce 100644 --- a/test/evp_extra_test.c +++ b/test/evp_extra_test.c @@ -1,5 +1,5 @@ /* - * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -7,10 +7,14 @@ * https://www.openssl.org/source/license.html */ +/* We need to use some deprecated APIs */ +#define OPENSSL_SUPPRESS_DEPRECATED + #include #include #include #include +#include #include #include #include @@ -19,9 +23,18 @@ #include #include #include +#include +#include +#include +#include +#include #include "testutil.h" #include "internal/nelem.h" -#include "internal/evp_int.h" +#include "internal/sizes.h" +#include "crypto/evp.h" +#include "../e_os.h" /* strcasecmp */ + +static OSSL_LIB_CTX *testctx = NULL; /* * kExampleRSAKeyDER is an RSA private key in ASN.1, DER format. Of course, you @@ -81,6 +94,53 @@ static const unsigned char kExampleRSAKeyDER[] = { 0x2d, 0x86, 0x9d, 0xa5, 0x20, 0x1b, 0xe5, 0xdf, }; +/* +* kExampleDSAKeyDER is a DSA private key in ASN.1, DER format. Of course, you + * should never use this key anywhere but in an example. + */ +#ifndef OPENSSL_NO_DSA +static const unsigned char kExampleDSAKeyDER[] = { + 0x30, 0x82, 0x01, 0xba, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, 0x00, 0x9a, + 0x05, 0x6d, 0x33, 0xcd, 0x5d, 0x78, 0xa1, 0xbb, 0xcb, 0x7d, 0x5b, 0x8d, + 0xb4, 0xcc, 0xbf, 0x03, 0x99, 0x64, 0xde, 0x38, 0x78, 0x06, 0x15, 0x2f, + 0x86, 0x26, 0x77, 0xf3, 0xb1, 0x85, 0x00, 0xed, 0xfc, 0x28, 0x3a, 0x42, + 0x4d, 0xab, 0xab, 0xdf, 0xbc, 0x9c, 0x16, 0xd0, 0x22, 0x50, 0xd1, 0x38, + 0xdd, 0x3f, 0x64, 0x05, 0x9e, 0x68, 0x7a, 0x1e, 0xf1, 0x56, 0xbf, 0x1e, + 0x2c, 0xc5, 0x97, 0x2a, 0xfe, 0x7a, 0x22, 0xdc, 0x6c, 0x68, 0xb8, 0x2e, + 0x06, 0xdb, 0x41, 0xca, 0x98, 0xd8, 0x54, 0xc7, 0x64, 0x48, 0x24, 0x04, + 0x20, 0xbc, 0x59, 0xe3, 0x6b, 0xea, 0x7e, 0xfc, 0x7e, 0xc5, 0x4e, 0xd4, + 0xd8, 0x3a, 0xed, 0xcd, 0x5d, 0x99, 0xb8, 0x5c, 0xa2, 0x8b, 0xbb, 0x0b, + 0xac, 0xe6, 0x8e, 0x25, 0x56, 0x22, 0x3a, 0x2d, 0x3a, 0x56, 0x41, 0x14, + 0x1f, 0x1c, 0x8f, 0x53, 0x46, 0x13, 0x85, 0x02, 0x15, 0x00, 0x98, 0x7e, + 0x92, 0x81, 0x88, 0xc7, 0x3f, 0x70, 0x49, 0x54, 0xf6, 0x76, 0xb4, 0xa3, + 0x9e, 0x1d, 0x45, 0x98, 0x32, 0x7f, 0x02, 0x81, 0x80, 0x69, 0x4d, 0xef, + 0x55, 0xff, 0x4d, 0x59, 0x2c, 0x01, 0xfa, 0x6a, 0x38, 0xe0, 0x70, 0x9f, + 0x9e, 0x66, 0x8e, 0x3e, 0x8c, 0x52, 0x22, 0x9d, 0x15, 0x7e, 0x3c, 0xef, + 0x4c, 0x7a, 0x61, 0x26, 0xe0, 0x2b, 0x81, 0x3f, 0xeb, 0xaf, 0x35, 0x38, + 0x8d, 0xfe, 0xed, 0x46, 0xff, 0x5f, 0x03, 0x9b, 0x81, 0x92, 0xe7, 0x6f, + 0x76, 0x4f, 0x1d, 0xd9, 0xbb, 0x89, 0xc9, 0x3e, 0xd9, 0x0b, 0xf9, 0xf4, + 0x78, 0x11, 0x59, 0xc0, 0x1d, 0xcd, 0x0e, 0xa1, 0x6f, 0x15, 0xf1, 0x4d, + 0xc1, 0xc9, 0x22, 0xed, 0x8d, 0xad, 0x67, 0xc5, 0x4b, 0x95, 0x93, 0x86, + 0xa6, 0xaf, 0x8a, 0xee, 0x06, 0x89, 0x2f, 0x37, 0x7e, 0x64, 0xaa, 0xf6, + 0xe7, 0xb1, 0x5a, 0x0a, 0x93, 0x95, 0x5d, 0x3e, 0x53, 0x9a, 0xde, 0x8a, + 0xc2, 0x95, 0x45, 0x81, 0xbe, 0x5c, 0x2f, 0xc2, 0xb2, 0x92, 0x58, 0x19, + 0x72, 0x80, 0xe9, 0x79, 0xa1, 0x02, 0x81, 0x80, 0x07, 0xd7, 0x62, 0xff, + 0xdf, 0x1a, 0x3f, 0xed, 0x32, 0xd4, 0xd4, 0x88, 0x7b, 0x2c, 0x63, 0x7f, + 0x97, 0xdc, 0x44, 0xd4, 0x84, 0xa2, 0xdd, 0x17, 0x16, 0x85, 0x13, 0xe0, + 0xac, 0x51, 0x8d, 0x29, 0x1b, 0x75, 0x9a, 0xe4, 0xe3, 0x8a, 0x92, 0x69, + 0x09, 0x03, 0xc5, 0x68, 0xae, 0x5e, 0x94, 0xfe, 0xc9, 0x92, 0x6c, 0x07, + 0xb4, 0x1e, 0x64, 0x62, 0x87, 0xc6, 0xa4, 0xfd, 0x0d, 0x5f, 0xe5, 0xf9, + 0x1b, 0x4f, 0x85, 0x5f, 0xae, 0xf3, 0x11, 0xe5, 0x18, 0xd4, 0x4d, 0x79, + 0x9f, 0xc4, 0x79, 0x26, 0x04, 0x27, 0xf0, 0x0b, 0xee, 0x2b, 0x86, 0x9f, + 0x86, 0x61, 0xe6, 0x51, 0xce, 0x04, 0x9b, 0x5d, 0x6b, 0x34, 0x43, 0x8c, + 0x85, 0x3c, 0xf1, 0x51, 0x9b, 0x08, 0x23, 0x1b, 0xf5, 0x7e, 0x33, 0x12, + 0xea, 0xab, 0x1f, 0xb7, 0x2d, 0xe2, 0x5f, 0xe6, 0x97, 0x99, 0xb5, 0x45, + 0x16, 0x5b, 0xc3, 0x41, 0x02, 0x14, 0x61, 0xbf, 0x51, 0x60, 0xcf, 0xc8, + 0xf1, 0x8c, 0x82, 0x97, 0xf2, 0xf4, 0x19, 0xba, 0x2b, 0xf3, 0x16, 0xbe, + 0x40, 0x48 +}; +#endif + /* * kExampleBadRSAKeyDER is an RSA private key in ASN.1, DER format. The private * components are not correct. @@ -301,7 +361,7 @@ static const unsigned char kExampleECPubKeyDER[] = { }; /* - * kExampleBadECKeyDER is a sample EC public key with a wrong OID + * kExampleBadECPubKeyDER is a sample EC public key with a wrong OID * 1.2.840.10045.2.2 instead of 1.2.840.10045.2.1 - EC Public Key */ static const unsigned char kExampleBadECPubKeyDER[] = { @@ -374,6 +434,77 @@ end: return ret; } +#ifndef OPENSSL_NO_DSA +static EVP_PKEY *load_example_dsa_key(void) +{ + EVP_PKEY *ret = NULL; + const unsigned char *derp = kExampleDSAKeyDER; + EVP_PKEY *pkey = NULL; + DSA *dsa = NULL; + + if (!TEST_true(d2i_DSAPrivateKey(&dsa, &derp, sizeof(kExampleDSAKeyDER)))) + return NULL; + + if (!TEST_ptr(pkey = EVP_PKEY_new()) + || !TEST_true(EVP_PKEY_set1_DSA(pkey, dsa))) + goto end; + + ret = pkey; + pkey = NULL; + +end: + EVP_PKEY_free(pkey); + DSA_free(dsa); + + return ret; +} +#endif + +static EVP_PKEY *load_example_hmac_key(void) +{ + EVP_PKEY *pkey = NULL; + unsigned char key[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f + }; + + pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, key, sizeof(key)); + if (!TEST_ptr(pkey)) + return NULL; + + return pkey; +} + +static int test_EVP_set_default_properties(void) +{ + OSSL_LIB_CTX *ctx; + EVP_MD *md = NULL; + int res = 0; + + if (!TEST_ptr(ctx = OSSL_LIB_CTX_new()) + || !TEST_ptr(md = EVP_MD_fetch(ctx, "sha256", NULL))) + goto err; + EVP_MD_free(md); + md = NULL; + + if (!TEST_true(EVP_set_default_properties(ctx, "provider=fizzbang")) + || !TEST_ptr_null(md = EVP_MD_fetch(ctx, "sha256", NULL)) + || !TEST_ptr(md = EVP_MD_fetch(ctx, "sha256", "-provider"))) + goto err; + EVP_MD_free(md); + md = NULL; + + if (!TEST_true(EVP_set_default_properties(ctx, NULL)) + || !TEST_ptr(md = EVP_MD_fetch(ctx, "sha256", NULL))) + goto err; + res = 1; +err: + EVP_MD_free(md); + OSSL_LIB_CTX_free(ctx); + return res; +} + static int test_EVP_Enveloped(void) { int ret = 0; @@ -417,48 +548,119 @@ err: return ret; } - -static int test_EVP_DigestSignInit(void) +/* + * Test 0: Standard calls to EVP_DigestSignInit/Update/Final (Implicit fetch digest, RSA) + * Test 1: Standard calls to EVP_DigestSignInit/Update/Final (Implicit fetch digest, DSA) + * Test 2: Standard calls to EVP_DigestSignInit/Update/Final (Implicit fetch digest, HMAC) + * Test 3: Standard calls to EVP_DigestSignInit/Update/Final (Explicit fetch digest, RSA) + * Test 4: Standard calls to EVP_DigestSignInit/Update/Final (Explicit fetch digest, DSA) + * Test 5: Standard calls to EVP_DigestSignInit/Update/Final (Explicit fetch diegst, HMAC) + * Test 6: Use an MD BIO to do the Update calls instead (RSA) + * Test 7: Use an MD BIO to do the Update calls instead (DSA) + * Test 8: Use an MD BIO to do the Update calls instead (HMAC) + */ +static int test_EVP_DigestSignInit(int tst) { int ret = 0; EVP_PKEY *pkey = NULL; unsigned char *sig = NULL; size_t sig_len = 0; - EVP_MD_CTX *md_ctx, *md_ctx_verify = NULL; + EVP_MD_CTX *md_ctx = NULL, *md_ctx_verify = NULL; + EVP_MD_CTX *a_md_ctx = NULL, *a_md_ctx_verify = NULL; + BIO *mdbio = NULL, *membio = NULL; + size_t written; + const EVP_MD *md; + EVP_MD *mdexp = NULL; + + if (tst >= 6) { + membio = BIO_new(BIO_s_mem()); + mdbio = BIO_new(BIO_f_md()); + if (!TEST_ptr(membio) || !TEST_ptr(mdbio)) + goto out; + BIO_push(mdbio, membio); + if (!TEST_int_gt(BIO_get_md_ctx(mdbio, &md_ctx), 0)) + goto out; + } else { + if (!TEST_ptr(a_md_ctx = md_ctx = EVP_MD_CTX_new()) + || !TEST_ptr(a_md_ctx_verify = md_ctx_verify = EVP_MD_CTX_new())) + goto out; + } - if (!TEST_ptr(md_ctx = EVP_MD_CTX_new()) - || !TEST_ptr(md_ctx_verify = EVP_MD_CTX_new()) - || !TEST_ptr(pkey = load_example_rsa_key())) + if (tst == 0 || tst == 3 || tst == 6) { + if (!TEST_ptr(pkey = load_example_rsa_key())) + goto out; + } else if (tst == 1 || tst == 4 || tst == 7) { +#ifndef OPENSSL_NO_DSA + if (!TEST_ptr(pkey = load_example_dsa_key())) + goto out; +#else + ret = 1; goto out; +#endif + } else { + if (!TEST_ptr(pkey = load_example_hmac_key())) + goto out; + } + + if (tst >= 3 && tst <= 5) + md = mdexp = EVP_MD_fetch(NULL, "SHA256", NULL); + else + md = EVP_sha256(); - if (!TEST_true(EVP_DigestSignInit(md_ctx, NULL, EVP_sha256(), NULL, pkey)) - || !TEST_true(EVP_DigestSignUpdate(md_ctx, kMsg, sizeof(kMsg)))) + if (!TEST_true(EVP_DigestSignInit(md_ctx, NULL, md, NULL, pkey))) goto out; + if (tst >= 6) { + if (!BIO_write_ex(mdbio, kMsg, sizeof(kMsg), &written)) + goto out; + } else { + if (!TEST_true(EVP_DigestSignUpdate(md_ctx, kMsg, sizeof(kMsg)))) + goto out; + } + /* Determine the size of the signature. */ if (!TEST_true(EVP_DigestSignFinal(md_ctx, NULL, &sig_len)) - || !TEST_size_t_eq(sig_len, (size_t)EVP_PKEY_size(pkey))) - goto out; - - if (!TEST_ptr(sig = OPENSSL_malloc(sig_len)) + || !TEST_ptr(sig = OPENSSL_malloc(sig_len)) || !TEST_true(EVP_DigestSignFinal(md_ctx, sig, &sig_len))) goto out; - /* Ensure that the signature round-trips. */ - if (!TEST_true(EVP_DigestVerifyInit(md_ctx_verify, NULL, EVP_sha256(), - NULL, pkey)) - || !TEST_true(EVP_DigestVerifyUpdate(md_ctx_verify, - kMsg, sizeof(kMsg))) - || !TEST_true(EVP_DigestVerifyFinal(md_ctx_verify, sig, sig_len))) - goto out; + if (tst >= 6) { + if (!TEST_int_gt(BIO_reset(mdbio), 0) + || !TEST_int_gt(BIO_get_md_ctx(mdbio, &md_ctx_verify), 0)) + goto out; + } + + /* + * Ensure that the signature round-trips (Verification isn't supported for + * HMAC via EVP_DigestVerify*) + */ + if (tst != 2 && tst != 5 && tst != 8) { + if (!TEST_true(EVP_DigestVerifyInit(md_ctx_verify, NULL, md, + NULL, pkey))) + goto out; + + if (tst >= 6) { + if (!TEST_true(BIO_write_ex(mdbio, kMsg, sizeof(kMsg), &written))) + goto out; + } else { + if (!TEST_true(EVP_DigestVerifyUpdate(md_ctx_verify, kMsg, + sizeof(kMsg)))) + goto out; + } + if (!TEST_true(EVP_DigestVerifyFinal(md_ctx_verify, sig, sig_len))) + goto out; + } ret = 1; out: - EVP_MD_CTX_free(md_ctx); - EVP_MD_CTX_free(md_ctx_verify); + BIO_free(membio); + BIO_free(mdbio); + EVP_MD_CTX_free(a_md_ctx); + EVP_MD_CTX_free(a_md_ctx_verify); EVP_PKEY_free(pkey); OPENSSL_free(sig); + EVP_MD_free(mdexp); return ret; } @@ -599,37 +801,135 @@ static int test_EVP_PKCS82PKEY(void) } #endif -#ifndef OPENSSL_NO_SM2 +/* This uses kExampleRSAKeyDER and kExampleRSAKeyPKCS8 to verify encoding */ +static int test_privatekey_to_pkcs8(void) +{ + EVP_PKEY *pkey = NULL; + BIO *membio = NULL; + char *membuf = NULL; + long membuf_len = 0; + int ok = 0; + + if (!TEST_ptr(membio = BIO_new(BIO_s_mem())) + || !TEST_ptr(pkey = load_example_rsa_key()) + || !TEST_int_gt(i2d_PKCS8PrivateKey_bio(membio, pkey, NULL, + NULL, 0, NULL, NULL), + 0) + || !TEST_int_gt(membuf_len = BIO_get_mem_data(membio, &membuf), 0) + || !TEST_ptr(membuf) + || !TEST_mem_eq(membuf, (size_t)membuf_len, + kExampleRSAKeyPKCS8, sizeof(kExampleRSAKeyPKCS8)) + /* + * We try to write PEM as well, just to see that it doesn't err, but + * assume that the result is correct. + */ + || !TEST_int_gt(PEM_write_bio_PKCS8PrivateKey(membio, pkey, NULL, + NULL, 0, NULL, NULL), + 0)) + goto done; + + ok = 1; + done: + EVP_PKEY_free(pkey); + BIO_free_all(membio); + return ok; +} + +#ifndef OPENSSL_NO_EC +static const struct { + int encoding; + const char *encoding_name; +} ec_encodings[] = { + { OPENSSL_EC_EXPLICIT_CURVE, OSSL_PKEY_EC_ENCODING_EXPLICIT }, + { OPENSSL_EC_NAMED_CURVE, OSSL_PKEY_EC_ENCODING_GROUP } +}; + +static int ec_export_get_encoding_cb(const OSSL_PARAM params[], void *arg) +{ + const OSSL_PARAM *p; + const char *enc_name = NULL; + int *enc = arg; + size_t i; + + *enc = -1; + + if (!TEST_ptr(p = OSSL_PARAM_locate_const(params, + OSSL_PKEY_PARAM_EC_ENCODING)) + || !TEST_true(OSSL_PARAM_get_utf8_string_ptr(p, &enc_name))) + return 0; + + for (i = 0; i < OSSL_NELEM(ec_encodings); i++) { + if (strcasecmp(enc_name, ec_encodings[i].encoding_name) == 0) { + *enc = ec_encodings[i].encoding; + break; + } + } + + return (*enc != -1); +} + +static int test_EC_keygen_with_enc(int idx) +{ + EVP_PKEY *params = NULL, *key = NULL; + EVP_PKEY_CTX *pctx = NULL, *kctx = NULL; + int enc; + int ret = 0; + + enc = ec_encodings[idx].encoding; + + /* Create key parameters */ + if (!TEST_ptr(pctx = EVP_PKEY_CTX_new_from_name(testctx, "EC", NULL)) + || !TEST_true(EVP_PKEY_paramgen_init(pctx)) + || !TEST_true(EVP_PKEY_CTX_set_group_name(pctx, "P-256")) + || !TEST_true(EVP_PKEY_CTX_set_ec_param_enc(pctx, enc)) + || !TEST_true(EVP_PKEY_paramgen(pctx, ¶ms)) + || !TEST_ptr(params)) + goto done; + + /* Create key */ + if (!TEST_ptr(kctx = EVP_PKEY_CTX_new_from_pkey(testctx, params, NULL)) + || !TEST_true(EVP_PKEY_keygen_init(kctx)) + || !TEST_true(EVP_PKEY_keygen(kctx, &key)) + || !TEST_ptr(key)) + goto done; + + /* Check that the encoding got all the way into the key */ + if (!TEST_true(evp_keymgmt_util_export(key, OSSL_KEYMGMT_SELECT_ALL, + ec_export_get_encoding_cb, &enc)) + || !TEST_int_eq(enc, ec_encodings[idx].encoding)) + goto done; + + ret = 1; + done: + EVP_PKEY_free(key); + EVP_PKEY_free(params); + EVP_PKEY_CTX_free(kctx); + EVP_PKEY_CTX_free(pctx); + return ret; +} +#endif + +#if !defined(OPENSSL_NO_SM2) && !defined(FIPS_MODULE) static int test_EVP_SM2_verify(void) { - /* From https://tools.ietf.org/html/draft-shen-sm2-ecdsa-02#appendix-A */ const char *pubkey = - "-----BEGIN PUBLIC KEY-----\n" - "MIIBMzCB7AYHKoZIzj0CATCB4AIBATAsBgcqhkjOPQEBAiEAhULWnkwETxjouSQ1\n" - "v2/33kVyg5FcRVF9ci7biwjx38MwRAQgeHlotPoyw/0kF4Quc7v+/y88hItoMdfg\n" - "7GUiizk35JgEIGPkxtOyOwyEnPhCQUhL/kj2HVmlsWugbm4S0donxSSaBEEEQh3r\n" - "1hti6rZ0ZDTrw8wxXjIiCzut1QvcTE5sFH/t1D0GgFEry7QsB9RzSdIVO3DE5df9\n" - "/L+jbqGoWEG55G4JogIhAIVC1p5MBE8Y6LkkNb9v990pdyBjBIVijVrnTufDLnm3\n" - "AgEBA0IABArkx3mKoPEZRxvuEYJb5GICu3nipYRElel8BP9N8lSKfAJA+I8c1OFj\n" - "Uqc8F7fxbwc1PlOhdtaEqf4Ma7eY6Fc=\n" - "-----END PUBLIC KEY-----\n"; + "-----BEGIN PUBLIC KEY-----\n" + "MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEp1KLWq1ZE2jmoAnnBJE1LBGxVr18\n" + "YvvqECWCpXfAQ9qUJ+UmthnUPf0iM3SaXKHe6PlLIDyNlWMWb9RUh/yU3g==\n" + "-----END PUBLIC KEY-----\n"; const char *msg = "message digest"; const char *id = "ALICE123@YAHOO.COM"; const uint8_t signature[] = { - 0x30, 0x44, 0x02, 0x20, - - 0x40, 0xF1, 0xEC, 0x59, 0xF7, 0x93, 0xD9, 0xF4, 0x9E, 0x09, 0xDC, - 0xEF, 0x49, 0x13, 0x0D, 0x41, 0x94, 0xF7, 0x9F, 0xB1, 0xEE, 0xD2, - 0xCA, 0xA5, 0x5B, 0xAC, 0xDB, 0x49, 0xC4, 0xE7, 0x55, 0xD1, - - 0x02, 0x20, - - 0x6F, 0xC6, 0xDA, 0xC3, 0x2C, 0x5D, 0x5C, 0xF1, 0x0C, 0x77, 0xDF, - 0xB2, 0x0F, 0x7C, 0x2E, 0xB6, 0x67, 0xA4, 0x57, 0x87, 0x2F, 0xB0, - 0x9E, 0xC5, 0x63, 0x27, 0xA6, 0x7E, 0xC7, 0xDE, 0xEB, 0xE7 + 0x30, 0x44, 0x02, 0x20, 0x5b, 0xdb, 0xab, 0x81, 0x4f, 0xbb, + 0x8b, 0x69, 0xb1, 0x05, 0x9c, 0x99, 0x3b, 0xb2, 0x45, 0x06, + 0x4a, 0x30, 0x15, 0x59, 0x84, 0xcd, 0xee, 0x30, 0x60, 0x36, + 0x57, 0x87, 0xef, 0x5c, 0xd0, 0xbe, 0x02, 0x20, 0x43, 0x8d, + 0x1f, 0xc7, 0x77, 0x72, 0x39, 0xbb, 0x72, 0xe1, 0xfd, 0x07, + 0x58, 0xd5, 0x82, 0xc8, 0x2d, 0xba, 0x3b, 0x2c, 0x46, 0x24, + 0xe3, 0x50, 0xff, 0x04, 0xc7, 0xa0, 0x71, 0x9f, 0xa4, 0x70 }; int rc = 0; @@ -646,7 +946,7 @@ static int test_EVP_SM2_verify(void) if (!TEST_true(pkey != NULL)) goto done; - if (!TEST_true(EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2))) + if (!TEST_true(EVP_PKEY_is_a(pkey, "SM2"))) goto done; if (!TEST_ptr(mctx = EVP_MD_CTX_new())) @@ -655,15 +955,14 @@ static int test_EVP_SM2_verify(void) if (!TEST_ptr(pctx = EVP_PKEY_CTX_new(pkey, NULL))) goto done; - if (!TEST_int_gt(EVP_PKEY_CTX_set1_id(pctx, (const uint8_t *)id, - strlen(id)), 0)) - goto done; - EVP_MD_CTX_set_pkey_ctx(mctx, pctx); if (!TEST_true(EVP_DigestVerifyInit(mctx, NULL, EVP_sm3(), NULL, pkey))) goto done; + if (!TEST_int_gt(EVP_PKEY_CTX_set1_id(pctx, id, strlen(id)), 0)) + goto done; + if (!TEST_true(EVP_DigestVerifyUpdate(mctx, msg, strlen(msg)))) goto done; @@ -683,7 +982,7 @@ static int test_EVP_SM2(void) { int ret = 0; EVP_PKEY *pkey = NULL; - EVP_PKEY *params = NULL; + EVP_PKEY *pkeyparams = NULL; EVP_PKEY_CTX *pctx = NULL; EVP_PKEY_CTX *kctx = NULL; EVP_PKEY_CTX *sctx = NULL; @@ -701,20 +1000,26 @@ static int test_EVP_SM2(void) uint8_t sm2_id[] = {1, 2, 3, 4, 'l', 'e', 't', 't', 'e', 'r'}; - pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL); + OSSL_PARAM sparams[2] = {OSSL_PARAM_END, OSSL_PARAM_END}; + OSSL_PARAM gparams[2] = {OSSL_PARAM_END, OSSL_PARAM_END}; + int i; + char mdname[20]; + + pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_SM2, NULL); if (!TEST_ptr(pctx)) goto done; if (!TEST_true(EVP_PKEY_paramgen_init(pctx) == 1)) goto done; + /* TODO is this even needed? */ if (!TEST_true(EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_sm2))) goto done; - if (!TEST_true(EVP_PKEY_paramgen(pctx, ¶ms))) + if (!TEST_true(EVP_PKEY_paramgen(pctx, &pkeyparams))) goto done; - kctx = EVP_PKEY_CTX_new(params, NULL); + kctx = EVP_PKEY_CTX_new(pkeyparams, NULL); if (!TEST_ptr(kctx)) goto done; @@ -724,9 +1029,6 @@ static int test_EVP_SM2(void) if (!TEST_true(EVP_PKEY_keygen(kctx, &pkey))) goto done; - if (!TEST_true(EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2))) - goto done; - if (!TEST_ptr(md_ctx = EVP_MD_CTX_new())) goto done; @@ -739,10 +1041,10 @@ static int test_EVP_SM2(void) EVP_MD_CTX_set_pkey_ctx(md_ctx, sctx); EVP_MD_CTX_set_pkey_ctx(md_ctx_verify, sctx); - if (!TEST_int_gt(EVP_PKEY_CTX_set1_id(sctx, sm2_id, sizeof(sm2_id)), 0)) + if (!TEST_true(EVP_DigestSignInit(md_ctx, NULL, EVP_sm3(), NULL, pkey))) goto done; - if (!TEST_true(EVP_DigestSignInit(md_ctx, NULL, EVP_sm3(), NULL, pkey))) + if (!TEST_int_gt(EVP_PKEY_CTX_set1_id(sctx, sm2_id, sizeof(sm2_id)), 0)) goto done; if(!TEST_true(EVP_DigestSignUpdate(md_ctx, kMsg, sizeof(kMsg)))) @@ -752,9 +1054,6 @@ static int test_EVP_SM2(void) if (!TEST_true(EVP_DigestSignFinal(md_ctx, NULL, &sig_len))) goto done; - if (!TEST_size_t_eq(sig_len, (size_t)EVP_PKEY_size(pkey))) - goto done; - if (!TEST_ptr(sig = OPENSSL_malloc(sig_len))) goto done; @@ -766,6 +1065,9 @@ static int test_EVP_SM2(void) if (!TEST_true(EVP_DigestVerifyInit(md_ctx_verify, NULL, EVP_sm3(), NULL, pkey))) goto done; + if (!TEST_int_gt(EVP_PKEY_CTX_set1_id(sctx, sm2_id, sizeof(sm2_id)), 0)) + goto done; + if (!TEST_true(EVP_DigestVerifyUpdate(md_ctx_verify, kMsg, sizeof(kMsg)))) goto done; @@ -774,26 +1076,53 @@ static int test_EVP_SM2(void) /* now check encryption/decryption */ - if (!TEST_ptr(cctx = EVP_PKEY_CTX_new(pkey, NULL))) - goto done; + gparams[0] = OSSL_PARAM_construct_utf8_string(OSSL_ASYM_CIPHER_PARAM_DIGEST, + mdname, sizeof(mdname)); + for (i = 0; i < 2; i++) { + EVP_PKEY_CTX_free(cctx); - if (!TEST_true(EVP_PKEY_encrypt_init(cctx))) - goto done; + sparams[0] = OSSL_PARAM_construct_utf8_string(OSSL_ASYM_CIPHER_PARAM_DIGEST, + i == 0 ? "SM3" : "SHA2-256", + 0); - if (!TEST_true(EVP_PKEY_encrypt(cctx, ciphertext, &ctext_len, kMsg, sizeof(kMsg)))) - goto done; + if (!TEST_ptr(cctx = EVP_PKEY_CTX_new(pkey, NULL))) + goto done; - if (!TEST_true(EVP_PKEY_decrypt_init(cctx))) - goto done; + if (!TEST_true(EVP_PKEY_encrypt_init(cctx))) + goto done; - if (!TEST_true(EVP_PKEY_decrypt(cctx, plaintext, &ptext_len, ciphertext, ctext_len))) - goto done; + if (!TEST_true(EVP_PKEY_CTX_set_params(cctx, sparams))) + goto done; - if (!TEST_true(ptext_len == sizeof(kMsg))) - goto done; + if (!TEST_true(EVP_PKEY_encrypt(cctx, ciphertext, &ctext_len, kMsg, + sizeof(kMsg)))) + goto done; - if (!TEST_true(memcmp(plaintext, kMsg, sizeof(kMsg)) == 0)) - goto done; + if (!TEST_true(EVP_PKEY_decrypt_init(cctx))) + goto done; + + if (!TEST_true(EVP_PKEY_CTX_set_params(cctx, sparams))) + goto done; + + if (!TEST_true(EVP_PKEY_decrypt(cctx, plaintext, &ptext_len, ciphertext, + ctext_len))) + goto done; + + if (!TEST_true(EVP_PKEY_CTX_get_params(cctx, gparams))) + goto done; + + /* Test we're still using the digest we think we are */ + if (i == 0 && !TEST_int_eq(strcmp(mdname, "SM3"), 0)) + goto done; + if (i == 1 && !TEST_int_eq(strcmp(mdname, "SHA2-256"), 0)) + goto done; + + if (!TEST_true(ptext_len == sizeof(kMsg))) + goto done; + + if (!TEST_true(memcmp(plaintext, kMsg, sizeof(kMsg)) == 0)) + goto done; + } ret = 1; done: @@ -802,7 +1131,7 @@ done: EVP_PKEY_CTX_free(sctx); EVP_PKEY_CTX_free(cctx); EVP_PKEY_free(pkey); - EVP_PKEY_free(params); + EVP_PKEY_free(pkeyparams); EVP_MD_CTX_free(md_ctx); EVP_MD_CTX_free(md_ctx_verify); OPENSSL_free(sig); @@ -842,7 +1171,7 @@ static struct keys_st { #endif }; -static int test_set_get_raw_keys_int(int tst, int pub) +static int test_set_get_raw_keys_int(int tst, int pub, int uselibctx) { int ret = 0; unsigned char buf[80]; @@ -859,17 +1188,34 @@ static int test_set_get_raw_keys_int(int tst, int pub) if (pub) { inlen = strlen(keys[tst].pub); in = (unsigned char *)keys[tst].pub; - pkey = EVP_PKEY_new_raw_public_key(keys[tst].type, - NULL, - in, - inlen); + if (uselibctx) { + pkey = EVP_PKEY_new_raw_public_key_ex( + testctx, + OBJ_nid2sn(keys[tst].type), + NULL, + in, + inlen); + } else { + pkey = EVP_PKEY_new_raw_public_key(keys[tst].type, + NULL, + in, + inlen); + } } else { inlen = strlen(keys[tst].priv); in = (unsigned char *)keys[tst].priv; - pkey = EVP_PKEY_new_raw_private_key(keys[tst].type, - NULL, - in, - inlen); + if (uselibctx) { + pkey = EVP_PKEY_new_raw_private_key_ex( + testctx, OBJ_nid2sn(keys[tst].type), + NULL, + in, + inlen); + } else { + pkey = EVP_PKEY_new_raw_private_key(keys[tst].type, + NULL, + in, + inlen); + } } if (!TEST_ptr(pkey) @@ -889,10 +1235,13 @@ static int test_set_get_raw_keys_int(int tst, int pub) static int test_set_get_raw_keys(int tst) { - return test_set_get_raw_keys_int(tst, 0) - && test_set_get_raw_keys_int(tst, 1); + return test_set_get_raw_keys_int(tst, 0, 0) + && test_set_get_raw_keys_int(tst, 0, 1) + && test_set_get_raw_keys_int(tst, 1, 0) + && test_set_get_raw_keys_int(tst, 1, 1); } +#ifndef OPENSSL_NO_DEPRECATED_3_0 static int pkey_custom_check(EVP_PKEY *pkey) { return 0xbeef; @@ -909,6 +1258,7 @@ static int pkey_custom_param_check(EVP_PKEY *pkey) } static EVP_PKEY_METHOD *custom_pmeth; +#endif static int test_EVP_PKEY_check(int i) { @@ -919,7 +1269,9 @@ static int test_EVP_PKEY_check(int i) EC_KEY *eckey = NULL; #endif EVP_PKEY_CTX *ctx = NULL; +#ifndef OPENSSL_NO_DEPRECATED_3_0 EVP_PKEY_CTX *ctx2 = NULL; +#endif const APK_DATA *ak = &keycheckdata[i]; const unsigned char *input = ak->kder; size_t input_len = ak->size; @@ -971,6 +1323,7 @@ static int test_EVP_PKEY_check(int i) if (!TEST_int_eq(EVP_PKEY_param_check(ctx), expected_param_check)) goto done; +#ifndef OPENSSL_NO_DEPRECATED_3_0 ctx2 = EVP_PKEY_CTX_new_id(0xdefaced, NULL); /* assign the pkey directly, as an internal test */ EVP_PKEY_up_ref(pkey); @@ -984,17 +1337,89 @@ static int test_EVP_PKEY_check(int i) if (!TEST_int_eq(EVP_PKEY_param_check(ctx2), 0xbeef)) goto done; +#endif ret = 1; done: EVP_PKEY_CTX_free(ctx); +#ifndef OPENSSL_NO_DEPRECATED_3_0 EVP_PKEY_CTX_free(ctx2); +#endif EVP_PKEY_free(pkey); BIO_free(pubkey); return ret; } +#ifndef OPENSSL_NO_CMAC +static int get_cmac_val(EVP_PKEY *pkey, unsigned char *mac) +{ + EVP_MD_CTX *mdctx = EVP_MD_CTX_new(); + const char msg[] = "Hello World"; + size_t maclen; + int ret = 1; + + if (!TEST_ptr(mdctx) + || !TEST_true(EVP_DigestSignInit(mdctx, NULL, NULL, NULL, pkey)) + || !TEST_true(EVP_DigestSignUpdate(mdctx, msg, sizeof(msg))) + || !TEST_true(EVP_DigestSignFinal(mdctx, mac, &maclen)) + || !TEST_size_t_eq(maclen, AES_BLOCK_SIZE)) + ret = 0; + + EVP_MD_CTX_free(mdctx); + + return ret; +} +static int test_CMAC_keygen(void) +{ + static unsigned char key[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f + }; + /* + * This is a legacy method for CMACs, but should still work. + * This verifies that it works without an ENGINE. + */ + EVP_PKEY_CTX *kctx = EVP_PKEY_CTX_new_id(EVP_PKEY_CMAC, NULL); + int ret = 0; + EVP_PKEY *pkey = NULL; + unsigned char mac[AES_BLOCK_SIZE], mac2[AES_BLOCK_SIZE]; + + /* Test a CMAC key created using the "generated" method */ + if (!TEST_int_gt(EVP_PKEY_keygen_init(kctx), 0) + || !TEST_int_gt(EVP_PKEY_CTX_ctrl(kctx, -1, EVP_PKEY_OP_KEYGEN, + EVP_PKEY_CTRL_CIPHER, + 0, (void *)EVP_aes_256_ecb()), 0) + || !TEST_int_gt(EVP_PKEY_CTX_ctrl(kctx, -1, EVP_PKEY_OP_KEYGEN, + EVP_PKEY_CTRL_SET_MAC_KEY, + sizeof(key), (void *)key), 0) + || !TEST_int_gt(EVP_PKEY_keygen(kctx, &pkey), 0) + || !TEST_ptr(pkey) + || !TEST_true(get_cmac_val(pkey, mac))) + goto done; + + EVP_PKEY_free(pkey); + + /* + * Test a CMAC key using the direct method, and compare with the mac + * created above. + */ + pkey = EVP_PKEY_new_CMAC_key(NULL, key, sizeof(key), EVP_aes_256_ecb()); + if (!TEST_ptr(pkey) + || !TEST_true(get_cmac_val(pkey, mac2)) + || !TEST_mem_eq(mac, sizeof(mac), mac2, sizeof(mac2))) + goto done; + + ret = 1; + + done: + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(kctx); + return ret; +} +#endif + static int test_HKDF(void) { EVP_PKEY_CTX *pctx; @@ -1039,6 +1464,47 @@ static int test_HKDF(void) return ret; } +static int test_emptyikm_HKDF(void) +{ + EVP_PKEY_CTX *pctx; + unsigned char out[20]; + size_t outlen; + int ret = 0; + unsigned char salt[] = "9876543210"; + unsigned char key[] = ""; + unsigned char info[] = "stringinfo"; + const unsigned char expected[] = { + 0x68, 0x81, 0xa5, 0x3e, 0x5b, 0x9c, 0x7b, 0x6f, 0x2e, 0xec, 0xc8, 0x47, + 0x7c, 0xfa, 0x47, 0x35, 0x66, 0x82, 0x15, 0x30 + }; + size_t expectedlen = sizeof(expected); + + if (!TEST_ptr(pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL))) + goto done; + + outlen = sizeof(out); + memset(out, 0, outlen); + + if (!TEST_int_gt(EVP_PKEY_derive_init(pctx), 0) + || !TEST_int_gt(EVP_PKEY_CTX_set_hkdf_md(pctx, EVP_sha256()), 0) + || !TEST_int_gt(EVP_PKEY_CTX_set1_hkdf_salt(pctx, salt, + sizeof(salt) - 1), 0) + || !TEST_int_gt(EVP_PKEY_CTX_set1_hkdf_key(pctx, key, + sizeof(key) - 1), 0) + || !TEST_int_gt(EVP_PKEY_CTX_add1_hkdf_info(pctx, info, + sizeof(info) - 1), 0) + || !TEST_int_gt(EVP_PKEY_derive(pctx, out, &outlen), 0) + || !TEST_mem_eq(out, outlen, expected, expectedlen)) + goto done; + + ret = 1; + + done: + EVP_PKEY_CTX_free(pctx); + + return ret; +} + #ifndef OPENSSL_NO_EC static int test_X509_PUBKEY_inplace(void) { @@ -1068,122 +1534,593 @@ done: X509_PUBKEY_free(xp); return ret; } +#endif /* OPENSSL_NO_EC */ + +/* Test getting and setting parameters on an EVP_PKEY_CTX */ +static int test_EVP_PKEY_CTX_get_set_params(EVP_PKEY *pkey) +{ + EVP_MD_CTX *mdctx = NULL; + EVP_PKEY_CTX *ctx = NULL; + const OSSL_PARAM *params; + OSSL_PARAM ourparams[2], *param = ourparams, *param_md; + int ret = 0; + const EVP_MD *md; + char mdname[OSSL_MAX_NAME_SIZE]; + char ssl3ms[48]; + + /* Initialise a sign operation */ + ctx = EVP_PKEY_CTX_new(pkey, NULL); + if (!TEST_ptr(ctx) + || !TEST_int_gt(EVP_PKEY_sign_init(ctx), 0)) + goto err; + + /* + * We should be able to query the parameters now. + */ + params = EVP_PKEY_CTX_settable_params(ctx); + if (!TEST_ptr(params) + || !TEST_ptr(OSSL_PARAM_locate_const(params, + OSSL_SIGNATURE_PARAM_DIGEST))) + goto err; + + params = EVP_PKEY_CTX_gettable_params(ctx); + if (!TEST_ptr(params) + || !TEST_ptr(OSSL_PARAM_locate_const(params, + OSSL_SIGNATURE_PARAM_ALGORITHM_ID)) + || !TEST_ptr(OSSL_PARAM_locate_const(params, + OSSL_SIGNATURE_PARAM_DIGEST))) + goto err; + + /* + * Test getting and setting params via EVP_PKEY_CTX_set_params() and + * EVP_PKEY_CTX_get_params() + */ + strcpy(mdname, "SHA512"); + param_md = param; + *param++ = OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, + mdname, 0); + *param++ = OSSL_PARAM_construct_end(); + + if (!TEST_true(EVP_PKEY_CTX_set_params(ctx, ourparams))) + goto err; + + mdname[0] = '\0'; + *param_md = OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, + mdname, sizeof(mdname)); + if (!TEST_true(EVP_PKEY_CTX_get_params(ctx, ourparams)) + || !TEST_str_eq(mdname, "SHA512")) + goto err; + + /* + * Test the TEST_PKEY_CTX_set_signature_md() and + * TEST_PKEY_CTX_get_signature_md() functions + */ + if (!TEST_int_gt(EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()), 0) + || !TEST_int_gt(EVP_PKEY_CTX_get_signature_md(ctx, &md), 0) + || !TEST_ptr_eq(md, EVP_sha256())) + goto err; + + /* + * Test getting MD parameters via an associated EVP_PKEY_CTX + */ + mdctx = EVP_MD_CTX_new(); + if (!TEST_ptr(mdctx) + || !TEST_true(EVP_DigestSignInit_ex(mdctx, NULL, "SHA1", NULL, NULL, + pkey))) + goto err; + + /* + * We now have an EVP_MD_CTX with an EVP_PKEY_CTX inside it. We should be + * able to obtain the digest's settable parameters from the provider. + */ + params = EVP_MD_CTX_settable_params(mdctx); + if (!TEST_ptr(params) + || !TEST_int_eq(strcmp(params[0].key, OSSL_DIGEST_PARAM_SSL3_MS), 0) + /* The final key should be NULL */ + || !TEST_ptr_null(params[1].key)) + goto err; + + param = ourparams; + memset(ssl3ms, 0, sizeof(ssl3ms)); + *param++ = OSSL_PARAM_construct_octet_string(OSSL_DIGEST_PARAM_SSL3_MS, + ssl3ms, sizeof(ssl3ms)); + *param++ = OSSL_PARAM_construct_end(); + + if (!TEST_true(EVP_MD_CTX_set_params(mdctx, ourparams))) + goto err; + + ret = 1; + + err: + EVP_MD_CTX_free(mdctx); + EVP_PKEY_CTX_free(ctx); + + return ret; +} + +#ifndef OPENSSL_NO_DSA +static int test_DSA_get_set_params(void) +{ + DSA *dsa = NULL; + BIGNUM *p = NULL, *q = NULL, *g = NULL, *pub = NULL, *priv = NULL; + EVP_PKEY *pkey = NULL; + int ret = 0; + + /* + * Setup the parameters for our DSA object. For our purposes they don't + * have to actually be *valid* parameters. We just need to set something. + */ + dsa = DSA_new(); + p = BN_new(); + q = BN_new(); + g = BN_new(); + pub = BN_new(); + priv = BN_new(); + if (!TEST_ptr(dsa) + || !TEST_ptr(p) + || !TEST_ptr(q) + || !TEST_ptr(g) + || !TEST_ptr(pub) + || !DSA_set0_pqg(dsa, p, q, g) + || !DSA_set0_key(dsa, pub, priv)) + goto err; + p = q = g = pub = priv = NULL; + + pkey = EVP_PKEY_new(); + if (!TEST_ptr(pkey) + || !TEST_true(EVP_PKEY_assign_DSA(pkey, dsa))) + goto err; + + dsa = NULL; + + ret = test_EVP_PKEY_CTX_get_set_params(pkey); + + err: + EVP_PKEY_free(pkey); + DSA_free(dsa); + BN_free(p); + BN_free(q); + BN_free(g); + BN_free(pub); + BN_free(priv); + + return ret; +} #endif +static int test_RSA_get_set_params(void) +{ + RSA *rsa = NULL; + BIGNUM *n = NULL, *e = NULL, *d = NULL; + EVP_PKEY *pkey = NULL; + int ret = 0; + + /* + * Setup the parameters for our RSA object. For our purposes they don't + * have to actually be *valid* parameters. We just need to set something. + */ + rsa = RSA_new(); + n = BN_new(); + e = BN_new(); + d = BN_new(); + if (!TEST_ptr(rsa) + || !TEST_ptr(n) + || !TEST_ptr(e) + || !TEST_ptr(d) + || !RSA_set0_key(rsa, n, e, d)) + goto err; + n = e = d = NULL; + + pkey = EVP_PKEY_new(); + if (!TEST_ptr(pkey) + || !TEST_true(EVP_PKEY_assign_RSA(pkey, rsa))) + goto err; + + rsa = NULL; + + ret = test_EVP_PKEY_CTX_get_set_params(pkey); + + err: + EVP_PKEY_free(pkey); + RSA_free(rsa); + BN_free(n); + BN_free(e); + BN_free(d); + + return ret; +} -static int calculate_digest(const EVP_MD *md, const char *msg, size_t len, - const unsigned char *exptd) +#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305) +static int test_decrypt_null_chunks(void) { - unsigned char out[SHA256_DIGEST_LENGTH]; - EVP_MD_CTX *ctx; + EVP_CIPHER_CTX* ctx = NULL; + const unsigned char key[32] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1 + }; + unsigned char iv[12] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b + }; + unsigned char msg[] = "It was the best of times, it was the worst of times"; + unsigned char ciphertext[80]; + unsigned char plaintext[80]; + /* We initialise tmp to a non zero value on purpose */ + int ctlen, ptlen, tmp = 99; int ret = 0; + const int enc_offset = 10, dec_offset = 20; + + if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new()) + || !TEST_true(EVP_EncryptInit_ex(ctx, EVP_chacha20_poly1305(), NULL, + key, iv)) + || !TEST_true(EVP_EncryptUpdate(ctx, ciphertext, &ctlen, msg, + enc_offset)) + /* Deliberate add a zero length update */ + || !TEST_true(EVP_EncryptUpdate(ctx, ciphertext + ctlen, &tmp, NULL, + 0)) + || !TEST_int_eq(tmp, 0) + || !TEST_true(EVP_EncryptUpdate(ctx, ciphertext + ctlen, &tmp, + msg + enc_offset, + sizeof(msg) - enc_offset)) + || !TEST_int_eq(ctlen += tmp, sizeof(msg)) + || !TEST_true(EVP_EncryptFinal(ctx, ciphertext + ctlen, &tmp)) + || !TEST_int_eq(tmp, 0)) + goto err; - if (!TEST_ptr(ctx = EVP_MD_CTX_new()) - || !TEST_true(EVP_DigestInit_ex(ctx, md, NULL)) - || !TEST_true(EVP_DigestUpdate(ctx, msg, len)) - || !TEST_true(EVP_DigestFinal_ex(ctx, out, NULL)) - || !TEST_mem_eq(out, SHA256_DIGEST_LENGTH, exptd, - SHA256_DIGEST_LENGTH)) + /* Deliberately initialise tmp to a non zero value */ + tmp = 99; + if (!TEST_true(EVP_DecryptInit_ex(ctx, EVP_chacha20_poly1305(), NULL, key, + iv)) + || !TEST_true(EVP_DecryptUpdate(ctx, plaintext, &ptlen, ciphertext, + dec_offset)) + /* + * Deliberately add a zero length update. We also deliberately do + * this at a different offset than for encryption. + */ + || !TEST_true(EVP_DecryptUpdate(ctx, plaintext + ptlen, &tmp, NULL, + 0)) + || !TEST_int_eq(tmp, 0) + || !TEST_true(EVP_DecryptUpdate(ctx, plaintext + ptlen, &tmp, + ciphertext + dec_offset, + ctlen - dec_offset)) + || !TEST_int_eq(ptlen += tmp, sizeof(msg)) + || !TEST_true(EVP_DecryptFinal(ctx, plaintext + ptlen, &tmp)) + || !TEST_int_eq(tmp, 0) + || !TEST_mem_eq(msg, sizeof(msg), plaintext, ptlen)) goto err; ret = 1; err: - EVP_MD_CTX_free(ctx); + EVP_CIPHER_CTX_free(ctx); return ret; } +#endif /* !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305) */ + +#ifndef OPENSSL_NO_DH +static int test_EVP_PKEY_set1_DH(void) +{ + DH *x942dh = NULL, *noqdh = NULL; + EVP_PKEY *pkey1 = NULL, *pkey2 = NULL; + int ret = 0; + BIGNUM *p, *g = NULL; + + if (!TEST_ptr(p = BN_new()) + || !TEST_ptr(g = BN_new()) + || !BN_set_word(p, 9999) + || !BN_set_word(g, 2) + || !TEST_ptr(noqdh = DH_new()) + || !DH_set0_pqg(noqdh, p, NULL, g)) + goto err; + p = g = NULL; + + x942dh = DH_get_2048_256(); + pkey1 = EVP_PKEY_new(); + pkey2 = EVP_PKEY_new(); + if (!TEST_ptr(x942dh) + || !TEST_ptr(noqdh) + || !TEST_ptr(pkey1) + || !TEST_ptr(pkey2)) + goto err; + + if(!TEST_true(EVP_PKEY_set1_DH(pkey1, x942dh)) + || !TEST_int_eq(EVP_PKEY_id(pkey1), EVP_PKEY_DHX)) + goto err; + + if(!TEST_true(EVP_PKEY_set1_DH(pkey2, noqdh)) + || !TEST_int_eq(EVP_PKEY_id(pkey2), EVP_PKEY_DH)) + goto err; + + ret = 1; + err: + BN_free(p); + BN_free(g); + EVP_PKEY_free(pkey1); + EVP_PKEY_free(pkey2); + DH_free(x942dh); + DH_free(noqdh); + + return ret; +} +#endif + /* - * Test EVP_MD_fetch() - * - * Test 0: Test with the default OPENSSL_CTX - * Test 1: Test with an explicit OPENSSL_CTX - * Test 2: Explicit OPENSSL_CTX with explicit load of default provider + * We test what happens with an empty template. For the sake of this test, + * the template must be ignored, and we know that's the case for RSA keys + * (this might arguably be a misfeature, but that's what we currently do, + * even in provider code, since that's how the legacy RSA implementation + * does things) */ -static int test_EVP_MD_fetch(int tst) +static int test_keygen_with_empty_template(int n) { - OPENSSL_CTX *ctx = NULL; - EVP_MD *md = NULL; - OSSL_PROVIDER *prov = NULL; + EVP_PKEY_CTX *ctx = NULL; + EVP_PKEY *pkey = NULL; + EVP_PKEY *tkey = NULL; int ret = 0; - const char testmsg[] = "Hello world"; - const unsigned char exptd[] = { - 0x27, 0x51, 0x8b, 0xa9, 0x68, 0x30, 0x11, 0xf6, 0xb3, 0x96, 0x07, 0x2c, - 0x05, 0xf6, 0x65, 0x6d, 0x04, 0xf5, 0xfb, 0xc3, 0x78, 0x7c, 0xf9, 0x24, - 0x90, 0xec, 0x60, 0x6e, 0x50, 0x92, 0xe3, 0x26 - }; - if (tst > 0) { - ctx = OPENSSL_CTX_new(); - if (!TEST_ptr(ctx)) + switch (n) { + case 0: + /* We do test with no template at all as well */ + if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL))) goto err; - - if (tst == 2) { - prov = OSSL_PROVIDER_load(ctx, "default"); - if (!TEST_ptr(prov)) - goto err; - } + break; + case 1: + /* Here we create an empty RSA key that serves as our template */ + if (!TEST_ptr(tkey = EVP_PKEY_new()) + || !TEST_true(EVP_PKEY_set_type(tkey, EVP_PKEY_RSA)) + || !TEST_ptr(ctx = EVP_PKEY_CTX_new(tkey, NULL))) + goto err; + break; } - /* Implicit fetching of the MD should produce the expected result */ - if (!TEST_true(calculate_digest(EVP_sha256(), testmsg, sizeof(testmsg), - exptd))) + if (!TEST_int_gt(EVP_PKEY_keygen_init(ctx), 0) + || !TEST_int_gt(EVP_PKEY_keygen(ctx, &pkey), 0)) goto err; - /* - * Test that without loading any providers or specifying any properties we - * can get a sha256 md from the default provider. - */ - if (!TEST_ptr(md = EVP_MD_fetch(ctx, "SHA256", NULL)) - || !TEST_ptr(md) - || !TEST_int_eq(EVP_MD_nid(md), NID_sha256) - || !TEST_true(calculate_digest(md, testmsg, sizeof(testmsg), exptd))) + + ret = 1; + err: + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); + EVP_PKEY_free(tkey); + return ret; +} + +/* + * Test that we fail if we attempt to use an algorithm that is not available + * in the current library context (unless we are using an algorithm that + * should be made available via legacy codepaths). + * + * 0: RSA + * 1: SM2 + */ +static int test_pkey_ctx_fail_without_provider(int tst) +{ + OSSL_LIB_CTX *tmpctx = OSSL_LIB_CTX_new(); + OSSL_PROVIDER *nullprov = NULL; + EVP_PKEY_CTX *pctx = NULL; + const char *keytype = NULL; + int expect_null = 0; + int ret = 0; + + if (!TEST_ptr(tmpctx)) goto err; - /* Also test EVP_MD_upref() while we're doing this */ - if (!TEST_true(EVP_MD_upref(md))) + nullprov = OSSL_PROVIDER_load(tmpctx, "null"); + if (!TEST_ptr(nullprov)) goto err; - /* Ref count should now be 2. Release both */ - EVP_MD_meth_free(md); - EVP_MD_meth_free(md); - md = NULL; /* - * We've only loaded the default provider so explicitly asking for a - * non-default implementation should fail. + * We check for certain algos in the null provider. + * If an algo is expected to have a provider keymgmt, contructing an + * EVP_PKEY_CTX is expected to fail (return NULL). + * Otherwise, if it's expected to have legacy support, contructing an + * EVP_PKEY_CTX is expected to succeed (return non-NULL). */ - if (!TEST_ptr_null(md = EVP_MD_fetch(ctx, "SHA256", "default=no"))) + switch (tst) { + case 0: + keytype = "RSA"; + expect_null = 1; + break; + case 1: + keytype = "SM2"; + expect_null = 1; +#ifdef OPENSSL_NO_EC + TEST_info("EC disable, skipping SM2 check..."); + goto end; +#endif +#ifdef OPENSSL_NO_SM2 + TEST_info("SM2 disable, skipping SM2 check..."); + goto end; +#endif + break; + default: + TEST_error("No test for case %d", tst); goto err; + } - /* Explicitly asking for the default implementation should succeeed */ - if (!TEST_ptr(md = EVP_MD_fetch(ctx, "SHA256", "default=yes")) - || !TEST_int_eq(EVP_MD_nid(md), NID_sha256) - || !TEST_true(calculate_digest(md, testmsg, sizeof(testmsg), exptd))) + pctx = EVP_PKEY_CTX_new_from_name(tmpctx, keytype, ""); + if (expect_null ? !TEST_ptr_null(pctx) : !TEST_ptr(pctx)) goto err; - EVP_MD_meth_free(md); - md = NULL; - +#if defined(OPENSSL_NO_EC) || defined(OPENSSL_NO_SM2) + end: +#endif ret = 1; err: - EVP_MD_meth_free(md); - OSSL_PROVIDER_unload(prov); - OPENSSL_CTX_free(ctx); + EVP_PKEY_CTX_free(pctx); + OSSL_PROVIDER_unload(nullprov); + OSSL_LIB_CTX_free(tmpctx); + return ret; +} + +static int test_rand_agglomeration(void) +{ + EVP_RAND *rand; + EVP_RAND_CTX *ctx; + OSSL_PARAM params[3], *p = params; + int res; + unsigned int step = 7; + static unsigned char seed[] = "It does not matter how slowly you go " + "as long as you do not stop."; + unsigned char out[sizeof(seed)]; + + if (!TEST_int_ne(sizeof(seed) % step, 0) + || !TEST_ptr(rand = EVP_RAND_fetch(NULL, "TEST-RAND", NULL))) + return 0; + ctx = EVP_RAND_CTX_new(rand, NULL); + EVP_RAND_free(rand); + if (!TEST_ptr(ctx)) + return 0; + + memset(out, 0, sizeof(out)); + *p++ = OSSL_PARAM_construct_octet_string(OSSL_RAND_PARAM_TEST_ENTROPY, + seed, sizeof(seed)); + *p++ = OSSL_PARAM_construct_uint(OSSL_DRBG_PARAM_MAX_REQUEST, &step); + *p = OSSL_PARAM_construct_end(); + res = TEST_true(EVP_RAND_set_ctx_params(ctx, params)) + && TEST_true(EVP_RAND_generate(ctx, out, sizeof(out), 0, 1, NULL, 0)) + && TEST_mem_eq(seed, sizeof(seed), out, sizeof(out)); + EVP_RAND_CTX_free(ctx); + return res; +} + +/* + * Test that we correctly return the original or "running" IV after + * an encryption operation. + * Run multiple times for some different relevant algorithms/modes. + */ +static int test_evp_iv(int idx) +{ + int ret = 0; + EVP_CIPHER_CTX *ctx = NULL; + unsigned char key[16] = {0x4c, 0x43, 0xdb, 0xdd, 0x42, 0x73, 0x47, 0xd1, + 0xe5, 0x62, 0x7d, 0xcd, 0x4d, 0x76, 0x4d, 0x57}; + unsigned char init_iv[EVP_MAX_IV_LENGTH] = + {0x57, 0x71, 0x7d, 0xad, 0xdb, 0x9b, 0x98, 0x82, + 0x5a, 0x55, 0x91, 0x81, 0x42, 0xa8, 0x89, 0x34}; + static const unsigned char msg[] = { 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16 }; + unsigned char ciphertext[32], oiv[16], iv[16]; + unsigned char *ref_iv; + unsigned char cbc_state[16] = {0x10, 0x2f, 0x05, 0xcc, 0xc2, 0x55, 0x72, 0xb9, + 0x88, 0xe6, 0x4a, 0x17, 0x10, 0x74, 0x22, 0x5e}; + + unsigned char ofb_state[16] = {0x76, 0xe6, 0x66, 0x61, 0xd0, 0x8a, 0xe4, 0x64, + 0xdd, 0x66, 0xbf, 0x00, 0xf0, 0xe3, 0x6f, 0xfd}; + unsigned char gcm_state[12] = {0x57, 0x71, 0x7d, 0xad, 0xdb, 0x9b, + 0x98, 0x82, 0x5a, 0x55, 0x91, 0x81}; + unsigned char ccm_state[7] = {0x57, 0x71, 0x7d, 0xad, 0xdb, 0x9b, 0x98}; +#ifndef OPENSSL_NO_OCB + unsigned char ocb_state[12] = {0x57, 0x71, 0x7d, 0xad, 0xdb, 0x9b, + 0x98, 0x82, 0x5a, 0x55, 0x91, 0x81}; +#endif + int len = sizeof(ciphertext); + size_t ivlen, ref_len; + const EVP_CIPHER *type = NULL; + + switch(idx) { + case 0: + type = EVP_aes_128_cbc(); + /* FALLTHROUGH */ + case 5: + type = (type != NULL) ? type : + EVP_CIPHER_fetch(testctx, "aes-128-cbc", NULL); + ref_iv = cbc_state; + ref_len = sizeof(cbc_state); + break; + case 1: + type = EVP_aes_128_ofb(); + /* FALLTHROUGH */ + case 6: + type = (type != NULL) ? type : + EVP_CIPHER_fetch(testctx, "aes-128-ofb", NULL); + ref_iv = ofb_state; + ref_len = sizeof(ofb_state); + break; + case 2: + type = EVP_aes_128_gcm(); + /* FALLTHROUGH */ + case 7: + type = (type != NULL) ? type : + EVP_CIPHER_fetch(testctx, "aes-128-gcm", NULL); + ref_iv = gcm_state; + ref_len = sizeof(gcm_state); + break; + case 3: + type = EVP_aes_128_ccm(); + /* FALLTHROUGH */ + case 8: + type = (type != NULL) ? type : + EVP_CIPHER_fetch(testctx, "aes-128-ccm", NULL); + ref_iv = ccm_state; + ref_len = sizeof(ccm_state); + break; +#ifdef OPENSSL_NO_OCB + case 4: + case 9: + return 1; +#else + case 4: + type = EVP_aes_128_ocb(); + /* FALLTHROUGH */ + case 9: + type = (type != NULL) ? type : + EVP_CIPHER_fetch(testctx, "aes-128-ocb", NULL); + ref_iv = ocb_state; + ref_len = sizeof(ocb_state); + break; +#endif + default: + return 0; + } + + if (!TEST_ptr(type) + || !TEST_ptr((ctx = EVP_CIPHER_CTX_new())) + || !TEST_true(EVP_EncryptInit_ex(ctx, type, NULL, key, init_iv)) + || !TEST_true(EVP_EncryptUpdate(ctx, ciphertext, &len, msg, + (int)sizeof(msg))) + || !TEST_true(EVP_CIPHER_CTX_get_iv(ctx, oiv, sizeof(oiv))) + || !TEST_true(EVP_CIPHER_CTX_get_iv_state(ctx, iv, sizeof(iv))) + || !TEST_true(EVP_EncryptFinal_ex(ctx, ciphertext, &len))) + goto err; + ivlen = EVP_CIPHER_CTX_iv_length(ctx); + if (!TEST_mem_eq(init_iv, ivlen, oiv, ivlen) + || !TEST_mem_eq(ref_iv, ref_len, iv, ivlen)) + goto err; + + ret = 1; +err: + EVP_CIPHER_CTX_free(ctx); + if (idx >= 5) + EVP_CIPHER_free((EVP_CIPHER *)type); return ret; } int setup_tests(void) { - ADD_TEST(test_EVP_DigestSignInit); + testctx = OSSL_LIB_CTX_new(); + + if (!TEST_ptr(testctx)) + return 0; + + ADD_TEST(test_EVP_set_default_properties); + ADD_ALL_TESTS(test_EVP_DigestSignInit, 9); ADD_TEST(test_EVP_DigestVerifyInit); ADD_TEST(test_EVP_Enveloped); ADD_ALL_TESTS(test_d2i_AutoPrivateKey, OSSL_NELEM(keydata)); + ADD_TEST(test_privatekey_to_pkcs8); #ifndef OPENSSL_NO_EC ADD_TEST(test_EVP_PKCS82PKEY); #endif -#ifndef OPENSSL_NO_SM2 +#ifndef OPENSSL_NO_EC + ADD_ALL_TESTS(test_EC_keygen_with_enc, OSSL_NELEM(ec_encodings)); +#endif +#if !defined(OPENSSL_NO_SM2) && !defined(FIPS_MODULE) ADD_TEST(test_EVP_SM2); ADD_TEST(test_EVP_SM2_verify); #endif ADD_ALL_TESTS(test_set_get_raw_keys, OSSL_NELEM(keys)); +#ifndef OPENSSL_NO_DEPRECATED_3_0 custom_pmeth = EVP_PKEY_meth_new(0xdefaced, 0); if (!TEST_ptr(custom_pmeth)) return 0; @@ -1192,13 +2129,38 @@ int setup_tests(void) EVP_PKEY_meth_set_param_check(custom_pmeth, pkey_custom_param_check); if (!TEST_int_eq(EVP_PKEY_meth_add0(custom_pmeth), 1)) return 0; +#endif ADD_ALL_TESTS(test_EVP_PKEY_check, OSSL_NELEM(keycheckdata)); +#ifndef OPENSSL_NO_CMAC + ADD_TEST(test_CMAC_keygen); +#endif ADD_TEST(test_HKDF); + ADD_TEST(test_emptyikm_HKDF); #ifndef OPENSSL_NO_EC ADD_TEST(test_X509_PUBKEY_inplace); ADD_ALL_TESTS(test_invalide_ec_char2_pub_range_decode, OSSL_NELEM(ec_der_pub_keys)); #endif - ADD_ALL_TESTS(test_EVP_MD_fetch, 3); +#ifndef OPENSSL_NO_DSA + ADD_TEST(test_DSA_get_set_params); +#endif + ADD_TEST(test_RSA_get_set_params); +#if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305) + ADD_TEST(test_decrypt_null_chunks); +#endif +#ifndef OPENSSL_NO_DH + ADD_TEST(test_EVP_PKEY_set1_DH); +#endif + ADD_ALL_TESTS(test_keygen_with_empty_template, 2); + ADD_ALL_TESTS(test_pkey_ctx_fail_without_provider, 2); + + ADD_TEST(test_rand_agglomeration); + ADD_ALL_TESTS(test_evp_iv, 10); + return 1; } + +void cleanup_tests(void) +{ + OSSL_LIB_CTX_free(testctx); +}