Provider: cannot sign with ed25519-like key

131 views
Skip to first unread message

Bernd Ritter

unread,
Aug 6, 2024, 2:57:18 AM8/6/24
to openss...@openssl.org
Hello everyone,

I am writing a custom provider which uses a different OID for ED25519
but internally uses this cipher. I'm now stuck on the signing for weeks.

The private and public key look identical except for the OID when
compared to a ED25519-key created by the default provider. This is the
logging output I see, when I run into the problem with

The used md_ctx is built up in the
OSSL_FUNC_signature_digest_sign_init_fn. Shortened for readability:

####################################################################
static int digest_sign_init(void *ctx, const char *mdname, void
*provkey, const OSSL_PARAM *params)
{
sig_ctx *sigctx = (sig_ctx*) ctx;

EVP_PKEY *pkey = (EVP_PKEY*) provkey;
EVP_PKEY_CTX* pkey_ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey,
"provider=default");

EVP_MD_CTX* dflt_md_ctx = EVP_MD_CTX_new();
EVP_MD_CTX_set_pkey_ctx(dflt_md_ctx, pkey_ctx);

// These two are checked in their return code but omitted here
EVP_DigestSignInit_ex(dflt_md_ctx, NULL, NULL, NULL, NULL, pkey,
params));
EVP_PKEY_CTX_ctrl_str(pkey_ctx, "instance", "ed25519ph");

sigctx->md_ctx = dflt_md_ctx;

return 1;
}
####################################################################

The digest-sign function is implemented as
OSSL_FUNC_signature_digest_sign_update_fn digest_sign_update:

####################################################################
static int digest_sign_update(void *ctx, const unsigned char *data,
size_t datalen)
{
DBG("%s - digest sign update. datalen=%lu\n", __FILE__, datalen);
sig_ctx *sigctx = (sig_ctx*) ctx;

// Just to see if we have a valid key
EVP_PKEY* pkey =
EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_get_pkey_ctx(sigctx->md_ctx));
DBG("%s - Public Key Context: %s, size:%d\n", __FILE__,
EVP_PKEY_get0_description(pkey), EVP_PKEY_get_size(pkey));

const int rc = EVP_DigestSignUpdate(sigctx->md_ctx, data, datalen);
if (rc != 1) {
DBG("%s - digest sign update failed rc=%d. %s\n", __FILE__, rc,
ERR_error_string(ERR_get_error(), NULL));
}

return rc;
}
####################################################################

So this is now the resulting log messages:

####################################################################
operating switch: 12 (1=DIGEST, 2=CIPHER, 5=RAND, 10=KEYMGMT, 12=SIG,
20=ENC, 21=DEC, 22=STOR)
/src/ed25519ph_sign_x509.c - d
/src/ed25519ph_sign_x509.c - digest sign update. datalen=29
/src/ed25519ph_sign_x509.c - Public Key Context: OpenSSL ED25519
implementation, size:64
/src/ed25519ph_sign_x509.c - digest sign update failed rc=0.
error:030000A7:digital envelope routines::unknown max size
Error signing raw input data
Public Key operation error
804B6635217A0000:error:030C0101:digital envelope
routines:EVP_DigestSignUpdate:called a function you should not
call:crypto/evp/m_sigver.c:420:
####################################################################

What does "unknown max size" mean in this context? The (custom) public
key can be worked on with EVP_PKEY_print_public so it seems correct-(ish)?

####################################################################
ED25519 Public-Key:
pub:
86:f1:df:8f:7c:d1:51:b1:8d:b8:bf:4c:d7:e3:28:
b3:1c:d6:1a:66:2a:00:2b:e8:34:18:bb:c4:e8:82:
f5:d1
####################################################################

Hope anyone can give me some hint or direction, as said above I am
trying to figure this out for some weeks now.

This message has been posted to OpenSSL github discussion board as well,
it has nicer formatting if you like:
https://github.com/openssl/openssl/discussions/25050

All the best,
Bernd

