mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
The libseckey is a secure key library to perform secure key operations with OpenSSL. It provides a framework to create OpenSSL PKEYs with a secure key attached. Such a PKEY contains the public key parts in clear, but the private key as secure key blob. Only the private key operations are actually performed with the secure key, public key operations are performed in software by OpenSSL. It supports CCA and EP11 secure keys for RSA and ECC crypto operations. Because many PKEY method related functions are deprecated since OpenSSL 3.0, two versions of the OpenSSL secure key support are needed. One (using a PKEY method override) for OpenSSL 1.1.1, and another one (using an own OpenSSL provider) for OpenSSL 3.0 and later. The desired implementation is selected automatically at compile time, using OpenSSL version defines. The interface of both implementations is the same, so a user does not need to care which one is used. Reviewed-by: Juergen Christ <jchrist@linux.ibm.com> Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com> Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
5080 lines
141 KiB
C
5080 lines
141 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;
|
|
int (*sign_fn)(struct sk_prov_op_ctx *ctx, unsigned char *sig,
|
|
size_t *siglen, size_t sigsize, const unsigned char *tbs,
|
|
size_t tbslen);
|
|
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);
|
|
|
|
#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 void sk_prov_keymgmt_free(struct sk_prov_key *key);
|
|
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];
|
|
}
|
|
|
|
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(struct sk_prov_op_ctx *ctx)
|
|
{
|
|
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 struct sk_prov_op_ctx *sk_prov_asym_op_dupctx(struct sk_prov_op_ctx *ctx)
|
|
{
|
|
OSSL_FUNC_asym_cipher_dupctx_fn *default_dupctx_fn;
|
|
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(struct sk_prov_op_ctx *ctx,
|
|
OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_asym_cipher_get_ctx_params_fn *default_get_params_fn;
|
|
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(struct sk_prov_op_ctx *ctx,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_asym_cipher_set_ctx_params_fn *default_set_params_fn;
|
|
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(struct sk_prov_op_ctx *ctx,
|
|
struct sk_prov_key *key,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_asym_cipher_encrypt_init_fn *default_encrypt_init_fn;
|
|
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(struct sk_prov_op_ctx *ctx,
|
|
struct sk_prov_key *key,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_asym_cipher_decrypt_init_fn *default_decrypt_init_fn;
|
|
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(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_encrypt_fn *default_encrypt_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_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 struct sk_prov_op_ctx *sk_prov_sign_op_dupctx(struct sk_prov_op_ctx *ctx)
|
|
{
|
|
OSSL_FUNC_signature_dupctx_fn *default_dupctx_fn;
|
|
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(struct sk_prov_op_ctx *ctx,
|
|
OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_signature_get_ctx_params_fn *default_get_params_fn;
|
|
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(struct sk_prov_op_ctx *ctx,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_signature_set_ctx_params_fn *default_set_params_fn;
|
|
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_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(struct sk_prov_op_ctx *ctx,
|
|
OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_signature_get_ctx_md_params_fn *default_get_md_params_fn;
|
|
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(struct sk_prov_op_ctx *ctx,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_signature_set_ctx_md_params_fn *default_set_md_params_fn;
|
|
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;
|
|
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(struct sk_prov_op_ctx *ctx,
|
|
struct sk_prov_key *key,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_signature_sign_init_fn *default_sign_init_fn;
|
|
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_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(struct sk_prov_op_ctx *ctx,
|
|
struct sk_prov_key *key,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_signature_verify_init_fn *default_verify_init_fn;
|
|
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(struct sk_prov_op_ctx *ctx,
|
|
struct sk_prov_key *key,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_signature_verify_recover_init_fn
|
|
*default_verify_recover_init_fn;
|
|
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(struct sk_prov_op_ctx *ctx,
|
|
unsigned char *sig, size_t siglen,
|
|
const unsigned char *tbs, size_t tbslen)
|
|
{
|
|
OSSL_FUNC_signature_verify_fn *default_verify_fn;
|
|
|
|
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(struct sk_prov_op_ctx *ctx,
|
|
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;
|
|
|
|
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[],
|
|
int (*sign_fn)
|
|
(struct sk_prov_op_ctx *,
|
|
unsigned char *, size_t *,
|
|
size_t, const unsigned char *,
|
|
size_t))
|
|
{
|
|
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);
|
|
|
|
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(struct sk_prov_op_ctx *ctx,
|
|
const unsigned char *data,
|
|
size_t datalen)
|
|
{
|
|
OSSL_FUNC_signature_digest_sign_update_fn
|
|
*default_digest_sign_update_fn;
|
|
|
|
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(struct sk_prov_op_ctx *ctx,
|
|
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];
|
|
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(struct sk_prov_op_ctx *ctx,
|
|
const char *mdname,
|
|
struct sk_prov_key *key,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_signature_digest_verify_init_fn
|
|
*default_digest_verify_init_fn;
|
|
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(struct sk_prov_op_ctx *ctx,
|
|
const unsigned char *data,
|
|
size_t datalen)
|
|
{
|
|
OSSL_FUNC_signature_digest_verify_update_fn
|
|
*default_digest_verify_update_fn;
|
|
|
|
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(struct sk_prov_op_ctx *ctx,
|
|
const unsigned char *sig,
|
|
size_t siglen)
|
|
{
|
|
OSSL_FUNC_signature_digest_verify_final_fn
|
|
*default_digest_verify_final_fn;
|
|
|
|
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(struct sk_prov_key *key)
|
|
{
|
|
OSSL_FUNC_keymgmt_free_fn *default_free_fn;
|
|
|
|
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 struct sk_prov_key *key1,
|
|
const struct sk_prov_key *key2,
|
|
int selection)
|
|
{
|
|
OSSL_FUNC_keymgmt_match_fn *default_match_fn;
|
|
|
|
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_PRIVATE_KEY) {
|
|
if (key1->secure_key_size != key2->secure_key_size)
|
|
return 0;
|
|
if (key1->secure_key_size > 0 &&
|
|
memcmp(key1->secure_key, key2->secure_key,
|
|
key1->secure_key_size) != 0)
|
|
return 0;
|
|
}
|
|
|
|
return default_match_fn(key1->default_key, key2->default_key,
|
|
selection);
|
|
}
|
|
|
|
static int sk_prov_keymgmt_validate(const struct sk_prov_key *key,
|
|
int selection, int checktype)
|
|
{
|
|
OSSL_FUNC_keymgmt_validate_fn *default_validate_fn;
|
|
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(struct sk_prov_key *key,
|
|
OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_keymgmt_get_params_fn *default_get_params_fn;
|
|
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(struct sk_prov_key *key,
|
|
OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_keymgmt_set_params_fn *default_set_params_fn;
|
|
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 struct sk_prov_key *key, int selection)
|
|
{
|
|
OSSL_FUNC_keymgmt_has_fn *default_has_fn;
|
|
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(struct sk_prov_key *key, int selection,
|
|
OSSL_CALLBACK *param_callback, void *cbarg)
|
|
{
|
|
OSSL_FUNC_keymgmt_export_fn *default_export_fn;
|
|
struct sk_prov_export_cb cb_data;
|
|
|
|
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(struct sk_prov_key *key, int selection,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
const OSSL_PARAM *p_blob, *p_funcs, *p_private, *p;
|
|
OSSL_FUNC_keymgmt_import_fn *default_import_fn;
|
|
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(struct sk_prov_op_ctx *genctx)
|
|
{
|
|
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(struct sk_prov_op_ctx *genctx,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_keymgmt_gen_set_params_fn *default_gen_set_params_fn;
|
|
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(struct sk_prov_op_ctx *genctx,
|
|
struct sk_prov_key *templ)
|
|
{
|
|
OSSL_FUNC_keymgmt_gen_set_template_fn *default_gen_set_template_fn;
|
|
|
|
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 struct sk_prov_key *sk_prov_keymgmt_gen(struct sk_prov_op_ctx *genctx,
|
|
OSSL_CALLBACK *osslcb, void *cbarg)
|
|
{
|
|
OSSL_FUNC_keymgmt_gen_fn *default_gen_fn;
|
|
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 struct sk_prov_key *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(struct sk_prov_ctx *provctx)
|
|
{
|
|
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(
|
|
struct sk_prov_ctx *provctx)
|
|
{
|
|
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(
|
|
struct sk_prov_ctx *provctx)
|
|
{
|
|
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 struct sk_prov_op_ctx *sk_prov_keymgmt_rsa_gen_init(
|
|
struct sk_prov_ctx *provctx, int selection,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
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(
|
|
struct sk_prov_op_ctx *genctx,
|
|
struct sk_prov_ctx *provctx)
|
|
{
|
|
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(struct sk_prov_ctx *provctx)
|
|
{
|
|
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(
|
|
struct sk_prov_ctx *provctx)
|
|
{
|
|
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(
|
|
struct sk_prov_ctx *provctx)
|
|
{
|
|
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 struct sk_prov_op_ctx *sk_prov_keymgmt_rsa_pss_gen_init(
|
|
struct sk_prov_ctx *provctx, int selection,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
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(
|
|
struct sk_prov_op_ctx *genctx,
|
|
struct sk_prov_ctx *provctx)
|
|
{
|
|
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(struct sk_prov_ctx *provctx)
|
|
{
|
|
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(
|
|
struct sk_prov_ctx *provctx)
|
|
{
|
|
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(
|
|
struct sk_prov_ctx *provctx)
|
|
{
|
|
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 struct sk_prov_op_ctx *sk_prov_keymgmt_ec_gen_init(
|
|
struct sk_prov_ctx *provctx, int selection,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
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(
|
|
struct sk_prov_op_ctx *genctx,
|
|
struct sk_prov_ctx *provctx)
|
|
{
|
|
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 struct sk_prov_op_ctx *sk_prov_keyexch_ec_newctx(
|
|
struct sk_prov_ctx *provctx)
|
|
{
|
|
OSSL_FUNC_keyexch_freectx_fn *default_freectx_fn;
|
|
OSSL_FUNC_keyexch_newctx_fn *default_newctx_fn;
|
|
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(struct sk_prov_op_ctx *ctx)
|
|
{
|
|
OSSL_FUNC_keyexch_dupctx_fn *default_dupctx_fn;
|
|
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(struct sk_prov_op_ctx *ctx,
|
|
struct sk_prov_key *key,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_keyexch_init_fn *default_init_fn;
|
|
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(struct sk_prov_op_ctx *ctx,
|
|
struct sk_prov_key *peerkey)
|
|
|
|
{
|
|
OSSL_FUNC_keyexch_set_peer_fn *default_set_peer_fn;
|
|
|
|
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(struct sk_prov_op_ctx *ctx,
|
|
unsigned char *secret, size_t *secretlen,
|
|
size_t outlen)
|
|
{
|
|
OSSL_FUNC_keyexch_derive_fn *default_derive_fn;
|
|
|
|
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(struct sk_prov_op_ctx *ctx,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_keyexch_set_ctx_params_fn *default_set_params_fn;
|
|
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(
|
|
struct sk_prov_op_ctx *ctx,
|
|
struct sk_prov_ctx *provctx)
|
|
{
|
|
OSSL_FUNC_keyexch_settable_ctx_params_fn
|
|
*default_settable_params_fn;
|
|
const OSSL_PARAM *params = NULL, *p;
|
|
|
|
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(struct sk_prov_op_ctx *ctx,
|
|
OSSL_PARAM params[])
|
|
{
|
|
OSSL_FUNC_keyexch_get_ctx_params_fn *default_get_params_fn;
|
|
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(
|
|
struct sk_prov_op_ctx *ctx,
|
|
struct sk_prov_ctx *provctx)
|
|
{
|
|
OSSL_FUNC_keyexch_gettable_ctx_params_fn
|
|
*default_gettable_params_fn;
|
|
const OSSL_PARAM *params = NULL, *p;
|
|
|
|
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 struct sk_prov_op_ctx *sk_prov_asym_rsa_newctx(
|
|
struct sk_prov_ctx *provctx)
|
|
{
|
|
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(
|
|
struct sk_prov_op_ctx *ctx,
|
|
struct sk_prov_ctx *provctx)
|
|
{
|
|
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(
|
|
struct sk_prov_op_ctx *ctx,
|
|
struct sk_prov_ctx *provctx)
|
|
{
|
|
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(struct sk_prov_op_ctx *ctx,
|
|
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;
|
|
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 struct sk_prov_op_ctx *sk_prov_sign_rsa_newctx(
|
|
struct sk_prov_ctx *provctx,
|
|
const char *propq)
|
|
{
|
|
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(
|
|
struct sk_prov_op_ctx *ctx,
|
|
struct sk_prov_ctx *provctx)
|
|
{
|
|
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(
|
|
struct sk_prov_op_ctx *ctx,
|
|
struct sk_prov_ctx *provctx)
|
|
{
|
|
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(
|
|
struct sk_prov_op_ctx *ctx)
|
|
{
|
|
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(
|
|
struct sk_prov_op_ctx *ctx)
|
|
{
|
|
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(struct sk_prov_op_ctx *ctx,
|
|
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_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(struct sk_prov_op_ctx *ctx,
|
|
const char *mdname,
|
|
struct sk_prov_key *key,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
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 struct sk_prov_op_ctx *sk_prov_sign_ec_newctx(
|
|
struct sk_prov_ctx *provctx,
|
|
const char *propq)
|
|
{
|
|
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(
|
|
struct sk_prov_op_ctx *ctx,
|
|
struct sk_prov_ctx *provctx)
|
|
{
|
|
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(
|
|
struct sk_prov_op_ctx *ctx,
|
|
struct sk_prov_ctx *provctx)
|
|
{
|
|
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(
|
|
struct sk_prov_op_ctx *ctx)
|
|
{
|
|
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(
|
|
struct sk_prov_op_ctx *ctx)
|
|
{
|
|
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(struct sk_prov_op_ctx *ctx,
|
|
unsigned char *sig, size_t *siglen,
|
|
size_t sigsize,
|
|
const unsigned char *tbs, size_t tbslen)
|
|
{
|
|
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(struct sk_prov_op_ctx *ctx,
|
|
const char *mdname,
|
|
struct sk_prov_key *key,
|
|
const OSSL_PARAM params[])
|
|
{
|
|
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(struct sk_prov_ctx *provctx)
|
|
{
|
|
if (provctx == NULL)
|
|
return NULL;
|
|
|
|
sk_debug_ctx(provctx, "provctx: %p", provctx);
|
|
return sk_prov_param_types;
|
|
}
|
|
|
|
static int sk_prov_get_params(struct sk_prov_ctx *provctx, OSSL_PARAM params[])
|
|
{
|
|
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(struct sk_prov_ctx *provctx,
|
|
int operation_id, int *no_cache)
|
|
{
|
|
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(struct sk_prov_ctx *provctx)
|
|
{
|
|
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(struct sk_prov_ctx *provctx)
|
|
{
|
|
sk_debug_ctx(provctx, "provctx: %p", provctx);
|
|
return sk_prov_reason_strings;
|
|
}
|
|
|
|
static int sk_prov_prov_get_capabilities(struct sk_prov_ctx *provctx,
|
|
const char *capability,
|
|
OSSL_CALLBACK *cb, void *arg)
|
|
{
|
|
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
|