Add ECDSA to providers

Added ECDSA support for OSSL_SIGNATURE_PARAM_ALGORITHM_ID

Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/10968)
This commit is contained in:
Shane Lontis 2020-03-15 21:34:29 +10:00
parent 2decdad31d
commit edd3b7a309
13 changed files with 655 additions and 10 deletions

View File

@ -51,7 +51,7 @@ $COMMON=ec_lib.c ecp_smpl.c ecp_mont.c ecp_nist.c ec_cvt.c ec_mult.c \
ecdsa_ossl.c ecdsa_sign.c ecdsa_vrf.c curve25519.c \
curve448/arch_32/f_impl.c curve448/f_generic.c curve448/scalar.c \
curve448/curve448_tables.c curve448/eddsa.c curve448/curve448.c \
$ECASM
$ECASM ecdsa_aid.c
SOURCE[../../libcrypto]=$COMMON ec_ameth.c ec_pmeth.c ecx_meth.c ecx_key.c \
ec_err.c ecdh_kdf.c eck_prn.c ec_evp_lib.c
SOURCE[../../providers/libfips.a]=$COMMON

105
crypto/ec/ecdsa_aid.c Normal file
View File

@ -0,0 +1,105 @@
/*
* 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 <stdlib.h>
#include <openssl/objects.h>
#include "crypto/ec.h"
#define ASN1_SEQUENCE 0x30
#define ASN1_OID 0x06
#define OID_FIRST(a, b) a * 40 + b
#define DER_840() 0x86, 0x48 /* DER encoding of number 840 is 2 bytes */
#define DER_10045() 0xCE, 0x3D /* DER encoding of number 10045 is 2 bytes */
#define SHA1_SZ 7
#define SHA2_SZ 8
#define SHA3_SZ 9
/*
* -- RFC 3279
* ansi-X9-62 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) 10045 }
* id-ecSigType OBJECT IDENTIFIER ::= { ansi-X9-62 signatures(4) }
*
* ecdsa-with-SHA1 OBJECT IDENTIFIER ::= { id-ecSigType 1 }
*/
#define ENCODE_ALGORITHMIDENTIFIER_SHA1(name) \
static const unsigned char algorithmidentifier_##name##_der[] = { \
ASN1_SEQUENCE, 2 + SHA1_SZ, \
ASN1_OID, SHA1_SZ, OID_FIRST(1, 2), DER_840(), DER_10045(), 4, 1 \
}
/*
* -- RFC 5758
*
* ecdsa-with-SHA224 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
* us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 1 }
*
* ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
* us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 2 }
*
* ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
* us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 3 }
*
* ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
* us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 4 }
*/
#define ENCODE_ALGORITHMIDENTIFIER_SHA2(name, n) \
static const unsigned char algorithmidentifier_##name##_der[] = { \
ASN1_SEQUENCE, 2 + SHA2_SZ, \
ASN1_OID, SHA2_SZ, OID_FIRST(1, 2), DER_840(), DER_10045(), 4, 3, n \
}
/*
* https://csrc.nist.gov/projects/computer-security-objects-register/algorithm-registration
*
* sigAlgs OBJECT IDENTIFIER ::= { 2 16 840 1 101 3 4 3 }
*
* id-ecdsa-with-sha3-224 ::= { sigAlgs 9 }
* id-ecdsa-with-sha3-256 ::= { sigAlgs 10 }
* id-ecdsa-with-sha3-384 ::= { sigAlgs 11 }
* id-ecdsa-with-sha3-512 ::= { sigAlgs 12 }
*/
#define ENCODE_ALGORITHMIDENTIFIER_SHA3(name, n) \
static const unsigned char algorithmidentifier_##name##_der[] = { \
ASN1_SEQUENCE, 2 + SHA3_SZ, \
ASN1_OID, SHA3_SZ, OID_FIRST(2, 16), DER_840(), 1, 101, 3, 4, 3, n \
}
ENCODE_ALGORITHMIDENTIFIER_SHA1(sha1);
ENCODE_ALGORITHMIDENTIFIER_SHA2(sha224, 1);
ENCODE_ALGORITHMIDENTIFIER_SHA2(sha256, 2);
ENCODE_ALGORITHMIDENTIFIER_SHA2(sha384, 3);
ENCODE_ALGORITHMIDENTIFIER_SHA2(sha512, 4);
ENCODE_ALGORITHMIDENTIFIER_SHA3(sha3_224, 9);
ENCODE_ALGORITHMIDENTIFIER_SHA3(sha3_256, 10);
ENCODE_ALGORITHMIDENTIFIER_SHA3(sha3_384, 11);
ENCODE_ALGORITHMIDENTIFIER_SHA3(sha3_512, 12);
/* TODO - Add SHAKE OIDS when they are standardized */
#define MD_CASE(name) \
case NID_##name: \
*len = sizeof(algorithmidentifier_##name##_der); \
return algorithmidentifier_##name##_der
const unsigned char *ecdsa_algorithmidentifier_encoding(int md_nid, size_t *len)
{
switch (md_nid) {
MD_CASE(sha1);
MD_CASE(sha224);
MD_CASE(sha256);
MD_CASE(sha384);
MD_CASE(sha512);
MD_CASE(sha3_224);
MD_CASE(sha3_256);
MD_CASE(sha3_384);
MD_CASE(sha3_512);
default:
return NULL;
}
}

View File

@ -332,6 +332,23 @@ Gets or sets the output size of the digest algorithm used for the input to the
signature functions.
The length of the "digest-size" parameter should not exceed that of a B<size_t>.
= item "algorithm-id" (B<OSSL_SIGNATURE_PARAM_ALGORITHM_ID>) <octet string>
Gets the DER encoded AlgorithmIdentifier that corresponds to the combination of
signature algorithm and digest algorithm for the signature operation.
=item "kat" (B<OSSL_SIGNATURE_PARAM_KAT>) <unsigned integer>
Sets a flag to modify the sign operation to return an error if the initial
calculated signature is invalid.
In the normal mode of operation - new random values are chosen until the
signature operation succeeds.
By default it retries until a signature is calculated.
Setting the value to 0 causes the sign operation to retry,
otherwise the sign operation is only tried once and returns whether or not it
was successful.
Known answer tests can be performed if the random generator is overriden to
supply known values that either pass or fail.
=back

View File

@ -14,7 +14,6 @@
# include <openssl/opensslconf.h>
# ifndef OPENSSL_NO_EC
# include <openssl/ec.h>
/*-
@ -56,5 +55,6 @@ int ec_key_pairwise_check(const EC_KEY *eckey, BN_CTX *ctx);
OPENSSL_CTX *ec_key_get_libctx(const EC_KEY *eckey);
const char *ec_curve_nid2name(int nid);
int ec_curve_name2nid(const char *name);
const unsigned char *ecdsa_algorithmidentifier_encoding(int md_nid, size_t *len);
# endif /* OPENSSL_NO_EC */
#endif

View File

@ -257,6 +257,8 @@ extern "C" {
#define OSSL_SIGNATURE_PARAM_MGF1_DIGEST OSSL_PKEY_PARAM_MGF1_DIGEST
#define OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES \
OSSL_PKEY_PARAM_MGF1_PROPERTIES
#define OSSL_SIGNATURE_PARAM_DIGEST_SIZE OSSL_PKEY_PARAM_DIGEST_SIZE
#define OSSL_SIGNATURE_PARAM_KAT "kat"
/* Asym cipher parameters */
#define OSSL_ASYM_CIPHER_PARAM_PAD_MODE OSSL_PKEY_PARAM_PAD_MODE

View File

@ -373,7 +373,7 @@ static const OSSL_ALGORITHM deflt_keyexch[] = {
{ "DH:dhKeyAgreement", "provider=default", dh_keyexch_functions },
#endif
#ifndef OPENSSL_NO_EC
{ "ECDH:id-ecPublicKey", "provider=default", ecdh_keyexch_functions },
{ "ECDH", "provider=default", ecdh_keyexch_functions },
{ "X25519", "provider=default", x25519_keyexch_functions },
{ "X448", "provider=default", x448_keyexch_functions },
#endif
@ -388,6 +388,7 @@ static const OSSL_ALGORITHM deflt_signature[] = {
#ifndef OPENSSL_NO_EC
{ "ED25519:Ed25519", "provider=default", ed25519_signature_functions },
{ "ED448:Ed448", "provider=default", ed448_signature_functions },
{ "ECDSA", "provider=default", ecdsa_signature_functions },
#endif
{ NULL, NULL, NULL }
};

View File

@ -797,7 +797,7 @@ static const OSSL_ALGORITHM fips_keyexch[] = {
{ "DH:dhKeyAgreement", "provider=fips,fips=yes", dh_keyexch_functions },
#endif
#ifndef OPENSSL_NO_EC
{ "ECDH:id-ecPublicKey", "provider=fips,fips=yes", ecdh_keyexch_functions },
{ "ECDH", "provider=fips,fips=yes", ecdh_keyexch_functions },
#endif
{ NULL, NULL, NULL }
};
@ -807,6 +807,9 @@ static const OSSL_ALGORITHM fips_signature[] = {
{ "DSA:dsaEncryption", "provider=fips,fips=yes", dsa_signature_functions },
#endif
{ "RSA:rsaEncryption", "provider=fips,fips=yes", rsa_signature_functions },
#ifndef OPENSSL_NO_EC
{ "ECDSA", "provider=fips,fips=yes", ecdsa_signature_functions },
#endif
{ NULL, NULL, NULL }
};

View File

@ -274,6 +274,8 @@ extern const OSSL_DISPATCH dsa_signature_functions[];
extern const OSSL_DISPATCH rsa_signature_functions[];
extern const OSSL_DISPATCH ed25519_signature_functions[];
extern const OSSL_DISPATCH ed448_signature_functions[];
extern const OSSL_DISPATCH ecdsa_signature_functions[];
/* Asym Cipher */
extern const OSSL_DISPATCH rsa_asym_cipher_functions[];

View File

@ -49,10 +49,8 @@ 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 "ECDSA";
}
return NULL;
}
@ -135,7 +133,8 @@ int domparams_to_params(const EC_KEY *ec, OSSL_PARAM_BLD *tmpl)
if ((curve_name = ec_curve_nid2name(curve_nid)) == NULL)
return 0;
if (!ossl_param_bld_push_utf8_string(tmpl, OSSL_PKEY_PARAM_EC_NAME, curve_name, 0))
if (!ossl_param_bld_push_utf8_string(tmpl, OSSL_PKEY_PARAM_EC_NAME,
curve_name, 0))
return 0;
}