--
Bernd Ritter
Senior Linux Developer
Tel.: +49 175 534 4534
Mail: rit...@b1-systems.de

B1 Systems GmbH
Osterfeldstraße 7 / 85088 Vohburg / http://www.b1-systems.de
GF: Ralph Dehner / Unternehmenssitz: Vohburg / AG: Ingolstadt, HRB 3537

Tomas Mraz

unread,
Aug 6, 2024, 3:26:19 AM8/6/24
to Bernd Ritter, openss...@openssl.org
Hello Bernd,

the EdDSA implementation in the default provider currently does not
support the streaming operation with Update, Update,..., Final. It
could be supported for the prehash variant but currently this is not
implemented.

Tomas Mraz, OpenSSL

On Tue, 2024-08-06 at 08:57 +0200, 'Bernd Ritter' via openssl-users
wrote:
--
Tomáš Mráz, OpenSSL

Bernd Ritter

unread,
Aug 6, 2024, 3:30:27 AM8/6/24
to openss...@openssl.org
Hello Tomas,

thank you for your response! I am aware of that ED25519 only supports
the block operation. I also tried to implement that, but it seems to
only call the update variant. Is there a way to "enforce" the use of the
block operation in the provider? There seems to be a parameter for that,
but I could not find the correct usage of that.

All the best,
Bernd

Am 06.08.24 um 09:26 schrieb Tomas Mraz:

Steffen Nurpmeso

unread,
Aug 6, 2024, 6:03:22 PM8/6/24
to 'Bernd Ritter' via openssl-users
'Bernd Ritter' via openssl-users wrote in
<0474896a-fe7f-4842...@b1-systems.de>:
|Hello Tomas,
|
|thank you for your response! I am aware of that ED25519 only supports
|the block operation. I also tried to implement that, but it seems to
|only call the update variant. Is there a way to "enforce" the use of the
|block operation in the provider? There seems to be a parameter for that,
|but I could not find the correct usage of that.

EVP_DigestSignInit + EVP_DigestSign does that.
See Ed25519(7ssl) (it is *so* cool that the documentation has
become so much better!):

The PureEdDSA instances do not support the streaming mechanism of other
signature algorithms using, for example, EVP_DigestUpdate(). The
message to sign or verify must be passed using the one‐shot
EVP_DigestSign() and EVP_DigestVerify() functions.

*My* problem is that it does not seem automatizable, ie, you there
is no interface which says which way to go. I had

if(!EVP_DigestSignInit(mdcp->mdc_md_ctx, NIL, mdcp->mdc_md->md_md, NIL, kp->k_key) &&
!EVP_DigestSignInit(mdcp->mdc_md_ctx, NIL, NIL, NIL, kp->k_key)){

which "does that" (at least today), but is hacky.

--steffen
|
|Der Kragenbaer, The moon bear,
|der holt sich munter he cheerfully and one by one
|einen nach dem anderen runter wa.ks himself off
|(By Robert Gernhardt)
|
| Only during dog days:
| On the 81st anniversary of the Goebbel's Sportpalast speech
| von der Leyen gave an overlong hypocritical inauguration one.
| The brew's essence of our civilizing advancement seems o be:
| Total war - shortest war -> Permanent war - everlasting war

Bernd Ritter

unread,
Aug 8, 2024, 2:34:49 AM8/8/24
to Tomas Mraz, openss...@openssl.org
Hey Tomas,

I have a working provider that uses a ED25519 key and has the sign
(OSSL_FUNC_SIGNATURE_DIGEST_SIGN) and verify
(OSSL_FUNC_SIGNATURE_DIGEST_VERIFY) methods implemented to use the
ed25519ph algorithm.

Difference between this POC and my current implementation is that I need
a ED25519 key with a different OID, thus implementing the encoder and
decoder myself.

Do you have any idea what the error message means in this regard?

> error:030000A7:digital envelope routines::unknown max size

The key looks exactly the same when I compare the ASN1dump with a
originally created ED25519 key. Maybe the decoder is wrong somewhere?
Hope you have any hint.

Cheers,
Bernd

Am 06.08.24 um 09:26 schrieb Tomas Mraz:

Matt Caswell

unread,
Aug 8, 2024, 4:44:19 AM8/8/24
to Bernd Ritter, Tomas Mraz, openss...@openssl.org
On Thu, Aug 8, 2024 at 7:34 AM 'Bernd Ritter' via openssl-users <openss...@openssl.org> wrote:
 > error:030000A7:digital envelope routines::unknown max size


That error comes from here:


So something is attempting to determine the size of a pkey and found it to be invalid.

This value should be returned by the keymgmt get_params function for the parameter OSSL_PKEY_PARAM_MAX_SIZE

See:

and


Matt

Bernd Ritter

unread,
Aug 12, 2024, 2:24:17 AM8/12/24
to openss...@openssl.org
Hey Matt,

thanks, that seems to be it! I've set up a params list in keymanagement
with:

static const OSSL_PARAM keymgmt_params[] = {
OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, &_ed25519_keysize),
OSSL_PARAM_END
};

