2001-08-18 21:53:01 +08:00
|
|
|
/*
|
2025-03-12 21:35:59 +08:00
|
|
|
* Copyright 2015-2025 The OpenSSL Project Authors. All Rights Reserved.
|
2001-08-18 21:53:01 +08:00
|
|
|
*
|
2018-12-06 20:05:25 +08:00
|
|
|
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
2016-05-18 02:20:24 +08:00
|
|
|
* this file except in compliance with the License. You can obtain a copy
|
|
|
|
* in the file LICENSE in the source distribution or at
|
|
|
|
* https://www.openssl.org/source/license.html
|
2001-08-18 21:53:01 +08:00
|
|
|
*/
|
|
|
|
|
2020-12-08 23:13:54 +08:00
|
|
|
#define OPENSSL_SUPPRESS_DEPRECATED /* EVP_PKEY_new_CMAC_key */
|
2001-08-18 21:53:01 +08:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
2015-02-10 01:29:47 +08:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <ctype.h>
|
2001-08-18 21:53:01 +08:00
|
|
|
#include <openssl/evp.h>
|
2015-02-12 01:15:51 +08:00
|
|
|
#include <openssl/pem.h>
|
2003-01-31 01:39:26 +08:00
|
|
|
#include <openssl/err.h>
|
2019-04-11 18:27:59 +08:00
|
|
|
#include <openssl/provider.h>
|
2015-02-10 01:29:47 +08:00
|
|
|
#include <openssl/x509v3.h>
|
2015-05-23 00:17:21 +08:00
|
|
|
#include <openssl/pkcs12.h>
|
2016-01-19 21:59:00 +08:00
|
|
|
#include <openssl/kdf.h>
|
2019-07-31 04:52:07 +08:00
|
|
|
#include <openssl/params.h>
|
2024-11-13 21:18:13 +08:00
|
|
|
#include <openssl/param_build.h>
|
2019-07-31 04:52:07 +08:00
|
|
|
#include <openssl/core_names.h>
|
2020-09-05 11:08:27 +08:00
|
|
|
#include <openssl/fips_names.h>
|
2022-07-21 01:07:46 +08:00
|
|
|
#include <openssl/thread.h>
|
2015-05-19 22:51:01 +08:00
|
|
|
#include "internal/numbers.h"
|
2019-07-31 04:52:07 +08:00
|
|
|
#include "internal/nelem.h"
|
2024-07-11 03:26:30 +08:00
|
|
|
#include "internal/sizes.h"
|
2020-08-07 12:29:00 +08:00
|
|
|
#include "crypto/evp.h"
|
2017-04-27 03:33:43 +08:00
|
|
|
#include "testutil.h"
|
2020-11-29 19:40:10 +08:00
|
|
|
|
|
|
|
typedef struct evp_test_buffer_st EVP_TEST_BUFFER;
|
|
|
|
DEFINE_STACK_OF(EVP_TEST_BUFFER)
|
2001-08-18 21:53:01 +08:00
|
|
|
|
2017-05-19 22:27:28 +08:00
|
|
|
#define AAD_NUM 4
|
2017-05-13 02:19:51 +08:00
|
|
|
|
|
|
|
typedef struct evp_test_method_st EVP_TEST_METHOD;
|
2017-05-09 02:46:57 +08:00
|
|
|
|
2020-08-07 12:29:00 +08:00
|
|
|
/* Structure holding test information */
|
2017-05-13 02:19:51 +08:00
|
|
|
typedef struct evp_test_st {
|
2017-06-06 01:32:05 +08:00
|
|
|
STANZA s; /* Common test stanza */
|
|
|
|
char *name;
|
2017-05-13 02:19:51 +08:00
|
|
|
int skip; /* Current test should be skipped */
|
|
|
|
const EVP_TEST_METHOD *meth; /* method for this test */
|
|
|
|
const char *err, *aux_err; /* Error string for test */
|
|
|
|
char *expected_err; /* Expected error value of test */
|
|
|
|
char *reason; /* Expected error reason string */
|
|
|
|
void *data; /* test specific data */
|
2024-07-03 09:12:39 +08:00
|
|
|
int expect_unapproved;
|
2025-05-06 09:32:21 +08:00
|
|
|
int security_category; /* NIST's security category */
|
2025-07-09 10:50:02 +08:00
|
|
|
unsigned char *entropy;
|
|
|
|
size_t entropy_len;
|
2017-05-13 02:19:51 +08:00
|
|
|
} EVP_TEST;
|
2001-08-18 21:53:01 +08:00
|
|
|
|
2020-08-07 12:29:00 +08:00
|
|
|
/* Test method structure */
|
2017-05-13 02:19:51 +08:00
|
|
|
struct evp_test_method_st {
|
|
|
|
/* Name of test as it appears in file */
|
|
|
|
const char *name;
|
|
|
|
/* Initialise test for "alg" */
|
2023-07-17 02:03:40 +08:00
|
|
|
int (*init) (EVP_TEST *t, const char *alg);
|
2017-05-13 02:19:51 +08:00
|
|
|
/* Clean up method */
|
2023-07-17 02:03:40 +08:00
|
|
|
void (*cleanup) (EVP_TEST *t);
|
2017-05-13 02:19:51 +08:00
|
|
|
/* Test specific name value pair processing */
|
2023-07-17 02:03:40 +08:00
|
|
|
int (*parse) (EVP_TEST *t, const char *name, const char *value);
|
2017-05-13 02:19:51 +08:00
|
|
|
/* Run the test itself */
|
2023-07-17 02:03:40 +08:00
|
|
|
int (*run_test) (EVP_TEST *t);
|
2017-05-13 02:19:51 +08:00
|
|
|
};
|
2001-09-05 06:19:06 +08:00
|
|
|
|
2020-08-07 12:29:00 +08:00
|
|
|
/* Linked list of named keys. */
|
2017-05-13 02:19:51 +08:00
|
|
|
typedef struct key_list_st {
|
|
|
|
char *name;
|
|
|
|
EVP_PKEY *key;
|
|
|
|
struct key_list_st *next;
|
|
|
|
} KEY_LIST;
|
2016-10-12 01:26:23 +08:00
|
|
|
|
2020-08-07 12:29:00 +08:00
|
|
|
typedef enum OPTION_choice {
|
|
|
|
OPT_ERR = -1,
|
|
|
|
OPT_EOF = 0,
|
|
|
|
OPT_CONFIG_FILE,
|
2023-07-13 23:07:00 +08:00
|
|
|
OPT_IN_PLACE,
|
2023-09-12 21:24:21 +08:00
|
|
|
OPT_PROVIDER_NAME,
|
2023-09-08 17:44:27 +08:00
|
|
|
OPT_PROV_PROPQUERY,
|
2023-07-27 18:03:47 +08:00
|
|
|
OPT_DATA_CHUNK,
|
2020-08-07 12:29:00 +08:00
|
|
|
OPT_TEST_ENUM
|
|
|
|
} OPTION_CHOICE;
|
|
|
|
|
|
|
|
static OSSL_PROVIDER *prov_null = NULL;
|
2023-09-12 21:24:21 +08:00
|
|
|
static OSSL_PROVIDER *libprov = NULL;
|
2020-10-15 17:55:50 +08:00
|
|
|
static OSSL_LIB_CTX *libctx = NULL;
|
2024-07-03 09:12:39 +08:00
|
|
|
static int fips_indicator_callback_unapproved_count = 0;
|
2025-02-14 06:43:54 +08:00
|
|
|
static int extended_tests = 0;
|
2020-08-07 12:29:00 +08:00
|
|
|
|
|
|
|
/* List of public and private keys */
|
2017-05-13 02:19:51 +08:00
|
|
|
static KEY_LIST *private_keys;
|
|
|
|
static KEY_LIST *public_keys;
|
2016-10-12 01:26:23 +08:00
|
|
|
|
2020-08-07 12:29:00 +08:00
|
|
|
static int find_key(EVP_PKEY **ppk, const char *name, KEY_LIST *lst);
|
2017-05-13 02:19:51 +08:00
|
|
|
static int parse_bin(const char *value, unsigned char **buf, size_t *buflen);
|
2023-07-28 18:35:37 +08:00
|
|
|
static int parse_bin_chunk(const char *value, size_t offset, size_t max,
|
|
|
|
unsigned char **buf, size_t *buflen, size_t *out_offset);
|
2020-08-07 12:29:00 +08:00
|
|
|
static int is_digest_disabled(const char *name);
|
|
|
|
static int is_pkey_disabled(const char *name);
|
|
|
|
static int is_mac_disabled(const char *name);
|
|
|
|
static int is_cipher_disabled(const char *name);
|
|
|
|
static int is_kdf_disabled(const char *name);
|
2015-09-02 21:31:28 +08:00
|
|
|
|
2025-07-09 10:50:02 +08:00
|
|
|
/* Random bit generator */
|
|
|
|
static OSSL_PROVIDER *fake_rand = NULL;
|
|
|
|
static uint8_t *fake_rand_bytes = NULL;
|
|
|
|
static size_t fake_rand_bytes_offset = 0;
|
|
|
|
static size_t fake_rand_size = 0;
|
|
|
|
|
|
|
|
static int get_faked_bytes(unsigned char *buf, size_t num,
|
|
|
|
ossl_unused const char *name,
|
|
|
|
ossl_unused EVP_RAND_CTX *ctx)
|
|
|
|
{
|
|
|
|
if (!TEST_ptr(fake_rand_bytes) || !TEST_size_t_gt(fake_rand_size, 0))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
while (num-- > 0) {
|
|
|
|
if (fake_rand_bytes_offset >= fake_rand_size)
|
|
|
|
fake_rand_bytes_offset = 0;
|
|
|
|
*buf++ = fake_rand_bytes[fake_rand_bytes_offset++];
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2024-07-03 09:12:39 +08:00
|
|
|
/* A callback that is triggered if fips unapproved mode is detected */
|
|
|
|
static int fips_indicator_cb(const char *type, const char *desc,
|
|
|
|
const OSSL_PARAM params[])
|
|
|
|
{
|
|
|
|
fips_indicator_callback_unapproved_count++;
|
|
|
|
TEST_info("(Indicator Callback received %s : %s is not approved)", type, desc);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int check_fips_approved(EVP_TEST *t, int approved)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* If the expected result is approved
|
|
|
|
* then it is expected that approved will be 1
|
|
|
|
* and the fips indicator callback has not been triggered, otherwise
|
|
|
|
* approved should be 0 and the fips indicator callback should be triggered.
|
|
|
|
*/
|
|
|
|
if (t->expect_unapproved) {
|
2024-08-21 15:43:19 +08:00
|
|
|
if (approved == 1 || fips_indicator_callback_unapproved_count == 0) {
|
|
|
|
TEST_error("Test is not expected to be FIPS approved");
|
2024-07-03 09:12:39 +08:00
|
|
|
return 0;
|
2024-08-21 15:43:19 +08:00
|
|
|
}
|
2024-07-03 09:12:39 +08:00
|
|
|
} else {
|
2024-08-21 15:43:19 +08:00
|
|
|
if (approved == 0 || fips_indicator_callback_unapproved_count > 0) {
|
|
|
|
TEST_error("Test is expected to be FIPS approved");
|
2024-07-03 09:12:39 +08:00
|
|
|
return 0;
|
2024-08-21 15:43:19 +08:00
|
|
|
}
|
2024-07-03 09:12:39 +08:00
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2024-07-18 05:59:01 +08:00
|
|
|
static int mac_check_fips_approved(EVP_MAC_CTX *ctx, EVP_TEST *t)
|
|
|
|
{
|
|
|
|
OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
|
|
|
|
/*
|
|
|
|
* For any getters that do not handle the FIPS indicator assume a default
|
|
|
|
* value of approved.
|
|
|
|
*/
|
|
|
|
int approved = 1;
|
|
|
|
|
2024-08-06 06:40:38 +08:00
|
|
|
if (EVP_MAC_CTX_gettable_params(ctx) == NULL)
|
|
|
|
return 1;
|
|
|
|
|
2024-07-18 05:59:01 +08:00
|
|
|
params[0] = OSSL_PARAM_construct_int(OSSL_MAC_PARAM_FIPS_APPROVED_INDICATOR,
|
|
|
|
&approved);
|
|
|
|
if (!EVP_MAC_CTX_get_params(ctx, params))
|
|
|
|
return 0;
|
|
|
|
return check_fips_approved(t, approved);
|
|
|
|
}
|
|
|
|
|
2024-07-03 09:12:39 +08:00
|
|
|
static int pkey_check_fips_approved(EVP_PKEY_CTX *ctx, EVP_TEST *t)
|
|
|
|
{
|
|
|
|
OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
|
|
|
|
/*
|
|
|
|
* For any getters that do not handle the FIPS indicator assume a default
|
|
|
|
* value of approved.
|
|
|
|
*/
|
|
|
|
int approved = 1;
|
2024-07-24 15:24:33 +08:00
|
|
|
const OSSL_PARAM *gettables = EVP_PKEY_CTX_gettable_params(ctx);
|
|
|
|
|
|
|
|
if (gettables == NULL
|
|
|
|
|| OSSL_PARAM_locate_const(gettables,
|
|
|
|
OSSL_ALG_PARAM_FIPS_APPROVED_INDICATOR)
|
|
|
|
== NULL)
|
|
|
|
return 1;
|
2024-07-03 09:12:39 +08:00
|
|
|
|
2024-08-06 06:40:38 +08:00
|
|
|
/* Older providers dont have a gettable */
|
|
|
|
if (EVP_PKEY_CTX_gettable_params(ctx) == NULL)
|
|
|
|
return 1;
|
|
|
|
|
2024-07-03 09:12:39 +08:00
|
|
|
params[0] = OSSL_PARAM_construct_int(OSSL_ALG_PARAM_FIPS_APPROVED_INDICATOR,
|
|
|
|
&approved);
|
|
|
|
if (!EVP_PKEY_CTX_get_params(ctx, params))
|
|
|
|
return 0;
|
|
|
|
return check_fips_approved(t, approved);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int rand_check_fips_approved(EVP_RAND_CTX *ctx, EVP_TEST *t)
|
|
|
|
{
|
|
|
|
OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
|
|
|
|
/*
|
|
|
|
* For any getters that do not handle the FIPS indicator assume a default
|
|
|
|
* value of approved.
|
|
|
|
*/
|
|
|
|
int approved = 1;
|
|
|
|
|
2024-08-06 06:40:38 +08:00
|
|
|
if (EVP_RAND_CTX_gettable_params(ctx) == NULL)
|
|
|
|
return 1;
|
|
|
|
|
2024-07-03 09:12:39 +08:00
|
|
|
params[0] = OSSL_PARAM_construct_int(OSSL_DRBG_PARAM_FIPS_APPROVED_INDICATOR,
|
|
|
|
&approved);
|
|
|
|
if (!EVP_RAND_CTX_get_params(ctx, params))
|
|
|
|
return 0;
|
|
|
|
return check_fips_approved(t, approved);
|
|
|
|
}
|
|
|
|
|
2025-05-06 09:32:21 +08:00
|
|
|
static int check_security_category(EVP_TEST *t, void *alg_obj,
|
|
|
|
int (*get_param)(void *, OSSL_PARAM *)) {
|
|
|
|
OSSL_PARAM p[2];
|
|
|
|
int security_category = -1;
|
|
|
|
|
|
|
|
if (t->security_category < 0)
|
|
|
|
return 1;
|
|
|
|
p[0] = OSSL_PARAM_construct_int(OSSL_ALG_PARAM_SECURITY_CATEGORY,
|
|
|
|
&security_category);
|
|
|
|
p[1] = OSSL_PARAM_construct_end();
|
|
|
|
if (!TEST_int_gt(get_param(alg_obj, p), 0)
|
|
|
|
|| !TEST_true(OSSL_PARAM_modified(p))
|
|
|
|
|| !TEST_int_eq(security_category, t->security_category)) {
|
|
|
|
t->err = "INCORRECT_SECURITY_CATEGORY";
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int pkey_check_security_category(EVP_TEST *t, EVP_PKEY *pkey) {
|
|
|
|
return check_security_category(t, pkey,
|
|
|
|
(int (*)(void *, OSSL_PARAM *))EVP_PKEY_get_params);
|
|
|
|
}
|
|
|
|
|
2024-07-03 09:12:39 +08:00
|
|
|
static int ctrladd(STACK_OF(OPENSSL_STRING) *controls, const char *value)
|
|
|
|
{
|
|
|
|
char *data = OPENSSL_strdup(value);
|
|
|
|
|
|
|
|
if (data == NULL)
|
|
|
|
return -1;
|
2024-12-20 22:45:53 +08:00
|
|
|
|
|
|
|
if (sk_OPENSSL_STRING_push(controls, data) <= 0) {
|
|
|
|
OPENSSL_free(data);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
2024-07-03 09:12:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Because OPENSSL_free is a macro, it can't be passed as a function pointer */
|
|
|
|
static void openssl_free(char *m)
|
|
|
|
{
|
|
|
|
OPENSSL_free(m);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ctrlfree(STACK_OF(OPENSSL_STRING) *controls)
|
|
|
|
{
|
|
|
|
sk_OPENSSL_STRING_pop_free(controls, openssl_free);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This is used if ctrl2params() passes settables as NULL.
|
|
|
|
* A default list of settable OSSL_PARAM that may be set during an operations
|
|
|
|
* init().
|
|
|
|
* Using the algorithms settable list is problematic since it requires that the
|
|
|
|
* init() has already run.
|
|
|
|
*/
|
|
|
|
static const OSSL_PARAM settable_ctx_params[] = {
|
|
|
|
OSSL_PARAM_int("key-check", NULL),
|
|
|
|
OSSL_PARAM_int("digest-check", NULL),
|
|
|
|
OSSL_PARAM_int("ems_check", NULL),
|
2024-07-04 09:59:43 +08:00
|
|
|
OSSL_PARAM_int("sign-check", NULL),
|
2024-07-22 15:24:53 +08:00
|
|
|
OSSL_PARAM_int("encrypt-check", NULL),
|
2024-08-07 10:24:36 +08:00
|
|
|
OSSL_PARAM_int("rsa-pss-saltlen-check", NULL),
|
2024-07-29 08:16:30 +08:00
|
|
|
OSSL_PARAM_int("sign-x931-pad-check", NULL),
|
2024-07-03 09:12:39 +08:00
|
|
|
OSSL_PARAM_END
|
|
|
|
};
|
|
|
|
|
|
|
|
static int ctrl2params(EVP_TEST *t, STACK_OF(OPENSSL_STRING) *controls,
|
|
|
|
const OSSL_PARAM *settables,
|
|
|
|
OSSL_PARAM params[], size_t params_sz, size_t *params_n)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (settables == NULL)
|
|
|
|
settables = settable_ctx_params;
|
|
|
|
/* check bounds */
|
|
|
|
if (*params_n + sk_OPENSSL_STRING_num(controls) >= params_sz) {
|
|
|
|
t->err = "ERR_TOO_MANY_PARAMETERS";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
for (i = 0; i < sk_OPENSSL_STRING_num(controls); i++) {
|
|
|
|
char *tmpkey, *tmpval;
|
|
|
|
char *value = sk_OPENSSL_STRING_value(controls, i);
|
|
|
|
|
|
|
|
if (!TEST_ptr(tmpkey = OPENSSL_strdup(value))) {
|
|
|
|
t->err = "ERR_PARAM_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
tmpval = strchr(tmpkey, ':');
|
|
|
|
if (tmpval != NULL)
|
|
|
|
*tmpval++ = '\0';
|
|
|
|
|
|
|
|
if (tmpval == NULL
|
|
|
|
|| !OSSL_PARAM_allocate_from_text(¶ms[*params_n],
|
|
|
|
settables,
|
|
|
|
tmpkey, tmpval,
|
|
|
|
strlen(tmpval), NULL)) {
|
|
|
|
OPENSSL_free(tmpkey);
|
|
|
|
t->err = "ERR_PARAM_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
*params_n += 1;
|
|
|
|
OPENSSL_free(tmpkey);
|
|
|
|
}
|
|
|
|
params[*params_n] = OSSL_PARAM_construct_end();
|
|
|
|
return 1;
|
|
|
|
err:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ctrl2params_free(OSSL_PARAM params[],
|
|
|
|
size_t params_n, size_t params_n_allocstart)
|
|
|
|
{
|
|
|
|
while (params_n-- > params_n_allocstart) {
|
|
|
|
OPENSSL_free(params[params_n].data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int kdf_check_fips_approved(EVP_KDF_CTX *ctx, EVP_TEST *t)
|
|
|
|
{
|
|
|
|
OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
|
|
|
|
int approved = 1;
|
|
|
|
|
|
|
|
params[0] = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_FIPS_APPROVED_INDICATOR,
|
|
|
|
&approved);
|
|
|
|
if (!EVP_KDF_CTX_get_params(ctx, params))
|
|
|
|
return 0;
|
|
|
|
return check_fips_approved(t, approved);
|
|
|
|
}
|
|
|
|
|
2024-07-22 15:24:53 +08:00
|
|
|
static int cipher_check_fips_approved(EVP_CIPHER_CTX *ctx, EVP_TEST *t)
|
|
|
|
{
|
|
|
|
OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
|
|
|
|
int approved = 1;
|
|
|
|
|
|
|
|
params[0] = OSSL_PARAM_construct_int(OSSL_CIPHER_PARAM_FIPS_APPROVED_INDICATOR,
|
|
|
|
&approved);
|
|
|
|
if (!EVP_CIPHER_CTX_get_params(ctx, params))
|
|
|
|
return 0;
|
|
|
|
return check_fips_approved(t, approved);
|
|
|
|
}
|
|
|
|
|
2018-08-09 07:27:42 +08:00
|
|
|
/*
|
|
|
|
* Compare two memory regions for equality, returning zero if they differ.
|
|
|
|
* However, if there is expected to be an error and the actual error
|
|
|
|
* matches then the memory is expected to be different so handle this
|
|
|
|
* case without producing unnecessary test framework output.
|
|
|
|
*/
|
|
|
|
static int memory_err_compare(EVP_TEST *t, const char *err,
|
|
|
|
const void *expected, size_t expected_len,
|
|
|
|
const void *got, size_t got_len)
|
|
|
|
{
|
|
|
|
int r;
|
|
|
|
|
|
|
|
if (t->expected_err != NULL && strcmp(t->expected_err, err) == 0)
|
|
|
|
r = !TEST_mem_ne(expected, expected_len, got, got_len);
|
|
|
|
else
|
|
|
|
r = TEST_mem_eq(expected, expected_len, got, got_len);
|
|
|
|
if (!r)
|
|
|
|
t->err = err;
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2023-07-13 23:07:00 +08:00
|
|
|
/* Option specific for evp test */
|
|
|
|
static int process_mode_in_place;
|
2023-09-08 17:44:27 +08:00
|
|
|
static const char *propquery = NULL;
|
2023-07-27 18:03:47 +08:00
|
|
|
static int data_chunk_size;
|
2023-07-13 23:07:00 +08:00
|
|
|
|
|
|
|
static int evp_test_process_mode(char *mode)
|
|
|
|
{
|
|
|
|
if (strcmp(mode, "in_place") == 0)
|
|
|
|
return 1;
|
|
|
|
else if (strcmp(mode, "both") == 0)
|
|
|
|
return 0;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2017-05-12 02:28:09 +08:00
|
|
|
/*
|
|
|
|
* Structure used to hold a list of blocks of memory to test
|
|
|
|
* calls to "update" like functions.
|
|
|
|
*/
|
|
|
|
struct evp_test_buffer_st {
|
|
|
|
unsigned char *buf;
|
|
|
|
size_t buflen;
|
|
|
|
size_t count;
|
|
|
|
int count_set;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void evp_test_buffer_free(EVP_TEST_BUFFER *db)
|
|
|
|
{
|
|
|
|
if (db != NULL) {
|
|
|
|
OPENSSL_free(db->buf);
|
|
|
|
OPENSSL_free(db);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-07 12:29:00 +08:00
|
|
|
/* append buffer to a list */
|
2023-07-28 18:35:37 +08:00
|
|
|
static int evp_test_buffer_append(const char *value, size_t max_len,
|
2017-05-12 02:28:09 +08:00
|
|
|
STACK_OF(EVP_TEST_BUFFER) **sk)
|
|
|
|
{
|
|
|
|
EVP_TEST_BUFFER *db = NULL;
|
2023-07-28 18:35:37 +08:00
|
|
|
int rv = 0;
|
|
|
|
size_t offset = 0;
|
2017-05-12 02:28:09 +08:00
|
|
|
|
2023-07-28 18:35:37 +08:00
|
|
|
if (*sk == NULL && !TEST_ptr(*sk = sk_EVP_TEST_BUFFER_new_null()))
|
2017-05-12 02:28:09 +08:00
|
|
|
goto err;
|
|
|
|
|
2023-07-28 18:35:37 +08:00
|
|
|
do {
|
|
|
|
if (!TEST_ptr(db = OPENSSL_zalloc(sizeof(*db))))
|
|
|
|
goto err;
|
|
|
|
if (max_len == 0) {
|
|
|
|
/* parse all in one shot */
|
|
|
|
if ((rv = parse_bin(value, &db->buf, &db->buflen)) != 1)
|
|
|
|
goto err;
|
|
|
|
} else {
|
|
|
|
/* parse in chunks */
|
|
|
|
size_t new_offset = 0;
|
2017-05-12 02:28:09 +08:00
|
|
|
|
2023-07-28 18:35:37 +08:00
|
|
|
if ((rv = parse_bin_chunk(value, offset, max_len, &db->buf,
|
|
|
|
&db->buflen, &new_offset)) == -1)
|
|
|
|
goto err;
|
|
|
|
offset = new_offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
db->count = 1;
|
|
|
|
db->count_set = 0;
|
|
|
|
|
|
|
|
if (db->buf == NULL)
|
|
|
|
evp_test_buffer_free(db);
|
|
|
|
else if (db->buf != NULL && !sk_EVP_TEST_BUFFER_push(*sk, db))
|
|
|
|
goto err;
|
|
|
|
/* if processing by chunks, continue until the whole value is parsed */
|
|
|
|
} while (rv == 1 && max_len != 0);
|
2017-05-12 02:28:09 +08:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
2017-05-13 02:19:51 +08:00
|
|
|
err:
|
2017-05-12 02:28:09 +08:00
|
|
|
evp_test_buffer_free(db);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-08-07 12:29:00 +08:00
|
|
|
/* replace last buffer in list with copies of itself */
|
2017-05-12 02:28:09 +08:00
|
|
|
static int evp_test_buffer_ncopy(const char *value,
|
|
|
|
STACK_OF(EVP_TEST_BUFFER) *sk)
|
|
|
|
{
|
|
|
|
EVP_TEST_BUFFER *db;
|
|
|
|
unsigned char *tbuf, *p;
|
|
|
|
size_t tbuflen;
|
|
|
|
int ncopy = atoi(value);
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (ncopy <= 0)
|
|
|
|
return 0;
|
|
|
|
if (sk == NULL || sk_EVP_TEST_BUFFER_num(sk) == 0)
|
|
|
|
return 0;
|
|
|
|
db = sk_EVP_TEST_BUFFER_value(sk, sk_EVP_TEST_BUFFER_num(sk) - 1);
|
|
|
|
|
|
|
|
tbuflen = db->buflen * ncopy;
|
|
|
|
if (!TEST_ptr(tbuf = OPENSSL_malloc(tbuflen)))
|
|
|
|
return 0;
|
|
|
|
for (i = 0, p = tbuf; i < ncopy; i++, p += db->buflen)
|
|
|
|
memcpy(p, db->buf, db->buflen);
|
|
|
|
|
|
|
|
OPENSSL_free(db->buf);
|
|
|
|
db->buf = tbuf;
|
|
|
|
db->buflen = tbuflen;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2020-08-07 12:29:00 +08:00
|
|
|
/* set repeat count for last buffer in list */
|
2017-05-12 02:28:09 +08:00
|
|
|
static int evp_test_buffer_set_count(const char *value,
|
|
|
|
STACK_OF(EVP_TEST_BUFFER) *sk)
|
|
|
|
{
|
|
|
|
EVP_TEST_BUFFER *db;
|
|
|
|
int count = atoi(value);
|
|
|
|
|
|
|
|
if (count <= 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (sk == NULL || sk_EVP_TEST_BUFFER_num(sk) == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
db = sk_EVP_TEST_BUFFER_value(sk, sk_EVP_TEST_BUFFER_num(sk) - 1);
|
2017-05-13 02:19:51 +08:00
|
|
|
if (db->count_set != 0)
|
2017-05-12 02:28:09 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
db->count = (size_t)count;
|
|
|
|
db->count_set = 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2020-08-07 12:29:00 +08:00
|
|
|
/* call "fn" with each element of the list in turn */
|
2017-05-12 02:28:09 +08:00
|
|
|
static int evp_test_buffer_do(STACK_OF(EVP_TEST_BUFFER) *sk,
|
|
|
|
int (*fn)(void *ctx,
|
|
|
|
const unsigned char *buf,
|
|
|
|
size_t buflen),
|
|
|
|
void *ctx)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < sk_EVP_TEST_BUFFER_num(sk); i++) {
|
|
|
|
EVP_TEST_BUFFER *tb = sk_EVP_TEST_BUFFER_value(sk, i);
|
|
|
|
size_t j;
|
|
|
|
|
|
|
|
for (j = 0; j < tb->count; j++) {
|
|
|
|
if (fn(ctx, tb->buf, tb->buflen) <= 0)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
/*
|
2017-05-13 02:19:51 +08:00
|
|
|
* Unescape some sequences in string literals (only \n for now).
|
|
|
|
* Return an allocated buffer, set |out_len|. If |input_len|
|
|
|
|
* is zero, get an empty buffer but set length to zero.
|
2017-04-27 03:33:43 +08:00
|
|
|
*/
|
2017-05-13 02:19:51 +08:00
|
|
|
static unsigned char* unescape(const char *input, size_t input_len,
|
|
|
|
size_t *out_len)
|
|
|
|
{
|
|
|
|
unsigned char *ret, *p;
|
|
|
|
size_t i;
|
2015-02-12 01:15:51 +08:00
|
|
|
|
2017-05-13 02:19:51 +08:00
|
|
|
if (input_len == 0) {
|
|
|
|
*out_len = 0;
|
|
|
|
return OPENSSL_zalloc(1);
|
|
|
|
}
|
2015-02-10 01:29:47 +08:00
|
|
|
|
2017-05-13 02:19:51 +08:00
|
|
|
/* Escaping is non-expanding; over-allocate original size for simplicity. */
|
|
|
|
if (!TEST_ptr(ret = p = OPENSSL_malloc(input_len)))
|
|
|
|
return NULL;
|
2017-04-27 03:33:43 +08:00
|
|
|
|
2017-05-13 02:19:51 +08:00
|
|
|
for (i = 0; i < input_len; i++) {
|
|
|
|
if (*input == '\\') {
|
|
|
|
if (i == input_len - 1 || *++input != 'n') {
|
|
|
|
TEST_error("Bad escape sequence in file");
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
*p++ = '\n';
|
|
|
|
i++;
|
|
|
|
input++;
|
|
|
|
} else {
|
|
|
|
*p++ = *input++;
|
|
|
|
}
|
|
|
|
}
|
2015-02-10 01:29:47 +08:00
|
|
|
|
2017-05-13 02:19:51 +08:00
|
|
|
*out_len = p - ret;
|
|
|
|
return ret;
|
2015-05-07 02:56:14 +08:00
|
|
|
|
2017-05-13 02:19:51 +08:00
|
|
|
err:
|
|
|
|
OPENSSL_free(ret);
|
2015-02-10 01:29:47 +08:00
|
|
|
return NULL;
|
2014-06-30 20:26:28 +08:00
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
/*
|
2017-05-13 02:19:51 +08:00
|
|
|
* For a hex string "value" convert to a binary allocated buffer.
|
|
|
|
* Return 1 on success or 0 on failure.
|
2017-04-27 03:33:43 +08:00
|
|
|
*/
|
2017-05-13 02:19:51 +08:00
|
|
|
static int parse_bin(const char *value, unsigned char **buf, size_t *buflen)
|
2001-08-18 21:53:01 +08:00
|
|
|
{
|
2017-05-13 02:19:51 +08:00
|
|
|
long len;
|
2017-04-27 03:33:43 +08:00
|
|
|
|
2017-05-13 02:19:51 +08:00
|
|
|
/* Check for NULL literal */
|
|
|
|
if (strcmp(value, "NULL") == 0) {
|
|
|
|
*buf = NULL;
|
|
|
|
*buflen = 0;
|
2015-02-10 01:29:47 +08:00
|
|
|
return 1;
|
2017-01-06 03:27:41 +08:00
|
|
|
}
|
2017-04-27 03:33:43 +08:00
|
|
|
|
2017-05-13 02:19:51 +08:00
|
|
|
/* Check for empty value */
|
|
|
|
if (*value == '\0') {
|
|
|
|
/*
|
|
|
|
* Don't return NULL for zero length buffer. This is needed for
|
|
|
|
* some tests with empty keys: HMAC_Init_ex() expects a non-NULL key
|
|
|
|
* buffer even if the key length is 0, in order to detect key reset.
|
|
|
|
*/
|
|
|
|
*buf = OPENSSL_malloc(1);
|
|
|
|
if (*buf == NULL)
|
2015-02-12 01:15:51 +08:00
|
|
|
return 0;
|
2017-05-13 02:19:51 +08:00
|
|
|
**buf = 0;
|
|
|
|
*buflen = 0;
|
2017-01-06 03:27:41 +08:00
|
|
|
return 1;
|
2015-02-12 01:15:51 +08:00
|
|
|
}
|
|
|
|
|
2017-05-13 02:19:51 +08:00
|
|
|
/* Check for string literal */
|
|
|
|
if (value[0] == '"') {
|
|
|
|
size_t vlen = strlen(++value);
|
|
|
|
|
|
|
|
if (vlen == 0 || value[vlen - 1] != '"')
|
2015-02-10 01:29:47 +08:00
|
|
|
return 0;
|
2017-05-13 02:19:51 +08:00
|
|
|
vlen--;
|
|
|
|
*buf = unescape(value, vlen, buflen);
|
|
|
|
return *buf == NULL ? 0 : 1;
|
2017-04-27 03:33:43 +08:00
|
|
|
}
|
2015-02-10 01:29:47 +08:00
|
|
|
|
2017-05-13 02:19:51 +08:00
|
|
|
/* Otherwise assume as hex literal and convert it to binary buffer */
|
|
|
|
if (!TEST_ptr(*buf = OPENSSL_hexstr2buf(value, &len))) {
|
|
|
|
TEST_info("Can't convert %s", value);
|
2017-06-19 09:21:22 +08:00
|
|
|
TEST_openssl_errors();
|
2017-05-13 02:19:51 +08:00
|
|
|
return -1;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2017-05-13 02:19:51 +08:00
|
|
|
/* Size of input buffer means we'll never overflow */
|
|
|
|
*buflen = len;
|
2015-02-10 01:29:47 +08:00
|
|
|
return 1;
|
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2023-07-28 18:35:37 +08:00
|
|
|
/*
|
|
|
|
* Convert at maximum "max" bytes to a binary allocated buffer.
|
|
|
|
* Return 1 on success, -1 on failure or 0 for end of value string.
|
|
|
|
*/
|
|
|
|
static int parse_bin_chunk(const char *value, size_t offset, size_t max,
|
|
|
|
unsigned char **buf, size_t *buflen, size_t *out_offset)
|
|
|
|
{
|
|
|
|
size_t vlen;
|
|
|
|
size_t chunk_len;
|
|
|
|
const char *value_str = value[0] == '"' ? value + offset + 1 : value + offset;
|
|
|
|
|
|
|
|
if (max < 1)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (*value == '\0' || strcmp(value, "\"\"") == 0) {
|
|
|
|
*buf = OPENSSL_malloc(1);
|
|
|
|
if (*buf == NULL)
|
|
|
|
return 0;
|
|
|
|
**buf = 0;
|
|
|
|
*buflen = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*value_str == '\0')
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
vlen = strlen(value_str);
|
|
|
|
if (value[0] == '"') {
|
|
|
|
/* Parse string literal */
|
|
|
|
if (vlen == 1 && value_str[0] != '"')
|
|
|
|
/* Missing ending quotation mark */
|
|
|
|
return -1;
|
|
|
|
if (vlen == 1 && value_str[0] == '"')
|
|
|
|
/* End of value */
|
|
|
|
return 0;
|
|
|
|
vlen--;
|
|
|
|
chunk_len = max > vlen ? vlen : max;
|
|
|
|
if ((*buf = unescape(value_str, chunk_len, buflen)) == NULL)
|
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
/* Parse hex string chunk */
|
|
|
|
long len;
|
|
|
|
char *chunk = NULL;
|
|
|
|
|
|
|
|
chunk_len = 2 * max > vlen ? vlen : 2 * max;
|
|
|
|
chunk = OPENSSL_strndup(value_str, chunk_len);
|
|
|
|
if (chunk == NULL)
|
|
|
|
return -1;
|
|
|
|
if (!TEST_ptr(*buf = OPENSSL_hexstr2buf(chunk, &len))) {
|
|
|
|
OPENSSL_free(chunk);
|
|
|
|
TEST_openssl_errors();
|
|
|
|
return -1;
|
|
|
|
}
|
2024-05-07 02:13:52 +08:00
|
|
|
OPENSSL_free(chunk);
|
2023-07-28 18:35:37 +08:00
|
|
|
*buflen = len;
|
|
|
|
}
|
|
|
|
*out_offset = value[0] == '"' ? offset + (*buflen) : offset + 2 * (*buflen);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-05-13 02:19:51 +08:00
|
|
|
/**
|
2020-08-07 12:29:00 +08:00
|
|
|
** MESSAGE DIGEST TESTS
|
|
|
|
**/
|
2001-08-27 01:09:31 +08:00
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
typedef struct digest_data_st {
|
2015-02-10 01:29:47 +08:00
|
|
|
/* Digest this test is for */
|
|
|
|
const EVP_MD *digest;
|
2019-06-07 16:52:25 +08:00
|
|
|
EVP_MD *fetched_digest;
|
2015-02-10 01:29:47 +08:00
|
|
|
/* Input to digest */
|
2017-05-12 02:28:09 +08:00
|
|
|
STACK_OF(EVP_TEST_BUFFER) *input;
|
2015-02-10 01:29:47 +08:00
|
|
|
/* Expected output */
|
|
|
|
unsigned char *output;
|
|
|
|
size_t output_len;
|
2020-01-14 06:01:34 +08:00
|
|
|
/* Padding type */
|
|
|
|
int pad_type;
|
2022-11-30 03:20:09 +08:00
|
|
|
/* XOF mode? */
|
|
|
|
int xof;
|
2023-10-24 19:44:26 +08:00
|
|
|
/* Size for variable output length but non-XOF */
|
|
|
|
size_t digest_size;
|
2017-04-27 03:33:43 +08:00
|
|
|
} DIGEST_DATA;
|
2001-08-27 01:09:31 +08:00
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static int digest_test_init(EVP_TEST *t, const char *alg)
|
2015-02-10 01:29:47 +08:00
|
|
|
{
|
2017-04-27 03:33:43 +08:00
|
|
|
DIGEST_DATA *mdat;
|
2017-05-13 02:19:51 +08:00
|
|
|
const EVP_MD *digest;
|
2019-06-07 16:52:25 +08:00
|
|
|
EVP_MD *fetched_digest;
|
2017-04-27 03:33:43 +08:00
|
|
|
|
2020-08-07 12:29:00 +08:00
|
|
|
if (is_digest_disabled(alg)) {
|
|
|
|
TEST_info("skipping, '%s' is disabled", alg);
|
|
|
|
t->skip = 1;
|
|
|
|
return 1;
|
2015-02-27 03:58:20 +08:00
|
|
|
}
|
2020-08-07 12:29:00 +08:00
|
|
|
|
2023-09-08 17:44:27 +08:00
|
|
|
if ((digest = fetched_digest = EVP_MD_fetch(libctx, alg, propquery)) == NULL
|
2020-08-07 12:29:00 +08:00
|
|
|
&& (digest = EVP_get_digestbyname(alg)) == NULL)
|
|
|
|
return 0;
|
2025-05-17 08:20:47 +08:00
|
|
|
if (!TEST_ptr(mdat = OPENSSL_zalloc(sizeof(*mdat)))) {
|
|
|
|
EVP_MD_free(fetched_digest);
|
2017-05-13 02:19:51 +08:00
|
|
|
return 0;
|
2025-05-17 08:20:47 +08:00
|
|
|
}
|
2015-02-10 01:29:47 +08:00
|
|
|
t->data = mdat;
|
2017-05-13 02:19:51 +08:00
|
|
|
mdat->digest = digest;
|
2019-06-07 16:52:25 +08:00
|
|
|
mdat->fetched_digest = fetched_digest;
|
2020-01-14 06:01:34 +08:00
|
|
|
mdat->pad_type = 0;
|
2022-11-30 03:20:09 +08:00
|
|
|
mdat->xof = 0;
|
2019-06-07 16:52:25 +08:00
|
|
|
if (fetched_digest != NULL)
|
|
|
|
TEST_info("%s is fetched", alg);
|
2001-08-27 01:09:31 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static void digest_test_cleanup(EVP_TEST *t)
|
2015-02-10 01:29:47 +08:00
|
|
|
{
|
2017-04-27 03:33:43 +08:00
|
|
|
DIGEST_DATA *mdat = t->data;
|
|
|
|
|
2017-05-12 02:28:09 +08:00
|
|
|
sk_EVP_TEST_BUFFER_pop_free(mdat->input, evp_test_buffer_free);
|
2017-04-27 03:33:43 +08:00
|
|
|
OPENSSL_free(mdat->output);
|
2020-04-22 08:24:05 +08:00
|
|
|
EVP_MD_free(mdat->fetched_digest);
|
2015-02-10 01:29:47 +08:00
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static int digest_test_parse(EVP_TEST *t,
|
2015-02-10 01:29:47 +08:00
|
|
|
const char *keyword, const char *value)
|
|
|
|
{
|
2017-04-27 03:33:43 +08:00
|
|
|
DIGEST_DATA *mdata = t->data;
|
|
|
|
|
2015-05-07 02:56:14 +08:00
|
|
|
if (strcmp(keyword, "Input") == 0)
|
2023-07-28 18:35:37 +08:00
|
|
|
return evp_test_buffer_append(value, data_chunk_size, &mdata->input);
|
2015-05-07 02:56:14 +08:00
|
|
|
if (strcmp(keyword, "Output") == 0)
|
2017-05-13 02:19:51 +08:00
|
|
|
return parse_bin(value, &mdata->output, &mdata->output_len);
|
2017-05-12 02:28:09 +08:00
|
|
|
if (strcmp(keyword, "Count") == 0)
|
|
|
|
return evp_test_buffer_set_count(value, mdata->input);
|
|
|
|
if (strcmp(keyword, "Ncopy") == 0)
|
|
|
|
return evp_test_buffer_ncopy(value, mdata->input);
|
2020-01-14 06:01:34 +08:00
|
|
|
if (strcmp(keyword, "Padding") == 0)
|
|
|
|
return (mdata->pad_type = atoi(value)) > 0;
|
2022-11-30 03:20:09 +08:00
|
|
|
if (strcmp(keyword, "XOF") == 0)
|
|
|
|
return (mdata->xof = atoi(value)) > 0;
|
2023-10-24 19:44:26 +08:00
|
|
|
if (strcmp(keyword, "OutputSize") == 0) {
|
|
|
|
int sz;
|
|
|
|
|
|
|
|
sz = atoi(value);
|
|
|
|
if (sz < 0)
|
|
|
|
return -1;
|
|
|
|
mdata->digest_size = sz;
|
|
|
|
return 1;
|
|
|
|
}
|
2015-02-10 01:29:47 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-05-12 02:28:09 +08:00
|
|
|
static int digest_update_fn(void *ctx, const unsigned char *buf, size_t buflen)
|
|
|
|
{
|
|
|
|
return EVP_DigestUpdate(ctx, buf, buflen);
|
|
|
|
}
|
|
|
|
|
2022-01-07 08:47:20 +08:00
|
|
|
static int test_duplicate_md_ctx(EVP_TEST *t, EVP_MD_CTX *mctx)
|
|
|
|
{
|
|
|
|
char dont[] = "touch";
|
|
|
|
|
|
|
|
if (!TEST_ptr(mctx))
|
|
|
|
return 0;
|
|
|
|
if (!EVP_DigestFinalXOF(mctx, (unsigned char *)dont, 0)) {
|
|
|
|
EVP_MD_CTX_free(mctx);
|
|
|
|
t->err = "DIGESTFINALXOF_ERROR";
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (!TEST_str_eq(dont, "touch")) {
|
|
|
|
EVP_MD_CTX_free(mctx);
|
|
|
|
t->err = "DIGESTFINALXOF_ERROR";
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
EVP_MD_CTX_free(mctx);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static int digest_test_run(EVP_TEST *t)
|
2001-08-27 01:09:31 +08:00
|
|
|
{
|
2017-05-25 19:48:32 +08:00
|
|
|
DIGEST_DATA *expected = t->data;
|
2021-06-24 09:32:50 +08:00
|
|
|
EVP_TEST_BUFFER *inbuf;
|
2015-02-10 01:29:47 +08:00
|
|
|
EVP_MD_CTX *mctx;
|
2017-08-11 04:39:40 +08:00
|
|
|
unsigned char *got = NULL;
|
2017-05-25 19:48:32 +08:00
|
|
|
unsigned int got_len;
|
2021-06-24 09:47:48 +08:00
|
|
|
size_t size = 0;
|
2021-06-24 09:32:50 +08:00
|
|
|
int xof = 0;
|
2023-10-26 15:59:22 +08:00
|
|
|
OSSL_PARAM params[4], *p = ¶ms[0];
|
2017-04-27 03:33:43 +08:00
|
|
|
|
|
|
|
t->err = "TEST_FAILURE";
|
|
|
|
if (!TEST_ptr(mctx = EVP_MD_CTX_new()))
|
2015-02-10 01:29:47 +08:00
|
|
|
goto err;
|
2017-04-27 03:33:43 +08:00
|
|
|
|
2017-08-11 04:39:40 +08:00
|
|
|
got = OPENSSL_malloc(expected->output_len > EVP_MAX_MD_SIZE ?
|
|
|
|
expected->output_len : EVP_MAX_MD_SIZE);
|
|
|
|
if (!TEST_ptr(got))
|
|
|
|
goto err;
|
|
|
|
|
2022-11-30 03:20:09 +08:00
|
|
|
if (expected->xof > 0) {
|
|
|
|
xof |= 1;
|
|
|
|
*p++ = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_XOFLEN,
|
|
|
|
&expected->output_len);
|
|
|
|
}
|
2023-10-24 19:44:26 +08:00
|
|
|
if (expected->digest_size > 0) {
|
|
|
|
*p++ = OSSL_PARAM_construct_size_t(OSSL_DIGEST_PARAM_SIZE,
|
|
|
|
&expected->digest_size);
|
|
|
|
}
|
2022-11-30 03:20:09 +08:00
|
|
|
if (expected->pad_type > 0)
|
|
|
|
*p++ = OSSL_PARAM_construct_int(OSSL_DIGEST_PARAM_PAD_TYPE,
|
|
|
|
&expected->pad_type);
|
|
|
|
*p++ = OSSL_PARAM_construct_end();
|
|
|
|
|
|
|
|
if (!EVP_DigestInit_ex2(mctx, expected->digest, params)) {
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "DIGESTINIT_ERROR";
|
2015-02-10 01:29:47 +08:00
|
|
|
goto err;
|
2015-03-01 23:38:56 +08:00
|
|
|
}
|
2022-11-30 03:20:09 +08:00
|
|
|
|
2017-05-25 19:48:32 +08:00
|
|
|
if (!evp_test_buffer_do(expected->input, digest_update_fn, mctx)) {
|
2017-05-12 02:28:09 +08:00
|
|
|
t->err = "DIGESTUPDATE_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2024-08-26 09:14:55 +08:00
|
|
|
xof |= EVP_MD_xof(expected->digest);
|
2021-06-24 09:32:50 +08:00
|
|
|
if (xof) {
|
2019-08-05 22:56:14 +08:00
|
|
|
EVP_MD_CTX *mctx_cpy;
|
|
|
|
|
|
|
|
if (!TEST_ptr(mctx_cpy = EVP_MD_CTX_new())) {
|
|
|
|
goto err;
|
|
|
|
}
|
2022-01-07 08:47:20 +08:00
|
|
|
if (!TEST_true(EVP_MD_CTX_copy(mctx_cpy, mctx))) {
|
2019-08-05 22:56:14 +08:00
|
|
|
EVP_MD_CTX_free(mctx_cpy);
|
|
|
|
goto err;
|
2022-01-07 08:47:20 +08:00
|
|
|
} else if (!test_duplicate_md_ctx(t, mctx_cpy)) {
|
2019-08-05 22:56:14 +08:00
|
|
|
goto err;
|
|
|
|
}
|
2022-01-07 08:47:20 +08:00
|
|
|
|
|
|
|
if (!test_duplicate_md_ctx(t, EVP_MD_CTX_dup(mctx)))
|
2019-08-05 22:56:14 +08:00
|
|
|
goto err;
|
|
|
|
|
2025-06-18 17:59:04 +08:00
|
|
|
got_len = (unsigned int)expected->output_len;
|
|
|
|
if (!EVP_DigestFinalXOF(mctx, got, expected->output_len)) {
|
2017-08-11 04:39:40 +08:00
|
|
|
t->err = "DIGESTFINALXOF_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!EVP_DigestFinal(mctx, got, &got_len)) {
|
|
|
|
t->err = "DIGESTFINAL_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
2017-04-27 03:33:43 +08:00
|
|
|
}
|
2025-06-18 17:59:04 +08:00
|
|
|
if (!TEST_size_t_eq(expected->output_len, got_len)) {
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "DIGEST_LENGTH_MISMATCH";
|
2015-02-10 01:29:47 +08:00
|
|
|
goto err;
|
2017-04-27 03:33:43 +08:00
|
|
|
}
|
2018-08-09 07:27:42 +08:00
|
|
|
if (!memory_err_compare(t, "DIGEST_MISMATCH",
|
|
|
|
expected->output, expected->output_len,
|
|
|
|
got, got_len))
|
2015-02-10 01:29:47 +08:00
|
|
|
goto err;
|
2018-08-09 07:27:42 +08:00
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = NULL;
|
|
|
|
|
2021-06-24 09:47:48 +08:00
|
|
|
/* Test the EVP_Q_digest interface as well */
|
2021-06-24 09:32:50 +08:00
|
|
|
if (sk_EVP_TEST_BUFFER_num(expected->input) == 1
|
|
|
|
&& !xof
|
|
|
|
/* This should never fail but we need the returned pointer now */
|
|
|
|
&& !TEST_ptr(inbuf = sk_EVP_TEST_BUFFER_value(expected->input, 0))
|
|
|
|
&& !inbuf->count_set) {
|
2021-06-25 21:18:28 +08:00
|
|
|
OPENSSL_cleanse(got, got_len);
|
2021-06-24 09:32:50 +08:00
|
|
|
if (!TEST_true(EVP_Q_digest(libctx,
|
|
|
|
EVP_MD_get0_name(expected->fetched_digest),
|
|
|
|
NULL, inbuf->buf, inbuf->buflen,
|
|
|
|
got, &size))
|
|
|
|
|| !TEST_mem_eq(got, size,
|
|
|
|
expected->output, expected->output_len)) {
|
|
|
|
t->err = "EVP_Q_digest failed";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-10 01:29:47 +08:00
|
|
|
err:
|
2017-08-11 04:39:40 +08:00
|
|
|
OPENSSL_free(got);
|
2015-12-02 07:49:35 +08:00
|
|
|
EVP_MD_CTX_free(mctx);
|
2015-02-10 07:24:10 +08:00
|
|
|
return 1;
|
2015-02-10 01:29:47 +08:00
|
|
|
}
|
2001-08-27 01:09:31 +08:00
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static const EVP_TEST_METHOD digest_test_method = {
|
2015-02-10 01:29:47 +08:00
|
|
|
"Digest",
|
|
|
|
digest_test_init,
|
|
|
|
digest_test_cleanup,
|
|
|
|
digest_test_parse,
|
|
|
|
digest_test_run
|
|
|
|
};
|
|
|
|
|
2017-05-13 02:19:51 +08:00
|
|
|
/**
|
|
|
|
*** CIPHER TESTS
|
|
|
|
**/
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
typedef struct cipher_data_st {
|
2015-02-10 01:29:47 +08:00
|
|
|
const EVP_CIPHER *cipher;
|
2019-06-07 16:52:25 +08:00
|
|
|
EVP_CIPHER *fetched_cipher;
|
2015-02-10 01:29:47 +08:00
|
|
|
int enc;
|
2015-02-27 08:49:47 +08:00
|
|
|
/* EVP_CIPH_GCM_MODE, EVP_CIPH_CCM_MODE or EVP_CIPH_OCB_MODE if AEAD */
|
2015-02-10 01:29:47 +08:00
|
|
|
int aead;
|
|
|
|
unsigned char *key;
|
|
|
|
size_t key_len;
|
2019-10-08 14:42:28 +08:00
|
|
|
size_t key_bits; /* Used by RC2 */
|
2015-02-10 01:29:47 +08:00
|
|
|
unsigned char *iv;
|
2021-04-27 12:56:00 +08:00
|
|
|
unsigned char *next_iv; /* Expected IV state after operation */
|
2019-10-03 14:05:49 +08:00
|
|
|
unsigned int rounds;
|
2015-02-10 01:29:47 +08:00
|
|
|
size_t iv_len;
|
|
|
|
unsigned char *plaintext;
|
|
|
|
size_t plaintext_len;
|
|
|
|
unsigned char *ciphertext;
|
|
|
|
size_t ciphertext_len;
|
2021-06-18 21:02:23 +08:00
|
|
|
/* AEAD ciphers only */
|
2017-05-19 22:27:28 +08:00
|
|
|
unsigned char *aad[AAD_NUM];
|
|
|
|
size_t aad_len[AAD_NUM];
|
2021-06-18 21:02:23 +08:00
|
|
|
int tls_aad;
|
|
|
|
int tls_version;
|
2015-02-10 01:29:47 +08:00
|
|
|
unsigned char *tag;
|
2020-06-08 12:33:27 +08:00
|
|
|
const char *cts_mode;
|
2015-02-10 01:29:47 +08:00
|
|
|
size_t tag_len;
|
2018-09-15 03:49:34 +08:00
|
|
|
int tag_late;
|
2021-06-18 21:02:23 +08:00
|
|
|
unsigned char *mac_key;
|
|
|
|
size_t mac_key_len;
|
2022-11-25 13:54:07 +08:00
|
|
|
const char *xts_standard;
|
2024-07-22 15:24:53 +08:00
|
|
|
STACK_OF(OPENSSL_STRING) *init_controls; /* collection of controls */
|
2017-04-27 03:33:43 +08:00
|
|
|
} CIPHER_DATA;
|
2015-02-10 01:29:47 +08:00
|
|
|
|
2023-07-27 21:11:57 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* XTS, SIV, CCM, stitched ciphers and Wrap modes have special
|
|
|
|
* requirements about input lengths so we don't fragment for those
|
|
|
|
*/
|
|
|
|
static int cipher_test_valid_fragmentation(CIPHER_DATA *cdat)
|
|
|
|
{
|
|
|
|
return (cdat->aead == EVP_CIPH_CCM_MODE
|
|
|
|
|| cdat->aead == EVP_CIPH_CBC_MODE
|
|
|
|
|| (cdat->aead == -1
|
|
|
|
&& EVP_CIPHER_get_mode(cdat->cipher) == EVP_CIPH_STREAM_CIPHER)
|
|
|
|
|| ((EVP_CIPHER_get_flags(cdat->cipher) & EVP_CIPH_FLAG_CTS) != 0)
|
|
|
|
|| EVP_CIPHER_get_mode(cdat->cipher) == EVP_CIPH_SIV_MODE
|
|
|
|
|| EVP_CIPHER_get_mode(cdat->cipher) == EVP_CIPH_GCM_SIV_MODE
|
|
|
|
|| EVP_CIPHER_get_mode(cdat->cipher) == EVP_CIPH_XTS_MODE
|
2024-01-17 18:48:55 +08:00
|
|
|
|| EVP_CIPHER_get_mode(cdat->cipher) == EVP_CIPH_WRAP_MODE
|
|
|
|
|| EVP_CIPHER_get_mode(cdat->cipher) == EVP_CIPH_CBC_MODE) ? 0 : 1;
|
2023-07-27 21:11:57 +08:00
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static int cipher_test_init(EVP_TEST *t, const char *alg)
|
2015-02-10 01:29:47 +08:00
|
|
|
{
|
|
|
|
const EVP_CIPHER *cipher;
|
2019-06-07 16:52:25 +08:00
|
|
|
EVP_CIPHER *fetched_cipher;
|
2017-05-13 02:19:51 +08:00
|
|
|
CIPHER_DATA *cdat;
|
|
|
|
int m;
|
2017-04-27 03:33:43 +08:00
|
|
|
|
2020-08-07 12:29:00 +08:00
|
|
|
if (is_cipher_disabled(alg)) {
|
|
|
|
t->skip = 1;
|
|
|
|
TEST_info("skipping, '%s' is disabled", alg);
|
|
|
|
return 1;
|
2015-02-27 03:26:53 +08:00
|
|
|
}
|
2020-08-07 12:29:00 +08:00
|
|
|
|
2021-06-18 21:02:23 +08:00
|
|
|
ERR_set_mark();
|
2023-09-08 17:44:27 +08:00
|
|
|
if ((cipher = fetched_cipher = EVP_CIPHER_fetch(libctx, alg, propquery)) == NULL
|
2021-06-18 21:02:23 +08:00
|
|
|
&& (cipher = EVP_get_cipherbyname(alg)) == NULL) {
|
|
|
|
/* a stitched cipher might not be available */
|
|
|
|
if (strstr(alg, "HMAC") != NULL) {
|
|
|
|
ERR_pop_to_mark();
|
|
|
|
t->skip = 1;
|
|
|
|
TEST_info("skipping, '%s' is not available", alg);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
ERR_clear_last_mark();
|
2020-08-07 12:29:00 +08:00
|
|
|
return 0;
|
2021-06-18 21:02:23 +08:00
|
|
|
}
|
|
|
|
ERR_clear_last_mark();
|
2020-08-07 12:29:00 +08:00
|
|
|
|
2022-01-24 11:06:34 +08:00
|
|
|
if (!TEST_ptr(cdat = OPENSSL_zalloc(sizeof(*cdat))))
|
|
|
|
return 0;
|
|
|
|
|
2024-07-22 15:24:53 +08:00
|
|
|
cdat->init_controls = sk_OPENSSL_STRING_new_null();
|
2015-02-10 01:29:47 +08:00
|
|
|
cdat->cipher = cipher;
|
2019-06-07 16:52:25 +08:00
|
|
|
cdat->fetched_cipher = fetched_cipher;
|
2015-02-10 01:29:47 +08:00
|
|
|
cdat->enc = -1;
|
Rename all getters to use get/get0 in name
For functions that exist in 1.1.1 provide a simple aliases via #define.
Fixes #15236
Functions with OSSL_DECODER_, OSSL_ENCODER_, OSSL_STORE_LOADER_,
EVP_KEYEXCH_, EVP_KEM_, EVP_ASYM_CIPHER_, EVP_SIGNATURE_,
EVP_KEYMGMT_, EVP_RAND_, EVP_MAC_, EVP_KDF_, EVP_PKEY_,
EVP_MD_, and EVP_CIPHER_ prefixes are renamed.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15405)
2021-05-21 22:58:08 +08:00
|
|
|
m = EVP_CIPHER_get_mode(cipher);
|
2021-06-18 21:02:23 +08:00
|
|
|
if (EVP_CIPHER_get_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER)
|
|
|
|
cdat->aead = m != 0 ? m : -1;
|
2015-02-10 01:29:47 +08:00
|
|
|
else
|
|
|
|
cdat->aead = 0;
|
2001-08-27 01:09:31 +08:00
|
|
|
|
2023-07-27 21:11:57 +08:00
|
|
|
if (data_chunk_size != 0 && !cipher_test_valid_fragmentation(cdat)) {
|
|
|
|
ERR_pop_to_mark();
|
2024-05-07 02:13:52 +08:00
|
|
|
EVP_CIPHER_free(fetched_cipher);
|
|
|
|
OPENSSL_free(cdat);
|
2023-07-27 21:11:57 +08:00
|
|
|
t->skip = 1;
|
|
|
|
TEST_info("skipping, '%s' does not support fragmentation", alg);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-05-13 02:19:51 +08:00
|
|
|
t->data = cdat;
|
2019-06-07 16:52:25 +08:00
|
|
|
if (fetched_cipher != NULL)
|
|
|
|
TEST_info("%s is fetched", alg);
|
2015-02-10 01:29:47 +08:00
|
|
|
return 1;
|
|
|
|
}
|
2001-08-27 01:09:31 +08:00
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static void cipher_test_cleanup(EVP_TEST *t)
|
2015-02-10 01:29:47 +08:00
|
|
|
{
|
2017-05-19 22:27:28 +08:00
|
|
|
int i;
|
2017-04-27 03:33:43 +08:00
|
|
|
CIPHER_DATA *cdat = t->data;
|
|
|
|
|
|
|
|
OPENSSL_free(cdat->key);
|
|
|
|
OPENSSL_free(cdat->iv);
|
2021-04-27 12:56:00 +08:00
|
|
|
OPENSSL_free(cdat->next_iv);
|
2017-04-27 03:33:43 +08:00
|
|
|
OPENSSL_free(cdat->ciphertext);
|
|
|
|
OPENSSL_free(cdat->plaintext);
|
2017-05-19 22:27:28 +08:00
|
|
|
for (i = 0; i < AAD_NUM; i++)
|
|
|
|
OPENSSL_free(cdat->aad[i]);
|
2017-04-27 03:33:43 +08:00
|
|
|
OPENSSL_free(cdat->tag);
|
2021-06-18 21:02:23 +08:00
|
|
|
OPENSSL_free(cdat->mac_key);
|
2020-04-22 08:25:23 +08:00
|
|
|
EVP_CIPHER_free(cdat->fetched_cipher);
|
2024-07-22 15:24:53 +08:00
|
|
|
ctrlfree(cdat->init_controls);
|
2015-02-10 01:29:47 +08:00
|
|
|
}
|
2001-08-27 01:09:31 +08:00
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static int cipher_test_parse(EVP_TEST *t, const char *keyword,
|
2015-02-10 01:29:47 +08:00
|
|
|
const char *value)
|
|
|
|
{
|
2017-04-27 03:33:43 +08:00
|
|
|
CIPHER_DATA *cdat = t->data;
|
2017-05-19 22:27:28 +08:00
|
|
|
int i;
|
2017-04-27 03:33:43 +08:00
|
|
|
|
2015-05-07 02:56:14 +08:00
|
|
|
if (strcmp(keyword, "Key") == 0)
|
2017-05-13 02:19:51 +08:00
|
|
|
return parse_bin(value, &cdat->key, &cdat->key_len);
|
2019-10-03 14:05:49 +08:00
|
|
|
if (strcmp(keyword, "Rounds") == 0) {
|
|
|
|
i = atoi(value);
|
|
|
|
if (i < 0)
|
|
|
|
return -1;
|
|
|
|
cdat->rounds = (unsigned int)i;
|
|
|
|
return 1;
|
|
|
|
}
|
2015-05-07 02:56:14 +08:00
|
|
|
if (strcmp(keyword, "IV") == 0)
|
2017-05-13 02:19:51 +08:00
|
|
|
return parse_bin(value, &cdat->iv, &cdat->iv_len);
|
2021-04-27 12:56:00 +08:00
|
|
|
if (strcmp(keyword, "NextIV") == 0)
|
|
|
|
return parse_bin(value, &cdat->next_iv, &cdat->iv_len);
|
2015-05-07 02:56:14 +08:00
|
|
|
if (strcmp(keyword, "Plaintext") == 0)
|
2017-05-13 02:19:51 +08:00
|
|
|
return parse_bin(value, &cdat->plaintext, &cdat->plaintext_len);
|
2015-05-07 02:56:14 +08:00
|
|
|
if (strcmp(keyword, "Ciphertext") == 0)
|
2017-05-13 02:19:51 +08:00
|
|
|
return parse_bin(value, &cdat->ciphertext, &cdat->ciphertext_len);
|
2019-10-08 14:42:28 +08:00
|
|
|
if (strcmp(keyword, "KeyBits") == 0) {
|
|
|
|
i = atoi(value);
|
|
|
|
if (i < 0)
|
|
|
|
return -1;
|
|
|
|
cdat->key_bits = (size_t)i;
|
|
|
|
return 1;
|
|
|
|
}
|
2024-01-17 18:48:55 +08:00
|
|
|
if (strcmp(keyword, "Tag") == 0)
|
|
|
|
return parse_bin(value, &cdat->tag, &cdat->tag_len);
|
|
|
|
if (strcmp(keyword, "MACKey") == 0)
|
|
|
|
return parse_bin(value, &cdat->mac_key, &cdat->mac_key_len);
|
2015-02-10 01:29:47 +08:00
|
|
|
if (cdat->aead) {
|
2021-06-18 21:02:23 +08:00
|
|
|
int tls_aad = 0;
|
|
|
|
|
|
|
|
if (strcmp(keyword, "TLSAAD") == 0)
|
|
|
|
cdat->tls_aad = tls_aad = 1;
|
|
|
|
if (strcmp(keyword, "AAD") == 0 || tls_aad) {
|
2017-05-19 22:27:28 +08:00
|
|
|
for (i = 0; i < AAD_NUM; i++) {
|
|
|
|
if (cdat->aad[i] == NULL)
|
|
|
|
return parse_bin(value, &cdat->aad[i], &cdat->aad_len[i]);
|
|
|
|
}
|
2019-08-23 23:41:23 +08:00
|
|
|
return -1;
|
2017-05-19 22:27:28 +08:00
|
|
|
}
|
2018-09-15 03:49:34 +08:00
|
|
|
if (strcmp(keyword, "SetTagLate") == 0) {
|
|
|
|
if (strcmp(value, "TRUE") == 0)
|
|
|
|
cdat->tag_late = 1;
|
|
|
|
else if (strcmp(value, "FALSE") == 0)
|
|
|
|
cdat->tag_late = 0;
|
|
|
|
else
|
2019-08-23 23:41:23 +08:00
|
|
|
return -1;
|
2018-09-15 03:49:34 +08:00
|
|
|
return 1;
|
|
|
|
}
|
2021-06-18 21:02:23 +08:00
|
|
|
if (strcmp(keyword, "TLSVersion") == 0) {
|
|
|
|
char *endptr;
|
|
|
|
|
|
|
|
cdat->tls_version = (int)strtol(value, &endptr, 0);
|
|
|
|
return value[0] != '\0' && endptr[0] == '\0';
|
|
|
|
}
|
2001-08-27 01:09:31 +08:00
|
|
|
}
|
|
|
|
|
2015-05-07 02:56:14 +08:00
|
|
|
if (strcmp(keyword, "Operation") == 0) {
|
|
|
|
if (strcmp(value, "ENCRYPT") == 0)
|
2015-02-10 01:29:47 +08:00
|
|
|
cdat->enc = 1;
|
2015-05-07 02:56:14 +08:00
|
|
|
else if (strcmp(value, "DECRYPT") == 0)
|
2015-02-10 01:29:47 +08:00
|
|
|
cdat->enc = 0;
|
|
|
|
else
|
2019-08-23 23:41:23 +08:00
|
|
|
return -1;
|
2015-02-10 01:29:47 +08:00
|
|
|
return 1;
|
2001-08-27 01:09:31 +08:00
|
|
|
}
|
2020-06-08 12:33:27 +08:00
|
|
|
if (strcmp(keyword, "CTSMode") == 0) {
|
|
|
|
cdat->cts_mode = value;
|
|
|
|
return 1;
|
|
|
|
}
|
2022-11-25 13:54:07 +08:00
|
|
|
if (strcmp(keyword, "XTSStandard") == 0) {
|
|
|
|
cdat->xts_standard = value;
|
|
|
|
return 1;
|
|
|
|
}
|
2024-07-22 15:24:53 +08:00
|
|
|
if (strcmp(keyword, "CtrlInit") == 0)
|
|
|
|
return ctrladd(cdat->init_controls, value);
|
2015-02-10 01:29:47 +08:00
|
|
|
return 0;
|
2001-08-27 01:09:31 +08:00
|
|
|
}
|
|
|
|
|
2023-07-13 23:07:00 +08:00
|
|
|
static int cipher_test_enc(EVP_TEST *t, int enc, size_t out_misalign,
|
2024-07-22 15:24:53 +08:00
|
|
|
size_t inp_misalign, int frag, int in_place,
|
|
|
|
const OSSL_PARAM initparams[])
|
2001-08-18 21:53:01 +08:00
|
|
|
{
|
2017-05-25 19:48:32 +08:00
|
|
|
CIPHER_DATA *expected = t->data;
|
|
|
|
unsigned char *in, *expected_out, *tmp = NULL;
|
2017-01-23 20:45:33 +08:00
|
|
|
size_t in_len, out_len, donelen = 0;
|
2017-05-19 22:27:28 +08:00
|
|
|
int ok = 0, tmplen, chunklen, tmpflen, i;
|
2019-11-18 11:13:05 +08:00
|
|
|
EVP_CIPHER_CTX *ctx_base = NULL;
|
2022-01-17 10:09:41 +08:00
|
|
|
EVP_CIPHER_CTX *ctx = NULL, *duped;
|
2023-09-22 06:46:31 +08:00
|
|
|
int fips_dupctx_supported = fips_provider_version_ge(libctx, 3, 2, 0);
|
2025-04-17 21:32:40 +08:00
|
|
|
int fips_no_silent_error = fips_provider_version_ge(libctx, 3, 6, 0);
|
2017-04-27 03:33:43 +08:00
|
|
|
|
|
|
|
t->err = "TEST_FAILURE";
|
2019-11-18 11:13:05 +08:00
|
|
|
if (!TEST_ptr(ctx_base = EVP_CIPHER_CTX_new()))
|
|
|
|
goto err;
|
2017-04-27 03:33:43 +08:00
|
|
|
if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new()))
|
2015-02-10 01:29:47 +08:00
|
|
|
goto err;
|
2019-11-18 11:13:05 +08:00
|
|
|
EVP_CIPHER_CTX_set_flags(ctx_base, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW);
|
2015-02-10 01:29:47 +08:00
|
|
|
if (enc) {
|
2017-05-25 19:48:32 +08:00
|
|
|
in = expected->plaintext;
|
|
|
|
in_len = expected->plaintext_len;
|
|
|
|
expected_out = expected->ciphertext;
|
|
|
|
out_len = expected->ciphertext_len;
|
2015-02-10 01:29:47 +08:00
|
|
|
} else {
|
2017-05-25 19:48:32 +08:00
|
|
|
in = expected->ciphertext;
|
|
|
|
in_len = expected->ciphertext_len;
|
|
|
|
expected_out = expected->plaintext;
|
|
|
|
out_len = expected->plaintext_len;
|
2001-08-18 21:53:01 +08:00
|
|
|
}
|
2023-07-13 23:07:00 +08:00
|
|
|
if (in_place == 1) {
|
2020-08-07 12:29:00 +08:00
|
|
|
/* Exercise in-place encryption */
|
2016-05-09 20:18:14 +08:00
|
|
|
tmp = OPENSSL_malloc(out_misalign + in_len + 2 * EVP_MAX_BLOCK_LENGTH);
|
|
|
|
if (!tmp)
|
|
|
|
goto err;
|
|
|
|
in = memcpy(tmp + out_misalign, in, in_len);
|
|
|
|
} else {
|
|
|
|
inp_misalign += 16 - ((out_misalign + in_len) & 15);
|
|
|
|
/*
|
|
|
|
* 'tmp' will store both output and copy of input. We make the copy
|
|
|
|
* of input to specifically aligned part of 'tmp'. So we just
|
|
|
|
* figured out how much padding would ensure the required alignment,
|
|
|
|
* now we allocate extended buffer and finally copy the input just
|
|
|
|
* past inp_misalign in expression below. Output will be written
|
|
|
|
* past out_misalign...
|
|
|
|
*/
|
|
|
|
tmp = OPENSSL_malloc(out_misalign + in_len + 2 * EVP_MAX_BLOCK_LENGTH +
|
|
|
|
inp_misalign + in_len);
|
|
|
|
if (!tmp)
|
|
|
|
goto err;
|
|
|
|
in = memcpy(tmp + out_misalign + in_len + 2 * EVP_MAX_BLOCK_LENGTH +
|
|
|
|
inp_misalign, in, in_len);
|
|
|
|
}
|
2024-07-22 15:24:53 +08:00
|
|
|
if (!EVP_CipherInit_ex2(ctx_base, expected->cipher, NULL, NULL, enc,
|
|
|
|
initparams)) {
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "CIPHERINIT_ERROR";
|
2015-02-10 01:29:47 +08:00
|
|
|
goto err;
|
2017-04-27 03:33:43 +08:00
|
|
|
}
|
2020-06-08 12:33:27 +08:00
|
|
|
if (expected->cts_mode != NULL) {
|
|
|
|
OSSL_PARAM params[2];
|
|
|
|
|
|
|
|
params[0] = OSSL_PARAM_construct_utf8_string(OSSL_CIPHER_PARAM_CTS_MODE,
|
|
|
|
(char *)expected->cts_mode,
|
|
|
|
0);
|
|
|
|
params[1] = OSSL_PARAM_construct_end();
|
|
|
|
if (!EVP_CIPHER_CTX_set_params(ctx_base, params)) {
|
|
|
|
t->err = "INVALID_CTS_MODE";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
2017-05-25 19:48:32 +08:00
|
|
|
if (expected->iv) {
|
|
|
|
if (expected->aead) {
|
2022-05-21 16:17:23 +08:00
|
|
|
if (EVP_CIPHER_CTX_ctrl(ctx_base, EVP_CTRL_AEAD_SET_IVLEN,
|
2025-06-18 17:59:04 +08:00
|
|
|
(int)expected->iv_len, 0) <= 0) {
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "INVALID_IV_LENGTH";
|
2015-02-10 01:29:47 +08:00
|
|
|
goto err;
|
2017-04-27 03:33:43 +08:00
|
|
|
}
|
Rename all getters to use get/get0 in name
For functions that exist in 1.1.1 provide a simple aliases via #define.
Fixes #15236
Functions with OSSL_DECODER_, OSSL_ENCODER_, OSSL_STORE_LOADER_,
EVP_KEYEXCH_, EVP_KEM_, EVP_ASYM_CIPHER_, EVP_SIGNATURE_,
EVP_KEYMGMT_, EVP_RAND_, EVP_MAC_, EVP_KDF_, EVP_PKEY_,
EVP_MD_, and EVP_CIPHER_ prefixes are renamed.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15405)
2021-05-21 22:58:08 +08:00
|
|
|
} else if (expected->iv_len != (size_t)EVP_CIPHER_CTX_get_iv_length(ctx_base)) {
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "INVALID_IV_LENGTH";
|
2015-02-10 01:29:47 +08:00
|
|
|
goto err;
|
2017-04-27 03:33:43 +08:00
|
|
|
}
|
2001-08-18 21:53:01 +08:00
|
|
|
}
|
2021-06-18 21:02:23 +08:00
|
|
|
if (expected->aead && !expected->tls_aad) {
|
2015-02-10 01:29:47 +08:00
|
|
|
unsigned char *tag;
|
|
|
|
/*
|
2015-02-27 08:49:47 +08:00
|
|
|
* If encrypting or OCB just set tag length initially, otherwise
|
|
|
|
* set tag length and value.
|
2015-02-10 01:29:47 +08:00
|
|
|
*/
|
2018-09-15 03:49:34 +08:00
|
|
|
if (enc || expected->aead == EVP_CIPH_OCB_MODE || expected->tag_late) {
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "TAG_LENGTH_SET_ERROR";
|
2015-02-10 01:29:47 +08:00
|
|
|
tag = NULL;
|
2002-05-31 21:12:49 +08:00
|
|
|
} else {
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "TAG_SET_ERROR";
|
2017-05-25 19:48:32 +08:00
|
|
|
tag = expected->tag;
|
2002-05-31 21:12:49 +08:00
|
|
|
}
|
2017-05-25 19:48:32 +08:00
|
|
|
if (tag || expected->aead != EVP_CIPH_GCM_MODE) {
|
2022-05-21 16:17:23 +08:00
|
|
|
if (EVP_CIPHER_CTX_ctrl(ctx_base, EVP_CTRL_AEAD_SET_TAG,
|
2025-06-18 17:59:04 +08:00
|
|
|
(int)expected->tag_len, tag) <= 0)
|
2015-02-10 01:29:47 +08:00
|
|
|
goto err;
|
2013-03-06 23:45:15 +08:00
|
|
|
}
|
2015-02-10 01:29:47 +08:00
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2019-10-03 14:05:49 +08:00
|
|
|
if (expected->rounds > 0) {
|
|
|
|
int rounds = (int)expected->rounds;
|
|
|
|
|
2022-05-21 16:17:23 +08:00
|
|
|
if (EVP_CIPHER_CTX_ctrl(ctx_base, EVP_CTRL_SET_RC5_ROUNDS, rounds, NULL) <= 0) {
|
2019-10-03 14:05:49 +08:00
|
|
|
t->err = "INVALID_ROUNDS";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-06-18 17:59:04 +08:00
|
|
|
if (!EVP_CIPHER_CTX_set_key_length(ctx_base, (int)expected->key_len)) {
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "INVALID_KEY_LENGTH";
|
2015-02-10 01:29:47 +08:00
|
|
|
goto err;
|
2017-04-27 03:33:43 +08:00
|
|
|
}
|
2019-10-08 14:42:28 +08:00
|
|
|
if (expected->key_bits > 0) {
|
|
|
|
int bits = (int)expected->key_bits;
|
|
|
|
|
2022-05-21 16:17:23 +08:00
|
|
|
if (EVP_CIPHER_CTX_ctrl(ctx_base, EVP_CTRL_SET_RC2_KEY_BITS, bits, NULL) <= 0) {
|
2019-10-08 14:42:28 +08:00
|
|
|
t->err = "INVALID KEY BITS";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
2019-11-18 11:13:05 +08:00
|
|
|
if (!EVP_CipherInit_ex(ctx_base, NULL, NULL, expected->key, expected->iv, -1)) {
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "KEY_SET_ERROR";
|
2015-02-10 01:29:47 +08:00
|
|
|
goto err;
|
2017-04-27 03:33:43 +08:00
|
|
|
}
|
2019-10-08 14:42:28 +08:00
|
|
|
|
2019-07-09 02:36:29 +08:00
|
|
|
/* Check that we get the same IV back */
|
2020-07-10 05:29:33 +08:00
|
|
|
if (expected->iv != NULL) {
|
|
|
|
/* Some (e.g., GCM) tests use IVs longer than EVP_MAX_IV_LENGTH. */
|
|
|
|
unsigned char iv[128];
|
2021-01-14 22:19:46 +08:00
|
|
|
if (!TEST_true(EVP_CIPHER_CTX_get_updated_iv(ctx_base, iv, sizeof(iv)))
|
Rename all getters to use get/get0 in name
For functions that exist in 1.1.1 provide a simple aliases via #define.
Fixes #15236
Functions with OSSL_DECODER_, OSSL_ENCODER_, OSSL_STORE_LOADER_,
EVP_KEYEXCH_, EVP_KEM_, EVP_ASYM_CIPHER_, EVP_SIGNATURE_,
EVP_KEYMGMT_, EVP_RAND_, EVP_MAC_, EVP_KDF_, EVP_PKEY_,
EVP_MD_, and EVP_CIPHER_ prefixes are renamed.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15405)
2021-05-21 22:58:08 +08:00
|
|
|
|| ((EVP_CIPHER_get_flags(expected->cipher) & EVP_CIPH_CUSTOM_IV) == 0
|
|
|
|
&& !TEST_mem_eq(expected->iv, expected->iv_len, iv,
|
|
|
|
expected->iv_len))) {
|
2020-07-10 05:29:33 +08:00
|
|
|
t->err = "INVALID_IV";
|
|
|
|
goto err;
|
2025-03-26 22:56:39 +08:00
|
|
|
} else {
|
2025-04-17 21:32:40 +08:00
|
|
|
if (fips_no_silent_error && !TEST_false(ERR_peek_error())) {
|
2025-03-26 22:56:39 +08:00
|
|
|
t->err = "GET_UPDATED_IV_SILENT_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
2020-07-10 05:29:33 +08:00
|
|
|
}
|
2019-07-09 02:36:29 +08:00
|
|
|
}
|
2015-02-10 01:29:47 +08:00
|
|
|
|
2019-11-18 11:13:05 +08:00
|
|
|
/* Test that the cipher dup functions correctly if it is supported */
|
2021-06-18 21:02:23 +08:00
|
|
|
ERR_set_mark();
|
2023-08-30 03:42:48 +08:00
|
|
|
if (!EVP_CIPHER_CTX_copy(ctx, ctx_base)) {
|
|
|
|
if (fips_dupctx_supported) {
|
|
|
|
TEST_info("Doing a copy of Cipher %s Fails!\n",
|
|
|
|
EVP_CIPHER_get0_name(expected->cipher));
|
|
|
|
ERR_print_errors_fp(stderr);
|
|
|
|
goto err;
|
|
|
|
} else {
|
|
|
|
TEST_info("Allowing copy fail as an old fips provider is in use.");
|
|
|
|
}
|
2023-09-13 05:07:53 +08:00
|
|
|
EVP_CIPHER_CTX_free(ctx);
|
|
|
|
ctx = ctx_base;
|
|
|
|
} else {
|
|
|
|
EVP_CIPHER_CTX_free(ctx_base);
|
|
|
|
ctx_base = NULL;
|
2019-11-18 11:13:05 +08:00
|
|
|
}
|
2022-01-17 10:09:41 +08:00
|
|
|
/* Likewise for dup */
|
|
|
|
duped = EVP_CIPHER_CTX_dup(ctx);
|
|
|
|
if (duped != NULL) {
|
|
|
|
EVP_CIPHER_CTX_free(ctx);
|
|
|
|
ctx = duped;
|
2023-08-30 03:42:48 +08:00
|
|
|
} else {
|
|
|
|
if (fips_dupctx_supported) {
|
|
|
|
TEST_info("Doing a dup of Cipher %s Fails!\n",
|
|
|
|
EVP_CIPHER_get0_name(expected->cipher));
|
|
|
|
ERR_print_errors_fp(stderr);
|
|
|
|
goto err;
|
|
|
|
} else {
|
|
|
|
TEST_info("Allowing dup fail as an old fips provider is in use.");
|
|
|
|
}
|
2022-01-17 10:09:41 +08:00
|
|
|
}
|
2021-06-18 21:02:23 +08:00
|
|
|
ERR_pop_to_mark();
|
|
|
|
|
|
|
|
if (expected->mac_key != NULL
|
2022-05-21 16:17:23 +08:00
|
|
|
&& EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_MAC_KEY,
|
2021-06-18 21:02:23 +08:00
|
|
|
(int)expected->mac_key_len,
|
2022-05-21 16:17:23 +08:00
|
|
|
(void *)expected->mac_key) <= 0) {
|
2021-06-18 21:02:23 +08:00
|
|
|
t->err = "SET_MAC_KEY_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (expected->tls_version) {
|
|
|
|
OSSL_PARAM params[2];
|
|
|
|
|
|
|
|
params[0] = OSSL_PARAM_construct_int(OSSL_CIPHER_PARAM_TLS_VERSION,
|
|
|
|
&expected->tls_version);
|
|
|
|
params[1] = OSSL_PARAM_construct_end();
|
|
|
|
if (!EVP_CIPHER_CTX_set_params(ctx, params)) {
|
|
|
|
t->err = "SET_TLS_VERSION_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
2019-11-18 11:13:05 +08:00
|
|
|
|
2017-05-25 19:48:32 +08:00
|
|
|
if (expected->aead == EVP_CIPH_CCM_MODE) {
|
2025-06-18 17:59:04 +08:00
|
|
|
if (!EVP_CipherUpdate(ctx, NULL, &tmplen, NULL, (int)out_len)) {
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "CCM_PLAINTEXT_LENGTH_SET_ERROR";
|
2015-02-10 01:29:47 +08:00
|
|
|
goto err;
|
2001-08-18 21:53:01 +08:00
|
|
|
}
|
|
|
|
}
|
2021-06-18 21:02:23 +08:00
|
|
|
if (expected->aad[0] != NULL && !expected->tls_aad) {
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "AAD_SET_ERROR";
|
2017-01-23 20:45:33 +08:00
|
|
|
if (!frag) {
|
2023-07-27 21:11:57 +08:00
|
|
|
/* Supply the data all in one go or according to data_chunk_size */
|
2017-05-19 22:27:28 +08:00
|
|
|
for (i = 0; expected->aad[i] != NULL; i++) {
|
2023-07-27 21:11:57 +08:00
|
|
|
size_t aad_len = expected->aad_len[i];
|
|
|
|
donelen = 0;
|
|
|
|
|
|
|
|
do {
|
2025-06-18 17:59:04 +08:00
|
|
|
size_t current_aad_len = (size_t)data_chunk_size;
|
2023-07-27 21:11:57 +08:00
|
|
|
|
2025-06-18 17:59:04 +08:00
|
|
|
if (data_chunk_size == 0 || current_aad_len > aad_len)
|
2023-07-27 21:11:57 +08:00
|
|
|
current_aad_len = aad_len;
|
|
|
|
if (!EVP_CipherUpdate(ctx, NULL, &chunklen,
|
|
|
|
expected->aad[i] + donelen,
|
2025-06-18 17:59:04 +08:00
|
|
|
(int)current_aad_len))
|
2023-07-27 21:11:57 +08:00
|
|
|
goto err;
|
|
|
|
donelen += current_aad_len;
|
|
|
|
aad_len -= current_aad_len;
|
|
|
|
} while (aad_len > 0);
|
2017-05-19 22:27:28 +08:00
|
|
|
}
|
2017-01-23 20:45:33 +08:00
|
|
|
} else {
|
2023-07-27 21:11:57 +08:00
|
|
|
/* Supply the AAD in chunks less than the block size where possible */
|
2017-05-19 22:27:28 +08:00
|
|
|
for (i = 0; expected->aad[i] != NULL; i++) {
|
|
|
|
if (expected->aad_len[i] > 0) {
|
|
|
|
if (!EVP_CipherUpdate(ctx, NULL, &chunklen, expected->aad[i], 1))
|
|
|
|
goto err;
|
|
|
|
donelen++;
|
|
|
|
}
|
|
|
|
if (expected->aad_len[i] > 2) {
|
|
|
|
if (!EVP_CipherUpdate(ctx, NULL, &chunklen,
|
|
|
|
expected->aad[i] + donelen,
|
2025-06-18 17:59:04 +08:00
|
|
|
(int)(expected->aad_len[i] - 2)))
|
2017-05-19 22:27:28 +08:00
|
|
|
goto err;
|
|
|
|
donelen += expected->aad_len[i] - 2;
|
|
|
|
}
|
|
|
|
if (expected->aad_len[i] > 1
|
|
|
|
&& !EVP_CipherUpdate(ctx, NULL, &chunklen,
|
|
|
|
expected->aad[i] + donelen, 1))
|
2017-01-23 20:45:33 +08:00
|
|
|
goto err;
|
|
|
|
}
|
2015-02-10 01:29:47 +08:00
|
|
|
}
|
|
|
|
}
|
2018-09-15 03:49:34 +08:00
|
|
|
|
2021-06-18 21:02:23 +08:00
|
|
|
if (expected->tls_aad) {
|
|
|
|
OSSL_PARAM params[2];
|
|
|
|
char *tls_aad;
|
|
|
|
|
|
|
|
/* duplicate the aad as the implementation might modify it */
|
|
|
|
if ((tls_aad = OPENSSL_memdup(expected->aad[0],
|
|
|
|
expected->aad_len[0])) == NULL)
|
|
|
|
goto err;
|
|
|
|
params[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_PARAM_AEAD_TLS1_AAD,
|
|
|
|
tls_aad,
|
|
|
|
expected->aad_len[0]);
|
|
|
|
params[1] = OSSL_PARAM_construct_end();
|
|
|
|
if (!EVP_CIPHER_CTX_set_params(ctx, params)) {
|
|
|
|
OPENSSL_free(tls_aad);
|
|
|
|
t->err = "TLS1_AAD_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
OPENSSL_free(tls_aad);
|
|
|
|
} else if (!enc && (expected->aead == EVP_CIPH_OCB_MODE
|
|
|
|
|| expected->tag_late)) {
|
2022-05-21 16:17:23 +08:00
|
|
|
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG,
|
2025-06-18 17:59:04 +08:00
|
|
|
(int)expected->tag_len, expected->tag) <= 0) {
|
2018-09-15 03:49:34 +08:00
|
|
|
t->err = "TAG_SET_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
2024-01-17 18:48:55 +08:00
|
|
|
} else if (!enc && expected->mac_key && expected->tag) {
|
2024-01-26 18:48:17 +08:00
|
|
|
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG,
|
2025-06-18 17:59:04 +08:00
|
|
|
(int)expected->tag_len, expected->tag) <= 0) {
|
2024-01-17 18:48:55 +08:00
|
|
|
t->err = "TAG_SET_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
2018-09-15 03:49:34 +08:00
|
|
|
}
|
2022-11-25 13:54:07 +08:00
|
|
|
if (expected->xts_standard != NULL) {
|
|
|
|
OSSL_PARAM params[2];
|
2018-09-15 03:49:34 +08:00
|
|
|
|
2022-11-25 13:54:07 +08:00
|
|
|
params[0] =
|
|
|
|
OSSL_PARAM_construct_utf8_string(OSSL_CIPHER_PARAM_XTS_STANDARD,
|
|
|
|
(char *)expected->xts_standard, 0);
|
|
|
|
params[1] = OSSL_PARAM_construct_end();
|
|
|
|
if (!EVP_CIPHER_CTX_set_params(ctx, params)) {
|
|
|
|
t->err = "SET_XTS_STANDARD_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
2015-02-10 01:29:47 +08:00
|
|
|
EVP_CIPHER_CTX_set_padding(ctx, 0);
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "CIPHERUPDATE_ERROR";
|
2017-01-23 20:45:33 +08:00
|
|
|
tmplen = 0;
|
|
|
|
if (!frag) {
|
2023-07-27 21:11:57 +08:00
|
|
|
do {
|
|
|
|
/* Supply the data all in one go or according to data_chunk_size */
|
2025-06-18 17:59:04 +08:00
|
|
|
size_t current_in_len = (size_t)data_chunk_size;
|
2023-07-27 21:11:57 +08:00
|
|
|
|
2025-06-18 17:59:04 +08:00
|
|
|
if (data_chunk_size == 0 || current_in_len > in_len)
|
2023-07-27 21:11:57 +08:00
|
|
|
current_in_len = in_len;
|
|
|
|
if (!EVP_CipherUpdate(ctx, tmp + out_misalign + tmplen, &chunklen,
|
2025-06-18 17:59:04 +08:00
|
|
|
in, (int)current_in_len))
|
2023-07-27 21:11:57 +08:00
|
|
|
goto err;
|
|
|
|
tmplen += chunklen;
|
|
|
|
in += current_in_len;
|
|
|
|
in_len -= current_in_len;
|
|
|
|
} while (in_len > 0);
|
2017-01-23 20:45:33 +08:00
|
|
|
} else {
|
|
|
|
/* Supply the data in chunks less than the block size where possible */
|
|
|
|
if (in_len > 0) {
|
|
|
|
if (!EVP_CipherUpdate(ctx, tmp + out_misalign, &chunklen, in, 1))
|
|
|
|
goto err;
|
|
|
|
tmplen += chunklen;
|
2017-01-25 17:26:35 +08:00
|
|
|
in++;
|
|
|
|
in_len--;
|
2017-01-23 20:45:33 +08:00
|
|
|
}
|
2017-01-25 17:26:35 +08:00
|
|
|
if (in_len > 1) {
|
2017-01-23 20:45:33 +08:00
|
|
|
if (!EVP_CipherUpdate(ctx, tmp + out_misalign + tmplen, &chunklen,
|
2025-06-18 17:59:04 +08:00
|
|
|
in, (int)(in_len - 1)))
|
2017-01-23 20:45:33 +08:00
|
|
|
goto err;
|
|
|
|
tmplen += chunklen;
|
2017-01-25 17:26:35 +08:00
|
|
|
in += in_len - 1;
|
|
|
|
in_len = 1;
|
2017-01-23 20:45:33 +08:00
|
|
|
}
|
2021-10-26 15:16:18 +08:00
|
|
|
if (in_len > 0) {
|
2017-01-23 20:45:33 +08:00
|
|
|
if (!EVP_CipherUpdate(ctx, tmp + out_misalign + tmplen, &chunklen,
|
2017-01-25 17:26:35 +08:00
|
|
|
in, 1))
|
2017-01-23 20:45:33 +08:00
|
|
|
goto err;
|
|
|
|
tmplen += chunklen;
|
|
|
|
}
|
|
|
|
}
|
2017-04-27 03:33:43 +08:00
|
|
|
if (!EVP_CipherFinal_ex(ctx, tmp + out_misalign + tmplen, &tmpflen)) {
|
|
|
|
t->err = "CIPHERFINAL_ERROR";
|
2017-02-03 10:49:26 +08:00
|
|
|
goto err;
|
2017-04-27 03:33:43 +08:00
|
|
|
}
|
2024-07-22 15:24:53 +08:00
|
|
|
if (!cipher_check_fips_approved(ctx, t)) {
|
|
|
|
t->err = "FIPSAPPROVED_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2021-06-18 21:02:23 +08:00
|
|
|
if (!enc && expected->tls_aad) {
|
|
|
|
if (expected->tls_version >= TLS1_1_VERSION
|
|
|
|
&& (EVP_CIPHER_is_a(expected->cipher, "AES-128-CBC-HMAC-SHA1")
|
|
|
|
|| EVP_CIPHER_is_a(expected->cipher, "AES-256-CBC-HMAC-SHA1"))) {
|
2025-06-18 17:59:04 +08:00
|
|
|
tmplen -= (int)expected->iv_len;
|
2021-06-18 21:02:23 +08:00
|
|
|
expected_out += expected->iv_len;
|
|
|
|
out_misalign += expected->iv_len;
|
|
|
|
}
|
|
|
|
if ((int)out_len > tmplen + tmpflen)
|
|
|
|
out_len = tmplen + tmpflen;
|
|
|
|
}
|
2018-08-09 07:27:42 +08:00
|
|
|
if (!memory_err_compare(t, "VALUE_MISMATCH", expected_out, out_len,
|
|
|
|
tmp + out_misalign, tmplen + tmpflen))
|
2015-02-10 01:29:47 +08:00
|
|
|
goto err;
|
2021-06-18 21:02:23 +08:00
|
|
|
if (enc && expected->aead && !expected->tls_aad) {
|
2023-12-01 19:47:07 +08:00
|
|
|
unsigned char rtag[48]; /* longest known for TLS_SHA384_SHA384 */
|
2017-04-27 03:33:43 +08:00
|
|
|
|
2017-05-25 19:48:32 +08:00
|
|
|
if (!TEST_size_t_le(expected->tag_len, sizeof(rtag))) {
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "TAG_LENGTH_INTERNAL_ERROR";
|
2015-02-10 01:29:47 +08:00
|
|
|
goto err;
|
|
|
|
}
|
2022-05-21 16:17:23 +08:00
|
|
|
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG,
|
2025-06-18 17:59:04 +08:00
|
|
|
(int)expected->tag_len, rtag) <= 0) {
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "TAG_RETRIEVE_ERROR";
|
2015-02-10 01:29:47 +08:00
|
|
|
goto err;
|
|
|
|
}
|
2018-08-09 07:27:42 +08:00
|
|
|
if (!memory_err_compare(t, "TAG_VALUE_MISMATCH",
|
|
|
|
expected->tag, expected->tag_len,
|
|
|
|
rtag, expected->tag_len))
|
2015-02-10 01:29:47 +08:00
|
|
|
goto err;
|
|
|
|
}
|
2024-01-17 18:48:55 +08:00
|
|
|
if (enc && expected->tag) {
|
|
|
|
if (EVP_CIPHER_is_a(expected->cipher, "AES-128-CBC-HMAC-SHA1-ETM")
|
|
|
|
|| EVP_CIPHER_is_a(expected->cipher, "AES-128-CBC-HMAC-SHA256-ETM")
|
2024-01-26 18:48:17 +08:00
|
|
|
|| EVP_CIPHER_is_a(expected->cipher, "AES-128-CBC-HMAC-SHA512-ETM")
|
2024-01-17 18:48:55 +08:00
|
|
|
|| EVP_CIPHER_is_a(expected->cipher, "AES-192-CBC-HMAC-SHA1-ETM")
|
|
|
|
|| EVP_CIPHER_is_a(expected->cipher, "AES-192-CBC-HMAC-SHA256-ETM")
|
2024-01-26 18:48:17 +08:00
|
|
|
|| EVP_CIPHER_is_a(expected->cipher, "AES-192-CBC-HMAC-SHA512-ETM")
|
2024-01-17 18:48:55 +08:00
|
|
|
|| EVP_CIPHER_is_a(expected->cipher, "AES-256-CBC-HMAC-SHA1-ETM")
|
2024-01-26 18:48:17 +08:00
|
|
|
|| EVP_CIPHER_is_a(expected->cipher, "AES-256-CBC-HMAC-SHA256-ETM")
|
|
|
|
|| EVP_CIPHER_is_a(expected->cipher, "AES-256-CBC-HMAC-SHA512-ETM")) {
|
|
|
|
unsigned char rtag[64] = {0};
|
2024-01-17 18:48:55 +08:00
|
|
|
unsigned tag_len = 0;
|
|
|
|
OSSL_PARAM params[2];
|
|
|
|
|
|
|
|
if (EVP_CIPHER_is_a(expected->cipher, "AES-128-CBC-HMAC-SHA1-ETM")
|
|
|
|
|| EVP_CIPHER_is_a(expected->cipher, "AES-192-CBC-HMAC-SHA1-ETM")
|
2024-01-26 18:48:17 +08:00
|
|
|
|| EVP_CIPHER_is_a(expected->cipher, "AES-256-CBC-HMAC-SHA1-ETM"))
|
2024-01-17 18:48:55 +08:00
|
|
|
tag_len = 20;
|
2024-01-26 18:48:17 +08:00
|
|
|
else if (EVP_CIPHER_is_a(expected->cipher, "AES-128-CBC-HMAC-SHA256-ETM")
|
|
|
|
|| EVP_CIPHER_is_a(expected->cipher, "AES-192-CBC-HMAC-SHA256-ETM")
|
|
|
|
|| EVP_CIPHER_is_a(expected->cipher, "AES-256-CBC-HMAC-SHA256-ETM"))
|
2024-01-17 18:48:55 +08:00
|
|
|
tag_len = 32;
|
2024-01-26 18:48:17 +08:00
|
|
|
else if (EVP_CIPHER_is_a(expected->cipher, "AES-128-CBC-HMAC-SHA512-ETM")
|
|
|
|
|| EVP_CIPHER_is_a(expected->cipher, "AES-192-CBC-HMAC-SHA512-ETM")
|
|
|
|
|| EVP_CIPHER_is_a(expected->cipher, "AES-256-CBC-HMAC-SHA512-ETM"))
|
|
|
|
tag_len = 64;
|
2024-01-17 18:48:55 +08:00
|
|
|
|
2024-01-26 18:48:17 +08:00
|
|
|
if (!TEST_size_t_le(expected->tag_len, tag_len) ||
|
|
|
|
!TEST_size_t_le(tag_len, sizeof(rtag))) {
|
2024-01-17 18:48:55 +08:00
|
|
|
t->err = "TAG_LENGTH_INTERNAL_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
params[0] = OSSL_PARAM_construct_octet_string(OSSL_CIPHER_HMAC_PARAM_MAC,
|
|
|
|
&rtag[0],
|
|
|
|
tag_len);
|
|
|
|
params[1] = OSSL_PARAM_construct_end();
|
|
|
|
|
|
|
|
if (!EVP_CIPHER_CTX_get_params(ctx, params)) {
|
|
|
|
t->err = "TAG_RETRIEVE_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!memory_err_compare(t, "TAG_VALUE_MISMATCH",
|
|
|
|
expected->tag, expected->tag_len,
|
|
|
|
rtag, expected->tag_len))
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
2021-04-27 12:56:00 +08:00
|
|
|
/* Check the updated IV */
|
|
|
|
if (expected->next_iv != NULL) {
|
|
|
|
/* Some (e.g., GCM) tests use IVs longer than EVP_MAX_IV_LENGTH. */
|
|
|
|
unsigned char iv[128];
|
|
|
|
if (!TEST_true(EVP_CIPHER_CTX_get_updated_iv(ctx, iv, sizeof(iv)))
|
2025-04-03 23:31:27 +08:00
|
|
|
|| !TEST_mem_eq(expected->next_iv, expected->iv_len, iv,
|
|
|
|
expected->iv_len)) {
|
2021-04-27 12:56:00 +08:00
|
|
|
t->err = "INVALID_NEXT_IV";
|
|
|
|
goto err;
|
2025-03-26 22:56:39 +08:00
|
|
|
} else {
|
2025-04-17 21:32:40 +08:00
|
|
|
if (fips_no_silent_error && !TEST_false(ERR_peek_error())) {
|
2025-03-26 22:56:39 +08:00
|
|
|
t->err = "GET_UPDATED_IV_SILENT_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
2021-04-27 12:56:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = NULL;
|
|
|
|
ok = 1;
|
2015-02-10 01:29:47 +08:00
|
|
|
err:
|
2015-05-01 22:02:07 +08:00
|
|
|
OPENSSL_free(tmp);
|
2019-11-18 11:13:05 +08:00
|
|
|
if (ctx != ctx_base)
|
|
|
|
EVP_CIPHER_CTX_free(ctx_base);
|
2015-02-10 01:29:47 +08:00
|
|
|
EVP_CIPHER_CTX_free(ctx);
|
2017-04-27 03:33:43 +08:00
|
|
|
return ok;
|
2015-02-10 01:29:47 +08:00
|
|
|
}
|
2001-08-18 21:53:01 +08:00
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static int cipher_test_run(EVP_TEST *t)
|
2015-02-10 01:29:47 +08:00
|
|
|
{
|
2017-04-27 03:33:43 +08:00
|
|
|
CIPHER_DATA *cdat = t->data;
|
2023-07-13 23:07:00 +08:00
|
|
|
int rv, frag, fragmax, in_place;
|
2016-04-24 01:14:21 +08:00
|
|
|
size_t out_misalign, inp_misalign;
|
2024-07-22 15:24:53 +08:00
|
|
|
OSSL_PARAM initparams[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
|
|
|
|
size_t params_n = 0;
|
2016-04-24 01:14:21 +08:00
|
|
|
|
2023-08-30 03:42:48 +08:00
|
|
|
TEST_info("RUNNING TEST FOR CIPHER %s\n", EVP_CIPHER_get0_name(cdat->cipher));
|
2015-02-10 01:29:47 +08:00
|
|
|
if (!cdat->key) {
|
|
|
|
t->err = "NO_KEY";
|
|
|
|
return 0;
|
|
|
|
}
|
2023-12-10 02:40:01 +08:00
|
|
|
if (!cdat->iv && EVP_CIPHER_get_iv_length(cdat->cipher) > 0) {
|
2015-02-10 01:29:47 +08:00
|
|
|
/* IV is optional and usually omitted in wrap mode */
|
Rename all getters to use get/get0 in name
For functions that exist in 1.1.1 provide a simple aliases via #define.
Fixes #15236
Functions with OSSL_DECODER_, OSSL_ENCODER_, OSSL_STORE_LOADER_,
EVP_KEYEXCH_, EVP_KEM_, EVP_ASYM_CIPHER_, EVP_SIGNATURE_,
EVP_KEYMGMT_, EVP_RAND_, EVP_MAC_, EVP_KDF_, EVP_PKEY_,
EVP_MD_, and EVP_CIPHER_ prefixes are renamed.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15405)
2021-05-21 22:58:08 +08:00
|
|
|
if (EVP_CIPHER_get_mode(cdat->cipher) != EVP_CIPH_WRAP_MODE) {
|
2015-02-10 01:29:47 +08:00
|
|
|
t->err = "NO_IV";
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2021-06-18 21:02:23 +08:00
|
|
|
if (cdat->aead && cdat->tag == NULL && !cdat->tls_aad) {
|
2015-02-10 01:29:47 +08:00
|
|
|
t->err = "NO_TAG";
|
|
|
|
return 0;
|
|
|
|
}
|
2023-07-13 23:07:00 +08:00
|
|
|
|
2024-07-22 15:24:53 +08:00
|
|
|
if (sk_OPENSSL_STRING_num(cdat->init_controls) > 0) {
|
|
|
|
if (!ctrl2params(t, cdat->init_controls, NULL,
|
|
|
|
initparams, OSSL_NELEM(initparams), ¶ms_n))
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2023-07-13 23:07:00 +08:00
|
|
|
fragmax = (cipher_test_valid_fragmentation(cdat) == 0) ? 0 : 1;
|
|
|
|
for (in_place = 1; in_place >= 0; in_place--) {
|
2016-04-24 01:14:21 +08:00
|
|
|
static char aux_err[64];
|
2023-07-13 23:07:00 +08:00
|
|
|
|
2016-04-24 01:14:21 +08:00
|
|
|
t->aux_err = aux_err;
|
2023-07-13 23:07:00 +08:00
|
|
|
/* Test only in-place data processing */
|
|
|
|
if (process_mode_in_place == 1 && in_place == 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
for (frag = 0; frag <= fragmax; frag++) {
|
2023-07-27 21:11:57 +08:00
|
|
|
if (frag == 1 && data_chunk_size != 0)
|
|
|
|
break;
|
2023-07-13 23:07:00 +08:00
|
|
|
for (out_misalign = 0; out_misalign <= 1; out_misalign++) {
|
|
|
|
for (inp_misalign = 0; inp_misalign <= 1; inp_misalign++) {
|
|
|
|
/* Skip input misalign tests for in-place processing */
|
|
|
|
if (inp_misalign == 1 && in_place == 1)
|
|
|
|
break;
|
|
|
|
if (in_place == 1) {
|
|
|
|
BIO_snprintf(aux_err, sizeof(aux_err),
|
|
|
|
"%s in-place, %sfragmented",
|
|
|
|
out_misalign ? "misaligned" : "aligned",
|
|
|
|
frag ? "" : "not ");
|
|
|
|
} else {
|
|
|
|
BIO_snprintf(aux_err, sizeof(aux_err),
|
|
|
|
"%s output and %s input, %sfragmented",
|
|
|
|
out_misalign ? "misaligned" : "aligned",
|
|
|
|
inp_misalign ? "misaligned" : "aligned",
|
|
|
|
frag ? "" : "not ");
|
|
|
|
}
|
|
|
|
if (cdat->enc) {
|
|
|
|
rv = cipher_test_enc(t, 1, out_misalign, inp_misalign,
|
2024-07-22 15:24:53 +08:00
|
|
|
frag, in_place, initparams);
|
|
|
|
if (rv != 1)
|
|
|
|
goto end;
|
2023-07-13 23:07:00 +08:00
|
|
|
}
|
|
|
|
if (cdat->enc != 1) {
|
|
|
|
rv = cipher_test_enc(t, 0, out_misalign, inp_misalign,
|
2024-07-22 15:24:53 +08:00
|
|
|
frag, in_place, initparams);
|
|
|
|
if (rv != 1)
|
|
|
|
goto end;
|
2023-07-13 23:07:00 +08:00
|
|
|
}
|
2016-04-24 01:14:21 +08:00
|
|
|
}
|
|
|
|
}
|
2015-02-10 01:29:47 +08:00
|
|
|
}
|
|
|
|
}
|
2024-07-22 15:24:53 +08:00
|
|
|
ctrl2params_free(initparams, params_n, 0);
|
2016-04-24 01:14:21 +08:00
|
|
|
t->aux_err = NULL;
|
2015-02-10 01:29:47 +08:00
|
|
|
return 1;
|
2024-07-22 15:24:53 +08:00
|
|
|
end:
|
|
|
|
ctrl2params_free(initparams, params_n, 0);
|
|
|
|
return (rv < 0 ? 0 : 1);
|
2001-08-18 21:53:01 +08:00
|
|
|
}
|
2015-02-10 01:29:47 +08:00
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static const EVP_TEST_METHOD cipher_test_method = {
|
2015-02-10 01:29:47 +08:00
|
|
|
"Cipher",
|
|
|
|
cipher_test_init,
|
|
|
|
cipher_test_cleanup,
|
|
|
|
cipher_test_parse,
|
|
|
|
cipher_test_run
|
|
|
|
};
|
2015-02-10 21:44:17 +08:00
|
|
|
|
2017-05-13 02:19:51 +08:00
|
|
|
|
|
|
|
/**
|
2020-08-07 12:29:00 +08:00
|
|
|
** MAC TESTS
|
|
|
|
**/
|
2017-05-13 02:19:51 +08:00
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
typedef struct mac_data_st {
|
2018-10-25 00:36:31 +08:00
|
|
|
/* MAC type in one form or another */
|
2019-09-23 16:56:13 +08:00
|
|
|
char *mac_name;
|
2019-07-31 04:52:07 +08:00
|
|
|
EVP_MAC *mac; /* for mac_test_run_mac */
|
2018-10-25 00:36:31 +08:00
|
|
|
int type; /* for mac_test_run_pkey */
|
2015-02-10 21:44:17 +08:00
|
|
|
/* Algorithm string for this MAC */
|
|
|
|
char *alg;
|
|
|
|
/* MAC key */
|
|
|
|
unsigned char *key;
|
|
|
|
size_t key_len;
|
2018-11-05 06:09:41 +08:00
|
|
|
/* MAC IV (GMAC) */
|
|
|
|
unsigned char *iv;
|
|
|
|
size_t iv_len;
|
2015-02-10 21:44:17 +08:00
|
|
|
/* Input to MAC */
|
|
|
|
unsigned char *input;
|
|
|
|
size_t input_len;
|
|
|
|
/* Expected output */
|
|
|
|
unsigned char *output;
|
|
|
|
size_t output_len;
|
2018-11-09 12:00:05 +08:00
|
|
|
unsigned char *custom;
|
|
|
|
size_t custom_len;
|
2018-12-21 07:36:40 +08:00
|
|
|
/* MAC salt (blake2) */
|
|
|
|
unsigned char *salt;
|
|
|
|
size_t salt_len;
|
2021-04-28 10:58:08 +08:00
|
|
|
/* XOF mode? */
|
|
|
|
int xof;
|
2022-04-12 22:35:56 +08:00
|
|
|
/* Reinitialization fails */
|
|
|
|
int no_reinit;
|
2018-09-09 05:16:55 +08:00
|
|
|
/* Collection of controls */
|
|
|
|
STACK_OF(OPENSSL_STRING) *controls;
|
2021-05-24 12:16:44 +08:00
|
|
|
/* Output size */
|
|
|
|
int output_size;
|
|
|
|
/* Block size */
|
|
|
|
int block_size;
|
2017-04-27 03:33:43 +08:00
|
|
|
} MAC_DATA;
|
2015-02-10 21:44:17 +08:00
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static int mac_test_init(EVP_TEST *t, const char *alg)
|
2015-02-10 21:44:17 +08:00
|
|
|
{
|
2019-07-31 04:52:07 +08:00
|
|
|
EVP_MAC *mac = NULL;
|
2018-10-25 00:36:31 +08:00
|
|
|
int type = NID_undef;
|
2017-04-27 03:33:43 +08:00
|
|
|
MAC_DATA *mdat;
|
|
|
|
|
2020-08-07 12:29:00 +08:00
|
|
|
if (is_mac_disabled(alg)) {
|
|
|
|
TEST_info("skipping, '%s' is disabled", alg);
|
|
|
|
t->skip = 1;
|
|
|
|
return 1;
|
|
|
|
}
|
2023-09-08 17:44:27 +08:00
|
|
|
if ((mac = EVP_MAC_fetch(libctx, alg, propquery)) == NULL) {
|
2018-10-25 00:36:31 +08:00
|
|
|
/*
|
|
|
|
* Since we didn't find an EVP_MAC, we check for known EVP_PKEY methods
|
|
|
|
* For debugging purposes, we allow 'NNNN by EVP_PKEY' to force running
|
|
|
|
* the EVP_PKEY method.
|
|
|
|
*/
|
|
|
|
size_t sz = strlen(alg);
|
|
|
|
static const char epilogue[] = " by EVP_PKEY";
|
|
|
|
|
2018-10-29 23:27:43 +08:00
|
|
|
if (sz >= sizeof(epilogue)
|
|
|
|
&& strcmp(alg + sz - (sizeof(epilogue) - 1), epilogue) == 0)
|
2018-10-25 00:36:31 +08:00
|
|
|
sz -= sizeof(epilogue) - 1;
|
|
|
|
|
2020-08-07 12:29:00 +08:00
|
|
|
if (strncmp(alg, "HMAC", sz) == 0)
|
2018-10-25 00:36:31 +08:00
|
|
|
type = EVP_PKEY_HMAC;
|
2020-08-07 12:29:00 +08:00
|
|
|
else if (strncmp(alg, "CMAC", sz) == 0)
|
2018-10-25 00:36:31 +08:00
|
|
|
type = EVP_PKEY_CMAC;
|
2020-08-07 12:29:00 +08:00
|
|
|
else if (strncmp(alg, "Poly1305", sz) == 0)
|
2018-10-25 00:36:31 +08:00
|
|
|
type = EVP_PKEY_POLY1305;
|
2020-08-07 12:29:00 +08:00
|
|
|
else if (strncmp(alg, "SipHash", sz) == 0)
|
2018-10-25 00:36:31 +08:00
|
|
|
type = EVP_PKEY_SIPHASH;
|
2020-08-07 12:29:00 +08:00
|
|
|
else
|
2018-10-25 00:36:31 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2015-02-10 21:44:17 +08:00
|
|
|
|
2022-01-24 11:06:34 +08:00
|
|
|
if (!TEST_ptr(mdat = OPENSSL_zalloc(sizeof(*mdat))))
|
|
|
|
return 0;
|
|
|
|
|
2015-02-10 21:44:17 +08:00
|
|
|
mdat->type = type;
|
2022-02-02 19:45:59 +08:00
|
|
|
if (!TEST_ptr(mdat->mac_name = OPENSSL_strdup(alg))) {
|
|
|
|
OPENSSL_free(mdat);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-10-25 00:36:31 +08:00
|
|
|
mdat->mac = mac;
|
2022-02-02 19:45:59 +08:00
|
|
|
if (!TEST_ptr(mdat->controls = sk_OPENSSL_STRING_new_null())) {
|
|
|
|
OPENSSL_free(mdat->mac_name);
|
|
|
|
OPENSSL_free(mdat);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-05-24 12:16:44 +08:00
|
|
|
mdat->output_size = mdat->block_size = -1;
|
2015-02-10 21:44:17 +08:00
|
|
|
t->data = mdat;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static void mac_test_cleanup(EVP_TEST *t)
|
2015-02-10 21:44:17 +08:00
|
|
|
{
|
2017-04-27 03:33:43 +08:00
|
|
|
MAC_DATA *mdat = t->data;
|
|
|
|
|
2019-07-31 04:52:07 +08:00
|
|
|
EVP_MAC_free(mdat->mac);
|
2019-09-23 16:56:13 +08:00
|
|
|
OPENSSL_free(mdat->mac_name);
|
2018-09-09 05:16:55 +08:00
|
|
|
sk_OPENSSL_STRING_pop_free(mdat->controls, openssl_free);
|
2017-04-27 03:33:43 +08:00
|
|
|
OPENSSL_free(mdat->alg);
|
|
|
|
OPENSSL_free(mdat->key);
|
2018-11-05 06:09:41 +08:00
|
|
|
OPENSSL_free(mdat->iv);
|
2018-11-09 12:00:05 +08:00
|
|
|
OPENSSL_free(mdat->custom);
|
2018-12-21 07:36:40 +08:00
|
|
|
OPENSSL_free(mdat->salt);
|
2017-04-27 03:33:43 +08:00
|
|
|
OPENSSL_free(mdat->input);
|
|
|
|
OPENSSL_free(mdat->output);
|
2015-02-10 21:44:17 +08:00
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static int mac_test_parse(EVP_TEST *t,
|
2015-02-10 21:44:17 +08:00
|
|
|
const char *keyword, const char *value)
|
|
|
|
{
|
2017-04-27 03:33:43 +08:00
|
|
|
MAC_DATA *mdata = t->data;
|
|
|
|
|
2015-05-07 02:56:14 +08:00
|
|
|
if (strcmp(keyword, "Key") == 0)
|
2017-05-13 02:19:51 +08:00
|
|
|
return parse_bin(value, &mdata->key, &mdata->key_len);
|
2018-11-05 06:09:41 +08:00
|
|
|
if (strcmp(keyword, "IV") == 0)
|
|
|
|
return parse_bin(value, &mdata->iv, &mdata->iv_len);
|
2018-11-09 12:00:05 +08:00
|
|
|
if (strcmp(keyword, "Custom") == 0)
|
|
|
|
return parse_bin(value, &mdata->custom, &mdata->custom_len);
|
2018-12-21 07:36:40 +08:00
|
|
|
if (strcmp(keyword, "Salt") == 0)
|
|
|
|
return parse_bin(value, &mdata->salt, &mdata->salt_len);
|
2015-05-07 02:56:14 +08:00
|
|
|
if (strcmp(keyword, "Algorithm") == 0) {
|
Rename some BUF_xxx to OPENSSL_xxx
Rename BUF_{strdup,strlcat,strlcpy,memdup,strndup,strnlen}
to OPENSSL_{strdup,strlcat,strlcpy,memdup,strndup,strnlen}
Add #define's for the old names.
Add CRYPTO_{memdup,strndup}, called by OPENSSL_{memdup,strndup} macros.
Reviewed-by: Tim Hudson <tjh@openssl.org>
2015-12-17 05:12:24 +08:00
|
|
|
mdata->alg = OPENSSL_strdup(value);
|
2022-06-17 16:57:15 +08:00
|
|
|
if (mdata->alg == NULL)
|
2019-08-23 23:41:23 +08:00
|
|
|
return -1;
|
2015-02-10 21:44:17 +08:00
|
|
|
return 1;
|
|
|
|
}
|
2015-05-07 02:56:14 +08:00
|
|
|
if (strcmp(keyword, "Input") == 0)
|
2017-05-13 02:19:51 +08:00
|
|
|
return parse_bin(value, &mdata->input, &mdata->input_len);
|
2015-05-07 02:56:14 +08:00
|
|
|
if (strcmp(keyword, "Output") == 0)
|
2017-05-13 02:19:51 +08:00
|
|
|
return parse_bin(value, &mdata->output, &mdata->output_len);
|
2021-04-28 10:58:08 +08:00
|
|
|
if (strcmp(keyword, "XOF") == 0)
|
|
|
|
return mdata->xof = 1;
|
2022-04-12 22:35:56 +08:00
|
|
|
if (strcmp(keyword, "NoReinit") == 0)
|
|
|
|
return mdata->no_reinit = 1;
|
2024-07-03 09:12:39 +08:00
|
|
|
if (strcmp(keyword, "Ctrl") == 0)
|
|
|
|
return ctrladd(mdata->controls, value);
|
2021-05-24 12:16:44 +08:00
|
|
|
if (strcmp(keyword, "OutputSize") == 0) {
|
|
|
|
mdata->output_size = atoi(value);
|
|
|
|
if (mdata->output_size < 0)
|
|
|
|
return -1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (strcmp(keyword, "BlockSize") == 0) {
|
|
|
|
mdata->block_size = atoi(value);
|
|
|
|
if (mdata->block_size < 0)
|
|
|
|
return -1;
|
|
|
|
return 1;
|
|
|
|
}
|
2015-02-10 21:44:17 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-10-26 19:42:40 +08:00
|
|
|
static int mac_test_ctrl_pkey(EVP_TEST *t, EVP_PKEY_CTX *pctx,
|
|
|
|
const char *value)
|
|
|
|
{
|
2021-03-17 11:04:20 +08:00
|
|
|
int rv = 0;
|
2018-10-26 19:42:40 +08:00
|
|
|
char *p, *tmpval;
|
|
|
|
|
|
|
|
if (!TEST_ptr(tmpval = OPENSSL_strdup(value)))
|
|
|
|
return 0;
|
|
|
|
p = strchr(tmpval, ':');
|
2021-03-17 11:04:20 +08:00
|
|
|
if (p != NULL) {
|
2018-10-26 19:42:40 +08:00
|
|
|
*p++ = '\0';
|
2021-03-17 11:04:20 +08:00
|
|
|
rv = EVP_PKEY_CTX_ctrl_str(pctx, tmpval, p);
|
|
|
|
}
|
2018-10-26 19:42:40 +08:00
|
|
|
if (rv == -2)
|
|
|
|
t->err = "PKEY_CTRL_INVALID";
|
|
|
|
else if (rv <= 0)
|
|
|
|
t->err = "PKEY_CTRL_ERROR";
|
|
|
|
else
|
|
|
|
rv = 1;
|
|
|
|
OPENSSL_free(tmpval);
|
|
|
|
return rv > 0;
|
|
|
|
}
|
|
|
|
|
2018-10-25 00:36:31 +08:00
|
|
|
static int mac_test_run_pkey(EVP_TEST *t)
|
2015-02-10 21:44:17 +08:00
|
|
|
{
|
2017-05-25 19:48:32 +08:00
|
|
|
MAC_DATA *expected = t->data;
|
2015-02-10 21:44:17 +08:00
|
|
|
EVP_MD_CTX *mctx = NULL;
|
|
|
|
EVP_PKEY_CTX *pctx = NULL, *genctx = NULL;
|
|
|
|
EVP_PKEY *key = NULL;
|
2020-08-07 12:29:00 +08:00
|
|
|
const char *mdname = NULL;
|
|
|
|
EVP_CIPHER *cipher = NULL;
|
2017-05-25 19:48:32 +08:00
|
|
|
unsigned char *got = NULL;
|
|
|
|
size_t got_len;
|
2018-09-09 05:16:55 +08:00
|
|
|
int i;
|
2023-08-08 22:04:03 +08:00
|
|
|
size_t input_len, donelen;
|
2015-02-10 21:44:17 +08:00
|
|
|
|
2021-04-28 10:58:08 +08:00
|
|
|
/* We don't do XOF mode via PKEY */
|
|
|
|
if (expected->xof)
|
|
|
|
return 1;
|
|
|
|
|
2018-10-25 00:36:31 +08:00
|
|
|
if (expected->alg == NULL)
|
|
|
|
TEST_info("Trying the EVP_PKEY %s test", OBJ_nid2sn(expected->type));
|
|
|
|
else
|
|
|
|
TEST_info("Trying the EVP_PKEY %s test with %s",
|
|
|
|
OBJ_nid2sn(expected->type), expected->alg);
|
|
|
|
|
2020-08-07 12:29:00 +08:00
|
|
|
if (expected->type == EVP_PKEY_CMAC) {
|
2020-12-08 23:13:54 +08:00
|
|
|
#ifdef OPENSSL_NO_DEPRECATED_3_0
|
|
|
|
TEST_info("skipping, PKEY CMAC '%s' is disabled", expected->alg);
|
|
|
|
t->skip = 1;
|
|
|
|
t->err = NULL;
|
|
|
|
goto err;
|
|
|
|
#else
|
|
|
|
OSSL_LIB_CTX *tmpctx;
|
|
|
|
|
2020-08-11 13:36:49 +08:00
|
|
|
if (expected->alg != NULL && is_cipher_disabled(expected->alg)) {
|
2020-08-07 12:29:00 +08:00
|
|
|
TEST_info("skipping, PKEY CMAC '%s' is disabled", expected->alg);
|
|
|
|
t->skip = 1;
|
|
|
|
t->err = NULL;
|
|
|
|
goto err;
|
|
|
|
}
|
2023-09-08 17:44:27 +08:00
|
|
|
if (!TEST_ptr(cipher = EVP_CIPHER_fetch(libctx, expected->alg, propquery))) {
|
2020-08-07 12:29:00 +08:00
|
|
|
t->err = "MAC_KEY_CREATE_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
2020-12-08 23:13:54 +08:00
|
|
|
tmpctx = OSSL_LIB_CTX_set0_default(libctx);
|
|
|
|
key = EVP_PKEY_new_CMAC_key(NULL, expected->key, expected->key_len,
|
|
|
|
cipher);
|
|
|
|
OSSL_LIB_CTX_set0_default(tmpctx);
|
|
|
|
#endif
|
2020-08-07 12:29:00 +08:00
|
|
|
} else {
|
2020-09-24 17:42:23 +08:00
|
|
|
key = EVP_PKEY_new_raw_private_key_ex(libctx,
|
|
|
|
OBJ_nid2sn(expected->type), NULL,
|
|
|
|
expected->key, expected->key_len);
|
2020-08-07 12:29:00 +08:00
|
|
|
}
|
2018-03-06 00:22:41 +08:00
|
|
|
if (key == NULL) {
|
|
|
|
t->err = "MAC_KEY_CREATE_ERROR";
|
2015-02-10 21:44:17 +08:00
|
|
|
goto err;
|
2017-04-27 03:33:43 +08:00
|
|
|
}
|
2015-02-10 21:44:17 +08:00
|
|
|
|
2020-08-11 13:36:49 +08:00
|
|
|
if (expected->type == EVP_PKEY_HMAC && expected->alg != NULL) {
|
2020-08-07 12:29:00 +08:00
|
|
|
if (is_digest_disabled(expected->alg)) {
|
|
|
|
TEST_info("skipping, HMAC '%s' is disabled", expected->alg);
|
|
|
|
t->skip = 1;
|
|
|
|
t->err = NULL;
|
2015-02-10 21:44:17 +08:00
|
|
|
goto err;
|
2017-04-27 03:33:43 +08:00
|
|
|
}
|
2020-08-07 12:29:00 +08:00
|
|
|
mdname = expected->alg;
|
2015-02-10 21:44:17 +08:00
|
|
|
}
|
2017-04-27 03:33:43 +08:00
|
|
|
if (!TEST_ptr(mctx = EVP_MD_CTX_new())) {
|
|
|
|
t->err = "INTERNAL_ERROR";
|
2015-02-10 21:44:17 +08:00
|
|
|
goto err;
|
2017-04-27 03:33:43 +08:00
|
|
|
}
|
2021-03-02 20:41:24 +08:00
|
|
|
if (!EVP_DigestSignInit_ex(mctx, &pctx, mdname, libctx, NULL, key, NULL)) {
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "DIGESTSIGNINIT_ERROR";
|
2015-02-10 21:44:17 +08:00
|
|
|
goto err;
|
2017-04-27 03:33:43 +08:00
|
|
|
}
|
2018-09-09 05:16:55 +08:00
|
|
|
for (i = 0; i < sk_OPENSSL_STRING_num(expected->controls); i++)
|
2018-10-26 19:42:40 +08:00
|
|
|
if (!mac_test_ctrl_pkey(t, pctx,
|
|
|
|
sk_OPENSSL_STRING_value(expected->controls,
|
|
|
|
i))) {
|
2018-09-09 05:16:55 +08:00
|
|
|
t->err = "EVPPKEYCTXCTRL_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
2023-08-08 22:04:03 +08:00
|
|
|
input_len = expected->input_len;
|
|
|
|
donelen = 0;
|
|
|
|
do {
|
|
|
|
size_t current_len = (size_t) data_chunk_size;
|
|
|
|
|
|
|
|
if (data_chunk_size == 0 || (size_t) data_chunk_size > input_len)
|
|
|
|
current_len = input_len;
|
|
|
|
if (!EVP_DigestSignUpdate(mctx, expected->input + donelen, current_len)) {
|
|
|
|
t->err = "DIGESTSIGNUPDATE_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
donelen += current_len;
|
|
|
|
input_len -= current_len;
|
|
|
|
} while (input_len > 0);
|
|
|
|
|
2017-05-25 19:48:32 +08:00
|
|
|
if (!EVP_DigestSignFinal(mctx, NULL, &got_len)) {
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "DIGESTSIGNFINAL_LENGTH_ERROR";
|
2015-02-10 21:44:17 +08:00
|
|
|
goto err;
|
2017-04-27 03:33:43 +08:00
|
|
|
}
|
2017-05-25 19:48:32 +08:00
|
|
|
if (!TEST_ptr(got = OPENSSL_malloc(got_len))) {
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "TEST_FAILURE";
|
2015-02-10 21:44:17 +08:00
|
|
|
goto err;
|
2017-04-27 03:33:43 +08:00
|
|
|
}
|
2017-05-25 19:48:32 +08:00
|
|
|
if (!EVP_DigestSignFinal(mctx, got, &got_len)
|
2018-08-09 07:27:42 +08:00
|
|
|
|| !memory_err_compare(t, "TEST_MAC_ERR",
|
|
|
|
expected->output, expected->output_len,
|
|
|
|
got, got_len)) {
|
2017-05-01 08:38:39 +08:00
|
|
|
t->err = "TEST_MAC_ERR";
|
|
|
|
goto err;
|
|
|
|
}
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = NULL;
|
2015-02-10 21:44:17 +08:00
|
|
|
err:
|
2020-08-07 12:29:00 +08:00
|
|
|
EVP_CIPHER_free(cipher);
|
2015-12-02 07:49:35 +08:00
|
|
|
EVP_MD_CTX_free(mctx);
|
2017-05-25 19:48:32 +08:00
|
|
|
OPENSSL_free(got);
|
2015-03-28 22:54:15 +08:00
|
|
|
EVP_PKEY_CTX_free(genctx);
|
|
|
|
EVP_PKEY_free(key);
|
2015-02-10 21:44:17 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-10-25 00:36:31 +08:00
|
|
|
static int mac_test_run_mac(EVP_TEST *t)
|
|
|
|
{
|
|
|
|
MAC_DATA *expected = t->data;
|
|
|
|
EVP_MAC_CTX *ctx = NULL;
|
|
|
|
unsigned char *got = NULL;
|
2021-06-24 09:47:48 +08:00
|
|
|
size_t got_len = 0, size = 0;
|
2023-12-11 22:19:47 +08:00
|
|
|
size_t size_before_init = 0, size_after_init, size_val = 0;
|
2024-07-03 09:12:39 +08:00
|
|
|
int block_size = -1, output_size = -1;
|
|
|
|
OSSL_PARAM params[21], sizes[3], *psizes = sizes, *p;
|
2019-07-31 04:52:07 +08:00
|
|
|
size_t params_n = 0;
|
|
|
|
size_t params_n_allocstart = 0;
|
|
|
|
const OSSL_PARAM *defined_params =
|
2019-09-27 14:35:45 +08:00
|
|
|
EVP_MAC_settable_ctx_params(expected->mac);
|
2021-06-24 09:47:48 +08:00
|
|
|
int xof;
|
2022-04-12 22:35:56 +08:00
|
|
|
int reinit = 1;
|
2023-08-08 22:04:03 +08:00
|
|
|
size_t input_len, donelen ;
|
2018-10-25 00:36:31 +08:00
|
|
|
|
|
|
|
if (expected->alg == NULL)
|
2019-09-23 16:56:13 +08:00
|
|
|
TEST_info("Trying the EVP_MAC %s test", expected->mac_name);
|
2018-10-25 00:36:31 +08:00
|
|
|
else
|
|
|
|
TEST_info("Trying the EVP_MAC %s test with %s",
|
2019-09-23 16:56:13 +08:00
|
|
|
expected->mac_name, expected->alg);
|
2018-10-25 00:36:31 +08:00
|
|
|
|
2019-08-22 18:50:00 +08:00
|
|
|
if (expected->alg != NULL) {
|
2022-07-07 10:01:09 +08:00
|
|
|
int skip = 0;
|
|
|
|
|
2019-08-22 18:50:00 +08:00
|
|
|
/*
|
|
|
|
* The underlying algorithm may be a cipher or a digest.
|
|
|
|
* We don't know which it is, but we can ask the MAC what it
|
|
|
|
* should be and bet on that.
|
|
|
|
*/
|
|
|
|
if (OSSL_PARAM_locate_const(defined_params,
|
|
|
|
OSSL_MAC_PARAM_CIPHER) != NULL) {
|
2022-07-07 10:01:09 +08:00
|
|
|
if (is_cipher_disabled(expected->alg))
|
|
|
|
skip = 1;
|
|
|
|
else
|
|
|
|
params[params_n++] =
|
|
|
|
OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER,
|
|
|
|
expected->alg, 0);
|
2019-08-22 18:50:00 +08:00
|
|
|
} else if (OSSL_PARAM_locate_const(defined_params,
|
|
|
|
OSSL_MAC_PARAM_DIGEST) != NULL) {
|
2022-07-07 10:01:09 +08:00
|
|
|
if (is_digest_disabled(expected->alg))
|
|
|
|
skip = 1;
|
|
|
|
else
|
|
|
|
params[params_n++] =
|
|
|
|
OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST,
|
|
|
|
expected->alg, 0);
|
2019-08-22 18:50:00 +08:00
|
|
|
} else {
|
|
|
|
t->err = "MAC_BAD_PARAMS";
|
|
|
|
goto err;
|
|
|
|
}
|
2022-07-07 10:01:09 +08:00
|
|
|
if (skip) {
|
|
|
|
TEST_info("skipping, algorithm '%s' is disabled", expected->alg);
|
|
|
|
t->skip = 1;
|
|
|
|
t->err = NULL;
|
|
|
|
goto err;
|
|
|
|
}
|
2019-08-22 18:50:00 +08:00
|
|
|
}
|
2019-07-31 04:52:07 +08:00
|
|
|
if (expected->custom != NULL)
|
|
|
|
params[params_n++] =
|
|
|
|
OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_CUSTOM,
|
|
|
|
expected->custom,
|
|
|
|
expected->custom_len);
|
|
|
|
if (expected->salt != NULL)
|
|
|
|
params[params_n++] =
|
|
|
|
OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_SALT,
|
|
|
|
expected->salt,
|
|
|
|
expected->salt_len);
|
|
|
|
if (expected->iv != NULL)
|
|
|
|
params[params_n++] =
|
|
|
|
OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_IV,
|
|
|
|
expected->iv,
|
|
|
|
expected->iv_len);
|
|
|
|
|
|
|
|
params_n_allocstart = params_n;
|
2024-07-03 09:12:39 +08:00
|
|
|
if (!ctrl2params(t, expected->controls, defined_params,
|
|
|
|
params, OSSL_NELEM(params), ¶ms_n))
|
|
|
|
goto err;
|
2023-11-29 11:43:52 +08:00
|
|
|
|
2024-07-03 09:12:39 +08:00
|
|
|
p = OSSL_PARAM_locate(params + params_n_allocstart, "size");
|
2024-07-12 04:04:28 +08:00
|
|
|
if (p != NULL) {
|
|
|
|
if (!OSSL_PARAM_get_size_t(p, &size_val))
|
|
|
|
goto err;
|
|
|
|
}
|
2018-12-21 07:36:40 +08:00
|
|
|
|
2020-06-18 16:26:22 +08:00
|
|
|
if ((ctx = EVP_MAC_CTX_new(expected->mac)) == NULL) {
|
2019-07-31 04:52:07 +08:00
|
|
|
t->err = "MAC_CREATE_ERROR";
|
|
|
|
goto err;
|
2018-11-05 06:09:41 +08:00
|
|
|
}
|
2024-07-31 12:56:44 +08:00
|
|
|
if (fips_provider_version_gt(libctx, 3, 2, 0)) {
|
|
|
|
/* HMAC will put an error on the stack here (digest is not set yet) */
|
|
|
|
ERR_set_mark();
|
2023-12-11 22:19:47 +08:00
|
|
|
size_before_init = EVP_MAC_CTX_get_mac_size(ctx);
|
2024-07-31 12:56:44 +08:00
|
|
|
ERR_pop_to_mark();
|
|
|
|
}
|
2021-02-25 11:49:37 +08:00
|
|
|
if (!EVP_MAC_init(ctx, expected->key, expected->key_len, params)) {
|
2018-12-21 07:36:40 +08:00
|
|
|
t->err = "MAC_INIT_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
2023-11-29 11:43:52 +08:00
|
|
|
size_after_init = EVP_MAC_CTX_get_mac_size(ctx);
|
|
|
|
if (!TEST_false(size_before_init == 0 && size_after_init == 0)) {
|
|
|
|
t->err = "MAC SIZE not set";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
if (size_before_init != 0) {
|
|
|
|
/* mac-size not modified by init params */
|
|
|
|
if (size_val == 0 && !TEST_size_t_eq(size_before_init, size_after_init)) {
|
|
|
|
t->err = "MAC SIZE check failed";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
/* mac-size modified by init params */
|
|
|
|
if (size_val != 0 && !TEST_size_t_eq(size_val, size_after_init)) {
|
|
|
|
t->err = "MAC SIZE check failed";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
2021-05-24 12:16:44 +08:00
|
|
|
if (expected->output_size >= 0)
|
|
|
|
*psizes++ = OSSL_PARAM_construct_int(OSSL_MAC_PARAM_SIZE,
|
|
|
|
&output_size);
|
|
|
|
if (expected->block_size >= 0)
|
|
|
|
*psizes++ = OSSL_PARAM_construct_int(OSSL_MAC_PARAM_BLOCK_SIZE,
|
|
|
|
&block_size);
|
|
|
|
if (psizes != sizes) {
|
|
|
|
*psizes = OSSL_PARAM_construct_end();
|
|
|
|
if (!TEST_true(EVP_MAC_CTX_get_params(ctx, sizes))) {
|
|
|
|
t->err = "INTERNAL_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
if (expected->output_size >= 0
|
|
|
|
&& !TEST_int_eq(output_size, expected->output_size)) {
|
|
|
|
t->err = "TEST_FAILURE";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
if (expected->block_size >= 0
|
|
|
|
&& !TEST_int_eq(block_size, expected->block_size)) {
|
|
|
|
t->err = "TEST_FAILURE";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
2022-04-12 22:35:56 +08:00
|
|
|
retry:
|
2023-08-08 22:04:03 +08:00
|
|
|
input_len = expected->input_len;
|
|
|
|
donelen = 0;
|
|
|
|
do {
|
|
|
|
size_t current_len = (size_t) data_chunk_size;
|
|
|
|
|
|
|
|
if (data_chunk_size == 0 || (size_t) data_chunk_size > input_len)
|
|
|
|
current_len = input_len;
|
|
|
|
if (!EVP_MAC_update(ctx, expected->input + donelen, current_len)) {
|
|
|
|
t->err = "MAC_UPDATE_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
donelen += current_len;
|
|
|
|
input_len -= current_len;
|
|
|
|
} while (input_len > 0);
|
|
|
|
|
2021-06-24 09:47:48 +08:00
|
|
|
xof = expected->xof;
|
|
|
|
if (xof) {
|
2021-04-28 10:58:08 +08:00
|
|
|
if (!TEST_ptr(got = OPENSSL_malloc(expected->output_len))) {
|
|
|
|
t->err = "TEST_FAILURE";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
if (!EVP_MAC_finalXOF(ctx, got, expected->output_len)
|
|
|
|
|| !memory_err_compare(t, "TEST_MAC_ERR",
|
|
|
|
expected->output, expected->output_len,
|
|
|
|
got, expected->output_len)) {
|
|
|
|
t->err = "MAC_FINAL_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!EVP_MAC_final(ctx, NULL, &got_len, 0)) {
|
|
|
|
t->err = "MAC_FINAL_LENGTH_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
if (!TEST_ptr(got = OPENSSL_malloc(got_len))) {
|
|
|
|
t->err = "TEST_FAILURE";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
if (!EVP_MAC_final(ctx, got, &got_len, got_len)
|
|
|
|
|| !memory_err_compare(t, "TEST_MAC_ERR",
|
|
|
|
expected->output, expected->output_len,
|
|
|
|
got, got_len)) {
|
|
|
|
t->err = "TEST_MAC_ERR";
|
|
|
|
goto err;
|
|
|
|
}
|
2024-07-18 05:59:01 +08:00
|
|
|
if (!mac_check_fips_approved(ctx, t))
|
|
|
|
goto err;
|
2018-10-25 00:36:31 +08:00
|
|
|
}
|
2022-09-14 04:38:30 +08:00
|
|
|
/* FIPS(3.0.0): can't reinitialise MAC contexts #18100 */
|
2022-09-13 06:49:05 +08:00
|
|
|
if (reinit-- && fips_provider_version_gt(libctx, 3, 0, 0)) {
|
2022-04-12 22:35:56 +08:00
|
|
|
OSSL_PARAM ivparams[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
/* If the MAC uses IV, we have to set it again */
|
|
|
|
if (expected->iv != NULL) {
|
|
|
|
ivparams[0] =
|
|
|
|
OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_IV,
|
|
|
|
expected->iv,
|
|
|
|
expected->iv_len);
|
|
|
|
ivparams[1] = OSSL_PARAM_construct_end();
|
|
|
|
}
|
|
|
|
ERR_set_mark();
|
|
|
|
ret = EVP_MAC_init(ctx, NULL, 0, ivparams);
|
|
|
|
if (expected->no_reinit) {
|
|
|
|
if (ret) {
|
|
|
|
ERR_clear_last_mark();
|
|
|
|
t->err = "MAC_REINIT_SHOULD_FAIL";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
} else if (ret) {
|
|
|
|
ERR_clear_last_mark();
|
|
|
|
OPENSSL_free(got);
|
|
|
|
got = NULL;
|
|
|
|
goto retry;
|
|
|
|
} else {
|
|
|
|
ERR_clear_last_mark();
|
|
|
|
t->err = "MAC_REINIT_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
/* If reinitialization fails, it is unsupported by the algorithm */
|
|
|
|
ERR_pop_to_mark();
|
|
|
|
}
|
2018-10-25 00:36:31 +08:00
|
|
|
t->err = NULL;
|
2021-06-24 09:47:48 +08:00
|
|
|
|
|
|
|
/* Test the EVP_Q_mac interface as well */
|
|
|
|
if (!xof) {
|
2021-06-25 21:18:28 +08:00
|
|
|
OPENSSL_cleanse(got, got_len);
|
2021-06-24 09:47:48 +08:00
|
|
|
if (!TEST_true(EVP_Q_mac(libctx, expected->mac_name, NULL,
|
|
|
|
expected->alg, params,
|
|
|
|
expected->key, expected->key_len,
|
|
|
|
expected->input, expected->input_len,
|
|
|
|
got, got_len, &size))
|
|
|
|
|| !TEST_mem_eq(got, size,
|
|
|
|
expected->output, expected->output_len)) {
|
|
|
|
t->err = "EVP_Q_mac failed";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
2018-10-25 00:36:31 +08:00
|
|
|
err:
|
2024-07-03 09:12:39 +08:00
|
|
|
ctrl2params_free(params, params_n, params_n_allocstart);
|
2020-06-18 16:26:22 +08:00
|
|
|
EVP_MAC_CTX_free(ctx);
|
2018-10-25 00:36:31 +08:00
|
|
|
OPENSSL_free(got);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int mac_test_run(EVP_TEST *t)
|
|
|
|
{
|
|
|
|
MAC_DATA *expected = t->data;
|
|
|
|
|
|
|
|
if (expected->mac != NULL)
|
|
|
|
return mac_test_run_mac(t);
|
|
|
|
return mac_test_run_pkey(t);
|
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static const EVP_TEST_METHOD mac_test_method = {
|
2015-02-10 21:44:17 +08:00
|
|
|
"MAC",
|
|
|
|
mac_test_init,
|
|
|
|
mac_test_cleanup,
|
|
|
|
mac_test_parse,
|
|
|
|
mac_test_run
|
|
|
|
};
|
2015-02-12 01:15:51 +08:00
|
|
|
|
2024-07-03 09:12:39 +08:00
|
|
|
typedef struct kem_data_st {
|
|
|
|
/* Context for this operation */
|
|
|
|
EVP_PKEY_CTX *ctx;
|
|
|
|
const char *op;
|
|
|
|
/* Input to decapsulate */
|
|
|
|
unsigned char *input;
|
|
|
|
size_t inputlen;
|
|
|
|
/* Expected secret */
|
|
|
|
unsigned char *output;
|
|
|
|
size_t outputlen;
|
|
|
|
STACK_OF(OPENSSL_STRING) *init_ctrls;
|
2024-11-13 21:18:13 +08:00
|
|
|
/* Algorithm name */
|
|
|
|
char *algname;
|
|
|
|
/* Name of previously generated key */
|
|
|
|
char *keyname;
|
|
|
|
/* Encoded public key */
|
|
|
|
unsigned char *encoded_pub_key;
|
|
|
|
size_t encoded_pub_key_len;
|
|
|
|
/* Encoded private key */
|
|
|
|
unsigned char *encoded_priv_key;
|
|
|
|
size_t encoded_priv_key_len;
|
|
|
|
/* Entropy for encapsulation */
|
|
|
|
unsigned char *entropy;
|
|
|
|
size_t entropylen;
|
|
|
|
/* Ciphertext */
|
|
|
|
unsigned char *ciphertext;
|
|
|
|
size_t ciphertext_len;
|
2024-07-03 09:12:39 +08:00
|
|
|
} KEM_DATA;
|
|
|
|
|
2024-11-13 21:18:13 +08:00
|
|
|
static int kem_test_init(EVP_TEST *t, const char *alg)
|
2024-07-03 09:12:39 +08:00
|
|
|
{
|
|
|
|
KEM_DATA *kdata = NULL;
|
|
|
|
EVP_PKEY *pkey = NULL;
|
|
|
|
|
2024-11-13 21:18:13 +08:00
|
|
|
if (!TEST_ptr(kdata = OPENSSL_zalloc(sizeof(*kdata)))
|
|
|
|
|| !TEST_ptr(kdata->algname = OPENSSL_strdup(alg)))
|
2024-07-03 09:12:39 +08:00
|
|
|
goto err;
|
|
|
|
|
|
|
|
kdata->init_ctrls = sk_OPENSSL_STRING_new_null();
|
2024-11-13 21:18:13 +08:00
|
|
|
t->data = kdata;
|
2024-07-03 09:12:39 +08:00
|
|
|
return 1;
|
|
|
|
err:
|
|
|
|
EVP_PKEY_free(pkey);
|
|
|
|
OPENSSL_free(kdata);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void kem_test_cleanup(EVP_TEST *t)
|
|
|
|
{
|
|
|
|
KEM_DATA *kdata = t->data;
|
|
|
|
|
|
|
|
ctrlfree(kdata->init_ctrls);
|
|
|
|
OPENSSL_free(kdata->input);
|
|
|
|
OPENSSL_free(kdata->output);
|
2024-11-13 21:18:13 +08:00
|
|
|
OPENSSL_free(kdata->algname);
|
|
|
|
OPENSSL_free(kdata->keyname);
|
|
|
|
OPENSSL_free(kdata->encoded_pub_key);
|
|
|
|
OPENSSL_free(kdata->encoded_priv_key);
|
|
|
|
OPENSSL_free(kdata->entropy);
|
|
|
|
OPENSSL_free(kdata->ciphertext);
|
2024-07-03 09:12:39 +08:00
|
|
|
EVP_PKEY_CTX_free(kdata->ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int kem_test_parse(EVP_TEST *t, const char *keyword, const char *value)
|
|
|
|
{
|
|
|
|
KEM_DATA *kdata = t->data;
|
|
|
|
|
|
|
|
if (strcmp(keyword, "Op") == 0) {
|
|
|
|
kdata->op = value;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (strcmp(keyword, "CtrlInit") == 0)
|
|
|
|
return ctrladd(kdata->init_ctrls, value);
|
|
|
|
if (strcmp(keyword, "Input") == 0)
|
|
|
|
return parse_bin(value, &kdata->input, &kdata->inputlen);
|
|
|
|
if (strcmp(keyword, "Output") == 0)
|
|
|
|
return parse_bin(value, &kdata->output, &kdata->outputlen);
|
2024-11-13 21:18:13 +08:00
|
|
|
if (strcmp(keyword, "EncodedPublicKey") == 0)
|
|
|
|
return parse_bin(value, &kdata->encoded_pub_key,
|
|
|
|
&kdata->encoded_pub_key_len);
|
|
|
|
if (strcmp(keyword, "EncodedPrivateKey") == 0)
|
|
|
|
return parse_bin(value, &kdata->encoded_priv_key,
|
|
|
|
&kdata->encoded_priv_key_len);
|
|
|
|
if (strcmp(keyword, "Entropy") == 0)
|
|
|
|
return parse_bin(value, &kdata->entropy, &kdata->entropylen);
|
|
|
|
if (strcmp(keyword, "Ciphertext") == 0)
|
|
|
|
return parse_bin(value, &kdata->ciphertext, &kdata->ciphertext_len);
|
|
|
|
if (strcmp(keyword, "KeyName") == 0)
|
|
|
|
return TEST_ptr(kdata->keyname = OPENSSL_strdup(value));
|
2024-07-03 09:12:39 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int encapsulate(EVP_TEST *t, EVP_PKEY_CTX *ctx, const char *op,
|
|
|
|
unsigned char **outwrapped, size_t *outwrappedlen,
|
|
|
|
unsigned char **outsecret, size_t *outsecretlen)
|
|
|
|
{
|
Multi-variant ML-KEM
This introduces support for ML-KEM-512 and ML-KEM-1024 using the same
underlying implementation parameterised by a few macros for the
associated types and constants.
KAT tests are added for ML-KEM 512 and 1024, to complement the previous
tests for ML-KEM-768.
MLKEM{512,768,1024} TLS "group" codepoints are updated to match the
final IANA assigments and to make the additional KEMs known to the TLS
layer.
The pure-QC MLKEMs are not in the default list of supported groups, and
need to be explicitly enabled by the application. Future work will
introduce support for hybrids, and for more fine-grained policy of
which keyshares a client should send by default, and when a server
should request (HRR) a new mutually-supported group that was not
sent.
Tests for ML-KEM key exchange added to sslapitest to make sure that our
TLS client MLKEM{512,768,1024} implementations interoperate with our TLS
server, and that MLKEM* are not negotiated in TLS 1.2.
Tests also added to excercise non-derandomised ML-KEM APIs, both
directly (bypassing the provider layer), and through the generic EVP KEM
API (exercising the provider). These make sure that RNG input is used
correctly (KAT tests bypass the RNG by specifying seeds).
The API interface to the provider takes an "const ML_KEM_VINFO" pointer,
(obtained from ossl_ml_kem_get_vinfo()). This checks input and output
buffer sizes before passing control to internal code that assumes
correctly sized (for each variant) buffers.
The original BoringSSL API was refactored to eliminate the opaque
public/private key structure wrappers, since these structures are an
internal detail between libcrypto and the provider, they are not part of
the public (EVP) API.
New "clangover" counter-measures added, refined with much appreciated
input from David Benjamin (Chromium).
The internal steps of "encrypt_cpa" were reordered to reduce the
working-set size of the algorithm, now needs space for just two
temporary "vectors" rather than three. The "decap" function now process
the decrypted message in one call, rather than three separate calls to
scalar_decode_1, scalar_decompress and scalar_add.
Some loops were unrolled, improving performance of en/decapsulate
(pre-expanded vectors and matrix) by around 5%.
To handle, however unlikely, the SHA3 primitives not behaving like
"pure" functions and failing, the implementation of `decap` was modifed:
- To use the KDF to compute the Fujisaki-Okamoto (FO) failure secret
first thing, and if that fails, bail out returning an error, a shared
secret is still returned at random from the RNG, but it is OK for the
caller to not use it.
- If any of the subsequently used hash primitives fail, use the computed
FO failure secret (OK, despite no longer constant-time) and return
success (otherwise the RNG would replace the result).
- We quite reasonably assume that chosen-ciphertext attacks (of the
correct length) cannot cause hash functions to fail in a manner the
depends on the private key content.
Support for ML-KEM-512 required adding a centered binomial distribution
helper function to deal with η_1 == 3 in just that variant.
Some additional comments were added to highlight how the code relates to
the ML-KEM specification in FIPS 203.
Reviewed-by: Paul Dale <ppzgs1@gmail.com>
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26172)
2024-11-30 22:20:58 +08:00
|
|
|
int ret = 0;
|
2024-07-03 09:12:39 +08:00
|
|
|
KEM_DATA *kdata = t->data;
|
|
|
|
unsigned char *wrapped = NULL, *secret = NULL;
|
|
|
|
size_t wrappedlen = 0, secretlen = 0;
|
2024-12-09 10:03:03 +08:00
|
|
|
OSSL_PARAM params[10];
|
Multi-variant ML-KEM
This introduces support for ML-KEM-512 and ML-KEM-1024 using the same
underlying implementation parameterised by a few macros for the
associated types and constants.
KAT tests are added for ML-KEM 512 and 1024, to complement the previous
tests for ML-KEM-768.
MLKEM{512,768,1024} TLS "group" codepoints are updated to match the
final IANA assigments and to make the additional KEMs known to the TLS
layer.
The pure-QC MLKEMs are not in the default list of supported groups, and
need to be explicitly enabled by the application. Future work will
introduce support for hybrids, and for more fine-grained policy of
which keyshares a client should send by default, and when a server
should request (HRR) a new mutually-supported group that was not
sent.
Tests for ML-KEM key exchange added to sslapitest to make sure that our
TLS client MLKEM{512,768,1024} implementations interoperate with our TLS
server, and that MLKEM* are not negotiated in TLS 1.2.
Tests also added to excercise non-derandomised ML-KEM APIs, both
directly (bypassing the provider layer), and through the generic EVP KEM
API (exercising the provider). These make sure that RNG input is used
correctly (KAT tests bypass the RNG by specifying seeds).
The API interface to the provider takes an "const ML_KEM_VINFO" pointer,
(obtained from ossl_ml_kem_get_vinfo()). This checks input and output
buffer sizes before passing control to internal code that assumes
correctly sized (for each variant) buffers.
The original BoringSSL API was refactored to eliminate the opaque
public/private key structure wrappers, since these structures are an
internal detail between libcrypto and the provider, they are not part of
the public (EVP) API.
New "clangover" counter-measures added, refined with much appreciated
input from David Benjamin (Chromium).
The internal steps of "encrypt_cpa" were reordered to reduce the
working-set size of the algorithm, now needs space for just two
temporary "vectors" rather than three. The "decap" function now process
the decrypted message in one call, rather than three separate calls to
scalar_decode_1, scalar_decompress and scalar_add.
Some loops were unrolled, improving performance of en/decapsulate
(pre-expanded vectors and matrix) by around 5%.
To handle, however unlikely, the SHA3 primitives not behaving like
"pure" functions and failing, the implementation of `decap` was modifed:
- To use the KDF to compute the Fujisaki-Okamoto (FO) failure secret
first thing, and if that fails, bail out returning an error, a shared
secret is still returned at random from the RNG, but it is OK for the
caller to not use it.
- If any of the subsequently used hash primitives fail, use the computed
FO failure secret (OK, despite no longer constant-time) and return
success (otherwise the RNG would replace the result).
- We quite reasonably assume that chosen-ciphertext attacks (of the
correct length) cannot cause hash functions to fail in a manner the
depends on the private key content.
Support for ML-KEM-512 required adding a centered binomial distribution
helper function to deal with η_1 == 3 in just that variant.
Some additional comments were added to highlight how the code relates to
the ML-KEM specification in FIPS 203.
Reviewed-by: Paul Dale <ppzgs1@gmail.com>
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26172)
2024-11-30 22:20:58 +08:00
|
|
|
size_t params_n = 0;
|
2024-12-09 10:03:03 +08:00
|
|
|
/* Reserve space for the terminator and possibly IKME */
|
|
|
|
const size_t params_max = OSSL_NELEM(params) - 1 - (kdata->entropy != NULL);
|
2024-07-03 09:12:39 +08:00
|
|
|
|
Multi-variant ML-KEM
This introduces support for ML-KEM-512 and ML-KEM-1024 using the same
underlying implementation parameterised by a few macros for the
associated types and constants.
KAT tests are added for ML-KEM 512 and 1024, to complement the previous
tests for ML-KEM-768.
MLKEM{512,768,1024} TLS "group" codepoints are updated to match the
final IANA assigments and to make the additional KEMs known to the TLS
layer.
The pure-QC MLKEMs are not in the default list of supported groups, and
need to be explicitly enabled by the application. Future work will
introduce support for hybrids, and for more fine-grained policy of
which keyshares a client should send by default, and when a server
should request (HRR) a new mutually-supported group that was not
sent.
Tests for ML-KEM key exchange added to sslapitest to make sure that our
TLS client MLKEM{512,768,1024} implementations interoperate with our TLS
server, and that MLKEM* are not negotiated in TLS 1.2.
Tests also added to excercise non-derandomised ML-KEM APIs, both
directly (bypassing the provider layer), and through the generic EVP KEM
API (exercising the provider). These make sure that RNG input is used
correctly (KAT tests bypass the RNG by specifying seeds).
The API interface to the provider takes an "const ML_KEM_VINFO" pointer,
(obtained from ossl_ml_kem_get_vinfo()). This checks input and output
buffer sizes before passing control to internal code that assumes
correctly sized (for each variant) buffers.
The original BoringSSL API was refactored to eliminate the opaque
public/private key structure wrappers, since these structures are an
internal detail between libcrypto and the provider, they are not part of
the public (EVP) API.
New "clangover" counter-measures added, refined with much appreciated
input from David Benjamin (Chromium).
The internal steps of "encrypt_cpa" were reordered to reduce the
working-set size of the algorithm, now needs space for just two
temporary "vectors" rather than three. The "decap" function now process
the decrypted message in one call, rather than three separate calls to
scalar_decode_1, scalar_decompress and scalar_add.
Some loops were unrolled, improving performance of en/decapsulate
(pre-expanded vectors and matrix) by around 5%.
To handle, however unlikely, the SHA3 primitives not behaving like
"pure" functions and failing, the implementation of `decap` was modifed:
- To use the KDF to compute the Fujisaki-Okamoto (FO) failure secret
first thing, and if that fails, bail out returning an error, a shared
secret is still returned at random from the RNG, but it is OK for the
caller to not use it.
- If any of the subsequently used hash primitives fail, use the computed
FO failure secret (OK, despite no longer constant-time) and return
success (otherwise the RNG would replace the result).
- We quite reasonably assume that chosen-ciphertext attacks (of the
correct length) cannot cause hash functions to fail in a manner the
depends on the private key content.
Support for ML-KEM-512 required adding a centered binomial distribution
helper function to deal with η_1 == 3 in just that variant.
Some additional comments were added to highlight how the code relates to
the ML-KEM specification in FIPS 203.
Reviewed-by: Paul Dale <ppzgs1@gmail.com>
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26172)
2024-11-30 22:20:58 +08:00
|
|
|
if (sk_OPENSSL_STRING_num(kdata->init_ctrls) > 0)
|
2025-03-03 08:45:27 +08:00
|
|
|
if (!ctrl2params(t, kdata->init_ctrls, NULL, params, params_max,
|
|
|
|
¶ms_n))
|
2024-07-03 09:12:39 +08:00
|
|
|
goto err;
|
2024-11-13 21:18:13 +08:00
|
|
|
|
Multi-variant ML-KEM
This introduces support for ML-KEM-512 and ML-KEM-1024 using the same
underlying implementation parameterised by a few macros for the
associated types and constants.
KAT tests are added for ML-KEM 512 and 1024, to complement the previous
tests for ML-KEM-768.
MLKEM{512,768,1024} TLS "group" codepoints are updated to match the
final IANA assigments and to make the additional KEMs known to the TLS
layer.
The pure-QC MLKEMs are not in the default list of supported groups, and
need to be explicitly enabled by the application. Future work will
introduce support for hybrids, and for more fine-grained policy of
which keyshares a client should send by default, and when a server
should request (HRR) a new mutually-supported group that was not
sent.
Tests for ML-KEM key exchange added to sslapitest to make sure that our
TLS client MLKEM{512,768,1024} implementations interoperate with our TLS
server, and that MLKEM* are not negotiated in TLS 1.2.
Tests also added to excercise non-derandomised ML-KEM APIs, both
directly (bypassing the provider layer), and through the generic EVP KEM
API (exercising the provider). These make sure that RNG input is used
correctly (KAT tests bypass the RNG by specifying seeds).
The API interface to the provider takes an "const ML_KEM_VINFO" pointer,
(obtained from ossl_ml_kem_get_vinfo()). This checks input and output
buffer sizes before passing control to internal code that assumes
correctly sized (for each variant) buffers.
The original BoringSSL API was refactored to eliminate the opaque
public/private key structure wrappers, since these structures are an
internal detail between libcrypto and the provider, they are not part of
the public (EVP) API.
New "clangover" counter-measures added, refined with much appreciated
input from David Benjamin (Chromium).
The internal steps of "encrypt_cpa" were reordered to reduce the
working-set size of the algorithm, now needs space for just two
temporary "vectors" rather than three. The "decap" function now process
the decrypted message in one call, rather than three separate calls to
scalar_decode_1, scalar_decompress and scalar_add.
Some loops were unrolled, improving performance of en/decapsulate
(pre-expanded vectors and matrix) by around 5%.
To handle, however unlikely, the SHA3 primitives not behaving like
"pure" functions and failing, the implementation of `decap` was modifed:
- To use the KDF to compute the Fujisaki-Okamoto (FO) failure secret
first thing, and if that fails, bail out returning an error, a shared
secret is still returned at random from the RNG, but it is OK for the
caller to not use it.
- If any of the subsequently used hash primitives fail, use the computed
FO failure secret (OK, despite no longer constant-time) and return
success (otherwise the RNG would replace the result).
- We quite reasonably assume that chosen-ciphertext attacks (of the
correct length) cannot cause hash functions to fail in a manner the
depends on the private key content.
Support for ML-KEM-512 required adding a centered binomial distribution
helper function to deal with η_1 == 3 in just that variant.
Some additional comments were added to highlight how the code relates to
the ML-KEM specification in FIPS 203.
Reviewed-by: Paul Dale <ppzgs1@gmail.com>
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26172)
2024-11-30 22:20:58 +08:00
|
|
|
/* We don't expect very many controls here */
|
2024-12-09 10:03:03 +08:00
|
|
|
if (!TEST_size_t_lt(params_n, params_max))
|
2024-11-13 21:18:13 +08:00
|
|
|
goto err;
|
|
|
|
|
2024-12-09 10:03:03 +08:00
|
|
|
if (kdata->entropy != NULL)
|
Multi-variant ML-KEM
This introduces support for ML-KEM-512 and ML-KEM-1024 using the same
underlying implementation parameterised by a few macros for the
associated types and constants.
KAT tests are added for ML-KEM 512 and 1024, to complement the previous
tests for ML-KEM-768.
MLKEM{512,768,1024} TLS "group" codepoints are updated to match the
final IANA assigments and to make the additional KEMs known to the TLS
layer.
The pure-QC MLKEMs are not in the default list of supported groups, and
need to be explicitly enabled by the application. Future work will
introduce support for hybrids, and for more fine-grained policy of
which keyshares a client should send by default, and when a server
should request (HRR) a new mutually-supported group that was not
sent.
Tests for ML-KEM key exchange added to sslapitest to make sure that our
TLS client MLKEM{512,768,1024} implementations interoperate with our TLS
server, and that MLKEM* are not negotiated in TLS 1.2.
Tests also added to excercise non-derandomised ML-KEM APIs, both
directly (bypassing the provider layer), and through the generic EVP KEM
API (exercising the provider). These make sure that RNG input is used
correctly (KAT tests bypass the RNG by specifying seeds).
The API interface to the provider takes an "const ML_KEM_VINFO" pointer,
(obtained from ossl_ml_kem_get_vinfo()). This checks input and output
buffer sizes before passing control to internal code that assumes
correctly sized (for each variant) buffers.
The original BoringSSL API was refactored to eliminate the opaque
public/private key structure wrappers, since these structures are an
internal detail between libcrypto and the provider, they are not part of
the public (EVP) API.
New "clangover" counter-measures added, refined with much appreciated
input from David Benjamin (Chromium).
The internal steps of "encrypt_cpa" were reordered to reduce the
working-set size of the algorithm, now needs space for just two
temporary "vectors" rather than three. The "decap" function now process
the decrypted message in one call, rather than three separate calls to
scalar_decode_1, scalar_decompress and scalar_add.
Some loops were unrolled, improving performance of en/decapsulate
(pre-expanded vectors and matrix) by around 5%.
To handle, however unlikely, the SHA3 primitives not behaving like
"pure" functions and failing, the implementation of `decap` was modifed:
- To use the KDF to compute the Fujisaki-Okamoto (FO) failure secret
first thing, and if that fails, bail out returning an error, a shared
secret is still returned at random from the RNG, but it is OK for the
caller to not use it.
- If any of the subsequently used hash primitives fail, use the computed
FO failure secret (OK, despite no longer constant-time) and return
success (otherwise the RNG would replace the result).
- We quite reasonably assume that chosen-ciphertext attacks (of the
correct length) cannot cause hash functions to fail in a manner the
depends on the private key content.
Support for ML-KEM-512 required adding a centered binomial distribution
helper function to deal with η_1 == 3 in just that variant.
Some additional comments were added to highlight how the code relates to
the ML-KEM specification in FIPS 203.
Reviewed-by: Paul Dale <ppzgs1@gmail.com>
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26172)
2024-11-30 22:20:58 +08:00
|
|
|
/* Input key material a.k.a entropy */
|
2024-12-09 10:03:03 +08:00
|
|
|
params[params_n++] =
|
Multi-variant ML-KEM
This introduces support for ML-KEM-512 and ML-KEM-1024 using the same
underlying implementation parameterised by a few macros for the
associated types and constants.
KAT tests are added for ML-KEM 512 and 1024, to complement the previous
tests for ML-KEM-768.
MLKEM{512,768,1024} TLS "group" codepoints are updated to match the
final IANA assigments and to make the additional KEMs known to the TLS
layer.
The pure-QC MLKEMs are not in the default list of supported groups, and
need to be explicitly enabled by the application. Future work will
introduce support for hybrids, and for more fine-grained policy of
which keyshares a client should send by default, and when a server
should request (HRR) a new mutually-supported group that was not
sent.
Tests for ML-KEM key exchange added to sslapitest to make sure that our
TLS client MLKEM{512,768,1024} implementations interoperate with our TLS
server, and that MLKEM* are not negotiated in TLS 1.2.
Tests also added to excercise non-derandomised ML-KEM APIs, both
directly (bypassing the provider layer), and through the generic EVP KEM
API (exercising the provider). These make sure that RNG input is used
correctly (KAT tests bypass the RNG by specifying seeds).
The API interface to the provider takes an "const ML_KEM_VINFO" pointer,
(obtained from ossl_ml_kem_get_vinfo()). This checks input and output
buffer sizes before passing control to internal code that assumes
correctly sized (for each variant) buffers.
The original BoringSSL API was refactored to eliminate the opaque
public/private key structure wrappers, since these structures are an
internal detail between libcrypto and the provider, they are not part of
the public (EVP) API.
New "clangover" counter-measures added, refined with much appreciated
input from David Benjamin (Chromium).
The internal steps of "encrypt_cpa" were reordered to reduce the
working-set size of the algorithm, now needs space for just two
temporary "vectors" rather than three. The "decap" function now process
the decrypted message in one call, rather than three separate calls to
scalar_decode_1, scalar_decompress and scalar_add.
Some loops were unrolled, improving performance of en/decapsulate
(pre-expanded vectors and matrix) by around 5%.
To handle, however unlikely, the SHA3 primitives not behaving like
"pure" functions and failing, the implementation of `decap` was modifed:
- To use the KDF to compute the Fujisaki-Okamoto (FO) failure secret
first thing, and if that fails, bail out returning an error, a shared
secret is still returned at random from the RNG, but it is OK for the
caller to not use it.
- If any of the subsequently used hash primitives fail, use the computed
FO failure secret (OK, despite no longer constant-time) and return
success (otherwise the RNG would replace the result).
- We quite reasonably assume that chosen-ciphertext attacks (of the
correct length) cannot cause hash functions to fail in a manner the
depends on the private key content.
Support for ML-KEM-512 required adding a centered binomial distribution
helper function to deal with η_1 == 3 in just that variant.
Some additional comments were added to highlight how the code relates to
the ML-KEM specification in FIPS 203.
Reviewed-by: Paul Dale <ppzgs1@gmail.com>
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26172)
2024-11-30 22:20:58 +08:00
|
|
|
OSSL_PARAM_construct_octet_string(OSSL_KEM_PARAM_IKME,
|
|
|
|
kdata->entropy,
|
|
|
|
kdata->entropylen);
|
2024-12-09 10:03:03 +08:00
|
|
|
params[params_n] = OSSL_PARAM_construct_end();
|
Multi-variant ML-KEM
This introduces support for ML-KEM-512 and ML-KEM-1024 using the same
underlying implementation parameterised by a few macros for the
associated types and constants.
KAT tests are added for ML-KEM 512 and 1024, to complement the previous
tests for ML-KEM-768.
MLKEM{512,768,1024} TLS "group" codepoints are updated to match the
final IANA assigments and to make the additional KEMs known to the TLS
layer.
The pure-QC MLKEMs are not in the default list of supported groups, and
need to be explicitly enabled by the application. Future work will
introduce support for hybrids, and for more fine-grained policy of
which keyshares a client should send by default, and when a server
should request (HRR) a new mutually-supported group that was not
sent.
Tests for ML-KEM key exchange added to sslapitest to make sure that our
TLS client MLKEM{512,768,1024} implementations interoperate with our TLS
server, and that MLKEM* are not negotiated in TLS 1.2.
Tests also added to excercise non-derandomised ML-KEM APIs, both
directly (bypassing the provider layer), and through the generic EVP KEM
API (exercising the provider). These make sure that RNG input is used
correctly (KAT tests bypass the RNG by specifying seeds).
The API interface to the provider takes an "const ML_KEM_VINFO" pointer,
(obtained from ossl_ml_kem_get_vinfo()). This checks input and output
buffer sizes before passing control to internal code that assumes
correctly sized (for each variant) buffers.
The original BoringSSL API was refactored to eliminate the opaque
public/private key structure wrappers, since these structures are an
internal detail between libcrypto and the provider, they are not part of
the public (EVP) API.
New "clangover" counter-measures added, refined with much appreciated
input from David Benjamin (Chromium).
The internal steps of "encrypt_cpa" were reordered to reduce the
working-set size of the algorithm, now needs space for just two
temporary "vectors" rather than three. The "decap" function now process
the decrypted message in one call, rather than three separate calls to
scalar_decode_1, scalar_decompress and scalar_add.
Some loops were unrolled, improving performance of en/decapsulate
(pre-expanded vectors and matrix) by around 5%.
To handle, however unlikely, the SHA3 primitives not behaving like
"pure" functions and failing, the implementation of `decap` was modifed:
- To use the KDF to compute the Fujisaki-Okamoto (FO) failure secret
first thing, and if that fails, bail out returning an error, a shared
secret is still returned at random from the RNG, but it is OK for the
caller to not use it.
- If any of the subsequently used hash primitives fail, use the computed
FO failure secret (OK, despite no longer constant-time) and return
success (otherwise the RNG would replace the result).
- We quite reasonably assume that chosen-ciphertext attacks (of the
correct length) cannot cause hash functions to fail in a manner the
depends on the private key content.
Support for ML-KEM-512 required adding a centered binomial distribution
helper function to deal with η_1 == 3 in just that variant.
Some additional comments were added to highlight how the code relates to
the ML-KEM specification in FIPS 203.
Reviewed-by: Paul Dale <ppzgs1@gmail.com>
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26172)
2024-11-30 22:20:58 +08:00
|
|
|
|
2024-11-13 21:18:13 +08:00
|
|
|
if (EVP_PKEY_encapsulate_init(ctx, params) <= 0) {
|
2024-07-03 09:12:39 +08:00
|
|
|
t->err = "TEST_ENCAPSULATE_INIT_ERROR";
|
2025-03-03 08:45:27 +08:00
|
|
|
goto ok;
|
2024-07-03 09:12:39 +08:00
|
|
|
}
|
|
|
|
|
2024-11-13 21:18:13 +08:00
|
|
|
if (op != NULL && EVP_PKEY_CTX_set_kem_op(ctx, op) <= 0) {
|
2024-07-03 09:12:39 +08:00
|
|
|
t->err = "TEST_SET_KEM_OP_ERROR";
|
2025-03-03 08:45:27 +08:00
|
|
|
goto ok;
|
2024-07-03 09:12:39 +08:00
|
|
|
}
|
|
|
|
if (EVP_PKEY_encapsulate(ctx, NULL, &wrappedlen, NULL, &secretlen) <= 0) {
|
|
|
|
t->err = "TEST_ENCAPSULATE_LEN_ERROR";
|
2025-03-03 08:45:27 +08:00
|
|
|
goto ok;
|
2024-07-03 09:12:39 +08:00
|
|
|
}
|
|
|
|
wrapped = OPENSSL_malloc(wrappedlen);
|
|
|
|
secret = OPENSSL_malloc(secretlen);
|
|
|
|
if (!TEST_ptr(wrapped) || !TEST_ptr(secret)) {
|
|
|
|
ret = 0;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
if (EVP_PKEY_encapsulate(ctx, wrapped, &wrappedlen, secret, &secretlen) <= 0) {
|
|
|
|
t->err = "TEST_ENCAPSULATE_ERROR";
|
2025-03-03 08:45:27 +08:00
|
|
|
goto ok;
|
2024-07-03 09:12:39 +08:00
|
|
|
}
|
|
|
|
ret = pkey_check_fips_approved(ctx, t);
|
2024-11-13 21:18:13 +08:00
|
|
|
|
|
|
|
if (kdata->ciphertext != NULL
|
|
|
|
&& !TEST_mem_eq(wrapped, wrappedlen, kdata->ciphertext, kdata->ciphertext_len)) {
|
|
|
|
ret = 0;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (kdata->output != NULL
|
|
|
|
&& !TEST_mem_eq(secret, secretlen, kdata->output, kdata->outputlen)) {
|
|
|
|
ret = 0;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2024-07-03 09:12:39 +08:00
|
|
|
if (ret == 0)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
t->err = NULL;
|
|
|
|
*outwrapped = wrapped;
|
|
|
|
*outsecret = secret;
|
|
|
|
*outwrappedlen = wrappedlen;
|
|
|
|
*outsecretlen = secretlen;
|
2025-03-03 08:45:27 +08:00
|
|
|
ok:
|
2024-07-03 09:12:39 +08:00
|
|
|
ret = 1;
|
|
|
|
err:
|
2025-03-03 08:45:27 +08:00
|
|
|
if (ret == 0) {
|
|
|
|
OPENSSL_free(wrapped);
|
|
|
|
OPENSSL_free(secret);
|
|
|
|
}
|
2024-11-13 21:18:13 +08:00
|
|
|
if (sk_OPENSSL_STRING_num(kdata->init_ctrls) > 0)
|
Multi-variant ML-KEM
This introduces support for ML-KEM-512 and ML-KEM-1024 using the same
underlying implementation parameterised by a few macros for the
associated types and constants.
KAT tests are added for ML-KEM 512 and 1024, to complement the previous
tests for ML-KEM-768.
MLKEM{512,768,1024} TLS "group" codepoints are updated to match the
final IANA assigments and to make the additional KEMs known to the TLS
layer.
The pure-QC MLKEMs are not in the default list of supported groups, and
need to be explicitly enabled by the application. Future work will
introduce support for hybrids, and for more fine-grained policy of
which keyshares a client should send by default, and when a server
should request (HRR) a new mutually-supported group that was not
sent.
Tests for ML-KEM key exchange added to sslapitest to make sure that our
TLS client MLKEM{512,768,1024} implementations interoperate with our TLS
server, and that MLKEM* are not negotiated in TLS 1.2.
Tests also added to excercise non-derandomised ML-KEM APIs, both
directly (bypassing the provider layer), and through the generic EVP KEM
API (exercising the provider). These make sure that RNG input is used
correctly (KAT tests bypass the RNG by specifying seeds).
The API interface to the provider takes an "const ML_KEM_VINFO" pointer,
(obtained from ossl_ml_kem_get_vinfo()). This checks input and output
buffer sizes before passing control to internal code that assumes
correctly sized (for each variant) buffers.
The original BoringSSL API was refactored to eliminate the opaque
public/private key structure wrappers, since these structures are an
internal detail between libcrypto and the provider, they are not part of
the public (EVP) API.
New "clangover" counter-measures added, refined with much appreciated
input from David Benjamin (Chromium).
The internal steps of "encrypt_cpa" were reordered to reduce the
working-set size of the algorithm, now needs space for just two
temporary "vectors" rather than three. The "decap" function now process
the decrypted message in one call, rather than three separate calls to
scalar_decode_1, scalar_decompress and scalar_add.
Some loops were unrolled, improving performance of en/decapsulate
(pre-expanded vectors and matrix) by around 5%.
To handle, however unlikely, the SHA3 primitives not behaving like
"pure" functions and failing, the implementation of `decap` was modifed:
- To use the KDF to compute the Fujisaki-Okamoto (FO) failure secret
first thing, and if that fails, bail out returning an error, a shared
secret is still returned at random from the RNG, but it is OK for the
caller to not use it.
- If any of the subsequently used hash primitives fail, use the computed
FO failure secret (OK, despite no longer constant-time) and return
success (otherwise the RNG would replace the result).
- We quite reasonably assume that chosen-ciphertext attacks (of the
correct length) cannot cause hash functions to fail in a manner the
depends on the private key content.
Support for ML-KEM-512 required adding a centered binomial distribution
helper function to deal with η_1 == 3 in just that variant.
Some additional comments were added to highlight how the code relates to
the ML-KEM specification in FIPS 203.
Reviewed-by: Paul Dale <ppzgs1@gmail.com>
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26172)
2024-11-30 22:20:58 +08:00
|
|
|
ctrl2params_free(params, params_n, 0);
|
2024-07-03 09:12:39 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int decapsulate(EVP_TEST *t, EVP_PKEY_CTX *ctx, const char *op,
|
|
|
|
const unsigned char *in, size_t inlen,
|
|
|
|
const unsigned char *expected, size_t expectedlen)
|
|
|
|
{
|
Multi-variant ML-KEM
This introduces support for ML-KEM-512 and ML-KEM-1024 using the same
underlying implementation parameterised by a few macros for the
associated types and constants.
KAT tests are added for ML-KEM 512 and 1024, to complement the previous
tests for ML-KEM-768.
MLKEM{512,768,1024} TLS "group" codepoints are updated to match the
final IANA assigments and to make the additional KEMs known to the TLS
layer.
The pure-QC MLKEMs are not in the default list of supported groups, and
need to be explicitly enabled by the application. Future work will
introduce support for hybrids, and for more fine-grained policy of
which keyshares a client should send by default, and when a server
should request (HRR) a new mutually-supported group that was not
sent.
Tests for ML-KEM key exchange added to sslapitest to make sure that our
TLS client MLKEM{512,768,1024} implementations interoperate with our TLS
server, and that MLKEM* are not negotiated in TLS 1.2.
Tests also added to excercise non-derandomised ML-KEM APIs, both
directly (bypassing the provider layer), and through the generic EVP KEM
API (exercising the provider). These make sure that RNG input is used
correctly (KAT tests bypass the RNG by specifying seeds).
The API interface to the provider takes an "const ML_KEM_VINFO" pointer,
(obtained from ossl_ml_kem_get_vinfo()). This checks input and output
buffer sizes before passing control to internal code that assumes
correctly sized (for each variant) buffers.
The original BoringSSL API was refactored to eliminate the opaque
public/private key structure wrappers, since these structures are an
internal detail between libcrypto and the provider, they are not part of
the public (EVP) API.
New "clangover" counter-measures added, refined with much appreciated
input from David Benjamin (Chromium).
The internal steps of "encrypt_cpa" were reordered to reduce the
working-set size of the algorithm, now needs space for just two
temporary "vectors" rather than three. The "decap" function now process
the decrypted message in one call, rather than three separate calls to
scalar_decode_1, scalar_decompress and scalar_add.
Some loops were unrolled, improving performance of en/decapsulate
(pre-expanded vectors and matrix) by around 5%.
To handle, however unlikely, the SHA3 primitives not behaving like
"pure" functions and failing, the implementation of `decap` was modifed:
- To use the KDF to compute the Fujisaki-Okamoto (FO) failure secret
first thing, and if that fails, bail out returning an error, a shared
secret is still returned at random from the RNG, but it is OK for the
caller to not use it.
- If any of the subsequently used hash primitives fail, use the computed
FO failure secret (OK, despite no longer constant-time) and return
success (otherwise the RNG would replace the result).
- We quite reasonably assume that chosen-ciphertext attacks (of the
correct length) cannot cause hash functions to fail in a manner the
depends on the private key content.
Support for ML-KEM-512 required adding a centered binomial distribution
helper function to deal with η_1 == 3 in just that variant.
Some additional comments were added to highlight how the code relates to
the ML-KEM specification in FIPS 203.
Reviewed-by: Paul Dale <ppzgs1@gmail.com>
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26172)
2024-11-30 22:20:58 +08:00
|
|
|
int ret = 0;
|
2024-07-03 09:12:39 +08:00
|
|
|
KEM_DATA *kdata = t->data;
|
|
|
|
size_t outlen = 0;
|
|
|
|
unsigned char *out = NULL;
|
|
|
|
OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
|
|
|
|
OSSL_PARAM *p = NULL;
|
|
|
|
size_t params_n = 0, params_n_allocated = 0;
|
|
|
|
|
|
|
|
if (sk_OPENSSL_STRING_num(kdata->init_ctrls) > 0) {
|
|
|
|
if (!ctrl2params(t, kdata->init_ctrls, NULL,
|
2024-11-13 21:18:13 +08:00
|
|
|
params, 2, ¶ms_n))
|
2024-07-03 09:12:39 +08:00
|
|
|
goto err;
|
|
|
|
p = params;
|
|
|
|
}
|
2024-11-13 21:18:13 +08:00
|
|
|
|
2024-07-03 09:12:39 +08:00
|
|
|
if (EVP_PKEY_decapsulate_init(ctx, p) <= 0) {
|
|
|
|
t->err = "TEST_DECAPSULATE_INIT_ERROR";
|
2025-03-03 08:45:27 +08:00
|
|
|
goto ok;
|
2024-07-03 09:12:39 +08:00
|
|
|
}
|
|
|
|
|
2024-11-13 21:18:13 +08:00
|
|
|
if (op != NULL && EVP_PKEY_CTX_set_kem_op(ctx, op) <= 0) {
|
2024-07-03 09:12:39 +08:00
|
|
|
t->err = "TEST_SET_KEM_OP_ERROR";
|
2025-03-03 08:45:27 +08:00
|
|
|
goto ok;
|
2024-07-03 09:12:39 +08:00
|
|
|
}
|
|
|
|
if (EVP_PKEY_decapsulate(ctx, NULL, &outlen, in, inlen) <= 0) {
|
|
|
|
t->err = "TEST_DECAPSULATE_LEN_ERROR";
|
2025-03-03 08:45:27 +08:00
|
|
|
goto ok;
|
2024-07-03 09:12:39 +08:00
|
|
|
}
|
|
|
|
if (!TEST_ptr(out = OPENSSL_malloc(outlen))) {
|
|
|
|
ret = 0;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (EVP_PKEY_decapsulate(ctx, out, &outlen, in, inlen) <= 0) {
|
|
|
|
t->err = "TEST_DECAPSULATE_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
if (!TEST_mem_eq(out, outlen, expected, expectedlen)) {
|
|
|
|
t->err = "TEST_SECRET_MISMATCH";
|
2025-03-03 08:45:27 +08:00
|
|
|
goto ok;
|
2024-07-03 09:12:39 +08:00
|
|
|
}
|
|
|
|
t->err = NULL;
|
2025-03-03 08:45:27 +08:00
|
|
|
ok:
|
2024-07-03 09:12:39 +08:00
|
|
|
ret = 1;
|
|
|
|
err:
|
|
|
|
OPENSSL_free(out);
|
2024-11-13 21:18:13 +08:00
|
|
|
if (sk_OPENSSL_STRING_num(kdata->init_ctrls) > 0)
|
|
|
|
ctrl2params_free(params, params_n, params_n_allocated);
|
2024-07-03 09:12:39 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int kem_test_run(EVP_TEST *t)
|
|
|
|
{
|
2024-11-13 21:18:13 +08:00
|
|
|
int ret = 0, found_key = 0;
|
|
|
|
EVP_PKEY *pkey = NULL;
|
2024-07-03 09:12:39 +08:00
|
|
|
KEM_DATA *kdata = t->data;
|
|
|
|
unsigned char *wrapped = NULL, *secret = NULL;
|
|
|
|
|
2024-11-13 21:18:13 +08:00
|
|
|
/* Generate either public or private key based on given params */
|
|
|
|
if (kdata->keyname != NULL) {
|
|
|
|
/* Previously generated private key */
|
|
|
|
found_key = find_key(&pkey, kdata->keyname, private_keys);
|
|
|
|
if (found_key == 0 || pkey == NULL) {
|
|
|
|
TEST_info("skipping, key '%s' is disabled", kdata->keyname);
|
|
|
|
t->skip = 1;
|
|
|
|
goto ok;
|
|
|
|
}
|
|
|
|
} else if (kdata->encoded_pub_key != NULL) {
|
|
|
|
/* Encoded public key */
|
|
|
|
if ((pkey = EVP_PKEY_new_raw_public_key_ex(libctx, kdata->algname,
|
|
|
|
propquery,
|
|
|
|
kdata->encoded_pub_key,
|
|
|
|
kdata->encoded_pub_key_len)) == NULL) {
|
|
|
|
t->err = "TEST_PARSE_PUBLIC_KEY_ERROR";
|
|
|
|
goto ok;
|
|
|
|
}
|
|
|
|
} else if (kdata->encoded_priv_key != NULL) {
|
|
|
|
/* Encoded private key */
|
|
|
|
if ((pkey = EVP_PKEY_new_raw_private_key_ex(libctx, kdata->algname,
|
|
|
|
propquery,
|
|
|
|
kdata->encoded_priv_key,
|
|
|
|
kdata->encoded_priv_key_len)) == NULL) {
|
|
|
|
t->err = "TEST_PARSE_PRIVATE_KEY_ERROR";
|
|
|
|
goto ok;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
TEST_info("Missing parameters to create key");
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2025-05-06 09:32:21 +08:00
|
|
|
if (!pkey_check_security_category(t, pkey))
|
|
|
|
goto err;
|
|
|
|
|
2024-11-13 21:18:13 +08:00
|
|
|
if (!TEST_ptr(kdata->ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propquery)))
|
|
|
|
goto err;
|
|
|
|
|
2024-07-03 09:12:39 +08:00
|
|
|
if (kdata->input == NULL) {
|
|
|
|
size_t wrappedlen = 0, secretlen = 0;
|
|
|
|
|
|
|
|
ret = encapsulate(t, kdata->ctx, kdata->op, &wrapped, &wrappedlen,
|
|
|
|
&secret, &secretlen);
|
|
|
|
if (ret == 0 || t->err != NULL)
|
|
|
|
goto err;
|
2024-11-13 21:18:13 +08:00
|
|
|
|
|
|
|
/* Also attempt to decrypt if we have the private key */
|
|
|
|
if (found_key || kdata->encoded_priv_key != NULL)
|
|
|
|
ret = decapsulate(t, kdata->ctx, kdata->op, wrapped, wrappedlen,
|
|
|
|
secret, secretlen);
|
2024-07-03 09:12:39 +08:00
|
|
|
} else {
|
|
|
|
ret = decapsulate(t, kdata->ctx, kdata->op, kdata->input, kdata->inputlen,
|
|
|
|
kdata->output, kdata->outputlen);
|
|
|
|
}
|
2024-11-13 21:18:13 +08:00
|
|
|
|
|
|
|
ok:
|
|
|
|
ret = 1;
|
2024-07-03 09:12:39 +08:00
|
|
|
err:
|
2024-11-13 21:18:13 +08:00
|
|
|
if (!found_key)
|
|
|
|
EVP_PKEY_free(pkey);
|
2024-07-03 09:12:39 +08:00
|
|
|
OPENSSL_free(wrapped);
|
|
|
|
OPENSSL_free(secret);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const EVP_TEST_METHOD pkey_kem_test_method = {
|
|
|
|
"Kem",
|
|
|
|
kem_test_init,
|
|
|
|
kem_test_cleanup,
|
|
|
|
kem_test_parse,
|
|
|
|
kem_test_run
|
|
|
|
};
|
2017-05-13 02:19:51 +08:00
|
|
|
|
|
|
|
/**
|
2020-08-07 12:29:00 +08:00
|
|
|
** PUBLIC KEY TESTS
|
|
|
|
** These are all very similar and share much common code.
|
|
|
|
**/
|
2015-02-12 01:15:51 +08:00
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
typedef struct pkey_data_st {
|
2015-02-12 01:15:51 +08:00
|
|
|
/* Context for this operation */
|
|
|
|
EVP_PKEY_CTX *ctx;
|
2024-07-11 03:26:30 +08:00
|
|
|
/* Signature algo for such operations */
|
|
|
|
EVP_SIGNATURE *sigalgo;
|
2015-02-12 01:15:51 +08:00
|
|
|
/* Key operation to perform */
|
2024-07-03 09:12:39 +08:00
|
|
|
int (*keyopinit) (EVP_PKEY_CTX *ctx, const OSSL_PARAM params[]);
|
2024-07-11 03:26:30 +08:00
|
|
|
int (*keyopinit_ex2) (EVP_PKEY_CTX *ctx, EVP_SIGNATURE *algo,
|
|
|
|
const OSSL_PARAM params[]);
|
2015-02-12 01:15:51 +08:00
|
|
|
int (*keyop) (EVP_PKEY_CTX *ctx,
|
|
|
|
unsigned char *sig, size_t *siglen,
|
|
|
|
const unsigned char *tbs, size_t tbslen);
|
|
|
|
/* Input to MAC */
|
|
|
|
unsigned char *input;
|
|
|
|
size_t input_len;
|
|
|
|
/* Expected output */
|
|
|
|
unsigned char *output;
|
|
|
|
size_t output_len;
|
2024-07-03 09:12:39 +08:00
|
|
|
STACK_OF(OPENSSL_STRING) *init_controls; /* collection of controls */
|
|
|
|
STACK_OF(OPENSSL_STRING) *controls; /* collection of controls */
|
|
|
|
EVP_PKEY *peer;
|
|
|
|
int validate;
|
2017-04-27 03:33:43 +08:00
|
|
|
} PKEY_DATA;
|
2015-02-12 01:15:51 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Perform public key operation setup: lookup key, allocated ctx and call
|
|
|
|
* the appropriate initialisation function
|
|
|
|
*/
|
2024-07-11 03:26:30 +08:00
|
|
|
static int pkey_test_init_keyctx(EVP_TEST *t, const char *keyname,
|
|
|
|
int use_public)
|
2015-02-12 01:15:51 +08:00
|
|
|
{
|
2017-04-27 03:33:43 +08:00
|
|
|
PKEY_DATA *kdata;
|
2015-02-12 01:15:51 +08:00
|
|
|
EVP_PKEY *pkey = NULL;
|
2015-02-27 02:54:12 +08:00
|
|
|
int rv = 0;
|
2017-04-27 03:33:43 +08:00
|
|
|
|
2015-02-27 02:54:12 +08:00
|
|
|
if (use_public)
|
2024-07-11 03:26:30 +08:00
|
|
|
rv = find_key(&pkey, keyname, public_keys);
|
2017-04-27 03:33:43 +08:00
|
|
|
if (rv == 0)
|
2024-07-11 03:26:30 +08:00
|
|
|
rv = find_key(&pkey, keyname, private_keys);
|
2017-04-27 03:33:43 +08:00
|
|
|
if (rv == 0 || pkey == NULL) {
|
2024-07-11 03:26:30 +08:00
|
|
|
TEST_info("skipping, key '%s' is disabled", keyname);
|
2015-02-27 02:54:12 +08:00
|
|
|
t->skip = 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-05-13 02:19:51 +08:00
|
|
|
if (!TEST_ptr(kdata = OPENSSL_zalloc(sizeof(*kdata)))) {
|
2015-02-27 02:54:12 +08:00
|
|
|
EVP_PKEY_free(pkey);
|
2015-02-12 01:15:51 +08:00
|
|
|
return 0;
|
2015-02-27 02:54:12 +08:00
|
|
|
}
|
2023-09-08 17:44:27 +08:00
|
|
|
if (!TEST_ptr(kdata->ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propquery))) {
|
2017-07-06 07:10:28 +08:00
|
|
|
EVP_PKEY_free(pkey);
|
|
|
|
OPENSSL_free(kdata);
|
2015-02-12 01:15:51 +08:00
|
|
|
return 0;
|
2017-07-06 07:10:28 +08:00
|
|
|
}
|
2017-05-13 02:19:51 +08:00
|
|
|
t->data = kdata;
|
2024-07-11 03:26:30 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int pkey_test_init(EVP_TEST *t, const char *name,
|
|
|
|
int use_public,
|
|
|
|
int (*keyopinit) (EVP_PKEY_CTX *ctx,
|
|
|
|
const OSSL_PARAM params[]),
|
|
|
|
int (*keyop)(EVP_PKEY_CTX *ctx,
|
|
|
|
unsigned char *sig, size_t *siglen,
|
|
|
|
const unsigned char *tbs,
|
|
|
|
size_t tbslen))
|
|
|
|
{
|
|
|
|
PKEY_DATA *kdata = NULL;
|
|
|
|
int rv = 0;
|
|
|
|
|
|
|
|
rv = pkey_test_init_keyctx(t, name, use_public);
|
|
|
|
if (t->skip || !rv)
|
|
|
|
return rv;
|
|
|
|
kdata = t->data;
|
|
|
|
kdata->keyopinit = keyopinit;
|
|
|
|
kdata->keyop = keyop;
|
|
|
|
kdata->init_controls = sk_OPENSSL_STRING_new_null();
|
|
|
|
kdata->controls = sk_OPENSSL_STRING_new_null();
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int pkey_test_init_ex2(EVP_TEST *t, const char *name,
|
|
|
|
int use_public,
|
|
|
|
int (*keyopinit)(EVP_PKEY_CTX *ctx,
|
|
|
|
EVP_SIGNATURE *algo,
|
|
|
|
const OSSL_PARAM param[]),
|
|
|
|
int (*keyop)(EVP_PKEY_CTX *ctx,
|
|
|
|
unsigned char *sig, size_t *siglen,
|
|
|
|
const unsigned char *tbs,
|
|
|
|
size_t tbslen))
|
|
|
|
{
|
|
|
|
PKEY_DATA *kdata = NULL;
|
|
|
|
int rv = 0;
|
|
|
|
char algoname[OSSL_MAX_NAME_SIZE + 1];
|
|
|
|
const char *p;
|
|
|
|
|
|
|
|
if ((p = strchr(name, ':')) == NULL
|
|
|
|
|| p == name || p[1] == '\0' || p - name > OSSL_MAX_NAME_SIZE) {
|
|
|
|
TEST_info("Can't extract algorithm or key name from '%s'", name);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
memcpy(algoname, name, p - name);
|
|
|
|
algoname[p - name] = '\0';
|
|
|
|
|
|
|
|
if (is_pkey_disabled(algoname)) {
|
|
|
|
t->skip = 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = pkey_test_init_keyctx(t, /* keyname */ p + 1, use_public);
|
|
|
|
if (t->skip || !rv)
|
|
|
|
return rv;
|
|
|
|
kdata = t->data;
|
|
|
|
kdata->keyopinit_ex2 = keyopinit;
|
|
|
|
kdata->keyop = keyop;
|
|
|
|
if (!TEST_ptr(kdata->sigalgo
|
|
|
|
= EVP_SIGNATURE_fetch(libctx, algoname, propquery))) {
|
|
|
|
TEST_info("algoname = '%s'", algoname);
|
|
|
|
return 0;
|
|
|
|
}
|
2024-07-03 09:12:39 +08:00
|
|
|
kdata->init_controls = sk_OPENSSL_STRING_new_null();
|
|
|
|
kdata->controls = sk_OPENSSL_STRING_new_null();
|
2015-02-12 01:15:51 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static void pkey_test_cleanup(EVP_TEST *t)
|
2015-02-12 01:15:51 +08:00
|
|
|
{
|
2017-04-27 03:33:43 +08:00
|
|
|
PKEY_DATA *kdata = t->data;
|
2015-05-01 22:02:07 +08:00
|
|
|
|
2024-07-03 09:12:39 +08:00
|
|
|
ctrlfree(kdata->init_controls);
|
|
|
|
ctrlfree(kdata->controls);
|
2015-05-01 22:02:07 +08:00
|
|
|
OPENSSL_free(kdata->input);
|
|
|
|
OPENSSL_free(kdata->output);
|
2015-03-28 22:54:15 +08:00
|
|
|
EVP_PKEY_CTX_free(kdata->ctx);
|
2024-07-11 03:26:30 +08:00
|
|
|
EVP_SIGNATURE_free(kdata->sigalgo);
|
2015-02-12 01:15:51 +08:00
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static int pkey_test_ctrl(EVP_TEST *t, EVP_PKEY_CTX *pctx,
|
2016-11-10 17:03:37 +08:00
|
|
|
const char *value)
|
2016-01-30 21:17:09 +08:00
|
|
|
{
|
2021-03-17 11:05:37 +08:00
|
|
|
int rv = 0;
|
2016-01-30 21:17:09 +08:00
|
|
|
char *p, *tmpval;
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
if (!TEST_ptr(tmpval = OPENSSL_strdup(value)))
|
2016-01-30 21:17:09 +08:00
|
|
|
return 0;
|
|
|
|
p = strchr(tmpval, ':');
|
2021-03-17 11:05:37 +08:00
|
|
|
if (p != NULL) {
|
2017-05-13 02:19:51 +08:00
|
|
|
*p++ = '\0';
|
2021-03-17 11:05:37 +08:00
|
|
|
rv = EVP_PKEY_CTX_ctrl_str(pctx, tmpval, p);
|
|
|
|
}
|
2016-12-10 21:59:29 +08:00
|
|
|
if (rv == -2) {
|
|
|
|
t->err = "PKEY_CTRL_INVALID";
|
|
|
|
rv = 1;
|
|
|
|
} else if (p != NULL && rv <= 0) {
|
2020-08-07 12:29:00 +08:00
|
|
|
if (is_digest_disabled(p) || is_cipher_disabled(p)) {
|
|
|
|
TEST_info("skipping, '%s' is disabled", p);
|
2016-11-10 17:03:37 +08:00
|
|
|
t->skip = 1;
|
|
|
|
rv = 1;
|
2016-12-10 21:59:29 +08:00
|
|
|
} else {
|
|
|
|
t->err = "PKEY_CTRL_ERROR";
|
|
|
|
rv = 1;
|
2016-11-10 17:03:37 +08:00
|
|
|
}
|
|
|
|
}
|
2016-01-30 21:17:09 +08:00
|
|
|
OPENSSL_free(tmpval);
|
|
|
|
return rv > 0;
|
|
|
|
}
|
|
|
|
|
2024-07-03 09:12:39 +08:00
|
|
|
static int pkey_add_control(EVP_TEST *t, STACK_OF(OPENSSL_STRING) *controls,
|
|
|
|
const char *value)
|
|
|
|
{
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
if (controls == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
p = strchr(value, ':');
|
|
|
|
if (p == NULL)
|
|
|
|
return 0;
|
|
|
|
p++;
|
|
|
|
if (is_digest_disabled(p) || is_cipher_disabled(p)) {
|
|
|
|
TEST_info("skipping, '%s' is disabled", p);
|
|
|
|
t->skip = 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ctrladd(controls, value) > 0;
|
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static int pkey_test_parse(EVP_TEST *t,
|
2015-02-12 01:15:51 +08:00
|
|
|
const char *keyword, const char *value)
|
|
|
|
{
|
2017-04-27 03:33:43 +08:00
|
|
|
PKEY_DATA *kdata = t->data;
|
2015-05-07 02:56:14 +08:00
|
|
|
if (strcmp(keyword, "Input") == 0)
|
2017-05-13 02:19:51 +08:00
|
|
|
return parse_bin(value, &kdata->input, &kdata->input_len);
|
2015-05-07 02:56:14 +08:00
|
|
|
if (strcmp(keyword, "Output") == 0)
|
2017-05-13 02:19:51 +08:00
|
|
|
return parse_bin(value, &kdata->output, &kdata->output_len);
|
2024-07-03 09:12:39 +08:00
|
|
|
if (strcmp(keyword, "CtrlInit") == 0)
|
|
|
|
return ctrladd(kdata->init_controls, value);
|
2016-01-30 21:17:09 +08:00
|
|
|
if (strcmp(keyword, "Ctrl") == 0)
|
2024-07-03 09:12:39 +08:00
|
|
|
return pkey_add_control(t, kdata->controls, value);
|
2015-02-12 01:15:51 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2024-07-03 09:12:39 +08:00
|
|
|
static int pkey_test_run_init(EVP_TEST *t)
|
|
|
|
{
|
|
|
|
PKEY_DATA *data = t->data;
|
|
|
|
int i, ret = 0;
|
2025-01-17 12:07:47 +08:00
|
|
|
OSSL_PARAM params[5] = {
|
|
|
|
OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END,
|
|
|
|
OSSL_PARAM_END, OSSL_PARAM_END
|
|
|
|
};
|
2024-07-03 09:12:39 +08:00
|
|
|
OSSL_PARAM *p = NULL;
|
|
|
|
size_t params_n = 0, params_n_allocstart = 0;
|
|
|
|
|
|
|
|
if (sk_OPENSSL_STRING_num(data->init_controls) > 0) {
|
|
|
|
if (!ctrl2params(t, data->init_controls,
|
|
|
|
NULL,
|
|
|
|
params, OSSL_NELEM(params), ¶ms_n))
|
|
|
|
goto err;
|
|
|
|
p = params;
|
|
|
|
}
|
2024-07-11 03:26:30 +08:00
|
|
|
if (data->keyopinit != NULL) {
|
|
|
|
if (data->keyopinit(data->ctx, p) <= 0) {
|
|
|
|
t->err = "KEYOP_INIT_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
} else if (data->keyopinit_ex2 != NULL) {
|
|
|
|
if (data->keyopinit_ex2(data->ctx, data->sigalgo, p) <= 0) {
|
|
|
|
t->err = "KEYOP_INIT_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
} else {
|
2024-07-03 09:12:39 +08:00
|
|
|
t->err = "KEYOP_INIT_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < sk_OPENSSL_STRING_num(data->controls); i++) {
|
|
|
|
char *value = sk_OPENSSL_STRING_value(data->controls, i);
|
|
|
|
|
|
|
|
if (!pkey_test_ctrl(t, data->ctx, value) || t->err != NULL)
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
ret = 1;
|
|
|
|
err:
|
|
|
|
ctrl2params_free(params, params_n, params_n_allocstart);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static int pkey_test_run(EVP_TEST *t)
|
2015-02-12 01:15:51 +08:00
|
|
|
{
|
2017-05-25 19:48:32 +08:00
|
|
|
PKEY_DATA *expected = t->data;
|
|
|
|
unsigned char *got = NULL;
|
|
|
|
size_t got_len;
|
2019-04-16 11:36:40 +08:00
|
|
|
EVP_PKEY_CTX *copy = NULL;
|
2017-04-27 03:33:43 +08:00
|
|
|
|
2024-07-03 09:12:39 +08:00
|
|
|
if (!pkey_test_run_init(t))
|
|
|
|
goto err;
|
|
|
|
|
2025-05-06 09:32:21 +08:00
|
|
|
if (!pkey_check_security_category(t, EVP_PKEY_CTX_get0_pkey(expected->ctx)))
|
|
|
|
goto err;
|
|
|
|
|
2024-07-11 03:26:30 +08:00
|
|
|
/* Make a copy of the EVP_PKEY context, for repeat use further down */
|
|
|
|
if (!TEST_ptr(copy = EVP_PKEY_CTX_dup(expected->ctx))) {
|
|
|
|
t->err = "INTERNAL_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2017-05-25 19:48:32 +08:00
|
|
|
if (expected->keyop(expected->ctx, NULL, &got_len,
|
|
|
|
expected->input, expected->input_len) <= 0
|
|
|
|
|| !TEST_ptr(got = OPENSSL_malloc(got_len))) {
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "KEYOP_LENGTH_ERROR";
|
2015-02-12 01:15:51 +08:00
|
|
|
goto err;
|
2017-04-27 03:33:43 +08:00
|
|
|
}
|
2017-05-25 19:48:32 +08:00
|
|
|
if (expected->keyop(expected->ctx, got, &got_len,
|
|
|
|
expected->input, expected->input_len) <= 0) {
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "KEYOP_ERROR";
|
2015-02-12 01:15:51 +08:00
|
|
|
goto err;
|
2017-04-27 03:33:43 +08:00
|
|
|
}
|
2025-01-17 12:07:47 +08:00
|
|
|
|
2018-08-09 07:27:42 +08:00
|
|
|
if (!memory_err_compare(t, "KEYOP_MISMATCH",
|
|
|
|
expected->output, expected->output_len,
|
|
|
|
got, got_len))
|
2015-02-12 01:15:51 +08:00
|
|
|
goto err;
|
2018-08-09 07:27:42 +08:00
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = NULL;
|
2019-04-16 11:36:40 +08:00
|
|
|
OPENSSL_free(got);
|
|
|
|
got = NULL;
|
|
|
|
|
2024-07-11 03:26:30 +08:00
|
|
|
/* Repeat the test on the EVP_PKEY context copy. */
|
2019-04-16 11:36:40 +08:00
|
|
|
if (expected->keyop(copy, NULL, &got_len, expected->input,
|
|
|
|
expected->input_len) <= 0
|
|
|
|
|| !TEST_ptr(got = OPENSSL_malloc(got_len))) {
|
|
|
|
t->err = "KEYOP_LENGTH_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
if (expected->keyop(copy, got, &got_len, expected->input,
|
|
|
|
expected->input_len) <= 0) {
|
|
|
|
t->err = "KEYOP_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
if (!memory_err_compare(t, "KEYOP_MISMATCH",
|
|
|
|
expected->output, expected->output_len,
|
|
|
|
got, got_len))
|
|
|
|
goto err;
|
|
|
|
|
2024-07-24 21:37:08 +08:00
|
|
|
if (pkey_check_fips_approved(expected->ctx, t) <= 0)
|
|
|
|
goto err;
|
|
|
|
|
2015-02-12 01:15:51 +08:00
|
|
|
err:
|
2017-05-25 19:48:32 +08:00
|
|
|
OPENSSL_free(got);
|
2019-04-16 11:36:40 +08:00
|
|
|
EVP_PKEY_CTX_free(copy);
|
2015-02-12 01:15:51 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2025-02-25 07:06:26 +08:00
|
|
|
static int pkey_fromdata_test_init(EVP_TEST *t, const char *name)
|
|
|
|
{
|
|
|
|
PKEY_DATA *kdata = NULL;
|
|
|
|
|
|
|
|
if (is_pkey_disabled(name)) {
|
|
|
|
TEST_info("skipping, '%s' is disabled", name);
|
|
|
|
t->skip = 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!TEST_ptr(kdata = OPENSSL_zalloc(sizeof(*kdata))))
|
|
|
|
return 0;
|
|
|
|
kdata->ctx = EVP_PKEY_CTX_new_from_name(libctx, name, "");
|
|
|
|
if (kdata->ctx == NULL)
|
|
|
|
goto err;
|
|
|
|
if (EVP_PKEY_fromdata_init(kdata->ctx) <= 0)
|
|
|
|
goto err;
|
|
|
|
kdata->controls = sk_OPENSSL_STRING_new_null();
|
|
|
|
if (kdata->controls == NULL)
|
|
|
|
goto err;
|
|
|
|
t->data = kdata;
|
|
|
|
return 1;
|
|
|
|
err:
|
|
|
|
EVP_PKEY_CTX_free(kdata->ctx);
|
|
|
|
OPENSSL_free(kdata);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void pkey_fromdata_test_cleanup(EVP_TEST *t)
|
|
|
|
{
|
|
|
|
PKEY_DATA *kdata = t->data;
|
|
|
|
|
|
|
|
ctrlfree(kdata->controls);
|
|
|
|
EVP_PKEY_CTX_free(kdata->ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int pkey_fromdata_test_parse(EVP_TEST *t,
|
|
|
|
const char *keyword, const char *value)
|
|
|
|
{
|
|
|
|
PKEY_DATA *kdata = t->data;
|
|
|
|
|
|
|
|
if (strcmp(keyword, "Ctrl") == 0)
|
|
|
|
return pkey_add_control(t, kdata->controls, value);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int pkey_fromdata_test_run(EVP_TEST *t)
|
|
|
|
{
|
|
|
|
EVP_PKEY *key = NULL;
|
|
|
|
PKEY_DATA *kdata = t->data;
|
|
|
|
int ret = 0;
|
|
|
|
static const OSSL_PARAM key_settable_ctx_params[] = {
|
|
|
|
OSSL_PARAM_octet_string("priv", NULL, 0),
|
|
|
|
OSSL_PARAM_octet_string("pub", NULL, 0),
|
|
|
|
OSSL_PARAM_END
|
|
|
|
};
|
|
|
|
OSSL_PARAM params[5] = {
|
|
|
|
OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END,
|
|
|
|
OSSL_PARAM_END, OSSL_PARAM_END
|
|
|
|
};
|
|
|
|
OSSL_PARAM *p = NULL;
|
|
|
|
size_t params_n = 0, params_n_allocstart = 0;
|
|
|
|
|
|
|
|
if (sk_OPENSSL_STRING_num(kdata->controls) > 0) {
|
|
|
|
if (!ctrl2params(t, kdata->controls, key_settable_ctx_params,
|
|
|
|
params, OSSL_NELEM(params), ¶ms_n))
|
|
|
|
goto err;
|
|
|
|
p = params;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = 1;
|
|
|
|
if (EVP_PKEY_fromdata(kdata->ctx, &key, EVP_PKEY_KEYPAIR, p) <= 0) {
|
|
|
|
t->err = "KEY_FROMDATA_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
2025-05-06 09:32:21 +08:00
|
|
|
if (!pkey_check_security_category(t, key))
|
|
|
|
goto err;
|
|
|
|
|
2025-02-25 07:06:26 +08:00
|
|
|
err:
|
|
|
|
ctrl2params_free(params, params_n, params_n_allocstart);
|
|
|
|
EVP_PKEY_free(key);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const EVP_TEST_METHOD pkey_fromdata_test_method = {
|
|
|
|
"KeyFromData",
|
|
|
|
pkey_fromdata_test_init,
|
|
|
|
pkey_fromdata_test_cleanup,
|
|
|
|
pkey_fromdata_test_parse,
|
|
|
|
pkey_fromdata_test_run
|
|
|
|
};
|
|
|
|
|
2024-07-11 03:26:30 +08:00
|
|
|
/*
|
|
|
|
* "Sign" implies EVP_PKEY_sign_init_ex2() if the argument is a colon-separated
|
|
|
|
* pair, {algorithm}:{key}. If not, it implies EVP_PKEY_sign_init_ex()
|
|
|
|
*/
|
2017-04-27 03:33:43 +08:00
|
|
|
static int sign_test_init(EVP_TEST *t, const char *name)
|
2015-02-12 01:15:51 +08:00
|
|
|
{
|
2024-07-11 03:26:30 +08:00
|
|
|
if (strchr(name, ':') != NULL)
|
|
|
|
return pkey_test_init_ex2(t, name, 0,
|
|
|
|
EVP_PKEY_sign_init_ex2, EVP_PKEY_sign);
|
2024-07-03 09:12:39 +08:00
|
|
|
return pkey_test_init(t, name, 0, EVP_PKEY_sign_init_ex, EVP_PKEY_sign);
|
2015-02-12 01:15:51 +08:00
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static const EVP_TEST_METHOD psign_test_method = {
|
2015-02-12 01:15:51 +08:00
|
|
|
"Sign",
|
|
|
|
sign_test_init,
|
|
|
|
pkey_test_cleanup,
|
|
|
|
pkey_test_parse,
|
|
|
|
pkey_test_run
|
|
|
|
};
|
|
|
|
|
2024-07-11 03:26:30 +08:00
|
|
|
/*
|
|
|
|
* "Sign-Message" is like "Sign", but uses EVP_PKEY_sign_message_init()
|
|
|
|
* The argument must be a colon separated pair, {algorithm}:{key}
|
|
|
|
*/
|
|
|
|
static int sign_test_message_init(EVP_TEST *t, const char *name)
|
|
|
|
{
|
|
|
|
return pkey_test_init_ex2(t, name, 0,
|
|
|
|
EVP_PKEY_sign_message_init, EVP_PKEY_sign);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const EVP_TEST_METHOD psign_message_test_method = {
|
|
|
|
"Sign-Message",
|
|
|
|
sign_test_message_init,
|
|
|
|
pkey_test_cleanup,
|
|
|
|
pkey_test_parse,
|
|
|
|
pkey_test_run
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* "VerifyRecover" implies EVP_PKEY_verify_recover_init_ex2() if the argument is a
|
|
|
|
* colon-separated pair, {algorithm}:{key}.
|
|
|
|
* If not, it implies EVP_PKEY_verify_recover_init_ex()
|
|
|
|
*/
|
2017-04-27 03:33:43 +08:00
|
|
|
static int verify_recover_test_init(EVP_TEST *t, const char *name)
|
2015-02-12 01:15:51 +08:00
|
|
|
{
|
2024-07-11 03:26:30 +08:00
|
|
|
if (strchr(name, ':') != NULL)
|
|
|
|
return pkey_test_init_ex2(t, name, 1,
|
|
|
|
EVP_PKEY_verify_recover_init_ex2,
|
|
|
|
EVP_PKEY_verify_recover);
|
2024-07-03 09:12:39 +08:00
|
|
|
return pkey_test_init(t, name, 1, EVP_PKEY_verify_recover_init_ex,
|
2015-02-12 01:15:51 +08:00
|
|
|
EVP_PKEY_verify_recover);
|
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static const EVP_TEST_METHOD pverify_recover_test_method = {
|
2015-02-12 01:15:51 +08:00
|
|
|
"VerifyRecover",
|
|
|
|
verify_recover_test_init,
|
|
|
|
pkey_test_cleanup,
|
|
|
|
pkey_test_parse,
|
|
|
|
pkey_test_run
|
|
|
|
};
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static int decrypt_test_init(EVP_TEST *t, const char *name)
|
2015-02-12 01:15:51 +08:00
|
|
|
{
|
2024-07-03 09:12:39 +08:00
|
|
|
return pkey_test_init(t, name, 0, EVP_PKEY_decrypt_init_ex,
|
2015-02-12 01:15:51 +08:00
|
|
|
EVP_PKEY_decrypt);
|
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static const EVP_TEST_METHOD pdecrypt_test_method = {
|
2015-02-12 01:15:51 +08:00
|
|
|
"Decrypt",
|
|
|
|
decrypt_test_init,
|
|
|
|
pkey_test_cleanup,
|
|
|
|
pkey_test_parse,
|
|
|
|
pkey_test_run
|
|
|
|
};
|
|
|
|
|
2024-07-11 03:26:30 +08:00
|
|
|
/*
|
|
|
|
* "Verify" implies EVP_PKEY_verify_init_ex2() if the argument is a
|
|
|
|
* colon-separated pair, {algorithm}:{key}.
|
|
|
|
* If not, it implies EVP_PKEY_verify_init_ex()
|
|
|
|
*/
|
2017-04-27 03:33:43 +08:00
|
|
|
static int verify_test_init(EVP_TEST *t, const char *name)
|
2015-02-12 01:15:51 +08:00
|
|
|
{
|
2024-07-11 03:26:30 +08:00
|
|
|
if (strchr(name, ':') != NULL)
|
|
|
|
return pkey_test_init_ex2(t, name, 1,
|
|
|
|
EVP_PKEY_verify_init_ex2, NULL);
|
2024-07-03 09:12:39 +08:00
|
|
|
return pkey_test_init(t, name, 1, EVP_PKEY_verify_init_ex, NULL);
|
2015-02-12 01:15:51 +08:00
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static int verify_test_run(EVP_TEST *t)
|
2015-02-12 01:15:51 +08:00
|
|
|
{
|
2024-08-07 10:24:36 +08:00
|
|
|
int ret = 1;
|
2017-04-27 03:33:43 +08:00
|
|
|
PKEY_DATA *kdata = t->data;
|
|
|
|
|
2024-07-03 09:12:39 +08:00
|
|
|
if (!pkey_test_run_init(t))
|
|
|
|
goto err;
|
2025-05-06 09:32:21 +08:00
|
|
|
if (!pkey_check_security_category(t, EVP_PKEY_CTX_get0_pkey(kdata->ctx)))
|
|
|
|
goto err;
|
2015-02-12 01:15:51 +08:00
|
|
|
if (EVP_PKEY_verify(kdata->ctx, kdata->output, kdata->output_len,
|
2024-08-07 10:24:36 +08:00
|
|
|
kdata->input, kdata->input_len) <= 0) {
|
2015-02-12 01:15:51 +08:00
|
|
|
t->err = "VERIFY_ERROR";
|
2024-08-07 10:24:36 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
if (!pkey_check_fips_approved(kdata->ctx, t))
|
|
|
|
ret = 0;
|
2024-07-03 09:12:39 +08:00
|
|
|
err:
|
2024-08-07 10:24:36 +08:00
|
|
|
return ret;
|
2015-02-12 01:15:51 +08:00
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static const EVP_TEST_METHOD pverify_test_method = {
|
2015-02-12 01:15:51 +08:00
|
|
|
"Verify",
|
|
|
|
verify_test_init,
|
|
|
|
pkey_test_cleanup,
|
|
|
|
pkey_test_parse,
|
|
|
|
verify_test_run
|
|
|
|
};
|
2015-05-19 22:51:01 +08:00
|
|
|
|
2024-07-11 03:26:30 +08:00
|
|
|
/*
|
|
|
|
* "Verify-Message" is like "Verify", but uses EVP_PKEY_verify_message_init()
|
|
|
|
* The argument must be a colon separated pair, {algorithm}:{key}
|
|
|
|
*/
|
|
|
|
static int verify_message_test_init(EVP_TEST *t, const char *name)
|
|
|
|
{
|
|
|
|
return pkey_test_init_ex2(t, name, 0,
|
|
|
|
EVP_PKEY_verify_message_init, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const EVP_TEST_METHOD pverify_message_test_method = {
|
|
|
|
"Verify-Message",
|
|
|
|
verify_message_test_init,
|
|
|
|
pkey_test_cleanup,
|
|
|
|
pkey_test_parse,
|
|
|
|
verify_test_run
|
|
|
|
};
|
|
|
|
|
2025-02-14 09:54:59 +08:00
|
|
|
/*
|
|
|
|
* "Verify-Message-Public" is like "Verify-Message", but uses a public key
|
|
|
|
* instead of a private key.
|
|
|
|
* The argument must be a colon separated pair, {algorithm}:{key}
|
|
|
|
*/
|
2025-01-17 12:07:47 +08:00
|
|
|
static int verify_message_public_test_init(EVP_TEST *t, const char *name)
|
|
|
|
{
|
|
|
|
return pkey_test_init_ex2(t, name, 1,
|
|
|
|
EVP_PKEY_verify_message_init, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const EVP_TEST_METHOD pverify_message_public_test_method = {
|
|
|
|
"Verify-Message-Public",
|
|
|
|
verify_message_public_test_init,
|
|
|
|
pkey_test_cleanup,
|
|
|
|
pkey_test_parse,
|
|
|
|
verify_test_run
|
|
|
|
};
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static int pderive_test_init(EVP_TEST *t, const char *name)
|
2016-01-29 22:58:36 +08:00
|
|
|
{
|
2024-07-03 09:12:39 +08:00
|
|
|
return pkey_test_init(t, name, 0, EVP_PKEY_derive_init_ex, 0);
|
2016-01-29 22:58:36 +08:00
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static int pderive_test_parse(EVP_TEST *t,
|
2016-01-29 22:58:36 +08:00
|
|
|
const char *keyword, const char *value)
|
|
|
|
{
|
2017-04-27 03:33:43 +08:00
|
|
|
PKEY_DATA *kdata = t->data;
|
2021-04-12 07:06:24 +08:00
|
|
|
int validate = 0;
|
2016-01-29 22:58:36 +08:00
|
|
|
|
2021-04-12 07:06:24 +08:00
|
|
|
if (strcmp(keyword, "PeerKeyValidate") == 0)
|
|
|
|
validate = 1;
|
|
|
|
|
|
|
|
if (validate || strcmp(keyword, "PeerKey") == 0) {
|
2024-07-03 09:12:39 +08:00
|
|
|
EVP_PKEY *peer = NULL;
|
|
|
|
|
|
|
|
kdata->validate = validate;
|
2017-04-27 03:33:43 +08:00
|
|
|
if (find_key(&peer, value, public_keys) == 0)
|
2019-08-23 23:41:23 +08:00
|
|
|
return -1;
|
2024-07-03 09:12:39 +08:00
|
|
|
kdata->peer = peer;
|
2016-01-29 22:58:36 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (strcmp(keyword, "SharedSecret") == 0)
|
2017-05-13 02:19:51 +08:00
|
|
|
return parse_bin(value, &kdata->output, &kdata->output_len);
|
2016-01-30 21:17:09 +08:00
|
|
|
if (strcmp(keyword, "Ctrl") == 0)
|
2024-07-03 09:12:39 +08:00
|
|
|
return pkey_add_control(t, kdata->controls, value);
|
|
|
|
if (strcmp(keyword, "CtrlInit") == 0)
|
|
|
|
return ctrladd(kdata->init_controls, value);
|
2016-01-29 22:58:36 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static int pderive_test_run(EVP_TEST *t)
|
2016-01-29 22:58:36 +08:00
|
|
|
{
|
2021-09-02 14:49:37 +08:00
|
|
|
EVP_PKEY_CTX *dctx = NULL;
|
2017-05-25 19:48:32 +08:00
|
|
|
PKEY_DATA *expected = t->data;
|
|
|
|
unsigned char *got = NULL;
|
|
|
|
size_t got_len;
|
2024-08-08 14:56:22 +08:00
|
|
|
int ret = 1;
|
2016-01-29 22:58:36 +08:00
|
|
|
|
2024-07-03 09:12:39 +08:00
|
|
|
if (!pkey_test_run_init(t))
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
t->err = NULL;
|
2025-05-06 09:32:21 +08:00
|
|
|
if (!pkey_check_security_category(t, EVP_PKEY_CTX_get0_pkey(expected->ctx)))
|
|
|
|
goto err;
|
2024-07-03 09:12:39 +08:00
|
|
|
if (EVP_PKEY_derive_set_peer_ex(expected->ctx, expected->peer,
|
|
|
|
expected->validate) <= 0) {
|
|
|
|
t->err = "DERIVE_SET_PEER_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2021-09-02 14:49:37 +08:00
|
|
|
if (!TEST_ptr(dctx = EVP_PKEY_CTX_dup(expected->ctx))) {
|
|
|
|
t->err = "DERIVE_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2022-03-11 01:41:30 +08:00
|
|
|
if (EVP_PKEY_derive(dctx, NULL, &got_len) <= 0
|
|
|
|
|| !TEST_size_t_ne(got_len, 0)) {
|
2017-10-07 07:04:17 +08:00
|
|
|
t->err = "DERIVE_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
2017-05-25 19:48:32 +08:00
|
|
|
if (!TEST_ptr(got = OPENSSL_malloc(got_len))) {
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "DERIVE_ERROR";
|
2016-01-29 22:58:36 +08:00
|
|
|
goto err;
|
2017-04-27 03:33:43 +08:00
|
|
|
}
|
2021-09-02 14:49:37 +08:00
|
|
|
if (EVP_PKEY_derive(dctx, got, &got_len) <= 0) {
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "DERIVE_ERROR";
|
2016-01-29 22:58:36 +08:00
|
|
|
goto err;
|
2017-04-27 03:33:43 +08:00
|
|
|
}
|
2018-08-09 07:27:42 +08:00
|
|
|
if (!memory_err_compare(t, "SHARED_SECRET_MISMATCH",
|
|
|
|
expected->output, expected->output_len,
|
|
|
|
got, got_len))
|
2016-01-29 22:58:36 +08:00
|
|
|
goto err;
|
2017-04-27 03:33:43 +08:00
|
|
|
|
2024-08-08 14:56:22 +08:00
|
|
|
if (!pkey_check_fips_approved(dctx, t)) {
|
|
|
|
ret = 0;
|
|
|
|
goto err;
|
|
|
|
}
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = NULL;
|
2016-01-29 22:58:36 +08:00
|
|
|
err:
|
2017-05-25 19:48:32 +08:00
|
|
|
OPENSSL_free(got);
|
2021-09-02 14:49:37 +08:00
|
|
|
EVP_PKEY_CTX_free(dctx);
|
2024-08-08 14:56:22 +08:00
|
|
|
return ret;
|
2016-01-29 22:58:36 +08:00
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static const EVP_TEST_METHOD pderive_test_method = {
|
2016-01-29 22:58:36 +08:00
|
|
|
"Derive",
|
|
|
|
pderive_test_init,
|
|
|
|
pkey_test_cleanup,
|
|
|
|
pderive_test_parse,
|
|
|
|
pderive_test_run
|
|
|
|
};
|
|
|
|
|
2017-05-13 02:19:51 +08:00
|
|
|
/**
|
2020-08-07 12:29:00 +08:00
|
|
|
** PBE TESTS
|
|
|
|
**/
|
2017-05-13 02:19:51 +08:00
|
|
|
|
|
|
|
typedef enum pbe_type_enum {
|
|
|
|
PBE_TYPE_INVALID = 0,
|
|
|
|
PBE_TYPE_SCRYPT, PBE_TYPE_PBKDF2, PBE_TYPE_PKCS12
|
|
|
|
} PBE_TYPE;
|
2015-05-19 22:51:01 +08:00
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
typedef struct pbe_data_st {
|
2017-05-13 02:19:51 +08:00
|
|
|
PBE_TYPE pbe_type;
|
2017-04-27 03:33:43 +08:00
|
|
|
/* scrypt parameters */
|
2015-05-19 22:51:01 +08:00
|
|
|
uint64_t N, r, p, maxmem;
|
2017-04-27 03:33:43 +08:00
|
|
|
/* PKCS#12 parameters */
|
2015-05-23 00:17:21 +08:00
|
|
|
int id, iter;
|
|
|
|
const EVP_MD *md;
|
2017-04-27 03:33:43 +08:00
|
|
|
/* password */
|
2015-05-19 22:51:01 +08:00
|
|
|
unsigned char *pass;
|
|
|
|
size_t pass_len;
|
2017-04-27 03:33:43 +08:00
|
|
|
/* salt */
|
2015-05-19 22:51:01 +08:00
|
|
|
unsigned char *salt;
|
|
|
|
size_t salt_len;
|
2017-04-27 03:33:43 +08:00
|
|
|
/* Expected output */
|
2015-05-19 22:51:01 +08:00
|
|
|
unsigned char *key;
|
|
|
|
size_t key_len;
|
2017-04-27 03:33:43 +08:00
|
|
|
} PBE_DATA;
|
2015-05-19 22:51:01 +08:00
|
|
|
|
2015-09-05 01:07:10 +08:00
|
|
|
#ifndef OPENSSL_NO_SCRYPT
|
2020-08-07 12:29:00 +08:00
|
|
|
/* Parse unsigned decimal 64 bit integer value */
|
2017-05-13 02:19:51 +08:00
|
|
|
static int parse_uint64(const char *value, uint64_t *pr)
|
|
|
|
{
|
|
|
|
const char *p = value;
|
|
|
|
|
|
|
|
if (!TEST_true(*p)) {
|
|
|
|
TEST_info("Invalid empty integer value");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
for (*pr = 0; *p; ) {
|
|
|
|
if (*pr > UINT64_MAX / 10) {
|
|
|
|
TEST_error("Integer overflow in string %s", value);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
*pr *= 10;
|
2017-08-21 05:36:23 +08:00
|
|
|
if (!TEST_true(isdigit((unsigned char)*p))) {
|
2017-05-13 02:19:51 +08:00
|
|
|
TEST_error("Invalid character in string %s", value);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
*pr += *p - '0';
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static int scrypt_test_parse(EVP_TEST *t,
|
2015-05-19 22:51:01 +08:00
|
|
|
const char *keyword, const char *value)
|
|
|
|
{
|
2017-04-27 03:33:43 +08:00
|
|
|
PBE_DATA *pdata = t->data;
|
2015-05-23 00:17:21 +08:00
|
|
|
|
2015-05-19 22:51:01 +08:00
|
|
|
if (strcmp(keyword, "N") == 0)
|
2017-05-13 02:19:51 +08:00
|
|
|
return parse_uint64(value, &pdata->N);
|
2015-05-19 22:51:01 +08:00
|
|
|
if (strcmp(keyword, "p") == 0)
|
2017-05-13 02:19:51 +08:00
|
|
|
return parse_uint64(value, &pdata->p);
|
2015-05-19 22:51:01 +08:00
|
|
|
if (strcmp(keyword, "r") == 0)
|
2017-05-13 02:19:51 +08:00
|
|
|
return parse_uint64(value, &pdata->r);
|
2015-05-19 22:51:01 +08:00
|
|
|
if (strcmp(keyword, "maxmem") == 0)
|
2017-05-13 02:19:51 +08:00
|
|
|
return parse_uint64(value, &pdata->maxmem);
|
2015-05-19 22:51:01 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2015-09-05 01:07:10 +08:00
|
|
|
#endif
|
2015-05-19 22:51:01 +08:00
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static int pbkdf2_test_parse(EVP_TEST *t,
|
2015-05-23 00:17:21 +08:00
|
|
|
const char *keyword, const char *value)
|
2015-05-19 22:51:01 +08:00
|
|
|
{
|
2017-04-27 03:33:43 +08:00
|
|
|
PBE_DATA *pdata = t->data;
|
2015-05-23 00:17:21 +08:00
|
|
|
|
|
|
|
if (strcmp(keyword, "iter") == 0) {
|
|
|
|
pdata->iter = atoi(value);
|
|
|
|
if (pdata->iter <= 0)
|
2017-05-13 02:19:51 +08:00
|
|
|
return -1;
|
2015-05-23 00:17:21 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (strcmp(keyword, "MD") == 0) {
|
|
|
|
pdata->md = EVP_get_digestbyname(value);
|
|
|
|
if (pdata->md == NULL)
|
2017-05-13 02:19:51 +08:00
|
|
|
return -1;
|
2015-05-23 00:17:21 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static int pkcs12_test_parse(EVP_TEST *t,
|
2015-05-23 00:17:21 +08:00
|
|
|
const char *keyword, const char *value)
|
|
|
|
{
|
2017-04-27 03:33:43 +08:00
|
|
|
PBE_DATA *pdata = t->data;
|
2015-05-23 00:17:21 +08:00
|
|
|
|
|
|
|
if (strcmp(keyword, "id") == 0) {
|
|
|
|
pdata->id = atoi(value);
|
|
|
|
if (pdata->id <= 0)
|
2017-05-13 02:19:51 +08:00
|
|
|
return -1;
|
2015-05-23 00:17:21 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return pbkdf2_test_parse(t, keyword, value);
|
2015-05-19 22:51:01 +08:00
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static int pbe_test_init(EVP_TEST *t, const char *alg)
|
2015-05-19 22:51:01 +08:00
|
|
|
{
|
2017-04-27 03:33:43 +08:00
|
|
|
PBE_DATA *pdat;
|
2017-05-13 02:19:51 +08:00
|
|
|
PBE_TYPE pbe_type = PBE_TYPE_INVALID;
|
2015-05-23 00:17:21 +08:00
|
|
|
|
2020-08-07 12:29:00 +08:00
|
|
|
if (is_kdf_disabled(alg)) {
|
|
|
|
TEST_info("skipping, '%s' is disabled", alg);
|
2016-03-21 19:23:08 +08:00
|
|
|
t->skip = 1;
|
|
|
|
return 1;
|
2020-08-07 12:29:00 +08:00
|
|
|
}
|
|
|
|
if (strcmp(alg, "scrypt") == 0) {
|
|
|
|
pbe_type = PBE_TYPE_SCRYPT;
|
2016-03-21 19:23:08 +08:00
|
|
|
} else if (strcmp(alg, "pbkdf2") == 0) {
|
2015-05-23 00:17:21 +08:00
|
|
|
pbe_type = PBE_TYPE_PBKDF2;
|
2016-03-21 19:23:08 +08:00
|
|
|
} else if (strcmp(alg, "pkcs12") == 0) {
|
2015-05-23 00:17:21 +08:00
|
|
|
pbe_type = PBE_TYPE_PKCS12;
|
2016-03-21 19:23:08 +08:00
|
|
|
} else {
|
2017-04-27 03:33:43 +08:00
|
|
|
TEST_error("Unknown pbe algorithm %s", alg);
|
2021-06-25 10:56:57 +08:00
|
|
|
return 0;
|
2016-03-21 19:23:08 +08:00
|
|
|
}
|
2021-06-25 10:56:57 +08:00
|
|
|
if (!TEST_ptr(pdat = OPENSSL_zalloc(sizeof(*pdat))))
|
|
|
|
return 0;
|
2015-05-19 22:51:01 +08:00
|
|
|
pdat->pbe_type = pbe_type;
|
|
|
|
t->data = pdat;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static void pbe_test_cleanup(EVP_TEST *t)
|
2015-05-19 22:51:01 +08:00
|
|
|
{
|
2017-04-27 03:33:43 +08:00
|
|
|
PBE_DATA *pdat = t->data;
|
|
|
|
|
|
|
|
OPENSSL_free(pdat->pass);
|
|
|
|
OPENSSL_free(pdat->salt);
|
|
|
|
OPENSSL_free(pdat->key);
|
2015-05-19 22:51:01 +08:00
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static int pbe_test_parse(EVP_TEST *t,
|
|
|
|
const char *keyword, const char *value)
|
2015-05-19 22:51:01 +08:00
|
|
|
{
|
2017-04-27 03:33:43 +08:00
|
|
|
PBE_DATA *pdata = t->data;
|
2015-05-23 00:17:21 +08:00
|
|
|
|
2015-05-19 22:51:01 +08:00
|
|
|
if (strcmp(keyword, "Password") == 0)
|
2017-05-13 02:19:51 +08:00
|
|
|
return parse_bin(value, &pdata->pass, &pdata->pass_len);
|
2015-05-19 22:51:01 +08:00
|
|
|
if (strcmp(keyword, "Salt") == 0)
|
2017-05-13 02:19:51 +08:00
|
|
|
return parse_bin(value, &pdata->salt, &pdata->salt_len);
|
2015-05-19 22:51:01 +08:00
|
|
|
if (strcmp(keyword, "Key") == 0)
|
2017-05-13 02:19:51 +08:00
|
|
|
return parse_bin(value, &pdata->key, &pdata->key_len);
|
2015-09-05 01:07:10 +08:00
|
|
|
if (pdata->pbe_type == PBE_TYPE_PBKDF2)
|
2015-05-23 00:17:21 +08:00
|
|
|
return pbkdf2_test_parse(t, keyword, value);
|
|
|
|
else if (pdata->pbe_type == PBE_TYPE_PKCS12)
|
|
|
|
return pkcs12_test_parse(t, keyword, value);
|
2015-09-05 01:07:10 +08:00
|
|
|
#ifndef OPENSSL_NO_SCRYPT
|
|
|
|
else if (pdata->pbe_type == PBE_TYPE_SCRYPT)
|
|
|
|
return scrypt_test_parse(t, keyword, value);
|
|
|
|
#endif
|
2015-05-19 22:51:01 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static int pbe_test_run(EVP_TEST *t)
|
2015-05-19 22:51:01 +08:00
|
|
|
{
|
2017-05-25 19:48:32 +08:00
|
|
|
PBE_DATA *expected = t->data;
|
2015-05-23 00:17:21 +08:00
|
|
|
unsigned char *key;
|
2020-08-07 12:29:00 +08:00
|
|
|
EVP_MD *fetched_digest = NULL;
|
2020-10-15 17:55:50 +08:00
|
|
|
OSSL_LIB_CTX *save_libctx;
|
2020-08-07 12:29:00 +08:00
|
|
|
|
2020-10-15 17:55:50 +08:00
|
|
|
save_libctx = OSSL_LIB_CTX_set0_default(libctx);
|
2015-05-23 00:17:21 +08:00
|
|
|
|
2017-05-25 19:48:32 +08:00
|
|
|
if (!TEST_ptr(key = OPENSSL_malloc(expected->key_len))) {
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "INTERNAL_ERROR";
|
2015-05-23 00:17:21 +08:00
|
|
|
goto err;
|
2017-04-27 03:33:43 +08:00
|
|
|
}
|
2017-05-25 19:48:32 +08:00
|
|
|
if (expected->pbe_type == PBE_TYPE_PBKDF2) {
|
2025-06-18 17:59:04 +08:00
|
|
|
if (PKCS5_PBKDF2_HMAC((char *)expected->pass, (int)expected->pass_len,
|
|
|
|
expected->salt, (int)expected->salt_len,
|
2017-05-25 19:48:32 +08:00
|
|
|
expected->iter, expected->md,
|
2025-06-18 17:59:04 +08:00
|
|
|
(int)expected->key_len, key) == 0) {
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "PBKDF2_ERROR";
|
2015-05-23 00:17:21 +08:00
|
|
|
goto err;
|
2017-04-27 03:33:43 +08:00
|
|
|
}
|
2015-09-05 01:07:10 +08:00
|
|
|
#ifndef OPENSSL_NO_SCRYPT
|
2017-05-25 19:48:32 +08:00
|
|
|
} else if (expected->pbe_type == PBE_TYPE_SCRYPT) {
|
|
|
|
if (EVP_PBE_scrypt((const char *)expected->pass, expected->pass_len,
|
2020-08-07 12:29:00 +08:00
|
|
|
expected->salt, expected->salt_len,
|
|
|
|
expected->N, expected->r, expected->p,
|
|
|
|
expected->maxmem, key, expected->key_len) == 0) {
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "SCRYPT_ERROR";
|
2015-05-23 00:17:21 +08:00
|
|
|
goto err;
|
2017-04-27 03:33:43 +08:00
|
|
|
}
|
2015-09-05 01:07:10 +08:00
|
|
|
#endif
|
2017-05-25 19:48:32 +08:00
|
|
|
} else if (expected->pbe_type == PBE_TYPE_PKCS12) {
|
Rename all getters to use get/get0 in name
For functions that exist in 1.1.1 provide a simple aliases via #define.
Fixes #15236
Functions with OSSL_DECODER_, OSSL_ENCODER_, OSSL_STORE_LOADER_,
EVP_KEYEXCH_, EVP_KEM_, EVP_ASYM_CIPHER_, EVP_SIGNATURE_,
EVP_KEYMGMT_, EVP_RAND_, EVP_MAC_, EVP_KDF_, EVP_PKEY_,
EVP_MD_, and EVP_CIPHER_ prefixes are renamed.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15405)
2021-05-21 22:58:08 +08:00
|
|
|
fetched_digest = EVP_MD_fetch(libctx, EVP_MD_get0_name(expected->md),
|
2023-09-08 17:44:27 +08:00
|
|
|
propquery);
|
2020-08-07 12:29:00 +08:00
|
|
|
if (fetched_digest == NULL) {
|
|
|
|
t->err = "PKCS12_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
2025-06-18 17:59:04 +08:00
|
|
|
if (PKCS12_key_gen_uni(expected->pass, (int)expected->pass_len,
|
|
|
|
expected->salt, (int)expected->salt_len,
|
|
|
|
expected->id, expected->iter, (int)expected->key_len,
|
2020-08-07 12:29:00 +08:00
|
|
|
key, fetched_digest) == 0) {
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "PKCS12_ERROR";
|
2015-05-23 00:17:21 +08:00
|
|
|
goto err;
|
2017-04-27 03:33:43 +08:00
|
|
|
}
|
2015-05-23 00:17:21 +08:00
|
|
|
}
|
2018-08-09 07:27:42 +08:00
|
|
|
if (!memory_err_compare(t, "KEY_MISMATCH", expected->key, expected->key_len,
|
|
|
|
key, expected->key_len))
|
2015-05-23 00:17:21 +08:00
|
|
|
goto err;
|
2018-08-09 07:27:42 +08:00
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = NULL;
|
|
|
|
err:
|
2020-08-07 12:29:00 +08:00
|
|
|
EVP_MD_free(fetched_digest);
|
2015-05-23 00:17:21 +08:00
|
|
|
OPENSSL_free(key);
|
2020-10-15 17:55:50 +08:00
|
|
|
OSSL_LIB_CTX_set0_default(save_libctx);
|
2015-05-23 00:17:21 +08:00
|
|
|
return 1;
|
2015-05-19 22:51:01 +08:00
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static const EVP_TEST_METHOD pbe_test_method = {
|
2015-05-19 22:51:01 +08:00
|
|
|
"PBE",
|
|
|
|
pbe_test_init,
|
|
|
|
pbe_test_cleanup,
|
|
|
|
pbe_test_parse,
|
|
|
|
pbe_test_run
|
|
|
|
};
|
2015-09-02 21:31:28 +08:00
|
|
|
|
2017-05-13 02:19:51 +08:00
|
|
|
|
|
|
|
/**
|
2020-08-07 12:29:00 +08:00
|
|
|
** BASE64 TESTS
|
|
|
|
**/
|
2015-09-02 21:31:28 +08:00
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
BASE64_CANONICAL_ENCODING = 0,
|
|
|
|
BASE64_VALID_ENCODING = 1,
|
|
|
|
BASE64_INVALID_ENCODING = 2
|
|
|
|
} base64_encoding_type;
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
typedef struct encode_data_st {
|
2015-09-02 21:31:28 +08:00
|
|
|
/* Input to encoding */
|
|
|
|
unsigned char *input;
|
|
|
|
size_t input_len;
|
|
|
|
/* Expected output */
|
|
|
|
unsigned char *output;
|
|
|
|
size_t output_len;
|
|
|
|
base64_encoding_type encoding;
|
2017-04-27 03:33:43 +08:00
|
|
|
} ENCODE_DATA;
|
2015-09-02 21:31:28 +08:00
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static int encode_test_init(EVP_TEST *t, const char *encoding)
|
2015-09-02 21:31:28 +08:00
|
|
|
{
|
2017-05-13 02:19:51 +08:00
|
|
|
ENCODE_DATA *edata;
|
2015-09-02 21:31:28 +08:00
|
|
|
|
2017-05-13 02:19:51 +08:00
|
|
|
if (!TEST_ptr(edata = OPENSSL_zalloc(sizeof(*edata))))
|
|
|
|
return 0;
|
2015-09-02 21:31:28 +08:00
|
|
|
if (strcmp(encoding, "canonical") == 0) {
|
|
|
|
edata->encoding = BASE64_CANONICAL_ENCODING;
|
|
|
|
} else if (strcmp(encoding, "valid") == 0) {
|
|
|
|
edata->encoding = BASE64_VALID_ENCODING;
|
|
|
|
} else if (strcmp(encoding, "invalid") == 0) {
|
|
|
|
edata->encoding = BASE64_INVALID_ENCODING;
|
2017-05-13 02:19:51 +08:00
|
|
|
if (!TEST_ptr(t->expected_err = OPENSSL_strdup("DECODE_ERROR")))
|
2019-01-08 14:27:27 +08:00
|
|
|
goto err;
|
2015-09-02 21:31:28 +08:00
|
|
|
} else {
|
2017-05-13 02:19:51 +08:00
|
|
|
TEST_error("Bad encoding: %s."
|
|
|
|
" Should be one of {canonical, valid, invalid}",
|
|
|
|
encoding);
|
2019-01-08 14:27:27 +08:00
|
|
|
goto err;
|
2015-09-02 21:31:28 +08:00
|
|
|
}
|
|
|
|
t->data = edata;
|
|
|
|
return 1;
|
2019-01-08 14:27:27 +08:00
|
|
|
err:
|
|
|
|
OPENSSL_free(edata);
|
|
|
|
return 0;
|
2015-09-02 21:31:28 +08:00
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static void encode_test_cleanup(EVP_TEST *t)
|
2015-09-02 21:31:28 +08:00
|
|
|
{
|
2017-04-27 03:33:43 +08:00
|
|
|
ENCODE_DATA *edata = t->data;
|
|
|
|
|
|
|
|
OPENSSL_free(edata->input);
|
|
|
|
OPENSSL_free(edata->output);
|
2015-09-02 21:31:28 +08:00
|
|
|
memset(edata, 0, sizeof(*edata));
|
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static int encode_test_parse(EVP_TEST *t,
|
2015-09-02 21:31:28 +08:00
|
|
|
const char *keyword, const char *value)
|
|
|
|
{
|
2017-04-27 03:33:43 +08:00
|
|
|
ENCODE_DATA *edata = t->data;
|
2017-05-13 02:19:51 +08:00
|
|
|
|
2015-09-02 21:31:28 +08:00
|
|
|
if (strcmp(keyword, "Input") == 0)
|
2017-05-13 02:19:51 +08:00
|
|
|
return parse_bin(value, &edata->input, &edata->input_len);
|
2015-09-02 21:31:28 +08:00
|
|
|
if (strcmp(keyword, "Output") == 0)
|
2017-05-13 02:19:51 +08:00
|
|
|
return parse_bin(value, &edata->output, &edata->output_len);
|
2015-09-02 21:31:28 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static int encode_test_run(EVP_TEST *t)
|
2015-09-02 21:31:28 +08:00
|
|
|
{
|
2017-05-25 19:48:32 +08:00
|
|
|
ENCODE_DATA *expected = t->data;
|
2015-09-02 21:31:28 +08:00
|
|
|
unsigned char *encode_out = NULL, *decode_out = NULL;
|
|
|
|
int output_len, chunk_len;
|
2019-01-08 14:27:27 +08:00
|
|
|
EVP_ENCODE_CTX *decode_ctx = NULL, *encode_ctx = NULL;
|
2025-02-25 23:57:26 +08:00
|
|
|
size_t input_len, donelen, decode_length;
|
2015-12-11 23:10:53 +08:00
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
if (!TEST_ptr(decode_ctx = EVP_ENCODE_CTX_new())) {
|
|
|
|
t->err = "INTERNAL_ERROR";
|
2015-12-11 23:10:53 +08:00
|
|
|
goto err;
|
2017-04-27 03:33:43 +08:00
|
|
|
}
|
2015-09-02 21:31:28 +08:00
|
|
|
|
2017-05-25 19:48:32 +08:00
|
|
|
if (expected->encoding == BASE64_CANONICAL_ENCODING) {
|
2017-04-27 03:33:43 +08:00
|
|
|
|
|
|
|
if (!TEST_ptr(encode_ctx = EVP_ENCODE_CTX_new())
|
|
|
|
|| !TEST_ptr(encode_out =
|
2017-05-25 19:48:32 +08:00
|
|
|
OPENSSL_malloc(EVP_ENCODE_LENGTH(expected->input_len))))
|
2015-09-02 21:31:28 +08:00
|
|
|
goto err;
|
|
|
|
|
2015-12-11 23:10:53 +08:00
|
|
|
EVP_EncodeInit(encode_ctx);
|
2019-01-08 14:27:27 +08:00
|
|
|
|
2023-08-02 22:34:12 +08:00
|
|
|
input_len = expected->input_len;
|
|
|
|
donelen = 0;
|
|
|
|
output_len = 0;
|
|
|
|
do {
|
2025-06-18 17:59:04 +08:00
|
|
|
size_t current_len = (size_t)data_chunk_size;
|
2023-08-02 22:34:12 +08:00
|
|
|
|
2025-06-18 17:59:04 +08:00
|
|
|
if (data_chunk_size == 0 || current_len > input_len)
|
2023-08-02 22:34:12 +08:00
|
|
|
current_len = input_len;
|
|
|
|
if (!TEST_true(EVP_EncodeUpdate(encode_ctx, encode_out, &chunk_len,
|
|
|
|
expected->input + donelen,
|
2025-06-18 17:59:04 +08:00
|
|
|
(int)current_len)))
|
2023-08-02 22:34:12 +08:00
|
|
|
goto err;
|
|
|
|
donelen += current_len;
|
|
|
|
input_len -= current_len;
|
|
|
|
output_len += chunk_len;
|
|
|
|
} while (input_len > 0);
|
2015-09-02 21:31:28 +08:00
|
|
|
|
2023-08-02 22:34:12 +08:00
|
|
|
EVP_EncodeFinal(encode_ctx, encode_out + output_len, &chunk_len);
|
2015-09-02 21:31:28 +08:00
|
|
|
output_len += chunk_len;
|
|
|
|
|
2018-08-09 07:27:42 +08:00
|
|
|
if (!memory_err_compare(t, "BAD_ENCODING",
|
|
|
|
expected->output, expected->output_len,
|
|
|
|
encode_out, output_len))
|
2015-09-02 21:31:28 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2025-02-25 23:57:26 +08:00
|
|
|
decode_length = EVP_DECODE_LENGTH(expected->output_len);
|
|
|
|
if (!TEST_ptr(decode_out = OPENSSL_malloc(decode_length)))
|
2015-09-02 21:31:28 +08:00
|
|
|
goto err;
|
2025-02-25 23:57:26 +08:00
|
|
|
/*
|
|
|
|
* Fill memory with non-zeros
|
|
|
|
* to check that decoding does not place redundant zeros.
|
|
|
|
*/
|
|
|
|
memset(decode_out, 0xff, decode_length);
|
2015-09-02 21:31:28 +08:00
|
|
|
|
2023-08-02 22:34:12 +08:00
|
|
|
output_len = 0;
|
2015-12-11 23:10:53 +08:00
|
|
|
EVP_DecodeInit(decode_ctx);
|
2015-09-02 21:31:28 +08:00
|
|
|
|
2023-08-02 22:34:12 +08:00
|
|
|
input_len = expected->output_len;
|
|
|
|
donelen = 0;
|
|
|
|
do {
|
|
|
|
size_t current_len = (size_t) data_chunk_size;
|
|
|
|
|
|
|
|
if (data_chunk_size == 0 || (size_t) data_chunk_size > input_len)
|
|
|
|
current_len = input_len;
|
|
|
|
if (EVP_DecodeUpdate(decode_ctx, decode_out + output_len, &chunk_len,
|
2025-06-18 17:59:04 +08:00
|
|
|
expected->output + donelen, (int)current_len) < 0) {
|
2023-08-02 22:34:12 +08:00
|
|
|
t->err = "DECODE_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
donelen += current_len;
|
|
|
|
input_len -= current_len;
|
|
|
|
output_len += chunk_len;
|
|
|
|
} while (input_len > 0);
|
|
|
|
|
|
|
|
if (EVP_DecodeFinal(decode_ctx, decode_out + output_len, &chunk_len) != 1) {
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "DECODE_ERROR";
|
2015-09-02 21:31:28 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
output_len += chunk_len;
|
|
|
|
|
2017-05-25 19:48:32 +08:00
|
|
|
if (expected->encoding != BASE64_INVALID_ENCODING
|
2018-08-09 07:27:42 +08:00
|
|
|
&& !memory_err_compare(t, "BAD_DECODING",
|
|
|
|
expected->input, expected->input_len,
|
|
|
|
decode_out, output_len)) {
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "BAD_DECODING";
|
2015-09-02 21:31:28 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2025-02-25 23:57:26 +08:00
|
|
|
for (; output_len < (int)decode_length; output_len++) {
|
|
|
|
if (decode_out[output_len] != 0xff) {
|
|
|
|
t->err = "BAD_DECODING";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = NULL;
|
2015-09-02 21:31:28 +08:00
|
|
|
err:
|
|
|
|
OPENSSL_free(encode_out);
|
|
|
|
OPENSSL_free(decode_out);
|
2015-12-11 23:10:53 +08:00
|
|
|
EVP_ENCODE_CTX_free(decode_ctx);
|
2019-01-08 14:27:27 +08:00
|
|
|
EVP_ENCODE_CTX_free(encode_ctx);
|
2015-09-02 21:31:28 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static const EVP_TEST_METHOD encode_test_method = {
|
2015-09-02 21:31:28 +08:00
|
|
|
"Encoding",
|
|
|
|
encode_test_init,
|
|
|
|
encode_test_cleanup,
|
|
|
|
encode_test_parse,
|
|
|
|
encode_test_run,
|
|
|
|
};
|
2016-01-19 21:59:00 +08:00
|
|
|
|
2018-06-22 05:16:18 +08:00
|
|
|
|
2020-06-05 11:47:55 +08:00
|
|
|
/**
|
2020-08-07 12:29:00 +08:00
|
|
|
** RAND TESTS
|
|
|
|
**/
|
2020-06-05 11:47:55 +08:00
|
|
|
#define MAX_RAND_REPEATS 15
|
|
|
|
|
|
|
|
typedef struct rand_data_pass_st {
|
|
|
|
unsigned char *entropy;
|
|
|
|
unsigned char *reseed_entropy;
|
|
|
|
unsigned char *nonce;
|
|
|
|
unsigned char *pers;
|
|
|
|
unsigned char *reseed_addin;
|
|
|
|
unsigned char *addinA;
|
|
|
|
unsigned char *addinB;
|
|
|
|
unsigned char *pr_entropyA;
|
|
|
|
unsigned char *pr_entropyB;
|
|
|
|
unsigned char *output;
|
|
|
|
size_t entropy_len, nonce_len, pers_len, addinA_len, addinB_len,
|
|
|
|
pr_entropyA_len, pr_entropyB_len, output_len, reseed_entropy_len,
|
|
|
|
reseed_addin_len;
|
|
|
|
} RAND_DATA_PASS;
|
|
|
|
|
|
|
|
typedef struct rand_data_st {
|
|
|
|
/* Context for this operation */
|
|
|
|
EVP_RAND_CTX *ctx;
|
|
|
|
EVP_RAND_CTX *parent;
|
|
|
|
int n;
|
|
|
|
int prediction_resistance;
|
|
|
|
int use_df;
|
|
|
|
unsigned int generate_bits;
|
|
|
|
char *cipher;
|
|
|
|
char *digest;
|
2024-07-03 09:12:39 +08:00
|
|
|
STACK_OF(OPENSSL_STRING) *init_controls; /* collection of controls */
|
2020-06-05 11:47:55 +08:00
|
|
|
|
|
|
|
/* Expected output */
|
|
|
|
RAND_DATA_PASS data[MAX_RAND_REPEATS];
|
|
|
|
} RAND_DATA;
|
|
|
|
|
|
|
|
static int rand_test_init(EVP_TEST *t, const char *name)
|
|
|
|
{
|
|
|
|
RAND_DATA *rdata;
|
|
|
|
EVP_RAND *rand;
|
|
|
|
OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
|
|
|
|
unsigned int strength = 256;
|
|
|
|
|
|
|
|
if (!TEST_ptr(rdata = OPENSSL_zalloc(sizeof(*rdata))))
|
|
|
|
return 0;
|
|
|
|
|
2020-08-05 21:46:48 +08:00
|
|
|
/* TEST-RAND is available in the FIPS provider but not with "fips=yes" */
|
|
|
|
rand = EVP_RAND_fetch(libctx, "TEST-RAND", "-fips");
|
2020-06-05 11:47:55 +08:00
|
|
|
if (rand == NULL)
|
|
|
|
goto err;
|
|
|
|
rdata->parent = EVP_RAND_CTX_new(rand, NULL);
|
|
|
|
EVP_RAND_free(rand);
|
|
|
|
if (rdata->parent == NULL)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
*params = OSSL_PARAM_construct_uint(OSSL_RAND_PARAM_STRENGTH, &strength);
|
2021-04-16 07:13:43 +08:00
|
|
|
if (!EVP_RAND_CTX_set_params(rdata->parent, params))
|
2020-06-05 11:47:55 +08:00
|
|
|
goto err;
|
|
|
|
|
2023-09-08 17:44:27 +08:00
|
|
|
rand = EVP_RAND_fetch(libctx, name, propquery);
|
2020-06-05 11:47:55 +08:00
|
|
|
if (rand == NULL)
|
|
|
|
goto err;
|
|
|
|
rdata->ctx = EVP_RAND_CTX_new(rand, rdata->parent);
|
|
|
|
EVP_RAND_free(rand);
|
|
|
|
if (rdata->ctx == NULL)
|
|
|
|
goto err;
|
2024-07-03 09:12:39 +08:00
|
|
|
rdata->init_controls = sk_OPENSSL_STRING_new_null();
|
2020-06-05 11:47:55 +08:00
|
|
|
|
|
|
|
rdata->n = -1;
|
|
|
|
t->data = rdata;
|
|
|
|
return 1;
|
|
|
|
err:
|
|
|
|
EVP_RAND_CTX_free(rdata->parent);
|
|
|
|
OPENSSL_free(rdata);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void rand_test_cleanup(EVP_TEST *t)
|
|
|
|
{
|
|
|
|
RAND_DATA *rdata = t->data;
|
|
|
|
int i;
|
|
|
|
|
2024-07-03 09:12:39 +08:00
|
|
|
ctrlfree(rdata->init_controls);
|
2020-06-05 11:47:55 +08:00
|
|
|
OPENSSL_free(rdata->cipher);
|
|
|
|
OPENSSL_free(rdata->digest);
|
|
|
|
|
|
|
|
for (i = 0; i <= rdata->n; i++) {
|
|
|
|
OPENSSL_free(rdata->data[i].entropy);
|
|
|
|
OPENSSL_free(rdata->data[i].reseed_entropy);
|
|
|
|
OPENSSL_free(rdata->data[i].nonce);
|
|
|
|
OPENSSL_free(rdata->data[i].pers);
|
|
|
|
OPENSSL_free(rdata->data[i].reseed_addin);
|
|
|
|
OPENSSL_free(rdata->data[i].addinA);
|
|
|
|
OPENSSL_free(rdata->data[i].addinB);
|
|
|
|
OPENSSL_free(rdata->data[i].pr_entropyA);
|
|
|
|
OPENSSL_free(rdata->data[i].pr_entropyB);
|
|
|
|
OPENSSL_free(rdata->data[i].output);
|
|
|
|
}
|
|
|
|
EVP_RAND_CTX_free(rdata->ctx);
|
|
|
|
EVP_RAND_CTX_free(rdata->parent);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int rand_test_parse(EVP_TEST *t,
|
|
|
|
const char *keyword, const char *value)
|
|
|
|
{
|
|
|
|
RAND_DATA *rdata = t->data;
|
|
|
|
RAND_DATA_PASS *item;
|
|
|
|
const char *p;
|
|
|
|
int n;
|
|
|
|
|
|
|
|
if ((p = strchr(keyword, '.')) != NULL) {
|
|
|
|
n = atoi(++p);
|
|
|
|
if (n >= MAX_RAND_REPEATS)
|
|
|
|
return 0;
|
|
|
|
if (n > rdata->n)
|
|
|
|
rdata->n = n;
|
|
|
|
item = rdata->data + n;
|
2021-06-21 14:55:50 +08:00
|
|
|
if (HAS_PREFIX(keyword, "Entropy."))
|
2020-06-05 11:47:55 +08:00
|
|
|
return parse_bin(value, &item->entropy, &item->entropy_len);
|
2021-06-21 14:55:50 +08:00
|
|
|
if (HAS_PREFIX(keyword, "ReseedEntropy."))
|
2020-06-05 11:47:55 +08:00
|
|
|
return parse_bin(value, &item->reseed_entropy,
|
|
|
|
&item->reseed_entropy_len);
|
2021-06-21 14:55:50 +08:00
|
|
|
if (HAS_PREFIX(keyword, "Nonce."))
|
2020-06-05 11:47:55 +08:00
|
|
|
return parse_bin(value, &item->nonce, &item->nonce_len);
|
2021-06-21 14:55:50 +08:00
|
|
|
if (HAS_PREFIX(keyword, "PersonalisationString."))
|
2020-06-05 11:47:55 +08:00
|
|
|
return parse_bin(value, &item->pers, &item->pers_len);
|
2021-06-21 14:55:50 +08:00
|
|
|
if (HAS_PREFIX(keyword, "ReseedAdditionalInput."))
|
2020-06-05 11:47:55 +08:00
|
|
|
return parse_bin(value, &item->reseed_addin,
|
|
|
|
&item->reseed_addin_len);
|
2021-06-21 14:55:50 +08:00
|
|
|
if (HAS_PREFIX(keyword, "AdditionalInputA."))
|
2020-06-05 11:47:55 +08:00
|
|
|
return parse_bin(value, &item->addinA, &item->addinA_len);
|
2021-06-21 14:55:50 +08:00
|
|
|
if (HAS_PREFIX(keyword, "AdditionalInputB."))
|
2020-06-05 11:47:55 +08:00
|
|
|
return parse_bin(value, &item->addinB, &item->addinB_len);
|
2021-06-21 14:55:50 +08:00
|
|
|
if (HAS_PREFIX(keyword, "EntropyPredictionResistanceA."))
|
2020-06-05 11:47:55 +08:00
|
|
|
return parse_bin(value, &item->pr_entropyA, &item->pr_entropyA_len);
|
2021-06-21 14:55:50 +08:00
|
|
|
if (HAS_PREFIX(keyword, "EntropyPredictionResistanceB."))
|
2020-06-05 11:47:55 +08:00
|
|
|
return parse_bin(value, &item->pr_entropyB, &item->pr_entropyB_len);
|
2021-06-21 14:55:50 +08:00
|
|
|
if (HAS_PREFIX(keyword, "Output."))
|
2020-06-05 11:47:55 +08:00
|
|
|
return parse_bin(value, &item->output, &item->output_len);
|
|
|
|
} else {
|
|
|
|
if (strcmp(keyword, "Cipher") == 0)
|
|
|
|
return TEST_ptr(rdata->cipher = OPENSSL_strdup(value));
|
|
|
|
if (strcmp(keyword, "Digest") == 0)
|
|
|
|
return TEST_ptr(rdata->digest = OPENSSL_strdup(value));
|
|
|
|
if (strcmp(keyword, "DerivationFunction") == 0) {
|
|
|
|
rdata->use_df = atoi(value) != 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (strcmp(keyword, "GenerateBits") == 0) {
|
|
|
|
if ((n = atoi(value)) <= 0 || n % 8 != 0)
|
|
|
|
return 0;
|
|
|
|
rdata->generate_bits = (unsigned int)n;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (strcmp(keyword, "PredictionResistance") == 0) {
|
|
|
|
rdata->prediction_resistance = atoi(value) != 0;
|
|
|
|
return 1;
|
|
|
|
}
|
2024-07-03 09:12:39 +08:00
|
|
|
if (strcmp(keyword, "CtrlInit") == 0)
|
|
|
|
return ctrladd(rdata->init_controls, value);
|
2020-06-05 11:47:55 +08:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int rand_test_run(EVP_TEST *t)
|
|
|
|
{
|
|
|
|
RAND_DATA *expected = t->data;
|
|
|
|
RAND_DATA_PASS *item;
|
|
|
|
unsigned char *got;
|
|
|
|
size_t got_len = expected->generate_bits / 8;
|
2024-07-03 09:12:39 +08:00
|
|
|
OSSL_PARAM params[8], *p = params;
|
2020-06-05 11:47:55 +08:00
|
|
|
int i = -1, ret = 0;
|
|
|
|
unsigned int strength;
|
|
|
|
unsigned char *z;
|
2024-07-03 09:12:39 +08:00
|
|
|
size_t params_n = 0, params_allocated_n = 0;
|
2020-06-05 11:47:55 +08:00
|
|
|
|
|
|
|
if (!TEST_ptr(got = OPENSSL_malloc(got_len)))
|
|
|
|
return 0;
|
|
|
|
|
2024-07-03 09:12:39 +08:00
|
|
|
if (sk_OPENSSL_STRING_num(expected->init_controls) > 0) {
|
|
|
|
if (!ctrl2params(t, expected->init_controls,
|
|
|
|
NULL,
|
|
|
|
params, OSSL_NELEM(params), ¶ms_n))
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
p = params + params_n;
|
|
|
|
|
2020-06-05 11:47:55 +08:00
|
|
|
*p++ = OSSL_PARAM_construct_int(OSSL_DRBG_PARAM_USE_DF, &expected->use_df);
|
|
|
|
if (expected->cipher != NULL)
|
|
|
|
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_CIPHER,
|
|
|
|
expected->cipher, 0);
|
|
|
|
if (expected->digest != NULL)
|
|
|
|
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_DIGEST,
|
|
|
|
expected->digest, 0);
|
|
|
|
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_DRBG_PARAM_MAC, "HMAC", 0);
|
|
|
|
*p = OSSL_PARAM_construct_end();
|
2024-07-03 09:12:39 +08:00
|
|
|
if (!EVP_RAND_CTX_set_params(expected->ctx, params)) {
|
|
|
|
if (t->expect_unapproved == 0) {
|
|
|
|
t->err = "EVP_RAND_CTX_set_params";
|
|
|
|
ret = 1;
|
|
|
|
}
|
2020-06-05 11:47:55 +08:00
|
|
|
goto err;
|
2024-07-03 09:12:39 +08:00
|
|
|
}
|
|
|
|
ctrl2params_free(params, params_n, params_allocated_n);
|
|
|
|
params_n = 0;
|
2020-06-05 11:47:55 +08:00
|
|
|
|
Rename all getters to use get/get0 in name
For functions that exist in 1.1.1 provide a simple aliases via #define.
Fixes #15236
Functions with OSSL_DECODER_, OSSL_ENCODER_, OSSL_STORE_LOADER_,
EVP_KEYEXCH_, EVP_KEM_, EVP_ASYM_CIPHER_, EVP_SIGNATURE_,
EVP_KEYMGMT_, EVP_RAND_, EVP_MAC_, EVP_KDF_, EVP_PKEY_,
EVP_MD_, and EVP_CIPHER_ prefixes are renamed.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15405)
2021-05-21 22:58:08 +08:00
|
|
|
strength = EVP_RAND_get_strength(expected->ctx);
|
2020-06-05 11:47:55 +08:00
|
|
|
for (i = 0; i <= expected->n; i++) {
|
|
|
|
item = expected->data + i;
|
|
|
|
|
|
|
|
p = params;
|
|
|
|
z = item->entropy != NULL ? item->entropy : (unsigned char *)"";
|
|
|
|
*p++ = OSSL_PARAM_construct_octet_string(OSSL_RAND_PARAM_TEST_ENTROPY,
|
|
|
|
z, item->entropy_len);
|
|
|
|
z = item->nonce != NULL ? item->nonce : (unsigned char *)"";
|
|
|
|
*p++ = OSSL_PARAM_construct_octet_string(OSSL_RAND_PARAM_TEST_NONCE,
|
|
|
|
z, item->nonce_len);
|
|
|
|
*p = OSSL_PARAM_construct_end();
|
2021-02-26 08:56:17 +08:00
|
|
|
if (!TEST_true(EVP_RAND_instantiate(expected->parent, strength,
|
|
|
|
0, NULL, 0, params)))
|
2020-06-05 11:47:55 +08:00
|
|
|
goto err;
|
|
|
|
|
|
|
|
z = item->pers != NULL ? item->pers : (unsigned char *)"";
|
|
|
|
if (!TEST_true(EVP_RAND_instantiate
|
|
|
|
(expected->ctx, strength,
|
|
|
|
expected->prediction_resistance, z,
|
2021-02-26 08:56:17 +08:00
|
|
|
item->pers_len, NULL)))
|
2020-06-05 11:47:55 +08:00
|
|
|
goto err;
|
|
|
|
|
|
|
|
if (item->reseed_entropy != NULL) {
|
|
|
|
params[0] = OSSL_PARAM_construct_octet_string
|
|
|
|
(OSSL_RAND_PARAM_TEST_ENTROPY, item->reseed_entropy,
|
|
|
|
item->reseed_entropy_len);
|
|
|
|
params[1] = OSSL_PARAM_construct_end();
|
2021-04-16 07:13:43 +08:00
|
|
|
if (!TEST_true(EVP_RAND_CTX_set_params(expected->parent, params)))
|
2020-06-05 11:47:55 +08:00
|
|
|
goto err;
|
|
|
|
|
|
|
|
if (!TEST_true(EVP_RAND_reseed
|
|
|
|
(expected->ctx, expected->prediction_resistance,
|
|
|
|
NULL, 0, item->reseed_addin,
|
|
|
|
item->reseed_addin_len)))
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
if (item->pr_entropyA != NULL) {
|
|
|
|
params[0] = OSSL_PARAM_construct_octet_string
|
|
|
|
(OSSL_RAND_PARAM_TEST_ENTROPY, item->pr_entropyA,
|
|
|
|
item->pr_entropyA_len);
|
|
|
|
params[1] = OSSL_PARAM_construct_end();
|
2021-04-16 07:13:43 +08:00
|
|
|
if (!TEST_true(EVP_RAND_CTX_set_params(expected->parent, params)))
|
2020-06-05 11:47:55 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
if (!TEST_true(EVP_RAND_generate
|
|
|
|
(expected->ctx, got, got_len,
|
|
|
|
strength, expected->prediction_resistance,
|
|
|
|
item->addinA, item->addinA_len)))
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
if (item->pr_entropyB != NULL) {
|
|
|
|
params[0] = OSSL_PARAM_construct_octet_string
|
|
|
|
(OSSL_RAND_PARAM_TEST_ENTROPY, item->pr_entropyB,
|
|
|
|
item->pr_entropyB_len);
|
|
|
|
params[1] = OSSL_PARAM_construct_end();
|
2021-04-16 07:13:43 +08:00
|
|
|
if (!TEST_true(EVP_RAND_CTX_set_params(expected->parent, params)))
|
2022-01-05 23:17:53 +08:00
|
|
|
goto err;
|
2020-06-05 11:47:55 +08:00
|
|
|
}
|
|
|
|
if (!TEST_true(EVP_RAND_generate
|
|
|
|
(expected->ctx, got, got_len,
|
|
|
|
strength, expected->prediction_resistance,
|
|
|
|
item->addinB, item->addinB_len)))
|
|
|
|
goto err;
|
|
|
|
if (!TEST_mem_eq(got, got_len, item->output, item->output_len))
|
|
|
|
goto err;
|
2024-07-03 09:12:39 +08:00
|
|
|
if (!rand_check_fips_approved(expected->ctx, t))
|
|
|
|
goto err;
|
2020-06-05 11:47:55 +08:00
|
|
|
if (!TEST_true(EVP_RAND_uninstantiate(expected->ctx))
|
|
|
|
|| !TEST_true(EVP_RAND_uninstantiate(expected->parent))
|
|
|
|
|| !TEST_true(EVP_RAND_verify_zeroization(expected->ctx))
|
Rename all getters to use get/get0 in name
For functions that exist in 1.1.1 provide a simple aliases via #define.
Fixes #15236
Functions with OSSL_DECODER_, OSSL_ENCODER_, OSSL_STORE_LOADER_,
EVP_KEYEXCH_, EVP_KEM_, EVP_ASYM_CIPHER_, EVP_SIGNATURE_,
EVP_KEYMGMT_, EVP_RAND_, EVP_MAC_, EVP_KDF_, EVP_PKEY_,
EVP_MD_, and EVP_CIPHER_ prefixes are renamed.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15405)
2021-05-21 22:58:08 +08:00
|
|
|
|| !TEST_int_eq(EVP_RAND_get_state(expected->ctx),
|
2020-06-05 11:47:55 +08:00
|
|
|
EVP_RAND_STATE_UNINITIALISED))
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
t->err = NULL;
|
|
|
|
ret = 1;
|
|
|
|
|
|
|
|
err:
|
|
|
|
if (ret == 0 && i >= 0)
|
|
|
|
TEST_info("Error in test case %d of %d\n", i, expected->n + 1);
|
|
|
|
OPENSSL_free(got);
|
2024-07-03 09:12:39 +08:00
|
|
|
ctrl2params_free(params, params_n, params_allocated_n);
|
2020-06-05 11:47:55 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const EVP_TEST_METHOD rand_test_method = {
|
|
|
|
"RAND",
|
|
|
|
rand_test_init,
|
|
|
|
rand_test_cleanup,
|
|
|
|
rand_test_parse,
|
|
|
|
rand_test_run
|
|
|
|
};
|
|
|
|
|
2017-05-13 02:19:51 +08:00
|
|
|
/**
|
2020-08-07 12:29:00 +08:00
|
|
|
** KDF TESTS
|
|
|
|
**/
|
2017-04-27 03:33:43 +08:00
|
|
|
typedef struct kdf_data_st {
|
2016-01-19 21:59:00 +08:00
|
|
|
/* Context for this operation */
|
2018-06-22 05:16:18 +08:00
|
|
|
EVP_KDF_CTX *ctx;
|
2016-01-19 21:59:00 +08:00
|
|
|
/* Expected output */
|
|
|
|
unsigned char *output;
|
|
|
|
size_t output_len;
|
2019-08-21 16:52:04 +08:00
|
|
|
OSSL_PARAM params[20];
|
|
|
|
OSSL_PARAM *p;
|
2024-07-03 09:12:39 +08:00
|
|
|
STACK_OF(OPENSSL_STRING) *init_controls; /* collection of controls */
|
2017-04-27 03:33:43 +08:00
|
|
|
} KDF_DATA;
|
2016-01-19 21:59:00 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Perform public key operation setup: lookup key, allocated ctx and call
|
|
|
|
* the appropriate initialisation function
|
|
|
|
*/
|
2017-04-27 03:33:43 +08:00
|
|
|
static int kdf_test_init(EVP_TEST *t, const char *name)
|
2016-01-19 21:59:00 +08:00
|
|
|
{
|
2017-04-27 03:33:43 +08:00
|
|
|
KDF_DATA *kdata;
|
2019-08-21 16:52:04 +08:00
|
|
|
EVP_KDF *kdf;
|
2017-08-03 07:45:49 +08:00
|
|
|
|
2020-08-07 12:29:00 +08:00
|
|
|
if (is_kdf_disabled(name)) {
|
|
|
|
TEST_info("skipping, '%s' is disabled", name);
|
2019-07-09 07:33:18 +08:00
|
|
|
t->skip = 1;
|
|
|
|
return 1;
|
|
|
|
}
|
2017-08-25 18:18:23 +08:00
|
|
|
|
2019-08-21 16:52:04 +08:00
|
|
|
if (!TEST_ptr(kdata = OPENSSL_zalloc(sizeof(*kdata))))
|
2019-04-22 15:18:56 +08:00
|
|
|
return 0;
|
2019-08-21 16:52:04 +08:00
|
|
|
kdata->p = kdata->params;
|
|
|
|
*kdata->p = OSSL_PARAM_construct_end();
|
2016-01-19 21:59:00 +08:00
|
|
|
|
2023-09-08 17:44:27 +08:00
|
|
|
kdf = EVP_KDF_fetch(libctx, name, propquery);
|
2019-09-08 16:25:34 +08:00
|
|
|
if (kdf == NULL) {
|
|
|
|
OPENSSL_free(kdata);
|
2016-01-19 21:59:00 +08:00
|
|
|
return 0;
|
2019-09-08 16:25:34 +08:00
|
|
|
}
|
2020-06-18 16:30:48 +08:00
|
|
|
kdata->ctx = EVP_KDF_CTX_new(kdf);
|
2019-08-21 16:52:04 +08:00
|
|
|
EVP_KDF_free(kdf);
|
2017-07-06 07:10:28 +08:00
|
|
|
if (kdata->ctx == NULL) {
|
|
|
|
OPENSSL_free(kdata);
|
2016-01-19 21:59:00 +08:00
|
|
|
return 0;
|
2017-07-06 07:10:28 +08:00
|
|
|
}
|
2017-05-13 02:19:51 +08:00
|
|
|
t->data = kdata;
|
2024-07-03 09:12:39 +08:00
|
|
|
kdata->init_controls = sk_OPENSSL_STRING_new_null();
|
2016-01-19 21:59:00 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static void kdf_test_cleanup(EVP_TEST *t)
|
2016-01-19 21:59:00 +08:00
|
|
|
{
|
2017-04-27 03:33:43 +08:00
|
|
|
KDF_DATA *kdata = t->data;
|
2019-08-21 16:52:04 +08:00
|
|
|
OSSL_PARAM *p;
|
|
|
|
|
2024-07-03 09:12:39 +08:00
|
|
|
ctrlfree(kdata->init_controls);
|
2019-08-21 16:52:04 +08:00
|
|
|
for (p = kdata->params; p->key != NULL; p++)
|
|
|
|
OPENSSL_free(p->data);
|
2016-01-19 21:59:00 +08:00
|
|
|
OPENSSL_free(kdata->output);
|
2020-06-18 16:30:48 +08:00
|
|
|
EVP_KDF_CTX_free(kdata->ctx);
|
2018-06-22 05:16:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int kdf_test_ctrl(EVP_TEST *t, EVP_KDF_CTX *kctx,
|
|
|
|
const char *value)
|
|
|
|
{
|
2019-08-21 16:52:04 +08:00
|
|
|
KDF_DATA *kdata = t->data;
|
2018-06-22 05:16:18 +08:00
|
|
|
int rv;
|
2019-08-21 16:52:04 +08:00
|
|
|
char *p, *name;
|
2020-06-18 16:30:48 +08:00
|
|
|
const OSSL_PARAM *defs = EVP_KDF_settable_ctx_params(EVP_KDF_CTX_kdf(kctx));
|
2018-06-22 05:16:18 +08:00
|
|
|
|
2019-08-21 16:52:04 +08:00
|
|
|
if (!TEST_ptr(name = OPENSSL_strdup(value)))
|
2018-06-22 05:16:18 +08:00
|
|
|
return 0;
|
2019-08-21 16:52:04 +08:00
|
|
|
p = strchr(name, ':');
|
2024-01-27 00:33:18 +08:00
|
|
|
if (p == NULL)
|
|
|
|
p = "";
|
|
|
|
else
|
2018-06-22 05:16:18 +08:00
|
|
|
*p++ = '\0';
|
2019-08-21 16:52:04 +08:00
|
|
|
|
2022-02-09 18:23:01 +08:00
|
|
|
if (strcmp(name, "r") == 0
|
|
|
|
&& OSSL_PARAM_locate_const(defs, name) == NULL) {
|
|
|
|
TEST_info("skipping, setting 'r' is unsupported");
|
|
|
|
t->skip = 1;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
2021-09-28 04:45:38 +08:00
|
|
|
if (strcmp(name, "lanes") == 0
|
|
|
|
&& OSSL_PARAM_locate_const(defs, name) == NULL) {
|
|
|
|
TEST_info("skipping, setting 'lanes' is unsupported");
|
|
|
|
t->skip = 1;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strcmp(name, "iter") == 0
|
|
|
|
&& OSSL_PARAM_locate_const(defs, name) == NULL) {
|
|
|
|
TEST_info("skipping, setting 'iter' is unsupported");
|
|
|
|
t->skip = 1;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strcmp(name, "memcost") == 0
|
|
|
|
&& OSSL_PARAM_locate_const(defs, name) == NULL) {
|
|
|
|
TEST_info("skipping, setting 'memcost' is unsupported");
|
|
|
|
t->skip = 1;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strcmp(name, "secret") == 0
|
|
|
|
&& OSSL_PARAM_locate_const(defs, name) == NULL) {
|
|
|
|
TEST_info("skipping, setting 'secret' is unsupported");
|
|
|
|
t->skip = 1;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strcmp(name, "pass") == 0
|
|
|
|
&& OSSL_PARAM_locate_const(defs, name) == NULL) {
|
|
|
|
TEST_info("skipping, setting 'pass' is unsupported");
|
|
|
|
t->skip = 1;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strcmp(name, "ad") == 0
|
|
|
|
&& OSSL_PARAM_locate_const(defs, name) == NULL) {
|
|
|
|
TEST_info("skipping, setting 'ad' is unsupported");
|
|
|
|
t->skip = 1;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
2019-09-08 16:37:13 +08:00
|
|
|
rv = OSSL_PARAM_allocate_from_text(kdata->p, defs, name, p,
|
2024-01-27 00:33:18 +08:00
|
|
|
strlen(p), NULL);
|
2019-08-21 16:52:04 +08:00
|
|
|
*++kdata->p = OSSL_PARAM_construct_end();
|
|
|
|
if (!rv) {
|
|
|
|
t->err = "KDF_PARAM_ERROR";
|
|
|
|
OPENSSL_free(name);
|
|
|
|
return 0;
|
|
|
|
}
|
2024-01-27 00:33:18 +08:00
|
|
|
if (strcmp(name, "digest") == 0) {
|
2020-08-07 12:29:00 +08:00
|
|
|
if (is_digest_disabled(p)) {
|
|
|
|
TEST_info("skipping, '%s' is disabled", p);
|
2018-06-22 05:16:18 +08:00
|
|
|
t->skip = 1;
|
2020-08-07 12:29:00 +08:00
|
|
|
}
|
2022-02-09 18:23:01 +08:00
|
|
|
goto end;
|
2018-06-22 05:16:18 +08:00
|
|
|
}
|
2024-01-27 00:33:18 +08:00
|
|
|
|
|
|
|
if ((strcmp(name, "cipher") == 0
|
|
|
|
|| strcmp(name, "cekalg") == 0)
|
2020-11-16 10:42:18 +08:00
|
|
|
&& is_cipher_disabled(p)) {
|
|
|
|
TEST_info("skipping, '%s' is disabled", p);
|
|
|
|
t->skip = 1;
|
2022-02-09 18:23:01 +08:00
|
|
|
goto end;
|
2019-09-18 04:35:23 +08:00
|
|
|
}
|
2024-01-27 00:33:18 +08:00
|
|
|
if ((strcmp(name, "mac") == 0)
|
2021-11-18 17:47:14 +08:00
|
|
|
&& is_mac_disabled(p)) {
|
|
|
|
TEST_info("skipping, '%s' is disabled", p);
|
|
|
|
t->skip = 1;
|
|
|
|
}
|
2022-02-09 18:23:01 +08:00
|
|
|
end:
|
2019-08-21 16:52:04 +08:00
|
|
|
OPENSSL_free(name);
|
|
|
|
return 1;
|
2016-01-19 21:59:00 +08:00
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static int kdf_test_parse(EVP_TEST *t,
|
2016-01-19 21:59:00 +08:00
|
|
|
const char *keyword, const char *value)
|
|
|
|
{
|
2017-04-27 03:33:43 +08:00
|
|
|
KDF_DATA *kdata = t->data;
|
|
|
|
|
2016-01-19 21:59:00 +08:00
|
|
|
if (strcmp(keyword, "Output") == 0)
|
2017-05-13 02:19:51 +08:00
|
|
|
return parse_bin(value, &kdata->output, &kdata->output_len);
|
2024-07-03 09:12:39 +08:00
|
|
|
if (strcmp(keyword, "CtrlInit") == 0)
|
|
|
|
return ctrladd(kdata->init_controls, value);
|
2021-06-21 14:55:50 +08:00
|
|
|
if (HAS_PREFIX(keyword, "Ctrl"))
|
2018-06-22 05:16:18 +08:00
|
|
|
return kdf_test_ctrl(t, kdata->ctx, value);
|
2016-01-19 21:59:00 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static int kdf_test_run(EVP_TEST *t)
|
2016-01-19 21:59:00 +08:00
|
|
|
{
|
2024-07-03 09:12:39 +08:00
|
|
|
int ret = 1;
|
2017-05-25 19:48:32 +08:00
|
|
|
KDF_DATA *expected = t->data;
|
|
|
|
unsigned char *got = NULL;
|
|
|
|
size_t got_len = expected->output_len;
|
2022-01-24 13:17:25 +08:00
|
|
|
EVP_KDF_CTX *ctx;
|
2024-07-03 09:12:39 +08:00
|
|
|
OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END };
|
|
|
|
size_t params_n = 0, params_allocated_n = 0;
|
|
|
|
|
|
|
|
if (sk_OPENSSL_STRING_num(expected->init_controls) > 0) {
|
|
|
|
if (!ctrl2params(t, expected->init_controls,
|
|
|
|
NULL,
|
|
|
|
params, OSSL_NELEM(params), ¶ms_n))
|
|
|
|
goto err;
|
|
|
|
if (!EVP_KDF_CTX_set_params(expected->ctx, params)) {
|
|
|
|
t->err = "KDF_CTRL_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
2017-04-27 03:33:43 +08:00
|
|
|
|
2020-06-18 16:30:48 +08:00
|
|
|
if (!EVP_KDF_CTX_set_params(expected->ctx, expected->params)) {
|
2019-08-21 16:52:04 +08:00
|
|
|
t->err = "KDF_CTRL_ERROR";
|
2024-07-03 09:12:39 +08:00
|
|
|
goto err;
|
2019-08-21 16:52:04 +08:00
|
|
|
}
|
2021-08-27 19:11:39 +08:00
|
|
|
if (!TEST_ptr(got = OPENSSL_malloc(got_len == 0 ? 1 : got_len))) {
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "INTERNAL_ERROR";
|
2016-01-19 21:59:00 +08:00
|
|
|
goto err;
|
2017-04-27 03:33:43 +08:00
|
|
|
}
|
2022-09-14 04:38:30 +08:00
|
|
|
/* FIPS(3.0.0): can't dup KDF contexts #17572 */
|
2022-09-13 06:49:05 +08:00
|
|
|
if (fips_provider_version_gt(libctx, 3, 0, 0)
|
|
|
|
&& (ctx = EVP_KDF_CTX_dup(expected->ctx)) != NULL) {
|
2022-01-24 13:17:25 +08:00
|
|
|
EVP_KDF_CTX_free(expected->ctx);
|
|
|
|
expected->ctx = ctx;
|
|
|
|
}
|
2021-02-26 08:06:31 +08:00
|
|
|
if (EVP_KDF_derive(expected->ctx, got, got_len, NULL) <= 0) {
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "KDF_DERIVE_ERROR";
|
2016-01-19 21:59:00 +08:00
|
|
|
goto err;
|
2017-04-27 03:33:43 +08:00
|
|
|
}
|
2024-07-03 09:12:39 +08:00
|
|
|
if (!kdf_check_fips_approved(expected->ctx, t)) {
|
|
|
|
ret = 0;
|
|
|
|
goto err;
|
|
|
|
}
|
2018-08-09 07:27:42 +08:00
|
|
|
if (!memory_err_compare(t, "KDF_MISMATCH",
|
|
|
|
expected->output, expected->output_len,
|
|
|
|
got, got_len))
|
2016-01-19 21:59:00 +08:00
|
|
|
goto err;
|
2018-08-09 07:27:42 +08:00
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = NULL;
|
|
|
|
|
2016-01-19 21:59:00 +08:00
|
|
|
err:
|
2024-07-03 09:12:39 +08:00
|
|
|
ctrl2params_free(params, params_n, params_allocated_n);
|
2017-05-25 19:48:32 +08:00
|
|
|
OPENSSL_free(got);
|
2024-07-03 09:12:39 +08:00
|
|
|
return ret;
|
2016-01-19 21:59:00 +08:00
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static const EVP_TEST_METHOD kdf_test_method = {
|
2016-01-19 21:59:00 +08:00
|
|
|
"KDF",
|
|
|
|
kdf_test_init,
|
|
|
|
kdf_test_cleanup,
|
|
|
|
kdf_test_parse,
|
|
|
|
kdf_test_run
|
|
|
|
};
|
2017-04-26 08:50:59 +08:00
|
|
|
|
2018-06-22 05:16:18 +08:00
|
|
|
/**
|
2020-08-07 12:29:00 +08:00
|
|
|
** PKEY KDF TESTS
|
|
|
|
**/
|
2018-06-22 05:16:18 +08:00
|
|
|
|
|
|
|
typedef struct pkey_kdf_data_st {
|
|
|
|
/* Context for this operation */
|
|
|
|
EVP_PKEY_CTX *ctx;
|
|
|
|
/* Expected output */
|
|
|
|
unsigned char *output;
|
|
|
|
size_t output_len;
|
|
|
|
} PKEY_KDF_DATA;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Perform public key operation setup: lookup key, allocated ctx and call
|
|
|
|
* the appropriate initialisation function
|
|
|
|
*/
|
|
|
|
static int pkey_kdf_test_init(EVP_TEST *t, const char *name)
|
|
|
|
{
|
2020-08-07 12:29:00 +08:00
|
|
|
PKEY_KDF_DATA *kdata = NULL;
|
2018-06-22 05:16:18 +08:00
|
|
|
|
2020-08-07 12:29:00 +08:00
|
|
|
if (is_kdf_disabled(name)) {
|
|
|
|
TEST_info("skipping, '%s' is disabled", name);
|
2018-06-22 05:16:18 +08:00
|
|
|
t->skip = 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!TEST_ptr(kdata = OPENSSL_zalloc(sizeof(*kdata))))
|
|
|
|
return 0;
|
2020-08-07 19:23:07 +08:00
|
|
|
|
2023-09-08 17:44:27 +08:00
|
|
|
kdata->ctx = EVP_PKEY_CTX_new_from_name(libctx, name, propquery);
|
2020-08-07 12:29:00 +08:00
|
|
|
if (kdata->ctx == NULL
|
|
|
|
|| EVP_PKEY_derive_init(kdata->ctx) <= 0)
|
|
|
|
goto err;
|
|
|
|
|
2018-06-22 05:16:18 +08:00
|
|
|
t->data = kdata;
|
|
|
|
return 1;
|
2020-08-07 12:29:00 +08:00
|
|
|
err:
|
|
|
|
EVP_PKEY_CTX_free(kdata->ctx);
|
|
|
|
OPENSSL_free(kdata);
|
|
|
|
return 0;
|
2018-06-22 05:16:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void pkey_kdf_test_cleanup(EVP_TEST *t)
|
|
|
|
{
|
|
|
|
PKEY_KDF_DATA *kdata = t->data;
|
2019-08-21 16:52:04 +08:00
|
|
|
|
2018-06-22 05:16:18 +08:00
|
|
|
OPENSSL_free(kdata->output);
|
|
|
|
EVP_PKEY_CTX_free(kdata->ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int pkey_kdf_test_parse(EVP_TEST *t,
|
|
|
|
const char *keyword, const char *value)
|
|
|
|
{
|
|
|
|
PKEY_KDF_DATA *kdata = t->data;
|
|
|
|
|
|
|
|
if (strcmp(keyword, "Output") == 0)
|
|
|
|
return parse_bin(value, &kdata->output, &kdata->output_len);
|
2021-06-21 14:55:50 +08:00
|
|
|
if (HAS_PREFIX(keyword, "Ctrl"))
|
2018-06-22 05:16:18 +08:00
|
|
|
return pkey_test_ctrl(t, kdata->ctx, value);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int pkey_kdf_test_run(EVP_TEST *t)
|
|
|
|
{
|
2024-07-12 14:25:50 +08:00
|
|
|
int ret = 1;
|
2018-06-22 05:16:18 +08:00
|
|
|
PKEY_KDF_DATA *expected = t->data;
|
|
|
|
unsigned char *got = NULL;
|
2022-06-12 12:03:50 +08:00
|
|
|
size_t got_len = 0;
|
|
|
|
|
2022-09-13 06:49:05 +08:00
|
|
|
if (fips_provider_version_eq(libctx, 3, 0, 0)) {
|
2022-09-14 04:38:30 +08:00
|
|
|
/* FIPS(3.0.0): can't deal with oversized output buffers #18533 */
|
2022-06-12 12:03:50 +08:00
|
|
|
got_len = expected->output_len;
|
2022-09-13 06:49:05 +08:00
|
|
|
} else {
|
|
|
|
/* Find out the KDF output size */
|
|
|
|
if (EVP_PKEY_derive(expected->ctx, NULL, &got_len) <= 0) {
|
|
|
|
t->err = "INTERNAL_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We may get an absurd output size, which signals that anything goes.
|
|
|
|
* If not, we specify a too big buffer for the output, to test that
|
|
|
|
* EVP_PKEY_derive() can cope with it.
|
|
|
|
*/
|
|
|
|
if (got_len == SIZE_MAX || got_len == 0)
|
|
|
|
got_len = expected->output_len;
|
|
|
|
else
|
|
|
|
got_len = expected->output_len * 2;
|
|
|
|
}
|
2018-06-22 05:16:18 +08:00
|
|
|
|
2021-08-27 19:11:39 +08:00
|
|
|
if (!TEST_ptr(got = OPENSSL_malloc(got_len == 0 ? 1 : got_len))) {
|
2018-06-22 05:16:18 +08:00
|
|
|
t->err = "INTERNAL_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
if (EVP_PKEY_derive(expected->ctx, got, &got_len) <= 0) {
|
|
|
|
t->err = "KDF_DERIVE_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
2024-07-12 14:25:50 +08:00
|
|
|
if (!pkey_check_fips_approved(expected->ctx, t)) {
|
|
|
|
ret = 0;
|
|
|
|
goto err;
|
|
|
|
}
|
2018-06-22 05:16:18 +08:00
|
|
|
if (!TEST_mem_eq(expected->output, expected->output_len, got, got_len)) {
|
|
|
|
t->err = "KDF_MISMATCH";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
t->err = NULL;
|
|
|
|
|
|
|
|
err:
|
|
|
|
OPENSSL_free(got);
|
2024-07-12 14:25:50 +08:00
|
|
|
return ret;
|
2018-06-22 05:16:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static const EVP_TEST_METHOD pkey_kdf_test_method = {
|
|
|
|
"PKEYKDF",
|
|
|
|
pkey_kdf_test_init,
|
|
|
|
pkey_kdf_test_cleanup,
|
|
|
|
pkey_kdf_test_parse,
|
|
|
|
pkey_kdf_test_run
|
|
|
|
};
|
|
|
|
|
2017-05-13 02:19:51 +08:00
|
|
|
/**
|
2020-08-07 12:29:00 +08:00
|
|
|
** KEYPAIR TESTS
|
|
|
|
**/
|
2017-05-13 02:19:51 +08:00
|
|
|
|
|
|
|
typedef struct keypair_test_data_st {
|
2017-04-26 08:50:59 +08:00
|
|
|
EVP_PKEY *privk;
|
|
|
|
EVP_PKEY *pubk;
|
2017-04-27 03:33:43 +08:00
|
|
|
} KEYPAIR_TEST_DATA;
|
2017-04-26 08:50:59 +08:00
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static int keypair_test_init(EVP_TEST *t, const char *pair)
|
2017-04-26 08:50:59 +08:00
|
|
|
{
|
2017-05-13 02:19:51 +08:00
|
|
|
KEYPAIR_TEST_DATA *data;
|
2017-04-26 08:50:59 +08:00
|
|
|
int rv = 0;
|
|
|
|
EVP_PKEY *pk = NULL, *pubk = NULL;
|
|
|
|
char *pub, *priv = NULL;
|
|
|
|
|
2017-05-13 02:19:51 +08:00
|
|
|
/* Split private and public names. */
|
2017-04-27 03:33:43 +08:00
|
|
|
if (!TEST_ptr(priv = OPENSSL_strdup(pair))
|
|
|
|
|| !TEST_ptr(pub = strchr(priv, ':'))) {
|
|
|
|
t->err = "PARSING_ERROR";
|
2017-04-26 08:50:59 +08:00
|
|
|
goto end;
|
|
|
|
}
|
2017-05-13 02:19:51 +08:00
|
|
|
*pub++ = '\0';
|
2017-04-26 08:50:59 +08:00
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
if (!TEST_true(find_key(&pk, priv, private_keys))) {
|
2017-05-13 02:19:51 +08:00
|
|
|
TEST_info("Can't find private key: %s", priv);
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "MISSING_PRIVATE_KEY";
|
2017-04-26 08:50:59 +08:00
|
|
|
goto end;
|
|
|
|
}
|
2017-04-27 03:33:43 +08:00
|
|
|
if (!TEST_true(find_key(&pubk, pub, public_keys))) {
|
2017-05-13 02:19:51 +08:00
|
|
|
TEST_info("Can't find public key: %s", pub);
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "MISSING_PUBLIC_KEY";
|
2017-04-26 08:50:59 +08:00
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pk == NULL && pubk == NULL) {
|
|
|
|
/* Both keys are listed but unsupported: skip this test */
|
|
|
|
t->skip = 1;
|
|
|
|
rv = 1;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
if (!TEST_ptr(data = OPENSSL_malloc(sizeof(*data))))
|
2017-04-26 08:50:59 +08:00
|
|
|
goto end;
|
|
|
|
data->privk = pk;
|
|
|
|
data->pubk = pubk;
|
|
|
|
t->data = data;
|
|
|
|
rv = 1;
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = NULL;
|
2017-04-26 08:50:59 +08:00
|
|
|
|
2024-07-26 11:31:42 +08:00
|
|
|
end:
|
2017-04-27 03:33:43 +08:00
|
|
|
OPENSSL_free(priv);
|
2017-04-26 08:50:59 +08:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static void keypair_test_cleanup(EVP_TEST *t)
|
2017-04-26 08:50:59 +08:00
|
|
|
{
|
2017-04-27 03:33:43 +08:00
|
|
|
OPENSSL_free(t->data);
|
2017-04-26 08:50:59 +08:00
|
|
|
t->data = NULL;
|
|
|
|
}
|
|
|
|
|
2017-05-13 02:19:51 +08:00
|
|
|
/*
|
|
|
|
* For tests that do not accept any custom keywords.
|
2017-04-26 08:50:59 +08:00
|
|
|
*/
|
2017-04-27 03:33:43 +08:00
|
|
|
static int void_test_parse(EVP_TEST *t, const char *keyword, const char *value)
|
2017-04-26 08:50:59 +08:00
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static int keypair_test_run(EVP_TEST *t)
|
2017-04-26 08:50:59 +08:00
|
|
|
{
|
|
|
|
int rv = 0;
|
2017-04-27 03:33:43 +08:00
|
|
|
const KEYPAIR_TEST_DATA *pair = t->data;
|
2017-04-26 08:50:59 +08:00
|
|
|
|
|
|
|
if (pair->privk == NULL || pair->pubk == NULL) {
|
2017-04-27 03:33:43 +08:00
|
|
|
/*
|
|
|
|
* this can only happen if only one of the keys is not set
|
2017-04-26 08:50:59 +08:00
|
|
|
* which means that one of them was unsupported while the
|
|
|
|
* other isn't: hence a key type mismatch.
|
|
|
|
*/
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "KEYPAIR_TYPE_MISMATCH";
|
2017-04-26 08:50:59 +08:00
|
|
|
rv = 1;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
2021-10-26 15:16:18 +08:00
|
|
|
if ((rv = EVP_PKEY_eq(pair->privk, pair->pubk)) != 1) {
|
|
|
|
if (0 == rv) {
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "KEYPAIR_MISMATCH";
|
2021-10-26 15:16:18 +08:00
|
|
|
} else if (-1 == rv) {
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "KEYPAIR_TYPE_MISMATCH";
|
2021-10-26 15:16:18 +08:00
|
|
|
} else if (-2 == rv) {
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = "UNSUPPORTED_KEY_COMPARISON";
|
2017-04-26 08:50:59 +08:00
|
|
|
} else {
|
2017-04-27 03:33:43 +08:00
|
|
|
TEST_error("Unexpected error in key comparison");
|
2017-04-26 08:50:59 +08:00
|
|
|
rv = 0;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
rv = 1;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = 1;
|
2017-04-27 03:33:43 +08:00
|
|
|
t->err = NULL;
|
2017-04-26 08:50:59 +08:00
|
|
|
|
|
|
|
end:
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2017-04-27 03:33:43 +08:00
|
|
|
static const EVP_TEST_METHOD keypair_test_method = {
|
2017-04-26 08:50:59 +08:00
|
|
|
"PrivPubKeyPair",
|
|
|
|
keypair_test_init,
|
|
|
|
keypair_test_cleanup,
|
|
|
|
void_test_parse,
|
|
|
|
keypair_test_run
|
|
|
|
};
|
|
|
|
|
2017-07-17 07:15:58 +08:00
|
|
|
/**
|
2020-08-07 12:29:00 +08:00
|
|
|
** KEYGEN TEST
|
|
|
|
**/
|
2017-07-17 07:15:58 +08:00
|
|
|
|
|
|
|
typedef struct keygen_test_data_st {
|
|
|
|
char *keyname; /* Key name to store key or NULL */
|
2024-07-24 15:24:33 +08:00
|
|
|
char *paramname;
|
|
|
|
char *alg;
|
2025-01-17 12:07:47 +08:00
|
|
|
STACK_OF(OPENSSL_STRING) *in_controls; /* Collection of controls */
|
|
|
|
STACK_OF(OPENSSL_STRING) *out_controls;
|
2017-07-17 07:15:58 +08:00
|
|
|
} KEYGEN_TEST_DATA;
|
|
|
|
|
|
|
|
static int keygen_test_init(EVP_TEST *t, const char *alg)
|
|
|
|
{
|
|
|
|
KEYGEN_TEST_DATA *data;
|
|
|
|
|
2020-08-07 12:29:00 +08:00
|
|
|
if (is_pkey_disabled(alg)) {
|
2017-07-17 07:15:58 +08:00
|
|
|
t->skip = 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2024-11-13 21:18:13 +08:00
|
|
|
if (!TEST_ptr(data = OPENSSL_zalloc(sizeof(*data))))
|
2024-07-26 11:31:42 +08:00
|
|
|
return 0;
|
2017-07-17 07:15:58 +08:00
|
|
|
data->keyname = NULL;
|
2024-07-24 15:24:33 +08:00
|
|
|
data->paramname = NULL;
|
2025-01-17 12:07:47 +08:00
|
|
|
data->in_controls = sk_OPENSSL_STRING_new_null();
|
|
|
|
data->out_controls = sk_OPENSSL_STRING_new_null();
|
2024-07-26 11:31:42 +08:00
|
|
|
data->alg = OPENSSL_strdup(alg);
|
2017-07-17 07:15:58 +08:00
|
|
|
t->data = data;
|
|
|
|
t->err = NULL;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void keygen_test_cleanup(EVP_TEST *t)
|
|
|
|
{
|
|
|
|
KEYGEN_TEST_DATA *keygen = t->data;
|
|
|
|
|
2025-01-17 12:07:47 +08:00
|
|
|
ctrlfree(keygen->in_controls);
|
|
|
|
ctrlfree(keygen->out_controls);
|
2024-07-24 15:24:33 +08:00
|
|
|
OPENSSL_free(keygen->alg);
|
2017-07-17 07:15:58 +08:00
|
|
|
OPENSSL_free(keygen->keyname);
|
2024-07-26 11:31:42 +08:00
|
|
|
OPENSSL_free(keygen->paramname);
|
2017-07-17 07:15:58 +08:00
|
|
|
OPENSSL_free(t->data);
|
|
|
|
t->data = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int keygen_test_parse(EVP_TEST *t,
|
|
|
|
const char *keyword, const char *value)
|
|
|
|
{
|
|
|
|
KEYGEN_TEST_DATA *keygen = t->data;
|
|
|
|
|
|
|
|
if (strcmp(keyword, "KeyName") == 0)
|
|
|
|
return TEST_ptr(keygen->keyname = OPENSSL_strdup(value));
|
2024-07-24 15:24:33 +08:00
|
|
|
if (strcmp(keyword, "KeyParam") == 0)
|
|
|
|
return TEST_ptr(keygen->paramname = OPENSSL_strdup(value));
|
2017-07-17 07:15:58 +08:00
|
|
|
if (strcmp(keyword, "Ctrl") == 0)
|
2025-01-17 12:07:47 +08:00
|
|
|
return ctrladd(keygen->in_controls, value);
|
|
|
|
if (strcmp(keyword, "CtrlOut") == 0)
|
|
|
|
return ctrladd(keygen->out_controls, value);
|
2017-07-17 07:15:58 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2025-01-17 12:07:47 +08:00
|
|
|
/* Iterate thru the key's expected values */
|
|
|
|
static int check_pkey_expected_values(EVP_TEST *t, const EVP_PKEY *pkey,
|
|
|
|
STACK_OF(OPENSSL_STRING) *out_controls)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
OSSL_PARAM out_params[4], *p;
|
|
|
|
size_t out_params_n = 0, len;
|
|
|
|
|
|
|
|
if (sk_OPENSSL_STRING_num(out_controls) > 0) {
|
|
|
|
|
|
|
|
if (!ctrl2params(t, out_controls,
|
|
|
|
EVP_PKEY_gettable_params(pkey),
|
|
|
|
out_params, OSSL_NELEM(out_params), &out_params_n))
|
|
|
|
goto err;
|
|
|
|
for (p = out_params; p->key != NULL; ++p) {
|
|
|
|
if (p->data_type == OSSL_PARAM_OCTET_STRING) {
|
|
|
|
uint8_t *data = OPENSSL_malloc(p->data_size);
|
|
|
|
|
|
|
|
if (data == NULL)
|
|
|
|
goto err;
|
|
|
|
ret = EVP_PKEY_get_octet_string_param(pkey, p->key, data,
|
|
|
|
p->data_size, &len)
|
|
|
|
&& len == p->data_size
|
|
|
|
&& (TEST_mem_eq(p->data, len, data, len) == 1);
|
|
|
|
OPENSSL_free(data);
|
|
|
|
if (ret == 0) {
|
|
|
|
TEST_error("Expected %s value is incorrect", p->key);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ret = 1;
|
|
|
|
err:
|
|
|
|
ctrl2params_free(out_params, out_params_n, 0);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-07-17 07:15:58 +08:00
|
|
|
static int keygen_test_run(EVP_TEST *t)
|
|
|
|
{
|
|
|
|
KEYGEN_TEST_DATA *keygen = t->data;
|
2024-07-24 15:24:33 +08:00
|
|
|
EVP_PKEY *pkey = NULL, *keyparams = NULL;
|
|
|
|
EVP_PKEY_CTX *genctx = NULL; /* Keygen context to use */
|
2024-07-26 11:42:09 +08:00
|
|
|
int rv = 1;
|
2024-11-13 21:18:13 +08:00
|
|
|
OSSL_PARAM_BLD *bld = NULL;
|
|
|
|
OSSL_PARAM *params = NULL;
|
2025-02-18 07:51:48 +08:00
|
|
|
size_t params_n = 0;
|
|
|
|
int key_free = 1;
|
2024-07-24 15:24:33 +08:00
|
|
|
|
|
|
|
if (keygen->paramname != NULL) {
|
|
|
|
rv = find_key(&keyparams, keygen->paramname, public_keys);
|
|
|
|
if (rv == 0 || keyparams == NULL) {
|
|
|
|
TEST_info("skipping, key '%s' is disabled", keygen->paramname);
|
|
|
|
t->skip = 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (!TEST_ptr(genctx = EVP_PKEY_CTX_new_from_pkey(libctx, keyparams,
|
|
|
|
propquery)))
|
|
|
|
goto err;
|
2017-07-17 07:15:58 +08:00
|
|
|
|
2024-07-24 15:24:33 +08:00
|
|
|
} else {
|
|
|
|
if (!TEST_ptr(genctx = EVP_PKEY_CTX_new_from_name(libctx, keygen->alg,
|
|
|
|
propquery)))
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (EVP_PKEY_keygen_init(genctx) <= 0) {
|
|
|
|
t->err = "KEYGEN_INIT_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2025-01-17 12:07:47 +08:00
|
|
|
if (sk_OPENSSL_STRING_num(keygen->in_controls) > 0) {
|
2025-07-17 21:19:56 +08:00
|
|
|
if ((params = OPENSSL_malloc_array(4, sizeof(OSSL_PARAM))) == NULL)
|
2024-11-13 21:18:13 +08:00
|
|
|
goto err;
|
2025-01-17 12:07:47 +08:00
|
|
|
if (!ctrl2params(t, keygen->in_controls,
|
2024-07-26 11:31:42 +08:00
|
|
|
EVP_PKEY_CTX_settable_params(genctx),
|
2024-11-13 21:18:13 +08:00
|
|
|
params, 4, ¶ms_n))
|
2024-07-26 11:31:42 +08:00
|
|
|
goto err;
|
|
|
|
if (!EVP_PKEY_CTX_set_params(genctx, params)) {
|
|
|
|
t->err = "PKEY_CTRL_ERROR";
|
2024-07-24 15:24:33 +08:00
|
|
|
goto err;
|
2024-07-26 11:31:42 +08:00
|
|
|
}
|
2024-07-24 15:24:33 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (EVP_PKEY_keygen(genctx, &pkey) <= 0) {
|
2017-07-17 07:15:58 +08:00
|
|
|
t->err = "KEYGEN_GENERATE_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
2025-01-17 12:07:47 +08:00
|
|
|
|
2024-07-24 15:24:33 +08:00
|
|
|
if (!pkey_check_fips_approved(genctx, t)) {
|
|
|
|
rv = 0;
|
|
|
|
goto err;
|
|
|
|
}
|
2017-07-17 07:15:58 +08:00
|
|
|
|
2025-05-06 09:32:21 +08:00
|
|
|
if (!pkey_check_security_category(t, pkey))
|
|
|
|
goto err;
|
|
|
|
|
2020-08-07 12:29:00 +08:00
|
|
|
if (!evp_pkey_is_provided(pkey)) {
|
|
|
|
TEST_info("Warning: legacy key generated %s", keygen->keyname);
|
|
|
|
goto err;
|
|
|
|
}
|
2025-01-17 12:07:47 +08:00
|
|
|
|
|
|
|
if (!check_pkey_expected_values(t, pkey, keygen->out_controls)) {
|
|
|
|
t->err = "KEYGEN_PKEY_MISMATCH_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2017-07-17 07:15:58 +08:00
|
|
|
if (keygen->keyname != NULL) {
|
|
|
|
KEY_LIST *key;
|
|
|
|
|
2020-02-18 22:35:24 +08:00
|
|
|
rv = 0;
|
2017-07-17 07:15:58 +08:00
|
|
|
if (find_key(NULL, keygen->keyname, private_keys)) {
|
|
|
|
TEST_info("Duplicate key %s", keygen->keyname);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!TEST_ptr(key = OPENSSL_malloc(sizeof(*key))))
|
|
|
|
goto err;
|
|
|
|
key->name = keygen->keyname;
|
|
|
|
keygen->keyname = NULL;
|
|
|
|
key->key = pkey;
|
|
|
|
key->next = private_keys;
|
|
|
|
private_keys = key;
|
2020-02-18 22:35:24 +08:00
|
|
|
rv = 1;
|
2025-02-18 07:51:48 +08:00
|
|
|
key_free = 0;
|
2017-07-17 07:15:58 +08:00
|
|
|
}
|
|
|
|
|
2020-02-18 22:35:24 +08:00
|
|
|
t->err = NULL;
|
2024-11-13 21:18:13 +08:00
|
|
|
err:
|
2025-02-18 07:51:48 +08:00
|
|
|
if (key_free) {
|
|
|
|
EVP_PKEY_free(pkey);
|
|
|
|
pkey = NULL;
|
|
|
|
}
|
2024-07-24 15:24:33 +08:00
|
|
|
EVP_PKEY_CTX_free(genctx);
|
2024-11-13 21:18:13 +08:00
|
|
|
if (sk_OPENSSL_STRING_num(keygen->in_controls) > 0)
|
|
|
|
ctrl2params_free(params, params_n, 0);
|
|
|
|
OSSL_PARAM_free(params);
|
|
|
|
OSSL_PARAM_BLD_free(bld);
|
2020-02-18 22:35:24 +08:00
|
|
|
return rv;
|
2017-07-17 07:15:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static const EVP_TEST_METHOD keygen_test_method = {
|
|
|
|
"KeyGen",
|
|
|
|
keygen_test_init,
|
|
|
|
keygen_test_cleanup,
|
|
|
|
keygen_test_parse,
|
|
|
|
keygen_test_run,
|
|
|
|
};
|
2017-05-13 02:19:51 +08:00
|
|
|
|
|
|
|
/**
|
2020-08-07 12:29:00 +08:00
|
|
|
** DIGEST SIGN+VERIFY TESTS
|
|
|
|
**/
|
2017-05-13 02:19:51 +08:00
|
|
|
|
2017-05-13 07:44:02 +08:00
|
|
|
typedef struct {
|
2017-05-20 04:43:05 +08:00
|
|
|
int is_verify; /* Set to 1 if verifying */
|
|
|
|
int is_oneshot; /* Set to 1 for one shot operation */
|
|
|
|
const EVP_MD *md; /* Digest to use */
|
|
|
|
EVP_MD_CTX *ctx; /* Digest context */
|
2017-05-13 07:44:02 +08:00
|
|
|
EVP_PKEY_CTX *pctx;
|
2017-05-20 04:43:05 +08:00
|
|
|
STACK_OF(EVP_TEST_BUFFER) *input; /* Input data: streaming */
|
|
|
|
unsigned char *osin; /* Input data if one shot */
|
|
|
|
size_t osin_len; /* Input length data if one shot */
|
|
|
|
unsigned char *output; /* Expected output */
|
|
|
|
size_t output_len; /* Expected output length */
|
2024-07-03 09:12:39 +08:00
|
|
|
int deterministic_noncetype;
|
|
|
|
EVP_PKEY *key;
|
|
|
|
STACK_OF(OPENSSL_STRING) *init_controls; /* collection of controls */
|
|
|
|
STACK_OF(OPENSSL_STRING) *controls; /* Collection of controls */
|
2017-05-13 07:44:02 +08:00
|
|
|
} DIGESTSIGN_DATA;
|
|
|
|
|
2017-05-16 04:27:43 +08:00
|
|
|
static int digestsigver_test_init(EVP_TEST *t, const char *alg, int is_verify,
|
|
|
|
int is_oneshot)
|
2017-05-13 07:44:02 +08:00
|
|
|
{
|
|
|
|
const EVP_MD *md = NULL;
|
|
|
|
DIGESTSIGN_DATA *mdat;
|
|
|
|
|
|
|
|
if (strcmp(alg, "NULL") != 0) {
|
2020-08-07 12:29:00 +08:00
|
|
|
if (is_digest_disabled(alg)) {
|
|
|
|
t->skip = 1;
|
|
|
|
return 1;
|
2017-05-13 07:44:02 +08:00
|
|
|
}
|
2020-08-07 12:29:00 +08:00
|
|
|
md = EVP_get_digestbyname(alg);
|
|
|
|
if (md == NULL)
|
|
|
|
return 0;
|
2017-05-13 07:44:02 +08:00
|
|
|
}
|
|
|
|
if (!TEST_ptr(mdat = OPENSSL_zalloc(sizeof(*mdat))))
|
|
|
|
return 0;
|
2024-07-03 09:12:39 +08:00
|
|
|
mdat->init_controls = sk_OPENSSL_STRING_new_null();
|
|
|
|
mdat->controls = sk_OPENSSL_STRING_new_null();
|
2017-05-13 07:44:02 +08:00
|
|
|
mdat->md = md;
|
|
|
|
if (!TEST_ptr(mdat->ctx = EVP_MD_CTX_new())) {
|
|
|
|
OPENSSL_free(mdat);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
mdat->is_verify = is_verify;
|
2017-05-16 04:27:43 +08:00
|
|
|
mdat->is_oneshot = is_oneshot;
|
2017-05-13 07:44:02 +08:00
|
|
|
t->data = mdat;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int digestsign_test_init(EVP_TEST *t, const char *alg)
|
|
|
|
{
|
2017-05-16 04:27:43 +08:00
|
|
|
return digestsigver_test_init(t, alg, 0, 0);
|
2017-05-13 07:44:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void digestsigver_test_cleanup(EVP_TEST *t)
|
|
|
|
{
|
|
|
|
DIGESTSIGN_DATA *mdata = t->data;
|
|
|
|
|
2024-07-03 09:12:39 +08:00
|
|
|
ctrlfree(mdata->init_controls);
|
|
|
|
ctrlfree(mdata->controls);
|
2017-05-13 07:44:02 +08:00
|
|
|
EVP_MD_CTX_free(mdata->ctx);
|
|
|
|
sk_EVP_TEST_BUFFER_pop_free(mdata->input, evp_test_buffer_free);
|
2017-05-16 04:27:43 +08:00
|
|
|
OPENSSL_free(mdata->osin);
|
2017-05-13 07:44:02 +08:00
|
|
|
OPENSSL_free(mdata->output);
|
|
|
|
OPENSSL_free(mdata);
|
|
|
|
t->data = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int digestsigver_test_parse(EVP_TEST *t,
|
|
|
|
const char *keyword, const char *value)
|
|
|
|
{
|
|
|
|
DIGESTSIGN_DATA *mdata = t->data;
|
|
|
|
|
|
|
|
if (strcmp(keyword, "Key") == 0) {
|
|
|
|
EVP_PKEY *pkey = NULL;
|
|
|
|
int rv = 0;
|
|
|
|
|
|
|
|
if (mdata->is_verify)
|
|
|
|
rv = find_key(&pkey, value, public_keys);
|
|
|
|
if (rv == 0)
|
|
|
|
rv = find_key(&pkey, value, private_keys);
|
|
|
|
if (rv == 0 || pkey == NULL) {
|
|
|
|
t->skip = 1;
|
|
|
|
return 1;
|
|
|
|
}
|
2024-07-03 09:12:39 +08:00
|
|
|
mdata->key = pkey;
|
2017-05-13 07:44:02 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-05-16 04:27:43 +08:00
|
|
|
if (strcmp(keyword, "Input") == 0) {
|
|
|
|
if (mdata->is_oneshot)
|
2017-05-13 02:19:51 +08:00
|
|
|
return parse_bin(value, &mdata->osin, &mdata->osin_len);
|
2023-07-28 18:35:37 +08:00
|
|
|
return evp_test_buffer_append(value, data_chunk_size, &mdata->input);
|
2017-05-16 04:27:43 +08:00
|
|
|
}
|
2017-05-13 07:44:02 +08:00
|
|
|
if (strcmp(keyword, "Output") == 0)
|
2017-05-13 02:19:51 +08:00
|
|
|
return parse_bin(value, &mdata->output, &mdata->output_len);
|
2017-05-16 04:27:43 +08:00
|
|
|
|
2023-07-28 18:35:37 +08:00
|
|
|
if (!mdata->is_oneshot && data_chunk_size == 0) {
|
2017-05-16 04:27:43 +08:00
|
|
|
if (strcmp(keyword, "Count") == 0)
|
|
|
|
return evp_test_buffer_set_count(value, mdata->input);
|
|
|
|
if (strcmp(keyword, "Ncopy") == 0)
|
|
|
|
return evp_test_buffer_ncopy(value, mdata->input);
|
|
|
|
}
|
2024-07-03 09:12:39 +08:00
|
|
|
if (strcmp(keyword, "Ctrl") == 0)
|
|
|
|
return pkey_add_control(t, mdata->controls, value);
|
|
|
|
if (strcmp(keyword, "CtrlInit") == 0)
|
|
|
|
return ctrladd(mdata->init_controls, value);
|
2022-07-15 19:22:01 +08:00
|
|
|
if (strcmp(keyword, "NonceType") == 0) {
|
2024-07-03 09:12:39 +08:00
|
|
|
if (strcmp(value, "deterministic") == 0)
|
|
|
|
mdata->deterministic_noncetype = 1;
|
2022-07-15 19:22:01 +08:00
|
|
|
return 1;
|
|
|
|
}
|
2017-05-13 07:44:02 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2024-07-03 09:12:39 +08:00
|
|
|
static int check_deterministic_noncetype(EVP_TEST *t,
|
|
|
|
DIGESTSIGN_DATA *mdata)
|
|
|
|
{
|
|
|
|
if (mdata->deterministic_noncetype == 1) {
|
|
|
|
OSSL_PARAM params[2];
|
|
|
|
unsigned int nonce_type = 1;
|
|
|
|
|
|
|
|
params[0] =
|
|
|
|
OSSL_PARAM_construct_uint(OSSL_SIGNATURE_PARAM_NONCE_TYPE,
|
|
|
|
&nonce_type);
|
|
|
|
params[1] = OSSL_PARAM_construct_end();
|
|
|
|
if (!EVP_PKEY_CTX_set_params(mdata->pctx, params))
|
|
|
|
t->err = "EVP_PKEY_CTX_set_params_ERROR";
|
|
|
|
else if (!EVP_PKEY_CTX_get_params(mdata->pctx, params))
|
|
|
|
t->err = "EVP_PKEY_CTX_get_params_ERROR";
|
|
|
|
else if (!OSSL_PARAM_modified(¶ms[0]))
|
|
|
|
t->err = "nonce_type_not_modified_ERROR";
|
|
|
|
else if (nonce_type != 1)
|
|
|
|
t->err = "nonce_type_value_ERROR";
|
|
|
|
}
|
|
|
|
return t->err == NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int signverify_init(EVP_TEST *t, DIGESTSIGN_DATA *data)
|
|
|
|
{
|
|
|
|
const char *name = data->md == NULL ? NULL : EVP_MD_get0_name(data->md);
|
2024-07-04 09:59:43 +08:00
|
|
|
OSSL_PARAM params[5];
|
2024-07-03 09:12:39 +08:00
|
|
|
OSSL_PARAM *p = NULL;
|
|
|
|
int i, ret = 0;
|
|
|
|
size_t params_n = 0, params_allocated_n = 0;
|
|
|
|
|
|
|
|
if (sk_OPENSSL_STRING_num(data->init_controls) > 0) {
|
|
|
|
if (!ctrl2params(t, data->init_controls,
|
|
|
|
NULL,
|
|
|
|
params, OSSL_NELEM(params), ¶ms_n))
|
|
|
|
goto err;
|
|
|
|
p = params;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (data->is_verify) {
|
|
|
|
if (!EVP_DigestVerifyInit_ex(data->ctx, &data->pctx, name, libctx,
|
|
|
|
NULL, data->key, p)) {
|
|
|
|
t->err = "DIGESTVERIFYINIT_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!EVP_DigestSignInit_ex(data->ctx, &data->pctx, name, libctx, NULL,
|
|
|
|
data->key, p)) {
|
|
|
|
t->err = "DIGESTSIGNINIT_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < sk_OPENSSL_STRING_num(data->controls); i++) {
|
|
|
|
char *value = sk_OPENSSL_STRING_value(data->controls, i);
|
|
|
|
|
|
|
|
if (!pkey_test_ctrl(t, data->pctx, value) || t->err != NULL)
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
ret = 1;
|
|
|
|
err:
|
|
|
|
ctrl2params_free(params, params_n, params_allocated_n);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-05-13 07:44:02 +08:00
|
|
|
static int digestsign_update_fn(void *ctx, const unsigned char *buf,
|
|
|
|
size_t buflen)
|
|
|
|
{
|
|
|
|
return EVP_DigestSignUpdate(ctx, buf, buflen);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int digestsign_test_run(EVP_TEST *t)
|
|
|
|
{
|
2024-07-03 09:12:39 +08:00
|
|
|
int i;
|
2017-05-25 19:48:32 +08:00
|
|
|
DIGESTSIGN_DATA *expected = t->data;
|
|
|
|
unsigned char *got = NULL;
|
|
|
|
size_t got_len;
|
2017-05-13 07:44:02 +08:00
|
|
|
|
2024-07-03 09:12:39 +08:00
|
|
|
if (!signverify_init(t, expected))
|
|
|
|
goto err;
|
|
|
|
if (!check_deterministic_noncetype(t, expected))
|
|
|
|
goto err;
|
|
|
|
|
2025-05-06 09:32:21 +08:00
|
|
|
if (!pkey_check_security_category(t, expected->key))
|
|
|
|
goto err;
|
|
|
|
|
2024-07-03 09:12:39 +08:00
|
|
|
for (i = 0; i < sk_OPENSSL_STRING_num(expected->controls); i++) {
|
|
|
|
char *value = sk_OPENSSL_STRING_value(expected->controls, i);
|
|
|
|
if (!pkey_test_ctrl(t, expected->pctx, value) || t->err != NULL)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-05-25 19:48:32 +08:00
|
|
|
if (!evp_test_buffer_do(expected->input, digestsign_update_fn,
|
|
|
|
expected->ctx)) {
|
2017-05-13 07:44:02 +08:00
|
|
|
t->err = "DIGESTUPDATE_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2017-05-25 19:48:32 +08:00
|
|
|
if (!EVP_DigestSignFinal(expected->ctx, NULL, &got_len)) {
|
2017-05-13 07:44:02 +08:00
|
|
|
t->err = "DIGESTSIGNFINAL_LENGTH_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
2017-05-25 19:48:32 +08:00
|
|
|
if (!TEST_ptr(got = OPENSSL_malloc(got_len))) {
|
2017-05-13 07:44:02 +08:00
|
|
|
t->err = "MALLOC_FAILURE";
|
|
|
|
goto err;
|
|
|
|
}
|
2022-08-02 04:08:27 +08:00
|
|
|
got_len *= 2;
|
2017-05-25 19:48:32 +08:00
|
|
|
if (!EVP_DigestSignFinal(expected->ctx, got, &got_len)) {
|
2017-05-13 07:44:02 +08:00
|
|
|
t->err = "DIGESTSIGNFINAL_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
2018-08-09 07:27:42 +08:00
|
|
|
if (!memory_err_compare(t, "SIGNATURE_MISMATCH",
|
|
|
|
expected->output, expected->output_len,
|
|
|
|
got, got_len))
|
2017-05-13 07:44:02 +08:00
|
|
|
goto err;
|
|
|
|
|
2018-08-09 07:27:42 +08:00
|
|
|
t->err = NULL;
|
2017-05-13 07:44:02 +08:00
|
|
|
err:
|
2017-05-25 19:48:32 +08:00
|
|
|
OPENSSL_free(got);
|
2017-05-13 07:44:02 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const EVP_TEST_METHOD digestsign_test_method = {
|
|
|
|
"DigestSign",
|
|
|
|
digestsign_test_init,
|
|
|
|
digestsigver_test_cleanup,
|
|
|
|
digestsigver_test_parse,
|
|
|
|
digestsign_test_run
|
|
|
|
};
|
|
|
|
|
|
|
|
static int digestverify_test_init(EVP_TEST *t, const char *alg)
|
|
|
|
{
|
2017-05-16 04:27:43 +08:00
|
|
|
return digestsigver_test_init(t, alg, 1, 0);
|
2017-05-13 07:44:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int digestverify_update_fn(void *ctx, const unsigned char *buf,
|
|
|
|
size_t buflen)
|
|
|
|
{
|
|
|
|
return EVP_DigestVerifyUpdate(ctx, buf, buflen);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int digestverify_test_run(EVP_TEST *t)
|
|
|
|
{
|
|
|
|
DIGESTSIGN_DATA *mdata = t->data;
|
|
|
|
|
2024-07-03 09:12:39 +08:00
|
|
|
if (!signverify_init(t, mdata))
|
|
|
|
return 1;
|
|
|
|
|
2017-05-13 07:44:02 +08:00
|
|
|
if (!evp_test_buffer_do(mdata->input, digestverify_update_fn, mdata->ctx)) {
|
|
|
|
t->err = "DIGESTUPDATE_ERROR";
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (EVP_DigestVerifyFinal(mdata->ctx, mdata->output,
|
|
|
|
mdata->output_len) <= 0)
|
|
|
|
t->err = "VERIFY_ERROR";
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const EVP_TEST_METHOD digestverify_test_method = {
|
|
|
|
"DigestVerify",
|
|
|
|
digestverify_test_init,
|
|
|
|
digestsigver_test_cleanup,
|
|
|
|
digestsigver_test_parse,
|
|
|
|
digestverify_test_run
|
|
|
|
};
|
|
|
|
|
2017-05-16 04:27:43 +08:00
|
|
|
static int oneshot_digestsign_test_init(EVP_TEST *t, const char *alg)
|
|
|
|
{
|
|
|
|
return digestsigver_test_init(t, alg, 0, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int oneshot_digestsign_test_run(EVP_TEST *t)
|
|
|
|
{
|
2017-05-25 19:48:32 +08:00
|
|
|
DIGESTSIGN_DATA *expected = t->data;
|
|
|
|
unsigned char *got = NULL;
|
|
|
|
size_t got_len;
|
2017-05-16 04:27:43 +08:00
|
|
|
|
2024-07-03 09:12:39 +08:00
|
|
|
if (!signverify_init(t, expected))
|
|
|
|
goto err;
|
|
|
|
|
2017-05-25 19:48:32 +08:00
|
|
|
if (!EVP_DigestSign(expected->ctx, NULL, &got_len,
|
|
|
|
expected->osin, expected->osin_len)) {
|
2017-05-16 04:27:43 +08:00
|
|
|
t->err = "DIGESTSIGN_LENGTH_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
2017-05-25 19:48:32 +08:00
|
|
|
if (!TEST_ptr(got = OPENSSL_malloc(got_len))) {
|
2017-05-16 04:27:43 +08:00
|
|
|
t->err = "MALLOC_FAILURE";
|
|
|
|
goto err;
|
|
|
|
}
|
2022-08-02 04:08:27 +08:00
|
|
|
got_len *= 2;
|
2017-05-25 19:48:32 +08:00
|
|
|
if (!EVP_DigestSign(expected->ctx, got, &got_len,
|
|
|
|
expected->osin, expected->osin_len)) {
|
2017-05-16 04:27:43 +08:00
|
|
|
t->err = "DIGESTSIGN_ERROR";
|
|
|
|
goto err;
|
|
|
|
}
|
2018-08-09 07:27:42 +08:00
|
|
|
if (!memory_err_compare(t, "SIGNATURE_MISMATCH",
|
|
|
|
expected->output, expected->output_len,
|
|
|
|
got, got_len))
|
2017-05-16 04:27:43 +08:00
|
|
|
goto err;
|
|
|
|
|
2018-08-09 07:27:42 +08:00
|
|
|
t->err = NULL;
|
2017-05-16 04:27:43 +08:00
|
|
|
err:
|
2017-05-25 19:48:32 +08:00
|
|
|
OPENSSL_free(got);
|
2017-05-16 04:27:43 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const EVP_TEST_METHOD oneshot_digestsign_test_method = {
|
|
|
|
"OneShotDigestSign",
|
|
|
|
oneshot_digestsign_test_init,
|
|
|
|
digestsigver_test_cleanup,
|
|
|
|
digestsigver_test_parse,
|
|
|
|
oneshot_digestsign_test_run
|
|
|
|
};
|
|
|
|
|
|
|
|
static int oneshot_digestverify_test_init(EVP_TEST *t, const char *alg)
|
|
|
|
{
|
|
|
|
return digestsigver_test_init(t, alg, 1, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int oneshot_digestverify_test_run(EVP_TEST *t)
|
|
|
|
{
|
|
|
|
DIGESTSIGN_DATA *mdata = t->data;
|
|
|
|
|
2024-07-03 09:12:39 +08:00
|
|
|
if (!signverify_init(t, mdata))
|
|
|
|
return 1;
|
|
|
|
|
2017-05-16 04:27:43 +08:00
|
|
|
if (EVP_DigestVerify(mdata->ctx, mdata->output, mdata->output_len,
|
|
|
|
mdata->osin, mdata->osin_len) <= 0)
|
|
|
|
t->err = "VERIFY_ERROR";
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const EVP_TEST_METHOD oneshot_digestverify_test_method = {
|
|
|
|
"OneShotDigestVerify",
|
|
|
|
oneshot_digestverify_test_init,
|
|
|
|
digestsigver_test_cleanup,
|
|
|
|
digestsigver_test_parse,
|
|
|
|
oneshot_digestverify_test_run
|
|
|
|
};
|
|
|
|
|
2017-05-13 02:19:51 +08:00
|
|
|
|
|
|
|
/**
|
2020-08-07 12:29:00 +08:00
|
|
|
** PARSING AND DISPATCH
|
|
|
|
**/
|
2017-05-13 02:19:51 +08:00
|
|
|
|
|
|
|
static const EVP_TEST_METHOD *evp_test_list[] = {
|
2020-06-05 11:47:55 +08:00
|
|
|
&rand_test_method,
|
2017-05-13 02:19:51 +08:00
|
|
|
&cipher_test_method,
|
|
|
|
&digest_test_method,
|
|
|
|
&digestsign_test_method,
|
|
|
|
&digestverify_test_method,
|
|
|
|
&encode_test_method,
|
|
|
|
&kdf_test_method,
|
2018-06-22 05:16:18 +08:00
|
|
|
&pkey_kdf_test_method,
|
2017-05-13 02:19:51 +08:00
|
|
|
&keypair_test_method,
|
2017-07-17 07:15:58 +08:00
|
|
|
&keygen_test_method,
|
2017-05-13 02:19:51 +08:00
|
|
|
&mac_test_method,
|
|
|
|
&oneshot_digestsign_test_method,
|
|
|
|
&oneshot_digestverify_test_method,
|
|
|
|
&pbe_test_method,
|
|
|
|
&pdecrypt_test_method,
|
|
|
|
&pderive_test_method,
|
|
|
|
&psign_test_method,
|
2024-07-11 03:26:30 +08:00
|
|
|
&psign_message_test_method,
|
2017-05-13 02:19:51 +08:00
|
|
|
&pverify_recover_test_method,
|
|
|
|
&pverify_test_method,
|
2024-07-11 03:26:30 +08:00
|
|
|
&pverify_message_test_method,
|
2025-01-17 12:07:47 +08:00
|
|
|
&pverify_message_public_test_method,
|
2024-07-03 09:12:39 +08:00
|
|
|
&pkey_kem_test_method,
|
2025-02-25 07:06:26 +08:00
|
|
|
&pkey_fromdata_test_method,
|
2017-05-13 02:19:51 +08:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const EVP_TEST_METHOD *find_test(const char *name)
|
|
|
|
{
|
|
|
|
const EVP_TEST_METHOD **tt;
|
|
|
|
|
|
|
|
for (tt = evp_test_list; *tt; tt++) {
|
|
|
|
if (strcmp(name, (*tt)->name) == 0)
|
|
|
|
return *tt;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void clear_test(EVP_TEST *t)
|
|
|
|
{
|
2017-06-06 01:32:05 +08:00
|
|
|
test_clearstanza(&t->s);
|
2017-05-13 02:19:51 +08:00
|
|
|
ERR_clear_error();
|
|
|
|
if (t->data != NULL) {
|
|
|
|
if (t->meth != NULL)
|
|
|
|
t->meth->cleanup(t);
|
|
|
|
OPENSSL_free(t->data);
|
|
|
|
t->data = NULL;
|
|
|
|
}
|
|
|
|
OPENSSL_free(t->expected_err);
|
|
|
|
t->expected_err = NULL;
|
|
|
|
OPENSSL_free(t->reason);
|
|
|
|
t->reason = NULL;
|
2025-07-09 10:50:02 +08:00
|
|
|
OPENSSL_free(t->entropy);
|
|
|
|
t->entropy = NULL;
|
|
|
|
t->entropy_len = 0;
|
2017-06-06 01:32:05 +08:00
|
|
|
|
2017-05-13 02:19:51 +08:00
|
|
|
/* Text literal. */
|
|
|
|
t->err = NULL;
|
|
|
|
t->skip = 0;
|
|
|
|
t->meth = NULL;
|
2024-07-03 09:12:39 +08:00
|
|
|
t->expect_unapproved = 0;
|
2025-05-06 09:32:21 +08:00
|
|
|
t->security_category = -1;
|
2022-07-21 01:07:46 +08:00
|
|
|
|
|
|
|
#if !defined(OPENSSL_NO_DEFAULT_THREAD_POOL)
|
|
|
|
OSSL_set_max_threads(libctx, 0);
|
|
|
|
#endif
|
2017-05-13 02:19:51 +08:00
|
|
|
}
|
|
|
|
|
2020-08-07 12:29:00 +08:00
|
|
|
/* Check for errors in the test structure; return 1 if okay, else 0. */
|
2017-05-13 02:19:51 +08:00
|
|
|
static int check_test_error(EVP_TEST *t)
|
|
|
|
{
|
|
|
|
unsigned long err;
|
|
|
|
const char *reason;
|
|
|
|
|
|
|
|
if (t->err == NULL && t->expected_err == NULL)
|
|
|
|
return 1;
|
|
|
|
if (t->err != NULL && t->expected_err == NULL) {
|
|
|
|
if (t->aux_err != NULL) {
|
2017-06-06 01:32:05 +08:00
|
|
|
TEST_info("%s:%d: Source of above error (%s); unexpected error %s",
|
|
|
|
t->s.test_file, t->s.start, t->aux_err, t->err);
|
2017-05-13 02:19:51 +08:00
|
|
|
} else {
|
2017-06-06 01:32:05 +08:00
|
|
|
TEST_info("%s:%d: Source of above error; unexpected error %s",
|
|
|
|
t->s.test_file, t->s.start, t->err);
|
2017-05-13 02:19:51 +08:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (t->err == NULL && t->expected_err != NULL) {
|
2017-06-06 01:32:05 +08:00
|
|
|
TEST_info("%s:%d: Succeeded but was expecting %s",
|
|
|
|
t->s.test_file, t->s.start, t->expected_err);
|
2017-05-13 02:19:51 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strcmp(t->err, t->expected_err) != 0) {
|
2017-06-06 01:32:05 +08:00
|
|
|
TEST_info("%s:%d: Expected %s got %s",
|
|
|
|
t->s.test_file, t->s.start, t->expected_err, t->err);
|
2017-05-13 02:19:51 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-06-01 01:52:45 +08:00
|
|
|
if (t->reason == NULL)
|
2017-05-13 02:19:51 +08:00
|
|
|
return 1;
|
|
|
|
|
2019-06-01 01:52:45 +08:00
|
|
|
if (t->reason == NULL) {
|
2017-06-06 01:32:05 +08:00
|
|
|
TEST_info("%s:%d: Test is missing function or reason code",
|
|
|
|
t->s.test_file, t->s.start);
|
2017-05-13 02:19:51 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = ERR_peek_error();
|
|
|
|
if (err == 0) {
|
2019-06-01 01:52:45 +08:00
|
|
|
TEST_info("%s:%d: Expected error \"%s\" not set",
|
|
|
|
t->s.test_file, t->s.start, t->reason);
|
2017-05-13 02:19:51 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
reason = ERR_reason_error_string(err);
|
2019-09-05 04:04:08 +08:00
|
|
|
if (reason == NULL) {
|
2019-06-01 01:52:45 +08:00
|
|
|
TEST_info("%s:%d: Expected error \"%s\", no strings available."
|
2017-06-06 01:32:05 +08:00
|
|
|
" Assuming ok.",
|
2019-06-01 01:52:45 +08:00
|
|
|
t->s.test_file, t->s.start, t->reason);
|
2017-05-13 02:19:51 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2019-06-01 01:52:45 +08:00
|
|
|
if (strcmp(reason, t->reason) == 0)
|
2017-05-13 02:19:51 +08:00
|
|
|
return 1;
|
|
|
|
|
2019-06-01 01:52:45 +08:00
|
|
|
TEST_info("%s:%d: Expected error \"%s\", got \"%s\"",
|
|
|
|
t->s.test_file, t->s.start, t->reason, reason);
|
2017-05-13 02:19:51 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-08-07 12:29:00 +08:00
|
|
|
/* Run a parsed test. Log a message and return 0 on error. */
|
2017-05-13 02:19:51 +08:00
|
|
|
static int run_test(EVP_TEST *t)
|
|
|
|
{
|
2025-07-09 10:50:02 +08:00
|
|
|
int res = 0;
|
|
|
|
|
2017-05-13 02:19:51 +08:00
|
|
|
if (t->meth == NULL)
|
|
|
|
return 1;
|
2017-06-06 01:32:05 +08:00
|
|
|
t->s.numtests++;
|
2017-05-13 02:19:51 +08:00
|
|
|
if (t->skip) {
|
2017-06-06 01:32:05 +08:00
|
|
|
t->s.numskip++;
|
2017-05-13 02:19:51 +08:00
|
|
|
} else {
|
2025-07-09 10:50:02 +08:00
|
|
|
if (t->entropy != NULL) {
|
|
|
|
fake_rand_bytes = t->entropy;
|
|
|
|
fake_rand_bytes_offset = 0;
|
|
|
|
fake_rand_size = t->entropy_len;
|
|
|
|
fake_rand_set_public_private_callbacks(libctx, &get_faked_bytes);
|
|
|
|
}
|
2017-05-13 02:19:51 +08:00
|
|
|
/* run the test */
|
|
|
|
if (t->err == NULL && t->meth->run_test(t) != 1) {
|
2017-06-06 01:32:05 +08:00
|
|
|
TEST_info("%s:%d %s error",
|
|
|
|
t->s.test_file, t->s.start, t->meth->name);
|
2025-07-09 10:50:02 +08:00
|
|
|
goto err;
|
2017-05-13 02:19:51 +08:00
|
|
|
}
|
|
|
|
if (!check_test_error(t)) {
|
2017-06-19 09:21:22 +08:00
|
|
|
TEST_openssl_errors();
|
2017-06-06 01:32:05 +08:00
|
|
|
t->s.errors++;
|
2017-05-13 02:19:51 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-07-09 10:50:02 +08:00
|
|
|
res = 1;
|
|
|
|
err:
|
2017-05-13 02:19:51 +08:00
|
|
|
/* clean it up */
|
2025-07-09 10:50:02 +08:00
|
|
|
if (fake_rand_bytes != NULL) {
|
|
|
|
fake_rand_set_public_private_callbacks(libctx, NULL);
|
|
|
|
fake_rand_bytes = NULL;
|
|
|
|
fake_rand_bytes_offset = 0;
|
|
|
|
fake_rand_size = 0;
|
|
|
|
}
|
|
|
|
return res;
|
2017-05-13 02:19:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int find_key(EVP_PKEY **ppk, const char *name, KEY_LIST *lst)
|
|
|
|
{
|
|
|
|
for (; lst != NULL; lst = lst->next) {
|
|
|
|
if (strcmp(lst->name, name) == 0) {
|
|
|
|
if (ppk != NULL)
|
|
|
|
*ppk = lst->key;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void free_key_list(KEY_LIST *lst)
|
|
|
|
{
|
|
|
|
while (lst != NULL) {
|
|
|
|
KEY_LIST *next = lst->next;
|
|
|
|
|
|
|
|
EVP_PKEY_free(lst->key);
|
|
|
|
OPENSSL_free(lst->name);
|
|
|
|
OPENSSL_free(lst);
|
|
|
|
lst = next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Is the key type an unsupported algorithm?
|
|
|
|
*/
|
2018-05-09 23:09:50 +08:00
|
|
|
static int key_unsupported(void)
|
2017-05-13 02:19:51 +08:00
|
|
|
{
|
2020-08-30 02:38:25 +08:00
|
|
|
long err = ERR_peek_last_error();
|
2021-04-16 16:08:38 +08:00
|
|
|
int lib = ERR_GET_LIB(err);
|
|
|
|
long reason = ERR_GET_REASON(err);
|
2017-05-13 02:19:51 +08:00
|
|
|
|
2021-04-16 16:08:38 +08:00
|
|
|
if ((lib == ERR_LIB_EVP && reason == EVP_R_UNSUPPORTED_ALGORITHM)
|
2021-06-07 21:54:24 +08:00
|
|
|
|| (lib == ERR_LIB_EVP && reason == EVP_R_DECODE_ERROR)
|
2021-04-16 16:08:38 +08:00
|
|
|
|| reason == ERR_R_UNSUPPORTED) {
|
2017-05-13 02:19:51 +08:00
|
|
|
ERR_clear_error();
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
#ifndef OPENSSL_NO_EC
|
|
|
|
/*
|
|
|
|
* If EC support is enabled we should catch also EC_R_UNKNOWN_GROUP as an
|
|
|
|
* hint to an unsupported algorithm/curve (e.g. if binary EC support is
|
|
|
|
* disabled).
|
|
|
|
*/
|
2021-04-16 16:08:38 +08:00
|
|
|
if (lib == ERR_LIB_EC
|
|
|
|
&& (reason == EC_R_UNKNOWN_GROUP
|
|
|
|
|| reason == EC_R_INVALID_CURVE)) {
|
2017-05-13 02:19:51 +08:00
|
|
|
ERR_clear_error();
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
#endif /* OPENSSL_NO_EC */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-08-07 12:29:00 +08:00
|
|
|
/* NULL out the value from |pp| but return it. This "steals" a pointer. */
|
2017-06-06 01:32:05 +08:00
|
|
|
static char *take_value(PAIR *pp)
|
2017-05-13 02:19:51 +08:00
|
|
|
{
|
2017-06-06 01:32:05 +08:00
|
|
|
char *p = pp->value;
|
|
|
|
|
|
|
|
pp->value = NULL;
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2020-11-12 15:57:12 +08:00
|
|
|
#if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS)
|
2020-09-05 11:08:27 +08:00
|
|
|
static int securitycheck_enabled(void)
|
|
|
|
{
|
|
|
|
static int enabled = -1;
|
|
|
|
|
|
|
|
if (enabled == -1) {
|
|
|
|
if (OSSL_PROVIDER_available(libctx, "fips")) {
|
|
|
|
OSSL_PARAM params[2];
|
|
|
|
OSSL_PROVIDER *prov = NULL;
|
|
|
|
int check = 1;
|
|
|
|
|
|
|
|
prov = OSSL_PROVIDER_load(libctx, "fips");
|
|
|
|
if (prov != NULL) {
|
|
|
|
params[0] =
|
|
|
|
OSSL_PARAM_construct_int(OSSL_PROV_PARAM_SECURITY_CHECKS,
|
|
|
|
&check);
|
|
|
|
params[1] = OSSL_PARAM_construct_end();
|
|
|
|
OSSL_PROVIDER_get_params(prov, params);
|
|
|
|
OSSL_PROVIDER_unload(prov);
|
|
|
|
}
|
|
|
|
enabled = check;
|
|
|
|
return enabled;
|
|
|
|
}
|
|
|
|
enabled = 0;
|
|
|
|
}
|
|
|
|
return enabled;
|
|
|
|
}
|
2020-11-12 15:57:12 +08:00
|
|
|
#endif
|
2020-09-05 11:08:27 +08:00
|
|
|
|
2019-07-17 17:34:14 +08:00
|
|
|
/*
|
|
|
|
* Return 1 if one of the providers named in the string is available.
|
|
|
|
* The provider names are separated with whitespace.
|
|
|
|
* NOTE: destructive function, it inserts '\0' after each provider name.
|
|
|
|
*/
|
|
|
|
static int prov_available(char *providers)
|
|
|
|
{
|
|
|
|
char *p;
|
|
|
|
int more = 1;
|
|
|
|
|
|
|
|
while (more) {
|
2023-06-08 14:05:42 +08:00
|
|
|
for (; isspace((unsigned char)(*providers)); providers++)
|
2019-07-17 17:34:14 +08:00
|
|
|
continue;
|
|
|
|
if (*providers == '\0')
|
|
|
|
break; /* End of the road */
|
2023-06-08 14:05:42 +08:00
|
|
|
for (p = providers; *p != '\0' && !isspace((unsigned char)(*p)); p++)
|
2019-07-17 17:34:14 +08:00
|
|
|
continue;
|
|
|
|
if (*p == '\0')
|
|
|
|
more = 0;
|
|
|
|
else
|
|
|
|
*p = '\0';
|
2020-08-07 12:29:00 +08:00
|
|
|
if (OSSL_PROVIDER_available(libctx, providers))
|
2019-07-17 17:34:14 +08:00
|
|
|
return 1; /* Found one */
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-08-07 12:29:00 +08:00
|
|
|
/* Read and parse one test. Return 0 if failure, 1 if okay. */
|
2017-06-06 01:32:05 +08:00
|
|
|
static int parse(EVP_TEST *t)
|
|
|
|
{
|
|
|
|
KEY_LIST *key, **klist;
|
2017-05-13 02:19:51 +08:00
|
|
|
EVP_PKEY *pkey;
|
2017-06-06 01:32:05 +08:00
|
|
|
PAIR *pp;
|
2022-09-13 06:49:05 +08:00
|
|
|
int i, j, skipped = 0;
|
2017-05-13 02:19:51 +08:00
|
|
|
|
2024-07-03 09:12:39 +08:00
|
|
|
fips_indicator_callback_unapproved_count = 0;
|
2017-05-13 02:19:51 +08:00
|
|
|
top:
|
2017-06-06 01:32:05 +08:00
|
|
|
do {
|
|
|
|
if (BIO_eof(t->s.fp))
|
2017-05-13 02:19:51 +08:00
|
|
|
return EOF;
|
2017-06-06 01:32:05 +08:00
|
|
|
clear_test(t);
|
|
|
|
if (!test_readstanza(&t->s))
|
|
|
|
return 0;
|
|
|
|
} while (t->s.numpairs == 0);
|
|
|
|
pp = &t->s.pairs[0];
|
2017-05-13 02:19:51 +08:00
|
|
|
|
2017-06-06 01:32:05 +08:00
|
|
|
/* Are we adding a key? */
|
2017-05-13 02:19:51 +08:00
|
|
|
klist = NULL;
|
|
|
|
pkey = NULL;
|
2020-08-07 12:29:00 +08:00
|
|
|
start:
|
2017-06-06 01:32:05 +08:00
|
|
|
if (strcmp(pp->key, "PrivateKey") == 0) {
|
2020-08-07 12:29:00 +08:00
|
|
|
pkey = PEM_read_bio_PrivateKey_ex(t->s.key, NULL, 0, NULL, libctx, NULL);
|
2017-05-13 02:19:51 +08:00
|
|
|
if (pkey == NULL && !key_unsupported()) {
|
2018-03-20 00:17:58 +08:00
|
|
|
EVP_PKEY_free(pkey);
|
2017-06-06 01:32:05 +08:00
|
|
|
TEST_info("Can't read private key %s", pp->value);
|
2017-06-19 09:21:22 +08:00
|
|
|
TEST_openssl_errors();
|
2017-05-13 02:19:51 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
klist = &private_keys;
|
2017-12-02 01:57:42 +08:00
|
|
|
} else if (strcmp(pp->key, "PublicKey") == 0) {
|
2020-08-19 03:45:19 +08:00
|
|
|
pkey = PEM_read_bio_PUBKEY_ex(t->s.key, NULL, 0, NULL, libctx, NULL);
|
2017-05-13 02:19:51 +08:00
|
|
|
if (pkey == NULL && !key_unsupported()) {
|
2018-03-20 00:17:58 +08:00
|
|
|
EVP_PKEY_free(pkey);
|
2017-06-06 01:32:05 +08:00
|
|
|
TEST_info("Can't read public key %s", pp->value);
|
2017-06-19 09:21:22 +08:00
|
|
|
TEST_openssl_errors();
|
2024-07-24 15:24:33 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
klist = &public_keys;
|
|
|
|
} else if (strcmp(pp->key, "ParamKey") == 0) {
|
|
|
|
pkey = PEM_read_bio_Parameters_ex(t->s.key, NULL, libctx, NULL);
|
|
|
|
if (pkey == NULL && !key_unsupported()) {
|
|
|
|
EVP_PKEY_free(pkey);
|
|
|
|
TEST_info("Can't read params key %s", pp->value);
|
|
|
|
TEST_openssl_errors();
|
2017-05-13 02:19:51 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
klist = &public_keys;
|
2017-12-02 01:57:42 +08:00
|
|
|
} else if (strcmp(pp->key, "PrivateKeyRaw") == 0
|
2021-10-26 15:16:18 +08:00
|
|
|
|| strcmp(pp->key, "PublicKeyRaw") == 0) {
|
2017-12-02 01:57:42 +08:00
|
|
|
char *strnid = NULL, *keydata = NULL;
|
|
|
|
unsigned char *keybin;
|
|
|
|
size_t keylen;
|
|
|
|
|
|
|
|
if (strcmp(pp->key, "PrivateKeyRaw") == 0)
|
|
|
|
klist = &private_keys;
|
|
|
|
else
|
|
|
|
klist = &public_keys;
|
|
|
|
|
|
|
|
strnid = strchr(pp->value, ':');
|
|
|
|
if (strnid != NULL) {
|
|
|
|
*strnid++ = '\0';
|
|
|
|
keydata = strchr(strnid, ':');
|
|
|
|
if (keydata != NULL)
|
|
|
|
*keydata++ = '\0';
|
|
|
|
}
|
|
|
|
if (keydata == NULL) {
|
|
|
|
TEST_info("Failed to parse %s value", pp->key);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!parse_bin(keydata, &keybin, &keylen)) {
|
|
|
|
TEST_info("Failed to create binary key");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (klist == &private_keys)
|
2020-09-24 17:42:23 +08:00
|
|
|
pkey = EVP_PKEY_new_raw_private_key_ex(libctx, strnid, NULL, keybin,
|
|
|
|
keylen);
|
2017-12-02 01:57:42 +08:00
|
|
|
else
|
2020-09-24 17:42:23 +08:00
|
|
|
pkey = EVP_PKEY_new_raw_public_key_ex(libctx, strnid, NULL, keybin,
|
|
|
|
keylen);
|
2018-03-19 18:22:46 +08:00
|
|
|
if (pkey == NULL && !key_unsupported()) {
|
2017-12-02 01:57:42 +08:00
|
|
|
TEST_info("Can't read %s data", pp->key);
|
|
|
|
OPENSSL_free(keybin);
|
|
|
|
TEST_openssl_errors();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
OPENSSL_free(keybin);
|
2020-08-07 12:29:00 +08:00
|
|
|
} else if (strcmp(pp->key, "Availablein") == 0) {
|
|
|
|
if (!prov_available(pp->value)) {
|
|
|
|
TEST_info("skipping, '%s' provider not available: %s:%d",
|
|
|
|
pp->value, t->s.test_file, t->s.start);
|
|
|
|
t->skip = 1;
|
|
|
|
return 0;
|
|
|
|
}
|
2022-09-13 06:49:05 +08:00
|
|
|
skipped++;
|
|
|
|
pp++;
|
|
|
|
goto start;
|
|
|
|
} else if (strcmp(pp->key, "FIPSversion") == 0) {
|
|
|
|
if (prov_available("fips")) {
|
2022-09-14 04:38:30 +08:00
|
|
|
j = fips_provider_version_match(libctx, pp->value);
|
2022-09-13 06:49:05 +08:00
|
|
|
if (j < 0) {
|
|
|
|
TEST_info("Line %d: error matching FIPS versions\n", t->s.curr);
|
|
|
|
return 0;
|
|
|
|
} else if (j == 0) {
|
|
|
|
TEST_info("skipping, FIPS provider incompatible version: %s:%d",
|
|
|
|
t->s.test_file, t->s.start);
|
|
|
|
t->skip = 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
skipped++;
|
2020-08-07 12:29:00 +08:00
|
|
|
pp++;
|
|
|
|
goto start;
|
2017-05-13 02:19:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* If we have a key add to list */
|
|
|
|
if (klist != NULL) {
|
2017-06-06 01:32:05 +08:00
|
|
|
if (find_key(NULL, pp->value, *klist)) {
|
|
|
|
TEST_info("Duplicate key %s", pp->value);
|
2017-05-13 02:19:51 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2017-06-06 01:32:05 +08:00
|
|
|
if (!TEST_ptr(key = OPENSSL_malloc(sizeof(*key))))
|
2017-05-13 02:19:51 +08:00
|
|
|
return 0;
|
2017-06-06 01:32:05 +08:00
|
|
|
key->name = take_value(pp);
|
2017-05-13 02:19:51 +08:00
|
|
|
key->key = pkey;
|
|
|
|
key->next = *klist;
|
|
|
|
*klist = key;
|
|
|
|
|
|
|
|
/* Go back and start a new stanza. */
|
2022-09-13 06:49:05 +08:00
|
|
|
if ((t->s.numpairs - skipped) != 1)
|
2017-06-06 01:32:05 +08:00
|
|
|
TEST_info("Line %d: missing blank line\n", t->s.curr);
|
2017-05-13 02:19:51 +08:00
|
|
|
goto top;
|
|
|
|
}
|
|
|
|
|
2017-06-06 01:32:05 +08:00
|
|
|
/* Find the test, based on first keyword. */
|
|
|
|
if (!TEST_ptr(t->meth = find_test(pp->key)))
|
|
|
|
return 0;
|
|
|
|
if (!t->meth->init(t, pp->value)) {
|
|
|
|
TEST_error("unknown %s: %s\n", pp->key, pp->value);
|
|
|
|
return 0;
|
2017-05-13 02:19:51 +08:00
|
|
|
}
|
|
|
|
if (t->skip == 1) {
|
2017-06-06 01:32:05 +08:00
|
|
|
/* TEST_info("skipping %s %s", pp->key, pp->value); */
|
|
|
|
return 0;
|
2017-05-13 02:19:51 +08:00
|
|
|
}
|
|
|
|
|
2022-09-13 06:49:05 +08:00
|
|
|
for (pp++, i = 1; i < (t->s.numpairs - skipped); pp++, i++) {
|
2020-09-04 15:55:28 +08:00
|
|
|
if (strcmp(pp->key, "Securitycheck") == 0) {
|
|
|
|
#if defined(OPENSSL_NO_FIPS_SECURITYCHECKS)
|
2020-09-05 11:08:27 +08:00
|
|
|
#else
|
|
|
|
if (!securitycheck_enabled())
|
2020-09-04 15:55:28 +08:00
|
|
|
#endif
|
2020-09-05 11:08:27 +08:00
|
|
|
{
|
|
|
|
TEST_info("skipping, Securitycheck is disabled: %s:%d",
|
|
|
|
t->s.test_file, t->s.start);
|
|
|
|
t->skip = 1;
|
|
|
|
return 0;
|
|
|
|
}
|
2020-09-04 15:55:28 +08:00
|
|
|
} else if (strcmp(pp->key, "Availablein") == 0) {
|
2020-08-07 12:29:00 +08:00
|
|
|
TEST_info("Line %d: 'Availablein' should be the first option",
|
|
|
|
t->s.curr);
|
|
|
|
return 0;
|
2019-07-31 01:36:53 +08:00
|
|
|
} else if (strcmp(pp->key, "Result") == 0) {
|
2017-05-13 02:19:51 +08:00
|
|
|
if (t->expected_err != NULL) {
|
2017-06-06 01:32:05 +08:00
|
|
|
TEST_info("Line %d: multiple result lines", t->s.curr);
|
|
|
|
return 0;
|
2017-05-13 02:19:51 +08:00
|
|
|
}
|
2017-06-06 01:32:05 +08:00
|
|
|
t->expected_err = take_value(pp);
|
|
|
|
} else if (strcmp(pp->key, "Function") == 0) {
|
2019-06-01 01:52:45 +08:00
|
|
|
/* Ignore old line. */
|
2017-06-06 01:32:05 +08:00
|
|
|
} else if (strcmp(pp->key, "Reason") == 0) {
|
2017-05-13 02:19:51 +08:00
|
|
|
if (t->reason != NULL) {
|
2017-06-06 01:32:05 +08:00
|
|
|
TEST_info("Line %d: multiple reason lines", t->s.curr);
|
|
|
|
return 0;
|
2017-05-13 02:19:51 +08:00
|
|
|
}
|
2017-06-06 01:32:05 +08:00
|
|
|
t->reason = take_value(pp);
|
2022-07-21 01:07:46 +08:00
|
|
|
} else if (strcmp(pp->key, "Threads") == 0) {
|
|
|
|
if (OSSL_set_max_threads(libctx, atoi(pp->value)) == 0) {
|
|
|
|
TEST_info("skipping, '%s' threads not available: %s:%d",
|
|
|
|
pp->value, t->s.test_file, t->s.start);
|
|
|
|
t->skip = 1;
|
|
|
|
}
|
2024-07-03 09:12:39 +08:00
|
|
|
} else if (strcmp(pp->key, "Unapproved") == 0) {
|
|
|
|
t->expect_unapproved = 1;
|
2025-02-14 06:43:54 +08:00
|
|
|
} else if (strcmp(pp->key, "Extended-Test") == 0) {
|
|
|
|
if (!extended_tests) {
|
|
|
|
TEST_info("skipping extended test: %s:%d",
|
|
|
|
t->s.test_file, t->s.start);
|
|
|
|
t->skip = 1;
|
|
|
|
}
|
2025-05-06 09:32:21 +08:00
|
|
|
} else if (strcmp(pp->key, "Security-Category") == 0) {
|
|
|
|
if (t->security_category >= 0) {
|
|
|
|
TEST_info("Line %d: multiple security category lines", t->s.curr);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
t->security_category = atoi(pp->value);
|
|
|
|
if (t->security_category < 0 || t->security_category > 5) {
|
|
|
|
TEST_info("Line %d: invalid security category, should be 0..5",
|
|
|
|
t->s.curr);
|
|
|
|
return 0;
|
|
|
|
}
|
2025-07-09 10:50:02 +08:00
|
|
|
} else if (strcmp(pp->key, "Test-Entropy") == 0) {
|
|
|
|
if (!parse_bin(pp->value, &t->entropy, &t->entropy_len)) {
|
|
|
|
TEST_info("Line %d: invalid entropy", t->s.curr);
|
|
|
|
return 0;
|
|
|
|
}
|
2017-05-13 02:19:51 +08:00
|
|
|
} else {
|
|
|
|
/* Must be test specific line: try to parse it */
|
2017-06-06 01:32:05 +08:00
|
|
|
int rv = t->meth->parse(t, pp->key, pp->value);
|
2017-05-13 02:19:51 +08:00
|
|
|
|
|
|
|
if (rv == 0) {
|
2017-06-06 01:32:05 +08:00
|
|
|
TEST_info("Line %d: unknown keyword %s", t->s.curr, pp->key);
|
|
|
|
return 0;
|
2017-05-13 02:19:51 +08:00
|
|
|
}
|
|
|
|
if (rv < 0) {
|
2018-10-26 19:42:40 +08:00
|
|
|
TEST_info("Line %d: error processing keyword %s = %s\n",
|
|
|
|
t->s.curr, pp->key, pp->value);
|
2017-06-06 01:32:05 +08:00
|
|
|
return 0;
|
2017-05-13 02:19:51 +08:00
|
|
|
}
|
2022-07-19 12:17:52 +08:00
|
|
|
if (t->skip)
|
|
|
|
return 0;
|
2017-05-13 02:19:51 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-06-06 01:32:05 +08:00
|
|
|
static int run_file_tests(int i)
|
2017-04-27 03:33:43 +08:00
|
|
|
{
|
2017-06-06 01:32:05 +08:00
|
|
|
EVP_TEST *t;
|
2017-07-18 09:48:27 +08:00
|
|
|
const char *testfile = test_get_argument(i);
|
2017-05-13 02:19:51 +08:00
|
|
|
int c;
|
2017-04-27 03:33:43 +08:00
|
|
|
|
2017-06-06 01:32:05 +08:00
|
|
|
if (!TEST_ptr(t = OPENSSL_zalloc(sizeof(*t))))
|
2017-04-27 03:33:43 +08:00
|
|
|
return 0;
|
2017-07-18 09:48:27 +08:00
|
|
|
if (!test_start_file(&t->s, testfile)) {
|
2017-06-06 01:32:05 +08:00
|
|
|
OPENSSL_free(t);
|
|
|
|
return 0;
|
|
|
|
}
|
2017-05-13 02:19:51 +08:00
|
|
|
|
2024-07-03 09:12:39 +08:00
|
|
|
OSSL_INDICATOR_set_callback(libctx, fips_indicator_cb);
|
2017-06-06 01:32:05 +08:00
|
|
|
while (!BIO_eof(t->s.fp)) {
|
|
|
|
c = parse(t);
|
2019-04-11 18:27:59 +08:00
|
|
|
if (t->skip) {
|
|
|
|
t->s.numskip++;
|
2017-05-13 02:19:51 +08:00
|
|
|
continue;
|
2019-04-11 18:27:59 +08:00
|
|
|
}
|
2017-06-06 01:32:05 +08:00
|
|
|
if (c == 0 || !run_test(t)) {
|
|
|
|
t->s.errors++;
|
2017-05-13 02:19:51 +08:00
|
|
|
break;
|
|
|
|
}
|
2017-04-27 03:33:43 +08:00
|
|
|
}
|
2017-06-06 01:32:05 +08:00
|
|
|
test_end_file(&t->s);
|
|
|
|
clear_test(t);
|
2017-04-27 03:33:43 +08:00
|
|
|
|
|
|
|
free_key_list(public_keys);
|
2025-04-17 22:50:36 +08:00
|
|
|
public_keys = NULL;
|
2017-04-27 03:33:43 +08:00
|
|
|
free_key_list(private_keys);
|
2025-04-17 22:50:36 +08:00
|
|
|
private_keys = NULL;
|
2017-06-06 01:32:05 +08:00
|
|
|
BIO_free(t->s.key);
|
|
|
|
c = t->s.errors;
|
|
|
|
OPENSSL_free(t);
|
|
|
|
return c == 0;
|
2017-04-27 03:33:43 +08:00
|
|
|
}
|
|
|
|
|
2020-08-07 12:29:00 +08:00
|
|
|
const OPTIONS *test_get_options(void)
|
|
|
|
{
|
|
|
|
static const OPTIONS test_options[] = {
|
|
|
|
OPT_TEST_OPTIONS_WITH_EXTRA_USAGE("[file...]\n"),
|
|
|
|
{ "config", OPT_CONFIG_FILE, '<',
|
|
|
|
"The configuration file to use for the libctx" },
|
2023-07-13 23:07:00 +08:00
|
|
|
{ "process", OPT_IN_PLACE, 's',
|
|
|
|
"Mode for data processing by cipher tests [in_place/both], both by default"},
|
2023-09-12 21:24:21 +08:00
|
|
|
{ "provider", OPT_PROVIDER_NAME, 's',
|
|
|
|
"The provider to load (when no configuration file, the default value is 'default')" },
|
2023-09-08 17:44:27 +08:00
|
|
|
{ "propquery", OPT_PROV_PROPQUERY, 's',
|
|
|
|
"Property query used when fetching algorithms" },
|
2023-07-27 18:03:47 +08:00
|
|
|
{ "chunk", OPT_DATA_CHUNK, 'N', "Size of data chunks to be processed, 0 for default size"},
|
2021-04-03 20:05:09 +08:00
|
|
|
{ OPT_HELP_STR, 1, '-', "file\tFile to run tests on.\n" },
|
2020-08-07 12:29:00 +08:00
|
|
|
{ NULL }
|
|
|
|
};
|
|
|
|
return test_options;
|
|
|
|
}
|
2018-08-16 10:36:01 +08:00
|
|
|
|
2017-07-18 09:48:27 +08:00
|
|
|
int setup_tests(void)
|
2017-04-27 03:33:43 +08:00
|
|
|
{
|
2020-01-30 23:30:17 +08:00
|
|
|
size_t n;
|
2020-08-07 12:29:00 +08:00
|
|
|
char *config_file = NULL;
|
2023-09-12 21:24:21 +08:00
|
|
|
char *provider_name = NULL;
|
2020-08-07 12:29:00 +08:00
|
|
|
|
|
|
|
OPTION_CHOICE o;
|
|
|
|
|
2025-02-14 06:43:54 +08:00
|
|
|
extended_tests = getenv("EVP_TEST_EXTENDED") != NULL;
|
|
|
|
|
2020-08-07 12:29:00 +08:00
|
|
|
while ((o = opt_next()) != OPT_EOF) {
|
|
|
|
switch (o) {
|
|
|
|
case OPT_CONFIG_FILE:
|
|
|
|
config_file = opt_arg();
|
|
|
|
break;
|
2023-07-13 23:07:00 +08:00
|
|
|
case OPT_IN_PLACE:
|
|
|
|
if ((process_mode_in_place = evp_test_process_mode(opt_arg())) == -1)
|
2023-07-27 18:03:47 +08:00
|
|
|
case OPT_DATA_CHUNK:
|
|
|
|
if (!opt_int(opt_arg(), &data_chunk_size))
|
2023-07-13 23:07:00 +08:00
|
|
|
return 0;
|
|
|
|
break;
|
2023-09-12 21:24:21 +08:00
|
|
|
case OPT_PROVIDER_NAME:
|
|
|
|
provider_name = opt_arg();
|
|
|
|
break;
|
2023-09-08 17:44:27 +08:00
|
|
|
case OPT_PROV_PROPQUERY:
|
|
|
|
propquery = opt_arg();
|
|
|
|
break;
|
2020-08-07 12:29:00 +08:00
|
|
|
case OPT_TEST_CASES:
|
2023-07-13 23:07:00 +08:00
|
|
|
break;
|
2020-08-07 12:29:00 +08:00
|
|
|
default:
|
|
|
|
case OPT_ERR:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2020-09-26 21:21:48 +08:00
|
|
|
* Load the provider via configuration into the created library context.
|
2020-08-07 12:29:00 +08:00
|
|
|
* Load the 'null' provider into the default library context to ensure that
|
2021-03-04 11:54:40 +08:00
|
|
|
* the tests do not fallback to using the default provider.
|
2020-08-07 12:29:00 +08:00
|
|
|
*/
|
2023-09-12 21:24:21 +08:00
|
|
|
if (config_file == NULL && provider_name == NULL)
|
|
|
|
provider_name = "default";
|
|
|
|
if (!test_get_libctx(&libctx, &prov_null, config_file, &libprov, provider_name))
|
2020-08-07 12:29:00 +08:00
|
|
|
return 0;
|
2020-01-30 23:30:17 +08:00
|
|
|
|
|
|
|
n = test_get_argument_count();
|
2018-08-16 10:36:01 +08:00
|
|
|
if (n == 0)
|
2017-04-27 03:33:43 +08:00
|
|
|
return 0;
|
|
|
|
|
2025-07-09 10:50:02 +08:00
|
|
|
if ((fake_rand = fake_rand_start(libctx)) == NULL)
|
|
|
|
return 0;
|
|
|
|
|
2025-06-18 17:59:04 +08:00
|
|
|
ADD_ALL_TESTS(run_file_tests, (int)n);
|
2017-07-18 09:48:27 +08:00
|
|
|
return 1;
|
2017-04-27 03:33:43 +08:00
|
|
|
}
|
2020-08-07 12:29:00 +08:00
|
|
|
|
|
|
|
void cleanup_tests(void)
|
|
|
|
{
|
2025-07-09 10:50:02 +08:00
|
|
|
fake_rand_finish(fake_rand);
|
2023-09-12 21:24:21 +08:00
|
|
|
OSSL_PROVIDER_unload(libprov);
|
2020-08-07 12:29:00 +08:00
|
|
|
OSSL_PROVIDER_unload(prov_null);
|
2020-10-15 17:55:50 +08:00
|
|
|
OSSL_LIB_CTX_free(libctx);
|
2020-08-07 12:29:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int is_digest_disabled(const char *name)
|
|
|
|
{
|
|
|
|
#ifdef OPENSSL_NO_BLAKE2
|
2021-06-24 16:29:37 +08:00
|
|
|
if (HAS_CASE_PREFIX(name, "BLAKE"))
|
2020-08-07 12:29:00 +08:00
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
#ifdef OPENSSL_NO_MD2
|
2022-04-12 18:30:08 +08:00
|
|
|
if (OPENSSL_strcasecmp(name, "MD2") == 0)
|
2020-08-07 12:29:00 +08:00
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
#ifdef OPENSSL_NO_MDC2
|
2022-04-12 18:30:08 +08:00
|
|
|
if (OPENSSL_strcasecmp(name, "MDC2") == 0)
|
2020-08-07 12:29:00 +08:00
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
#ifdef OPENSSL_NO_MD4
|
2022-04-12 18:30:08 +08:00
|
|
|
if (OPENSSL_strcasecmp(name, "MD4") == 0)
|
2020-08-07 12:29:00 +08:00
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
#ifdef OPENSSL_NO_MD5
|
2022-04-12 18:30:08 +08:00
|
|
|
if (OPENSSL_strcasecmp(name, "MD5") == 0)
|
2020-08-07 12:29:00 +08:00
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
#ifdef OPENSSL_NO_RMD160
|
2022-04-12 18:30:08 +08:00
|
|
|
if (OPENSSL_strcasecmp(name, "RIPEMD160") == 0)
|
2020-08-07 12:29:00 +08:00
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
#ifdef OPENSSL_NO_SM3
|
2022-04-12 18:30:08 +08:00
|
|
|
if (OPENSSL_strcasecmp(name, "SM3") == 0)
|
2020-08-07 12:29:00 +08:00
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
#ifdef OPENSSL_NO_WHIRLPOOL
|
2022-04-12 18:30:08 +08:00
|
|
|
if (OPENSSL_strcasecmp(name, "WHIRLPOOL") == 0)
|
2020-08-07 12:29:00 +08:00
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int is_pkey_disabled(const char *name)
|
|
|
|
{
|
|
|
|
#ifdef OPENSSL_NO_EC
|
2021-06-24 16:29:37 +08:00
|
|
|
if (HAS_CASE_PREFIX(name, "EC"))
|
2020-08-07 12:29:00 +08:00
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
#ifdef OPENSSL_NO_DH
|
2021-06-24 16:29:37 +08:00
|
|
|
if (HAS_CASE_PREFIX(name, "DH"))
|
2020-08-07 12:29:00 +08:00
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
#ifdef OPENSSL_NO_DSA
|
2021-06-24 16:29:37 +08:00
|
|
|
if (HAS_CASE_PREFIX(name, "DSA"))
|
2020-08-07 12:29:00 +08:00
|
|
|
return 1;
|
2024-07-26 11:31:42 +08:00
|
|
|
#endif
|
|
|
|
#ifdef OPENSSL_NO_SM2
|
|
|
|
if (HAS_CASE_PREFIX(name, "SM2"))
|
|
|
|
return 1;
|
2020-08-07 12:29:00 +08:00
|
|
|
#endif
|
2024-07-11 03:26:30 +08:00
|
|
|
|
|
|
|
/* For sigalgs we use, we also check for digest suffixes */
|
|
|
|
#ifdef OPENSSL_NO_RMD160
|
|
|
|
if (HAS_CASE_SUFFIX(name, "-RIPEMD160"))
|
|
|
|
return 1;
|
2024-08-19 14:38:56 +08:00
|
|
|
#endif
|
|
|
|
#ifdef OPENSSL_NO_SM3
|
|
|
|
if (HAS_CASE_SUFFIX(name, "-SM3"))
|
|
|
|
return 1;
|
2025-02-25 07:06:26 +08:00
|
|
|
#endif
|
|
|
|
#ifdef OPENSSL_NO_ML_DSA
|
|
|
|
if (HAS_CASE_PREFIX(name, "ML-DSA"))
|
|
|
|
return 1;
|
2024-07-11 03:26:30 +08:00
|
|
|
#endif
|
2020-08-07 12:29:00 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int is_mac_disabled(const char *name)
|
|
|
|
{
|
|
|
|
#ifdef OPENSSL_NO_BLAKE2
|
2021-06-24 16:29:37 +08:00
|
|
|
if (HAS_CASE_PREFIX(name, "BLAKE2BMAC")
|
|
|
|
|| HAS_CASE_PREFIX(name, "BLAKE2SMAC"))
|
2020-08-07 12:29:00 +08:00
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
#ifdef OPENSSL_NO_CMAC
|
2021-06-24 16:29:37 +08:00
|
|
|
if (HAS_CASE_PREFIX(name, "CMAC"))
|
2020-08-07 12:29:00 +08:00
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
#ifdef OPENSSL_NO_POLY1305
|
2021-06-24 16:29:37 +08:00
|
|
|
if (HAS_CASE_PREFIX(name, "Poly1305"))
|
2020-08-07 12:29:00 +08:00
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
#ifdef OPENSSL_NO_SIPHASH
|
2021-06-24 16:29:37 +08:00
|
|
|
if (HAS_CASE_PREFIX(name, "SipHash"))
|
2020-08-07 12:29:00 +08:00
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
static int is_kdf_disabled(const char *name)
|
|
|
|
{
|
|
|
|
#ifdef OPENSSL_NO_SCRYPT
|
2021-06-24 16:29:37 +08:00
|
|
|
if (HAS_CASE_SUFFIX(name, "SCRYPT"))
|
2020-08-07 12:29:00 +08:00
|
|
|
return 1;
|
2021-09-28 04:45:38 +08:00
|
|
|
#endif
|
|
|
|
#ifdef OPENSSL_NO_ARGON2
|
|
|
|
if (HAS_CASE_SUFFIX(name, "ARGON2"))
|
|
|
|
return 1;
|
2020-08-07 12:29:00 +08:00
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int is_cipher_disabled(const char *name)
|
|
|
|
{
|
|
|
|
#ifdef OPENSSL_NO_ARIA
|
2021-06-24 16:29:37 +08:00
|
|
|
if (HAS_CASE_PREFIX(name, "ARIA"))
|
2020-08-07 12:29:00 +08:00
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
#ifdef OPENSSL_NO_BF
|
2021-06-24 16:29:37 +08:00
|
|
|
if (HAS_CASE_PREFIX(name, "BF"))
|
2020-08-07 12:29:00 +08:00
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
#ifdef OPENSSL_NO_CAMELLIA
|
2021-06-24 16:29:37 +08:00
|
|
|
if (HAS_CASE_PREFIX(name, "CAMELLIA"))
|
2020-08-07 12:29:00 +08:00
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
#ifdef OPENSSL_NO_CAST
|
2021-06-24 16:29:37 +08:00
|
|
|
if (HAS_CASE_PREFIX(name, "CAST"))
|
2020-08-07 12:29:00 +08:00
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
#ifdef OPENSSL_NO_CHACHA
|
2021-06-24 16:29:37 +08:00
|
|
|
if (HAS_CASE_PREFIX(name, "CHACHA"))
|
2020-08-07 12:29:00 +08:00
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
#ifdef OPENSSL_NO_POLY1305
|
2021-06-24 16:29:37 +08:00
|
|
|
if (HAS_CASE_SUFFIX(name, "Poly1305"))
|
2020-08-07 12:29:00 +08:00
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
#ifdef OPENSSL_NO_DES
|
2021-06-24 16:29:37 +08:00
|
|
|
if (HAS_CASE_PREFIX(name, "DES"))
|
2020-08-07 12:29:00 +08:00
|
|
|
return 1;
|
2021-06-24 16:29:37 +08:00
|
|
|
if (HAS_CASE_SUFFIX(name, "3DESwrap"))
|
2020-11-16 10:42:18 +08:00
|
|
|
return 1;
|
2020-08-07 12:29:00 +08:00
|
|
|
#endif
|
|
|
|
#ifdef OPENSSL_NO_OCB
|
2021-06-24 16:29:37 +08:00
|
|
|
if (HAS_CASE_SUFFIX(name, "OCB"))
|
2020-08-07 12:29:00 +08:00
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
#ifdef OPENSSL_NO_IDEA
|
2021-06-24 16:29:37 +08:00
|
|
|
if (HAS_CASE_PREFIX(name, "IDEA"))
|
2020-08-07 12:29:00 +08:00
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
#ifdef OPENSSL_NO_RC2
|
2021-06-24 16:29:37 +08:00
|
|
|
if (HAS_CASE_PREFIX(name, "RC2"))
|
2020-08-07 12:29:00 +08:00
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
#ifdef OPENSSL_NO_RC4
|
2021-06-24 16:29:37 +08:00
|
|
|
if (HAS_CASE_PREFIX(name, "RC4"))
|
2020-08-07 12:29:00 +08:00
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
#ifdef OPENSSL_NO_RC5
|
2021-06-24 16:29:37 +08:00
|
|
|
if (HAS_CASE_PREFIX(name, "RC5"))
|
2020-08-07 12:29:00 +08:00
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
#ifdef OPENSSL_NO_SEED
|
2021-06-24 16:29:37 +08:00
|
|
|
if (HAS_CASE_PREFIX(name, "SEED"))
|
2020-08-07 12:29:00 +08:00
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
#ifdef OPENSSL_NO_SIV
|
2021-06-24 16:29:37 +08:00
|
|
|
if (HAS_CASE_SUFFIX(name, "SIV"))
|
2020-08-07 12:29:00 +08:00
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
#ifdef OPENSSL_NO_SM4
|
2021-06-24 16:29:37 +08:00
|
|
|
if (HAS_CASE_PREFIX(name, "SM4"))
|
2020-08-07 12:29:00 +08:00
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|