Latest update.
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
|
||||
$DH_GOAL=../../libimplementations.a
|
||||
$ECX_GOAL=../../libimplementations.a
|
||||
$ECDH_GOAL=../../libimplementations.a
|
||||
|
||||
IF[{- !$disabled{dh} -}]
|
||||
SOURCE[$DH_GOAL]=dh_exch.c
|
||||
@@ -21,4 +22,5 @@ ENDIF
|
||||
IF[{- !$disabled{ec} -}]
|
||||
SOURCE[$ECX_GOAL]=ecx_exch.c
|
||||
DEFINE[$ECX_GOAL]=$ECDEF
|
||||
SOURCE[$ECDH_GOAL]=ecdh_exch.c
|
||||
ENDIF
|
||||
@@ -7,6 +7,12 @@
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* DH low level APIs are deprecated for public use, but still ok for
|
||||
* internal use.
|
||||
*/
|
||||
#include "internal/deprecated.h"
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/core_numbers.h>
|
||||
#include <openssl/core_names.h>
|
||||
|
||||
@@ -0,0 +1,533 @@
|
||||
/*
|
||||
* Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* ECDH low level APIs are deprecated for public use, but still ok for
|
||||
* internal use.
|
||||
*/
|
||||
#include "internal/deprecated.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/core_numbers.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/params.h>
|
||||
#include <openssl/err.h>
|
||||
#include "prov/provider_ctx.h"
|
||||
#include "prov/implementations.h"
|
||||
#include "crypto/ec.h" /* ecdh_KDF_X9_63() */
|
||||
|
||||
static OSSL_OP_keyexch_newctx_fn ecdh_newctx;
|
||||
static OSSL_OP_keyexch_init_fn ecdh_init;
|
||||
static OSSL_OP_keyexch_set_peer_fn ecdh_set_peer;
|
||||
static OSSL_OP_keyexch_derive_fn ecdh_derive;
|
||||
static OSSL_OP_keyexch_freectx_fn ecdh_freectx;
|
||||
static OSSL_OP_keyexch_dupctx_fn ecdh_dupctx;
|
||||
static OSSL_OP_keyexch_set_ctx_params_fn ecdh_set_ctx_params;
|
||||
static OSSL_OP_keyexch_settable_ctx_params_fn ecdh_settable_ctx_params;
|
||||
static OSSL_OP_keyexch_get_ctx_params_fn ecdh_get_ctx_params;
|
||||
static OSSL_OP_keyexch_gettable_ctx_params_fn ecdh_gettable_ctx_params;
|
||||
|
||||
enum kdf_type {
|
||||
PROV_ECDH_KDF_NONE = 0,
|
||||
PROV_ECDH_KDF_X9_63
|
||||
};
|
||||
|
||||
/*
|
||||
* What's passed as an actual key is defined by the KEYMGMT interface.
|
||||
* We happen to know that our KEYMGMT simply passes EC_KEY structures, so
|
||||
* we use that here too.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
OPENSSL_CTX *libctx;
|
||||
|
||||
EC_KEY *k;
|
||||
EC_KEY *peerk;
|
||||
|
||||
/*
|
||||
* ECDH cofactor mode:
|
||||
*
|
||||
* . 0 disabled
|
||||
* . 1 enabled
|
||||
* . -1 use cofactor mode set for k
|
||||
*/
|
||||
int cofactor_mode;
|
||||
|
||||
/************
|
||||
* ECDH KDF *
|
||||
************/
|
||||
/* KDF (if any) to use for ECDH */
|
||||
enum kdf_type kdf_type;
|
||||
/* Message digest to use for key derivation */
|
||||
EVP_MD *kdf_md;
|
||||
/* User key material */
|
||||
unsigned char *kdf_ukm;
|
||||
size_t kdf_ukmlen;
|
||||
/* KDF output length */
|
||||
size_t kdf_outlen;
|
||||
} PROV_ECDH_CTX;
|
||||
|
||||
static
|
||||
void *ecdh_newctx(void *provctx)
|
||||
{
|
||||
PROV_ECDH_CTX *pectx = OPENSSL_zalloc(sizeof(*pectx));
|
||||
|
||||
if (pectx == NULL)
|
||||
return NULL;
|
||||
|
||||
pectx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
|
||||
pectx->cofactor_mode = -1;
|
||||
pectx->kdf_type = PROV_ECDH_KDF_NONE;
|
||||
|
||||
return (void *)pectx;
|
||||
}
|
||||
|
||||
static
|
||||
int ecdh_init(void *vpecdhctx, void *vecdh)
|
||||
{
|
||||
PROV_ECDH_CTX *pecdhctx = (PROV_ECDH_CTX *)vpecdhctx;
|
||||
|
||||
if (pecdhctx == NULL || vecdh == NULL || !EC_KEY_up_ref(vecdh))
|
||||
return 0;
|
||||
EC_KEY_free(pecdhctx->k);
|
||||
pecdhctx->k = vecdh;
|
||||
pecdhctx->cofactor_mode = -1;
|
||||
pecdhctx->kdf_type = PROV_ECDH_KDF_NONE;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
int ecdh_set_peer(void *vpecdhctx, void *vecdh)
|
||||
{
|
||||
PROV_ECDH_CTX *pecdhctx = (PROV_ECDH_CTX *)vpecdhctx;
|
||||
|
||||
if (pecdhctx == NULL || vecdh == NULL || !EC_KEY_up_ref(vecdh))
|
||||
return 0;
|
||||
EC_KEY_free(pecdhctx->peerk);
|
||||
pecdhctx->peerk = vecdh;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
void ecdh_freectx(void *vpecdhctx)
|
||||
{
|
||||
PROV_ECDH_CTX *pecdhctx = (PROV_ECDH_CTX *)vpecdhctx;
|
||||
|
||||
EC_KEY_free(pecdhctx->k);
|
||||
EC_KEY_free(pecdhctx->peerk);
|
||||
|
||||
EVP_MD_free(pecdhctx->kdf_md);
|
||||
OPENSSL_clear_free(pecdhctx->kdf_ukm, pecdhctx->kdf_ukmlen);
|
||||
|
||||
OPENSSL_free(pecdhctx);
|
||||
}
|
||||
|
||||
static
|
||||
void *ecdh_dupctx(void *vpecdhctx)
|
||||
{
|
||||
PROV_ECDH_CTX *srcctx = (PROV_ECDH_CTX *)vpecdhctx;
|
||||
PROV_ECDH_CTX *dstctx;
|
||||
|
||||
dstctx = OPENSSL_zalloc(sizeof(*srcctx));
|
||||
if (dstctx == NULL)
|
||||
return NULL;
|
||||
|
||||
*dstctx = *srcctx;
|
||||
|
||||
/* clear all pointers */
|
||||
|
||||
dstctx->k= NULL;
|
||||
dstctx->peerk = NULL;
|
||||
dstctx->kdf_md = NULL;
|
||||
dstctx->kdf_ukm = NULL;
|
||||
|
||||
/* up-ref all ref-counted objects referenced in dstctx */
|
||||
|
||||
if (srcctx->k != NULL && !EC_KEY_up_ref(srcctx->k))
|
||||
goto err;
|
||||
else
|
||||
dstctx->k = srcctx->k;
|
||||
|
||||
if (srcctx->peerk != NULL && !EC_KEY_up_ref(srcctx->peerk))
|
||||
goto err;
|
||||
else
|
||||
dstctx->peerk = srcctx->peerk;
|
||||
|
||||
if (srcctx->kdf_md != NULL && !EVP_MD_up_ref(srcctx->kdf_md))
|
||||
goto err;
|
||||
else
|
||||
dstctx->kdf_md = srcctx->kdf_md;
|
||||
|
||||
/* Duplicate UKM data if present */
|
||||
if (srcctx->kdf_ukm != NULL && srcctx->kdf_ukmlen > 0) {
|
||||
dstctx->kdf_ukm = OPENSSL_memdup(srcctx->kdf_ukm,
|
||||
srcctx->kdf_ukmlen);
|
||||
if (dstctx->kdf_ukm == NULL)
|
||||
goto err;
|
||||
}
|
||||
|
||||
return dstctx;
|
||||
|
||||
err:
|
||||
ecdh_freectx(dstctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static
|
||||
int ecdh_set_ctx_params(void *vpecdhctx, const OSSL_PARAM params[])
|
||||
{
|
||||
char name[80] = { '\0' }; /* should be big enough */
|
||||
char *str = NULL;
|
||||
PROV_ECDH_CTX *pectx = (PROV_ECDH_CTX *)vpecdhctx;
|
||||
const OSSL_PARAM *p;
|
||||
|
||||
if (pectx == NULL || params == NULL)
|
||||
return 0;
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE);
|
||||
if (p != NULL) {
|
||||
int mode;
|
||||
|
||||
if (!OSSL_PARAM_get_int(p, &mode))
|
||||
return 0;
|
||||
|
||||
if (mode < -1 || mode > 1)
|
||||
return 0;
|
||||
|
||||
pectx->cofactor_mode = mode;
|
||||
}
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_TYPE);
|
||||
if (p != NULL) {
|
||||
str = name;
|
||||
if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(name)))
|
||||
return 0;
|
||||
|
||||
if (name[0] == '\0')
|
||||
pectx->kdf_type = PROV_ECDH_KDF_NONE;
|
||||
else if (strcmp(name, OSSL_KDF_NAME_X963KDF) == 0)
|
||||
pectx->kdf_type = PROV_ECDH_KDF_X9_63;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_DIGEST);
|
||||
if (p != NULL) {
|
||||
char mdprops[80] = { '\0' }; /* should be big enough */
|
||||
|
||||
str = name;
|
||||
if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(name)))
|
||||
return 0;
|
||||
|
||||
str = mdprops;
|
||||
p = OSSL_PARAM_locate_const(params,
|
||||
OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS);
|
||||
|
||||
if (p != NULL) {
|
||||
if (!OSSL_PARAM_get_utf8_string(p, &str, sizeof(mdprops)))
|
||||
return 0;
|
||||
}
|
||||
|
||||
EVP_MD_free(pectx->kdf_md);
|
||||
pectx->kdf_md = EVP_MD_fetch(pectx->libctx, name, mdprops);
|
||||
|
||||
if (pectx->kdf_md == NULL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_OUTLEN);
|
||||
if (p != NULL) {
|
||||
size_t outlen;
|
||||
|
||||
if (!OSSL_PARAM_get_size_t(p, &outlen))
|
||||
return 0;
|
||||
pectx->kdf_outlen = outlen;
|
||||
}
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_UKM);
|
||||
if (p != NULL) {
|
||||
void *tmp_ukm = NULL;
|
||||
size_t tmp_ukmlen;
|
||||
|
||||
if (!OSSL_PARAM_get_octet_string(p, &tmp_ukm, 0, &tmp_ukmlen))
|
||||
return 0;
|
||||
OPENSSL_free(pectx->kdf_ukm);
|
||||
pectx->kdf_ukm = tmp_ukm;
|
||||
pectx->kdf_ukmlen = tmp_ukmlen;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM known_settable_ctx_params[] = {
|
||||
OSSL_PARAM_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE, NULL),
|
||||
OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS, NULL, 0),
|
||||
OSSL_PARAM_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, NULL),
|
||||
OSSL_PARAM_octet_string(OSSL_EXCHANGE_PARAM_KDF_UKM, NULL, 0),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
|
||||
static
|
||||
const OSSL_PARAM *ecdh_settable_ctx_params(void)
|
||||
{
|
||||
return known_settable_ctx_params;
|
||||
}
|
||||
|
||||
static
|
||||
int ecdh_get_ctx_params(void *vpecdhctx, OSSL_PARAM params[])
|
||||
{
|
||||
PROV_ECDH_CTX *pectx = (PROV_ECDH_CTX *)vpecdhctx;
|
||||
OSSL_PARAM *p;
|
||||
|
||||
if (pectx == NULL || params == NULL)
|
||||
return 0;
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE);
|
||||
if (p != NULL) {
|
||||
int mode = pectx->cofactor_mode;
|
||||
|
||||
if (mode == -1) {
|
||||
/* check what is the default for pecdhctx->k */
|
||||
mode = EC_KEY_get_flags(pectx->k) & EC_FLAG_COFACTOR_ECDH ? 1 : 0;
|
||||
}
|
||||
|
||||
if (!OSSL_PARAM_set_int(p, mode))
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_TYPE);
|
||||
if (p != NULL) {
|
||||
const char *kdf_type = NULL;
|
||||
|
||||
switch (pectx->kdf_type) {
|
||||
case PROV_ECDH_KDF_NONE:
|
||||
kdf_type = "";
|
||||
break;
|
||||
case PROV_ECDH_KDF_X9_63:
|
||||
kdf_type = OSSL_KDF_NAME_X963KDF;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!OSSL_PARAM_set_utf8_string(p, kdf_type))
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_DIGEST);
|
||||
if (p != NULL
|
||||
&& !OSSL_PARAM_set_utf8_string(p, pectx->kdf_md == NULL
|
||||
? ""
|
||||
: EVP_MD_name(pectx->kdf_md))){
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_OUTLEN);
|
||||
if (p != NULL && !OSSL_PARAM_set_size_t(p, pectx->kdf_outlen))
|
||||
return 0;
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_UKM);
|
||||
if (p != NULL && !OSSL_PARAM_set_octet_ptr(p, pectx->kdf_ukm, 0))
|
||||
return 0;
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_KDF_UKM_LEN);
|
||||
if (p != NULL && !OSSL_PARAM_set_size_t(p, pectx->kdf_ukmlen))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM known_gettable_ctx_params[] = {
|
||||
OSSL_PARAM_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE, NULL),
|
||||
OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST, NULL, 0),
|
||||
OSSL_PARAM_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, NULL),
|
||||
OSSL_PARAM_DEFN(OSSL_EXCHANGE_PARAM_KDF_UKM, OSSL_PARAM_OCTET_PTR,
|
||||
NULL, 0),
|
||||
OSSL_PARAM_size_t(OSSL_EXCHANGE_PARAM_KDF_UKM_LEN, NULL),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
|
||||
static
|
||||
const OSSL_PARAM *ecdh_gettable_ctx_params(void)
|
||||
{
|
||||
return known_gettable_ctx_params;
|
||||
}
|
||||
|
||||
static ossl_inline
|
||||
size_t ecdh_size(const EC_KEY *k)
|
||||
{
|
||||
size_t degree = 0;
|
||||
const EC_GROUP *group;
|
||||
|
||||
if (k == NULL
|
||||
|| (group = EC_KEY_get0_group(k)) == NULL)
|
||||
return 0;
|
||||
|
||||
degree = EC_GROUP_get_degree(group);
|
||||
|
||||
return (degree + 7) / 8;
|
||||
}
|
||||
|
||||
static ossl_inline
|
||||
int ecdh_plain_derive(void *vpecdhctx, unsigned char *secret,
|
||||
size_t *psecretlen, size_t outlen)
|
||||
{
|
||||
PROV_ECDH_CTX *pecdhctx = (PROV_ECDH_CTX *)vpecdhctx;
|
||||
int retlen, ret = 0;
|
||||
size_t ecdhsize, size;
|
||||
const EC_POINT *ppubkey = NULL;
|
||||
EC_KEY *privk = NULL;
|
||||
const EC_GROUP *group;
|
||||
const BIGNUM *cofactor;
|
||||
int key_cofactor_mode;
|
||||
|
||||
if (pecdhctx->k == NULL || pecdhctx->peerk == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, EC_R_KEYS_NOT_SET);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ecdhsize = ecdh_size(pecdhctx->k);
|
||||
if (secret == NULL) {
|
||||
*psecretlen = ecdhsize;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((group = EC_KEY_get0_group(pecdhctx->k)) == NULL
|
||||
|| (cofactor = EC_GROUP_get0_cofactor(group)) == NULL )
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* NB: unlike PKCS#3 DH, if outlen is less than maximum size this is not
|
||||
* an error, the result is truncated.
|
||||
*/
|
||||
size = outlen < ecdhsize ? outlen : ecdhsize;
|
||||
|
||||
/*
|
||||
* The ctx->cofactor_mode flag has precedence over the
|
||||
* cofactor_mode flag set on ctx->k.
|
||||
*
|
||||
* - if ctx->cofactor_mode == -1, use ctx->k directly
|
||||
* - if ctx->cofactor_mode == key_cofactor_mode, use ctx->k directly
|
||||
* - if ctx->cofactor_mode != key_cofactor_mode:
|
||||
* - if ctx->k->cofactor == 1, the cofactor_mode flag is irrelevant, use
|
||||
* ctx->k directly
|
||||
* - if ctx->k->cofactor != 1, use a duplicate of ctx->k with the flag
|
||||
* set to ctx->cofactor_mode
|
||||
*/
|
||||
key_cofactor_mode =
|
||||
(EC_KEY_get_flags(pecdhctx->k) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;
|
||||
if (pecdhctx->cofactor_mode != -1
|
||||
&& pecdhctx->cofactor_mode != key_cofactor_mode
|
||||
&& !BN_is_one(cofactor)) {
|
||||
if ((privk = EC_KEY_dup(pecdhctx->k)) == NULL)
|
||||
return 0;
|
||||
|
||||
if (pecdhctx->cofactor_mode == 1)
|
||||
EC_KEY_set_flags(privk, EC_FLAG_COFACTOR_ECDH);
|
||||
else
|
||||
EC_KEY_clear_flags(privk, EC_FLAG_COFACTOR_ECDH);
|
||||
} else {
|
||||
privk = pecdhctx->k;
|
||||
}
|
||||
|
||||
ppubkey = EC_KEY_get0_public_key(pecdhctx->peerk);
|
||||
|
||||
retlen = ECDH_compute_key(secret, size, ppubkey, privk, NULL);
|
||||
|
||||
if (retlen <= 0)
|
||||
goto end;
|
||||
|
||||
*psecretlen = retlen;
|
||||
ret = 1;
|
||||
|
||||
end:
|
||||
if (privk != pecdhctx->k)
|
||||
EC_KEY_free(privk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ossl_inline
|
||||
int ecdh_X9_63_kdf_derive(void *vpecdhctx, unsigned char *secret,
|
||||
size_t *psecretlen, size_t outlen)
|
||||
{
|
||||
PROV_ECDH_CTX *pecdhctx = (PROV_ECDH_CTX *)vpecdhctx;
|
||||
unsigned char *stmp = NULL;
|
||||
size_t stmplen;
|
||||
int ret = 0;
|
||||
|
||||
if (secret == NULL) {
|
||||
*psecretlen = pecdhctx->kdf_outlen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (pecdhctx->kdf_outlen > outlen)
|
||||
return 0;
|
||||
if (!ecdh_plain_derive(vpecdhctx, NULL, &stmplen, 0))
|
||||
return 0;
|
||||
if ((stmp = OPENSSL_secure_malloc(stmplen)) == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
if (!ecdh_plain_derive(vpecdhctx, stmp, &stmplen, stmplen))
|
||||
goto err;
|
||||
|
||||
/* Do KDF stuff */
|
||||
if (!ecdh_KDF_X9_63(secret, pecdhctx->kdf_outlen,
|
||||
stmp, stmplen,
|
||||
pecdhctx->kdf_ukm,
|
||||
pecdhctx->kdf_ukmlen,
|
||||
pecdhctx->kdf_md))
|
||||
goto err;
|
||||
*psecretlen = pecdhctx->kdf_outlen;
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
OPENSSL_secure_clear_free(stmp, stmplen);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static
|
||||
int ecdh_derive(void *vpecdhctx, unsigned char *secret,
|
||||
size_t *psecretlen, size_t outlen)
|
||||
{
|
||||
PROV_ECDH_CTX *pecdhctx = (PROV_ECDH_CTX *)vpecdhctx;
|
||||
|
||||
switch (pecdhctx->kdf_type) {
|
||||
case PROV_ECDH_KDF_NONE:
|
||||
return ecdh_plain_derive(vpecdhctx, secret, psecretlen, outlen);
|
||||
case PROV_ECDH_KDF_X9_63:
|
||||
return ecdh_X9_63_kdf_derive(vpecdhctx, secret, psecretlen, outlen);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const OSSL_DISPATCH ecdh_keyexch_functions[] = {
|
||||
{ OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))ecdh_newctx },
|
||||
{ OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))ecdh_init },
|
||||
{ OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))ecdh_derive },
|
||||
{ OSSL_FUNC_KEYEXCH_SET_PEER, (void (*)(void))ecdh_set_peer },
|
||||
{ OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))ecdh_freectx },
|
||||
{ OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))ecdh_dupctx },
|
||||
{ OSSL_FUNC_KEYEXCH_SET_CTX_PARAMS, (void (*)(void))ecdh_set_ctx_params },
|
||||
{ OSSL_FUNC_KEYEXCH_SETTABLE_CTX_PARAMS,
|
||||
(void (*)(void))ecdh_settable_ctx_params },
|
||||
{ OSSL_FUNC_KEYEXCH_GET_CTX_PARAMS, (void (*)(void))ecdh_get_ctx_params },
|
||||
{ OSSL_FUNC_KEYEXCH_GETTABLE_CTX_PARAMS,
|
||||
(void (*)(void))ecdh_gettable_ctx_params },
|
||||
{ 0, NULL }
|
||||
};
|
||||
@@ -259,14 +259,17 @@ extern const OSSL_DISPATCH dsa_keymgmt_functions[];
|
||||
extern const OSSL_DISPATCH rsa_keymgmt_functions[];
|
||||
extern const OSSL_DISPATCH x25519_keymgmt_functions[];
|
||||
extern const OSSL_DISPATCH x448_keymgmt_functions[];
|
||||
extern const OSSL_DISPATCH ec_keymgmt_functions[];
|
||||
|
||||
/* Key Exchange */
|
||||
extern const OSSL_DISPATCH dh_keyexch_functions[];
|
||||
extern const OSSL_DISPATCH x25519_keyexch_functions[];
|
||||
extern const OSSL_DISPATCH x448_keyexch_functions[];
|
||||
extern const OSSL_DISPATCH ecdh_keyexch_functions[];
|
||||
|
||||
/* Signature */
|
||||
extern const OSSL_DISPATCH dsa_signature_functions[];
|
||||
extern const OSSL_DISPATCH rsa_signature_functions[];
|
||||
|
||||
/* Asym Cipher */
|
||||
extern const OSSL_DISPATCH rsa_asym_cipher_functions[];
|
||||
@@ -278,6 +281,7 @@ extern const OSSL_DISPATCH rsa_priv_der_serializer_functions[];
|
||||
extern const OSSL_DISPATCH rsa_pub_der_serializer_functions[];
|
||||
extern const OSSL_DISPATCH rsa_priv_pem_serializer_functions[];
|
||||
extern const OSSL_DISPATCH rsa_pub_pem_serializer_functions[];
|
||||
|
||||
extern const OSSL_DISPATCH dh_priv_text_serializer_functions[];
|
||||
extern const OSSL_DISPATCH dh_pub_text_serializer_functions[];
|
||||
extern const OSSL_DISPATCH dh_param_text_serializer_functions[];
|
||||
@@ -287,6 +291,7 @@ extern const OSSL_DISPATCH dh_param_der_serializer_functions[];
|
||||
extern const OSSL_DISPATCH dh_priv_pem_serializer_functions[];
|
||||
extern const OSSL_DISPATCH dh_pub_pem_serializer_functions[];
|
||||
extern const OSSL_DISPATCH dh_param_pem_serializer_functions[];
|
||||
|
||||
extern const OSSL_DISPATCH dsa_priv_text_serializer_functions[];
|
||||
extern const OSSL_DISPATCH dsa_pub_text_serializer_functions[];
|
||||
extern const OSSL_DISPATCH dsa_param_text_serializer_functions[];
|
||||
@@ -296,3 +301,17 @@ extern const OSSL_DISPATCH dsa_param_der_serializer_functions[];
|
||||
extern const OSSL_DISPATCH dsa_priv_pem_serializer_functions[];
|
||||
extern const OSSL_DISPATCH dsa_pub_pem_serializer_functions[];
|
||||
extern const OSSL_DISPATCH dsa_param_pem_serializer_functions[];
|
||||
|
||||
extern const OSSL_DISPATCH x25519_priv_print_serializer_functions[];
|
||||
extern const OSSL_DISPATCH x25519_pub_print_serializer_functions[];
|
||||
extern const OSSL_DISPATCH x25519_priv_der_serializer_functions[];
|
||||
extern const OSSL_DISPATCH x25519_pub_der_serializer_functions[];
|
||||
extern const OSSL_DISPATCH x25519_priv_pem_serializer_functions[];
|
||||
extern const OSSL_DISPATCH x25519_pub_pem_serializer_functions[];
|
||||
|
||||
extern const OSSL_DISPATCH x448_priv_print_serializer_functions[];
|
||||
extern const OSSL_DISPATCH x448_pub_print_serializer_functions[];
|
||||
extern const OSSL_DISPATCH x448_priv_der_serializer_functions[];
|
||||
extern const OSSL_DISPATCH x448_pub_der_serializer_functions[];
|
||||
extern const OSSL_DISPATCH x448_priv_pem_serializer_functions[];
|
||||
extern const OSSL_DISPATCH x448_pub_pem_serializer_functions[];
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
$DH_GOAL=../../libimplementations.a
|
||||
$DSA_GOAL=../../libimplementations.a
|
||||
$EC_GOAL=../../libimplementations.a
|
||||
$RSA_GOAL=../../libimplementations.a
|
||||
$ECX_GOAL=../../libimplementations.a
|
||||
|
||||
@@ -12,6 +13,9 @@ ENDIF
|
||||
IF[{- !$disabled{dsa} -}]
|
||||
SOURCE[$DSA_GOAL]=dsa_kmgmt.c
|
||||
ENDIF
|
||||
IF[{- !$disabled{ec} -}]
|
||||
SOURCE[$EC_GOAL]=ec_kmgmt.c
|
||||
ENDIF
|
||||
SOURCE[$RSA_GOAL]=rsa_kmgmt.c
|
||||
IF[{- !$disabled{ec} -}]
|
||||
SOURCE[$ECX_GOAL]=ecx_kmgmt.c
|
||||
|
||||
@@ -7,6 +7,12 @@
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* DH low level APIs are deprecated for public use, but still ok for
|
||||
* internal use.
|
||||
*/
|
||||
#include "internal/deprecated.h"
|
||||
|
||||
#include <openssl/core_numbers.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/bn.h>
|
||||
@@ -23,6 +29,7 @@ static OSSL_OP_keymgmt_free_fn dh_freedata;
|
||||
static OSSL_OP_keymgmt_get_params_fn dh_get_params;
|
||||
static OSSL_OP_keymgmt_gettable_params_fn dh_gettable_params;
|
||||
static OSSL_OP_keymgmt_has_fn dh_has;
|
||||
static OSSL_OP_keymgmt_match_fn dh_match;
|
||||
static OSSL_OP_keymgmt_import_fn dh_import;
|
||||
static OSSL_OP_keymgmt_import_types_fn dh_import_types;
|
||||
static OSSL_OP_keymgmt_export_fn dh_export;
|
||||
@@ -111,7 +118,7 @@ static int params_to_key(DH *dh, const OSSL_PARAM params[])
|
||||
return 1;
|
||||
|
||||
err:
|
||||
BN_free(priv_key);
|
||||
BN_clear_free(priv_key);
|
||||
BN_free(pub_key);
|
||||
return 0;
|
||||
}
|
||||
@@ -163,6 +170,25 @@ static int dh_has(void *keydata, int selection)
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int dh_match(const void *keydata1, const void *keydata2, int selection)
|
||||
{
|
||||
const DH *dh1 = keydata1;
|
||||
const DH *dh2 = keydata2;
|
||||
int ok = 1;
|
||||
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
|
||||
ok = ok && BN_cmp(DH_get0_pub_key(dh1), DH_get0_pub_key(dh2)) == 0;
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
|
||||
ok = ok && BN_cmp(DH_get0_priv_key(dh1), DH_get0_priv_key(dh2)) == 0;
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
|
||||
FFC_PARAMS *dhparams1 = dh_get0_params((DH *)dh1);
|
||||
FFC_PARAMS *dhparams2 = dh_get0_params((DH *)dh2);
|
||||
|
||||
ok = ok && ffc_params_cmp(dhparams1, dhparams2, 1);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int dh_import(void *keydata, int selection, const OSSL_PARAM params[])
|
||||
{
|
||||
DH *dh = keydata;
|
||||
@@ -296,6 +322,7 @@ const OSSL_DISPATCH dh_keymgmt_functions[] = {
|
||||
{ OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))dh_get_params },
|
||||
{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))dh_gettable_params },
|
||||
{ OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))dh_has },
|
||||
{ OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))dh_match },
|
||||
{ OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))dh_import },
|
||||
{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))dh_import_types },
|
||||
{ OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))dh_export },
|
||||
|
||||
@@ -29,6 +29,7 @@ static OSSL_OP_keymgmt_free_fn dsa_freedata;
|
||||
static OSSL_OP_keymgmt_get_params_fn dsa_get_params;
|
||||
static OSSL_OP_keymgmt_gettable_params_fn dsa_gettable_params;
|
||||
static OSSL_OP_keymgmt_has_fn dsa_has;
|
||||
static OSSL_OP_keymgmt_match_fn dsa_match;
|
||||
static OSSL_OP_keymgmt_import_fn dsa_import;
|
||||
static OSSL_OP_keymgmt_import_types_fn dsa_import_types;
|
||||
static OSSL_OP_keymgmt_export_fn dsa_export;
|
||||
@@ -123,7 +124,7 @@ static int params_to_key(DSA *dsa, const OSSL_PARAM params[])
|
||||
return 1;
|
||||
|
||||
err:
|
||||
BN_free(priv_key);
|
||||
BN_clear_free(priv_key);
|
||||
BN_free(pub_key);
|
||||
return 0;
|
||||
}
|
||||
@@ -175,6 +176,27 @@ static int dsa_has(void *keydata, int selection)
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int dsa_match(const void *keydata1, const void *keydata2, int selection)
|
||||
{
|
||||
const DSA *dsa1 = keydata1;
|
||||
const DSA *dsa2 = keydata2;
|
||||
int ok = 1;
|
||||
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
|
||||
ok = ok
|
||||
&& BN_cmp(DSA_get0_pub_key(dsa1), DSA_get0_pub_key(dsa2)) == 0;
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
|
||||
ok = ok
|
||||
&& BN_cmp(DSA_get0_priv_key(dsa1), DSA_get0_priv_key(dsa2)) == 0;
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
|
||||
FFC_PARAMS *dsaparams1 = dsa_get0_params((DSA *)dsa1);
|
||||
FFC_PARAMS *dsaparams2 = dsa_get0_params((DSA *)dsa2);
|
||||
|
||||
ok = ok && ffc_params_cmp(dsaparams1, dsaparams2, 1);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int dsa_import(void *keydata, int selection, const OSSL_PARAM params[])
|
||||
{
|
||||
DSA *dsa = keydata;
|
||||
@@ -313,6 +335,7 @@ const OSSL_DISPATCH dsa_keymgmt_functions[] = {
|
||||
{ OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))dsa_get_params },
|
||||
{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))dsa_gettable_params },
|
||||
{ OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))dsa_has },
|
||||
{ OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))dsa_match },
|
||||
{ OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))dsa_import },
|
||||
{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))dsa_import_types },
|
||||
{ OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))dsa_export },
|
||||
|
||||
@@ -0,0 +1,749 @@
|
||||
/*
|
||||
* Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* ECDH/ECDSA low level APIs are deprecated for public use, but still ok for
|
||||
* internal use.
|
||||
*/
|
||||
#include "internal/deprecated.h"
|
||||
|
||||
#include <openssl/core_numbers.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/params.h>
|
||||
#include "crypto/bn.h"
|
||||
#include "internal/param_build.h"
|
||||
#include "prov/implementations.h"
|
||||
#include "prov/providercommon.h"
|
||||
|
||||
static OSSL_OP_keymgmt_new_fn ec_newdata;
|
||||
static OSSL_OP_keymgmt_free_fn ec_freedata;
|
||||
static OSSL_OP_keymgmt_get_params_fn ec_get_params;
|
||||
static OSSL_OP_keymgmt_gettable_params_fn ec_gettable_params;
|
||||
static OSSL_OP_keymgmt_set_params_fn ec_set_params;
|
||||
static OSSL_OP_keymgmt_settable_params_fn ec_settable_params;
|
||||
static OSSL_OP_keymgmt_has_fn ec_has;
|
||||
static OSSL_OP_keymgmt_match_fn ec_match;
|
||||
static OSSL_OP_keymgmt_import_fn ec_import;
|
||||
static OSSL_OP_keymgmt_import_types_fn ec_import_types;
|
||||
static OSSL_OP_keymgmt_export_fn ec_export;
|
||||
static OSSL_OP_keymgmt_export_types_fn ec_export_types;
|
||||
static OSSL_OP_keymgmt_query_operation_name_fn ec_query_operation_name;
|
||||
|
||||
#define EC_POSSIBLE_SELECTIONS \
|
||||
(OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS )
|
||||
|
||||
static
|
||||
const char *ec_query_operation_name(int operation_id)
|
||||
{
|
||||
switch (operation_id) {
|
||||
case OSSL_OP_KEYEXCH:
|
||||
return "ECDH";
|
||||
#if 0
|
||||
case OSSL_OP_SIGNATURE:
|
||||
return deflt_signature;
|
||||
#endif
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static ossl_inline
|
||||
int params_to_domparams(EC_KEY *ec, const OSSL_PARAM params[])
|
||||
{
|
||||
const OSSL_PARAM *param_ec_name;
|
||||
EC_GROUP *ecg = NULL;
|
||||
char *curve_name = NULL;
|
||||
int ok = 0;
|
||||
|
||||
if (ec == NULL)
|
||||
return 0;
|
||||
|
||||
param_ec_name = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_NAME);
|
||||
if (param_ec_name == NULL) {
|
||||
/* explicit parameters */
|
||||
|
||||
/*
|
||||
* TODO(3.0): should we support explicit parameters curves?
|
||||
*/
|
||||
return 0;
|
||||
} else {
|
||||
/* named curve */
|
||||
int curve_nid;
|
||||
|
||||
if (!OSSL_PARAM_get_utf8_string(param_ec_name, &curve_name, 0)
|
||||
|| curve_name == NULL
|
||||
|| (curve_nid = OBJ_sn2nid(curve_name)) == NID_undef)
|
||||
goto err;
|
||||
|
||||
if ((ecg = EC_GROUP_new_by_curve_name(curve_nid)) == NULL)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!EC_KEY_set_group(ec, ecg))
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* TODO(3.0): if the group has changed, should we invalidate the private and
|
||||
* public key?
|
||||
*/
|
||||
|
||||
ok = 1;
|
||||
|
||||
err:
|
||||
OPENSSL_free(curve_name);
|
||||
EC_GROUP_free(ecg);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static ossl_inline
|
||||
int domparams_to_params(const EC_KEY *ec, OSSL_PARAM_BLD *tmpl)
|
||||
{
|
||||
const EC_GROUP *ecg;
|
||||
int curve_nid;
|
||||
|
||||
if (ec == NULL)
|
||||
return 0;
|
||||
|
||||
ecg = EC_KEY_get0_group(ec);
|
||||
if (ecg == NULL)
|
||||
return 0;
|
||||
|
||||
curve_nid = EC_GROUP_get_curve_name(ecg);
|
||||
|
||||
if (curve_nid == NID_undef) {
|
||||
/* explicit parameters */
|
||||
|
||||
/*
|
||||
* TODO(3.0): should we support explicit parameters curves?
|
||||
*/
|
||||
return 0;
|
||||
} else {
|
||||
/* named curve */
|
||||
const char *curve_name = NULL;
|
||||
|
||||
if ((curve_name = OBJ_nid2sn(curve_nid)) == NULL)
|
||||
return 0;
|
||||
|
||||
if (!ossl_param_bld_push_utf8_string(tmpl, OSSL_PKEY_PARAM_EC_NAME, curve_name, 0))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Callers of params_to_key MUST make sure that params_to_domparams has been
|
||||
* called before!
|
||||
*
|
||||
* This function only imports the bare keypair, domain parameters and other
|
||||
* parameters are imported separately, and domain parameters are required to
|
||||
* define a keypair.
|
||||
*/
|
||||
static ossl_inline
|
||||
int params_to_key(EC_KEY *ec, const OSSL_PARAM params[], int include_private)
|
||||
{
|
||||
const OSSL_PARAM *param_priv_key, *param_pub_key;
|
||||
BIGNUM *priv_key = NULL;
|
||||
unsigned char *pub_key = NULL;
|
||||
size_t pub_key_len;
|
||||
const EC_GROUP *ecg = NULL;
|
||||
EC_POINT *pub_point = NULL;
|
||||
int ok = 0;
|
||||
|
||||
ecg = EC_KEY_get0_group(ec);
|
||||
if (ecg == NULL)
|
||||
return 0;
|
||||
|
||||
param_priv_key =
|
||||
OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY);
|
||||
param_pub_key =
|
||||
OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY);
|
||||
|
||||
/*
|
||||
* We want to have at least a public key either way, so we end up
|
||||
* requiring it unconditionally.
|
||||
*/
|
||||
if (param_pub_key == NULL
|
||||
|| !OSSL_PARAM_get_octet_string(param_pub_key,
|
||||
(void **)&pub_key, 0, &pub_key_len)
|
||||
|| (pub_point = EC_POINT_new(ecg)) == NULL
|
||||
|| !EC_POINT_oct2point(ecg, pub_point,
|
||||
pub_key, pub_key_len, NULL))
|
||||
goto err;
|
||||
|
||||
if (param_priv_key != NULL && include_private) {
|
||||
int fixed_top;
|
||||
const BIGNUM *order;
|
||||
|
||||
/*
|
||||
* Key import/export should never leak the bit length of the secret
|
||||
* scalar in the key.
|
||||
*
|
||||
* For this reason, on export we use padded BIGNUMs with fixed length.
|
||||
*
|
||||
* When importing we also should make sure that, even if short lived,
|
||||
* the newly created BIGNUM is marked with the BN_FLG_CONSTTIME flag as
|
||||
* soon as possible, so that any processing of this BIGNUM might opt for
|
||||
* constant time implementations in the backend.
|
||||
*
|
||||
* Setting the BN_FLG_CONSTTIME flag alone is never enough, we also have
|
||||
* to preallocate the BIGNUM internal buffer to a fixed public size big
|
||||
* enough that operations performed during the processing never trigger
|
||||
* a realloc which would leak the size of the scalar through memory
|
||||
* accesses.
|
||||
*
|
||||
* Fixed Length
|
||||
* ------------
|
||||
*
|
||||
* The order of the large prime subgroup of the curve is our choice for
|
||||
* a fixed public size, as that is generally the upper bound for
|
||||
* generating a private key in EC cryptosystems and should fit all valid
|
||||
* secret scalars.
|
||||
*
|
||||
* For padding on export we just use the bit length of the order
|
||||
* converted to bytes (rounding up).
|
||||
*
|
||||
* For preallocating the BIGNUM storage we look at the number of "words"
|
||||
* required for the internal representation of the order, and we
|
||||
* preallocate 2 extra "words" in case any of the subsequent processing
|
||||
* might temporarily overflow the order length.
|
||||
*/
|
||||
order = EC_GROUP_get0_order(ecg);
|
||||
if (order == NULL || BN_is_zero(order))
|
||||
goto err;
|
||||
|
||||
fixed_top = bn_get_top(order) + 2;
|
||||
|
||||
if ((priv_key = BN_new()) == NULL)
|
||||
goto err;
|
||||
if (bn_wexpand(priv_key, fixed_top) == NULL)
|
||||
goto err;
|
||||
BN_set_flags(priv_key, BN_FLG_CONSTTIME);
|
||||
|
||||
if (!OSSL_PARAM_get_BN(param_priv_key, &priv_key))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (priv_key != NULL
|
||||
&& !EC_KEY_set_private_key(ec, priv_key))
|
||||
goto err;
|
||||
|
||||
if (!EC_KEY_set_public_key(ec, pub_point))
|
||||
goto err;
|
||||
|
||||
ok = 1;
|
||||
|
||||
err:
|
||||
BN_clear_free(priv_key);
|
||||
OPENSSL_free(pub_key);
|
||||
EC_POINT_free(pub_point);
|
||||
return ok;
|
||||
}
|
||||
|
||||
/*
|
||||
* Callers of key_to_params MUST make sure that domparams_to_params is also
|
||||
* called!
|
||||
*
|
||||
* This function only exports the bare keypair, domain parameters and other
|
||||
* parameters are exported separately.
|
||||
*/
|
||||
static ossl_inline
|
||||
int key_to_params(const EC_KEY *eckey, OSSL_PARAM_BLD *tmpl, int include_private)
|
||||
{
|
||||
const BIGNUM *priv_key = NULL;
|
||||
const EC_POINT *pub_point = NULL;
|
||||
const EC_GROUP *ecg = NULL;
|
||||
unsigned char *pub_key = NULL;
|
||||
size_t pub_key_len = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (eckey == NULL)
|
||||
return 0;
|
||||
|
||||
ecg = EC_KEY_get0_group(eckey);
|
||||
priv_key = EC_KEY_get0_private_key(eckey);
|
||||
pub_point = EC_KEY_get0_public_key(eckey);
|
||||
|
||||
/* group and public_key must be present, priv_key is optional */
|
||||
if (ecg == NULL || pub_point == NULL)
|
||||
return 0;
|
||||
if ((pub_key_len = EC_POINT_point2buf(ecg, pub_point,
|
||||
POINT_CONVERSION_COMPRESSED,
|
||||
&pub_key, NULL)) == 0)
|
||||
return 0;
|
||||
|
||||
if (!ossl_param_bld_push_octet_string(tmpl,
|
||||
OSSL_PKEY_PARAM_PUB_KEY,
|
||||
pub_key, pub_key_len))
|
||||
goto err;
|
||||
|
||||
if (priv_key != NULL && include_private) {
|
||||
size_t sz;
|
||||
int ecbits;
|
||||
|
||||
/*
|
||||
* Key import/export should never leak the bit length of the secret
|
||||
* scalar in the key.
|
||||
*
|
||||
* For this reason, on export we use padded BIGNUMs with fixed length.
|
||||
*
|
||||
* When importing we also should make sure that, even if short lived,
|
||||
* the newly created BIGNUM is marked with the BN_FLG_CONSTTIME flag as
|
||||
* soon as possible, so that any processing of this BIGNUM might opt for
|
||||
* constant time implementations in the backend.
|
||||
*
|
||||
* Setting the BN_FLG_CONSTTIME flag alone is never enough, we also have
|
||||
* to preallocate the BIGNUM internal buffer to a fixed public size big
|
||||
* enough that operations performed during the processing never trigger
|
||||
* a realloc which would leak the size of the scalar through memory
|
||||
* accesses.
|
||||
*
|
||||
* Fixed Length
|
||||
* ------------
|
||||
*
|
||||
* The order of the large prime subgroup of the curve is our choice for
|
||||
* a fixed public size, as that is generally the upper bound for
|
||||
* generating a private key in EC cryptosystems and should fit all valid
|
||||
* secret scalars.
|
||||
*
|
||||
* For padding on export we just use the bit length of the order
|
||||
* converted to bytes (rounding up).
|
||||
*
|
||||
* For preallocating the BIGNUM storage we look at the number of "words"
|
||||
* required for the internal representation of the order, and we
|
||||
* preallocate 2 extra "words" in case any of the subsequent processing
|
||||
* might temporarily overflow the order length.
|
||||
*/
|
||||
ecbits = EC_GROUP_order_bits(ecg);
|
||||
if (ecbits <= 0)
|
||||
goto err;
|
||||
sz = (ecbits + 7 ) / 8;
|
||||
if (!ossl_param_bld_push_BN_pad(tmpl,
|
||||
OSSL_PKEY_PARAM_PRIV_KEY,
|
||||
priv_key, sz))
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
OPENSSL_free(pub_key);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ossl_inline
|
||||
int ec_set_param_ecdh_cofactor_mode(EC_KEY *ec, const OSSL_PARAM *p)
|
||||
{
|
||||
const EC_GROUP *ecg = EC_KEY_get0_group(ec);
|
||||
const BIGNUM *cofactor;
|
||||
int mode;
|
||||
|
||||
if (!OSSL_PARAM_get_int(p, &mode))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* mode can be only 0 for disable, or 1 for enable here.
|
||||
*
|
||||
* This is in contrast with the same parameter on an ECDH EVP_PKEY_CTX that
|
||||
* also supports mode == -1 with the meaning of "reset to the default for
|
||||
* the associated key".
|
||||
*/
|
||||
if (mode < 0 || mode > 1)
|
||||
return 0;
|
||||
|
||||
if ((cofactor = EC_GROUP_get0_cofactor(ecg)) == NULL )
|
||||
return 0;
|
||||
|
||||
/* ECDH cofactor mode has no effect if cofactor is 1 */
|
||||
if (BN_is_one(cofactor))
|
||||
return 1;
|
||||
|
||||
if (mode == 1)
|
||||
EC_KEY_set_flags(ec, EC_FLAG_COFACTOR_ECDH);
|
||||
else if (mode == 0)
|
||||
EC_KEY_clear_flags(ec, EC_FLAG_COFACTOR_ECDH);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static ossl_inline
|
||||
int params_to_otherparams(EC_KEY *ec, const OSSL_PARAM params[])
|
||||
{
|
||||
const OSSL_PARAM *p;
|
||||
|
||||
if (ec == NULL)
|
||||
return 0;
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH);
|
||||
if (p != NULL && !ec_set_param_ecdh_cofactor_mode(ec, p))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static ossl_inline
|
||||
int otherparams_to_params(const EC_KEY *ec, OSSL_PARAM_BLD *tmpl)
|
||||
{
|
||||
int ecdh_cofactor_mode = 0;
|
||||
|
||||
if (ec == NULL)
|
||||
return 0;
|
||||
|
||||
ecdh_cofactor_mode =
|
||||
(EC_KEY_get_flags(ec) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;
|
||||
if (!ossl_param_bld_push_int(tmpl,
|
||||
OSSL_PKEY_PARAM_USE_COFACTOR_ECDH,
|
||||
ecdh_cofactor_mode))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static
|
||||
void *ec_newdata(void *provctx)
|
||||
{
|
||||
return EC_KEY_new();
|
||||
}
|
||||
|
||||
static
|
||||
void ec_freedata(void *keydata)
|
||||
{
|
||||
EC_KEY_free(keydata);
|
||||
}
|
||||
|
||||
static
|
||||
int ec_has(void *keydata, int selection)
|
||||
{
|
||||
EC_KEY *ec = keydata;
|
||||
int ok = 0;
|
||||
|
||||
if ((selection & EC_POSSIBLE_SELECTIONS) != 0)
|
||||
ok = 1;
|
||||
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
|
||||
ok = ok && (EC_KEY_get0_public_key(ec) != NULL);
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
|
||||
ok = ok && (EC_KEY_get0_private_key(ec) != NULL);
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
|
||||
ok = ok && (EC_KEY_get0_group(ec) != NULL);
|
||||
/*
|
||||
* We consider OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS to always be available,
|
||||
* so no extra check is needed other than the previous one against
|
||||
* EC_POSSIBLE_SELECTIONS.
|
||||
*/
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int ec_match(const void *keydata1, const void *keydata2, int selection)
|
||||
{
|
||||
const EC_KEY *ec1 = keydata1;
|
||||
const EC_KEY *ec2 = keydata2;
|
||||
const EC_GROUP *group_a = EC_KEY_get0_group(ec1);
|
||||
const EC_GROUP *group_b = EC_KEY_get0_group(ec2);
|
||||
int ok = 1;
|
||||
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
|
||||
ok = ok && group_a != NULL && group_b != NULL
|
||||
&& EC_GROUP_cmp(group_a, group_b, NULL) == 0;
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
|
||||
const BIGNUM *pa = EC_KEY_get0_private_key(ec1);
|
||||
const BIGNUM *pb = EC_KEY_get0_private_key(ec2);
|
||||
|
||||
ok = ok && BN_cmp(pa, pb) == 0;
|
||||
}
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
|
||||
const EC_POINT *pa = EC_KEY_get0_public_key(ec1);
|
||||
const EC_POINT *pb = EC_KEY_get0_public_key(ec2);
|
||||
|
||||
ok = ok && EC_POINT_cmp(group_b, pa, pb, NULL);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
static
|
||||
int ec_import(void *keydata, int selection, const OSSL_PARAM params[])
|
||||
{
|
||||
EC_KEY *ec = keydata;
|
||||
int ok = 0;
|
||||
|
||||
if (ec == NULL)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* In this implementation, we can export/import only keydata in the
|
||||
* following combinations:
|
||||
* - domain parameters only
|
||||
* - public key with associated domain parameters (+optional other params)
|
||||
* - private key with associated public key and domain parameters
|
||||
* (+optional other params)
|
||||
*
|
||||
* This means:
|
||||
* - domain parameters must always be requested
|
||||
* - private key must be requested alongside public key
|
||||
* - other parameters must be requested only alongside a key
|
||||
*/
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0)
|
||||
return 0;
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
|
||||
&& (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) == 0)
|
||||
return 0;
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0
|
||||
&& (selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
|
||||
return 0;
|
||||
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
|
||||
ok = ok && params_to_domparams(ec, params);
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
|
||||
int include_private =
|
||||
selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
|
||||
|
||||
ok = ok && params_to_key(ec, params, include_private);
|
||||
}
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
|
||||
ok = ok && params_to_otherparams(ec, params);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
static
|
||||
int ec_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
|
||||
void *cbarg)
|
||||
{
|
||||
EC_KEY *ec = keydata;
|
||||
OSSL_PARAM_BLD tmpl;
|
||||
OSSL_PARAM *params = NULL;
|
||||
int ok = 1;
|
||||
|
||||
if (ec == NULL)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* In this implementation, we can export/import only keydata in the
|
||||
* following combinations:
|
||||
* - domain parameters only
|
||||
* - public key with associated domain parameters (+optional other params)
|
||||
* - private key with associated public key and domain parameters
|
||||
* (+optional other params)
|
||||
*
|
||||
* This means:
|
||||
* - domain parameters must always be requested
|
||||
* - private key must be requested alongside public key
|
||||
* - other parameters must be requested only alongside a key
|
||||
*/
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0)
|
||||
return 0;
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
|
||||
&& (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) == 0)
|
||||
return 0;
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0
|
||||
&& (selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
|
||||
return 0;
|
||||
|
||||
ossl_param_bld_init(&tmpl);
|
||||
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
|
||||
ok = ok && domparams_to_params(ec, &tmpl);
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
|
||||
int include_private =
|
||||
selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
|
||||
|
||||
ok = ok && key_to_params(ec, &tmpl, include_private);
|
||||
}
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
|
||||
ok = ok && otherparams_to_params(ec, &tmpl);
|
||||
|
||||
if (!ok
|
||||
|| (params = ossl_param_bld_to_param(&tmpl)) == NULL)
|
||||
return 0;
|
||||
|
||||
ok = param_cb(params, cbarg);
|
||||
ossl_param_bld_free(params);
|
||||
return ok;
|
||||
}
|
||||
|
||||
/* IMEXPORT = IMPORT + EXPORT */
|
||||
|
||||
# define EC_IMEXPORTABLE_DOM_PARAMETERS \
|
||||
OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_NAME, NULL, 0)
|
||||
# define EC_IMEXPORTABLE_PUBLIC_KEY \
|
||||
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0)
|
||||
# define EC_IMEXPORTABLE_PRIVATE_KEY \
|
||||
OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
|
||||
# define EC_IMEXPORTABLE_OTHER_PARAMETERS \
|
||||
OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL)
|
||||
|
||||
/*
|
||||
* Include all the possible combinations of OSSL_PARAM arrays for
|
||||
* ec_imexport_types().
|
||||
*
|
||||
* They are in a separate file as it is ~100 lines of unreadable and
|
||||
* uninteresting machine generated stuff.
|
||||
*
|
||||
* TODO(3.0): the generated list looks quite ugly, as to cover all possible
|
||||
* combinations of the bits in `selection`, it also includes combinations that
|
||||
* are not really useful: we might want to consider alternatives to this
|
||||
* solution.
|
||||
*/
|
||||
#include "ec_kmgmt_imexport.inc"
|
||||
|
||||
static ossl_inline
|
||||
const OSSL_PARAM *ec_imexport_types(int selection)
|
||||
{
|
||||
int type_select = 0;
|
||||
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
|
||||
type_select += 1;
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
|
||||
type_select += 2;
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
|
||||
type_select += 4;
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
|
||||
type_select += 8;
|
||||
return ec_types[type_select];
|
||||
}
|
||||
|
||||
static
|
||||
const OSSL_PARAM *ec_import_types(int selection)
|
||||
{
|
||||
return ec_imexport_types(selection);
|
||||
}
|
||||
|
||||
static
|
||||
const OSSL_PARAM *ec_export_types(int selection)
|
||||
{
|
||||
return ec_imexport_types(selection);
|
||||
}
|
||||
|
||||
static
|
||||
int ec_get_params(void *key, OSSL_PARAM params[])
|
||||
{
|
||||
EC_KEY *eck = key;
|
||||
const EC_GROUP *ecg = NULL;
|
||||
OSSL_PARAM *p;
|
||||
|
||||
ecg = EC_KEY_get0_group(eck);
|
||||
if (ecg == NULL)
|
||||
return 0;
|
||||
|
||||
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
|
||||
&& !OSSL_PARAM_set_int(p, ECDSA_size(eck)))
|
||||
return 0;
|
||||
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
|
||||
&& !OSSL_PARAM_set_int(p, EC_GROUP_order_bits(ecg)))
|
||||
return 0;
|
||||
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL) {
|
||||
int ecbits, sec_bits;
|
||||
|
||||
ecbits = EC_GROUP_order_bits(ecg);
|
||||
|
||||
/*
|
||||
* The following estimates are based on the values published
|
||||
* in Table 2 of "NIST Special Publication 800-57 Part 1 Revision 4"
|
||||
* at http://dx.doi.org/10.6028/NIST.SP.800-57pt1r4 .
|
||||
*
|
||||
* Note that the above reference explicitly categorizes algorithms in a
|
||||
* discrete set of values {80, 112, 128, 192, 256}, and that it is
|
||||
* relevant only for NIST approved Elliptic Curves, while OpenSSL
|
||||
* applies the same logic also to other curves.
|
||||
*
|
||||
* Classifications produced by other standardazing bodies might differ,
|
||||
* so the results provided for "bits of security" by this provider are
|
||||
* to be considered merely indicative, and it is the users'
|
||||
* responsibility to compare these values against the normative
|
||||
* references that may be relevant for their intent and purposes.
|
||||
*/
|
||||
if (ecbits >= 512)
|
||||
sec_bits = 256;
|
||||
else if (ecbits >= 384)
|
||||
sec_bits = 192;
|
||||
else if (ecbits >= 256)
|
||||
sec_bits = 128;
|
||||
else if (ecbits >= 224)
|
||||
sec_bits = 112;
|
||||
else if (ecbits >= 160)
|
||||
sec_bits = 80;
|
||||
else
|
||||
sec_bits = ecbits / 2;
|
||||
|
||||
if (!OSSL_PARAM_set_int(p, sec_bits))
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH);
|
||||
if (p != NULL) {
|
||||
int ecdh_cofactor_mode = 0;
|
||||
|
||||
ecdh_cofactor_mode =
|
||||
(EC_KEY_get_flags(eck) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;
|
||||
|
||||
if (!OSSL_PARAM_set_int(p, ecdh_cofactor_mode))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM ec_known_gettable_params[] = {
|
||||
OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
|
||||
OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
|
||||
OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
|
||||
OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
|
||||
static
|
||||
const OSSL_PARAM *ec_gettable_params(void)
|
||||
{
|
||||
return ec_known_gettable_params;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM ec_known_settable_params[] = {
|
||||
OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
|
||||
static
|
||||
const OSSL_PARAM *ec_settable_params(void)
|
||||
{
|
||||
return ec_known_settable_params;
|
||||
}
|
||||
|
||||
static
|
||||
int ec_set_params(void *key, const OSSL_PARAM params[])
|
||||
{
|
||||
EC_KEY *eck = key;
|
||||
const OSSL_PARAM *p;
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH);
|
||||
if (p != NULL && !ec_set_param_ecdh_cofactor_mode(eck, p))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const OSSL_DISPATCH ec_keymgmt_functions[] = {
|
||||
{ OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))ec_newdata },
|
||||
{ OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ec_freedata },
|
||||
{ OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))ec_get_params },
|
||||
{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))ec_gettable_params },
|
||||
{ OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))ec_set_params },
|
||||
{ OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))ec_settable_params },
|
||||
{ OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ec_has },
|
||||
{ OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ec_match },
|
||||
{ OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ec_import },
|
||||
{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ec_import_types },
|
||||
{ OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ec_export },
|
||||
{ OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ec_export_types },
|
||||
{ OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME,
|
||||
(void (*)(void))ec_query_operation_name },
|
||||
{ 0, NULL }
|
||||
};
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* This file is meant to be included from ec_kmgmt.c
|
||||
*/
|
||||
|
||||
static const OSSL_PARAM ec_private_key_types[] = {
|
||||
EC_IMEXPORTABLE_PRIVATE_KEY,
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM ec_public_key_types[] = {
|
||||
EC_IMEXPORTABLE_PUBLIC_KEY,
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM ec_key_types[] = {
|
||||
EC_IMEXPORTABLE_PRIVATE_KEY,
|
||||
EC_IMEXPORTABLE_PUBLIC_KEY,
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM ec_dom_parameters_types[] = {
|
||||
EC_IMEXPORTABLE_DOM_PARAMETERS,
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM ec_5_types[] = {
|
||||
EC_IMEXPORTABLE_PRIVATE_KEY,
|
||||
EC_IMEXPORTABLE_DOM_PARAMETERS,
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM ec_6_types[] = {
|
||||
EC_IMEXPORTABLE_PUBLIC_KEY,
|
||||
EC_IMEXPORTABLE_DOM_PARAMETERS,
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM ec_key_domp_types[] = {
|
||||
EC_IMEXPORTABLE_PRIVATE_KEY,
|
||||
EC_IMEXPORTABLE_PUBLIC_KEY,
|
||||
EC_IMEXPORTABLE_DOM_PARAMETERS,
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM ec_other_parameters_types[] = {
|
||||
EC_IMEXPORTABLE_OTHER_PARAMETERS,
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM ec_9_types[] = {
|
||||
EC_IMEXPORTABLE_PRIVATE_KEY,
|
||||
EC_IMEXPORTABLE_OTHER_PARAMETERS,
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM ec_10_types[] = {
|
||||
EC_IMEXPORTABLE_PUBLIC_KEY,
|
||||
EC_IMEXPORTABLE_OTHER_PARAMETERS,
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM ec_11_types[] = {
|
||||
EC_IMEXPORTABLE_PRIVATE_KEY,
|
||||
EC_IMEXPORTABLE_PUBLIC_KEY,
|
||||
EC_IMEXPORTABLE_OTHER_PARAMETERS,
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM ec_all_parameters_types[] = {
|
||||
EC_IMEXPORTABLE_DOM_PARAMETERS,
|
||||
EC_IMEXPORTABLE_OTHER_PARAMETERS,
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM ec_13_types[] = {
|
||||
EC_IMEXPORTABLE_PRIVATE_KEY,
|
||||
EC_IMEXPORTABLE_DOM_PARAMETERS,
|
||||
EC_IMEXPORTABLE_OTHER_PARAMETERS,
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM ec_14_types[] = {
|
||||
EC_IMEXPORTABLE_PUBLIC_KEY,
|
||||
EC_IMEXPORTABLE_DOM_PARAMETERS,
|
||||
EC_IMEXPORTABLE_OTHER_PARAMETERS,
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM ec_all_types[] = {
|
||||
EC_IMEXPORTABLE_PRIVATE_KEY,
|
||||
EC_IMEXPORTABLE_PUBLIC_KEY,
|
||||
EC_IMEXPORTABLE_DOM_PARAMETERS,
|
||||
EC_IMEXPORTABLE_OTHER_PARAMETERS,
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
|
||||
static const OSSL_PARAM *ec_types[] = {
|
||||
NULL,
|
||||
ec_private_key_types,
|
||||
ec_public_key_types,
|
||||
ec_key_types,
|
||||
ec_dom_parameters_types,
|
||||
ec_5_types,
|
||||
ec_6_types,
|
||||
ec_key_domp_types,
|
||||
ec_other_parameters_types,
|
||||
ec_9_types,
|
||||
ec_10_types,
|
||||
ec_11_types,
|
||||
ec_all_parameters_types,
|
||||
ec_13_types,
|
||||
ec_14_types,
|
||||
ec_all_types
|
||||
};
|
||||
@@ -154,8 +154,8 @@ static int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
|
||||
}
|
||||
|
||||
static const OSSL_PARAM ecx_key_types[] = {
|
||||
OSSL_PARAM_BN(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0),
|
||||
OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0),
|
||||
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0),
|
||||
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
static const OSSL_PARAM *ecx_imexport_types(int selection)
|
||||
|
||||
@@ -26,6 +26,7 @@ static OSSL_OP_keymgmt_free_fn rsa_freedata;
|
||||
static OSSL_OP_keymgmt_get_params_fn rsa_get_params;
|
||||
static OSSL_OP_keymgmt_gettable_params_fn rsa_gettable_params;
|
||||
static OSSL_OP_keymgmt_has_fn rsa_has;
|
||||
static OSSL_OP_keymgmt_match_fn rsa_match;
|
||||
static OSSL_OP_keymgmt_validate_fn rsa_validate;
|
||||
static OSSL_OP_keymgmt_import_fn rsa_import;
|
||||
static OSSL_OP_keymgmt_import_types_fn rsa_import_types;
|
||||
@@ -197,6 +198,21 @@ static int rsa_has(void *keydata, int selection)
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int rsa_match(const void *keydata1, const void *keydata2, int selection)
|
||||
{
|
||||
const RSA *rsa1 = keydata1;
|
||||
const RSA *rsa2 = keydata2;
|
||||
int ok = 1;
|
||||
|
||||
/* There is always an |e| */
|
||||
ok = ok && BN_cmp(RSA_get0_e(rsa1), RSA_get0_e(rsa2)) == 0;
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
|
||||
ok = ok && BN_cmp(RSA_get0_n(rsa1), RSA_get0_n(rsa2)) == 0;
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
|
||||
ok = ok && BN_cmp(RSA_get0_d(rsa1), RSA_get0_d(rsa2)) == 0;
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int rsa_import(void *keydata, int selection, const OSSL_PARAM params[])
|
||||
{
|
||||
RSA *rsa = keydata;
|
||||
@@ -393,6 +409,7 @@ const OSSL_DISPATCH rsa_keymgmt_functions[] = {
|
||||
{ OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))rsa_get_params },
|
||||
{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))rsa_gettable_params },
|
||||
{ OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))rsa_has },
|
||||
{ OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))rsa_match },
|
||||
{ OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))rsa_validate },
|
||||
{ OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))rsa_import },
|
||||
{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))rsa_import_types },
|
||||
|
||||
@@ -5,6 +5,7 @@ $SERIALIZER_GOAL=../../libimplementations.a
|
||||
$RSA_GOAL=../../libimplementations.a
|
||||
$DH_GOAL=../../libimplementations.a
|
||||
$DSA_GOAL=../../libimplementations.a
|
||||
$ECX_GOAL=../../libimplementations.a
|
||||
|
||||
SOURCE[$SERIALIZER_GOAL]=serializer_common.c
|
||||
SOURCE[$RSA_GOAL]=serializer_rsa.c serializer_rsa_priv.c serializer_rsa_pub.c
|
||||
@@ -14,3 +15,6 @@ ENDIF
|
||||
IF[{- !$disabled{dsa} -}]
|
||||
SOURCE[$DSA_GOAL]=serializer_dsa.c serializer_dsa_priv.c serializer_dsa_pub.c serializer_dsa_param.c
|
||||
ENDIF
|
||||
IF[{- !$disabled{ec} -}]
|
||||
SOURCE[$ECX_GOAL]=serializer_ecx.c serializer_ecx_priv.c serializer_ecx_pub.c
|
||||
ENDIF
|
||||
@@ -243,6 +243,36 @@ int ossl_prov_print_labeled_bignum(BIO *out, const char *label,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Number of octets per line */
|
||||
#define LABELED_BUF_PRINT_WIDTH 15
|
||||
|
||||
int ossl_prov_print_labeled_buf(BIO *out, const char *label,
|
||||
const unsigned char *buf, size_t buflen)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (ossl_prov_bio_printf(out, "%s\n", label) <= 0)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < buflen; i++) {
|
||||
if ((i % LABELED_BUF_PRINT_WIDTH) == 0) {
|
||||
if (i > 0 && ossl_prov_bio_printf(out, "\n") <= 0)
|
||||
return 0;
|
||||
if (ossl_prov_bio_printf(out, " ") <= 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ossl_prov_bio_printf(out, "%02x%s", buf[i],
|
||||
(i == buflen - 1) ? "" : ":") <= 0)
|
||||
return 0;
|
||||
}
|
||||
if (ossl_prov_bio_printf(out, "\n") <= 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* p2s = param to asn1_string, k2d = key to der */
|
||||
int ossl_prov_write_priv_der_from_obj(BIO *out, const void *obj, int obj_nid,
|
||||
int (*p2s)(const void *obj, int nid,
|
||||
@@ -254,7 +284,7 @@ int ossl_prov_write_priv_der_from_obj(BIO *out, const void *obj, int obj_nid,
|
||||
{
|
||||
int ret = 0;
|
||||
ASN1_STRING *str = NULL;
|
||||
int strtype = 0;
|
||||
int strtype = V_ASN1_UNDEF;
|
||||
|
||||
if (p2s != NULL && !p2s(obj, obj_nid, &str, &strtype))
|
||||
return 0;
|
||||
@@ -290,7 +320,7 @@ int ossl_prov_write_priv_pem_from_obj(BIO *out, const void *obj, int obj_nid,
|
||||
{
|
||||
int ret = 0;
|
||||
ASN1_STRING *str = NULL;
|
||||
int strtype = 0;
|
||||
int strtype = V_ASN1_UNDEF;
|
||||
|
||||
if (p2s != NULL && !p2s(obj, obj_nid, &str, &strtype))
|
||||
return 0;
|
||||
@@ -325,7 +355,7 @@ int ossl_prov_write_pub_der_from_obj(BIO *out, const void *obj, int obj_nid,
|
||||
{
|
||||
int ret = 0;
|
||||
ASN1_STRING *str = NULL;
|
||||
int strtype = 0;
|
||||
int strtype = V_ASN1_UNDEF;
|
||||
X509_PUBKEY *xpk = NULL;
|
||||
|
||||
if (p2s != NULL && !p2s(obj, obj_nid, &str, &strtype))
|
||||
@@ -350,7 +380,7 @@ int ossl_prov_write_pub_pem_from_obj(BIO *out, const void *obj, int obj_nid,
|
||||
{
|
||||
int ret = 0;
|
||||
ASN1_STRING *str = NULL;
|
||||
int strtype = 0;
|
||||
int strtype = V_ASN1_UNDEF;
|
||||
X509_PUBKEY *xpk = NULL;
|
||||
|
||||
if (p2s != NULL && !p2s(obj, obj_nid, &str, &strtype))
|
||||
|
||||
@@ -7,6 +7,12 @@
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* DH low level APIs are deprecated for public use, but still ok for
|
||||
* internal use.
|
||||
*/
|
||||
#include "internal/deprecated.h"
|
||||
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/err.h>
|
||||
#include "prov/bio.h" /* ossl_prov_bio_printf() */
|
||||
|
||||
@@ -7,6 +7,12 @@
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* DH low level APIs are deprecated for public use, but still ok for
|
||||
* internal use.
|
||||
*/
|
||||
#include "internal/deprecated.h"
|
||||
|
||||
#include <openssl/core_numbers.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/dh.h>
|
||||
|
||||
@@ -7,6 +7,12 @@
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* DH low level APIs are deprecated for public use, but still ok for
|
||||
* internal use.
|
||||
*/
|
||||
#include "internal/deprecated.h"
|
||||
|
||||
#include <openssl/core_numbers.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
@@ -7,6 +7,12 @@
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* DH low level APIs are deprecated for public use, but still ok for
|
||||
* internal use.
|
||||
*/
|
||||
#include "internal/deprecated.h"
|
||||
|
||||
#include <openssl/core_numbers.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/pem.h>
|
||||
@@ -126,7 +132,7 @@ static int dh_pub_print_data(void *ctx, const OSSL_PARAM params[], BIO *out,
|
||||
static int dh_pub_print(void *ctx, void *dh, BIO *out,
|
||||
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
|
||||
{
|
||||
return ossl_prov_print_dh(out, dh, 0);
|
||||
return ossl_prov_print_dh(out, dh, dh_print_pub);
|
||||
}
|
||||
|
||||
const OSSL_DISPATCH dh_pub_der_serializer_functions[] = {
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include "crypto/ecx.h"
|
||||
#include "prov/bio.h" /* ossl_prov_bio_printf() */
|
||||
#include "prov/implementations.h" /* ecx_keymgmt_functions */
|
||||
#include "serializer_local.h"
|
||||
|
||||
void ecx_get_new_free_import(ECX_KEY_TYPE type,
|
||||
OSSL_OP_keymgmt_new_fn **ecx_new,
|
||||
OSSL_OP_keymgmt_free_fn **ecx_free,
|
||||
OSSL_OP_keymgmt_import_fn **ecx_import)
|
||||
{
|
||||
if (type == ECX_KEY_TYPE_X25519) {
|
||||
*ecx_new = ossl_prov_get_keymgmt_new(x25519_keymgmt_functions);
|
||||
*ecx_free = ossl_prov_get_keymgmt_free(x25519_keymgmt_functions);
|
||||
*ecx_import = ossl_prov_get_keymgmt_import(x25519_keymgmt_functions);
|
||||
} else if (type == ECX_KEY_TYPE_X448) {
|
||||
*ecx_new = ossl_prov_get_keymgmt_new(x448_keymgmt_functions);
|
||||
*ecx_free = ossl_prov_get_keymgmt_free(x448_keymgmt_functions);
|
||||
*ecx_import = ossl_prov_get_keymgmt_import(x448_keymgmt_functions);
|
||||
} else {
|
||||
*ecx_new = NULL;
|
||||
*ecx_free = NULL;
|
||||
*ecx_import = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int ossl_prov_print_ecx(BIO *out, ECX_KEY *ecxkey, enum ecx_print_type type)
|
||||
{
|
||||
const char *type_label = NULL;
|
||||
|
||||
switch (type) {
|
||||
case ecx_print_priv:
|
||||
switch (ecxkey->keylen) {
|
||||
case X25519_KEYLEN:
|
||||
type_label = "X25519 Private-Key";
|
||||
break;
|
||||
case X448_KEYLEN:
|
||||
type_label = "X448 Private-Key";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ecx_print_pub:
|
||||
switch (ecxkey->keylen) {
|
||||
case X25519_KEYLEN:
|
||||
type_label = "X25519 Public-Key";
|
||||
break;
|
||||
case X448_KEYLEN:
|
||||
type_label = "X448 Public-Key";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (type == ecx_print_priv && ecxkey->privkey == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ossl_prov_bio_printf(out, "%s:\n", type_label) <= 0)
|
||||
return 0;
|
||||
if (type == ecx_print_priv
|
||||
&& !ossl_prov_print_labeled_buf(out, "priv:", ecxkey->privkey,
|
||||
ecxkey->keylen))
|
||||
return 0;
|
||||
if (!ossl_prov_print_labeled_buf(out, "pub:", ecxkey->pubkey,
|
||||
ecxkey->keylen))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int ossl_prov_ecx_pub_to_der(const void *vecxkey, unsigned char **pder)
|
||||
{
|
||||
const ECX_KEY *ecxkey = vecxkey;
|
||||
unsigned char *keyblob;
|
||||
|
||||
if (ecxkey == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
keyblob = OPENSSL_memdup(ecxkey->pubkey, ecxkey->keylen);
|
||||
if (keyblob == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*pder = keyblob;
|
||||
return ecxkey->keylen;
|
||||
}
|
||||
|
||||
int ossl_prov_ecx_priv_to_der(const void *vecxkey, unsigned char **pder)
|
||||
{
|
||||
const ECX_KEY *ecxkey = vecxkey;
|
||||
ASN1_OCTET_STRING oct;
|
||||
int keybloblen;
|
||||
|
||||
if (ecxkey == NULL || ecxkey->privkey == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
oct.data = ecxkey->privkey;
|
||||
oct.length = ecxkey->keylen;
|
||||
oct.flags = 0;
|
||||
|
||||
keybloblen = i2d_ASN1_OCTET_STRING(&oct, pder);
|
||||
if (keybloblen < 0) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return keybloblen;
|
||||
}
|
||||
@@ -0,0 +1,270 @@
|
||||
/*
|
||||
* Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <openssl/core_numbers.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/types.h>
|
||||
#include <openssl/params.h>
|
||||
#include "prov/bio.h"
|
||||
#include "prov/implementations.h"
|
||||
#include "serializer_local.h"
|
||||
|
||||
static OSSL_OP_serializer_newctx_fn x25519_priv_newctx;
|
||||
static OSSL_OP_serializer_newctx_fn x448_priv_newctx;
|
||||
static OSSL_OP_serializer_freectx_fn ecx_priv_freectx;
|
||||
static OSSL_OP_serializer_set_ctx_params_fn ecx_priv_set_ctx_params;
|
||||
static OSSL_OP_serializer_settable_ctx_params_fn ecx_priv_settable_ctx_params;
|
||||
static OSSL_OP_serializer_serialize_data_fn ecx_priv_der_data;
|
||||
static OSSL_OP_serializer_serialize_object_fn ecx_priv_der;
|
||||
static OSSL_OP_serializer_serialize_data_fn ecx_priv_pem_data;
|
||||
static OSSL_OP_serializer_serialize_object_fn ecx_priv_pem;
|
||||
|
||||
static OSSL_OP_serializer_serialize_data_fn ecx_priv_print_data;
|
||||
static OSSL_OP_serializer_serialize_object_fn ecx_priv_print;
|
||||
|
||||
/*
|
||||
* Context used for private key serialization.
|
||||
*/
|
||||
struct ecx_priv_ctx_st {
|
||||
void *provctx;
|
||||
|
||||
struct pkcs8_encrypt_ctx_st sc;
|
||||
ECX_KEY_TYPE type;
|
||||
};
|
||||
|
||||
/* Private key : context */
|
||||
static void *ecx_priv_newctx(void *provctx, ECX_KEY_TYPE type)
|
||||
{
|
||||
struct ecx_priv_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));
|
||||
|
||||
if (ctx != NULL) {
|
||||
ctx->provctx = provctx;
|
||||
|
||||
/* -1 is the "whatever" indicator, i.e. the PKCS8 library default PBE */
|
||||
ctx->sc.pbe_nid = -1;
|
||||
ctx->type = type;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static void *x25519_priv_newctx(void *provctx)
|
||||
{
|
||||
return ecx_priv_newctx(provctx, ECX_KEY_TYPE_X25519);
|
||||
}
|
||||
|
||||
static void *x448_priv_newctx(void *provctx)
|
||||
{
|
||||
return ecx_priv_newctx(provctx, ECX_KEY_TYPE_X448);
|
||||
}
|
||||
|
||||
static void ecx_priv_freectx(void *vctx)
|
||||
{
|
||||
struct ecx_priv_ctx_st *ctx = vctx;
|
||||
|
||||
EVP_CIPHER_free(ctx->sc.cipher);
|
||||
OPENSSL_free(ctx->sc.cipher_pass);
|
||||
OPENSSL_free(ctx);
|
||||
}
|
||||
|
||||
static const OSSL_PARAM *ecx_priv_settable_ctx_params(void)
|
||||
{
|
||||
static const OSSL_PARAM settables[] = {
|
||||
OSSL_PARAM_utf8_string(OSSL_SERIALIZER_PARAM_CIPHER, NULL, 0),
|
||||
OSSL_PARAM_octet_string(OSSL_SERIALIZER_PARAM_PASS, NULL, 0),
|
||||
OSSL_PARAM_END,
|
||||
};
|
||||
|
||||
return settables;
|
||||
}
|
||||
|
||||
static int ecx_priv_set_ctx_params(void *vctx, const OSSL_PARAM params[])
|
||||
{
|
||||
struct ecx_priv_ctx_st *ctx = vctx;
|
||||
const OSSL_PARAM *p;
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_SERIALIZER_PARAM_CIPHER);
|
||||
if (p != NULL) {
|
||||
const OSSL_PARAM *propsp =
|
||||
OSSL_PARAM_locate_const(params, OSSL_SERIALIZER_PARAM_PROPERTIES);
|
||||
const char *props;
|
||||
|
||||
if (p->data_type != OSSL_PARAM_UTF8_STRING)
|
||||
return 0;
|
||||
if (propsp != NULL && propsp->data_type != OSSL_PARAM_UTF8_STRING)
|
||||
return 0;
|
||||
props = (propsp != NULL ? propsp->data : NULL);
|
||||
|
||||
EVP_CIPHER_free(ctx->sc.cipher);
|
||||
ctx->sc.cipher_intent = p->data != NULL;
|
||||
if (p->data != NULL
|
||||
&& ((ctx->sc.cipher = EVP_CIPHER_fetch(NULL, p->data, props))
|
||||
== NULL))
|
||||
return 0;
|
||||
}
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_SERIALIZER_PARAM_PASS);
|
||||
if (p != NULL) {
|
||||
OPENSSL_free(ctx->sc.cipher_pass);
|
||||
ctx->sc.cipher_pass = NULL;
|
||||
if (!OSSL_PARAM_get_octet_string(p, &ctx->sc.cipher_pass, 0,
|
||||
&ctx->sc.cipher_pass_length))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Private key : DER */
|
||||
static int ecx_priv_der_data(void *vctx, const OSSL_PARAM params[], BIO *out,
|
||||
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
|
||||
{
|
||||
struct ecx_priv_ctx_st *ctx = vctx;
|
||||
OSSL_OP_keymgmt_new_fn *ecx_new;
|
||||
OSSL_OP_keymgmt_free_fn *ecx_free;
|
||||
OSSL_OP_keymgmt_import_fn *ecx_import;
|
||||
int ok = 0;
|
||||
|
||||
ecx_get_new_free_import(ctx->type, &ecx_new, &ecx_free, &ecx_import);
|
||||
|
||||
if (ecx_import != NULL) {
|
||||
ECX_KEY *ecxkey;
|
||||
|
||||
if ((ecxkey = ecx_new(ctx->provctx)) != NULL
|
||||
&& ecx_import(ecxkey, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
|
||||
&& ecx_priv_der(ctx, ecxkey, out, cb, cbarg))
|
||||
ok = 1;
|
||||
ecx_free(ecxkey);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int ecx_priv_der(void *vctx, void *vecxkey, BIO *out,
|
||||
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
|
||||
{
|
||||
struct ecx_priv_ctx_st *ctx = vctx;
|
||||
ECX_KEY *ecxkey = vecxkey;
|
||||
int ret;
|
||||
int type = (ctx->type == ECX_KEY_TYPE_X25519) ? EVP_PKEY_X25519
|
||||
: EVP_PKEY_X448;
|
||||
|
||||
ctx->sc.cb = cb;
|
||||
ctx->sc.cbarg = cbarg;
|
||||
|
||||
ret = ossl_prov_write_priv_der_from_obj(out, ecxkey,
|
||||
type,
|
||||
NULL,
|
||||
ossl_prov_ecx_priv_to_der,
|
||||
&ctx->sc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Private key : PEM */
|
||||
static int ecx_priv_pem_data(void *vctx, const OSSL_PARAM params[], BIO *out,
|
||||
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
|
||||
{
|
||||
struct ecx_priv_ctx_st *ctx = vctx;
|
||||
OSSL_OP_keymgmt_new_fn *ecx_new;
|
||||
OSSL_OP_keymgmt_free_fn *ecx_free;
|
||||
OSSL_OP_keymgmt_import_fn *ecx_import;
|
||||
int ok = 0;
|
||||
|
||||
ecx_get_new_free_import(ctx->type, &ecx_new, &ecx_free, &ecx_import);
|
||||
|
||||
if (ecx_import != NULL) {
|
||||
ECX_KEY *ecxkey;
|
||||
|
||||
if ((ecxkey = ecx_new(ctx->provctx)) != NULL
|
||||
&& ecx_import(ecxkey, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
|
||||
&& ecx_priv_pem(ctx->provctx, ecxkey, out, cb, cbarg))
|
||||
ok = 1;
|
||||
ecx_free(ecxkey);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int ecx_priv_pem(void *vctx, void *ecxkey, BIO *out,
|
||||
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
|
||||
{
|
||||
struct ecx_priv_ctx_st *ctx = vctx;
|
||||
int ret;
|
||||
int type = (ctx->type == ECX_KEY_TYPE_X25519) ? EVP_PKEY_X25519
|
||||
: EVP_PKEY_X448;
|
||||
|
||||
ctx->sc.cb = cb;
|
||||
ctx->sc.cbarg = cbarg;
|
||||
|
||||
ret = ossl_prov_write_priv_pem_from_obj(out, ecxkey,
|
||||
type,
|
||||
NULL,
|
||||
ossl_prov_ecx_priv_to_der,
|
||||
&ctx->sc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ecx_priv_print_data(void *vctx, const OSSL_PARAM params[], BIO *out,
|
||||
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
|
||||
{
|
||||
struct ecx_priv_ctx_st *ctx = vctx;
|
||||
OSSL_OP_keymgmt_new_fn *ecx_new;
|
||||
OSSL_OP_keymgmt_free_fn *ecx_free;
|
||||
OSSL_OP_keymgmt_import_fn *ecx_import;
|
||||
int ok = 0;
|
||||
|
||||
ecx_get_new_free_import(ctx->type, &ecx_new, &ecx_free, &ecx_import);
|
||||
|
||||
if (ecx_import != NULL) {
|
||||
ECX_KEY *ecxkey;
|
||||
|
||||
if ((ecxkey = ecx_new(ctx->provctx)) != NULL
|
||||
&& ecx_import(ecxkey, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
|
||||
&& ecx_priv_print(ctx, ecxkey, out, cb, cbarg))
|
||||
ok = 1;
|
||||
ecx_free(ecxkey);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int ecx_priv_print(void *ctx, void *ecxkey, BIO *out,
|
||||
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
|
||||
{
|
||||
return ossl_prov_print_ecx(out, ecxkey, ecx_print_priv);
|
||||
}
|
||||
|
||||
#define MAKE_SERIALIZER_FUNCTIONS(alg, type) \
|
||||
const OSSL_DISPATCH alg##_priv_##type##_serializer_functions[] = { \
|
||||
{ OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))alg##_priv_newctx }, \
|
||||
{ OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))ecx_priv_freectx }, \
|
||||
{ OSSL_FUNC_SERIALIZER_SET_CTX_PARAMS, \
|
||||
(void (*)(void))ecx_priv_set_ctx_params }, \
|
||||
{ OSSL_FUNC_SERIALIZER_SETTABLE_CTX_PARAMS, \
|
||||
(void (*)(void))ecx_priv_settable_ctx_params }, \
|
||||
{ OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, \
|
||||
(void (*)(void))ecx_priv_##type##_data }, \
|
||||
{ OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, \
|
||||
(void (*)(void))ecx_priv_##type }, \
|
||||
{ 0, NULL } \
|
||||
};
|
||||
|
||||
#define MAKE_SERIALIZER_FUNCTIONS_GROUP(alg) \
|
||||
MAKE_SERIALIZER_FUNCTIONS(alg, der) \
|
||||
MAKE_SERIALIZER_FUNCTIONS(alg, pem) \
|
||||
const OSSL_DISPATCH alg##_priv_print_serializer_functions[] = { \
|
||||
{ OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))alg##_priv_newctx }, \
|
||||
{ OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))ecx_priv_freectx }, \
|
||||
{ OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, \
|
||||
(void (*)(void))ecx_priv_print }, \
|
||||
{ OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, \
|
||||
(void (*)(void))ecx_priv_print_data }, \
|
||||
{ 0, NULL } \
|
||||
};
|
||||
|
||||
MAKE_SERIALIZER_FUNCTIONS_GROUP(x25519)
|
||||
MAKE_SERIALIZER_FUNCTIONS_GROUP(x448)
|
||||
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <openssl/core_numbers.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/types.h>
|
||||
#include <openssl/params.h>
|
||||
#include "prov/bio.h"
|
||||
#include "prov/implementations.h"
|
||||
#include "serializer_local.h"
|
||||
|
||||
static OSSL_OP_serializer_newctx_fn x25519_pub_newctx;
|
||||
static OSSL_OP_serializer_newctx_fn x448_pub_newctx;
|
||||
static OSSL_OP_serializer_freectx_fn ecx_pub_freectx;
|
||||
static OSSL_OP_serializer_serialize_data_fn ecx_pub_der_data;
|
||||
static OSSL_OP_serializer_serialize_object_fn ecx_pub_der;
|
||||
static OSSL_OP_serializer_serialize_data_fn ecx_pub_pem_data;
|
||||
static OSSL_OP_serializer_serialize_object_fn ecx_pub_pem;
|
||||
|
||||
static OSSL_OP_serializer_serialize_data_fn ecx_pub_print_data;
|
||||
static OSSL_OP_serializer_serialize_object_fn ecx_pub_print;
|
||||
|
||||
/*
|
||||
* Context used for public key serialization.
|
||||
*/
|
||||
struct ecx_pub_ctx_st {
|
||||
void *provctx;
|
||||
ECX_KEY_TYPE type;
|
||||
};
|
||||
|
||||
/* Public key : context */
|
||||
static void *ecx_pub_newctx(void *provctx, ECX_KEY_TYPE type)
|
||||
{
|
||||
struct ecx_pub_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));
|
||||
|
||||
if (ctx != NULL) {
|
||||
ctx->provctx = provctx;
|
||||
ctx->type = type;
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static void *x25519_pub_newctx(void *provctx)
|
||||
{
|
||||
return ecx_pub_newctx(provctx, ECX_KEY_TYPE_X25519);
|
||||
}
|
||||
|
||||
static void *x448_pub_newctx(void *provctx)
|
||||
{
|
||||
return ecx_pub_newctx(provctx, ECX_KEY_TYPE_X448);
|
||||
}
|
||||
|
||||
static void ecx_pub_freectx(void *ctx)
|
||||
{
|
||||
OPENSSL_free(ctx);
|
||||
}
|
||||
|
||||
/* Public key : DER */
|
||||
static int ecx_pub_der_data(void *vctx, const OSSL_PARAM params[], BIO *out,
|
||||
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
|
||||
{
|
||||
struct ecx_pub_ctx_st *ctx = vctx;
|
||||
OSSL_OP_keymgmt_new_fn *ecx_new;
|
||||
OSSL_OP_keymgmt_free_fn *ecx_free;
|
||||
OSSL_OP_keymgmt_import_fn *ecx_import;
|
||||
int ok = 0;
|
||||
|
||||
ecx_get_new_free_import(ctx->type, &ecx_new, &ecx_free, &ecx_import);
|
||||
|
||||
if (ecx_import != NULL) {
|
||||
ECX_KEY *ecxkey;
|
||||
|
||||
if ((ecxkey = ecx_new(ctx->provctx)) != NULL
|
||||
&& ecx_import(ecxkey, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
|
||||
&& ecx_pub_der(ctx, ecxkey, out, cb, cbarg))
|
||||
ok = 1;
|
||||
ecx_free(ecxkey);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int ecx_pub_der(void *vctx, void *ecxkey, BIO *out,
|
||||
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
|
||||
{
|
||||
struct ecx_pub_ctx_st *ctx = vctx;
|
||||
|
||||
return ossl_prov_write_pub_der_from_obj(out, ecxkey,
|
||||
ctx->type == ECX_KEY_TYPE_X25519
|
||||
? EVP_PKEY_X25519 : EVP_PKEY_X448,
|
||||
NULL,
|
||||
ossl_prov_ecx_pub_to_der);
|
||||
}
|
||||
|
||||
/* Public key : PEM */
|
||||
static int ecx_pub_pem_data(void *vctx, const OSSL_PARAM params[], BIO *out,
|
||||
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
|
||||
{
|
||||
struct ecx_pub_ctx_st *ctx = vctx;
|
||||
OSSL_OP_keymgmt_new_fn *ecx_new;
|
||||
OSSL_OP_keymgmt_free_fn *ecx_free;
|
||||
OSSL_OP_keymgmt_import_fn *ecx_import;
|
||||
int ok = 0;
|
||||
|
||||
ecx_get_new_free_import(ctx->type, &ecx_new, &ecx_free, &ecx_import);
|
||||
|
||||
if (ecx_import != NULL) {
|
||||
ECX_KEY *ecxkey;
|
||||
|
||||
if ((ecxkey = ecx_new(ctx->provctx)) != NULL
|
||||
&& ecx_import(ecxkey, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
|
||||
&& ecx_pub_pem(ctx, ecxkey, out, cb, cbarg))
|
||||
ok = 1;
|
||||
ecx_free(ecxkey);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int ecx_pub_pem(void *vctx, void *ecxkey, BIO *out,
|
||||
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
|
||||
{
|
||||
struct ecx_pub_ctx_st *ctx = vctx;
|
||||
|
||||
return ossl_prov_write_pub_pem_from_obj(out, ecxkey,
|
||||
ctx->type == ECX_KEY_TYPE_X25519
|
||||
? EVP_PKEY_X25519 : EVP_PKEY_X448,
|
||||
NULL,
|
||||
ossl_prov_ecx_pub_to_der);
|
||||
|
||||
}
|
||||
|
||||
static int ecx_pub_print_data(void *vctx, const OSSL_PARAM params[], BIO *out,
|
||||
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
|
||||
{
|
||||
struct ecx_pub_ctx_st *ctx = vctx;
|
||||
OSSL_OP_keymgmt_new_fn *ecx_new;
|
||||
OSSL_OP_keymgmt_free_fn *ecx_free;
|
||||
OSSL_OP_keymgmt_import_fn *ecx_import;
|
||||
int ok = 0;
|
||||
|
||||
ecx_get_new_free_import(ctx->type, &ecx_new, &ecx_free, &ecx_import);
|
||||
|
||||
if (ecx_import != NULL) {
|
||||
ECX_KEY *ecxkey;
|
||||
|
||||
if ((ecxkey = ecx_new(ctx)) != NULL
|
||||
&& ecx_import(ecxkey, OSSL_KEYMGMT_SELECT_KEYPAIR, params)
|
||||
&& ecx_pub_print(ctx, ecxkey, out, cb, cbarg))
|
||||
ok = 1;
|
||||
ecx_free(ecxkey);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int ecx_pub_print(void *ctx, void *ecxkey, BIO *out,
|
||||
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
|
||||
{
|
||||
return ossl_prov_print_ecx(out, ecxkey, ecx_print_pub);
|
||||
}
|
||||
|
||||
#define MAKE_SERIALIZER_FUNCTIONS(alg, type) \
|
||||
const OSSL_DISPATCH alg##_pub_##type##_serializer_functions[] = { \
|
||||
{ OSSL_FUNC_SERIALIZER_NEWCTX, (void (*)(void))alg##_pub_newctx }, \
|
||||
{ OSSL_FUNC_SERIALIZER_FREECTX, (void (*)(void))ecx_pub_freectx }, \
|
||||
{ OSSL_FUNC_SERIALIZER_SERIALIZE_DATA, \
|
||||
(void (*)(void))ecx_pub_##type##_data }, \
|
||||
{ OSSL_FUNC_SERIALIZER_SERIALIZE_OBJECT, \
|
||||
(void (*)(void))ecx_pub_##type }, \
|
||||
{ 0, NULL } \
|
||||
};
|
||||
|
||||
#define MAKE_SERIALIZER_FUNCTIONS_GROUP(alg) \
|
||||
MAKE_SERIALIZER_FUNCTIONS(alg, der) \
|
||||
MAKE_SERIALIZER_FUNCTIONS(alg, pem) \
|
||||
MAKE_SERIALIZER_FUNCTIONS(alg, print)
|
||||
|
||||
MAKE_SERIALIZER_FUNCTIONS_GROUP(x25519)
|
||||
MAKE_SERIALIZER_FUNCTIONS_GROUP(x448)
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <openssl/asn1.h> /* i2d_of_void */
|
||||
#include <openssl/x509.h> /* X509_SIG */
|
||||
#include <openssl/types.h>
|
||||
#include <crypto/ecx.h>
|
||||
|
||||
struct pkcs8_encrypt_ctx_st {
|
||||
/* Set to 1 if intending to encrypt/decrypt, otherwise 0 */
|
||||
@@ -30,6 +31,11 @@ struct pkcs8_encrypt_ctx_st {
|
||||
void *cbarg;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
ECX_KEY_TYPE_X25519,
|
||||
ECX_KEY_TYPE_X448
|
||||
} ECX_KEY_TYPE;
|
||||
|
||||
OSSL_OP_keymgmt_new_fn *ossl_prov_get_keymgmt_new(const OSSL_DISPATCH *fns);
|
||||
OSSL_OP_keymgmt_free_fn *ossl_prov_get_keymgmt_free(const OSSL_DISPATCH *fns);
|
||||
OSSL_OP_keymgmt_import_fn *ossl_prov_get_keymgmt_import(const OSSL_DISPATCH *fns);
|
||||
@@ -49,8 +55,15 @@ int ossl_prov_prepare_dh_params(const void *dh, int nid,
|
||||
int ossl_prov_dh_pub_to_der(const void *dh, unsigned char **pder);
|
||||
int ossl_prov_dh_priv_to_der(const void *dh, unsigned char **pder);
|
||||
|
||||
void ecx_get_new_free_import(ECX_KEY_TYPE type,
|
||||
OSSL_OP_keymgmt_new_fn **ecx_new,
|
||||
OSSL_OP_keymgmt_free_fn **ecx_free,
|
||||
OSSL_OP_keymgmt_import_fn **ecx_import);
|
||||
int ossl_prov_ecx_pub_to_der(const void *ecxkey, unsigned char **pder);
|
||||
int ossl_prov_ecx_priv_to_der(const void *ecxkey, unsigned char **pder);
|
||||
|
||||
int ossl_prov_prepare_dsa_params(const void *dsa, int nid,
|
||||
ASN1_STRING **pstr, int *pstrtype);
|
||||
ASN1_STRING **pstr, int *pstrtype);
|
||||
/*
|
||||
* Special variant of ossl_prov_prepare_dsa_params() that requires all
|
||||
* three parameters (P, Q and G) to be set. This is used when serializing
|
||||
@@ -63,6 +76,8 @@ int ossl_prov_dsa_priv_to_der(const void *dsa, unsigned char **pder);
|
||||
|
||||
int ossl_prov_print_labeled_bignum(BIO *out, const char *label,
|
||||
const BIGNUM *bn);
|
||||
int ossl_prov_print_labeled_buf(BIO *out, const char *label,
|
||||
const unsigned char *buf, size_t buflen);
|
||||
int ossl_prov_print_rsa(BIO *out, RSA *rsa, int priv);
|
||||
|
||||
enum dh_print_type {
|
||||
@@ -81,6 +96,15 @@ enum dsa_print_type {
|
||||
|
||||
int ossl_prov_print_dsa(BIO *out, DSA *dsa, enum dsa_print_type type);
|
||||
|
||||
enum ecx_print_type {
|
||||
ecx_print_priv,
|
||||
ecx_print_pub
|
||||
};
|
||||
|
||||
#ifndef OPENSSL_NO_EC
|
||||
int ossl_prov_print_ecx(BIO *out, ECX_KEY *ecxkey, enum ecx_print_type type);
|
||||
#endif
|
||||
|
||||
int ossl_prov_write_priv_der_from_obj(BIO *out, const void *obj, int obj_nid,
|
||||
int (*p2s)(const void *obj, int nid,
|
||||
ASN1_STRING **str,
|
||||
|
||||
@@ -2,9 +2,12 @@
|
||||
# switch each to the Legacy provider when needed.
|
||||
|
||||
$DSA_GOAL=../../libimplementations.a
|
||||
$RSA_GOAL=../../libimplementations.a
|
||||
|
||||
IF[{- !$disabled{dsa} -}]
|
||||
SOURCE[$DSA_GOAL]=dsa.c
|
||||
ENDIF
|
||||
|
||||
SOURCE[$RSA_GOAL]=rsa.c
|
||||
|
||||
|
||||
@@ -0,0 +1,1115 @@
|
||||
/*
|
||||
* Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/*
|
||||
* RSA low level APIs are deprecated for public use, but still ok for
|
||||
* internal use.
|
||||
*/
|
||||
#include "internal/deprecated.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/core_numbers.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/params.h>
|
||||
#include <openssl/evp.h>
|
||||
#include "internal/cryptlib.h"
|
||||
#include "internal/nelem.h"
|
||||
#include "internal/sizes.h"
|
||||
#include "crypto/rsa.h"
|
||||
#include "prov/providercommonerr.h"
|
||||
#include "prov/implementations.h"
|
||||
#include "prov/provider_ctx.h"
|
||||
|
||||
static OSSL_OP_signature_newctx_fn rsa_newctx;
|
||||
static OSSL_OP_signature_sign_init_fn rsa_signature_init;
|
||||
static OSSL_OP_signature_verify_init_fn rsa_signature_init;
|
||||
static OSSL_OP_signature_verify_recover_init_fn rsa_signature_init;
|
||||
static OSSL_OP_signature_sign_fn rsa_sign;
|
||||
static OSSL_OP_signature_verify_fn rsa_verify;
|
||||
static OSSL_OP_signature_verify_recover_fn rsa_verify_recover;
|
||||
static OSSL_OP_signature_digest_sign_init_fn rsa_digest_signverify_init;
|
||||
static OSSL_OP_signature_digest_sign_update_fn rsa_digest_signverify_update;
|
||||
static OSSL_OP_signature_digest_sign_final_fn rsa_digest_sign_final;
|
||||
static OSSL_OP_signature_digest_verify_init_fn rsa_digest_signverify_init;
|
||||
static OSSL_OP_signature_digest_verify_update_fn rsa_digest_signverify_update;
|
||||
static OSSL_OP_signature_digest_verify_final_fn rsa_digest_verify_final;
|
||||
static OSSL_OP_signature_freectx_fn rsa_freectx;
|
||||
static OSSL_OP_signature_dupctx_fn rsa_dupctx;
|
||||
static OSSL_OP_signature_get_ctx_params_fn rsa_get_ctx_params;
|
||||
static OSSL_OP_signature_gettable_ctx_params_fn rsa_gettable_ctx_params;
|
||||
static OSSL_OP_signature_set_ctx_params_fn rsa_set_ctx_params;
|
||||
static OSSL_OP_signature_settable_ctx_params_fn rsa_settable_ctx_params;
|
||||
static OSSL_OP_signature_get_ctx_md_params_fn rsa_get_ctx_md_params;
|
||||
static OSSL_OP_signature_gettable_ctx_md_params_fn rsa_gettable_ctx_md_params;
|
||||
static OSSL_OP_signature_set_ctx_md_params_fn rsa_set_ctx_md_params;
|
||||
static OSSL_OP_signature_settable_ctx_md_params_fn rsa_settable_ctx_md_params;
|
||||
|
||||
static OSSL_ITEM padding_item[] = {
|
||||
{ RSA_PKCS1_PADDING, "pkcs1" },
|
||||
{ RSA_SSLV23_PADDING, "sslv23" },
|
||||
{ RSA_NO_PADDING, "none" },
|
||||
{ RSA_PKCS1_OAEP_PADDING, "oaep" }, /* Correct spelling first */
|
||||
{ RSA_PKCS1_OAEP_PADDING, "oeap" },
|
||||
{ RSA_X931_PADDING, "x931" },
|
||||
{ RSA_PKCS1_PSS_PADDING, "pss" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
/*
|
||||
* What's passed as an actual key is defined by the KEYMGMT interface.
|
||||
* We happen to know that our KEYMGMT simply passes RSA structures, so
|
||||
* we use that here too.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
OPENSSL_CTX *libctx;
|
||||
RSA *rsa;
|
||||
|
||||
/*
|
||||
* Flag to determine if the hash function can be changed (1) or not (0)
|
||||
* Because it's dangerous to change during a DigestSign or DigestVerify
|
||||
* operation, this flag is cleared by their Init function, and set again
|
||||
* by their Final function.
|
||||
*/
|
||||
unsigned int flag_allow_md : 1;
|
||||
|
||||
/* The Algorithm Identifier of the combined signature agorithm */
|
||||
unsigned char aid[128];
|
||||
size_t aid_len;
|
||||
|
||||
/* main digest */
|
||||
EVP_MD *md;
|
||||
EVP_MD_CTX *mdctx;
|
||||
int mdnid;
|
||||
char mdname[OSSL_MAX_NAME_SIZE]; /* Purely informational */
|
||||
|
||||
/* RSA padding mode */
|
||||
int pad_mode;
|
||||
/* message digest for MGF1 */
|
||||
EVP_MD *mgf1_md;
|
||||
char mgf1_mdname[OSSL_MAX_NAME_SIZE]; /* Purely informational */
|
||||
/* PSS salt length */
|
||||
int saltlen;
|
||||
/* Minimum salt length or -1 if no PSS parameter restriction */
|
||||
int min_saltlen;
|
||||
|
||||
/* Temp buffer */
|
||||
unsigned char *tbuf;
|
||||
|
||||
} PROV_RSA_CTX;
|
||||
|
||||
static size_t rsa_get_md_size(const PROV_RSA_CTX *prsactx)
|
||||
{
|
||||
if (prsactx->md != NULL)
|
||||
return EVP_MD_size(prsactx->md);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rsa_get_md_nid(const EVP_MD *md)
|
||||
{
|
||||
/*
|
||||
* Because the RSA library deals with NIDs, we need to translate.
|
||||
* We do so using EVP_MD_is_a(), and therefore need a name to NID
|
||||
* map.
|
||||
*/
|
||||
static const OSSL_ITEM name_to_nid[] = {
|
||||
{ NID_sha1, OSSL_DIGEST_NAME_SHA1 },
|
||||
{ NID_sha224, OSSL_DIGEST_NAME_SHA2_224 },
|
||||
{ NID_sha256, OSSL_DIGEST_NAME_SHA2_256 },
|
||||
{ NID_sha384, OSSL_DIGEST_NAME_SHA2_384 },
|
||||
{ NID_sha512, OSSL_DIGEST_NAME_SHA2_512 },
|
||||
{ NID_md5, OSSL_DIGEST_NAME_MD5 },
|
||||
{ NID_md5_sha1, OSSL_DIGEST_NAME_MD5_SHA1 },
|
||||
{ NID_md2, OSSL_DIGEST_NAME_MD2 },
|
||||
{ NID_md4, OSSL_DIGEST_NAME_MD4 },
|
||||
{ NID_mdc2, OSSL_DIGEST_NAME_MDC2 },
|
||||
{ NID_ripemd160, OSSL_DIGEST_NAME_RIPEMD160 },
|
||||
{ NID_sha3_224, OSSL_DIGEST_NAME_SHA3_224 },
|
||||
{ NID_sha3_256, OSSL_DIGEST_NAME_SHA3_256 },
|
||||
{ NID_sha3_384, OSSL_DIGEST_NAME_SHA3_384 },
|
||||
{ NID_sha3_512, OSSL_DIGEST_NAME_SHA3_512 },
|
||||
};
|
||||
size_t i;
|
||||
int mdnid = NID_undef;
|
||||
|
||||
if (md == NULL)
|
||||
goto end;
|
||||
|
||||
for (i = 0; i < OSSL_NELEM(name_to_nid); i++) {
|
||||
if (EVP_MD_is_a(md, name_to_nid[i].ptr)) {
|
||||
mdnid = (int)name_to_nid[i].id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mdnid == NID_undef)
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST);
|
||||
|
||||
end:
|
||||
return mdnid;
|
||||
}
|
||||
|
||||
static int rsa_check_padding(int mdnid, int padding)
|
||||
{
|
||||
if (padding == RSA_NO_PADDING) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (padding == RSA_X931_PADDING) {
|
||||
if (RSA_X931_hash_id(mdnid) == -1) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_X931_DIGEST);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void *rsa_newctx(void *provctx)
|
||||
{
|
||||
PROV_RSA_CTX *prsactx = OPENSSL_zalloc(sizeof(PROV_RSA_CTX));
|
||||
|
||||
if (prsactx == NULL)
|
||||
return NULL;
|
||||
|
||||
prsactx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
|
||||
prsactx->flag_allow_md = 1;
|
||||
return prsactx;
|
||||
}
|
||||
|
||||
/* True if PSS parameters are restricted */
|
||||
#define rsa_pss_restricted(prsactx) (prsactx->min_saltlen != -1)
|
||||
|
||||
static int rsa_signature_init(void *vprsactx, void *vrsa)
|
||||
{
|
||||
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
|
||||
|
||||
if (prsactx == NULL || vrsa == NULL || !RSA_up_ref(vrsa))
|
||||
return 0;
|
||||
|
||||
RSA_free(prsactx->rsa);
|
||||
prsactx->rsa = vrsa;
|
||||
if (RSA_get0_pss_params(prsactx->rsa) != NULL)
|
||||
prsactx->pad_mode = RSA_PKCS1_PSS_PADDING;
|
||||
else
|
||||
prsactx->pad_mode = RSA_PKCS1_PADDING;
|
||||
/* Maximum for sign, auto for verify */
|
||||
prsactx->saltlen = RSA_PSS_SALTLEN_AUTO;
|
||||
prsactx->min_saltlen = -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int rsa_setup_md(PROV_RSA_CTX *ctx, const char *mdname,
|
||||
const char *mdprops)
|
||||
{
|
||||
if (mdname != NULL) {
|
||||
EVP_MD *md = EVP_MD_fetch(ctx->libctx, mdname, mdprops);
|
||||
int md_nid = rsa_get_md_nid(md);
|
||||
size_t algorithmidentifier_len = 0;
|
||||
const unsigned char *algorithmidentifier = NULL;
|
||||
|
||||
if (md == NULL)
|
||||
return 0;
|
||||
|
||||
if (!rsa_check_padding(md_nid, ctx->pad_mode)) {
|
||||
EVP_MD_free(md);
|
||||
return 0;
|
||||
}
|
||||
|
||||
EVP_MD_CTX_free(ctx->mdctx);
|
||||
EVP_MD_free(ctx->md);
|
||||
ctx->md = NULL;
|
||||
ctx->mdctx = NULL;
|
||||
ctx->mdname[0] = '\0';
|
||||
ctx->aid[0] = '\0';
|
||||
ctx->aid_len = 0;
|
||||
|
||||
algorithmidentifier =
|
||||
rsa_algorithmidentifier_encoding(md_nid, &algorithmidentifier_len);
|
||||
|
||||
ctx->md = md;
|
||||
ctx->mdnid = md_nid;
|
||||
OPENSSL_strlcpy(ctx->mdname, mdname, sizeof(ctx->mdname));
|
||||
if (algorithmidentifier != NULL) {
|
||||
memcpy(ctx->aid, algorithmidentifier, algorithmidentifier_len);
|
||||
ctx->aid_len = algorithmidentifier_len;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int rsa_setup_mgf1_md(PROV_RSA_CTX *ctx, const char *mdname,
|
||||
const char *props)
|
||||
{
|
||||
if (ctx->mgf1_mdname[0] != '\0')
|
||||
EVP_MD_free(ctx->mgf1_md);
|
||||
|
||||
if ((ctx->mgf1_md = EVP_MD_fetch(ctx->libctx, mdname, props)) == NULL)
|
||||
return 0;
|
||||
OPENSSL_strlcpy(ctx->mgf1_mdname, mdname, sizeof(ctx->mgf1_mdname));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int setup_tbuf(PROV_RSA_CTX *ctx)
|
||||
{
|
||||
if (ctx->tbuf != NULL)
|
||||
return 1;
|
||||
if ((ctx->tbuf = OPENSSL_malloc(RSA_size(ctx->rsa))) == NULL) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void clean_tbuf(PROV_RSA_CTX *ctx)
|
||||
{
|
||||
if (ctx->tbuf != NULL)
|
||||
OPENSSL_cleanse(ctx->tbuf, RSA_size(ctx->rsa));
|
||||
}
|
||||
|
||||
static void free_tbuf(PROV_RSA_CTX *ctx)
|
||||
{
|
||||
OPENSSL_clear_free(ctx->tbuf, RSA_size(ctx->rsa));
|
||||
ctx->tbuf = NULL;
|
||||
}
|
||||
|
||||
static int rsa_sign(void *vprsactx, unsigned char *sig, size_t *siglen,
|
||||
size_t sigsize, const unsigned char *tbs, size_t tbslen)
|
||||
{
|
||||
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
|
||||
int ret;
|
||||
size_t rsasize = RSA_size(prsactx->rsa);
|
||||
size_t mdsize = rsa_get_md_size(prsactx);
|
||||
|
||||
if (sig == NULL) {
|
||||
*siglen = rsasize;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (sigsize < (size_t)rsasize)
|
||||
return 0;
|
||||
|
||||
if (mdsize != 0) {
|
||||
if (tbslen != mdsize) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef FIPS_MODE
|
||||
if (EVP_MD_is_a(prsactx->md, OSSL_DIGEST_NAME_MDC2)) {
|
||||
unsigned int sltmp;
|
||||
|
||||
if (prsactx->pad_mode != RSA_PKCS1_PADDING) {
|
||||
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE,
|
||||
"only PKCS#1 padding supported with MDC2");
|
||||
return 0;
|
||||
}
|
||||
ret = RSA_sign_ASN1_OCTET_STRING(0, tbs, tbslen, sig, &sltmp,
|
||||
prsactx->rsa);
|
||||
|
||||
if (ret <= 0) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
|
||||
return 0;
|
||||
}
|
||||
ret = sltmp;
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (prsactx->pad_mode) {
|
||||
case RSA_X931_PADDING:
|
||||
if ((size_t)RSA_size(prsactx->rsa) < tbslen + 1) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_KEY_SIZE_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
if (!setup_tbuf(prsactx)) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
memcpy(prsactx->tbuf, tbs, tbslen);
|
||||
prsactx->tbuf[tbslen] = RSA_X931_hash_id(prsactx->mdnid);
|
||||
ret = RSA_private_encrypt(tbslen + 1, prsactx->tbuf,
|
||||
sig, prsactx->rsa, RSA_X931_PADDING);
|
||||
clean_tbuf(prsactx);
|
||||
break;
|
||||
|
||||
case RSA_PKCS1_PADDING:
|
||||
{
|
||||
unsigned int sltmp;
|
||||
|
||||
ret = RSA_sign(prsactx->mdnid, tbs, tbslen, sig, &sltmp,
|
||||
prsactx->rsa);
|
||||
if (ret <= 0) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
|
||||
return 0;
|
||||
}
|
||||
ret = sltmp;
|
||||
}
|
||||
break;
|
||||
|
||||
case RSA_PKCS1_PSS_PADDING:
|
||||
/* Check PSS restrictions */
|
||||
if (rsa_pss_restricted(prsactx)) {
|
||||
switch (prsactx->saltlen) {
|
||||
case RSA_PSS_SALTLEN_DIGEST:
|
||||
if (prsactx->min_saltlen > EVP_MD_size(prsactx->md)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_PSS_SALTLEN_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
default:
|
||||
if (prsactx->saltlen >= 0
|
||||
&& prsactx->saltlen < prsactx->min_saltlen) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_PSS_SALTLEN_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!setup_tbuf(prsactx))
|
||||
return 0;
|
||||
if (!RSA_padding_add_PKCS1_PSS_mgf1(prsactx->rsa,
|
||||
prsactx->tbuf, tbs,
|
||||
prsactx->md, prsactx->mgf1_md,
|
||||
prsactx->saltlen)) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
|
||||
return 0;
|
||||
}
|
||||
ret = RSA_private_encrypt(RSA_size(prsactx->rsa), prsactx->tbuf,
|
||||
sig, prsactx->rsa, RSA_NO_PADDING);
|
||||
clean_tbuf(prsactx);
|
||||
break;
|
||||
|
||||
default:
|
||||
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE,
|
||||
"Only X.931, PKCS#1 v1.5 or PSS padding allowed");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
ret = RSA_private_encrypt(tbslen, tbs, sig, prsactx->rsa,
|
||||
prsactx->pad_mode);
|
||||
}
|
||||
|
||||
#ifndef FIPS_MODE
|
||||
end:
|
||||
#endif
|
||||
if (ret <= 0) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*siglen = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int rsa_verify_recover(void *vprsactx,
|
||||
unsigned char *rout,
|
||||
size_t *routlen,
|
||||
size_t routsize,
|
||||
const unsigned char *sig,
|
||||
size_t siglen)
|
||||
{
|
||||
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
|
||||
int ret;
|
||||
|
||||
if (rout == NULL) {
|
||||
*routlen = RSA_size(prsactx->rsa);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (prsactx->md != NULL) {
|
||||
switch (prsactx->pad_mode) {
|
||||
case RSA_X931_PADDING:
|
||||
if (!setup_tbuf(prsactx))
|
||||
return 0;
|
||||
ret = RSA_public_decrypt(siglen, sig, prsactx->tbuf, prsactx->rsa,
|
||||
RSA_X931_PADDING);
|
||||
if (ret < 1) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
|
||||
return 0;
|
||||
}
|
||||
ret--;
|
||||
if (prsactx->tbuf[ret] != RSA_X931_hash_id(prsactx->mdnid)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_ALGORITHM_MISMATCH);
|
||||
return 0;
|
||||
}
|
||||
if (ret != EVP_MD_size(prsactx->md)) {
|
||||
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH,
|
||||
"Should be %d, but got %d",
|
||||
EVP_MD_size(prsactx->md), ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*routlen = ret;
|
||||
if (routsize < (size_t)ret) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
memcpy(rout, prsactx->tbuf, ret);
|
||||
break;
|
||||
|
||||
case RSA_PKCS1_PADDING:
|
||||
{
|
||||
size_t sltmp;
|
||||
|
||||
ret = int_rsa_verify(prsactx->mdnid, NULL, 0, rout, &sltmp,
|
||||
sig, siglen, prsactx->rsa);
|
||||
if (ret <= 0) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
|
||||
return 0;
|
||||
}
|
||||
ret = sltmp;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE,
|
||||
"Only X.931 or PKCS#1 v1.5 padding allowed");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
ret = RSA_public_decrypt(siglen, sig, rout, prsactx->rsa,
|
||||
prsactx->pad_mode);
|
||||
if (ret < 0) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*routlen = ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int rsa_verify(void *vprsactx, const unsigned char *sig, size_t siglen,
|
||||
const unsigned char *tbs, size_t tbslen)
|
||||
{
|
||||
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
|
||||
size_t rslen;
|
||||
|
||||
if (prsactx->md != NULL) {
|
||||
switch (prsactx->pad_mode) {
|
||||
case RSA_PKCS1_PADDING:
|
||||
if (!RSA_verify(prsactx->mdnid, tbs, tbslen, sig, siglen,
|
||||
prsactx->rsa)) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
case RSA_X931_PADDING:
|
||||
if (rsa_verify_recover(prsactx, NULL, &rslen, 0, sig, siglen) <= 0)
|
||||
return 0;
|
||||
break;
|
||||
case RSA_PKCS1_PSS_PADDING:
|
||||
{
|
||||
int ret;
|
||||
size_t mdsize;
|
||||
|
||||
/* Check PSS restrictions */
|
||||
if (rsa_pss_restricted(prsactx)) {
|
||||
switch (prsactx->saltlen) {
|
||||
case RSA_PSS_SALTLEN_AUTO:
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_PSS_SALTLEN);
|
||||
return 0;
|
||||
case RSA_PSS_SALTLEN_DIGEST:
|
||||
if (prsactx->min_saltlen > EVP_MD_size(prsactx->md)) {
|
||||
ERR_raise(ERR_LIB_PROV,
|
||||
PROV_R_PSS_SALTLEN_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
/* FALLTHRU */
|
||||
default:
|
||||
if (prsactx->saltlen >= 0
|
||||
&& prsactx->saltlen < prsactx->min_saltlen) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_PSS_SALTLEN_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to check this for the RSA_verify_PKCS1_PSS_mgf1()
|
||||
* call
|
||||
*/
|
||||
mdsize = rsa_get_md_size(prsactx);
|
||||
if (tbslen != mdsize) {
|
||||
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST_LENGTH,
|
||||
"Should be %d, but got %d",
|
||||
mdsize, tbslen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!setup_tbuf(prsactx))
|
||||
return 0;
|
||||
ret = RSA_public_decrypt(siglen, sig, prsactx->tbuf,
|
||||
prsactx->rsa, RSA_NO_PADDING);
|
||||
if (ret <= 0) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
|
||||
return 0;
|
||||
}
|
||||
ret = RSA_verify_PKCS1_PSS_mgf1(prsactx->rsa, tbs,
|
||||
prsactx->md, prsactx->mgf1_md,
|
||||
prsactx->tbuf,
|
||||
prsactx->saltlen);
|
||||
if (ret <= 0) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
default:
|
||||
ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_PADDING_MODE,
|
||||
"Only X.931, PKCS#1 v1.5 or PSS padding allowed");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (!setup_tbuf(prsactx))
|
||||
return 0;
|
||||
rslen = RSA_public_decrypt(siglen, sig, prsactx->tbuf, prsactx->rsa,
|
||||
prsactx->pad_mode);
|
||||
if (rslen == 0) {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_LIB_RSA);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((rslen != tbslen) || memcmp(tbs, prsactx->tbuf, rslen))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int rsa_digest_signverify_init(void *vprsactx, const char *mdname,
|
||||
const char *props, void *vrsa)
|
||||
{
|
||||
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
|
||||
|
||||
prsactx->flag_allow_md = 0;
|
||||
if (!rsa_signature_init(vprsactx, vrsa)
|
||||
|| !rsa_setup_md(prsactx, mdname, props))
|
||||
return 0;
|
||||
|
||||
prsactx->mdctx = EVP_MD_CTX_new();
|
||||
if (prsactx->mdctx == NULL)
|
||||
goto error;
|
||||
|
||||
if (!EVP_DigestInit_ex(prsactx->mdctx, prsactx->md, NULL))
|
||||
goto error;
|
||||
|
||||
return 1;
|
||||
|
||||
error:
|
||||
EVP_MD_CTX_free(prsactx->mdctx);
|
||||
EVP_MD_free(prsactx->md);
|
||||
prsactx->mdctx = NULL;
|
||||
prsactx->md = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rsa_digest_signverify_update(void *vprsactx, const unsigned char *data,
|
||||
size_t datalen)
|
||||
{
|
||||
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
|
||||
|
||||
if (prsactx == NULL || prsactx->mdctx == NULL)
|
||||
return 0;
|
||||
|
||||
return EVP_DigestUpdate(prsactx->mdctx, data, datalen);
|
||||
}
|
||||
|
||||
int rsa_digest_sign_final(void *vprsactx, unsigned char *sig, size_t *siglen,
|
||||
size_t sigsize)
|
||||
{
|
||||
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
|
||||
unsigned char digest[EVP_MAX_MD_SIZE];
|
||||
unsigned int dlen = 0;
|
||||
|
||||
prsactx->flag_allow_md = 1;
|
||||
if (prsactx == NULL || prsactx->mdctx == NULL)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If sig is NULL then we're just finding out the sig size. Other fields
|
||||
* are ignored. Defer to rsa_sign.
|
||||
*/
|
||||
if (sig != NULL) {
|
||||
/*
|
||||
* TODO(3.0): There is the possibility that some externally provided
|
||||
* digests exceed EVP_MAX_MD_SIZE. We should probably handle that somehow -
|
||||
* but that problem is much larger than just in RSA.
|
||||
*/
|
||||
if (!EVP_DigestFinal_ex(prsactx->mdctx, digest, &dlen))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return rsa_sign(vprsactx, sig, siglen, sigsize, digest, (size_t)dlen);
|
||||
}
|
||||
|
||||
|
||||
int rsa_digest_verify_final(void *vprsactx, const unsigned char *sig,
|
||||
size_t siglen)
|
||||
{
|
||||
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
|
||||
unsigned char digest[EVP_MAX_MD_SIZE];
|
||||
unsigned int dlen = 0;
|
||||
|
||||
prsactx->flag_allow_md = 1;
|
||||
if (prsactx == NULL || prsactx->mdctx == NULL)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* TODO(3.0): There is the possibility that some externally provided
|
||||
* digests exceed EVP_MAX_MD_SIZE. We should probably handle that somehow -
|
||||
* but that problem is much larger than just in RSA.
|
||||
*/
|
||||
if (!EVP_DigestFinal_ex(prsactx->mdctx, digest, &dlen))
|
||||
return 0;
|
||||
|
||||
return rsa_verify(vprsactx, sig, siglen, digest, (size_t)dlen);
|
||||
}
|
||||
|
||||
static void rsa_freectx(void *vprsactx)
|
||||
{
|
||||
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
|
||||
|
||||
if (prsactx == NULL)
|
||||
return;
|
||||
|
||||
RSA_free(prsactx->rsa);
|
||||
EVP_MD_CTX_free(prsactx->mdctx);
|
||||
EVP_MD_free(prsactx->md);
|
||||
EVP_MD_free(prsactx->mgf1_md);
|
||||
free_tbuf(prsactx);
|
||||
|
||||
OPENSSL_clear_free(prsactx, sizeof(prsactx));
|
||||
}
|
||||
|
||||
static void *rsa_dupctx(void *vprsactx)
|
||||
{
|
||||
PROV_RSA_CTX *srcctx = (PROV_RSA_CTX *)vprsactx;
|
||||
PROV_RSA_CTX *dstctx;
|
||||
|
||||
dstctx = OPENSSL_zalloc(sizeof(*srcctx));
|
||||
if (dstctx == NULL)
|
||||
return NULL;
|
||||
|
||||
*dstctx = *srcctx;
|
||||
dstctx->rsa = NULL;
|
||||
dstctx->md = NULL;
|
||||
dstctx->mdctx = NULL;
|
||||
dstctx->tbuf = NULL;
|
||||
|
||||
if (srcctx->rsa != NULL && !RSA_up_ref(srcctx->rsa))
|
||||
goto err;
|
||||
dstctx->rsa = srcctx->rsa;
|
||||
|
||||
if (srcctx->md != NULL && !EVP_MD_up_ref(srcctx->md))
|
||||
goto err;
|
||||
dstctx->md = srcctx->md;
|
||||
|
||||
if (srcctx->mgf1_md != NULL && !EVP_MD_up_ref(srcctx->mgf1_md))
|
||||
goto err;
|
||||
dstctx->mgf1_md = srcctx->mgf1_md;
|
||||
|
||||
if (srcctx->mdctx != NULL) {
|
||||
dstctx->mdctx = EVP_MD_CTX_new();
|
||||
if (dstctx->mdctx == NULL
|
||||
|| !EVP_MD_CTX_copy_ex(dstctx->mdctx, srcctx->mdctx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
return dstctx;
|
||||
err:
|
||||
rsa_freectx(dstctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int rsa_get_ctx_params(void *vprsactx, OSSL_PARAM *params)
|
||||
{
|
||||
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
|
||||
OSSL_PARAM *p;
|
||||
|
||||
if (prsactx == NULL || params == NULL)
|
||||
return 0;
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID);
|
||||
if (p != NULL
|
||||
&& !OSSL_PARAM_set_octet_string(p, prsactx->aid, prsactx->aid_len))
|
||||
return 0;
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_PAD_MODE);
|
||||
if (p != NULL)
|
||||
switch (p->data_type) {
|
||||
case OSSL_PARAM_INTEGER:
|
||||
if (!OSSL_PARAM_set_int(p, prsactx->pad_mode))
|
||||
return 0;
|
||||
break;
|
||||
case OSSL_PARAM_UTF8_STRING:
|
||||
{
|
||||
int i;
|
||||
const char *word = NULL;
|
||||
|
||||
for (i = 0; padding_item[i].id != 0; i++) {
|
||||
if (prsactx->pad_mode == (int)padding_item[i].id) {
|
||||
word = padding_item[i].ptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (word != NULL) {
|
||||
if (!OSSL_PARAM_set_utf8_string(p, word))
|
||||
return 0;
|
||||
} else {
|
||||
ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST);
|
||||
if (p != NULL && !OSSL_PARAM_set_utf8_string(p, prsactx->mdname))
|
||||
return 0;
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_MGF1_DIGEST);
|
||||
if (p != NULL && !OSSL_PARAM_set_utf8_string(p, prsactx->mgf1_mdname))
|
||||
return 0;
|
||||
|
||||
p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_PSS_SALTLEN);
|
||||
if (p != NULL) {
|
||||
if (p->data_type == OSSL_PARAM_INTEGER) {
|
||||
if (!OSSL_PARAM_set_int(p, prsactx->saltlen))
|
||||
return 0;
|
||||
} else if (p->data_type == OSSL_PARAM_UTF8_STRING) {
|
||||
switch (prsactx->saltlen) {
|
||||
case RSA_PSS_SALTLEN_DIGEST:
|
||||
if (!OSSL_PARAM_set_utf8_string(p, "digest"))
|
||||
return 0;
|
||||
break;
|
||||
case RSA_PSS_SALTLEN_MAX:
|
||||
if (!OSSL_PARAM_set_utf8_string(p, "max"))
|
||||
return 0;
|
||||
break;
|
||||
case RSA_PSS_SALTLEN_AUTO:
|
||||
if (!OSSL_PARAM_set_utf8_string(p, "auto"))
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
if (BIO_snprintf(p->data, p->data_size, "%d", prsactx->saltlen)
|
||||
<= 0)
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM known_gettable_ctx_params[] = {
|
||||
OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_DIGEST, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, NULL, 0),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
|
||||
static const OSSL_PARAM *rsa_gettable_ctx_params(void)
|
||||
{
|
||||
return known_gettable_ctx_params;
|
||||
}
|
||||
|
||||
static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[])
|
||||
{
|
||||
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
|
||||
const OSSL_PARAM *p;
|
||||
|
||||
if (prsactx == NULL || params == NULL)
|
||||
return 0;
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST);
|
||||
/* Not allowed during certain operations */
|
||||
if (p != NULL && !prsactx->flag_allow_md)
|
||||
return 0;
|
||||
if (p != NULL) {
|
||||
char mdname[OSSL_MAX_NAME_SIZE] = "", *pmdname = mdname;
|
||||
char mdprops[OSSL_MAX_PROPQUERY_SIZE] = "", *pmdprops = mdprops;
|
||||
const OSSL_PARAM *propsp =
|
||||
OSSL_PARAM_locate_const(params,
|
||||
OSSL_SIGNATURE_PARAM_PROPERTIES);
|
||||
|
||||
if (!OSSL_PARAM_get_utf8_string(p, &pmdname, sizeof(mdname)))
|
||||
return 0;
|
||||
if (propsp != NULL
|
||||
&& !OSSL_PARAM_get_utf8_string(propsp, &pmdprops, sizeof(mdprops)))
|
||||
return 0;
|
||||
|
||||
/* TODO(3.0) PSS check needs more work */
|
||||
if (rsa_pss_restricted(prsactx)) {
|
||||
/* TODO(3.0) figure out what to do for prsactx->md == NULL */
|
||||
if (prsactx->md == NULL || EVP_MD_is_a(prsactx->md, mdname))
|
||||
return 1;
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* non-PSS code follows */
|
||||
if (!rsa_setup_md(prsactx, mdname, mdprops))
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_PAD_MODE);
|
||||
if (p != NULL) {
|
||||
int pad_mode = 0;
|
||||
|
||||
switch (p->data_type) {
|
||||
case OSSL_PARAM_INTEGER: /* Support for legacy pad mode number */
|
||||
if (!OSSL_PARAM_get_int(p, &pad_mode))
|
||||
return 0;
|
||||
break;
|
||||
case OSSL_PARAM_UTF8_STRING:
|
||||
{
|
||||
int i;
|
||||
|
||||
if (p->data == NULL)
|
||||
return 0;
|
||||
|
||||
for (i = 0; padding_item[i].id != 0; i++) {
|
||||
if (strcmp(p->data, padding_item[i].ptr) == 0) {
|
||||
pad_mode = padding_item[i].id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (pad_mode) {
|
||||
case RSA_PKCS1_OAEP_PADDING:
|
||||
/*
|
||||
* OAEP padding is for asymmetric cipher only so is not compatible
|
||||
* with signature use.
|
||||
*/
|
||||
ERR_raise_data(ERR_LIB_PROV,
|
||||
PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE,
|
||||
"OAEP padding not allowed for signing / verifying");
|
||||
return 0;
|
||||
case RSA_PKCS1_PSS_PADDING:
|
||||
if (prsactx->mdname[0] == '\0')
|
||||
rsa_setup_md(prsactx, "SHA1", "");
|
||||
goto cont;
|
||||
case RSA_PKCS1_PADDING:
|
||||
case RSA_SSLV23_PADDING:
|
||||
case RSA_NO_PADDING:
|
||||
case RSA_X931_PADDING:
|
||||
if (RSA_get0_pss_params(prsactx->rsa) != NULL) {
|
||||
ERR_raise_data(ERR_LIB_PROV,
|
||||
PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE,
|
||||
"X.931 padding not allowed with RSA-PSS");
|
||||
return 0;
|
||||
}
|
||||
cont:
|
||||
if (!rsa_check_padding(prsactx->mdnid, pad_mode))
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
prsactx->pad_mode = pad_mode;
|
||||
}
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_PSS_SALTLEN);
|
||||
if (p != NULL) {
|
||||
int saltlen;
|
||||
|
||||
if (prsactx->pad_mode != RSA_PKCS1_PSS_PADDING) {
|
||||
ERR_raise_data(ERR_LIB_PROV, PROV_R_NOT_SUPPORTED,
|
||||
"PSS saltlen can only be specified if "
|
||||
"PSS padding has been specified first");
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (p->data_type) {
|
||||
case OSSL_PARAM_INTEGER: /* Support for legacy pad mode number */
|
||||
if (!OSSL_PARAM_get_int(p, &saltlen))
|
||||
return 0;
|
||||
break;
|
||||
case OSSL_PARAM_UTF8_STRING:
|
||||
if (strcmp(p->data, "digest") == 0)
|
||||
saltlen = RSA_PSS_SALTLEN_DIGEST;
|
||||
else if (strcmp(p->data, "max") == 0)
|
||||
saltlen = RSA_PSS_SALTLEN_MAX;
|
||||
else if (strcmp(p->data, "auto") == 0)
|
||||
saltlen = RSA_PSS_SALTLEN_AUTO;
|
||||
else
|
||||
saltlen = atoi(p->data);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* RSA_PSS_SALTLEN_MAX seems curiously named in this check.
|
||||
* Contrary to what it's name suggests, it's the currently
|
||||
* lowest saltlen number possible.
|
||||
*/
|
||||
if (saltlen < RSA_PSS_SALTLEN_MAX) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_PSS_SALTLEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
prsactx->saltlen = saltlen;
|
||||
}
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_MGF1_DIGEST);
|
||||
if (p != NULL) {
|
||||
char mdname[OSSL_MAX_NAME_SIZE] = "", *pmdname = mdname;
|
||||
char mdprops[OSSL_MAX_PROPQUERY_SIZE] = "", *pmdprops = mdprops;
|
||||
const OSSL_PARAM *propsp =
|
||||
OSSL_PARAM_locate_const(params,
|
||||
OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES);
|
||||
|
||||
if (!OSSL_PARAM_get_utf8_string(p, &pmdname, sizeof(mdname)))
|
||||
return 0;
|
||||
if (propsp != NULL
|
||||
&& !OSSL_PARAM_get_utf8_string(propsp, &pmdprops, sizeof(mdprops)))
|
||||
return 0;
|
||||
|
||||
if (prsactx->pad_mode != RSA_PKCS1_PSS_PADDING) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_MGF1_MD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO(3.0) PSS check needs more work */
|
||||
if (rsa_pss_restricted(prsactx)) {
|
||||
/* TODO(3.0) figure out what to do for prsactx->md == NULL */
|
||||
if (prsactx->mgf1_md == NULL
|
||||
|| EVP_MD_is_a(prsactx->mgf1_md, mdname))
|
||||
return 1;
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* non-PSS code follows */
|
||||
if (!rsa_setup_mgf1_md(prsactx, mdname, mdprops))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM known_settable_ctx_params[] = {
|
||||
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PROPERTIES, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_DIGEST, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES, NULL, 0),
|
||||
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, NULL, 0),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
|
||||
static const OSSL_PARAM *rsa_settable_ctx_params(void)
|
||||
{
|
||||
/*
|
||||
* TODO(3.0): Should this function return a different set of settable ctx
|
||||
* params if the ctx is being used for a DigestSign/DigestVerify? In that
|
||||
* case it is not allowed to set the digest size/digest name because the
|
||||
* digest is explicitly set as part of the init.
|
||||
*/
|
||||
return known_settable_ctx_params;
|
||||
}
|
||||
|
||||
static int rsa_get_ctx_md_params(void *vprsactx, OSSL_PARAM *params)
|
||||
{
|
||||
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
|
||||
|
||||
if (prsactx->mdctx == NULL)
|
||||
return 0;
|
||||
|
||||
return EVP_MD_CTX_get_params(prsactx->mdctx, params);
|
||||
}
|
||||
|
||||
static const OSSL_PARAM *rsa_gettable_ctx_md_params(void *vprsactx)
|
||||
{
|
||||
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
|
||||
|
||||
if (prsactx->md == NULL)
|
||||
return 0;
|
||||
|
||||
return EVP_MD_gettable_ctx_params(prsactx->md);
|
||||
}
|
||||
|
||||
static int rsa_set_ctx_md_params(void *vprsactx, const OSSL_PARAM params[])
|
||||
{
|
||||
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
|
||||
|
||||
if (prsactx->mdctx == NULL)
|
||||
return 0;
|
||||
|
||||
return EVP_MD_CTX_set_params(prsactx->mdctx, params);
|
||||
}
|
||||
|
||||
static const OSSL_PARAM *rsa_settable_ctx_md_params(void *vprsactx)
|
||||
{
|
||||
PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx;
|
||||
|
||||
if (prsactx->md == NULL)
|
||||
return 0;
|
||||
|
||||
return EVP_MD_settable_ctx_params(prsactx->md);
|
||||
}
|
||||
|
||||
const OSSL_DISPATCH rsa_signature_functions[] = {
|
||||
{ OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))rsa_newctx },
|
||||
{ OSSL_FUNC_SIGNATURE_SIGN_INIT, (void (*)(void))rsa_signature_init },
|
||||
{ OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))rsa_sign },
|
||||
{ OSSL_FUNC_SIGNATURE_VERIFY_INIT, (void (*)(void))rsa_signature_init },
|
||||
{ OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))rsa_verify },
|
||||
{ OSSL_FUNC_SIGNATURE_VERIFY_RECOVER_INIT, (void (*)(void))rsa_signature_init },
|
||||
{ OSSL_FUNC_SIGNATURE_VERIFY_RECOVER, (void (*)(void))rsa_verify_recover },
|
||||
{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
|
||||
(void (*)(void))rsa_digest_signverify_init },
|
||||
{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE,
|
||||
(void (*)(void))rsa_digest_signverify_update },
|
||||
{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL,
|
||||
(void (*)(void))rsa_digest_sign_final },
|
||||
{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
|
||||
(void (*)(void))rsa_digest_signverify_init },
|
||||
{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE,
|
||||
(void (*)(void))rsa_digest_signverify_update },
|
||||
{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL,
|
||||
(void (*)(void))rsa_digest_verify_final },
|
||||
{ OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))rsa_freectx },
|
||||
{ OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))rsa_dupctx },
|
||||
{ OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))rsa_get_ctx_params },
|
||||
{ OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
|
||||
(void (*)(void))rsa_gettable_ctx_params },
|
||||
{ OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))rsa_set_ctx_params },
|
||||
{ OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS,
|
||||
(void (*)(void))rsa_settable_ctx_params },
|
||||
{ OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS,
|
||||
(void (*)(void))rsa_get_ctx_md_params },
|
||||
{ OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS,
|
||||
(void (*)(void))rsa_gettable_ctx_md_params },
|
||||
{ OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS,
|
||||
(void (*)(void))rsa_set_ctx_md_params },
|
||||
{ OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS,
|
||||
(void (*)(void))rsa_settable_ctx_md_params },
|
||||
{ 0, NULL }
|
||||
};
|
||||
Reference in New Issue
Block a user