static const OSSL_PARAM* keymgmt_gettable_params(ossl_unused void *provctx)
{
return keymgmt_params;
}

but still the OSSL_FUNC_KEYMGMT_GET_PARAMS only returns two prefilled
params:

* default-digest
* mandatory-digest

but has not the "max-size" param. Why would that be?

All the best,
Bernd

Am 08.08.24 um 10:44 schrieb Matt Caswell:
>
>
> On Thu, Aug 8, 2024 at 7:34 AM 'Bernd Ritter' via openssl-users
> <openss...@openssl.org <mailto:openss...@openssl.org>> wrote:
>
>  > error:030000A7:digital envelope routines::unknown max size
>
>
> That error comes from here:
>
> https://github.com/openssl/openssl/blob/fd39d1c80cd5bd9cb5c64e3fc96102397e5e860f/crypto/evp/p_lib.c#L1811-L1827 <https://github.com/openssl/openssl/blob/fd39d1c80cd5bd9cb5c64e3fc96102397e5e860f/crypto/evp/p_lib.c#L1811-L1827>
>
> So something is attempting to determine the size of a pkey and found it
> to be invalid.
>
> This value should be returned by the keymgmt get_params function for the
> parameter OSSL_PKEY_PARAM_MAX_SIZE
>
> See:
> https://docs.openssl.org/master/man7/provider-keymgmt/#common-information-parameters <https://docs.openssl.org/master/man7/provider-keymgmt/#common-information-parameters>
>
> and
>
> https://docs.openssl.org/master/man3/EVP_PKEY_get_size/#description
> <https://docs.openssl.org/master/man3/EVP_PKEY_get_size/#description>
>
> Matt

Bernd Ritter

unread,
Aug 12, 2024, 4:50:11 AM8/12/24
to openss...@openssl.org
Hey Matt,

I could close in on this a little bit. Seems like when calling the
Encoder the additional parameter OSSL_PKEY_PARAM_MAX_SIZE is used.

operating switch: 20 (1=DIGEST, 2=CIPHER, 5=RAND, 10=KEYMGMT, 12=SIG,
20=ENC, 21=DEC, 22=STOR)
ED25519 Public-Key:
pub:
a8:40:93:b5:d5:d2:47:b5:c0:1f:25:7c:de:d2:c2:
4b:93:7a:6c:77:6b:90:5b:ae:1d:60:9a:80:03:f6:
f3:97
ed25519ph-provider/src/ed25519ph_keymgmt.c - setting pkey max size to 32
--- Start of PARAM list:
PARAM key=bits, data_type=1
PARAM key=security-bits, data_type=1
PARAM key=max-size, data_type=1
PARAM value - dump with len=4
20 00 00 00
dump done
--- End of PARAM list

But when in the Signing part this parameter is not found anymore.