View File

@ -3,6 +3,7 @@
$DSA_GOAL=../../libimplementations.a
$EC_GOAL=../../libimplementations.a
$ECDSA_GOAL=../../libimplementations.a
IF[{- !$disabled{dsa} -}]
SOURCE[$DSA_GOAL]=dsa.c
@ -10,6 +11,7 @@ ENDIF
IF[{- !$disabled{ec} -}]
SOURCE[$EC_GOAL]=eddsa.c
SOURCE[$ECDSA_GOAL]=ecdsa.c
ENDIF
SOURCE[../../libfips.a]=rsa.c

View File

@ -73,7 +73,7 @@ typedef struct {
char mdname[OSSL_MAX_NAME_SIZE];
/* The Algorithm Identifier of the combined signature agorithm */
/* The Algorithm Identifier of the combined signature algorithm */
unsigned char aid[OSSL_MAX_ALGORITHM_ID_SIZE];
size_t aid_len;

View File

@ -0,0 +1,514 @@
/*
* 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
*/
/*
* ECDSA low level APIs are deprecated for public use, but still ok for
* internal use.
*/
#include "internal/deprecated.h"
#include <string.h> /* memcpy */
#include <openssl/crypto.h>
#include <openssl/core_numbers.h>
#include <openssl/core_names.h>
#include <openssl/dsa.h>
#include <openssl/params.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include "internal/nelem.h"
#include "internal/sizes.h"
#include "prov/providercommonerr.h"
#include "prov/implementations.h"
#include "prov/provider_ctx.h"
#include "crypto/ec.h"
static OSSL_OP_signature_newctx_fn ecdsa_newctx;
static OSSL_OP_signature_sign_init_fn ecdsa_signature_init;
static OSSL_OP_signature_verify_init_fn ecdsa_signature_init;
static OSSL_OP_signature_sign_fn ecdsa_sign;
static OSSL_OP_signature_verify_fn ecdsa_verify;
static OSSL_OP_signature_digest_sign_init_fn ecdsa_digest_signverify_init;
static OSSL_OP_signature_digest_sign_update_fn ecdsa_digest_signverify_update;
static OSSL_OP_signature_digest_sign_final_fn ecdsa_digest_sign_final;
static OSSL_OP_signature_digest_verify_init_fn ecdsa_digest_signverify_init;
static OSSL_OP_signature_digest_verify_update_fn ecdsa_digest_signverify_update;
static OSSL_OP_signature_digest_verify_final_fn ecdsa_digest_verify_final;
static OSSL_OP_signature_freectx_fn ecdsa_freectx;
static OSSL_OP_signature_dupctx_fn ecdsa_dupctx;
static OSSL_OP_signature_get_ctx_params_fn ecdsa_get_ctx_params;
static OSSL_OP_signature_gettable_ctx_params_fn ecdsa_gettable_ctx_params;
static OSSL_OP_signature_set_ctx_params_fn ecdsa_set_ctx_params;
static OSSL_OP_signature_settable_ctx_params_fn ecdsa_settable_ctx_params;
static OSSL_OP_signature_get_ctx_md_params_fn ecdsa_get_ctx_md_params;
static OSSL_OP_signature_gettable_ctx_md_params_fn ecdsa_gettable_ctx_md_params;
static OSSL_OP_signature_set_ctx_md_params_fn ecdsa_set_ctx_md_params;
static OSSL_OP_signature_settable_ctx_md_params_fn ecdsa_settable_ctx_md_params;
/*
* What's passed as an actual key is defined by the KEYMGMT interface.
* We happen to know that our KEYMGMT simply passes DSA structures, so
* we use that here too.
*/
typedef struct {
OPENSSL_CTX *libctx;
EC_KEY *ec;
char mdname[OSSL_MAX_NAME_SIZE];
/* The Algorithm Identifier of the combined signature algorithm */
unsigned char aid[OSSL_MAX_ALGORITHM_ID_SIZE];
size_t aid_len;
size_t mdsize;
EVP_MD *md;
EVP_MD_CTX *mdctx;
/*
* This indicates that KAT (CAVS) test is running. Externally an app will
* override the random callback such that the generated private key and k
* are known.
* Normal operation will loop to choose a new k if the signature is not
* valid - but for this mode of operation it forces a failure instead.
*/
unsigned int kattest;
/*
* Internally used to cache the results of calling the EC group
* sign_setup() methods which are then passed to the sign operation.
* This is used by CAVS failure tests to terminate a loop if the signature
* is not valid.
* This could of also been done with a simple flag.
*/
BIGNUM *kinv;
BIGNUM *r;
} PROV_ECDSA_CTX;
static void *ecdsa_newctx(void *provctx)
{
PROV_ECDSA_CTX *ctx = OPENSSL_zalloc(sizeof(PROV_ECDSA_CTX));
if (ctx == NULL)
return NULL;
ctx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
return ctx;
}
static int ecdsa_signature_init(void *vctx, void *ec)
{
PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
if (ctx == NULL || ec == NULL || !EC_KEY_up_ref(ec))
return 0;
EC_KEY_free(ctx->ec);
ctx->ec = ec;
return 1;
}
static int ecdsa_sign(void *vctx, unsigned char *sig, size_t *siglen,
size_t sigsize, const unsigned char *tbs, size_t tbslen)
{
PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
int ret;
unsigned int sltmp;
size_t ecsize = ECDSA_size(ctx->ec);
if (sig == NULL) {
*siglen = ecsize;
return 1;
}
if (ctx->kattest && !ECDSA_sign_setup(ctx->ec, NULL, &ctx->kinv, &ctx->r))
return 0;
if (sigsize < (size_t)ecsize)
return 0;
if (ctx->mdsize != 0 && tbslen != ctx->mdsize)
return 0;
ret = ECDSA_sign_ex(0, tbs, tbslen, sig, &sltmp, ctx->kinv, ctx->r, ctx->ec);
if (ret <= 0)
return 0;
*siglen = sltmp;
return 1;
}
static int ecdsa_verify(void *vctx, const unsigned char *sig, size_t siglen,
const unsigned char *tbs, size_t tbslen)
{
PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
if (ctx->mdsize != 0 && tbslen != ctx->mdsize)
return 0;
return ECDSA_verify(0, tbs, tbslen, sig, siglen, ctx->ec);
}
static int get_md_nid(const EVP_MD *md)
{
/*
* Because the ECDSA 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_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 },
/* TODO - Add SHAKE OIDS when they are standardized */
};
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 void free_md(PROV_ECDSA_CTX *ctx)
{
EVP_MD_CTX_free(ctx->mdctx);
EVP_MD_free(ctx->md);
ctx->mdctx = NULL;
ctx->md = NULL;
ctx->mdsize = 0;
}
static int ecdsa_digest_signverify_init(void *vctx, const char *mdname,
const char *props, void *ec)
{
PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
size_t algorithmidentifier_len = 0;
const unsigned char *algorithmidentifier;
free_md(ctx);
if (!ecdsa_signature_init(vctx, ec))
return 0;
ctx->md = EVP_MD_fetch(ctx->libctx, mdname, props);
algorithmidentifier =
ecdsa_algorithmidentifier_encoding(get_md_nid(ctx->md),
&algorithmidentifier_len);
if (algorithmidentifier == NULL)
goto error;
ctx->mdsize = EVP_MD_size(ctx->md);
ctx->mdctx = EVP_MD_CTX_new();
if (ctx->mdctx == NULL)
goto error;
memcpy(ctx->aid, algorithmidentifier, algorithmidentifier_len);
ctx->aid_len = algorithmidentifier_len;
if (!EVP_DigestInit_ex(ctx->mdctx, ctx->md, NULL))
goto error;
return 1;
error:
free_md(ctx);
return 0;
}
int ecdsa_digest_signverify_update(void *vctx, const unsigned char *data,
size_t datalen)
{
PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
if (ctx == NULL || ctx->mdctx == NULL)
return 0;
return EVP_DigestUpdate(ctx->mdctx, data, datalen);
}
int ecdsa_digest_sign_final(void *vctx, unsigned char *sig, size_t *siglen,
size_t sigsize)
{
PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
unsigned char digest[EVP_MAX_MD_SIZE];
unsigned int dlen = 0;
if (ctx == NULL || ctx->mdctx == NULL)
return 0;
/*
* If sig is NULL then we're just finding out the sig size. Other fields
* are ignored. Defer to ecdsa_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 DSA.
*/
if (!EVP_DigestFinal_ex(ctx->mdctx, digest, &dlen))
return 0;
}
return ecdsa_sign(vctx, sig, siglen, sigsize, digest, (size_t)dlen);
}
int ecdsa_digest_verify_final(void *vctx, const unsigned char *sig,
size_t siglen)
{
PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
unsigned char digest[EVP_MAX_MD_SIZE];
unsigned int dlen = 0;
if (ctx == NULL || ctx->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 DSA.
*/
if (!EVP_DigestFinal_ex(ctx->mdctx, digest, &dlen))
return 0;
return ecdsa_verify(ctx, sig, siglen, digest, (size_t)dlen);
}
static void ecdsa_freectx(void *vctx)
{
PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
free_md(ctx);
EC_KEY_free(ctx->ec);
BN_clear_free(ctx->kinv);
BN_clear_free(ctx->r);
OPENSSL_free(ctx);
}
static void *ecdsa_dupctx(void *vctx)
{
PROV_ECDSA_CTX *srcctx = (PROV_ECDSA_CTX *)vctx;
PROV_ECDSA_CTX *dstctx;
dstctx = OPENSSL_zalloc(sizeof(*srcctx));
if (dstctx == NULL)
return NULL;
*dstctx = *srcctx;
dstctx->ec = NULL;
dstctx->md = NULL;
dstctx->mdctx = NULL;
if (srcctx->ec != NULL && !EC_KEY_up_ref(srcctx->ec))
goto err;
/* Test KATS should not need to be supported */
if (srcctx->kinv != NULL || srcctx->r != NULL)
goto err;
dstctx->ec = srcctx->ec;
if (srcctx->md != NULL && !EVP_MD_up_ref(srcctx->md))
goto err;
dstctx->md = srcctx->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:
ecdsa_freectx(dstctx);
return NULL;
}
static int ecdsa_get_ctx_params(void *vctx, OSSL_PARAM *params)
{
PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
OSSL_PARAM *p;
if (ctx == NULL || params == NULL)
return 0;
p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID);
if (p != NULL && !OSSL_PARAM_set_octet_string(p, ctx->aid, ctx->aid_len))
return 0;
p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST_SIZE);
if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->mdsize))
return 0;
p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST);
if (p != NULL && !OSSL_PARAM_set_utf8_string(p, ctx->md == NULL
? ctx->mdname
: EVP_MD_name(ctx->md)))
return 0;
return 1;
}
static const OSSL_PARAM known_gettable_ctx_params[] = {
OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0),
OSSL_PARAM_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, NULL),
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
OSSL_PARAM_END
};
static const OSSL_PARAM *ecdsa_gettable_ctx_params(void)
{
return known_gettable_ctx_params;
}
static int ecdsa_set_ctx_params(void *vctx, const OSSL_PARAM params[])
{
PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
const OSSL_PARAM *p;
char *mdname;
if (ctx == NULL || params == NULL)
return 0;
if (ctx->md != NULL) {
/*
* You cannot set the digest name/size when doing a DigestSign or
* DigestVerify.
*/
return 1;
}
p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_KAT);
if (p != NULL && !OSSL_PARAM_get_uint(p, &ctx->kattest))
return 0;
p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST_SIZE);
if (p != NULL && !OSSL_PARAM_get_size_t(p, &ctx->mdsize))
return 0;
/*
* We never actually use the mdname, but we do support getting it later.
* This can be useful for applications that want to know the MD that they
* previously set.
*/
p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST);
mdname = ctx->mdname;
if (p != NULL
&& !OSSL_PARAM_get_utf8_string(p, &mdname, sizeof(ctx->mdname)))
return 0;
return 1;
}
static const OSSL_PARAM known_settable_ctx_params[] = {
OSSL_PARAM_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, NULL),
OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
OSSL_PARAM_uint(OSSL_SIGNATURE_PARAM_KAT, NULL),
OSSL_PARAM_END
};
static const OSSL_PARAM *ecdsa_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 ecdsa_get_ctx_md_params(void *vctx, OSSL_PARAM *params)
{
PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
if (ctx->mdctx == NULL)
return 0;
return EVP_MD_CTX_get_params(ctx->mdctx, params);
}
static const OSSL_PARAM *ecdsa_gettable_ctx_md_params(void *vctx)
{
PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
if (ctx->md == NULL)
return 0;
return EVP_MD_gettable_ctx_params(ctx->md);
}
static int ecdsa_set_ctx_md_params(void *vctx, const OSSL_PARAM params[])
{
PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
if (ctx->mdctx == NULL)
return 0;
return EVP_MD_CTX_set_params(ctx->mdctx, params);
}
static const OSSL_PARAM *ecdsa_settable_ctx_md_params(void *vctx)
{
PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
if (ctx->md == NULL)
return 0;
return EVP_MD_settable_ctx_params(ctx->md);
}
const OSSL_DISPATCH ecdsa_signature_functions[] = {
{ OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))ecdsa_newctx },
{ OSSL_FUNC_SIGNATURE_SIGN_INIT, (void (*)(void))ecdsa_signature_init },
{ OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))ecdsa_sign },
{ OSSL_FUNC_SIGNATURE_VERIFY_INIT, (void (*)(void))ecdsa_signature_init },
{ OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))ecdsa_verify },
{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
(void (*)(void))ecdsa_digest_signverify_init },
{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE,
(void (*)(void))ecdsa_digest_signverify_update },
{ OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL,
(void (*)(void))ecdsa_digest_sign_final },
{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
(void (*)(void))ecdsa_digest_signverify_init },
{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE,
(void (*)(void))ecdsa_digest_signverify_update },
{ OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL,
(void (*)(void))ecdsa_digest_verify_final },
{ OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))ecdsa_freectx },
{ OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))ecdsa_dupctx },
{ OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))ecdsa_get_ctx_params },
{ OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
(void (*)(void))ecdsa_gettable_ctx_params },
{ OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))ecdsa_set_ctx_params },
{ OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS,
(void (*)(void))ecdsa_settable_ctx_params },
{ OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS,
(void (*)(void))ecdsa_get_ctx_md_params },
{ OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS,
(void (*)(void))ecdsa_gettable_ctx_md_params },
{ OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS,
(void (*)(void))ecdsa_set_ctx_md_params },
{ OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS,
(void (*)(void))ecdsa_settable_ctx_md_params },
{ 0, NULL }
};

View File

@ -635,7 +635,7 @@ Result = KEYOP_INIT_ERROR
Reason = invalid salt length
Title = EC tests
Title = ECDSA tests
Verify = P-256
Availablein = default