mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
Since OpenSSL 3.1 a new RSA-PSS salt length constant exists to select
the maximum possible salt length based on the RSA-PSS parameters and the
digest used: OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO_DIGEST_MAX
This is the default salt length when no other salt length is set by
the caller.
In contrast to OSSL_PKEY_RSA_PSS_SALT_LEN_MAX, OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO_DIGEST_MAX
also ensures that the resulting salt length is not larger than the used
digest size. The salt length calculated with OSSL_PKEY_RSA_PSS_SALT_LEN_MAX
may be larger than the digest size, dependent on the RSA-PSS parameters.
FIPS 186-4 section 5 "The RSA Digital Signature Algorithm", subsection
5.5 "PKCS #1" says: "For RSASSA-PSS […] the length (in bytes) of the
salt (sLen) shall satisfy 0 <= sLen <= hLen, where hLen is the length of
the hash function output block (in bytes)."
See OpenSSL commit 6c73ca4a2f
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Signed-off-by: Steffen Eiden <seiden@linux.ibm.com>
5376 lines
151 KiB
C
5376 lines
151 KiB
C
/*
|
|
* libseckey - Secure key library
|
|
*
|
|
* Copyright IBM Corp. 2021
|
|
*
|
|
* s390-tools is free software; you can redistribute it and/or modify
|
|
* it under the terms of the MIT license. See LICENSE for details.
|
|
*/
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <err.h>
|
|
#include <stdbool.h>
|
|
#include <stdarg.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/time.h>
|
|
|
|
#include <openssl/evp.h>
|
|
#include <openssl/pem.h>
|
|
#include <openssl/sha.h>
|
|
#include <openssl/bn.h>
|
|
#include <openssl/ec.h>
|
|
#include <openssl/rsa.h>
|
|
#include <openssl/x509v3.h>
|
|
|
|
#include "lib/zt_common.h"
|
|
|
|
#include "libseckey/sk_openssl.h"
|
|
#include "libseckey/sk_utilities.h"
|
|
|
|
/*
|
|
* This source file is only used with OpenSSL >= 3.0
|
|
*/
|
|
#if OPENSSL_VERSION_PREREQ(3, 0)
|
|
|
|
#include <openssl/provider.h>
|
|
#include <openssl/core.h>
|
|
#include <openssl/core_dispatch.h>
|
|
#include <openssl/core_names.h>
|
|
#include <openssl/params.h>
|
|
#include "openssl/param_build.h"
|
|
#include <openssl/decoder.h>
|
|
|
|
static OSSL_LIB_CTX *sk_prov_securekey_libctx;
|
|
static OSSL_LIB_CTX *sk_prov_previous_libctx;
|
|
static OSSL_PROVIDER *sk_prov_securekey_provider;
|
|
static OSSL_PROVIDER *sk_prov_default_provider;
|
|
|
|
#define SK_PROV_NAME "securekey"
|
|
#define SK_PROV_DESCRIPTION "Secure key provider"
|
|
#define SK_PROV_VERSION "1.0"
|
|
|
|
#define SK_PROV_RSA_DEFAULT_MD "SHA-1"
|
|
#define SK_PROV_EC_DEFAULT_MD_NID "SHA-1"
|
|
#define SK_PROV_PKEY_PARAM_SK_BLOB "sk-blob"
|
|
#define SK_PROV_PKEY_PARAM_SK_FUNCS "sk-funcs"
|
|
#define SK_PROV_PKEY_PARAM_SK_PRIVATE "sk-private"
|
|
|
|
#define SK_CONF_CACHED_PARAMS_OP_KEY_EXPORT 0 /* 16 possible selections */
|
|
#define SK_CONF_CACHED_PARAMS_OP_KEY_IMPORT 16 /* 16 possible selections */
|
|
#define SK_CONF_CACHED_PARAMS_OP_KEY_GET 32
|
|
#define SK_CONF_CACHED_PARAMS_OP_KEY_SET 33
|
|
#define SK_CONF_CACHED_PARAMS_OP_COUNT 34
|
|
|
|
#define SK_CONF_CACHED_PARAMS_ALGO_RSA 0
|
|
#define SK_CONF_CACHED_PARAMS_ALGO_RSA_PSS 1
|
|
#define SK_CONF_CACHED_PARAMS_ALGO_EC 2
|
|
#define SK_CONF_CACHED_PARAMS_ALGO_COUNT 3
|
|
|
|
#define SK_PROV_CACHED_PARAMS_COUNT \
|
|
(SK_CONF_CACHED_PARAMS_ALGO_COUNT * SK_CONF_CACHED_PARAMS_OP_COUNT)
|
|
|
|
struct sk_prov_ctx {
|
|
const OSSL_CORE_HANDLE *handle;
|
|
OSSL_FUNC_core_get_libctx_fn *c_get_libctx;
|
|
OSSL_FUNC_core_new_error_fn *c_new_error;
|
|
OSSL_FUNC_core_set_error_debug_fn *c_set_error_debug;
|
|
OSSL_FUNC_core_vset_error_fn *c_vset_error;
|
|
OSSL_PROVIDER *default_provider;
|
|
void *default_provctx;
|
|
const OSSL_ALGORITHM *cached_default_algos[OSSL_OP__HIGHEST];
|
|
const OSSL_PARAM *cached_parms[SK_PROV_CACHED_PARAMS_COUNT];
|
|
bool debug;
|
|
};
|
|
|
|
struct sk_prov_key {
|
|
struct sk_prov_ctx *provctx;
|
|
int type; /* EVP_PKEY_xxx types */
|
|
void *default_key; /* shadow key of default provider */
|
|
unsigned char *secure_key;
|
|
size_t secure_key_size;
|
|
struct sk_funcs *funcs;
|
|
void *private;
|
|
unsigned int ref_count;
|
|
};
|
|
|
|
struct sk_prov_op_ctx {
|
|
struct sk_prov_ctx *provctx;
|
|
int type; /* EVP_PKEY_xxx types */
|
|
const char *propq;
|
|
void *default_op_ctx; /* shadow context of default provider */
|
|
void (*default_op_ctx_free)(void *default_op_ctx);
|
|
struct sk_prov_key *key;
|
|
int operation;
|
|
OSSL_FUNC_signature_sign_fn *sign_fn;
|
|
EVP_MD_CTX *mdctx;
|
|
EVP_MD *md;
|
|
};
|
|
|
|
#define sk_debug_ctx(ctx, fmt...) sk_debug(ctx->debug, fmt)
|
|
#define sk_debug_key(key, fmt...) sk_debug(key->provctx->debug, fmt)
|
|
#define sk_debug_op_ctx(ctx, fmt...) sk_debug(ctx->provctx->debug, fmt)
|
|
|
|
int sk_openssl_get_pkey_ec(const unsigned char *secure_key,
|
|
size_t secure_key_size, int nid, size_t prime_len,
|
|
const unsigned char *x, const unsigned char *y,
|
|
const struct sk_funcs *sk_funcs, const void *private,
|
|
EVP_PKEY **pkey, bool debug);
|
|
|
|
int sk_openssl_get_pkey_rsa(const unsigned char *secure_key,
|
|
size_t secure_key_size,
|
|
const unsigned char *modulus, size_t modulus_length,
|
|
const unsigned char *pub_exp, size_t pub_exp_length,
|
|
int pkey_type, const struct sk_funcs *sk_funcs,
|
|
const void *private, EVP_PKEY **pkey, bool debug);
|
|
|
|
|
|
static OSSL_FUNC_provider_teardown_fn sk_prov_teardown;
|
|
static OSSL_FUNC_provider_gettable_params_fn sk_prov_gettable_params;
|
|
static OSSL_FUNC_provider_get_params_fn sk_prov_get_params;
|
|
static OSSL_FUNC_provider_query_operation_fn sk_prov_query;
|
|
static OSSL_FUNC_provider_get_reason_strings_fn sk_prov_get_reason_strings;
|
|
static OSSL_FUNC_provider_get_capabilities_fn sk_prov_prov_get_capabilities;
|
|
|
|
static OSSL_FUNC_keymgmt_free_fn sk_prov_keymgmt_free;
|
|
static OSSL_FUNC_keymgmt_gen_cleanup_fn sk_prov_keymgmt_gen_cleanup;
|
|
static OSSL_FUNC_keymgmt_load_fn sk_prov_keymgmt_load;
|
|
static OSSL_FUNC_keymgmt_gen_set_template_fn
|
|
sk_prov_keymgmt_gen_set_template;
|
|
static OSSL_FUNC_keymgmt_gen_set_params_fn sk_prov_keymgmt_gen_set_params;
|
|
static OSSL_FUNC_keymgmt_gen_fn sk_prov_keymgmt_gen;
|
|
static OSSL_FUNC_keymgmt_get_params_fn sk_prov_keymgmt_get_params;
|
|
static OSSL_FUNC_keymgmt_set_params_fn sk_prov_keymgmt_set_params;
|
|
static OSSL_FUNC_keymgmt_has_fn sk_prov_keymgmt_has;
|
|
static OSSL_FUNC_keymgmt_match_fn sk_prov_keymgmt_match;
|
|
static OSSL_FUNC_keymgmt_validate_fn sk_prov_keymgmt_validate;
|
|
static OSSL_FUNC_keymgmt_export_fn sk_prov_keymgmt_export;
|
|
static OSSL_FUNC_keymgmt_import_fn sk_prov_keymgmt_import;
|
|
static OSSL_FUNC_keymgmt_new_fn sk_prov_keymgmt_rsa_new;
|
|
static OSSL_FUNC_keymgmt_new_fn sk_prov_keymgmt_rsa_pss_new;
|
|
static OSSL_FUNC_keymgmt_new_fn sk_prov_keymgmt_ec_new;
|
|
static OSSL_FUNC_keymgmt_gen_init_fn sk_prov_keymgmt_rsa_gen_init;
|
|
static OSSL_FUNC_keymgmt_gen_init_fn sk_prov_keymgmt_rsa_pss_gen_init;
|
|
static OSSL_FUNC_keymgmt_gen_init_fn sk_prov_keymgmt_ec_gen_init;
|
|
static OSSL_FUNC_keymgmt_gen_settable_params_fn
|
|
sk_prov_keymgmt_rsa_gen_settable_params;
|
|
static OSSL_FUNC_keymgmt_gen_settable_params_fn
|
|
sk_prov_keymgmt_rsa_pss_gen_settable_params;
|
|
static OSSL_FUNC_keymgmt_gen_settable_params_fn
|
|
sk_prov_keymgmt_ec_gen_settable_params;
|
|
static OSSL_FUNC_keymgmt_query_operation_name_fn
|
|
sk_prov_keymgmt_rsa_query_operation_name;
|
|
static OSSL_FUNC_keymgmt_query_operation_name_fn
|
|
sk_prov_keymgmt_ec_query_operation_name;
|
|
static OSSL_FUNC_keymgmt_gettable_params_fn
|
|
sk_prov_keymgmt_rsa_gettable_params;
|
|
static OSSL_FUNC_keymgmt_gettable_params_fn
|
|
sk_prov_keymgmt_rsa_pss_gettable_params;
|
|
static OSSL_FUNC_keymgmt_gettable_params_fn
|
|
sk_prov_keymgmt_ec_gettable_params;
|
|
static OSSL_FUNC_keymgmt_settable_params_fn
|
|
sk_prov_keymgmt_rsa_settable_params;
|
|
static OSSL_FUNC_keymgmt_settable_params_fn
|
|
sk_prov_keymgmt_rsa_pss_settable_params;
|
|
static OSSL_FUNC_keymgmt_settable_params_fn
|
|
sk_prov_keymgmt_ec_settable_params;
|
|
static OSSL_FUNC_keymgmt_export_types_fn
|
|
sk_prov_keymgmt_rsa_export_types;
|
|
static OSSL_FUNC_keymgmt_export_types_fn
|
|
sk_prov_keymgmt_rsa_pss_export_types;
|
|
static OSSL_FUNC_keymgmt_export_types_fn
|
|
sk_prov_keymgmt_ec_export_types;
|
|
static OSSL_FUNC_keymgmt_import_types_fn
|
|
sk_prov_keymgmt_rsa_import_types;
|
|
static OSSL_FUNC_keymgmt_import_types_fn
|
|
sk_prov_keymgmt_rsa_pss_import_types;
|
|
static OSSL_FUNC_keymgmt_import_types_fn sk_prov_keymgmt_ec_import_types;
|
|
|
|
static OSSL_FUNC_keyexch_newctx_fn sk_prov_keyexch_ec_newctx;
|
|
static OSSL_FUNC_keyexch_dupctx_fn sk_prov_keyexch_ec_dupctx;
|
|
static OSSL_FUNC_keyexch_init_fn sk_prov_keyexch_ec_init;
|
|
static OSSL_FUNC_keyexch_set_peer_fn sk_prov_keyexch_ec_set_peer;
|
|
static OSSL_FUNC_keyexch_derive_fn sk_prov_keyexch_ec_derive;
|
|
static OSSL_FUNC_keyexch_set_ctx_params_fn
|
|
sk_prov_keyexch_ec_set_ctx_params;
|
|
static OSSL_FUNC_keyexch_settable_ctx_params_fn
|
|
sk_prov_keyexch_ec_settable_ctx_params;
|
|
static OSSL_FUNC_keyexch_get_ctx_params_fn sk_prov_keyexch_ec_get_ctx_params;
|
|
static OSSL_FUNC_keyexch_gettable_ctx_params_fn
|
|
sk_prov_keyexch_ec_gettable_ctx_params;
|
|
|
|
static OSSL_FUNC_signature_newctx_fn sk_prov_sign_rsa_newctx;
|
|
static OSSL_FUNC_signature_newctx_fn sk_prov_sign_ec_newctx;
|
|
static OSSL_FUNC_signature_dupctx_fn sk_prov_sign_op_dupctx;
|
|
static OSSL_FUNC_signature_sign_init_fn sk_prov_sign_op_sign_init;
|
|
static OSSL_FUNC_signature_sign_fn sk_prov_sign_rsa_sign;
|
|
static OSSL_FUNC_signature_sign_fn sk_prov_sign_ec_sign;
|
|
static OSSL_FUNC_signature_verify_init_fn sk_prov_sign_op_verify_init;
|
|
static OSSL_FUNC_signature_verify_fn sk_prov_sign_op_verify;
|
|
static OSSL_FUNC_signature_verify_recover_init_fn
|
|
sk_prov_sign_op_verify_recover_init;
|
|
static OSSL_FUNC_signature_verify_recover_fn sk_prov_sign_op_verify_recover;
|
|
static OSSL_FUNC_signature_digest_sign_init_fn
|
|
sk_prov_sign_rsa_digest_sign_init;
|
|
static OSSL_FUNC_signature_digest_sign_init_fn
|
|
sk_prov_sign_ec_digest_sign_init;
|
|
static OSSL_FUNC_signature_digest_sign_update_fn
|
|
sk_prov_sign_op_digest_sign_update;
|
|
static OSSL_FUNC_signature_digest_sign_final_fn
|
|
sk_prov_sign_op_digest_sign_final;
|
|
static OSSL_FUNC_signature_digest_verify_init_fn
|
|
sk_prov_sign_op_digest_verify_init;
|
|
static OSSL_FUNC_signature_digest_verify_update_fn
|
|
sk_prov_sign_op_digest_verify_update;
|
|
static OSSL_FUNC_signature_digest_verify_final_fn
|
|
sk_prov_sign_op_digest_verify_final;
|
|
static OSSL_FUNC_signature_get_ctx_params_fn sk_prov_sign_op_get_ctx_params;
|
|
static OSSL_FUNC_signature_gettable_ctx_params_fn
|
|
sk_prov_sign_rsa_gettable_ctx_params;
|
|
static OSSL_FUNC_signature_gettable_ctx_params_fn
|
|
sk_prov_sign_ec_gettable_ctx_params;
|
|
static OSSL_FUNC_signature_set_ctx_params_fn sk_prov_sign_op_set_ctx_params;
|
|
static OSSL_FUNC_signature_settable_ctx_params_fn
|
|
sk_prov_sign_rsa_settable_ctx_params;
|
|
static OSSL_FUNC_signature_settable_ctx_params_fn
|
|
sk_prov_sign_ec_settable_ctx_params;
|
|
static OSSL_FUNC_signature_get_ctx_md_params_fn
|
|
sk_prov_sign_op_get_ctx_md_params;
|
|
static OSSL_FUNC_signature_gettable_ctx_md_params_fn
|
|
sk_prov_sign_rsa_gettable_ctx_md_params;
|
|
static OSSL_FUNC_signature_gettable_ctx_md_params_fn
|
|
sk_prov_sign_ec_gettable_ctx_md_params;
|
|
static OSSL_FUNC_signature_set_ctx_md_params_fn
|
|
sk_prov_sign_op_set_ctx_md_params;
|
|
static OSSL_FUNC_signature_settable_ctx_md_params_fn
|
|
sk_prov_sign_rsa_settable_ctx_md_params;
|
|
static OSSL_FUNC_signature_settable_ctx_md_params_fn
|
|
sk_prov_sign_ec_settable_ctx_md_params;
|
|
|
|
static OSSL_FUNC_asym_cipher_newctx_fn sk_prov_asym_rsa_newctx;
|
|
static OSSL_FUNC_asym_cipher_dupctx_fn sk_prov_asym_op_dupctx;
|
|
static OSSL_FUNC_asym_cipher_freectx_fn sk_prov_op_freectx;
|
|
static OSSL_FUNC_asym_cipher_get_ctx_params_fn sk_prov_asym_op_get_ctx_params;
|
|
static OSSL_FUNC_asym_cipher_gettable_ctx_params_fn
|
|
sk_prov_asym_rsa_gettable_ctx_params;
|
|
static OSSL_FUNC_asym_cipher_set_ctx_params_fn sk_prov_asym_op_set_ctx_params;
|
|
static OSSL_FUNC_asym_cipher_settable_ctx_params_fn
|
|
sk_prov_asym_rsa_settable_ctx_params;
|
|
static OSSL_FUNC_asym_cipher_encrypt_init_fn sk_prov_asym_op_encrypt_init;
|
|
static OSSL_FUNC_asym_cipher_encrypt_fn sk_prov_asym_op_encrypt;
|
|
static OSSL_FUNC_asym_cipher_decrypt_init_fn sk_prov_asym_op_decrypt_init;
|
|
static OSSL_FUNC_asym_cipher_decrypt_fn sk_prov_asym_rsa_decrypt;
|
|
|
|
#define SK_PROV_ERR_INTERNAL_ERROR 1
|
|
#define SK_PROV_ERR_MALLOC_FAILED 2
|
|
#define SK_PROV_ERR_INVALID_PARAM 3
|
|
#define SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING 4
|
|
#define SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED 5
|
|
#define SK_PROV_ERR_OPRATION_NOT_INITIALIZED 6
|
|
#define SK_PROV_ERR_MISSING_PARAMETER 7
|
|
#define SK_PROV_ERR_INVALID_PADDING 8
|
|
#define SK_PROV_ERR_INVALID_MD 9
|
|
#define SK_PROV_ERR_INVALID_SALTLEN 10
|
|
#define SK_PROV_ERR_SECURE_KEY_FUNC_FAILED 11
|
|
|
|
static const OSSL_ITEM sk_prov_reason_strings[] = {
|
|
{ SK_PROV_ERR_INTERNAL_ERROR, "Internal error" },
|
|
{ SK_PROV_ERR_MALLOC_FAILED, "Memory allocation failed" },
|
|
{ SK_PROV_ERR_INVALID_PARAM, "Invalid parameter encountered" },
|
|
{ SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"A function inherited from default provider is missing" },
|
|
{ SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"A function inherited from default provider has failed" },
|
|
{ SK_PROV_ERR_OPRATION_NOT_INITIALIZED,
|
|
"An operation context has not been initialized" },
|
|
{ SK_PROV_ERR_MISSING_PARAMETER,
|
|
"A parameter of a key or a context is missing" },
|
|
{ SK_PROV_ERR_INVALID_PADDING,
|
|
"An invalid or unknown padding is used" },
|
|
{ SK_PROV_ERR_INVALID_MD, "An invalid or unknown digest is used" },
|
|
{ SK_PROV_ERR_INVALID_SALTLEN, "An invalid salt length is used" },
|
|
{ SK_PROV_ERR_SECURE_KEY_FUNC_FAILED,
|
|
"A secure key function has failed" },
|
|
{0, NULL }
|
|
};
|
|
|
|
static void sk_prov_put_error(struct sk_prov_ctx *provctx, int err,
|
|
const char *file, int line, const char *func,
|
|
char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
|
|
if (provctx == NULL)
|
|
return;
|
|
|
|
va_start(ap, fmt);
|
|
provctx->c_new_error(provctx->handle);
|
|
provctx->c_set_error_debug(provctx->handle, file, line, func);
|
|
provctx->c_vset_error(provctx->handle, err, fmt, ap);
|
|
va_end(ap);
|
|
}
|
|
|
|
#define put_error_ctx(ctx, err, fmt...) \
|
|
do { \
|
|
sk_debug_ctx(ctx, "ERROR: "fmt); \
|
|
sk_prov_put_error(ctx, err, __FILE__, \
|
|
__LINE__, __func__, fmt); \
|
|
} while (0)
|
|
#define put_error_key(key, err, fmt...) \
|
|
put_error_ctx(key->provctx, err, fmt)
|
|
#define put_error_op_ctx(ctx, err, fmt...) \
|
|
put_error_ctx(ctx->provctx, err, fmt)
|
|
|
|
static void sk_prov_keymgmt_upref(struct sk_prov_key *key);
|
|
static struct sk_prov_key *sk_prov_keymgmt_new(struct sk_prov_ctx *provctx,
|
|
int type);
|
|
static int sk_prov_keymgmt_get_bits(struct sk_prov_key *key);
|
|
|
|
typedef void (*func_t)(void);
|
|
|
|
static func_t sk_prov_get_default_func(struct sk_prov_ctx *provctx,
|
|
int operation_id,
|
|
const char *algorithm,
|
|
int function_id)
|
|
{
|
|
const OSSL_ALGORITHM *default_algos, *algs;
|
|
const OSSL_DISPATCH *default_impl, *impl;
|
|
int algolen = strlen(algorithm);
|
|
int no_cache = 0, query = 0;
|
|
func_t func = NULL;
|
|
const char *found;
|
|
|
|
if (provctx == NULL || provctx->default_provider == NULL ||
|
|
operation_id <= 0 || operation_id > OSSL_OP__HIGHEST)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "operation_id: %d, algo: %s, func: %d",
|
|
operation_id, algorithm, function_id);
|
|
|
|
default_algos = provctx->cached_default_algos[operation_id];
|
|
if (default_algos == NULL) {
|
|
default_algos = OSSL_PROVIDER_query_operation(
|
|
provctx->default_provider,
|
|
operation_id, &no_cache);
|
|
query = 1;
|
|
}
|
|
|
|
for (algs = default_algos; algs != NULL &&
|
|
algs->algorithm_names != NULL; algs++) {
|
|
found = strcasestr(algs->algorithm_names, algorithm);
|
|
if (found == NULL)
|
|
continue;
|
|
if (found[algolen] != '\0' && found[algolen] != ':')
|
|
continue;
|
|
if (found != algs->algorithm_names && found[-1] != ':')
|
|
continue;
|
|
|
|
default_impl = algs->implementation;
|
|
for (impl = default_impl; impl->function_id != 0; impl++) {
|
|
if (impl->function_id == function_id) {
|
|
func = impl->function;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (query == 1 && default_algos != NULL)
|
|
OSSL_PROVIDER_unquery_operation(provctx->default_provider,
|
|
operation_id,
|
|
default_algos);
|
|
|
|
if (no_cache == 0 &&
|
|
provctx->cached_default_algos[operation_id] == NULL)
|
|
provctx->cached_default_algos[operation_id] = default_algos;
|
|
|
|
sk_debug_ctx(provctx, "func: %p", func);
|
|
return func;
|
|
}
|
|
|
|
static const char *sk_prov_get_algo(int pkey_type, bool sign)
|
|
{
|
|
switch (pkey_type) {
|
|
case EVP_PKEY_RSA:
|
|
return "RSA";
|
|
case EVP_PKEY_RSA_PSS:
|
|
return "RSA-PSS";
|
|
case EVP_PKEY_EC:
|
|
if (sign)
|
|
return "ECDSA";
|
|
else
|
|
return "EC";
|
|
default:
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
static func_t sk_prov_get_default_keymgmt_func(struct sk_prov_ctx *provctx,
|
|
int pkey_type, int function_id)
|
|
{
|
|
return sk_prov_get_default_func(provctx, OSSL_OP_KEYMGMT,
|
|
sk_prov_get_algo(pkey_type, false),
|
|
function_id);
|
|
}
|
|
|
|
static func_t sk_prov_get_default_keyexch_func(struct sk_prov_ctx *provctx,
|
|
int function_id)
|
|
{
|
|
return sk_prov_get_default_func(provctx, OSSL_OP_KEYEXCH, "ECDH",
|
|
function_id);
|
|
}
|
|
|
|
static func_t sk_prov_get_default_asym_func(struct sk_prov_ctx *provctx,
|
|
int pkey_type, int function_id)
|
|
{
|
|
return sk_prov_get_default_func(provctx, OSSL_OP_ASYM_CIPHER,
|
|
sk_prov_get_algo(pkey_type, false),
|
|
function_id);
|
|
}
|
|
|
|
static func_t sk_prov_get_default_sign_func(struct sk_prov_ctx *provctx,
|
|
int pkey_type, int function_id)
|
|
{
|
|
return sk_prov_get_default_func(provctx, OSSL_OP_SIGNATURE,
|
|
sk_prov_get_algo(pkey_type, true),
|
|
function_id);
|
|
}
|
|
|
|
static int sk_prov_get_cached_params_index(int pkey_type, int operation,
|
|
int selection)
|
|
{
|
|
int ofs = 0;
|
|
|
|
if (operation < 0 || operation >= SK_CONF_CACHED_PARAMS_OP_COUNT)
|
|
return -1;
|
|
|
|
switch (operation) {
|
|
case SK_CONF_CACHED_PARAMS_OP_KEY_EXPORT:
|
|
case SK_CONF_CACHED_PARAMS_OP_KEY_IMPORT:
|
|
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
|
|
ofs += 1;
|
|
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
|
|
ofs += 2;
|
|
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
|
|
ofs += 4;
|
|
if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
|
|
ofs += 8;
|
|
break;
|
|
}
|
|
|
|
switch (pkey_type) {
|
|
case EVP_PKEY_RSA:
|
|
return (SK_CONF_CACHED_PARAMS_ALGO_RSA *
|
|
SK_CONF_CACHED_PARAMS_OP_COUNT) +
|
|
operation + ofs;
|
|
case EVP_PKEY_RSA_PSS:
|
|
return (SK_CONF_CACHED_PARAMS_ALGO_RSA_PSS *
|
|
SK_CONF_CACHED_PARAMS_OP_COUNT) +
|
|
operation + ofs;
|
|
case EVP_PKEY_EC:
|
|
return (SK_CONF_CACHED_PARAMS_ALGO_EC *
|
|
SK_CONF_CACHED_PARAMS_OP_COUNT) +
|
|
operation + ofs;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_get_cached_params(struct sk_prov_ctx *provctx,
|
|
int pkey_type, int operation,
|
|
int selection)
|
|
{
|
|
int index;
|
|
|
|
sk_debug_ctx(provctx, "pkey_type: %d operation: %d selection: %x",
|
|
pkey_type, operation, selection);
|
|
|
|
index = sk_prov_get_cached_params_index(pkey_type, operation,
|
|
selection);
|
|
if (index < 0) {
|
|
put_error_ctx(provctx, SK_PROV_ERR_INTERNAL_ERROR,
|
|
"Invalid type, operation or selection");
|
|
return NULL;
|
|
}
|
|
|
|
return provctx->cached_parms[index];
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_cached_params_build(
|
|
struct sk_prov_ctx *provctx,
|
|
int pkey_type,
|
|
int operation,
|
|
int selection,
|
|
const OSSL_PARAM *params1,
|
|
const OSSL_PARAM *params2)
|
|
{
|
|
int index, count = 0, i, k = 0;
|
|
OSSL_PARAM *params;
|
|
|
|
sk_debug_ctx(provctx, "pkey_type: %d operation: %d selection: %x",
|
|
pkey_type, operation, selection);
|
|
|
|
index = sk_prov_get_cached_params_index(pkey_type, operation,
|
|
selection);
|
|
if (index < 0) {
|
|
put_error_ctx(provctx, SK_PROV_ERR_INTERNAL_ERROR,
|
|
"Invalid type, operation or selection");
|
|
return NULL;
|
|
}
|
|
|
|
if (provctx->cached_parms[index] != NULL) {
|
|
OPENSSL_free((void *)provctx->cached_parms[index]);
|
|
provctx->cached_parms[index] = NULL;
|
|
}
|
|
|
|
for (i = 0; params1 != NULL && params1[i].key != NULL; i++, count++)
|
|
;
|
|
for (i = 0; params2 != NULL && params2[i].key != NULL; i++, count++)
|
|
;
|
|
sk_debug_ctx(provctx, "count: %d", count);
|
|
|
|
count++; /* End marker */
|
|
|
|
params = OPENSSL_zalloc(sizeof(OSSL_PARAM) * count);
|
|
if (params == NULL) {
|
|
put_error_ctx(provctx, SK_PROV_ERR_MALLOC_FAILED,
|
|
"OPENSSL_zalloc failed");
|
|
return NULL;
|
|
}
|
|
|
|
for (i = 0; params1 != NULL && params1[i].key != NULL; i++, k++) {
|
|
params[k] = params1[i];
|
|
sk_debug_ctx(provctx, "param %d: %s", k, params[k].key);
|
|
}
|
|
for (i = 0; params2 != NULL && params2[i].key != NULL; i++, k++) {
|
|
params[k] = params2[i];
|
|
sk_debug_ctx(provctx, "param %d: %s", k, params[k].key);
|
|
}
|
|
params[k] = OSSL_PARAM_construct_end();
|
|
|
|
provctx->cached_parms[index] = params;
|
|
return provctx->cached_parms[index];
|
|
}
|
|
|
|
#pragma GCC diagnostic push
|
|
#pragma GCC diagnostic ignored "-Wunused-function"
|
|
static bool sk_prov_check_uint_param(const OSSL_PARAM params[],
|
|
const char *param_name,
|
|
const struct sk_prov_key *key,
|
|
int key_type,
|
|
unsigned int expected_value)
|
|
{
|
|
const OSSL_PARAM *p;
|
|
unsigned int value;
|
|
|
|
if (key == NULL)
|
|
return true;
|
|
if (key->type != key_type)
|
|
return true;
|
|
|
|
p = OSSL_PARAM_locate_const(params, param_name);
|
|
if (p == NULL)
|
|
return true;
|
|
|
|
if (OSSL_PARAM_get_uint(p, &value) != 1)
|
|
return true;
|
|
|
|
return value == expected_value;
|
|
}
|
|
#pragma GCC diagnostic pop
|
|
|
|
static struct sk_prov_op_ctx *sk_prov_op_newctx(struct sk_prov_ctx *provctx,
|
|
const char *propq,
|
|
int type)
|
|
{
|
|
struct sk_prov_op_ctx *ctx;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "propq: %s type: %d",
|
|
propq != NULL ? propq : "", type);
|
|
|
|
ctx = OPENSSL_zalloc(sizeof(struct sk_prov_op_ctx));
|
|
if (ctx == NULL) {
|
|
put_error_ctx(provctx, SK_PROV_ERR_MALLOC_FAILED,
|
|
"OPENSSL_zalloc failed");
|
|
return NULL;
|
|
}
|
|
|
|
ctx->provctx = provctx;
|
|
ctx->type = type;
|
|
|
|
if (propq != NULL) {
|
|
ctx->propq = OPENSSL_strdup(propq);
|
|
if (ctx->propq == NULL) {
|
|
put_error_ctx(provctx, SK_PROV_ERR_MALLOC_FAILED,
|
|
"OPENSSL_strdup failed");
|
|
OPENSSL_free(ctx);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
sk_debug_ctx(provctx, "ctx: %p", ctx);
|
|
return ctx;
|
|
}
|
|
|
|
static void sk_prov_op_freectx(void *vctx)
|
|
{
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
|
|
if (ctx == NULL)
|
|
return;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p", ctx);
|
|
|
|
if (ctx->default_op_ctx != NULL && ctx->default_op_ctx_free != NULL)
|
|
ctx->default_op_ctx_free(ctx->default_op_ctx);
|
|
|
|
if (ctx->key != NULL)
|
|
sk_prov_keymgmt_free(ctx->key);
|
|
|
|
if (ctx->propq != NULL)
|
|
OPENSSL_free((void *)ctx->propq);
|
|
|
|
if (ctx->mdctx != NULL)
|
|
EVP_MD_CTX_free(ctx->mdctx);
|
|
if (ctx->md != NULL)
|
|
EVP_MD_free(ctx->md);
|
|
|
|
OPENSSL_free(ctx);
|
|
}
|
|
|
|
static struct sk_prov_op_ctx *sk_prov_op_dupctx(struct sk_prov_op_ctx *ctx)
|
|
{
|
|
struct sk_prov_op_ctx *new_ctx;
|
|
|
|
if (ctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p", ctx);
|
|
|
|
new_ctx = sk_prov_op_newctx(ctx->provctx, ctx->propq, ctx->type);
|
|
if (new_ctx == NULL) {
|
|
sk_debug_op_ctx(ctx, "ERROR: sk_prov_op_newctx failed");
|
|
return NULL;
|
|
}
|
|
|
|
new_ctx->operation = ctx->operation;
|
|
new_ctx->default_op_ctx_free = ctx->default_op_ctx_free;
|
|
new_ctx->sign_fn = ctx->sign_fn;
|
|
|
|
if (ctx->mdctx != NULL) {
|
|
new_ctx->mdctx = EVP_MD_CTX_new();
|
|
if (new_ctx->mdctx == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_MALLOC_FAILED,
|
|
"EVP_MD_CTX_new failed");
|
|
sk_prov_op_freectx(new_ctx);
|
|
return NULL;
|
|
}
|
|
|
|
if (!EVP_MD_CTX_copy_ex(new_ctx->mdctx, ctx->mdctx)) {
|
|
sk_debug_op_ctx(ctx,
|
|
"ERROR: EVP_MD_CTX_copy_ex failed");
|
|
sk_prov_op_freectx(new_ctx);
|
|
return NULL;
|
|
}
|
|
};
|
|
|
|
if (ctx->md != NULL) {
|
|
new_ctx->md = ctx->md;
|
|
EVP_MD_up_ref(ctx->md);
|
|
}
|
|
|
|
if (ctx->key != NULL) {
|
|
new_ctx->key = ctx->key;
|
|
sk_prov_keymgmt_upref(ctx->key);
|
|
}
|
|
|
|
sk_debug_op_ctx(ctx, "new_ctx: %p", new_ctx);
|
|
return new_ctx;
|
|
}
|
|
|
|
static int sk_prov_op_init(struct sk_prov_op_ctx *ctx, struct sk_prov_key *key,
|
|
int operation)
|
|
{
|
|
if (ctx == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p key: %p operation: %d", ctx, key,
|
|
operation);
|
|
|
|
if (key != NULL) {
|
|
switch (ctx->type) {
|
|
case EVP_PKEY_RSA:
|
|
case EVP_PKEY_RSA_PSS:
|
|
if (key->type != EVP_PKEY_RSA &&
|
|
key->type != EVP_PKEY_RSA_PSS) {
|
|
put_error_op_ctx(ctx,
|
|
SK_PROV_ERR_INTERNAL_ERROR,
|
|
"key type mismatch: ctx type: "
|
|
"%d key type: %d",
|
|
ctx->type, key->type);
|
|
return 0;
|
|
}
|
|
break;
|
|
case EVP_PKEY_EC:
|
|
if (key->type != EVP_PKEY_EC) {
|
|
put_error_op_ctx(ctx,
|
|
SK_PROV_ERR_INTERNAL_ERROR,
|
|
"key type mismatch: ctx type: "
|
|
"%d key type: %d",
|
|
ctx->type, key->type);
|
|
return 0;
|
|
}
|
|
break;
|
|
default:
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_INTERNAL_ERROR,
|
|
"key type unknown: ctx type: "
|
|
"%d key type: %d",
|
|
ctx->type, key->type);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if (key != NULL)
|
|
sk_prov_keymgmt_upref(key);
|
|
|
|
if (ctx->key != NULL)
|
|
sk_prov_keymgmt_free(ctx->key);
|
|
|
|
ctx->key = key;
|
|
ctx->operation = operation;
|
|
|
|
return 1;
|
|
}
|
|
|
|
static struct sk_prov_op_ctx *sk_prov_asym_op_newctx(
|
|
struct sk_prov_ctx *provctx,
|
|
int pkey_type)
|
|
{
|
|
OSSL_FUNC_asym_cipher_freectx_fn *default_freectx_fn;
|
|
OSSL_FUNC_asym_cipher_newctx_fn *default_newctx_fn;
|
|
struct sk_prov_op_ctx *ctx;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "pkey_type: %d", pkey_type);
|
|
|
|
default_newctx_fn = (OSSL_FUNC_asym_cipher_newctx_fn *)
|
|
sk_prov_get_default_asym_func(provctx, pkey_type,
|
|
OSSL_FUNC_ASYM_CIPHER_NEWCTX);
|
|
if (default_newctx_fn == NULL) {
|
|
put_error_ctx(provctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default newctx_fn");
|
|
return NULL;
|
|
}
|
|
|
|
default_freectx_fn = (OSSL_FUNC_asym_cipher_freectx_fn *)
|
|
sk_prov_get_default_asym_func(provctx, pkey_type,
|
|
OSSL_FUNC_ASYM_CIPHER_FREECTX);
|
|
if (default_freectx_fn == NULL) {
|
|
put_error_ctx(provctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default freectx_fn");
|
|
return NULL;
|
|
}
|
|
|
|
ctx = sk_prov_op_newctx(provctx, NULL, pkey_type);
|
|
if (ctx == NULL) {
|
|
sk_debug_ctx(provctx, "ERROR: sk_prov_op_newctx failed");
|
|
return NULL;
|
|
}
|
|
|
|
ctx->default_op_ctx = default_newctx_fn(provctx->default_provctx);
|
|
if (ctx->default_op_ctx == NULL) {
|
|
put_error_ctx(provctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_newctx_fn failed");
|
|
sk_prov_op_freectx(ctx);
|
|
return NULL;
|
|
}
|
|
ctx->default_op_ctx_free = default_freectx_fn;
|
|
|
|
sk_debug_ctx(provctx, "ctx: %p", ctx);
|
|
return ctx;
|
|
}
|
|
|
|
static void *sk_prov_asym_op_dupctx(void *vctx)
|
|
{
|
|
OSSL_FUNC_asym_cipher_dupctx_fn *default_dupctx_fn;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
struct sk_prov_op_ctx *new_ctx;
|
|
|
|
if (ctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p", ctx);
|
|
|
|
default_dupctx_fn = (OSSL_FUNC_asym_cipher_dupctx_fn *)
|
|
sk_prov_get_default_asym_func(ctx->provctx,
|
|
ctx->type, OSSL_FUNC_ASYM_CIPHER_DUPCTX);
|
|
if (default_dupctx_fn == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default dupctx_fn");
|
|
return NULL;
|
|
}
|
|
|
|
new_ctx = sk_prov_op_dupctx(ctx);
|
|
if (new_ctx == NULL) {
|
|
sk_debug_op_ctx(ctx, "ERROR: sk_prov_op_dupctx failed");
|
|
return NULL;
|
|
}
|
|
|
|
new_ctx->default_op_ctx = default_dupctx_fn(ctx->default_op_ctx);
|
|
if (new_ctx->default_op_ctx == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_dupctx_fn failed");
|
|
sk_prov_op_freectx(new_ctx);
|
|
return NULL;
|
|
}
|
|
|
|
sk_debug_op_ctx(ctx, "new_ctx: %p", new_ctx);
|
|
return new_ctx;
|
|
}
|
|
|
|
static int sk_prov_asym_op_get_ctx_params(void *vctx, OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_asym_cipher_get_ctx_params_fn *default_get_params_fn;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
const OSSL_PARAM *p;
|
|
|
|
if (ctx == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p", ctx);
|
|
for (p = params; p != NULL && p->key != NULL; p++)
|
|
sk_debug_op_ctx(ctx, "param: %s", p->key);
|
|
|
|
default_get_params_fn = (OSSL_FUNC_asym_cipher_get_ctx_params_fn *)
|
|
sk_prov_get_default_asym_func(ctx->provctx,
|
|
ctx->type,
|
|
OSSL_FUNC_ASYM_CIPHER_GET_CTX_PARAMS);
|
|
|
|
/* default_get_params_fn is optional */
|
|
if (default_get_params_fn != NULL) {
|
|
if (!default_get_params_fn(ctx->default_op_ctx, params)) {
|
|
put_error_op_ctx(ctx,
|
|
SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_get_params_fn failed");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int sk_prov_asym_op_set_ctx_params(void *vctx, const OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_asym_cipher_set_ctx_params_fn *default_set_params_fn;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
const OSSL_PARAM *p;
|
|
|
|
if (ctx == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p", ctx);
|
|
for (p = params; p != NULL && p->key != NULL; p++)
|
|
sk_debug_op_ctx(ctx, "param: %s", p->key);
|
|
|
|
default_set_params_fn = (OSSL_FUNC_asym_cipher_set_ctx_params_fn *)
|
|
sk_prov_get_default_asym_func(ctx->provctx,
|
|
ctx->type,
|
|
OSSL_FUNC_ASYM_CIPHER_SET_CTX_PARAMS);
|
|
|
|
/* default_set_params_fn is optional */
|
|
if (default_set_params_fn != NULL) {
|
|
if (!default_set_params_fn(ctx->default_op_ctx, params)) {
|
|
put_error_op_ctx(ctx,
|
|
SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_set_params_fn failed");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_asym_op_gettable_ctx_params(
|
|
struct sk_prov_op_ctx *ctx,
|
|
struct sk_prov_ctx *provctx, int pkey_type)
|
|
{
|
|
OSSL_FUNC_asym_cipher_gettable_ctx_params_fn
|
|
*default_gettable_params_fn;
|
|
const OSSL_PARAM *params = NULL, *p;
|
|
|
|
if (ctx == NULL || provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "pkey_type: %d", pkey_type);
|
|
|
|
default_gettable_params_fn =
|
|
(OSSL_FUNC_asym_cipher_gettable_ctx_params_fn *)
|
|
sk_prov_get_default_asym_func(provctx, pkey_type,
|
|
OSSL_FUNC_ASYM_CIPHER_GETTABLE_CTX_PARAMS);
|
|
|
|
/* default_gettable_params_fn is optional */
|
|
if (default_gettable_params_fn != NULL)
|
|
params = default_gettable_params_fn(ctx->default_op_ctx,
|
|
provctx->default_provctx);
|
|
|
|
for (p = params; p != NULL && p->key != NULL; p++)
|
|
sk_debug_ctx(provctx, "param: %s", p->key);
|
|
|
|
return params;
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_asym_op_settable_ctx_params(
|
|
struct sk_prov_op_ctx *ctx,
|
|
struct sk_prov_ctx *provctx, int pkey_type)
|
|
{
|
|
OSSL_FUNC_asym_cipher_settable_ctx_params_fn
|
|
*default_settable_params_fn;
|
|
const OSSL_PARAM *params = NULL, *p;
|
|
|
|
if (ctx == NULL || provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "pkey_type: %d", pkey_type);
|
|
|
|
default_settable_params_fn =
|
|
(OSSL_FUNC_asym_cipher_settable_ctx_params_fn *)
|
|
sk_prov_get_default_asym_func(provctx, pkey_type,
|
|
OSSL_FUNC_ASYM_CIPHER_SETTABLE_CTX_PARAMS);
|
|
|
|
/* default_settable_params_fn is optional */
|
|
if (default_settable_params_fn != NULL)
|
|
params = default_settable_params_fn(ctx->default_op_ctx,
|
|
provctx->default_provctx);
|
|
|
|
for (p = params; p != NULL && p->key != NULL; p++)
|
|
sk_debug_ctx(provctx, "param: %s", p->key);
|
|
|
|
return params;
|
|
}
|
|
|
|
static EVP_MD *sk_prov_asym_op_get_oaep_md(struct sk_prov_op_ctx *ctx)
|
|
{
|
|
char mdprops[256], mdname[50];
|
|
OSSL_PARAM ctx_params[] = {
|
|
OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST,
|
|
&mdname, sizeof(mdname)),
|
|
OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST_PROPS,
|
|
&mdprops, sizeof(mdprops)),
|
|
OSSL_PARAM_END
|
|
};
|
|
EVP_MD *md;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p", ctx);
|
|
|
|
if (!sk_prov_asym_op_get_ctx_params(ctx, ctx_params) ||
|
|
!OSSL_PARAM_modified(&ctx_params[0]) ||
|
|
!OSSL_PARAM_modified(&ctx_params[1])) {
|
|
sk_debug_op_ctx(ctx, "sk_prov_asym_op_get_ctx_params failed");
|
|
if (ctx->md != NULL) {
|
|
sk_debug_op_ctx(ctx, "use digest from context: %s",
|
|
EVP_MD_name(ctx->md));
|
|
EVP_MD_up_ref(ctx->md);
|
|
return ctx->md;
|
|
}
|
|
|
|
sk_debug_op_ctx(ctx, "use default");
|
|
strcpy(mdname, SK_PROV_RSA_DEFAULT_MD);
|
|
strcpy(mdprops, "");
|
|
}
|
|
|
|
md = EVP_MD_fetch((OSSL_LIB_CTX *)ctx->provctx->c_get_libctx(
|
|
ctx->provctx->handle),
|
|
mdname, mdprops[0] != '\0' ? mdprops : ctx->propq);
|
|
if (md == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_MISSING_PARAMETER,
|
|
"EVP_MD_fetch failed to fetch '%s' using "
|
|
"property query '%s'", mdname,
|
|
mdprops[0] != '\0' ? mdprops :
|
|
ctx->propq != NULL ? ctx->propq : "");
|
|
return NULL;
|
|
}
|
|
|
|
sk_debug_op_ctx(ctx, "md: %s", EVP_MD_name(md));
|
|
return md;
|
|
}
|
|
|
|
static EVP_MD *sk_prov_asym_op_get_mgf_md(struct sk_prov_op_ctx *ctx)
|
|
{
|
|
char mdprops[256], mdname[50];
|
|
OSSL_PARAM ctx_params[] = {
|
|
OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST,
|
|
&mdname, sizeof(mdname)),
|
|
OSSL_PARAM_utf8_string(OSSL_ASYM_CIPHER_PARAM_MGF1_DIGEST_PROPS,
|
|
&mdprops, sizeof(mdprops)),
|
|
OSSL_PARAM_END
|
|
};
|
|
EVP_MD *md;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p", ctx);
|
|
|
|
if (!sk_prov_asym_op_get_ctx_params(ctx, ctx_params) ||
|
|
!OSSL_PARAM_modified(&ctx_params[0]) ||
|
|
!OSSL_PARAM_modified(&ctx_params[1])) {
|
|
sk_debug_op_ctx(ctx, "sk_prov_asym_op_get_ctx_params failed, "
|
|
"using oaep digest");
|
|
return sk_prov_asym_op_get_oaep_md(ctx);
|
|
}
|
|
|
|
md = EVP_MD_fetch((OSSL_LIB_CTX *)ctx->provctx->c_get_libctx(
|
|
ctx->provctx->handle),
|
|
mdname, mdprops[0] != '\0' ? mdprops : ctx->propq);
|
|
if (md == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_MISSING_PARAMETER,
|
|
"EVP_MD_fetch failed to fetch '%s' using "
|
|
"property query '%s'", mdname,
|
|
mdprops[0] != '\0' ? mdprops :
|
|
ctx->propq != NULL ? ctx->propq : "");
|
|
return NULL;
|
|
}
|
|
|
|
sk_debug_op_ctx(ctx, "md: %s", EVP_MD_name(md));
|
|
return md;
|
|
}
|
|
|
|
static int sk_prov_asym_op_get_oaep_label(struct sk_prov_op_ctx *ctx,
|
|
unsigned char **label)
|
|
{
|
|
OSSL_PARAM ctx_params[] = {
|
|
OSSL_PARAM_octet_ptr(OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL,
|
|
label, 0),
|
|
OSSL_PARAM_END
|
|
};
|
|
int oaep_label_len;
|
|
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p", ctx);
|
|
|
|
if (!sk_prov_asym_op_get_ctx_params(ctx, ctx_params) ||
|
|
!OSSL_PARAM_modified(&ctx_params[0])) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_MISSING_PARAMETER,
|
|
"sk_prov_asym_op_get_ctx_params failed to "
|
|
"get OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL");
|
|
return -1;
|
|
}
|
|
|
|
oaep_label_len = ctx_params[0].return_size;
|
|
sk_debug_op_ctx(ctx, "oaep_label: %p oaep_label_len: %d", *label,
|
|
oaep_label_len);
|
|
|
|
return oaep_label_len;
|
|
}
|
|
|
|
static int sk_prov_parse_padding(const char *padding)
|
|
{
|
|
if (strcmp(padding, OSSL_PKEY_RSA_PAD_MODE_NONE) == 0)
|
|
return RSA_NO_PADDING;
|
|
if (strcmp(padding, OSSL_PKEY_RSA_PAD_MODE_PKCSV15) == 0)
|
|
return RSA_PKCS1_PADDING;
|
|
if (strcmp(padding, OSSL_PKEY_RSA_PAD_MODE_OAEP) == 0)
|
|
return RSA_PKCS1_OAEP_PADDING;
|
|
if (strcmp(padding, OSSL_PKEY_RSA_PAD_MODE_X931) == 0)
|
|
return RSA_X931_PADDING;
|
|
if (strcmp(padding, OSSL_PKEY_RSA_PAD_MODE_PSS) == 0)
|
|
return RSA_PKCS1_PSS_PADDING;
|
|
|
|
return -1;
|
|
}
|
|
|
|
static int sk_prov_asym_op_get_padding(struct sk_prov_op_ctx *ctx)
|
|
{
|
|
char padding[50];
|
|
OSSL_PARAM ctx_params[] = {
|
|
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_PAD_MODE,
|
|
&padding, sizeof(padding)),
|
|
OSSL_PARAM_END
|
|
};
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p", ctx);
|
|
|
|
if (!sk_prov_asym_op_get_ctx_params(ctx, ctx_params) ||
|
|
!OSSL_PARAM_modified(&ctx_params[0])) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_MISSING_PARAMETER,
|
|
"sk_prov_asym_op_get_ctx_params failed to "
|
|
"get OSSL_PKEY_PARAM_PAD_MODE");
|
|
return -1;
|
|
}
|
|
|
|
sk_debug_op_ctx(ctx, "padding: %s", padding);
|
|
|
|
return sk_prov_parse_padding(padding);
|
|
}
|
|
|
|
static int sk_prov_asym_op_encrypt_init(void *vctx, void *vkey,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_asym_cipher_encrypt_init_fn *default_encrypt_init_fn;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
struct sk_prov_key *key = vkey;
|
|
const OSSL_PARAM *p;
|
|
|
|
if (ctx == NULL || key == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p key: %p", ctx, key);
|
|
for (p = params; p != NULL && p->key != NULL; p++)
|
|
sk_debug_op_ctx(ctx, "param: %s", p->key);
|
|
|
|
default_encrypt_init_fn = (OSSL_FUNC_asym_cipher_encrypt_init_fn *)
|
|
sk_prov_get_default_asym_func(ctx->provctx,
|
|
ctx->type,
|
|
OSSL_FUNC_ASYM_CIPHER_ENCRYPT_INIT);
|
|
if (default_encrypt_init_fn == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default encrypt_init_fn");
|
|
return 0;
|
|
}
|
|
|
|
if (!sk_prov_op_init(ctx, key, EVP_PKEY_OP_ENCRYPT)) {
|
|
sk_debug_op_ctx(ctx, "ERROR: sk_prov_op_init failed");
|
|
return 0;
|
|
}
|
|
|
|
if (!default_encrypt_init_fn(ctx->default_op_ctx, key->default_key,
|
|
params)) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_encrypt_init_fn failed");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int sk_prov_asym_op_decrypt_init(void *vctx, void *vkey,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_asym_cipher_decrypt_init_fn *default_decrypt_init_fn;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
struct sk_prov_key *key = vkey;
|
|
const OSSL_PARAM *p;
|
|
|
|
if (ctx == NULL || key == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p key: %p", ctx, key);
|
|
for (p = params; p != NULL && p->key != NULL; p++)
|
|
sk_debug_op_ctx(ctx, "param: %s", p->key);
|
|
|
|
default_decrypt_init_fn = (OSSL_FUNC_asym_cipher_decrypt_init_fn *)
|
|
sk_prov_get_default_asym_func(ctx->provctx,
|
|
ctx->type,
|
|
OSSL_FUNC_ASYM_CIPHER_DECRYPT_INIT);
|
|
if (default_decrypt_init_fn == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default decrypt_init_fn");
|
|
return 0;
|
|
}
|
|
|
|
if (!sk_prov_op_init(ctx, key, EVP_PKEY_OP_DECRYPT)) {
|
|
sk_debug_op_ctx(ctx, "ERROR: sk_prov_op_init failed");
|
|
return 0;
|
|
}
|
|
|
|
if (!default_decrypt_init_fn(ctx->default_op_ctx, key->default_key,
|
|
params)) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_decrypt_init_fn failed");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int sk_prov_asym_op_encrypt(void *vctx,
|
|
unsigned char *out, size_t *outlen,
|
|
size_t outsize, const unsigned char *in,
|
|
size_t inlen)
|
|
{
|
|
OSSL_FUNC_asym_cipher_encrypt_fn *default_encrypt_fn;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
|
|
if (ctx == NULL || in == NULL || outlen == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p key: %p inlen: %lu outsize: %lu",
|
|
ctx, ctx->key, inlen, outsize);
|
|
|
|
default_encrypt_fn = (OSSL_FUNC_asym_cipher_encrypt_fn *)
|
|
sk_prov_get_default_asym_func(ctx->provctx,
|
|
ctx->type, OSSL_FUNC_ASYM_CIPHER_ENCRYPT);
|
|
if (default_encrypt_fn == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default encrypt_fn");
|
|
return 0;
|
|
}
|
|
|
|
if (!default_encrypt_fn(ctx->default_op_ctx, out, outlen, outsize,
|
|
in, inlen)) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_encrypt_fn failed");
|
|
return 0;
|
|
}
|
|
|
|
sk_debug_op_ctx(ctx, "outlen: %lu", *outlen);
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int sk_prov_asym_op_decrypt(struct sk_prov_op_ctx *ctx,
|
|
unsigned char *out, size_t *outlen,
|
|
size_t outsize, const unsigned char *in,
|
|
size_t inlen)
|
|
{
|
|
OSSL_FUNC_asym_cipher_decrypt_fn *default_decrypt_fn;
|
|
|
|
if (ctx == NULL || in == NULL || outlen == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p key: %p inlen: %lu outsize: %lu",
|
|
ctx, ctx->key, inlen, outsize);
|
|
|
|
default_decrypt_fn = (OSSL_FUNC_asym_cipher_decrypt_fn *)
|
|
sk_prov_get_default_asym_func(ctx->provctx,
|
|
ctx->type, OSSL_FUNC_ASYM_CIPHER_DECRYPT);
|
|
if (default_decrypt_fn == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default decrypt_fn");
|
|
return 0;
|
|
}
|
|
|
|
if (!default_decrypt_fn(ctx->default_op_ctx, out, outlen, outsize,
|
|
in, inlen)) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_decrypt_fn failed");
|
|
return 0;
|
|
}
|
|
|
|
sk_debug_op_ctx(ctx, "outlen: %lu", *outlen);
|
|
|
|
return 1;
|
|
}
|
|
|
|
static struct sk_prov_op_ctx *sk_prov_sign_op_newctx(
|
|
struct sk_prov_ctx *provctx,
|
|
const char *propq,
|
|
int pkey_type)
|
|
{
|
|
OSSL_FUNC_signature_freectx_fn *default_freectx_fn;
|
|
OSSL_FUNC_signature_newctx_fn *default_newctx_fn;
|
|
struct sk_prov_op_ctx *ctx;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "propq: %s pkey_type: %d",
|
|
propq != NULL ? propq : "", pkey_type);
|
|
|
|
default_newctx_fn = (OSSL_FUNC_signature_newctx_fn *)
|
|
sk_prov_get_default_sign_func(provctx, pkey_type,
|
|
OSSL_FUNC_SIGNATURE_NEWCTX);
|
|
if (default_newctx_fn == NULL) {
|
|
put_error_ctx(provctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default newctx_fn");
|
|
return NULL;
|
|
}
|
|
|
|
default_freectx_fn = (OSSL_FUNC_signature_freectx_fn *)
|
|
sk_prov_get_default_sign_func(provctx, pkey_type,
|
|
OSSL_FUNC_SIGNATURE_FREECTX);
|
|
if (default_freectx_fn == NULL) {
|
|
put_error_ctx(provctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default freectx_fn");
|
|
return NULL;
|
|
}
|
|
|
|
ctx = sk_prov_op_newctx(provctx, propq, pkey_type);
|
|
if (ctx == NULL) {
|
|
sk_debug_ctx(provctx, "ERROR: sk_prov_op_newctx failed");
|
|
return NULL;
|
|
}
|
|
|
|
ctx->default_op_ctx = default_newctx_fn(provctx->default_provctx,
|
|
propq);
|
|
if (ctx->default_op_ctx == NULL) {
|
|
put_error_ctx(provctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_newctx_fn failed");
|
|
sk_prov_op_freectx(ctx);
|
|
return NULL;
|
|
}
|
|
ctx->default_op_ctx_free = default_freectx_fn;
|
|
|
|
sk_debug_ctx(provctx, "ctx: %p", ctx);
|
|
return ctx;
|
|
}
|
|
|
|
static void *sk_prov_sign_op_dupctx(void *vctx)
|
|
{
|
|
OSSL_FUNC_signature_dupctx_fn *default_dupctx_fn;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
struct sk_prov_op_ctx *new_ctx;
|
|
|
|
if (ctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p", ctx);
|
|
|
|
default_dupctx_fn = (OSSL_FUNC_signature_dupctx_fn *)
|
|
sk_prov_get_default_sign_func(ctx->provctx,
|
|
ctx->type, OSSL_FUNC_SIGNATURE_DUPCTX);
|
|
if (default_dupctx_fn == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default dupctx_fn");
|
|
return NULL;
|
|
}
|
|
|
|
new_ctx = sk_prov_op_dupctx(ctx);
|
|
if (new_ctx == NULL) {
|
|
sk_debug_op_ctx(ctx, "ERROR: sk_prov_op_dupctx failed");
|
|
return NULL;
|
|
}
|
|
|
|
new_ctx->default_op_ctx = default_dupctx_fn(ctx->default_op_ctx);
|
|
if (new_ctx->default_op_ctx == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_dupctx_fn failed");
|
|
sk_prov_op_freectx(new_ctx);
|
|
return NULL;
|
|
}
|
|
|
|
sk_debug_op_ctx(ctx, "new_ctx: %p", new_ctx);
|
|
return new_ctx;
|
|
}
|
|
|
|
static int sk_prov_sign_op_get_ctx_params(void *vctx, OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_signature_get_ctx_params_fn *default_get_params_fn;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
const OSSL_PARAM *p;
|
|
|
|
if (ctx == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p", ctx);
|
|
for (p = params; p != NULL && p->key != NULL; p++)
|
|
sk_debug_op_ctx(ctx, "param: %s", p->key);
|
|
|
|
default_get_params_fn = (OSSL_FUNC_signature_get_ctx_params_fn *)
|
|
sk_prov_get_default_sign_func(ctx->provctx,
|
|
ctx->type, OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS);
|
|
|
|
/* default_get_params_fn is optional */
|
|
if (default_get_params_fn != NULL) {
|
|
if (!default_get_params_fn(ctx->default_op_ctx, params)) {
|
|
put_error_op_ctx(ctx,
|
|
SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_get_params_fn failed");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int sk_prov_sign_op_set_ctx_params(void *vctx, const OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_signature_set_ctx_params_fn *default_set_params_fn;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
const OSSL_PARAM *p;
|
|
|
|
if (ctx == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p", ctx);
|
|
for (p = params; p != NULL && p->key != NULL; p++)
|
|
sk_debug_op_ctx(ctx, "param: %s", p->key);
|
|
|
|
#ifdef OSSL_SIGNATURE_PARAM_NONCE_TYPE
|
|
/* OSSL_SIGNATURE_PARAM_NONCE_TYPE is used for EC sign ops only */
|
|
if (!sk_prov_check_uint_param(params, OSSL_SIGNATURE_PARAM_NONCE_TYPE,
|
|
ctx->key, EVP_PKEY_EC, 0)) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_INVALID_PARAM,
|
|
"Deterministic signature is not supported");
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
default_set_params_fn = (OSSL_FUNC_signature_set_ctx_params_fn *)
|
|
sk_prov_get_default_sign_func(ctx->provctx,
|
|
ctx->type, OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS);
|
|
|
|
/* default_set_params_fn is optional */
|
|
if (default_set_params_fn != NULL) {
|
|
if (!default_set_params_fn(ctx->default_op_ctx, params)) {
|
|
put_error_op_ctx(ctx,
|
|
SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_set_params_fn failed");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_sign_op_gettable_ctx_params(
|
|
struct sk_prov_op_ctx *ctx,
|
|
struct sk_prov_ctx *provctx, int pkey_type)
|
|
{
|
|
OSSL_FUNC_signature_gettable_ctx_params_fn *default_gettable_params_fn;
|
|
const OSSL_PARAM *params = NULL, *p;
|
|
|
|
if (ctx == NULL || provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "pkey_type: %d", pkey_type);
|
|
|
|
default_gettable_params_fn =
|
|
(OSSL_FUNC_signature_gettable_ctx_params_fn *)
|
|
sk_prov_get_default_sign_func(provctx, pkey_type,
|
|
OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS);
|
|
|
|
/* default_gettable_params_fn is optional */
|
|
if (default_gettable_params_fn != NULL)
|
|
params = default_gettable_params_fn(ctx->default_op_ctx,
|
|
provctx->default_provctx);
|
|
|
|
for (p = params; p != NULL && p->key != NULL; p++)
|
|
sk_debug_ctx(provctx, "param: %s", p->key);
|
|
|
|
return params;
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_sign_op_settable_ctx_params(
|
|
struct sk_prov_op_ctx *ctx,
|
|
struct sk_prov_ctx *provctx, int pkey_type)
|
|
{
|
|
OSSL_FUNC_signature_settable_ctx_params_fn *default_settable_params_fn;
|
|
const OSSL_PARAM *params = NULL, *p;
|
|
|
|
if (ctx == NULL || provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "pkey_type: %d", pkey_type);
|
|
|
|
default_settable_params_fn =
|
|
(OSSL_FUNC_signature_settable_ctx_params_fn *)
|
|
sk_prov_get_default_sign_func(provctx, pkey_type,
|
|
OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS);
|
|
|
|
/* default_settable_params_fn is optional */
|
|
if (default_settable_params_fn != NULL)
|
|
params = default_settable_params_fn(ctx->default_op_ctx,
|
|
provctx->default_provctx);
|
|
|
|
for (p = params; p != NULL && p->key != NULL; p++)
|
|
sk_debug_ctx(provctx, "param: %s", p->key);
|
|
|
|
return params;
|
|
}
|
|
|
|
static int sk_prov_sign_op_get_ctx_md_params(void *vctx, OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_signature_get_ctx_md_params_fn *default_get_md_params_fn;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
const OSSL_PARAM *p;
|
|
|
|
if (ctx == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p", ctx);
|
|
for (p = params; p != NULL && p->key != NULL; p++)
|
|
sk_debug_op_ctx(ctx, "param: %s", p->key);
|
|
|
|
default_get_md_params_fn = (OSSL_FUNC_signature_get_ctx_md_params_fn *)
|
|
sk_prov_get_default_sign_func(ctx->provctx,
|
|
ctx->type,
|
|
OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS);
|
|
|
|
/* default_get_md_params_fn is optional */
|
|
if (default_get_md_params_fn != NULL) {
|
|
if (!default_get_md_params_fn(ctx->default_op_ctx, params)) {
|
|
put_error_op_ctx(ctx,
|
|
SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_get_md_params_fn failed");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int sk_prov_sign_op_set_ctx_md_params(void *vctx,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_signature_set_ctx_md_params_fn *default_set_md_params_fn;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
const OSSL_PARAM *p;
|
|
|
|
if (ctx == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p", ctx);
|
|
for (p = params; p != NULL && p->key != NULL; p++)
|
|
sk_debug_op_ctx(ctx, "param: %s", p->key);
|
|
|
|
default_set_md_params_fn = (OSSL_FUNC_signature_set_ctx_md_params_fn *)
|
|
sk_prov_get_default_sign_func(ctx->provctx,
|
|
ctx->type,
|
|
OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS);
|
|
|
|
/* default_set_md_params_fn is optional */
|
|
if (default_set_md_params_fn != NULL) {
|
|
if (!default_set_md_params_fn(ctx->default_op_ctx, params)) {
|
|
put_error_op_ctx(ctx,
|
|
SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_set_md_params_fn failed");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/* Also set parameters in own MD context */
|
|
if (ctx->mdctx)
|
|
return EVP_MD_CTX_set_params(ctx->mdctx, params);
|
|
|
|
return 1;
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_sign_op_gettable_ctx_md_params(
|
|
struct sk_prov_op_ctx *ctx, int pkey_type)
|
|
{
|
|
OSSL_FUNC_signature_gettable_ctx_md_params_fn
|
|
*default_gettable_md_params_fn;
|
|
const OSSL_PARAM *params = NULL, *p;
|
|
|
|
if (ctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_op_ctx(ctx, "pkey_type: %d", pkey_type);
|
|
|
|
default_gettable_md_params_fn =
|
|
(OSSL_FUNC_signature_gettable_ctx_md_params_fn *)
|
|
sk_prov_get_default_sign_func(ctx->provctx, pkey_type,
|
|
OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS);
|
|
|
|
/* default_gettable_params_fn is optional */
|
|
if (default_gettable_md_params_fn != NULL)
|
|
params = default_gettable_md_params_fn(ctx->default_op_ctx);
|
|
|
|
for (p = params; p != NULL && p->key != NULL; p++)
|
|
sk_debug_op_ctx(ctx, "param: %s", p->key);
|
|
|
|
return params;
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_sign_op_settable_ctx_md_params(
|
|
struct sk_prov_op_ctx *ctx, int pkey_type)
|
|
{
|
|
OSSL_FUNC_signature_settable_ctx_md_params_fn
|
|
*default_settable_md_params_fn;
|
|
const OSSL_PARAM *params = NULL, *p;
|
|
|
|
if (ctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_op_ctx(ctx, "pkey_type: %d", pkey_type);
|
|
|
|
default_settable_md_params_fn =
|
|
(OSSL_FUNC_signature_settable_ctx_md_params_fn *)
|
|
sk_prov_get_default_sign_func(ctx->provctx, pkey_type,
|
|
OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS);
|
|
|
|
/* default_settable_md_params_fn is optional */
|
|
if (default_settable_md_params_fn != NULL)
|
|
params = default_settable_md_params_fn(ctx->default_op_ctx);
|
|
|
|
for (p = params; p != NULL && p->key != NULL; p++)
|
|
sk_debug_op_ctx(ctx, "param: %s", p->key);
|
|
|
|
return params;
|
|
}
|
|
|
|
static EVP_MD *sk_prov_sign_op_get_md(struct sk_prov_op_ctx *ctx)
|
|
{
|
|
char mdprops[256], mdname[50];
|
|
OSSL_PARAM ctx_params[] = {
|
|
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST,
|
|
&mdname, sizeof(mdname)),
|
|
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PROPERTIES,
|
|
&mdprops, sizeof(mdprops)),
|
|
OSSL_PARAM_END
|
|
};
|
|
EVP_MD *md;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p", ctx);
|
|
|
|
if (!sk_prov_sign_op_get_ctx_params(ctx, ctx_params) ||
|
|
!OSSL_PARAM_modified(&ctx_params[0]) ||
|
|
!OSSL_PARAM_modified(&ctx_params[1])) {
|
|
sk_debug_op_ctx(ctx, "sk_prov_sign_op_get_ctx_params failed");
|
|
if (ctx->md != NULL) {
|
|
sk_debug_op_ctx(ctx, "use digest from context: %s",
|
|
EVP_MD_name(ctx->md));
|
|
EVP_MD_up_ref(ctx->md);
|
|
return ctx->md;
|
|
}
|
|
|
|
sk_debug_op_ctx(ctx, "use default");
|
|
strcpy(mdname, SK_PROV_RSA_DEFAULT_MD);
|
|
strcpy(mdprops, "");
|
|
}
|
|
|
|
md = EVP_MD_fetch((OSSL_LIB_CTX *)ctx->provctx->c_get_libctx(
|
|
ctx->provctx->handle),
|
|
mdname, mdprops[0] != '\0' ? mdprops : ctx->propq);
|
|
if (md == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_MISSING_PARAMETER,
|
|
"EVP_MD_fetch failed to fetch '%s' using "
|
|
"property query '%s'", mdname,
|
|
mdprops[0] != '\0' ? mdprops :
|
|
ctx->propq != NULL ? ctx->propq : "");
|
|
return NULL;
|
|
}
|
|
|
|
sk_debug_op_ctx(ctx, "md: %s", EVP_MD_name(md));
|
|
return md;
|
|
}
|
|
|
|
static EVP_MD *sk_prov_sign_op_get_mgf_md(struct sk_prov_op_ctx *ctx)
|
|
{
|
|
char mdprops[256], mdname[50];
|
|
OSSL_PARAM ctx_params[] = {
|
|
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_DIGEST,
|
|
&mdname, sizeof(mdname)),
|
|
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES,
|
|
&mdprops, sizeof(mdprops)),
|
|
OSSL_PARAM_END
|
|
};
|
|
EVP_MD *md;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p", ctx);
|
|
|
|
if (!sk_prov_sign_op_get_ctx_params(ctx, ctx_params) ||
|
|
!OSSL_PARAM_modified(&ctx_params[0]) ||
|
|
!OSSL_PARAM_modified(&ctx_params[1])) {
|
|
sk_debug_op_ctx(ctx, "sk_prov_sign_op_get_ctx_params failed, "
|
|
"using signature digest");
|
|
return sk_prov_sign_op_get_md(ctx);
|
|
}
|
|
|
|
md = EVP_MD_fetch((OSSL_LIB_CTX *)ctx->provctx->c_get_libctx(
|
|
ctx->provctx->handle),
|
|
mdname, mdprops[0] != '\0' ? mdprops : ctx->propq);
|
|
if (md == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_MISSING_PARAMETER,
|
|
"EVP_MD_fetch failed to fetch '%s' using "
|
|
"property query '%s'", mdname,
|
|
mdprops[0] != '\0' ? mdprops :
|
|
ctx->propq != NULL ? ctx->propq : "");
|
|
return NULL;
|
|
}
|
|
|
|
sk_debug_op_ctx(ctx, "md: %s", EVP_MD_name(md));
|
|
return md;
|
|
}
|
|
|
|
static int sk_prov_sign_op_get_padding(struct sk_prov_op_ctx *ctx)
|
|
{
|
|
char padding[50];
|
|
OSSL_PARAM ctx_params[] = {
|
|
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_PAD_MODE,
|
|
&padding, sizeof(padding)),
|
|
OSSL_PARAM_END
|
|
};
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p", ctx);
|
|
|
|
if (!sk_prov_sign_op_get_ctx_params(ctx, ctx_params) ||
|
|
!OSSL_PARAM_modified(&ctx_params[0])) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_MISSING_PARAMETER,
|
|
"sk_prov_sign_op_get_ctx_params failed to "
|
|
"get OSSL_PKEY_PARAM_PAD_MODE");
|
|
return -1;
|
|
}
|
|
|
|
sk_debug_op_ctx(ctx, "padding: %s", padding);
|
|
return sk_prov_parse_padding(padding);
|
|
}
|
|
|
|
static int sk_prov_sign_op_get_pss_saltlen(struct sk_prov_op_ctx *ctx,
|
|
struct sk_prov_key *key,
|
|
EVP_MD *mgf_md)
|
|
{
|
|
char saltlen[50];
|
|
OSSL_PARAM ctx_params[] = {
|
|
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN,
|
|
&saltlen, sizeof(saltlen)),
|
|
OSSL_PARAM_END
|
|
};
|
|
int salt_len, rsa_bits, max_saltlen;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p", ctx);
|
|
|
|
if (!sk_prov_sign_op_get_ctx_params(ctx, ctx_params) ||
|
|
!OSSL_PARAM_modified(&ctx_params[0])) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_MISSING_PARAMETER,
|
|
"sk_prov_sign_op_get_ctx_params failed to "
|
|
"get OSSL_SIGNATURE_PARAM_PSS_SALTLEN");
|
|
return -1;
|
|
}
|
|
|
|
sk_debug_op_ctx(ctx, "saltlen: %s", saltlen);
|
|
|
|
rsa_bits = sk_prov_keymgmt_get_bits(key);
|
|
if (rsa_bits <= 0) {
|
|
sk_debug_op_ctx(ctx,
|
|
"ERROR: sk_prov_keymgmt_get_bits failed");
|
|
return -1;
|
|
}
|
|
|
|
max_saltlen = rsa_bits / 8 - EVP_MD_size(mgf_md) - 2;
|
|
|
|
if (strcmp(saltlen, OSSL_PKEY_RSA_PSS_SALT_LEN_DIGEST) == 0)
|
|
salt_len = EVP_MD_size(mgf_md);
|
|
else if (strcmp(saltlen, OSSL_PKEY_RSA_PSS_SALT_LEN_MAX) == 0)
|
|
salt_len = max_saltlen;
|
|
else if (strcmp(saltlen, OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO) == 0)
|
|
salt_len = max_saltlen;
|
|
#ifdef OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO_DIGEST_MAX
|
|
else if (strcmp(saltlen,
|
|
OSSL_PKEY_RSA_PSS_SALT_LEN_AUTO_DIGEST_MAX) == 0)
|
|
salt_len = MIN(max_saltlen, EVP_MD_size(mgf_md));
|
|
#endif
|
|
else
|
|
salt_len = atoi(saltlen);
|
|
|
|
if (salt_len > max_saltlen || salt_len < 0) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_INVALID_SALTLEN,
|
|
"invalid salt len: %d", saltlen);
|
|
return -1;
|
|
}
|
|
|
|
sk_debug_op_ctx(ctx, "salt_len: %d", salt_len);
|
|
return salt_len;
|
|
}
|
|
|
|
static int sk_prov_sign_op_sign_init(void *vctx, void *vkey,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_signature_sign_init_fn *default_sign_init_fn;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
struct sk_prov_key *key = vkey;
|
|
const OSSL_PARAM *p;
|
|
|
|
if (ctx == NULL || key == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p key: %p", ctx, key);
|
|
for (p = params; p != NULL && p->key != NULL; p++)
|
|
sk_debug_op_ctx(ctx, "param: %s", p->key);
|
|
|
|
#ifdef OSSL_SIGNATURE_PARAM_NONCE_TYPE
|
|
/* OSSL_SIGNATURE_PARAM_NONCE_TYPE is used for EC sign ops only */
|
|
if (!sk_prov_check_uint_param(params, OSSL_SIGNATURE_PARAM_NONCE_TYPE,
|
|
key, EVP_PKEY_EC, 0)) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_INVALID_PARAM,
|
|
"Deterministic signature is not supported");
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
default_sign_init_fn = (OSSL_FUNC_signature_sign_init_fn *)
|
|
sk_prov_get_default_sign_func(ctx->provctx,
|
|
ctx->type,
|
|
OSSL_FUNC_SIGNATURE_SIGN_INIT);
|
|
if (default_sign_init_fn == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default sign_init_fn");
|
|
return 0;
|
|
}
|
|
|
|
if (!sk_prov_op_init(ctx, key, EVP_PKEY_OP_SIGN)) {
|
|
sk_debug_op_ctx(ctx, "ERROR: sk_prov_op_init failed");
|
|
return 0;
|
|
}
|
|
|
|
if (!default_sign_init_fn(ctx->default_op_ctx, key->default_key,
|
|
params)) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_sign_init_fn failed");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int sk_prov_sign_op_verify_init(void *vctx, void *vkey,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_signature_verify_init_fn *default_verify_init_fn;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
struct sk_prov_key *key = vkey;
|
|
const OSSL_PARAM *p;
|
|
|
|
if (ctx == NULL || key == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p key: %p", ctx, key);
|
|
for (p = params; p != NULL && p->key != NULL; p++)
|
|
sk_debug_op_ctx(ctx, "param: %s", p->key);
|
|
|
|
default_verify_init_fn = (OSSL_FUNC_signature_verify_init_fn *)
|
|
sk_prov_get_default_sign_func(ctx->provctx,
|
|
ctx->type, OSSL_FUNC_SIGNATURE_VERIFY_INIT);
|
|
if (default_verify_init_fn == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default verify_init_fn");
|
|
return 0;
|
|
}
|
|
|
|
if (!sk_prov_op_init(ctx, key, EVP_PKEY_OP_VERIFY)) {
|
|
sk_debug_op_ctx(ctx, "ERROR: sk_prov_op_init failed");
|
|
return 0;
|
|
}
|
|
|
|
if (!default_verify_init_fn(ctx->default_op_ctx, key->default_key,
|
|
params)) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_verify_init_fn failed");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int sk_prov_sign_op_verify_recover_init(void *vctx, void *vkey,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_signature_verify_recover_init_fn
|
|
*default_verify_recover_init_fn;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
struct sk_prov_key *key = vkey;
|
|
const OSSL_PARAM *p;
|
|
|
|
if (ctx == NULL || key == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p key: %p", ctx, key);
|
|
for (p = params; p != NULL && p->key != NULL; p++)
|
|
sk_debug_op_ctx(ctx, "param: %s", p->key);
|
|
|
|
default_verify_recover_init_fn =
|
|
(OSSL_FUNC_signature_verify_recover_init_fn *)
|
|
sk_prov_get_default_sign_func(ctx->provctx,
|
|
ctx->type,
|
|
OSSL_FUNC_SIGNATURE_VERIFY_RECOVER_INIT);
|
|
if (default_verify_recover_init_fn == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default verify_recover_init_fn");
|
|
return 0;
|
|
}
|
|
|
|
if (!sk_prov_op_init(ctx, key, EVP_PKEY_OP_VERIFYRECOVER)) {
|
|
sk_debug_op_ctx(ctx, "ERROR: sk_prov_op_init failed");
|
|
return 0;
|
|
}
|
|
|
|
if (!default_verify_recover_init_fn(ctx->default_op_ctx,
|
|
key->default_key,
|
|
params)) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_verify_recover_init_fn failed");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int sk_prov_sign_op_sign(struct sk_prov_op_ctx *ctx,
|
|
unsigned char *sig, size_t *siglen,
|
|
size_t sigsize,
|
|
const unsigned char *tbs, size_t tbslen)
|
|
{
|
|
OSSL_FUNC_signature_sign_fn *default_sign_fn;
|
|
|
|
if (ctx == NULL || tbs == NULL || siglen == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p key: %p tbslen: %lu sigsize: %lu",
|
|
ctx, ctx->key, tbslen, sigsize);
|
|
|
|
default_sign_fn = (OSSL_FUNC_signature_sign_fn *)
|
|
sk_prov_get_default_sign_func(ctx->provctx,
|
|
ctx->type, OSSL_FUNC_SIGNATURE_SIGN);
|
|
if (default_sign_fn == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default sign_fn");
|
|
return 0;
|
|
}
|
|
|
|
if (!default_sign_fn(ctx->default_op_ctx, sig, siglen, sigsize,
|
|
tbs, tbslen)) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_sign_fn failed");
|
|
return 0;
|
|
}
|
|
|
|
sk_debug_op_ctx(ctx, "siglen: %lu", *siglen);
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int sk_prov_sign_op_verify(void *vctx,
|
|
const unsigned char *sig, size_t siglen,
|
|
const unsigned char *tbs, size_t tbslen)
|
|
{
|
|
OSSL_FUNC_signature_verify_fn *default_verify_fn;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
|
|
if (ctx == NULL || tbs == NULL || sig == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p key: %p tbslen: %lu siglen: %lu",
|
|
ctx, ctx->key, tbslen, siglen);
|
|
|
|
default_verify_fn = (OSSL_FUNC_signature_verify_fn *)
|
|
sk_prov_get_default_sign_func(ctx->provctx,
|
|
ctx->type, OSSL_FUNC_SIGNATURE_VERIFY);
|
|
if (default_verify_fn == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default verify_fn");
|
|
return 0;
|
|
}
|
|
|
|
if (!default_verify_fn(ctx->default_op_ctx, sig, siglen, tbs, tbslen)) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_verify_fn failed");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int sk_prov_sign_op_verify_recover(void *vctx,
|
|
unsigned char *rout, size_t *routlen,
|
|
size_t routsize,
|
|
const unsigned char *sig,
|
|
size_t siglen)
|
|
{
|
|
OSSL_FUNC_signature_verify_recover_fn *default_verify_recover_fn;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
|
|
if (ctx == NULL || routlen == NULL || sig == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(ctx,
|
|
"ctx: %p key: %p routsize: %lu siglen: %lu",
|
|
ctx, ctx->key, routsize, siglen);
|
|
|
|
default_verify_recover_fn = (OSSL_FUNC_signature_verify_recover_fn *)
|
|
sk_prov_get_default_sign_func(ctx->provctx,
|
|
ctx->type, OSSL_FUNC_SIGNATURE_VERIFY_RECOVER);
|
|
if (default_verify_recover_fn == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default verify_recover_fn");
|
|
return 0;
|
|
}
|
|
|
|
if (!default_verify_recover_fn(ctx->default_op_ctx, rout, routlen,
|
|
routsize, sig, siglen)) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_verify_recover_fn failed");
|
|
return 0;
|
|
}
|
|
|
|
sk_debug_op_ctx(ctx, "routlen: %lu", *routlen);
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int sk_prov_sign_op_digest_sign_init(struct sk_prov_op_ctx *ctx,
|
|
const char *mdname,
|
|
struct sk_prov_key *key,
|
|
const OSSL_PARAM params[],
|
|
OSSL_FUNC_signature_sign_fn *sign_fn)
|
|
{
|
|
OSSL_FUNC_signature_digest_sign_init_fn *default_digest_sign_init_fn;
|
|
const OSSL_PARAM *p;
|
|
|
|
if (ctx == NULL || key == NULL || sign_fn == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p mdname: %s key: %p", ctx,
|
|
mdname != NULL ? mdname : "", key);
|
|
for (p = params; p != NULL && p->key != NULL; p++)
|
|
sk_debug_op_ctx(ctx, "param: %s", p->key);
|
|
|
|
#ifdef OSSL_SIGNATURE_PARAM_NONCE_TYPE
|
|
/* OSSL_SIGNATURE_PARAM_NONCE_TYPE is used for EC sign ops only */
|
|
if (!sk_prov_check_uint_param(params, OSSL_SIGNATURE_PARAM_NONCE_TYPE,
|
|
key, EVP_PKEY_EC, 0)) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_INVALID_PARAM,
|
|
"Deterministic signature is not supported");
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
default_digest_sign_init_fn =
|
|
(OSSL_FUNC_signature_digest_sign_init_fn *)
|
|
sk_prov_get_default_sign_func(ctx->provctx,
|
|
ctx->type,
|
|
OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT);
|
|
if (default_digest_sign_init_fn == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default digest_sign_init_fn");
|
|
return 0;
|
|
}
|
|
|
|
if (!sk_prov_op_init(ctx, key, EVP_PKEY_OP_SIGN)) {
|
|
sk_debug_op_ctx(ctx, "ERROR: sk_prov_op_init failed");
|
|
return 0;
|
|
}
|
|
|
|
if (!default_digest_sign_init_fn(ctx->default_op_ctx, mdname,
|
|
key->default_key, params)) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_digest_sign_init_fn failed");
|
|
return 0;
|
|
}
|
|
|
|
/* For clear key, the default provider has already handled it */
|
|
if (ctx->key->secure_key == NULL)
|
|
return 1;
|
|
|
|
ctx->sign_fn = sign_fn;
|
|
|
|
if (ctx->mdctx != NULL)
|
|
EVP_MD_CTX_free(ctx->mdctx);
|
|
ctx->mdctx = EVP_MD_CTX_new();
|
|
if (ctx->mdctx == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_MALLOC_FAILED,
|
|
"EVP_MD_CTX_new failed");
|
|
return 0;
|
|
}
|
|
|
|
if (ctx->md != NULL)
|
|
EVP_MD_free(ctx->md);
|
|
if (mdname != NULL)
|
|
ctx->md = EVP_MD_fetch(
|
|
(OSSL_LIB_CTX *)ctx->provctx->c_get_libctx(
|
|
ctx->provctx->handle),
|
|
mdname, ctx->propq);
|
|
else
|
|
ctx->md = sk_prov_sign_op_get_md(ctx);
|
|
if (ctx->md == NULL) {
|
|
sk_debug_op_ctx(ctx, "ERROR: Failed to get digest sign digest");
|
|
EVP_MD_CTX_free(ctx->mdctx);
|
|
ctx->mdctx = NULL;
|
|
return 0;
|
|
}
|
|
|
|
return EVP_DigestInit_ex2(ctx->mdctx, ctx->md, params);
|
|
}
|
|
|
|
static int sk_prov_sign_op_digest_sign_update(void *vctx,
|
|
const unsigned char *data,
|
|
size_t datalen)
|
|
{
|
|
OSSL_FUNC_signature_digest_sign_update_fn
|
|
*default_digest_sign_update_fn;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
|
|
if (ctx == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p key: %p datalen: %lu", ctx, ctx->key,
|
|
datalen);
|
|
|
|
if (ctx->key == NULL || ctx->operation != EVP_PKEY_OP_SIGN) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_OPRATION_NOT_INITIALIZED,
|
|
"digest sign operation not initialized");
|
|
return 0;
|
|
}
|
|
|
|
/* For secure key, don't pass it to the default provider */
|
|
if (ctx->key->secure_key != NULL)
|
|
goto secure_key;
|
|
|
|
default_digest_sign_update_fn =
|
|
(OSSL_FUNC_signature_digest_sign_update_fn *)
|
|
sk_prov_get_default_sign_func(ctx->provctx,
|
|
ctx->type,
|
|
OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE);
|
|
if (default_digest_sign_update_fn == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default digest_sign_update_fn");
|
|
return 0;
|
|
}
|
|
|
|
if (!default_digest_sign_update_fn(ctx->default_op_ctx, data,
|
|
datalen)) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_digest_sign_update_fn failed");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
|
|
secure_key:
|
|
if (ctx->mdctx == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_OPRATION_NOT_INITIALIZED,
|
|
"digest sign operation not initialized");
|
|
return 0;
|
|
}
|
|
|
|
return EVP_DigestUpdate(ctx->mdctx, data, datalen);
|
|
}
|
|
|
|
static int sk_prov_sign_op_digest_sign_final(void *vctx,
|
|
unsigned char *sig,
|
|
size_t *siglen, size_t sigsize)
|
|
{
|
|
OSSL_FUNC_signature_digest_sign_final_fn *default_digest_sign_final_fn;
|
|
unsigned char digest[EVP_MAX_MD_SIZE];
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
unsigned int dlen = 0;
|
|
|
|
if (ctx == NULL || siglen == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p key: %p sigsize: %lu", ctx, ctx->key,
|
|
sigsize);
|
|
|
|
if (ctx->key == NULL || ctx->operation != EVP_PKEY_OP_SIGN) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_OPRATION_NOT_INITIALIZED,
|
|
"digest sign operation not initialized");
|
|
return 0;
|
|
}
|
|
|
|
/* For secure key, don't pass it to the default provider */
|
|
if (ctx->key->secure_key != NULL)
|
|
goto secure_key;
|
|
|
|
default_digest_sign_final_fn =
|
|
(OSSL_FUNC_signature_digest_sign_final_fn *)
|
|
sk_prov_get_default_sign_func(ctx->provctx,
|
|
ctx->type,
|
|
OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL);
|
|
if (default_digest_sign_final_fn == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default digest_sign_final_fn");
|
|
return 0;
|
|
}
|
|
|
|
if (!default_digest_sign_final_fn(ctx->default_op_ctx, sig, siglen,
|
|
sigsize)) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_digest_sign_final_fn failed");
|
|
return 0;
|
|
}
|
|
|
|
sk_debug_op_ctx(ctx, "siglen: %lu", *siglen);
|
|
return 1;
|
|
|
|
secure_key:
|
|
if (ctx->mdctx == NULL || ctx->sign_fn == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_OPRATION_NOT_INITIALIZED,
|
|
"digest sign operation not initialized");
|
|
return 0;
|
|
}
|
|
|
|
if (sig != NULL) {
|
|
if (!EVP_DigestFinal_ex(ctx->mdctx, digest, &dlen)) {
|
|
sk_debug_op_ctx(ctx,
|
|
"ERROR: EVP_DigestFinal_ex failed");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if (!ctx->sign_fn(ctx, sig, siglen, sigsize, digest, (size_t)dlen)) {
|
|
sk_debug_op_ctx(ctx, "ERROR: sign_fn failed");
|
|
return 0;
|
|
}
|
|
|
|
sk_debug_op_ctx(ctx, "siglen: %lu", *siglen);
|
|
return 1;
|
|
}
|
|
|
|
static int sk_prov_sign_op_digest_verify_init(void *vctx,
|
|
const char *mdname,
|
|
void *vkey,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_signature_digest_verify_init_fn
|
|
*default_digest_verify_init_fn;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
struct sk_prov_key *key = vkey;
|
|
const OSSL_PARAM *p;
|
|
|
|
if (ctx == NULL || key == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p mdname: %s key: %p", ctx,
|
|
mdname != NULL ? mdname : "", key);
|
|
for (p = params; p != NULL && p->key != NULL; p++)
|
|
sk_debug_op_ctx(ctx, "param: %s", p->key);
|
|
|
|
default_digest_verify_init_fn =
|
|
(OSSL_FUNC_signature_digest_verify_init_fn *)
|
|
sk_prov_get_default_sign_func(ctx->provctx,
|
|
ctx->type,
|
|
OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT);
|
|
if (default_digest_verify_init_fn == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default digest_verify_init_fn");
|
|
return 0;
|
|
}
|
|
|
|
if (!sk_prov_op_init(ctx, key, EVP_PKEY_OP_VERIFY)) {
|
|
sk_debug_op_ctx(ctx, "ERROR: sk_prov_op_init failed");
|
|
return 0;
|
|
}
|
|
|
|
if (!default_digest_verify_init_fn(ctx->default_op_ctx, mdname,
|
|
key->default_key, params)) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_digest_verify_init_fn failed");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int sk_prov_sign_op_digest_verify_update(void *vctx,
|
|
const unsigned char *data,
|
|
size_t datalen)
|
|
{
|
|
OSSL_FUNC_signature_digest_verify_update_fn
|
|
*default_digest_verify_update_fn;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
|
|
if (ctx == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p key: %p datalen: %lu", ctx, ctx->key,
|
|
datalen);
|
|
|
|
default_digest_verify_update_fn =
|
|
(OSSL_FUNC_signature_digest_verify_update_fn *)
|
|
sk_prov_get_default_sign_func(ctx->provctx, ctx->type,
|
|
OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE);
|
|
if (default_digest_verify_update_fn == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default digest_verify_update_fn");
|
|
return 0;
|
|
}
|
|
|
|
if (!default_digest_verify_update_fn(ctx->default_op_ctx,
|
|
data, datalen)) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_digest_verify_update_fn failed");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int sk_prov_sign_op_digest_verify_final(void *vctx,
|
|
const unsigned char *sig,
|
|
size_t siglen)
|
|
{
|
|
OSSL_FUNC_signature_digest_verify_final_fn
|
|
*default_digest_verify_final_fn;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
|
|
if (ctx == NULL || sig == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p key: %p siglen: %lu", ctx, ctx->key,
|
|
siglen);
|
|
|
|
default_digest_verify_final_fn =
|
|
(OSSL_FUNC_signature_digest_verify_final_fn *)
|
|
sk_prov_get_default_sign_func(ctx->provctx, ctx->type,
|
|
OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL);
|
|
if (default_digest_verify_final_fn == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default digest_verify_final_fn");
|
|
return 0;
|
|
}
|
|
|
|
if (!default_digest_verify_final_fn(ctx->default_op_ctx, sig, siglen)) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_digest_verify_final_fn failed");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static void sk_prov_keymgmt_upref(struct sk_prov_key *key)
|
|
{
|
|
sk_debug_key(key, "key: %p", key);
|
|
|
|
key->ref_count++;
|
|
|
|
sk_debug_key(key, "ref_count: %u", key->ref_count);
|
|
}
|
|
|
|
static unsigned int sk_prov_keymgmt_downref(struct sk_prov_key *key)
|
|
{
|
|
sk_debug_key(key, "key: %p ", key);
|
|
|
|
if (key->ref_count > 0)
|
|
key->ref_count--;
|
|
|
|
sk_debug_key(key, "ref_count: %u", key->ref_count);
|
|
|
|
return key->ref_count;
|
|
}
|
|
|
|
static struct sk_prov_key *sk_prov_keymgmt_new(struct sk_prov_ctx *provctx,
|
|
int type)
|
|
{
|
|
OSSL_FUNC_keymgmt_new_fn *default_new_fn;
|
|
struct sk_prov_key *key;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p type: %d", provctx,
|
|
type);
|
|
|
|
default_new_fn = (OSSL_FUNC_keymgmt_new_fn *)
|
|
sk_prov_get_default_keymgmt_func(provctx, type,
|
|
OSSL_FUNC_KEYMGMT_NEW);
|
|
if (default_new_fn == NULL) {
|
|
put_error_ctx(provctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default new_fn");
|
|
return NULL;
|
|
}
|
|
|
|
key = OPENSSL_zalloc(sizeof(struct sk_prov_key));
|
|
if (key == NULL) {
|
|
put_error_ctx(provctx, SK_PROV_ERR_MALLOC_FAILED,
|
|
"OPENSSL_zalloc failed");
|
|
return NULL;
|
|
}
|
|
|
|
key->provctx = provctx;
|
|
key->type = type;
|
|
|
|
key->default_key = default_new_fn(provctx->default_provctx);
|
|
if (key->default_key == NULL) {
|
|
put_error_ctx(provctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_new_fn failed");
|
|
OPENSSL_free(key);
|
|
return NULL;
|
|
}
|
|
|
|
sk_prov_keymgmt_upref(key);
|
|
|
|
sk_debug_ctx(provctx, "key: %p", key);
|
|
|
|
return key;
|
|
}
|
|
|
|
static void sk_prov_keymgmt_free(void *vkey)
|
|
{
|
|
OSSL_FUNC_keymgmt_free_fn *default_free_fn;
|
|
struct sk_prov_key *key = vkey;
|
|
|
|
if (key == NULL)
|
|
return;
|
|
|
|
sk_debug_key(key, "key: %p", key);
|
|
|
|
if (sk_prov_keymgmt_downref(key) > 0)
|
|
return;
|
|
|
|
sk_debug_key(key, "free key: %p", key);
|
|
|
|
default_free_fn = (OSSL_FUNC_keymgmt_free_fn *)
|
|
sk_prov_get_default_keymgmt_func(key->provctx,
|
|
key->type, OSSL_FUNC_KEYMGMT_FREE);
|
|
if (default_free_fn == NULL)
|
|
sk_debug_key(key, "no default free_fn");
|
|
else
|
|
default_free_fn(key->default_key);
|
|
|
|
if (key->secure_key != NULL)
|
|
OPENSSL_free(key->secure_key);
|
|
OPENSSL_free(key);
|
|
}
|
|
|
|
static int sk_prov_keymgmt_match(const void *vkey1, const void *vkey2,
|
|
int selection)
|
|
{
|
|
OSSL_FUNC_keymgmt_match_fn *default_match_fn;
|
|
const struct sk_prov_key *key1 = vkey1;
|
|
const struct sk_prov_key *key2 = vkey2;
|
|
|
|
if (key1 == NULL || key2 == NULL)
|
|
return 0;
|
|
|
|
sk_debug_key(key1, "key1: %p key2: %p", key1, key2);
|
|
|
|
default_match_fn = (OSSL_FUNC_keymgmt_match_fn *)
|
|
sk_prov_get_default_keymgmt_func(key1->provctx,
|
|
key1->type, OSSL_FUNC_KEYMGMT_MATCH);
|
|
if (default_match_fn == NULL) {
|
|
put_error_key(key1, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default match_fn");
|
|
return 0;
|
|
}
|
|
|
|
if (key1->type != key2->type)
|
|
return 0;
|
|
|
|
if (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) {
|
|
/* match everything except private key */
|
|
return default_match_fn(key1->default_key, key2->default_key,
|
|
selection &
|
|
(~OSSL_KEYMGMT_SELECT_PRIVATE_KEY));
|
|
}
|
|
|
|
if (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) {
|
|
if (key1->secure_key_size != key2->secure_key_size)
|
|
return 0;
|
|
if (key1->secure_key_size > 0) {
|
|
if (memcmp(key1->secure_key, key2->secure_key,
|
|
key1->secure_key_size) != 0)
|
|
return 0;
|
|
selection &= (~OSSL_KEYMGMT_SELECT_PRIVATE_KEY);
|
|
}
|
|
}
|
|
|
|
return default_match_fn(key1->default_key, key2->default_key,
|
|
selection);
|
|
}
|
|
|
|
static int sk_prov_keymgmt_validate(const void *vkey,
|
|
int selection, int checktype)
|
|
{
|
|
OSSL_FUNC_keymgmt_validate_fn *default_validate_fn;
|
|
const struct sk_prov_key *key = vkey;
|
|
int default_selection = selection;
|
|
|
|
if (key == NULL)
|
|
return 0;
|
|
|
|
sk_debug_key(key, "key: %p selection: %x checktype: %x", key,
|
|
selection, checktype);
|
|
|
|
default_validate_fn = (OSSL_FUNC_keymgmt_validate_fn *)
|
|
sk_prov_get_default_keymgmt_func(key->provctx,
|
|
key->type, OSSL_FUNC_KEYMGMT_VALIDATE);
|
|
if (default_validate_fn == NULL) {
|
|
put_error_key(key, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default validate_fn");
|
|
return 0;
|
|
}
|
|
|
|
/* A secure key doesn't have the private parts in the default key */
|
|
if (key->secure_key != NULL)
|
|
default_selection &= (~OSSL_KEYMGMT_SELECT_PRIVATE_KEY);
|
|
|
|
return default_validate_fn(key->default_key, default_selection,
|
|
checktype);
|
|
}
|
|
|
|
static int sk_prov_keymgmt_get_params(void *vkey, OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_keymgmt_get_params_fn *default_get_params_fn;
|
|
struct sk_prov_key *key = vkey;
|
|
OSSL_PARAM *p;
|
|
|
|
if (key == NULL)
|
|
return 0;
|
|
|
|
sk_debug_key(key, "key: %p", key);
|
|
for (p = params; p != NULL && p->key != NULL; p++)
|
|
sk_debug_key(key, "param: %s", p->key);
|
|
|
|
default_get_params_fn = (OSSL_FUNC_keymgmt_get_params_fn *)
|
|
sk_prov_get_default_keymgmt_func(key->provctx,
|
|
key->type, OSSL_FUNC_KEYMGMT_GET_PARAMS);
|
|
|
|
/* default_get_params_fn is optional */
|
|
if (default_get_params_fn != NULL) {
|
|
if (!default_get_params_fn(key->default_key, params)) {
|
|
put_error_key(key, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_get_params_fn failed");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if (key->secure_key == NULL)
|
|
return 1;
|
|
|
|
p = OSSL_PARAM_locate(params, SK_PROV_PKEY_PARAM_SK_BLOB);
|
|
if (p != NULL && !OSSL_PARAM_set_octet_string(p, key->secure_key,
|
|
key->secure_key_size)) {
|
|
put_error_key(key, SK_PROV_ERR_INTERNAL_ERROR,
|
|
"OSSL_PARAM_set_octet_string failed");
|
|
return 0;
|
|
}
|
|
p = OSSL_PARAM_locate(params, SK_PROV_PKEY_PARAM_SK_FUNCS);
|
|
if (p != NULL && !OSSL_PARAM_set_octet_ptr(p, key->funcs,
|
|
sizeof(struct sk_funcs))) {
|
|
put_error_key(key, SK_PROV_ERR_INTERNAL_ERROR,
|
|
"OSSL_PARAM_set_octet_ptr failed");
|
|
return 0;
|
|
}
|
|
p = OSSL_PARAM_locate(params, SK_PROV_PKEY_PARAM_SK_PRIVATE);
|
|
if (p != NULL && !OSSL_PARAM_set_octet_ptr(p, key->private, 0)) {
|
|
put_error_key(key, SK_PROV_ERR_INTERNAL_ERROR,
|
|
"OSSL_PARAM_set_octet_ptr failed");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
static int sk_prov_keymgmt_set_params(void *vkey, const OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_keymgmt_set_params_fn *default_set_params_fn;
|
|
struct sk_prov_key *key = vkey;
|
|
const OSSL_PARAM *p;
|
|
size_t len;
|
|
|
|
if (key == NULL)
|
|
return 0;
|
|
|
|
sk_debug_key(key, "key: %p", key);
|
|
for (p = params; p != NULL && p->key != NULL; p++)
|
|
sk_debug_key(key, "param: %s", p->key);
|
|
|
|
default_set_params_fn = (OSSL_FUNC_keymgmt_set_params_fn *)
|
|
sk_prov_get_default_keymgmt_func(key->provctx,
|
|
key->type, OSSL_FUNC_KEYMGMT_SET_PARAMS);
|
|
|
|
/* default_set_params_fn is optional */
|
|
if (default_set_params_fn != NULL) {
|
|
if (!default_set_params_fn(key->default_key, params)) {
|
|
put_error_key(key, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_set_params_fn failed");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if (key->secure_key == NULL)
|
|
return 1;
|
|
|
|
p = OSSL_PARAM_locate_const(params, SK_PROV_PKEY_PARAM_SK_FUNCS);
|
|
if (p != NULL && !OSSL_PARAM_get_octet_string_ptr(p,
|
|
(const void **)&key->funcs, &len)) {
|
|
put_error_key(key, SK_PROV_ERR_INTERNAL_ERROR,
|
|
"OSSL_PARAM_get_octet_string_ptr failed");
|
|
return 0;
|
|
}
|
|
|
|
p = OSSL_PARAM_locate_const(params, SK_PROV_PKEY_PARAM_SK_PRIVATE);
|
|
if (p != NULL && !OSSL_PARAM_get_octet_string_ptr(p,
|
|
(const void **)&key->private, &len)) {
|
|
put_error_key(key, SK_PROV_ERR_INTERNAL_ERROR,
|
|
"OSSL_PARAM_get_octet_string_ptr failed");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
#define SK_PROV_SECURE_KEY_FUNC_PARMS \
|
|
OSSL_PARAM_octet_ptr(SK_PROV_PKEY_PARAM_SK_FUNCS, NULL, 0), \
|
|
OSSL_PARAM_octet_ptr(SK_PROV_PKEY_PARAM_SK_PRIVATE, NULL, 0)
|
|
|
|
#define SK_PROV_SECURE_KEY_PARMS \
|
|
OSSL_PARAM_octet_string(SK_PROV_PKEY_PARAM_SK_BLOB, NULL, 0), \
|
|
SK_PROV_SECURE_KEY_FUNC_PARMS
|
|
|
|
|
|
static const OSSL_PARAM sk_prov_key_settable_params[] = {
|
|
SK_PROV_SECURE_KEY_FUNC_PARMS,
|
|
OSSL_PARAM_END
|
|
};
|
|
|
|
static const OSSL_PARAM sk_prov_key_gettable_params[] = {
|
|
SK_PROV_SECURE_KEY_PARMS,
|
|
OSSL_PARAM_END
|
|
};
|
|
|
|
static const OSSL_PARAM *sk_prov_keymgmt_gettable_params(
|
|
struct sk_prov_ctx *provctx, int pkey_type)
|
|
{
|
|
OSSL_FUNC_keymgmt_gettable_params_fn *default_gettable_params_fn;
|
|
const OSSL_PARAM *default_parms = NULL, *params, *p;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "pkey_type: %d", pkey_type);
|
|
|
|
params = sk_prov_get_cached_params(provctx, pkey_type,
|
|
SK_CONF_CACHED_PARAMS_OP_KEY_GET, 0);
|
|
if (params != NULL) {
|
|
for (p = params; p != NULL && p->key != NULL; p++)
|
|
sk_debug_ctx(provctx, "param: %s", p->key);
|
|
return params;
|
|
}
|
|
|
|
default_gettable_params_fn = (OSSL_FUNC_keymgmt_gettable_params_fn *)
|
|
sk_prov_get_default_keymgmt_func(provctx, pkey_type,
|
|
OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS);
|
|
|
|
/* default_gettable_params_fn is optional */
|
|
if (default_gettable_params_fn != NULL)
|
|
default_parms =
|
|
default_gettable_params_fn(provctx->default_provctx);
|
|
|
|
return sk_prov_cached_params_build(provctx, pkey_type,
|
|
SK_CONF_CACHED_PARAMS_OP_KEY_GET, 0,
|
|
default_parms,
|
|
sk_prov_key_gettable_params);
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_keymgmt_settable_params(
|
|
struct sk_prov_ctx *provctx, int pkey_type)
|
|
{
|
|
OSSL_FUNC_keymgmt_settable_params_fn *default_settable_params_fn;
|
|
const OSSL_PARAM *default_parms = NULL, *params, *p;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "pkey_type: %d", pkey_type);
|
|
|
|
params = sk_prov_get_cached_params(provctx, pkey_type,
|
|
SK_CONF_CACHED_PARAMS_OP_KEY_SET, 0);
|
|
if (params != NULL) {
|
|
for (p = params; p != NULL && p->key != NULL; p++)
|
|
sk_debug_ctx(provctx, "param: %s", p->key);
|
|
return params;
|
|
}
|
|
|
|
default_settable_params_fn = (OSSL_FUNC_keymgmt_settable_params_fn *)
|
|
sk_prov_get_default_keymgmt_func(provctx, pkey_type,
|
|
OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS);
|
|
|
|
/* default_settable_params_fn is optional */
|
|
if (default_settable_params_fn != NULL)
|
|
default_parms =
|
|
default_settable_params_fn(provctx->default_provctx);
|
|
|
|
return sk_prov_cached_params_build(provctx, pkey_type,
|
|
SK_CONF_CACHED_PARAMS_OP_KEY_SET, 0,
|
|
default_parms,
|
|
sk_prov_key_settable_params);
|
|
}
|
|
|
|
static int sk_prov_keymgmt_has(const void *vkey, int selection)
|
|
{
|
|
OSSL_FUNC_keymgmt_has_fn *default_has_fn;
|
|
const struct sk_prov_key *key = vkey;
|
|
int default_selection = selection;
|
|
|
|
if (key == NULL)
|
|
return 0;
|
|
|
|
sk_debug_key(key, "key: %p selection: %x", key,
|
|
selection);
|
|
|
|
default_has_fn = (OSSL_FUNC_keymgmt_has_fn *)
|
|
sk_prov_get_default_keymgmt_func(key->provctx,
|
|
key->type, OSSL_FUNC_KEYMGMT_HAS);
|
|
if (default_has_fn == NULL) {
|
|
put_error_key(key, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default has_fn");
|
|
return 0;
|
|
}
|
|
|
|
/* A secure key doesn't have the private parts in the default key */
|
|
if (key->secure_key != NULL)
|
|
default_selection &= (~OSSL_KEYMGMT_SELECT_PRIVATE_KEY);
|
|
|
|
return default_has_fn(key->default_key, default_selection);
|
|
}
|
|
|
|
struct sk_prov_export_cb {
|
|
struct sk_prov_key *key;
|
|
OSSL_CALLBACK *param_callback;
|
|
void *cbarg;
|
|
};
|
|
|
|
static int sk_prov_keymgmt_export_cb(const OSSL_PARAM params[], void *arg)
|
|
{
|
|
struct sk_prov_export_cb *cb_data = arg;
|
|
OSSL_PARAM *np, *new_params;
|
|
struct sk_prov_key *key;
|
|
const OSSL_PARAM *p;
|
|
int rc, count, i;
|
|
|
|
if (cb_data == NULL)
|
|
return 0;
|
|
|
|
key = cb_data->key;
|
|
|
|
sk_debug_key(key, "key: %p", key);
|
|
|
|
for (count = 0, p = params; p != NULL && p->key != NULL; p++, count++)
|
|
;
|
|
count += 3 + 1; /* 3 addl params plus end marker */
|
|
|
|
new_params = OPENSSL_zalloc(count * sizeof(OSSL_PARAM));
|
|
if (new_params == NULL) {
|
|
put_error_key(key, SK_PROV_ERR_MALLOC_FAILED,
|
|
"OPENSSL_zalloc failed");
|
|
return 0;
|
|
}
|
|
|
|
for (i = 0, p = params; p != NULL && p->key != NULL; p++, i++) {
|
|
sk_debug_key(key, "param: key: %s", p->key);
|
|
new_params[i] = *p;
|
|
}
|
|
|
|
np = &new_params[i++];
|
|
*np = OSSL_PARAM_construct_octet_string(SK_PROV_PKEY_PARAM_SK_BLOB,
|
|
key->secure_key,
|
|
key->secure_key_size);
|
|
sk_debug_key(key, "param: key: %s", np->key);
|
|
|
|
np = &new_params[i++];
|
|
*np = OSSL_PARAM_construct_octet_ptr(SK_PROV_PKEY_PARAM_SK_FUNCS,
|
|
(void **)key->funcs,
|
|
sizeof(struct sk_funcs));
|
|
sk_debug_key(key, "param: key: %s", np->key);
|
|
|
|
np = &new_params[i++];
|
|
*np = OSSL_PARAM_construct_octet_ptr(SK_PROV_PKEY_PARAM_SK_PRIVATE,
|
|
key->private, 0);
|
|
sk_debug_key(key, "param: key: %s", np->key);
|
|
|
|
np = &new_params[i++];
|
|
*np = OSSL_PARAM_construct_end();
|
|
|
|
rc = cb_data->param_callback(new_params, cb_data->cbarg);
|
|
if (rc != 1)
|
|
sk_debug_key(key, "ERROR: param_callback failed");
|
|
|
|
OPENSSL_free(new_params);
|
|
|
|
return rc;
|
|
}
|
|
|
|
static int sk_prov_keymgmt_export(void *vkey, int selection,
|
|
OSSL_CALLBACK *param_callback, void *cbarg)
|
|
{
|
|
OSSL_FUNC_keymgmt_export_fn *default_export_fn;
|
|
struct sk_prov_export_cb cb_data;
|
|
struct sk_prov_key *key = vkey;
|
|
|
|
if (key == NULL || param_callback == NULL)
|
|
return 0;
|
|
|
|
sk_debug_key(key, "key: %p selection: %x", key, selection);
|
|
|
|
default_export_fn = (OSSL_FUNC_keymgmt_export_fn *)
|
|
sk_prov_get_default_keymgmt_func(key->provctx,
|
|
key->type, OSSL_FUNC_KEYMGMT_EXPORT);
|
|
if (default_export_fn == NULL) {
|
|
put_error_key(key, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default export_fn");
|
|
return 0;
|
|
}
|
|
|
|
if (key->secure_key == NULL ||
|
|
(selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) == 0) {
|
|
/*
|
|
* Clear key, or no private key selected, call default_export_fn
|
|
* with original callback
|
|
*/
|
|
if (!default_export_fn(key->default_key, selection,
|
|
param_callback, cbarg)) {
|
|
put_error_key(key, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_export_fn failed");
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/* Let the callback add our 3 addl. params */
|
|
cb_data.key = key;
|
|
cb_data.param_callback = param_callback;
|
|
cb_data.cbarg = cbarg;
|
|
if (!default_export_fn(key->default_key, selection,
|
|
sk_prov_keymgmt_export_cb, &cb_data)) {
|
|
put_error_key(key, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_export_fn failed");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int sk_prov_keymgmt_import(void *vkey, int selection,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
const OSSL_PARAM *p_blob, *p_funcs, *p_private, *p;
|
|
OSSL_FUNC_keymgmt_import_fn *default_import_fn;
|
|
struct sk_prov_key *key = vkey;
|
|
size_t len;
|
|
|
|
if (key == NULL)
|
|
return 0;
|
|
|
|
sk_debug_key(key, "key: %p selection: %x", key,
|
|
selection);
|
|
for (p = params; p != NULL && p->key != NULL; p++)
|
|
sk_debug_key(key, "param: %s", p->key);
|
|
|
|
default_import_fn = (OSSL_FUNC_keymgmt_import_fn *)
|
|
sk_prov_get_default_keymgmt_func(key->provctx,
|
|
key->type, OSSL_FUNC_KEYMGMT_IMPORT);
|
|
if (default_import_fn == NULL) {
|
|
put_error_key(key, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default import_fn");
|
|
return 0;
|
|
}
|
|
|
|
if (!default_import_fn(key->default_key, selection, params)) {
|
|
put_error_key(key, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_import_fn failed");
|
|
return 0;
|
|
}
|
|
|
|
if (key->secure_key != NULL)
|
|
OPENSSL_free(key->secure_key);
|
|
key->secure_key = NULL;
|
|
key->secure_key_size = 0;
|
|
key->funcs = NULL;
|
|
key->private = NULL;
|
|
|
|
p_blob = OSSL_PARAM_locate_const(params, SK_PROV_PKEY_PARAM_SK_BLOB);
|
|
p_funcs = OSSL_PARAM_locate_const(params, SK_PROV_PKEY_PARAM_SK_FUNCS);
|
|
p_private = OSSL_PARAM_locate_const(params,
|
|
SK_PROV_PKEY_PARAM_SK_PRIVATE);
|
|
|
|
if (p_blob != NULL && p_funcs != NULL && p_private != NULL) {
|
|
if (!OSSL_PARAM_get_octet_string(p_blob,
|
|
(void **)&key->secure_key, 0,
|
|
&key->secure_key_size)) {
|
|
put_error_key(key, SK_PROV_ERR_INTERNAL_ERROR,
|
|
"OSSL_PARAM_get_octet_string failed");
|
|
return 0;
|
|
}
|
|
|
|
if (!OSSL_PARAM_get_octet_string_ptr(p_funcs,
|
|
(const void **)&key->funcs, &len)) {
|
|
put_error_key(key, SK_PROV_ERR_INTERNAL_ERROR,
|
|
"OSSL_PARAM_get_octet_string_ptr failed");
|
|
return 0;
|
|
}
|
|
|
|
if (!OSSL_PARAM_get_octet_string_ptr(p_private,
|
|
(const void **)&key->private, &len)) {
|
|
put_error_key(key, SK_PROV_ERR_INTERNAL_ERROR,
|
|
"OSSL_PARAM_get_octet_string_ptr failed");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static const OSSL_PARAM sk_prov_imexport_types[] = {
|
|
SK_PROV_SECURE_KEY_PARMS,
|
|
OSSL_PARAM_END
|
|
};
|
|
|
|
static const OSSL_PARAM *sk_prov_keymgmt_export_types(int selection,
|
|
int pkey_type)
|
|
{
|
|
OSSL_FUNC_keymgmt_export_types_fn *default_export_types_fn;
|
|
const OSSL_PARAM *default_parms = NULL, *params;
|
|
struct sk_prov_ctx *provctx;
|
|
|
|
provctx = OSSL_PROVIDER_get0_provider_ctx(sk_prov_securekey_provider);
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "selection: %d pkey_type: %d", selection,
|
|
pkey_type);
|
|
|
|
params = sk_prov_get_cached_params(provctx, pkey_type,
|
|
SK_CONF_CACHED_PARAMS_OP_KEY_EXPORT,
|
|
selection);
|
|
if (params != NULL)
|
|
return params;
|
|
|
|
default_export_types_fn = (OSSL_FUNC_keymgmt_export_types_fn *)
|
|
sk_prov_get_default_keymgmt_func(provctx, pkey_type,
|
|
OSSL_FUNC_KEYMGMT_EXPORT_TYPES);
|
|
|
|
/* default_export_types_fn is optional */
|
|
if (default_export_types_fn != NULL)
|
|
default_parms = default_export_types_fn(selection);
|
|
|
|
return sk_prov_cached_params_build(provctx, pkey_type,
|
|
SK_CONF_CACHED_PARAMS_OP_KEY_EXPORT,
|
|
selection,
|
|
default_parms,
|
|
sk_prov_imexport_types);
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_keymgmt_import_types(int selection,
|
|
int pkey_type)
|
|
{
|
|
OSSL_FUNC_keymgmt_import_types_fn *default_import_types_fn;
|
|
const OSSL_PARAM *default_parms = NULL, *params;
|
|
struct sk_prov_ctx *provctx;
|
|
|
|
provctx = OSSL_PROVIDER_get0_provider_ctx(sk_prov_securekey_provider);
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "selection: %d pkey_type: %d", selection,
|
|
pkey_type);
|
|
|
|
params = sk_prov_get_cached_params(provctx, pkey_type,
|
|
SK_CONF_CACHED_PARAMS_OP_KEY_IMPORT,
|
|
selection);
|
|
if (params != NULL)
|
|
return params;
|
|
|
|
default_import_types_fn = (OSSL_FUNC_keymgmt_import_types_fn *)
|
|
sk_prov_get_default_keymgmt_func(provctx, pkey_type,
|
|
OSSL_FUNC_KEYMGMT_EXPORT_TYPES);
|
|
|
|
/* default_import_types_fn is optional */
|
|
if (default_import_types_fn != NULL)
|
|
default_parms = default_import_types_fn(selection);
|
|
|
|
return sk_prov_cached_params_build(provctx, pkey_type,
|
|
SK_CONF_CACHED_PARAMS_OP_KEY_IMPORT,
|
|
selection,
|
|
default_parms,
|
|
sk_prov_imexport_types);
|
|
}
|
|
|
|
static struct sk_prov_op_ctx *sk_prov_keymgmt_gen_init(
|
|
struct sk_prov_ctx *provctx, int selection,
|
|
const OSSL_PARAM params[], int pkey_type)
|
|
{
|
|
OSSL_FUNC_keymgmt_gen_cleanup_fn *default_gen_cleanup_fn;
|
|
OSSL_FUNC_keymgmt_gen_init_fn *default_gen_init_fn;
|
|
struct sk_prov_op_ctx *genctx;
|
|
const OSSL_PARAM *p;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "selection: %x type: %d", selection, pkey_type);
|
|
for (p = params; p != NULL && p->key != NULL; p++)
|
|
sk_debug_ctx(provctx, "param: %s", p->key);
|
|
|
|
default_gen_init_fn = (OSSL_FUNC_keymgmt_gen_init_fn *)
|
|
sk_prov_get_default_keymgmt_func(provctx, pkey_type,
|
|
OSSL_FUNC_KEYMGMT_GEN_INIT);
|
|
if (default_gen_init_fn == NULL) {
|
|
put_error_ctx(provctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default gen_init_fn");
|
|
return NULL;
|
|
}
|
|
|
|
default_gen_cleanup_fn = (OSSL_FUNC_keymgmt_gen_cleanup_fn *)
|
|
sk_prov_get_default_keymgmt_func(provctx, pkey_type,
|
|
OSSL_FUNC_KEYMGMT_GEN_CLEANUP);
|
|
if (default_gen_cleanup_fn == NULL) {
|
|
put_error_ctx(provctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default gen_cleanup_fn");
|
|
return NULL;
|
|
}
|
|
|
|
genctx = sk_prov_op_newctx(provctx, NULL, pkey_type);
|
|
if (genctx == NULL) {
|
|
put_error_ctx(provctx, SK_PROV_ERR_INTERNAL_ERROR,
|
|
"sk_prov_op_newctx failed");
|
|
return NULL;
|
|
}
|
|
|
|
if (!sk_prov_op_init(genctx, NULL, EVP_PKEY_OP_KEYGEN)) {
|
|
put_error_ctx(provctx, SK_PROV_ERR_INTERNAL_ERROR,
|
|
"sk_prov_op_init failed");
|
|
sk_prov_op_freectx(genctx);
|
|
return NULL;
|
|
}
|
|
|
|
genctx->default_op_ctx = default_gen_init_fn(provctx->default_provctx,
|
|
selection, params);
|
|
if (genctx->default_op_ctx == NULL) {
|
|
put_error_ctx(provctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_gen_init_fn failed");
|
|
sk_prov_op_freectx(genctx);
|
|
return NULL;
|
|
}
|
|
genctx->default_op_ctx_free = default_gen_cleanup_fn;
|
|
|
|
sk_debug_ctx(provctx, "genctx: %p", genctx);
|
|
return genctx;
|
|
}
|
|
|
|
static void sk_prov_keymgmt_gen_cleanup(void *vgenctx)
|
|
{
|
|
struct sk_prov_op_ctx *genctx = vgenctx;
|
|
|
|
if (genctx == NULL)
|
|
return;
|
|
|
|
sk_debug_op_ctx(genctx, "genctx: %p", genctx);
|
|
sk_prov_op_freectx(genctx);
|
|
}
|
|
|
|
static int sk_prov_keymgmt_gen_set_params(void *vgenctx,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_keymgmt_gen_set_params_fn *default_gen_set_params_fn;
|
|
struct sk_prov_op_ctx *genctx = vgenctx;
|
|
const OSSL_PARAM *p;
|
|
|
|
if (genctx == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(genctx, "genctx: %p", genctx);
|
|
for (p = params; p != NULL && p->key != NULL; p++)
|
|
sk_debug_op_ctx(genctx, "param: %s", p->key);
|
|
|
|
default_gen_set_params_fn = (OSSL_FUNC_keymgmt_gen_set_params_fn *)
|
|
sk_prov_get_default_keymgmt_func(genctx->provctx,
|
|
genctx->type, OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS);
|
|
|
|
/* default_gen_set_params_fn is optional */
|
|
if (default_gen_set_params_fn != NULL) {
|
|
if (!default_gen_set_params_fn(genctx->default_op_ctx,
|
|
params)) {
|
|
put_error_op_ctx(genctx,
|
|
SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_gen_set_params_fn failed");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_keymgmt_gen_settable_params(
|
|
struct sk_prov_op_ctx *genctx,
|
|
struct sk_prov_ctx *provctx,
|
|
int pkey_type)
|
|
{
|
|
OSSL_FUNC_keymgmt_gen_settable_params_fn
|
|
*default_gen_settable_params_fn;
|
|
const OSSL_PARAM *params = NULL, *p;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "pkey_type: %d", pkey_type);
|
|
|
|
default_gen_settable_params_fn =
|
|
(OSSL_FUNC_keymgmt_gen_settable_params_fn *)
|
|
sk_prov_get_default_keymgmt_func(provctx,
|
|
pkey_type,
|
|
OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS);
|
|
|
|
/* default_gen_settable_params_fn is optional */
|
|
if (default_gen_settable_params_fn != NULL)
|
|
params = default_gen_settable_params_fn(genctx->default_op_ctx,
|
|
provctx->default_provctx);
|
|
|
|
for (p = params; p != NULL && p->key != NULL; p++)
|
|
sk_debug_ctx(provctx, "param: %s", p->key);
|
|
|
|
return params;
|
|
}
|
|
|
|
static int sk_prov_keymgmt_gen_set_template(void *vgenctx, void *vtempl)
|
|
{
|
|
OSSL_FUNC_keymgmt_gen_set_template_fn *default_gen_set_template_fn;
|
|
struct sk_prov_op_ctx *genctx = vgenctx;
|
|
struct sk_prov_key *templ = vtempl;
|
|
|
|
if (genctx == NULL || templ == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(genctx, "genctx: %p templ: %p", genctx, templ);
|
|
|
|
default_gen_set_template_fn = (OSSL_FUNC_keymgmt_gen_set_template_fn *)
|
|
sk_prov_get_default_keymgmt_func(genctx->provctx,
|
|
genctx->type,
|
|
OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE);
|
|
|
|
if (default_gen_set_template_fn == NULL) {
|
|
put_error_op_ctx(genctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default get_set_template_fn");
|
|
return 0;
|
|
}
|
|
|
|
return default_gen_set_template_fn(genctx->default_op_ctx,
|
|
templ->default_key);
|
|
}
|
|
|
|
static void *sk_prov_keymgmt_gen(void *vgenctx,
|
|
OSSL_CALLBACK *osslcb, void *cbarg)
|
|
{
|
|
OSSL_FUNC_keymgmt_gen_fn *default_gen_fn;
|
|
struct sk_prov_op_ctx *genctx = vgenctx;
|
|
struct sk_prov_key *key;
|
|
|
|
if (genctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_op_ctx(genctx, "genctx: %p", genctx);
|
|
|
|
default_gen_fn = (OSSL_FUNC_keymgmt_gen_fn *)
|
|
sk_prov_get_default_keymgmt_func(genctx->provctx,
|
|
genctx->type, OSSL_FUNC_KEYMGMT_GEN);
|
|
|
|
if (default_gen_fn == NULL) {
|
|
put_error_op_ctx(genctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default gen_fn");
|
|
return NULL;
|
|
}
|
|
|
|
key = OPENSSL_zalloc(sizeof(struct sk_prov_key));
|
|
if (key == NULL) {
|
|
put_error_op_ctx(genctx, SK_PROV_ERR_MALLOC_FAILED,
|
|
"OPENSSL_zalloc failed");
|
|
return NULL;
|
|
}
|
|
|
|
key->provctx = genctx->provctx;
|
|
key->type = genctx->type;
|
|
|
|
key->default_key = default_gen_fn(genctx->default_op_ctx,
|
|
osslcb, cbarg);
|
|
if (key->default_key == NULL) {
|
|
put_error_op_ctx(genctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_gen_fn failed");
|
|
OPENSSL_free(key);
|
|
return NULL;
|
|
}
|
|
|
|
sk_prov_keymgmt_upref(key);
|
|
|
|
sk_debug_op_ctx(genctx, "key: %p", key);
|
|
|
|
return key;
|
|
}
|
|
|
|
static void *sk_prov_keymgmt_load(const void *reference, size_t reference_sz)
|
|
{
|
|
struct sk_prov_key *key;
|
|
|
|
if (reference == NULL)
|
|
return NULL;
|
|
|
|
if (reference_sz == sizeof(struct sk_prov_key)) {
|
|
/* The contents of the reference is the address to our object */
|
|
key = *(struct sk_prov_key **)reference;
|
|
|
|
/* We grabbed, so we detach it */
|
|
*(struct sk_prov_key **)reference = NULL;
|
|
return key;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static int sk_prov_keymgmt_get_size(struct sk_prov_key *key)
|
|
{
|
|
int size = 0;
|
|
OSSL_PARAM key_params[] = {
|
|
OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, &size),
|
|
OSSL_PARAM_END
|
|
};
|
|
|
|
sk_debug_key(key, "key: %p", key);
|
|
|
|
if (!sk_prov_keymgmt_get_params(key, key_params) ||
|
|
!OSSL_PARAM_modified(&key_params[0]) ||
|
|
size <= 0) {
|
|
put_error_key(key, SK_PROV_ERR_MISSING_PARAMETER,
|
|
"sk_prov_keymgmt_get_params failed to "
|
|
"get OSSL_PKEY_PARAM_MAX_SIZE");
|
|
return -1;
|
|
}
|
|
|
|
sk_debug_key(key, "size: %d", size);
|
|
return size;
|
|
}
|
|
|
|
static int sk_prov_keymgmt_get_bits(struct sk_prov_key *key)
|
|
{
|
|
int bits = 0;
|
|
OSSL_PARAM key_params[] = {
|
|
OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, &bits),
|
|
OSSL_PARAM_END
|
|
};
|
|
|
|
sk_debug_key(key, "key: %p", key);
|
|
|
|
if (!sk_prov_keymgmt_get_params(key, key_params) ||
|
|
!OSSL_PARAM_modified(&key_params[0]) ||
|
|
bits <= 0) {
|
|
put_error_key(key, SK_PROV_ERR_MISSING_PARAMETER,
|
|
"sk_prov_keymgmt_get_params failed to "
|
|
"get OSSL_PKEY_PARAM_BITS");
|
|
return -1;
|
|
}
|
|
|
|
sk_debug_key(key, "bits: %d", bits);
|
|
return bits;
|
|
}
|
|
|
|
static void *sk_prov_keymgmt_rsa_new(void *vprovctx)
|
|
{
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p", provctx);
|
|
|
|
return sk_prov_keymgmt_new(provctx, EVP_PKEY_RSA);
|
|
}
|
|
|
|
static const char *sk_prov_keymgmt_rsa_query_operation_name(int operation_id)
|
|
{
|
|
switch (operation_id) {
|
|
case OSSL_OP_SIGNATURE:
|
|
case OSSL_OP_ASYM_CIPHER:
|
|
return "RSA";
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_keymgmt_rsa_gettable_params(void *vprovctx)
|
|
{
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p", provctx);
|
|
return sk_prov_keymgmt_gettable_params(provctx, EVP_PKEY_RSA);
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_keymgmt_rsa_settable_params(void *vprovctx)
|
|
{
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p", provctx);
|
|
return sk_prov_keymgmt_settable_params(provctx, EVP_PKEY_RSA);
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_keymgmt_rsa_export_types(int selection)
|
|
{
|
|
return sk_prov_keymgmt_export_types(selection, EVP_PKEY_RSA);
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_keymgmt_rsa_import_types(int selection)
|
|
{
|
|
return sk_prov_keymgmt_import_types(selection, EVP_PKEY_RSA);
|
|
}
|
|
|
|
static void *sk_prov_keymgmt_rsa_gen_init(void *vprovctx, int selection,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p", provctx);
|
|
return sk_prov_keymgmt_gen_init(provctx, selection, params,
|
|
EVP_PKEY_RSA);
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_keymgmt_rsa_gen_settable_params(void *vgenctx,
|
|
void *vprovctx)
|
|
{
|
|
struct sk_prov_op_ctx *genctx = vgenctx;
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p", provctx);
|
|
return sk_prov_keymgmt_gen_settable_params(genctx, provctx,
|
|
EVP_PKEY_RSA);
|
|
}
|
|
|
|
static void *sk_prov_keymgmt_rsa_pss_new(void *vprovctx)
|
|
{
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p", provctx);
|
|
return sk_prov_keymgmt_new(provctx, EVP_PKEY_RSA_PSS);
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_keymgmt_rsa_pss_gettable_params(void *vprovctx)
|
|
{
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p", provctx);
|
|
return sk_prov_keymgmt_gettable_params(provctx, EVP_PKEY_RSA_PSS);
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_keymgmt_rsa_pss_settable_params(void *vprovctx)
|
|
{
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p", provctx);
|
|
return sk_prov_keymgmt_settable_params(provctx, EVP_PKEY_RSA_PSS);
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_keymgmt_rsa_pss_export_types(int selection)
|
|
{
|
|
return sk_prov_keymgmt_export_types(selection, EVP_PKEY_RSA_PSS);
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_keymgmt_rsa_pss_import_types(int selection)
|
|
{
|
|
return sk_prov_keymgmt_import_types(selection, EVP_PKEY_RSA_PSS);
|
|
}
|
|
|
|
static void *sk_prov_keymgmt_rsa_pss_gen_init(void *vprovctx, int selection,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p", provctx);
|
|
return sk_prov_keymgmt_gen_init(provctx, selection, params,
|
|
EVP_PKEY_RSA_PSS);
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_keymgmt_rsa_pss_gen_settable_params(
|
|
void *vgenctx,
|
|
void *vprovctx)
|
|
{
|
|
struct sk_prov_op_ctx *genctx = vgenctx;
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p", provctx);
|
|
return sk_prov_keymgmt_gen_settable_params(genctx, provctx,
|
|
EVP_PKEY_RSA_PSS);
|
|
}
|
|
|
|
static void *sk_prov_keymgmt_ec_new(void *vprovctx)
|
|
{
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p", provctx);
|
|
return sk_prov_keymgmt_new(provctx, EVP_PKEY_EC);
|
|
}
|
|
|
|
static const char *sk_prov_keymgmt_ec_query_operation_name(int operation_id)
|
|
{
|
|
switch (operation_id) {
|
|
case OSSL_OP_KEYEXCH:
|
|
return "ECDH";
|
|
case OSSL_OP_SIGNATURE:
|
|
return "ECDSA";
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_keymgmt_ec_gettable_params(void *vprovctx)
|
|
{
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p", provctx);
|
|
return sk_prov_keymgmt_gettable_params(provctx, EVP_PKEY_EC);
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_keymgmt_ec_settable_params(void *vprovctx)
|
|
{
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p", provctx);
|
|
return sk_prov_keymgmt_settable_params(provctx, EVP_PKEY_EC);
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_keymgmt_ec_export_types(int selection)
|
|
{
|
|
return sk_prov_keymgmt_export_types(selection, EVP_PKEY_EC);
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_keymgmt_ec_import_types(int selection)
|
|
{
|
|
return sk_prov_keymgmt_import_types(selection, EVP_PKEY_EC);
|
|
}
|
|
|
|
static void *sk_prov_keymgmt_ec_gen_init(void *vprovctx, int selection,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p", provctx);
|
|
return sk_prov_keymgmt_gen_init(provctx, selection, params,
|
|
EVP_PKEY_EC);
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_keymgmt_ec_gen_settable_params(void *vgenctx,
|
|
void *vprovctx)
|
|
{
|
|
struct sk_prov_op_ctx *genctx = vgenctx;
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p", provctx);
|
|
return sk_prov_keymgmt_gen_settable_params(genctx, provctx,
|
|
EVP_PKEY_EC);
|
|
}
|
|
|
|
static void *sk_prov_keyexch_ec_newctx(void *vprovctx)
|
|
{
|
|
OSSL_FUNC_keyexch_freectx_fn *default_freectx_fn;
|
|
OSSL_FUNC_keyexch_newctx_fn *default_newctx_fn;
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
struct sk_prov_op_ctx *ctx;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p", provctx);
|
|
|
|
default_newctx_fn = (OSSL_FUNC_keyexch_newctx_fn *)
|
|
sk_prov_get_default_keyexch_func(provctx,
|
|
OSSL_FUNC_KEYEXCH_NEWCTX);
|
|
if (default_newctx_fn == NULL) {
|
|
put_error_ctx(provctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default newctx_fn");
|
|
return NULL;
|
|
}
|
|
|
|
default_freectx_fn = (OSSL_FUNC_keyexch_freectx_fn *)
|
|
sk_prov_get_default_keyexch_func(provctx,
|
|
OSSL_FUNC_KEYEXCH_FREECTX);
|
|
if (default_freectx_fn == NULL) {
|
|
put_error_ctx(provctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default freectx_fn");
|
|
return NULL;
|
|
}
|
|
|
|
ctx = sk_prov_op_newctx(provctx, NULL, EVP_PKEY_EC);
|
|
if (ctx == NULL) {
|
|
sk_debug_ctx(provctx, "ERROR: sk_prov_op_newctx failed");
|
|
return NULL;
|
|
}
|
|
|
|
ctx->default_op_ctx = default_newctx_fn(provctx->default_provctx);
|
|
if (ctx->default_op_ctx == NULL) {
|
|
put_error_ctx(provctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_newctx_fn failed");
|
|
sk_prov_op_freectx(ctx);
|
|
return NULL;
|
|
}
|
|
ctx->default_op_ctx_free = default_freectx_fn;
|
|
|
|
sk_debug_ctx(provctx, "ctx: %p", ctx);
|
|
|
|
return ctx;
|
|
}
|
|
|
|
static void *sk_prov_keyexch_ec_dupctx(void *vctx)
|
|
{
|
|
OSSL_FUNC_keyexch_dupctx_fn *default_dupctx_fn;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
struct sk_prov_op_ctx *new_ctx;
|
|
|
|
if (ctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p", ctx);
|
|
|
|
default_dupctx_fn = (OSSL_FUNC_keyexch_dupctx_fn *)
|
|
sk_prov_get_default_keyexch_func(ctx->provctx,
|
|
OSSL_FUNC_KEYEXCH_DUPCTX);
|
|
if (default_dupctx_fn == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default dupctx_fn");
|
|
return NULL;
|
|
}
|
|
|
|
new_ctx = sk_prov_op_dupctx(ctx);
|
|
if (new_ctx == NULL) {
|
|
sk_debug_op_ctx(ctx, "ERROR: sk_prov_op_dupctx failed");
|
|
return NULL;
|
|
}
|
|
|
|
new_ctx->default_op_ctx = default_dupctx_fn(ctx->default_op_ctx);
|
|
if (new_ctx->default_op_ctx == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_dupctx_fn failed");
|
|
sk_prov_op_freectx(new_ctx);
|
|
return NULL;
|
|
}
|
|
|
|
sk_debug_op_ctx(ctx, "new_ctx: %p", new_ctx);
|
|
return new_ctx;
|
|
}
|
|
|
|
static int sk_prov_keyexch_ec_init(void *vctx, void *vkey,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_keyexch_init_fn *default_init_fn;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
struct sk_prov_key *key = vkey;
|
|
const OSSL_PARAM *p;
|
|
|
|
if (ctx == NULL || key == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p key: %p", ctx, key);
|
|
for (p = params; p != NULL && p->key != NULL; p++)
|
|
sk_debug_op_ctx(ctx, "param: %s", p->key);
|
|
|
|
default_init_fn = (OSSL_FUNC_keyexch_init_fn *)
|
|
sk_prov_get_default_keyexch_func(ctx->provctx,
|
|
OSSL_FUNC_KEYEXCH_INIT);
|
|
if (default_init_fn == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default init_fn");
|
|
return 0;
|
|
}
|
|
|
|
if (!sk_prov_op_init(ctx, key, EVP_PKEY_OP_DERIVE)) {
|
|
sk_debug_op_ctx(ctx, "ERROR: sk_prov_op_init failed");
|
|
return 0;
|
|
}
|
|
|
|
if (!default_init_fn(ctx->default_op_ctx, key->default_key, params)) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_init_fn failed");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int sk_prov_keyexch_ec_set_peer(void *vctx, void *vpeerkey)
|
|
|
|
{
|
|
OSSL_FUNC_keyexch_set_peer_fn *default_set_peer_fn;
|
|
struct sk_prov_key *peerkey = vpeerkey;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
|
|
if (ctx == NULL || peerkey == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p key: %p peerkey: %p", ctx, ctx->key,
|
|
peerkey);
|
|
|
|
default_set_peer_fn = (OSSL_FUNC_keyexch_set_peer_fn *)
|
|
sk_prov_get_default_keyexch_func(ctx->provctx,
|
|
OSSL_FUNC_KEYEXCH_SET_PEER);
|
|
if (default_set_peer_fn == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default set_peer_fn");
|
|
return 0;
|
|
}
|
|
|
|
if (ctx->key == NULL || ctx->operation != EVP_PKEY_OP_DERIVE) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_OPRATION_NOT_INITIALIZED,
|
|
"derive operation not initialized");
|
|
return 0;
|
|
}
|
|
|
|
if (!default_set_peer_fn(ctx->default_op_ctx, peerkey->default_key)) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_set_peer_fn failed");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int sk_prov_keyexch_ec_derive(void *vctx,
|
|
unsigned char *secret, size_t *secretlen,
|
|
size_t outlen)
|
|
{
|
|
OSSL_FUNC_keyexch_derive_fn *default_derive_fn;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
|
|
if (ctx == NULL || secretlen == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p key: %p outlen: %lu", ctx, ctx->key,
|
|
outlen);
|
|
|
|
default_derive_fn = (OSSL_FUNC_keyexch_derive_fn *)
|
|
sk_prov_get_default_keyexch_func(ctx->provctx,
|
|
OSSL_FUNC_KEYEXCH_DERIVE);
|
|
if (default_derive_fn == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_MISSING,
|
|
"no default derive_fn");
|
|
return 0;
|
|
}
|
|
|
|
if (ctx->key == NULL || ctx->operation != EVP_PKEY_OP_DERIVE) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_OPRATION_NOT_INITIALIZED,
|
|
"derive operation not initialized");
|
|
return 0;
|
|
}
|
|
|
|
if (!default_derive_fn(ctx->default_op_ctx, secret, secretlen,
|
|
outlen)) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_derive_fn failed");
|
|
return 0;
|
|
}
|
|
|
|
sk_debug_op_ctx(ctx, "secretlen: %lu", *secretlen);
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int sk_prov_keyexch_ec_set_ctx_params(void *vctx,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_keyexch_set_ctx_params_fn *default_set_params_fn;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
const OSSL_PARAM *p;
|
|
|
|
if (ctx == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p", ctx);
|
|
for (p = params; p != NULL && p->key != NULL; p++)
|
|
sk_debug_op_ctx(ctx, "param: %s", p->key);
|
|
|
|
default_set_params_fn = (OSSL_FUNC_keyexch_set_ctx_params_fn *)
|
|
sk_prov_get_default_keyexch_func(ctx->provctx,
|
|
OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS);
|
|
|
|
/* default_set_params_fn is optional */
|
|
if (default_set_params_fn != NULL) {
|
|
if (!default_set_params_fn(ctx->default_op_ctx, params)) {
|
|
put_error_op_ctx(ctx,
|
|
SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_set_params_fn failed");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_keyexch_ec_settable_ctx_params(void *vctx,
|
|
void *vprovctx)
|
|
{
|
|
OSSL_FUNC_keyexch_settable_ctx_params_fn
|
|
*default_settable_params_fn;
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
const OSSL_PARAM *params = NULL, *p;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
|
|
if (ctx == NULL || provctx == NULL)
|
|
return NULL;
|
|
|
|
default_settable_params_fn =
|
|
(OSSL_FUNC_keyexch_settable_ctx_params_fn *)
|
|
sk_prov_get_default_keyexch_func(provctx,
|
|
OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS);
|
|
|
|
/* default_settable_params_fn is optional */
|
|
if (default_settable_params_fn != NULL)
|
|
params = default_settable_params_fn(ctx->default_op_ctx,
|
|
provctx->default_provctx);
|
|
|
|
for (p = params; p != NULL && p->key != NULL; p++)
|
|
sk_debug_ctx(provctx, "param: %s", p->key);
|
|
|
|
return params;
|
|
}
|
|
|
|
static int sk_prov_keyexch_ec_get_ctx_params(void *vctx, OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_keyexch_get_ctx_params_fn *default_get_params_fn;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
const OSSL_PARAM *p;
|
|
|
|
if (ctx == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p", ctx);
|
|
for (p = params; p != NULL && p->key != NULL; p++)
|
|
sk_debug_op_ctx(ctx, "param: %s", p->key);
|
|
|
|
default_get_params_fn = (OSSL_FUNC_keyexch_get_ctx_params_fn *)
|
|
sk_prov_get_default_keyexch_func(ctx->provctx,
|
|
OSSL_FUNC_KEYEXCH_GET_CTX_PARAMS);
|
|
|
|
/* default_get_params_fn is optional */
|
|
if (default_get_params_fn != NULL) {
|
|
if (!default_get_params_fn(ctx->default_op_ctx, params)) {
|
|
put_error_op_ctx(ctx,
|
|
SK_PROV_ERR_DEFAULT_PROV_FUNC_FAILED,
|
|
"default_get_params_fn failed");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_keyexch_ec_gettable_ctx_params(void *vctx,
|
|
void *vprovctx)
|
|
{
|
|
OSSL_FUNC_keyexch_gettable_ctx_params_fn
|
|
*default_gettable_params_fn;
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
const OSSL_PARAM *params = NULL, *p;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
|
|
if (ctx == NULL || provctx == NULL)
|
|
return NULL;
|
|
|
|
default_gettable_params_fn =
|
|
(OSSL_FUNC_keyexch_gettable_ctx_params_fn *)
|
|
sk_prov_get_default_keyexch_func(provctx,
|
|
OSSL_FUNC_KEYEXCH_GETTABLE_CTX_PARAMS);
|
|
|
|
/* default_settable_params_fn is optional */
|
|
if (default_gettable_params_fn != NULL)
|
|
params = default_gettable_params_fn(ctx->default_op_ctx,
|
|
provctx->default_provctx);
|
|
|
|
for (p = params; p != NULL && p->key != NULL; p++)
|
|
sk_debug_ctx(provctx, "param: %s", p->key);
|
|
|
|
return params;
|
|
}
|
|
|
|
static void *sk_prov_asym_rsa_newctx(void *vprovctx)
|
|
{
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p", provctx);
|
|
return sk_prov_asym_op_newctx(provctx, EVP_PKEY_RSA);
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_asym_rsa_gettable_ctx_params(void *vctx,
|
|
void *vprovctx)
|
|
{
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p", provctx);
|
|
return sk_prov_asym_op_gettable_ctx_params(ctx, provctx, EVP_PKEY_RSA);
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_asym_rsa_settable_ctx_params(void *vctx,
|
|
void *vprovctx)
|
|
{
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p", provctx);
|
|
return sk_prov_asym_op_settable_ctx_params(ctx, provctx, EVP_PKEY_RSA);
|
|
}
|
|
|
|
static int sk_prov_asym_rsa_decrypt(void *vctx,
|
|
unsigned char *out, size_t *outlen,
|
|
size_t outsize, const unsigned char *in,
|
|
size_t inlen)
|
|
{
|
|
int rsa_size, pad_mode, oaep_label_len = 0, rc;
|
|
EVP_MD *oaep_md = NULL, *mgf_md = NULL;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
unsigned char *oaep_label = NULL;
|
|
unsigned char *tmp = NULL;
|
|
struct sk_prov_key *key;
|
|
struct sk_funcs *funcs;
|
|
|
|
if (ctx == NULL || in == NULL || outlen == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p key: %p inlen: %lu outsize: %lu",
|
|
ctx, ctx->key, inlen, outsize);
|
|
|
|
if (ctx->key == NULL || ctx->operation != EVP_PKEY_OP_DECRYPT) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_OPRATION_NOT_INITIALIZED,
|
|
"decrypt operation not initialized");
|
|
return 0;
|
|
}
|
|
|
|
/* For clear key, let the default provider handle it */
|
|
if (ctx->key->secure_key == NULL)
|
|
return sk_prov_asym_op_decrypt(ctx, out, outlen, outsize,
|
|
in, inlen);
|
|
|
|
funcs = ctx->key->funcs;
|
|
if (funcs == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_MISSING_PARAMETER,
|
|
"no secure key funcs");
|
|
return 0;
|
|
}
|
|
|
|
key = ctx->key;
|
|
|
|
rsa_size = sk_prov_keymgmt_get_size(key);
|
|
if (rsa_size <= 0) {
|
|
sk_debug_op_ctx(ctx, "sk_prov_keymgmt_get_size failed");
|
|
return 0;
|
|
}
|
|
|
|
if (out == NULL) {
|
|
tmp = OPENSSL_zalloc(rsa_size);
|
|
if (tmp == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_MALLOC_FAILED,
|
|
"OPENSSL_zalloc failed");
|
|
return 0;
|
|
}
|
|
out = tmp;
|
|
outsize = rsa_size;
|
|
}
|
|
|
|
if (outsize < (size_t)rsa_size) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_INVALID_PARAM,
|
|
"output buffer length invalid");
|
|
return 0;
|
|
}
|
|
|
|
pad_mode = sk_prov_asym_op_get_padding(ctx);
|
|
switch (pad_mode) {
|
|
case RSA_NO_PADDING:
|
|
case RSA_PKCS1_PADDING:
|
|
case RSA_X931_PADDING:
|
|
break;
|
|
|
|
case RSA_PKCS1_OAEP_PADDING:
|
|
oaep_label_len = sk_prov_asym_op_get_oaep_label(ctx,
|
|
&oaep_label);
|
|
if (oaep_label_len < 0) {
|
|
sk_debug_op_ctx(ctx,
|
|
"ERROR: sk_prov_rsa_asym_get_oaep_label failed");
|
|
rc = 0;
|
|
goto out;
|
|
}
|
|
|
|
oaep_md = sk_prov_asym_op_get_oaep_md(ctx);
|
|
if (oaep_md == NULL) {
|
|
sk_debug_op_ctx(ctx,
|
|
"ERROR: sk_prov_asym_op_get_oaep_md failed");
|
|
rc = 0;
|
|
goto out;
|
|
}
|
|
|
|
mgf_md = sk_prov_asym_op_get_mgf_md(ctx);
|
|
if (mgf_md == NULL) {
|
|
sk_debug_op_ctx(ctx,
|
|
"ERROR: sk_prov_asym_op_get_mgf_md failed");
|
|
rc = 0;
|
|
goto out;
|
|
}
|
|
break;
|
|
default:
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_INVALID_PADDING,
|
|
"unknown/unsupported padding: %d", pad_mode);
|
|
return 0;
|
|
}
|
|
|
|
*outlen = outsize;
|
|
|
|
switch (pad_mode) {
|
|
case RSA_PKCS1_OAEP_PADDING:
|
|
if (funcs->rsa_decrypt_oaep == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_MISSING_PARAMETER,
|
|
"no secure key decrypt function");
|
|
rc = 0;
|
|
goto out;
|
|
}
|
|
|
|
rc = funcs->rsa_decrypt_oaep(key->secure_key,
|
|
key->secure_key_size,
|
|
out, outlen, in, inlen,
|
|
EVP_MD_type(oaep_md),
|
|
EVP_MD_type(mgf_md),
|
|
oaep_label, oaep_label_len,
|
|
key->private, ctx->provctx->debug);
|
|
break;
|
|
|
|
default:
|
|
if (funcs->rsa_decrypt == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_MISSING_PARAMETER,
|
|
"no secure key decrypt function");
|
|
rc = 0;
|
|
goto out;
|
|
}
|
|
|
|
rc = funcs->rsa_decrypt(key->secure_key, key->secure_key_size,
|
|
out, outlen, in, inlen, pad_mode,
|
|
key->private, ctx->provctx->debug);
|
|
break;
|
|
}
|
|
|
|
if (tmp != NULL) {
|
|
OPENSSL_cleanse(tmp, outsize);
|
|
OPENSSL_free(tmp);
|
|
}
|
|
|
|
if (rc != 0) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_SECURE_KEY_FUNC_FAILED,
|
|
"Secure key encrypt operation failed: rc: %d",
|
|
rc);
|
|
rc = 0;
|
|
goto out;
|
|
}
|
|
|
|
rc = 1;
|
|
|
|
sk_debug_op_ctx(ctx, "outlen: %lu", *outlen);
|
|
|
|
out:
|
|
if (oaep_md != NULL)
|
|
EVP_MD_free(oaep_md);
|
|
if (mgf_md != NULL)
|
|
EVP_MD_free(mgf_md);
|
|
|
|
return rc;
|
|
}
|
|
|
|
static void *sk_prov_sign_rsa_newctx(void *vprovctx, const char *propq)
|
|
{
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p propq: %s", provctx,
|
|
propq != NULL ? propq : "");
|
|
return sk_prov_sign_op_newctx(provctx, propq, EVP_PKEY_RSA);
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_sign_rsa_gettable_ctx_params(void *vctx,
|
|
void *vprovctx)
|
|
{
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p", provctx);
|
|
return sk_prov_sign_op_gettable_ctx_params(ctx, provctx, EVP_PKEY_RSA);
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_sign_rsa_settable_ctx_params(void *vctx,
|
|
void *vprovctx)
|
|
{
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p", provctx);
|
|
return sk_prov_sign_op_settable_ctx_params(ctx, provctx, EVP_PKEY_RSA);
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_sign_rsa_gettable_ctx_md_params(void *vctx)
|
|
{
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
|
|
if (ctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p", ctx);
|
|
return sk_prov_sign_op_gettable_ctx_md_params(ctx, EVP_PKEY_RSA);
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_sign_rsa_settable_ctx_md_params(void *vctx)
|
|
{
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
|
|
if (ctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p", ctx);
|
|
return sk_prov_sign_op_settable_ctx_md_params(ctx, EVP_PKEY_RSA);
|
|
}
|
|
|
|
static int sk_prov_sign_rsa_sign(void *vctx,
|
|
unsigned char *sig, size_t *siglen,
|
|
size_t sigsize,
|
|
const unsigned char *tbs, size_t tbslen)
|
|
{
|
|
EVP_MD *sign_md = NULL, *mgf_md = NULL;
|
|
int rsa_size, pad_mode, salt_len, rc;
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
struct sk_prov_key *key;
|
|
struct sk_funcs *funcs;
|
|
|
|
if (ctx == NULL || siglen == NULL || tbs == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p key: %p tbslen: %lu sigsize: %lu",
|
|
ctx, ctx->key, tbslen, sigsize);
|
|
|
|
if (ctx->key == NULL || ctx->operation != EVP_PKEY_OP_SIGN) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_OPRATION_NOT_INITIALIZED,
|
|
"sign operation not initialized");
|
|
return 0;
|
|
}
|
|
|
|
/* For clear key, let the default provider handle it */
|
|
if (ctx->key->secure_key == NULL)
|
|
return sk_prov_sign_op_sign(ctx, sig, siglen, sigsize,
|
|
tbs, tbslen);
|
|
|
|
key = ctx->key;
|
|
|
|
rsa_size = sk_prov_keymgmt_get_size(key);
|
|
if (rsa_size <= 0) {
|
|
sk_debug_op_ctx(ctx, "ERROR: sk_prov_keymgmt_get_size failed");
|
|
return 0;
|
|
}
|
|
|
|
if (sig == NULL) {
|
|
*siglen = rsa_size;
|
|
sk_debug_op_ctx(ctx, "siglen: %lu", *siglen);
|
|
return 1;
|
|
}
|
|
|
|
if (sigsize < (size_t)rsa_size) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_INVALID_PARAM,
|
|
"signature length invalid");
|
|
return 0;
|
|
}
|
|
|
|
funcs = ctx->key->funcs;
|
|
if (funcs == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_MISSING_PARAMETER,
|
|
"no secure key funcs");
|
|
return 0;
|
|
}
|
|
|
|
sign_md = sk_prov_sign_op_get_md(ctx);
|
|
pad_mode = sk_prov_sign_op_get_padding(ctx);
|
|
|
|
if (sign_md == NULL) {
|
|
/* Sign without a signature digest, fall back to no padding */
|
|
pad_mode = RSA_NO_PADDING;
|
|
} else {
|
|
if (tbslen != (size_t)EVP_MD_size(sign_md)) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_INVALID_PARAM,
|
|
"tbslen must be size of digest");
|
|
rc = 0;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
*siglen = rsa_size;
|
|
|
|
switch (pad_mode) {
|
|
case RSA_PKCS1_PADDING:
|
|
case RSA_X931_PADDING:
|
|
if (sign_md == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_MISSING_PARAMETER,
|
|
"padding needs a signature digest");
|
|
rc = 0;
|
|
goto out;
|
|
}
|
|
/* fall through */
|
|
|
|
case RSA_NO_PADDING:
|
|
if (funcs->rsa_sign == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_MISSING_PARAMETER,
|
|
"no secure key sign function");
|
|
rc = 0;
|
|
goto out;
|
|
|
|
}
|
|
|
|
rc = funcs->rsa_sign(key->secure_key, key->secure_key_size,
|
|
sig, siglen, tbs, tbslen, pad_mode,
|
|
sign_md != NULL ?
|
|
EVP_MD_type(sign_md) : NID_undef,
|
|
key->private, ctx->provctx->debug);
|
|
break;
|
|
|
|
case RSA_PKCS1_PSS_PADDING:
|
|
if (sign_md == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_MISSING_PARAMETER,
|
|
"PSS padding needs a signature digest");
|
|
rc = 0;
|
|
goto out;
|
|
}
|
|
|
|
mgf_md = sk_prov_sign_op_get_mgf_md(ctx);
|
|
if (mgf_md == NULL) {
|
|
sk_debug_op_ctx(ctx,
|
|
"ERROR sk_prov_sign_op_get_mgf_md failed");
|
|
rc = 0;
|
|
goto out;
|
|
}
|
|
|
|
salt_len = sk_prov_sign_op_get_pss_saltlen(ctx, key, mgf_md);
|
|
if (salt_len < 0) {
|
|
sk_debug_op_ctx(ctx,
|
|
"ERROR: sk_prov_sign_op_get_pss_saltlen failed");
|
|
rc = 0;
|
|
goto out;
|
|
}
|
|
|
|
if (funcs->rsa_pss_sign == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_MISSING_PARAMETER,
|
|
"no secure key sign function");
|
|
rc = 0;
|
|
goto out;
|
|
}
|
|
|
|
rc = funcs->rsa_pss_sign(key->secure_key, key->secure_key_size,
|
|
sig, siglen, tbs, tbslen,
|
|
EVP_MD_type(sign_md),
|
|
EVP_MD_type(mgf_md),
|
|
salt_len, key->private,
|
|
ctx->provctx->debug);
|
|
break;
|
|
default:
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_INVALID_PADDING,
|
|
"unknown/unsupported padding: %d", pad_mode);
|
|
rc = 0;
|
|
goto out;
|
|
}
|
|
|
|
if (rc != 0) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_SECURE_KEY_FUNC_FAILED,
|
|
"Secure key sign operation failed: rc: %d",
|
|
rc);
|
|
rc = 0;
|
|
goto out;
|
|
}
|
|
|
|
rc = 1;
|
|
|
|
sk_debug_op_ctx(ctx, "siglen: %lu", *siglen);
|
|
|
|
out:
|
|
if (sign_md != NULL)
|
|
EVP_MD_free(sign_md);
|
|
if (mgf_md != NULL)
|
|
EVP_MD_free(mgf_md);
|
|
|
|
return rc;
|
|
}
|
|
|
|
static int sk_prov_sign_rsa_digest_sign_init(void *vctx,
|
|
const char *mdname,
|
|
void *vkey,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
struct sk_prov_key *key = vkey;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p mdname: %s key: %p", ctx,
|
|
mdname != NULL ? mdname : "", key);
|
|
return sk_prov_sign_op_digest_sign_init(ctx, mdname, key, params,
|
|
sk_prov_sign_rsa_sign);
|
|
}
|
|
|
|
static void *sk_prov_sign_ec_newctx(void *vprovctx, const char *propq)
|
|
{
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p propq: %s", provctx,
|
|
propq != NULL ? propq : "");
|
|
return sk_prov_sign_op_newctx(provctx, propq, EVP_PKEY_EC);
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_sign_ec_gettable_ctx_params(void *vctx,
|
|
void *vprovctx)
|
|
{
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p", provctx);
|
|
return sk_prov_sign_op_gettable_ctx_params(ctx, provctx, EVP_PKEY_EC);
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_sign_ec_settable_ctx_params(void *vctx,
|
|
void *vprovctx)
|
|
{
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p", provctx);
|
|
return sk_prov_sign_op_settable_ctx_params(ctx, provctx, EVP_PKEY_EC);
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_sign_ec_gettable_ctx_md_params(void *vctx)
|
|
{
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
|
|
if (ctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p", ctx);
|
|
return sk_prov_sign_op_gettable_ctx_md_params(ctx, EVP_PKEY_EC);
|
|
}
|
|
|
|
static const OSSL_PARAM *sk_prov_sign_ec_settable_ctx_md_params(void *vctx)
|
|
{
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
|
|
if (ctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p", ctx);
|
|
return sk_prov_sign_op_settable_ctx_md_params(ctx, EVP_PKEY_EC);
|
|
}
|
|
|
|
static int sk_prov_sign_ec_sign(void *vctx,
|
|
unsigned char *sig, size_t *siglen,
|
|
size_t sigsize,
|
|
const unsigned char *tbs, size_t tbslen)
|
|
{
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
struct sk_prov_key *key;
|
|
EVP_MD *sign_md = NULL;
|
|
struct sk_funcs *funcs;
|
|
int ec_size, rc;
|
|
|
|
if (ctx == NULL || siglen == NULL || tbs == NULL)
|
|
return 0;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p key: %p tbslen: %lu sigsize: %lu",
|
|
ctx, ctx->key, tbslen, sigsize);
|
|
|
|
if (ctx->key == NULL || ctx->operation != EVP_PKEY_OP_SIGN) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_OPRATION_NOT_INITIALIZED,
|
|
"sign operation not initialized");
|
|
return 0;
|
|
}
|
|
|
|
/* For clear key, let the default provider handle it */
|
|
if (ctx->key->secure_key == NULL)
|
|
return sk_prov_sign_op_sign(ctx, sig, siglen, sigsize,
|
|
tbs, tbslen);
|
|
|
|
key = ctx->key;
|
|
|
|
ec_size = sk_prov_keymgmt_get_size(key);
|
|
if (ec_size <= 0) {
|
|
sk_debug_op_ctx(ctx, "ERROR: sk_prov_keymgmt_get_size failed");
|
|
return 0;
|
|
}
|
|
|
|
if (sig == NULL) {
|
|
*siglen = ec_size;
|
|
sk_debug_op_ctx(ctx, "siglen: %lu", *siglen);
|
|
return 1;
|
|
}
|
|
|
|
if (sigsize < (size_t)ec_size) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_INVALID_PARAM,
|
|
"signature length invalid");
|
|
return 0;
|
|
}
|
|
|
|
funcs = ctx->key->funcs;
|
|
if (funcs == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_MISSING_PARAMETER,
|
|
"no secure key funcs");
|
|
return 0;
|
|
}
|
|
|
|
sign_md = sk_prov_sign_op_get_md(ctx);
|
|
if (sign_md == NULL) {
|
|
sk_debug_op_ctx(ctx, "ERROR: sk_prov_sign_op_get_md failed");
|
|
return 0;
|
|
}
|
|
|
|
if (tbslen != (size_t)EVP_MD_size(sign_md)) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_INVALID_PARAM,
|
|
"tbslen must be size of digest");
|
|
rc = 0;
|
|
goto out;
|
|
}
|
|
|
|
*siglen = ec_size;
|
|
|
|
if (funcs->ecdsa_sign == NULL) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_MISSING_PARAMETER,
|
|
"no secure key sign function");
|
|
rc = 0;
|
|
goto out;
|
|
}
|
|
|
|
rc = funcs->ecdsa_sign(key->secure_key, key->secure_key_size,
|
|
sig, siglen, tbs, tbslen,
|
|
EVP_MD_type(sign_md), key->private,
|
|
ctx->provctx->debug);
|
|
if (rc != 0) {
|
|
put_error_op_ctx(ctx, SK_PROV_ERR_SECURE_KEY_FUNC_FAILED,
|
|
"Secure key sign operation failed: rc: %d",
|
|
rc);
|
|
rc = 0;
|
|
goto out;
|
|
}
|
|
|
|
rc = 1;
|
|
|
|
sk_debug_op_ctx(ctx, "siglen: %lu", *siglen);
|
|
|
|
out:
|
|
if (sign_md != NULL)
|
|
EVP_MD_free(sign_md);
|
|
|
|
return rc;
|
|
}
|
|
|
|
static int sk_prov_sign_ec_digest_sign_init(void *vctx,
|
|
const char *mdname,
|
|
void *vkey,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
struct sk_prov_op_ctx *ctx = vctx;
|
|
struct sk_prov_key *key = vkey;
|
|
|
|
sk_debug_op_ctx(ctx, "ctx: %p mdname: %s key: %p", ctx,
|
|
mdname != NULL ? mdname : "", key);
|
|
return sk_prov_sign_op_digest_sign_init(ctx, mdname, key, params,
|
|
sk_prov_sign_ec_sign);
|
|
}
|
|
|
|
static const OSSL_DISPATCH sk_prov_rsa_signature_functions[] = {
|
|
/* Signature context constructor, descructor */
|
|
{ OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))sk_prov_sign_rsa_newctx },
|
|
{ OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))sk_prov_op_freectx },
|
|
{ OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))sk_prov_sign_op_dupctx },
|
|
/* Signing */
|
|
{ OSSL_FUNC_SIGNATURE_SIGN_INIT,
|
|
(void (*)(void))sk_prov_sign_op_sign_init },
|
|
{ OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))sk_prov_sign_rsa_sign },
|
|
/* Verifying */
|
|
{ OSSL_FUNC_SIGNATURE_VERIFY_INIT,
|
|
(void (*)(void))sk_prov_sign_op_verify_init },
|
|
{ OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))sk_prov_sign_op_verify },
|
|
/* Verify recover */
|
|
{ OSSL_FUNC_SIGNATURE_VERIFY_RECOVER_INIT,
|
|
(void (*)(void))sk_prov_sign_op_verify_recover_init },
|
|
{ OSSL_FUNC_SIGNATURE_VERIFY_RECOVER,
|
|
(void (*)(void))sk_prov_sign_op_verify_recover },
|
|
/* Digest Sign */
|
|
{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
|
|
(void (*)(void))sk_prov_sign_rsa_digest_sign_init },
|
|
{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE,
|
|
(void (*)(void))sk_prov_sign_op_digest_sign_update },
|
|
{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL,
|
|
(void (*)(void))sk_prov_sign_op_digest_sign_final },
|
|
/* Digest Verify */
|
|
{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
|
|
(void (*)(void))sk_prov_sign_op_digest_verify_init },
|
|
{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE,
|
|
(void (*)(void))sk_prov_sign_op_digest_verify_update },
|
|
{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL,
|
|
(void (*)(void))sk_prov_sign_op_digest_verify_final },
|
|
/* Signature parameters */
|
|
{ OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS,
|
|
(void (*)(void))sk_prov_sign_op_get_ctx_params },
|
|
{ OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
|
|
(void (*)(void))sk_prov_sign_rsa_gettable_ctx_params },
|
|
{ OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void
|
|
(*)(void))sk_prov_sign_op_set_ctx_params },
|
|
{ OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS,
|
|
(void (*)(void))sk_prov_sign_rsa_settable_ctx_params },
|
|
/* MD parameters */
|
|
{ OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS,
|
|
(void (*)(void))sk_prov_sign_op_get_ctx_md_params },
|
|
{ OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS,
|
|
(void (*)(void))sk_prov_sign_rsa_gettable_ctx_md_params },
|
|
{ OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS,
|
|
(void (*)(void))sk_prov_sign_op_set_ctx_md_params },
|
|
{ OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS,
|
|
(void (*)(void))sk_prov_sign_rsa_settable_ctx_md_params },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static const OSSL_DISPATCH sk_prov_ecdsa_signature_functions[] = {
|
|
/* Signature context constructor, descructor */
|
|
{ OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))sk_prov_sign_ec_newctx },
|
|
{ OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))sk_prov_op_freectx },
|
|
{ OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))sk_prov_sign_op_dupctx },
|
|
/* Signing */
|
|
{ OSSL_FUNC_SIGNATURE_SIGN_INIT,
|
|
(void (*)(void))sk_prov_sign_op_sign_init },
|
|
{ OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))sk_prov_sign_ec_sign },
|
|
/* Verifying */
|
|
{ OSSL_FUNC_SIGNATURE_VERIFY_INIT,
|
|
(void (*)(void))sk_prov_sign_op_verify_init },
|
|
{ OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))sk_prov_sign_op_verify },
|
|
/* Verify recover */
|
|
{ OSSL_FUNC_SIGNATURE_VERIFY_RECOVER_INIT,
|
|
(void (*)(void))sk_prov_sign_op_verify_recover_init },
|
|
{ OSSL_FUNC_SIGNATURE_VERIFY_RECOVER,
|
|
(void (*)(void))sk_prov_sign_op_verify_recover },
|
|
/* Digest Sign */
|
|
{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
|
|
(void (*)(void))sk_prov_sign_ec_digest_sign_init },
|
|
{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE,
|
|
(void (*)(void))sk_prov_sign_op_digest_sign_update },
|
|
{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL,
|
|
(void (*)(void))sk_prov_sign_op_digest_sign_final },
|
|
/* Digest Verify */
|
|
{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
|
|
(void (*)(void))sk_prov_sign_op_digest_verify_init },
|
|
{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE,
|
|
(void (*)(void))sk_prov_sign_op_digest_verify_update },
|
|
{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL,
|
|
(void (*)(void))sk_prov_sign_op_digest_verify_final },
|
|
/* Signature parameters */
|
|
{ OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS,
|
|
(void (*)(void))sk_prov_sign_op_get_ctx_params },
|
|
{ OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
|
|
(void (*)(void))sk_prov_sign_ec_gettable_ctx_params },
|
|
{ OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void
|
|
(*)(void))sk_prov_sign_op_set_ctx_params },
|
|
{ OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS,
|
|
(void (*)(void))sk_prov_sign_ec_settable_ctx_params },
|
|
/* MD parameters */
|
|
{ OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS,
|
|
(void (*)(void))sk_prov_sign_op_get_ctx_md_params },
|
|
{ OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS,
|
|
(void (*)(void))sk_prov_sign_ec_gettable_ctx_md_params },
|
|
{ OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS,
|
|
(void (*)(void))sk_prov_sign_op_set_ctx_md_params },
|
|
{ OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS,
|
|
(void (*)(void))sk_prov_sign_ec_settable_ctx_md_params },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static const OSSL_ALGORITHM sk_prov_signature[] = {
|
|
{ "RSA:rsaEncryption", "provider="SK_PROV_NAME,
|
|
sk_prov_rsa_signature_functions, NULL },
|
|
{ "ECDSA", "provider="SK_PROV_NAME,
|
|
sk_prov_ecdsa_signature_functions, NULL },
|
|
{ NULL, NULL, NULL, NULL }
|
|
};
|
|
|
|
static const OSSL_DISPATCH sk_prov_rsa_asym_cipher_functions[] = {
|
|
/* RSA context constructor, descructor */
|
|
{ OSSL_FUNC_ASYM_CIPHER_NEWCTX,
|
|
(void (*)(void))sk_prov_asym_rsa_newctx },
|
|
{ OSSL_FUNC_ASYM_CIPHER_FREECTX, (void (*)(void))sk_prov_op_freectx },
|
|
{ OSSL_FUNC_ASYM_CIPHER_DUPCTX,
|
|
(void (*)(void))sk_prov_asym_op_dupctx },
|
|
/* RSA context set/get parameters */
|
|
{ OSSL_FUNC_ASYM_CIPHER_GET_CTX_PARAMS,
|
|
(void (*)(void))sk_prov_asym_op_get_ctx_params },
|
|
{ OSSL_FUNC_ASYM_CIPHER_GETTABLE_CTX_PARAMS,
|
|
(void (*)(void))sk_prov_asym_rsa_gettable_ctx_params },
|
|
{ OSSL_FUNC_ASYM_CIPHER_SET_CTX_PARAMS,
|
|
(void (*)(void))sk_prov_asym_op_set_ctx_params },
|
|
{ OSSL_FUNC_ASYM_CIPHER_SETTABLE_CTX_PARAMS,
|
|
(void (*)(void))sk_prov_asym_rsa_settable_ctx_params },
|
|
/* RSA encrypt */
|
|
{ OSSL_FUNC_ASYM_CIPHER_ENCRYPT_INIT,
|
|
(void (*)(void))sk_prov_asym_op_encrypt_init },
|
|
{ OSSL_FUNC_ASYM_CIPHER_ENCRYPT,
|
|
(void (*)(void))sk_prov_asym_op_encrypt },
|
|
/* RSA decrypt */
|
|
{ OSSL_FUNC_ASYM_CIPHER_DECRYPT_INIT,
|
|
(void (*)(void))sk_prov_asym_op_decrypt_init },
|
|
{ OSSL_FUNC_ASYM_CIPHER_DECRYPT,
|
|
(void (*)(void))sk_prov_asym_rsa_decrypt },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static const OSSL_ALGORITHM sk_prov_asym_cipher[] = {
|
|
{ "RSA:rsaEncryption", "provider="SK_PROV_NAME,
|
|
sk_prov_rsa_asym_cipher_functions, NULL },
|
|
{ NULL, NULL, NULL, NULL }
|
|
};
|
|
|
|
|
|
static const OSSL_DISPATCH sk_prov_rsa_keymgmt_functions[] = {
|
|
/* Constructor, destructor */
|
|
{ OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))sk_prov_keymgmt_rsa_new },
|
|
{ OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))sk_prov_keymgmt_free },
|
|
|
|
/* Key generation and loading */
|
|
{ OSSL_FUNC_KEYMGMT_GEN_INIT,
|
|
(void (*)(void))sk_prov_keymgmt_rsa_gen_init },
|
|
{ OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE,
|
|
(void (*)(void))sk_prov_keymgmt_gen_set_template },
|
|
{ OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS,
|
|
(void (*)(void))sk_prov_keymgmt_gen_set_params },
|
|
{ OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
|
|
(void (*)(void))sk_prov_keymgmt_rsa_gen_settable_params },
|
|
{ OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))sk_prov_keymgmt_gen },
|
|
{ OSSL_FUNC_KEYMGMT_GEN_CLEANUP,
|
|
(void (*)(void))sk_prov_keymgmt_gen_cleanup },
|
|
{ OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))sk_prov_keymgmt_load },
|
|
|
|
/* Key object checking */
|
|
{ OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))sk_prov_keymgmt_has },
|
|
{ OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))sk_prov_keymgmt_match },
|
|
{ OSSL_FUNC_KEYMGMT_VALIDATE,
|
|
(void (*)(void))sk_prov_keymgmt_validate },
|
|
{ OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME,
|
|
(void (*)(void))sk_prov_keymgmt_rsa_query_operation_name },
|
|
|
|
/* Key object information */
|
|
{ OSSL_FUNC_KEYMGMT_GET_PARAMS,
|
|
(void (*) (void))sk_prov_keymgmt_get_params },
|
|
{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS,
|
|
(void (*) (void))sk_prov_keymgmt_rsa_gettable_params },
|
|
{ OSSL_FUNC_KEYMGMT_SET_PARAMS,
|
|
(void (*) (void))sk_prov_keymgmt_set_params },
|
|
{ OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS,
|
|
(void (*) (void))sk_prov_keymgmt_rsa_settable_params },
|
|
|
|
/* Import and export routines */
|
|
{ OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))sk_prov_keymgmt_export },
|
|
{ OSSL_FUNC_KEYMGMT_EXPORT_TYPES,
|
|
(void (*)(void))sk_prov_keymgmt_rsa_export_types },
|
|
{ OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))sk_prov_keymgmt_import },
|
|
{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES,
|
|
(void (*)(void))sk_prov_keymgmt_rsa_import_types },
|
|
/* No copy function, OpenSSL will use export/import to copy instead */
|
|
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static const OSSL_DISPATCH sk_prov_rsapss_keymgmt_functions[] = {
|
|
/* Constructor, destructor */
|
|
{ OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))sk_prov_keymgmt_rsa_pss_new },
|
|
{ OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))sk_prov_keymgmt_free },
|
|
|
|
/* Key generation and loading */
|
|
{ OSSL_FUNC_KEYMGMT_GEN_INIT,
|
|
(void (*)(void))sk_prov_keymgmt_rsa_pss_gen_init },
|
|
{ OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE,
|
|
(void (*)(void))sk_prov_keymgmt_gen_set_template },
|
|
{ OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS,
|
|
(void (*)(void))sk_prov_keymgmt_gen_set_params },
|
|
{ OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
|
|
(void (*)(void))sk_prov_keymgmt_rsa_pss_gen_settable_params },
|
|
{ OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))sk_prov_keymgmt_gen },
|
|
{ OSSL_FUNC_KEYMGMT_GEN_CLEANUP,
|
|
(void (*)(void))sk_prov_keymgmt_gen_cleanup },
|
|
{ OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))sk_prov_keymgmt_load },
|
|
|
|
/* Key object checking */
|
|
{ OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))sk_prov_keymgmt_has },
|
|
{ OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))sk_prov_keymgmt_match },
|
|
{ OSSL_FUNC_KEYMGMT_VALIDATE,
|
|
(void (*)(void))sk_prov_keymgmt_validate },
|
|
{ OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME,
|
|
(void (*)(void))sk_prov_keymgmt_rsa_query_operation_name },
|
|
|
|
/* Key object information */
|
|
{ OSSL_FUNC_KEYMGMT_GET_PARAMS,
|
|
(void (*) (void))sk_prov_keymgmt_get_params },
|
|
{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS,
|
|
(void (*) (void))sk_prov_keymgmt_rsa_pss_gettable_params },
|
|
{ OSSL_FUNC_KEYMGMT_SET_PARAMS,
|
|
(void (*) (void))sk_prov_keymgmt_set_params },
|
|
{ OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS,
|
|
(void (*) (void))sk_prov_keymgmt_rsa_pss_settable_params },
|
|
|
|
/* Import and export routines */
|
|
{ OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))sk_prov_keymgmt_export },
|
|
{ OSSL_FUNC_KEYMGMT_EXPORT_TYPES,
|
|
(void (*)(void))sk_prov_keymgmt_rsa_pss_export_types },
|
|
{ OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))sk_prov_keymgmt_import },
|
|
{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES,
|
|
(void (*)(void))sk_prov_keymgmt_rsa_pss_import_types },
|
|
/* No copy function, OpenSSL will use export/import to copy instead */
|
|
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static const OSSL_DISPATCH sk_prov_ec_keymgmt_functions[] = {
|
|
/* Constructor, destructor */
|
|
{ OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))sk_prov_keymgmt_ec_new },
|
|
{ OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))sk_prov_keymgmt_free },
|
|
|
|
/* Key generation and loading */
|
|
{ OSSL_FUNC_KEYMGMT_GEN_INIT,
|
|
(void (*)(void))sk_prov_keymgmt_ec_gen_init },
|
|
{ OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE,
|
|
(void (*)(void))sk_prov_keymgmt_gen_set_template },
|
|
{ OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS,
|
|
(void (*)(void))sk_prov_keymgmt_gen_set_params },
|
|
{ OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
|
|
(void (*)(void))sk_prov_keymgmt_ec_gen_settable_params },
|
|
{ OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))sk_prov_keymgmt_gen },
|
|
{ OSSL_FUNC_KEYMGMT_GEN_CLEANUP,
|
|
(void (*)(void))sk_prov_keymgmt_gen_cleanup },
|
|
{ OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))sk_prov_keymgmt_load },
|
|
|
|
/* Key object checking */
|
|
{ OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))sk_prov_keymgmt_has },
|
|
{ OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))sk_prov_keymgmt_match },
|
|
{ OSSL_FUNC_KEYMGMT_VALIDATE,
|
|
(void (*)(void))sk_prov_keymgmt_validate },
|
|
{ OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME,
|
|
(void (*)(void))sk_prov_keymgmt_ec_query_operation_name },
|
|
|
|
/* Key object information */
|
|
{ OSSL_FUNC_KEYMGMT_GET_PARAMS,
|
|
(void (*) (void))sk_prov_keymgmt_get_params },
|
|
{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS,
|
|
(void (*) (void))sk_prov_keymgmt_ec_gettable_params },
|
|
{ OSSL_FUNC_KEYMGMT_SET_PARAMS,
|
|
(void (*) (void))sk_prov_keymgmt_set_params },
|
|
{ OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS,
|
|
(void (*) (void))sk_prov_keymgmt_ec_settable_params },
|
|
|
|
/* Import and export routines */
|
|
{ OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))sk_prov_keymgmt_export },
|
|
{ OSSL_FUNC_KEYMGMT_EXPORT_TYPES,
|
|
(void (*)(void))sk_prov_keymgmt_ec_export_types },
|
|
{ OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))sk_prov_keymgmt_import },
|
|
{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES,
|
|
(void (*)(void))sk_prov_keymgmt_ec_import_types },
|
|
/* No copy function, OpenSSL will use export/import to copy instead */
|
|
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static const OSSL_ALGORITHM sk_prov_keymgmt[] = {
|
|
{ "RSA:rsaEncryption", "provider="SK_PROV_NAME,
|
|
sk_prov_rsa_keymgmt_functions, NULL },
|
|
{ "RSA-PSS:RSASSA-PSS", "provider="SK_PROV_NAME,
|
|
sk_prov_rsapss_keymgmt_functions, NULL },
|
|
{ "EC:id-ecPublicKey", "provider="SK_PROV_NAME,
|
|
sk_prov_ec_keymgmt_functions, NULL },
|
|
{ NULL, NULL, NULL, NULL }
|
|
};
|
|
|
|
static const OSSL_DISPATCH sk_prov_ec_keyexch_functions[] = {
|
|
/* Context management */
|
|
{ OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))sk_prov_keyexch_ec_newctx },
|
|
{ OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))sk_prov_op_freectx },
|
|
{ OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))sk_prov_keyexch_ec_dupctx },
|
|
|
|
/* Shared secret derivation */
|
|
{ OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))sk_prov_keyexch_ec_init },
|
|
{ OSSL_FUNC_KEYEXCH_SET_PEER,
|
|
(void (*)(void))sk_prov_keyexch_ec_set_peer },
|
|
{ OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))sk_prov_keyexch_ec_derive },
|
|
|
|
/* Key Exchange parameters */
|
|
{ OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS,
|
|
(void (*)(void))sk_prov_keyexch_ec_set_ctx_params },
|
|
{ OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS,
|
|
(void (*)(void))sk_prov_keyexch_ec_settable_ctx_params },
|
|
{ OSSL_FUNC_KEYEXCH_GET_CTX_PARAMS,
|
|
(void (*)(void))sk_prov_keyexch_ec_get_ctx_params },
|
|
{ OSSL_FUNC_KEYEXCH_GETTABLE_CTX_PARAMS,
|
|
(void (*)(void))sk_prov_keyexch_ec_gettable_ctx_params },
|
|
|
|
{ 0, NULL }
|
|
};
|
|
|
|
/*
|
|
* Although ECDH key derivation is not supported for secure keys (would result
|
|
* in a secure symmetric key, which OpenSSL can't handle), the provider still
|
|
* must implement the ECDH key exchange functions and proxy them all to the
|
|
* default provider. OpenSSL common code requires that the key management
|
|
* provider and the key exchange provider for a derive operation is the same.
|
|
* So for clear EC keys created with this provider, we do support the ECDH
|
|
* operation by proxy'ing it to the default provider.
|
|
*/
|
|
static const OSSL_ALGORITHM sk_prov_keyexch[] = {
|
|
{ "ECDH", "provider="SK_PROV_NAME, sk_prov_ec_keyexch_functions, NULL },
|
|
{ NULL, NULL, NULL, NULL }
|
|
};
|
|
|
|
static const OSSL_PARAM sk_prov_param_types[] = {
|
|
OSSL_PARAM_DEFN(OSSL_PROV_PARAM_NAME, OSSL_PARAM_UTF8_PTR, NULL, 0),
|
|
OSSL_PARAM_DEFN(OSSL_PROV_PARAM_VERSION, OSSL_PARAM_UTF8_PTR, NULL, 0),
|
|
OSSL_PARAM_DEFN(OSSL_PROV_PARAM_BUILDINFO, OSSL_PARAM_UTF8_PTR, NULL,
|
|
0),
|
|
OSSL_PARAM_DEFN(OSSL_PROV_PARAM_STATUS, OSSL_PARAM_INTEGER, NULL, 0),
|
|
OSSL_PARAM_END
|
|
};
|
|
|
|
static const OSSL_PARAM *sk_prov_gettable_params(void *vprovctx)
|
|
{
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p", provctx);
|
|
return sk_prov_param_types;
|
|
}
|
|
|
|
static int sk_prov_get_params(void *vprovctx, OSSL_PARAM params[])
|
|
{
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
OSSL_PARAM *p;
|
|
|
|
if (provctx == NULL)
|
|
return 0;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p", provctx);
|
|
|
|
p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_NAME);
|
|
if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, SK_PROV_DESCRIPTION)) {
|
|
put_error_ctx(provctx, SK_PROV_ERR_INTERNAL_ERROR,
|
|
"OSSL_PARAM_set_utf8_ptr failed");
|
|
return 0;
|
|
}
|
|
p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_VERSION);
|
|
if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, SK_PROV_VERSION)) {
|
|
put_error_ctx(provctx, SK_PROV_ERR_INTERNAL_ERROR,
|
|
"OSSL_PARAM_set_utf8_ptr failed");
|
|
return 0;
|
|
}
|
|
p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_BUILDINFO);
|
|
if (p != NULL && !OSSL_PARAM_set_utf8_ptr(p, SK_PROV_VERSION)) {
|
|
put_error_ctx(provctx, SK_PROV_ERR_INTERNAL_ERROR,
|
|
"OSSL_PARAM_set_utf8_ptr failed");
|
|
return 0;
|
|
}
|
|
p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_STATUS);
|
|
if (p != NULL && !OSSL_PARAM_set_int(p, 1)) {
|
|
put_error_ctx(provctx, SK_PROV_ERR_INTERNAL_ERROR,
|
|
"OSSL_PARAM_set_int failed");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static const OSSL_ALGORITHM *sk_prov_query(void *vprovctx,
|
|
int operation_id, int *no_cache)
|
|
{
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
*no_cache = 0;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p operation_id: %d", provctx,
|
|
operation_id);
|
|
|
|
switch (operation_id) {
|
|
case OSSL_OP_KEYMGMT:
|
|
return sk_prov_keymgmt;
|
|
case OSSL_OP_KEYEXCH:
|
|
return sk_prov_keyexch;
|
|
case OSSL_OP_SIGNATURE:
|
|
return sk_prov_signature;
|
|
case OSSL_OP_ASYM_CIPHER:
|
|
return sk_prov_asym_cipher;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static void sk_prov_teardown(void *vprovctx)
|
|
{
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
int i;
|
|
|
|
if (provctx == NULL)
|
|
return;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p", provctx);
|
|
|
|
for (i = 0; i < SK_PROV_CACHED_PARAMS_COUNT; i++) {
|
|
if (provctx->cached_parms[i] != NULL)
|
|
OPENSSL_free((void *)provctx->cached_parms[i]);
|
|
}
|
|
|
|
OPENSSL_free(provctx);
|
|
}
|
|
|
|
static const OSSL_ITEM *sk_prov_get_reason_strings(void *vprovctx)
|
|
{
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p", provctx);
|
|
return sk_prov_reason_strings;
|
|
}
|
|
|
|
static int sk_prov_prov_get_capabilities(void *vprovctx,
|
|
const char *capability,
|
|
OSSL_CALLBACK *cb, void *arg)
|
|
{
|
|
struct sk_prov_ctx *provctx = vprovctx;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p capability: %s", provctx,
|
|
capability);
|
|
|
|
if (provctx->default_provider == NULL)
|
|
return 0;
|
|
|
|
return OSSL_PROVIDER_get_capabilities(provctx->default_provider,
|
|
capability, cb, arg);
|
|
}
|
|
|
|
/* Functions we provide to the core */
|
|
static const OSSL_DISPATCH sk_prov_dispatch_table[] = {
|
|
{ OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))sk_prov_teardown },
|
|
{ OSSL_FUNC_PROVIDER_GETTABLE_PARAMS,
|
|
(void (*)(void))sk_prov_gettable_params },
|
|
{ OSSL_FUNC_PROVIDER_GET_PARAMS, (void (*)(void))sk_prov_get_params },
|
|
{ OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))sk_prov_query },
|
|
{ OSSL_FUNC_PROVIDER_GET_REASON_STRINGS,
|
|
(void (*)(void))sk_prov_get_reason_strings },
|
|
{ OSSL_FUNC_PROVIDER_GET_CAPABILITIES,
|
|
(void (*)(void))sk_prov_prov_get_capabilities },
|
|
{ 0, NULL }
|
|
};
|
|
|
|
static int sk_provider_init(const OSSL_CORE_HANDLE *handle,
|
|
const OSSL_DISPATCH *in,
|
|
const OSSL_DISPATCH **out, void **provctx)
|
|
{
|
|
OSSL_FUNC_core_set_error_debug_fn *c_set_error_debug = NULL;
|
|
OSSL_FUNC_core_get_libctx_fn *c_get_libctx = NULL;
|
|
OSSL_FUNC_core_vset_error_fn *c_vset_error = NULL;
|
|
OSSL_FUNC_core_new_error_fn *c_new_error = NULL;
|
|
struct sk_prov_ctx *ctx;
|
|
|
|
if (handle == NULL || in == NULL || out == NULL || provctx == NULL)
|
|
return 0;
|
|
|
|
for (; in->function_id != 0; in++) {
|
|
switch (in->function_id) {
|
|
case OSSL_FUNC_CORE_GET_LIBCTX:
|
|
c_get_libctx = OSSL_FUNC_core_get_libctx(in);
|
|
break;
|
|
case OSSL_FUNC_CORE_NEW_ERROR:
|
|
c_new_error = OSSL_FUNC_core_new_error(in);
|
|
break;
|
|
case OSSL_FUNC_CORE_SET_ERROR_DEBUG:
|
|
c_set_error_debug = OSSL_FUNC_core_set_error_debug(in);
|
|
break;
|
|
case OSSL_FUNC_CORE_VSET_ERROR:
|
|
c_vset_error = OSSL_FUNC_core_vset_error(in);
|
|
break;
|
|
default:
|
|
/* Just ignore anything we don't understand */
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (c_get_libctx == NULL)
|
|
return 0;
|
|
|
|
ctx = OPENSSL_zalloc(sizeof(struct sk_prov_ctx));
|
|
if (ctx == NULL) {
|
|
c_new_error(handle);
|
|
c_set_error_debug(handle, __FILE__, __LINE__, __func__);
|
|
c_vset_error(handle, SK_PROV_ERR_MALLOC_FAILED,
|
|
"Failed to allocate provider context", NULL);
|
|
return 0;
|
|
}
|
|
|
|
ctx->handle = handle;
|
|
ctx->c_get_libctx = c_get_libctx;
|
|
ctx->c_new_error = c_new_error;
|
|
ctx->c_set_error_debug = c_set_error_debug;
|
|
ctx->c_vset_error = c_vset_error;
|
|
*provctx = ctx;
|
|
|
|
*out = sk_prov_dispatch_table;
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* Initializes the secure key support for OpenSSL.
|
|
*
|
|
* @param debug true to enable internal debugging
|
|
*
|
|
* @returns zero for success, a negative errno in case of an error:
|
|
* -ENOMEM: failed to allocate memory
|
|
* -EIO: OpenSSL failed for various reasons
|
|
*/
|
|
int SK_OPENSSL_init(bool debug)
|
|
{
|
|
struct sk_prov_ctx *provctx;
|
|
|
|
if (sk_prov_securekey_libctx == NULL)
|
|
sk_prov_securekey_libctx = OSSL_LIB_CTX_new();
|
|
if (sk_prov_securekey_libctx == NULL) {
|
|
sk_debug(debug, "ERROR: OSSL_LIB_CTX_new failed");
|
|
return -ENOMEM;
|
|
}
|
|
|
|
if (OSSL_PROVIDER_add_builtin(sk_prov_securekey_libctx, SK_PROV_NAME,
|
|
sk_provider_init) != 1) {
|
|
sk_debug(debug, "ERROR: OSSL_PROVIDER_add_builtin failed");
|
|
return -EIO;
|
|
}
|
|
|
|
if (sk_prov_securekey_provider == NULL) {
|
|
sk_prov_securekey_provider =
|
|
OSSL_PROVIDER_load(sk_prov_securekey_libctx,
|
|
SK_PROV_NAME);
|
|
if (sk_prov_securekey_provider == NULL) {
|
|
sk_debug(debug, "ERROR: OSSL_PROVIDER_load("
|
|
SK_PROV_NAME") failed");
|
|
return -EIO;
|
|
}
|
|
}
|
|
provctx = OSSL_PROVIDER_get0_provider_ctx(sk_prov_securekey_provider);
|
|
provctx->debug = debug;
|
|
|
|
if (sk_prov_default_provider == NULL) {
|
|
sk_prov_default_provider =
|
|
OSSL_PROVIDER_load(sk_prov_securekey_libctx,
|
|
"default");
|
|
if (sk_prov_default_provider == NULL) {
|
|
sk_debug(debug,
|
|
"ERROR: OSSL_PROVIDER_load(default) failed");
|
|
SK_OPENSSL_term();
|
|
return -EIO;
|
|
}
|
|
}
|
|
provctx->default_provider = sk_prov_default_provider;
|
|
provctx->default_provctx =
|
|
OSSL_PROVIDER_get0_provider_ctx(sk_prov_default_provider);
|
|
|
|
sk_prov_previous_libctx =
|
|
OSSL_LIB_CTX_set0_default(sk_prov_securekey_libctx);
|
|
if (sk_prov_previous_libctx == NULL) {
|
|
sk_debug(debug, "ERROR: OSSL_LIB_CTX_set0_default failed");
|
|
SK_OPENSSL_term();
|
|
return -EIO;
|
|
}
|
|
|
|
/* Prefer the secure key provider, but allow to fall back to default */
|
|
if (!EVP_set_default_properties(sk_prov_securekey_libctx,
|
|
"?provider="SK_PROV_NAME)) {
|
|
sk_debug(debug, "ERROR: EVP_set_default_properties failed");
|
|
SK_OPENSSL_term();
|
|
return -EIO;
|
|
}
|
|
|
|
sk_debug(debug, "sk_provider support initialized, provctx: %p",
|
|
provctx);
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Terminate the secure key support for OpenSSL.
|
|
*/
|
|
void SK_OPENSSL_term(void)
|
|
{
|
|
if (sk_prov_securekey_provider != NULL)
|
|
OSSL_PROVIDER_unload(sk_prov_securekey_provider);
|
|
sk_prov_securekey_provider = NULL;
|
|
|
|
if (sk_prov_default_provider != NULL)
|
|
OSSL_PROVIDER_unload(sk_prov_default_provider);
|
|
sk_prov_default_provider = NULL;
|
|
|
|
if (sk_prov_previous_libctx != NULL)
|
|
OSSL_LIB_CTX_set0_default(sk_prov_previous_libctx);
|
|
sk_prov_previous_libctx = NULL;
|
|
|
|
if (sk_prov_securekey_libctx != NULL)
|
|
OSSL_LIB_CTX_free(sk_prov_securekey_libctx);
|
|
sk_prov_securekey_libctx = NULL;
|
|
}
|
|
|
|
static int sk_openssl_pkey_from_data(OSSL_PARAM_BLD *bld, int pkey_type,
|
|
EVP_PKEY **pkey, bool debug)
|
|
{
|
|
OSSL_PARAM *params = NULL;
|
|
EVP_PKEY_CTX *pctx = NULL;
|
|
const char *key_name;
|
|
int rc = 0;
|
|
|
|
switch (pkey_type) {
|
|
case EVP_PKEY_EC:
|
|
key_name = "EC";
|
|
break;
|
|
case EVP_PKEY_RSA:
|
|
key_name = "RSA";
|
|
break;
|
|
case EVP_PKEY_RSA_PSS:
|
|
key_name = "RSA-PSS";
|
|
break;
|
|
default:
|
|
sk_debug(debug, "ERROR: unsupported PKEY type");
|
|
return -EINVAL;
|
|
}
|
|
|
|
params = OSSL_PARAM_BLD_to_param(bld);
|
|
if (params == NULL) {
|
|
sk_debug(debug, "ERROR: OSSL_PARAM_BLD_to_param failed");
|
|
rc = -EIO;
|
|
goto out;
|
|
}
|
|
|
|
pctx = EVP_PKEY_CTX_new_from_name(NULL, key_name,
|
|
"provider="SK_PROV_NAME);
|
|
if (pctx == NULL) {
|
|
sk_debug(debug, "ERROR: EVP_PKEY_CTX_new_from_name failed");
|
|
return -EIO;
|
|
}
|
|
|
|
if (EVP_PKEY_fromdata_init(pctx) <= 0) {
|
|
sk_debug(debug, "ERROR: EVP_PKEY_fromdata_init failed");
|
|
rc = -EIO;
|
|
goto out;
|
|
}
|
|
|
|
if (EVP_PKEY_fromdata(pctx, pkey, EVP_PKEY_KEYPAIR, params) <= 0) {
|
|
sk_debug(debug, "ERROR: EVP_PKEY_fromdata failed");
|
|
rc = -EIO;
|
|
goto out;
|
|
}
|
|
|
|
out:
|
|
if (pctx != NULL)
|
|
EVP_PKEY_CTX_free(pctx);
|
|
if (params != NULL)
|
|
OSSL_PARAM_free(params);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/**
|
|
* Converts an EC key given by the nid and the x and y coordinates into an
|
|
* OpenSSL PKEY and attaches the secure key together with secure key functions
|
|
* and private pointer to it. If no secure key is provided, a public EC key
|
|
* only PKEY is returned.
|
|
*
|
|
* @param secure_key the secure key blob.
|
|
* If NULL, a clear key PKEY is created.
|
|
* @param secure_key_size the size of the secure key blob (ignored if
|
|
* secure_key is NULL)
|
|
* @param nid the OpenSSL nid of the EC curve used
|
|
* @param prime_len the length of the prime in bytes. This is also the
|
|
* length of the x and y coordinates.
|
|
* @param x the x coordinate as big endian binary number in
|
|
* prime_len size
|
|
* @param y the y coordinate as big endian binary number in
|
|
* prime_len size
|
|
* @param sk_funcs the secure key functions to operate with the key.
|
|
* Ignored if secure_key is NULL, required otherwise.
|
|
* @param private a private pointer that is passed to the secure key
|
|
* functions (can be NULL)
|
|
* @param pkey On return: A PKEY containing the EC public key.
|
|
* @param debug true to enable internal debugging
|
|
*
|
|
* @returns zero for success, a negative errno in case of an error:
|
|
* -EINVAL: a function parameter is invalid
|
|
* -ENOMEM: failed to allocate memory
|
|
* -EIO: OpenSSL failed to generate the PKEY
|
|
* -ENOENT: OpenSSL does not know/support the curve (nid)
|
|
*/
|
|
int sk_openssl_get_pkey_ec(const unsigned char *secure_key,
|
|
size_t secure_key_size, int nid, size_t prime_len,
|
|
const unsigned char *x, const unsigned char *y,
|
|
const struct sk_funcs *sk_funcs, const void *private,
|
|
EVP_PKEY **pkey, bool debug)
|
|
{
|
|
BIGNUM *bn_x = NULL, *bn_y = NULL;
|
|
point_conversion_form_t form;
|
|
unsigned char *pub_key = NULL;
|
|
OSSL_PARAM_BLD *bld = NULL;
|
|
EC_GROUP *group = NULL;
|
|
EC_POINT *point = NULL;
|
|
size_t pub_key_len;
|
|
int rc;
|
|
|
|
if (pkey == NULL || x == NULL || y == NULL)
|
|
return -EINVAL;
|
|
if (secure_key != NULL && (secure_key_size == 0 || sk_funcs == NULL))
|
|
return -EINVAL;
|
|
|
|
*pkey = NULL;
|
|
|
|
group = EC_GROUP_new_by_curve_name(nid);
|
|
if (group == NULL) {
|
|
sk_debug(debug, "ERROR: EC_GROUP_new_by_curve_name failed");
|
|
rc = -ENOENT;
|
|
goto out;
|
|
}
|
|
|
|
bn_x = BN_bin2bn(x, prime_len, NULL);
|
|
bn_y = BN_bin2bn(y, prime_len, NULL);
|
|
if (bn_x == NULL || bn_y == NULL) {
|
|
sk_debug(debug, "ERROR: BN_bin2bn failed");
|
|
rc = -ENOMEM;
|
|
goto out;
|
|
}
|
|
|
|
point = EC_POINT_new(group);
|
|
if (point == NULL) {
|
|
sk_debug(debug, "ERROR: EC_POINT_new failed");
|
|
rc = -ENOMEM;
|
|
goto out;
|
|
}
|
|
|
|
if (!EC_POINT_set_affine_coordinates(group, point, bn_x, bn_y, NULL)) {
|
|
sk_debug(debug, "ERROR: EC_POINT_set_affine_coordinates failed");
|
|
rc = -EIO;
|
|
goto out;
|
|
}
|
|
|
|
form = EC_GROUP_get_point_conversion_form(group);
|
|
pub_key_len = EC_POINT_point2buf(group, point, form, &pub_key, NULL);
|
|
if (pub_key_len == 0) {
|
|
sk_debug(debug, "ERROR: EC_POINT_point2buf failed");
|
|
rc = -EIO;
|
|
goto out;
|
|
}
|
|
|
|
bld = OSSL_PARAM_BLD_new();
|
|
if (bld == NULL) {
|
|
sk_debug(debug, "ERROR: OSSL_PARAM_BLD_new failed");
|
|
rc = -ENOMEM;
|
|
goto out;
|
|
}
|
|
|
|
if (!OSSL_PARAM_BLD_push_utf8_string(bld, OSSL_PKEY_PARAM_GROUP_NAME,
|
|
OBJ_nid2sn(nid), 0)
|
|
|| !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_PUB_X, bn_x)
|
|
|| !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_EC_PUB_Y, bn_y)
|
|
|| !OSSL_PARAM_BLD_push_octet_string(bld, OSSL_PKEY_PARAM_PUB_KEY,
|
|
pub_key, pub_key_len)) {
|
|
sk_debug(debug, "ERROR: OSSL_PARAM_BLD_push_xxx failed");
|
|
rc = -EIO;
|
|
goto out;
|
|
}
|
|
|
|
if (secure_key != NULL) {
|
|
if (!OSSL_PARAM_BLD_push_octet_string(bld,
|
|
SK_PROV_PKEY_PARAM_SK_BLOB,
|
|
secure_key, secure_key_size)
|
|
|| !OSSL_PARAM_BLD_push_octet_ptr(bld,
|
|
SK_PROV_PKEY_PARAM_SK_FUNCS,
|
|
(void *)sk_funcs,
|
|
sizeof(struct sk_funcs))
|
|
|| !OSSL_PARAM_BLD_push_octet_ptr(bld,
|
|
SK_PROV_PKEY_PARAM_SK_PRIVATE,
|
|
(void *)private, 0)) {
|
|
sk_debug(debug,
|
|
"ERROR: OSSL_PARAM_BLD_push_xxx failed");
|
|
rc = -EIO;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
rc = sk_openssl_pkey_from_data(bld, EVP_PKEY_EC, pkey, debug);
|
|
if (rc != 0)
|
|
goto out;
|
|
|
|
rc = 0;
|
|
sk_debug(debug, "pkey created: %p", *pkey);
|
|
|
|
out:
|
|
if (group != NULL)
|
|
EC_GROUP_free(group);
|
|
if (point != NULL)
|
|
EC_POINT_free(point);
|
|
if (bn_x != NULL)
|
|
BN_free(bn_x);
|
|
if (bn_y != NULL)
|
|
BN_free(bn_y);
|
|
if (bld != NULL)
|
|
OSSL_PARAM_BLD_free(bld);
|
|
if (pub_key != NULL)
|
|
OPENSSL_free(pub_key);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/**
|
|
* Converts an RSA key given by the modulus and public exponent into an
|
|
* OpenSSL PKEY and attaches the secure key together with secure key functions
|
|
* and private pointer to it. If no secure key is provided, a public RSA key
|
|
* only PKEY is returned.
|
|
*
|
|
* @param secure_key the secure key blob.
|
|
* If NULL, a clear key PKEY is created.
|
|
* @param secure_key_size the size of the secure key blob (ignored if
|
|
* secure_key is NULL)
|
|
* @param modulus the modulus as big endian number
|
|
* @param modulus_length the length of the modulus in bytes
|
|
* @param pub_exp the public exponent as big endian number
|
|
* @param pub_exp_length the length of the public exponent in bytes
|
|
* @param pkey_type the PKEY type (EVP_PKEY_RSA or EVP_PKEY_RSA_PSS)
|
|
* @param sk_funcs the secure key functions to operate with the key.
|
|
* Ignored if secure_key is NULL, required otherwise.
|
|
* @param private a private pointer that is passed to the secure key
|
|
* functions (can be NULL)
|
|
* @param pkey On return: A PKEY containing the RSA public key.
|
|
* @param debug true to enable internal debugging
|
|
*
|
|
* @returns zero for success, a negative errno in case of an error:
|
|
* -EINVAL: a function parameter is invalid
|
|
* -ENOMEM: failed to allocate memory
|
|
* -EIO: OpenSSL failed to generate the PKEY
|
|
*/
|
|
int sk_openssl_get_pkey_rsa(const unsigned char *secure_key,
|
|
size_t secure_key_size,
|
|
const unsigned char *modulus, size_t modulus_length,
|
|
const unsigned char *pub_exp, size_t pub_exp_length,
|
|
int pkey_type, const struct sk_funcs *sk_funcs,
|
|
const void *private, EVP_PKEY **pkey, bool debug)
|
|
{
|
|
BIGNUM *bn_modulus = NULL, *bn_pub_exp = NULL;
|
|
OSSL_PARAM_BLD *bld = NULL;
|
|
int rc;
|
|
|
|
if (pkey == NULL || modulus == NULL || pub_exp == NULL)
|
|
return -EINVAL;
|
|
if (secure_key != NULL && (secure_key_size == 0 || sk_funcs == NULL))
|
|
return -EINVAL;
|
|
if (pkey_type != EVP_PKEY_RSA && pkey_type != EVP_PKEY_RSA_PSS)
|
|
return -EINVAL;
|
|
|
|
*pkey = NULL;
|
|
|
|
bn_modulus = BN_bin2bn(modulus, modulus_length, NULL);
|
|
bn_pub_exp = BN_bin2bn(pub_exp, pub_exp_length, NULL);
|
|
if (bn_modulus == NULL || bn_pub_exp == NULL) {
|
|
sk_debug(debug, "ERROR: BN_bin2bn failed");
|
|
rc = -ENOMEM;
|
|
goto out;
|
|
}
|
|
|
|
bld = OSSL_PARAM_BLD_new();
|
|
if (bld == NULL) {
|
|
sk_debug(debug, "ERROR: OSSL_PARAM_BLD_new failed");
|
|
rc = -ENOMEM;
|
|
goto out;
|
|
}
|
|
|
|
if (!OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_N, bn_modulus) ||
|
|
!OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_E, bn_pub_exp)) {
|
|
sk_debug(debug, "ERROR: OSSL_PARAM_BLD_push_xxx failed");
|
|
rc = -EIO;
|
|
goto out;
|
|
}
|
|
|
|
if (secure_key != NULL) {
|
|
if (!OSSL_PARAM_BLD_push_octet_string(bld,
|
|
SK_PROV_PKEY_PARAM_SK_BLOB,
|
|
secure_key, secure_key_size)
|
|
|| !OSSL_PARAM_BLD_push_octet_ptr(bld,
|
|
SK_PROV_PKEY_PARAM_SK_FUNCS,
|
|
(void *)sk_funcs,
|
|
sizeof(struct sk_funcs))
|
|
|| !OSSL_PARAM_BLD_push_octet_ptr(bld,
|
|
SK_PROV_PKEY_PARAM_SK_PRIVATE,
|
|
(void *)private, 0)) {
|
|
sk_debug(debug,
|
|
"ERROR: OSSL_PARAM_BLD_push_xxx failed");
|
|
rc = -EIO;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
rc = sk_openssl_pkey_from_data(bld, pkey_type, pkey, debug);
|
|
if (rc != 0)
|
|
goto out;
|
|
|
|
rc = 0;
|
|
sk_debug(debug, "pkey created: %p", *pkey);
|
|
|
|
out:
|
|
if (bn_modulus != NULL)
|
|
BN_free(bn_modulus);
|
|
if (bn_pub_exp != NULL)
|
|
BN_free(bn_pub_exp);
|
|
if (bld != NULL)
|
|
OSSL_PARAM_BLD_free(bld);
|
|
|
|
return rc;
|
|
}
|
|
|
|
/**
|
|
* Get the curve NID of the EC pkey
|
|
*/
|
|
int SK_OPENSSL_get_curve_from_ec_pkey(EVP_PKEY *pkey)
|
|
{
|
|
size_t curve_len;
|
|
char curve[80];
|
|
|
|
if (EVP_PKEY_id(pkey) != EVP_PKEY_EC)
|
|
return NID_undef;
|
|
|
|
if (!EVP_PKEY_get_utf8_string_param(pkey, OSSL_PKEY_PARAM_GROUP_NAME,
|
|
curve, sizeof(curve), &curve_len))
|
|
return NID_undef;
|
|
|
|
return OBJ_sn2nid(curve);
|
|
}
|
|
|
|
#endif
|