operating switch: 12 (1=DIGEST, 2=CIPHER, 5=RAND, 10=KEYMGMT, 12=SIG,
20=ENC, 21=DEC, 22=STOR)
operating switch: 10 (1=DIGEST, 2=CIPHER, 5=RAND, 10=KEYMGMT, 12=SIG,
20=ENC, 21=DEC, 22=STOR)
ed25519ph-provider/src/ed25519ph_sign_x509.c - digest sign newctx,
propq='?provider=myprov'
ed25519ph-provider/src/ed25519ph_keymgmt.c - keymgmt_get_params
--- Start of PARAM list:
PARAM key=default-digest, data_type=4
PARAM key=mandatory-digest, data_type=4
--- End of PARAM list

How could the list of parameters be different when both of them use the
keymanagement functions?

All the best,
Bernd

Am 12.08.24 um 08:24 schrieb 'Bernd Ritter' via openssl-users:

Matt Caswell

unread,
Aug 12, 2024, 5:42:55 AM8/12/24
to Bernd Ritter, openss...@openssl.org


On 12/08/2024 07:24, 'Bernd Ritter' via openssl-users wrote:
> Hey Matt,
>
> thanks, that seems to be it! I've set up a params list in keymanagement
> with:
>
>  static const OSSL_PARAM keymgmt_params[] = {
>     OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, &_ed25519_keysize),
>     OSSL_PARAM_END
> };

This looks slightly odd. You seem to be attempting to pass a variable
(_ed25519_keysize) as part of the *gettable* params. This would normally
be NULL here, e.g.

static const OSSL_PARAM keymgmt_params[] = {
OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
OSSL_PARAM_END
};

static const OSSL_PARAM *keymgmt_gettable_params(void *provctx)
{
return keymgmt_params;
}

The purpose of "gettable params" is simply to advertise what parameters
your keymgmt understands. It doesn't actually get the parameters themselves.

For that you need a separate "get_params" function, e.g.

static int keymgmt_get_params(void *key, OSSL_PARAM params[])
{
OSSL_PARAM *p;

if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
&& !OSSL_PARAM_set_int(p, _ed25519_keysize))
return 0;
return 1;
}

And of course both of those need exist in your OSSL_DISPATCH table:

const OSSL_DISPATCH keymgmt_functions[] = {
...otherstuff...
{ OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))keymgmt_get_params },
{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*)
(void))keymgmt_gettable_params },
OSSL_DISPATCH_END
};

Note, typically I would expect you to have to support some other params
too such as OSSL_PKEY_PARAM_BITS and OSSL_PKEY_PARAM_SECURITY_BITS.

Matt

Bernd Ritter

unread,
Aug 12, 2024, 6:08:58 AM8/12/24
to openss...@openssl.org
Hey Matt,

yeah, that was kind of a duplicate. I've looked up how they did it in
the TPM2 provider and changed it accordingly. It now matches your
description, thank you for that!

I also added two more parameters for the ED25519 key:
OSSL_PKEY_PARAM_BITS and OSSL_PKEY_PARAM_SECURITY_BITS.

Still no change. In the encoder part itself the parameters are all set,
in the digest sign they are not.

I do not understand how the parameter list can change? As my debugging
logs are called, it seems that my get_params is called accordingly.

All the best,
Bernd

Am 12.08.24 um 11:42 schrieb Matt Caswell:

Matt Caswell

unread,
Aug 12, 2024, 6:33:41 AM8/12/24
to Bernd Ritter, openss...@openssl.org


On 12/08/2024 11:08, 'Bernd Ritter' via openssl-users wrote:
> I do not understand how the parameter list can change? As my debugging
> logs are called, it seems that my get_params is called accordingly.
>

I don't really understand what you mean by this. Each invocation of your
get_params function may request different parameters depending on which
parameters the caller is interested in for any given context.

As I previously mentioned the "unknown max size" error comes from the
EVP_PKEY_get_size() function, and this ultimately gets the size by
querying the OSSL_PKEY_PARAM_MAX_SIZE parameter.

The value of this parameter is cached in the pkey. This happens here in
OpenSSL:

https://github.com/openssl/openssl/blob/2f33265039cdbd0e4589c80970e02e208f3f94d2/crypto/evp/keymgmt_lib.c#L289-L313

This is the point in libcrypto where your provider is called and the
OSSL_PKEY_PARAM_MAX_SIZE parameter is queried - the result of which is
cached in the cache.size field of the pkey. All subsequent calls to
`EVP_PEKY_get_size()` will refer to this cache and give the "unknown
max_size" error if this cached size is <= 0.

If you are struggling to see how this fits together with what your code
is doing then I suggest you build OpenSSL with debug symbols on and set
a breakpoint in the `evp_keymgmt_util_cache_keyinfo` function I linked
to above and step through what is happening in the interaction with your
provider.

Matt

Bernd Ritter

unread,
Aug 12, 2024, 9:17:54 AM8/12/24
to openss...@openssl.org
Hey there,

debugging actually solved it, there was a silent other error that caused
problems, but not visual problem I saw. Got that fixed, many thanks for
that!

Following through with debugging I got to the next road block. My
provider is now trying to sign some payload. It calls
OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE for the first time. I guess this
should be OSSL_FUNC_SIGNATURE_DIGEST_SIGN, but I have no idea to enforce
this.

It's the same context, same data, same data size.

Breakpoint 1, EVP_DigestSignUpdate (ctx=0x5555556a2e40,
data=0x7fffffffc3b0, dsize=29) at crypto/evp/m_sigver.c:419
423 if (pctx->op.sig.signature->digest_sign_update == NULL) {
428 return
pctx->op.sig.signature->digest_sign_update(pctx->op.sig.algctx,
(gdb) n
ed25519ph-provider/src/ed25519ph_sign_x509.c - digest sign update.
datalen=29

Now when the provider wants to close the deal, the digest_sign_update
from the context is now NULL suddenly.

Breakpoint 1, EVP_DigestSignUpdate (ctx=0x5555556bac40,
data=0x7fffffffc3b0, dsize=29) at crypto/evp/m_sigver.c:419
423 if (pctx->op.sig.signature->digest_sign_update == NULL) {
424 ERR_raise(ERR_LIB_EVP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);

ed25519ph-provider/src/ed25519ph_sign_x509.c - digest sign update failed
rc=0. error:030C0101:digital envelope routines::called a function you
should not call
Error signing raw input data
Public Key operation error

I've also tried the "trick" from Steffen who mentioned earlier a hacky
way to enforce block operation.

All the best,
Bernd

Am 12.08.24 um 12:33 schrieb Matt Caswell:

Matt Caswell

unread,
Aug 12, 2024, 9:22:45 AM8/12/24
to Bernd Ritter, openss...@openssl.org


On 12/08/2024 14:17, 'Bernd Ritter' via openssl-users wrote:
> Hey there,
>
> debugging actually solved it, there was a silent other error that caused
> problems, but not visual problem I saw. Got that fixed, many thanks for
> that!
>
> Following through with debugging I got to the next road block. My
> provider is now trying to sign some payload. It calls
> OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE for the first time. I guess this
> should be OSSL_FUNC_SIGNATURE_DIGEST_SIGN, but I have no idea to enforce
> this.
>
> It's the same context, same data, same data size.

You say its the same context, and yet the ctx pointer seems to be
different in the debugging output you showed, i.e. ctx=0x5555556a2e40
compared to ctx=0x5555556bac40.

So are you sure it is the same ctx?

Matt

Bernd Ritter

unread,
Aug 12, 2024, 9:27:41 AM8/12/24
to openss...@openssl.org
Hey Matt,

yeah point on. Its too hot I guess, was just checking the last memory
address numbers.

So you mean that somewhere the context contains a "wrong" key?

Bernd

Am 12.08.24 um 15:22 schrieb Matt Caswell:

Matt Caswell

unread,
Aug 12, 2024, 10:18:02 AM8/12/24
to Bernd Ritter, openss...@openssl.org


On 12/08/2024 14:27, 'Bernd Ritter' via openssl-users wrote:
> Hey Matt,
>
> yeah point on. Its too hot I guess, was just checking the last memory
> address numbers.
>
> So you mean that somewhere the context contains a "wrong" key?

Potentially. It's unclear. My point was simply that the ctx pointers
were different. If you are expecting them to be the same then you need
to figure out why they're not.

Matt

Bernd Ritter

unread,
Aug 13, 2024, 6:41:43 AM8/13/24
to openss...@openssl.org
Hey again,

the two contexts are fine and intended, one context is the ED25519 key
with the custom OID within the custom provider's context.

The other context is the default (OpenSSL) ED25519 context. And here's
where the error unfolds.

As I know (and was state here before) ED25519 currently only supports
block operations. Thus it should use <ed25519_digest_sign>.

When I load the EVP_PKEY from the keymanagement with the raw key and
build up a new EVP_PKEY from it, the DigestSign wants somehow to call
<ed25519_digest_update> which is not linked as a function pointer in the
EVP_PKEY struct.

The EVP_PKEY_CTX is build up like this in my custom providers
OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT:

OSSL_LIB_CTX* lctx = OSSL_LIB_CTX_new();
EVP_PKEY_CTX* pkey_ctx = EVP_PKEY_CTX_new_from_pkey(lctx, pkey,
"provider=default");

EVP_MD_CTX* dflt_md_ctx = EVP_MD_CTX_new();
EVP_MD_CTX_set_pkey_ctx(dflt_md_ctx, pkey_ctx);

EVP_DigestVerifyInit_ex(dflt_md_ctx, NULL, NULL, lctx,
"provider=default", pkey, NULL);
EVP_PKEY_CTX_ctrl_str(pkey_ctx, "instance", "ed25519ph")

and in the OSSL_FUNC_SIGNATURE_DIGEST_SIGN i call:

const int rc = EVP_DigestSign(sigctx->md_ctx, sigret, siglen, tbs,
tbslen);

The use of <ed25519_digest_sign> is - as far as I understand - correct
behavior - but how does it happen, that <ed25519_digest_update> is
supposed to be called?

The private key is loaded in keymangement load:

static void *keymgmt_load(const void *reference, size_t reference_sz)
EVP_PKEY* pkey = EVP_PKEY_new_raw_private_key_ex(NULL, "ED25519",
"provider=default", (const unsigned char*) reference, reference_sz);
return pkey;
}

Now the debugger shows, that sign_update_fn is NULL (which is supposed
to be)

(gdb) p pctx->op.sig.signature.digest_sign_update
$4 = (OSSL_FUNC_signature_digest_sign_update_fn *) 0x0
(gdb) p pctx->op.sig.signature.digest_sign
$5 = (OSSL_FUNC_signature_digest_sign_fn *) 0x7ffff7ca87d4
<ed25519_digest_sign>

How can this happen? Is loading the ED25519 evp_key from the raw data
somehow wrong or incomplete?

All the best,
Bernd


Am 12.08.24 um 16:17 schrieb Matt Caswell:

Matt Caswell

unread,
Aug 14, 2024, 3:16:27 AM8/14/24
to Bernd Ritter, openss...@openssl.org


On 13/08/2024 11:41, 'Bernd Ritter' via openssl-users wrote:
> The EVP_PKEY_CTX is build up like this in my custom providers
> OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT:
>
>   OSSL_LIB_CTX* lctx = OSSL_LIB_CTX_new();
>   EVP_PKEY_CTX* pkey_ctx = EVP_PKEY_CTX_new_from_pkey(lctx, pkey,
> "provider=default");
>
>   EVP_MD_CTX* dflt_md_ctx = EVP_MD_CTX_new();
>   EVP_MD_CTX_set_pkey_ctx(dflt_md_ctx, pkey_ctx);
>
>   EVP_DigestVerifyInit_ex(dflt_md_ctx, NULL, NULL, lctx,
> "provider=default", pkey, NULL);
>   EVP_PKEY_CTX_ctrl_str(pkey_ctx, "instance", "ed25519ph")
>
> and in the OSSL_FUNC_SIGNATURE_DIGEST_SIGN i call:
>
>   const int rc = EVP_DigestSign(sigctx->md_ctx, sigret, siglen, tbs,
> tbslen);
>
> The use of <ed25519_digest_sign> is - as far as I understand - correct
> behavior - but how does it happen, that <ed25519_digest_update> is
> supposed to be called?



This is how EVP_DigestSign() is implemented:

https://github.com/openssl/openssl/blob/21bcae6561d73e629f11e19975f24283559d36c0/crypto/evp/m_sigver.c#L579-L610

As you can see from the above, what it does is first check for the
availability of a "digest_sign" function in the fetched signature
algorithm. If it exists it calls it. However, if it does not exist for
some reason then it will fall back to calling EVP_DigestSignUpdate()
followed immediately by EVP_DigestSignFinal().

But - you can also see from the above that part of the check it does for
the availability of the "digest_sign" function is that it checks that
the current operation that the ctx has been configured for is
`EVP_PKEY_OP_SIGNCTX` - i.e. the ctx has been configured for signing.

But in the above code sample you seem to be calling
`EVP_DigestVerifyInit_ex`, i.e. the ctx is not configured for signing
but for verifying!!! So it looks to me like when `EVP_DigestSign` is
called it stops looks for the digest_sign function when it realises that
its been configured for verifying, and then (slightly strangely)
proceeds onto the fallback implementation of calling
`EVP_DigestSignUpdate` which hasn't been implemented, and therefore it
fails.

The solution would obviously be to call EVP_DigestSignInit_ex() instead
of EVP_DigestVerifyInit_ex().

Matt

Bernd Ritter

unread,
Aug 14, 2024, 3:47:57 AM8/14/24
to openss...@openssl.org
Hey Matt,

I am terribly sorry for that, I copied some wrong code snippets, because
SignInit and VerifyInit are very similar, except for calling
EVP_DigestSignInit and EVP_DigestVerifyInit. So please assume SignInit
and VerifyInit call each the correct init-method.

So I am still wondering: can I somehow configure that signing should use
automatically block operation instead of streaming?

All the best,
Bernd

Am 14.08.24 um 09:16 schrieb Matt Caswell:

Steffen Nurpmeso

unread,
Aug 14, 2024, 2:23:31 PM8/14/24
to Matt Caswell, Bernd Ritter, openss...@openssl.org
Matt Caswell wrote in
<15344cfb-ca5d-4413...@openssl.org>:
...
|This is how EVP_DigestSign() is implemented:
|
|https://github.com/openssl/openssl/blob/21bcae6561d73e629f11e19975f24283\
|559d36c0/crypto/evp/m_sigver.c#L579-L610
|
|As you can see from the above, what it does is first check for the
|availability of a "digest_sign" function in the fetched signature
|algorithm. If it exists it calls it. However, if it does not exist for

Users need a possibility to transparently gain knowledge of which
code path has to be taken. I cannot transparently implement this,
i need to hardcode something. (Yes, i did how i said in the past,
ie, trying to establish message-digest, and take the other code
path if that did not work, but whether that is the approach to do
it was only a guessing.)

This is at odds with what SSL_CONF_cmd() is trying to achieve (to
some extend, at least).

Bernd Ritter

unread,
Aug 19, 2024, 2:21:13 AM8/19/24
to openss...@openssl.org
Hey everyone,

thanks for all the answers. I've circumvented the problem with the
mislead DIGEST_UPDATE by letting it allow to call DIGEST_UPDATE and
saving the data into memory.

When DIGEST_UPDATE_FINAL is called, I then call EVP_DigestSign.

Thank you to everyone participating in finding a way!

Cheers,
Bernd

PS: IF there is a way to set a Parameter to enforce block operation,
please let me know.

Am 14.08.24 um 09:16 schrieb Matt Caswell:
>
>
Reply all
Reply to author
Forward
0 new messages