Mailing List Archive

Adding new public key KEM API
Hello,

We now have two sets of patches for PQC.

Simon Josefsson's second version of the sntrup761 patch
Falko Strenzke patch for ML-KEM

For the next new release of libgcrypt, I'd like to add new API for Key
Encapsulation Mechanism in libgcrypt. What I intend is lower level API
(instead of higher level API with S-expression), just like Simon
suggested. (If needed, S-expression based API will be possible to be
added later.)

What I'm testing now is following:

gcry_error_t gcry_kem_keypair (int algo, const void *context,
void *pubkey,
void *seckey);

gcry_error_t gcry_kem_encap (int algo, const void *context,
const void *pubkey,
void *ciphertext,
void *shared_secret);

gcry_error_t gcry_kem_decap (int algo, const void *context,
const void *seckey,
const void *ciphertext,
void *shared_secret);

That is, rename of functions and adding CONTEXT to Simon's proposal.

In this API, format of the CONTEXT, PUBKEY, SECKEY, CIPHERTEXT,
SHARED_SECRET are defined by ALGO. (Most of the cases, it's
fixed-length byte string.)

I'd like to cover NTRU Prime, Kyber, and ECDH KEM in hybrid PQC.

I'm not sure if ECDH in OpenPGP (of RFC 6637) will be covered by this
API. Perhaps, gcry_ecc_mul_point will be depreated, in preference of
new KEM API.

This development is tracked by:
https://dev.gnupg.org/T6755

Attached is modified version of Simon's t-kem.c, which works for me
(with NTRU Prime and Kyber).
--
Re: Adding new public key KEM API [ In reply to ]
NIIBE Yutaka <gniibe@fsij.org> writes:

> gcry_error_t gcry_kem_keypair (int algo, const void *context,
> void *pubkey,
> void *seckey);
>
> gcry_error_t gcry_kem_encap (int algo, const void *context,
> const void *pubkey,
> void *ciphertext,
> void *shared_secret);
>
> gcry_error_t gcry_kem_decap (int algo, const void *context,
> const void *seckey,
> const void *ciphertext,
> void *shared_secret);

Thanks for working on this, this looks okay to me.

Is there any known algorithm that will make use of CONTEXT? If not, I
suggest to drop the variable and when/if the need arise, add a separate
API for that use-case later on.

Some future KEM's MAY also have variable-length outputs, so a 'size_t
shared_secret_length' parameter would be useful, however similar to my
comment about CONTEXT; I believe it is better to have a separate API for
that use-case, when/if that arise, instead of polluting the API for
normal use-cases with extra parameters.

/Simon
Re: Adding new public key KEM API [ In reply to ]
Hello,

Simon Josefsson <simon@josefsson.org> wrote:
> Is there any known algorithm that will make use of CONTEXT? If not, I
> suggest to drop the variable and when/if the need arise, add a separate
> API for that use-case later on.

When we consider ECDH KEM, Kyber, and NTRU Prime for Hybrid PQC, we
don't need CONTEXT.

My concern is for two cases.

(1) Specifying the size of SHARED_SECRET

Well, for this case, the size may be specified by encoding into ALGO,
like GCRY_KEM_X25519_128 and GCRY_KEM_X25519_256.


(2) KDF with domain seperation

KDF under the KEM may want domain seperation. (For the case of Hybrid
PQC, this can be done in key combiner.)

If I today considered OpenPGP support with ECDH KEM (alternative of
RFC6637), I would need something like CONTEXT in the API to specify
domain seperation with KDF.

If I supported a composite KEM of Hybrid PQC by the API, I would need
CONTEXT, too.

Well, this could be also solved by encoding information into ALGO, like
GCRY_KEM_X25519_OPENPGP and GCRY_KEM_KEYBER768_PLUS_X25519_OPENPGP.

So... I could not insist that having CONTEXT is much useful.

> I believe it is better to have a separate API for that use-case,
> when/if that arise, instead of polluting the API for normal use-cases
> with extra parameters.

Good point.


In my not so humble opinion, it is not programmer's task to define this
kind of API, but it is better for standardization process or academic to
provide useful consensus for such an interface.

Today, I found this paper:

@misc{cryptoeprint:2023/272,
author = {Bertram Poettering and Simon Rastikian},
title = {A study of KEM generalizations},
howpublished = {Cryptology ePrint Archive, Paper 2023/272},
year = {2023},
doi = {10.1007/978-3-031-30731-7_3},
note = {\url{https://eprint.iacr.org/2023/272}},
url = {https://eprint.iacr.org/2023/272}

And I wonder what SP800-227 (not yet vailable) will be.
--

_______________________________________________
Gcrypt-devel mailing list
Gcrypt-devel@gnupg.org
https://lists.gnupg.org/mailman/listinfo/gcrypt-devel
Re: Adding new public key KEM API [ In reply to ]
Detailed comments below, however first a big +1 for your effort here,
and to clarify that my opinions are not strong: I would prefer libgcrypt
to have sntrup761 under /any/ API than delaying adding support further
while trying to make the API perfect. Post-quantum crypto has been
delayed for way too long already.

If it hasn't been mentioned already, I would give a +1 on supporting
Classic McEliece as well -- with support for McEliece, NTRU Prime and
Kyber we will have a good toolbox to work with. I've looked at the
McEliece API needs, and they are the same as for NTRU Prime,
i.e. minimal API with no variable-length outputs.

NIIBE Yutaka <gniibe@fsij.org> writes:

> Hello,
>
> Simon Josefsson <simon@josefsson.org> wrote:
>> Is there any known algorithm that will make use of CONTEXT? If not, I
>> suggest to drop the variable and when/if the need arise, add a separate
>> API for that use-case later on.
>
> When we consider ECDH KEM, Kyber, and NTRU Prime for Hybrid PQC, we
> don't need CONTEXT.
>
> My concern is for two cases.
>
> (1) Specifying the size of SHARED_SECRET
>
> Well, for this case, the size may be specified by encoding into ALGO,
> like GCRY_KEM_X25519_128 and GCRY_KEM_X25519_256.

I think a separate API with an explicit 'size_t shared_secret_length'
parameter would be a better interface than either of 1) 'void *context'
and casting of parameters, and 2) fixed-size ALGO identifiers.

> (2) KDF with domain seperation
>
> KDF under the KEM may want domain seperation. (For the case of Hybrid
> PQC, this can be done in key combiner.)
>
> If I today considered OpenPGP support with ECDH KEM (alternative of
> RFC6637), I would need something like CONTEXT in the API to specify
> domain seperation with KDF.

I don't know the details here, so I can't tell if this is a generally
useful thing, although my preference would still be a separate API that
has a parameter with explicit type and documented purpose.

> If I supported a composite KEM of Hybrid PQC by the API, I would need
> CONTEXT, too.
>
> Well, this could be also solved by encoding information into ALGO, like
> GCRY_KEM_X25519_OPENPGP and GCRY_KEM_KEYBER768_PLUS_X25519_OPENPGP.

Hybrid modes are in my mind a new instance of a KEM that indeed warrant
a new identifier.

> In my not so humble opinion, it is not programmer's task to define this
> kind of API, but it is better for standardization process or academic to
> provide useful consensus for such an interface.
>
> Today, I found this paper:
>
> @misc{cryptoeprint:2023/272,
> author = {Bertram Poettering and Simon Rastikian},
> title = {A study of KEM generalizations},
> howpublished = {Cryptology ePrint Archive, Paper 2023/272},
> year = {2023},
> doi = {10.1007/978-3-031-30731-7_3},
> note = {\url{https://eprint.iacr.org/2023/272}},
> url = {https://eprint.iacr.org/2023/272}
>
> And I wonder what SP800-227 (not yet vailable) will be.

Yeah, I think we need to take other research into account. However I
would not give standardization bodies or researchers a carte blanche on
this -- then we end up with stuff like PKCS#11, DRBG-CTR or ASN.1 which
has awful APIs that are harmful to security.

/Simon
Re: Adding new public key KEM API [ In reply to ]
Hi!

On Tue, 17 Oct 2023 15:27, NIIBE Yutaka said:

> In this API, format of the CONTEXT, PUBKEY, SECKEY, CIPHERTEXT,
> SHARED_SECRET are defined by ALGO. (Most of the cases, it's
> fixed-length byte string.)

I really would like to see a size parmater for each pointer. This can
help to detect eerrrors earlier, avoid problems with API/ABI mismatches,
and makes low-level language bindings easier to write.

Regarding the context parameter, I consider this extremely useful and it
was a misconception that we did not add this to the other public key
functions. Most other subsystems in Libgcrypt follow the open-use-close
paradigm with the public key functions beeing the major exception.

The context parameter offers us a way to do pre-computations and keep to
keep other kinds of state.


Salam-Shalom,

Werner

--
The pioneers of a warless world are the youth that
refuse military service. - A. Einstein
Re: Adding new public key KEM API [ In reply to ]
I also would prefer to provide the length of each encoded value in the
function signature explicitly.

Regarding the values which will de facto be byte arrays (keys, shared
secret), they should be passed as (const)unsigned char* in my opinion.

For the context object, as I wrote before, I think it should be a
specific type. This would be in line with existing API functions for
hash functions, MAC, etc. Or is there a specific reason to make the type
obscure specifically in this case?

- Falko

Am 18.10.23 um 10:21 schrieb Werner Koch via Gcrypt-devel:
> Hi!
>
> On Tue, 17 Oct 2023 15:27, NIIBE Yutaka said:
>
>> In this API, format of the CONTEXT, PUBKEY, SECKEY, CIPHERTEXT,
>> SHARED_SECRET are defined by ALGO. (Most of the cases, it's
>> fixed-length byte string.)
> I really would like to see a size parmater for each pointer. This can
> help to detect eerrrors earlier, avoid problems with API/ABI mismatches,
> and makes low-level language bindings easier to write.
>
> Regarding the context parameter, I consider this extremely useful and it
> was a misconception that we did not add this to the other public key
> functions. Most other subsystems in Libgcrypt follow the open-use-close
> paradigm with the public key functions beeing the major exception.
>
> The context parameter offers us a way to do pre-computations and keep to
> keep other kinds of state.
>
>
> Salam-Shalom,
>
> Werner
>
>
> _______________________________________________
> Gcrypt-devel mailing list
> Gcrypt-devel@gnupg.org
> https://lists.gnupg.org/mailman/listinfo/gcrypt-devel
--

*MTG AG*
Dr. Falko Strenzke
Executive System Architect

Phone: +49 6151 8000 24
E-Mail: falko.strenzke@mtg.de
Web: mtg.de <https://www.mtg.de>


------------------------------------------------------------------------

MTG AG - Dolivostr. 11 - 64293 Darmstadt, Germany
Commercial register: HRB 8901
Register Court: Amtsgericht Darmstadt
Management Board: Jürgen Ruf (CEO), Tamer Kemeröz
Chairman of the Supervisory Board: Dr. Thomas Milde

This email may contain confidential and/or privileged information. If
you are not the correct recipient or have received this email in error,
please inform the sender immediately and delete this email. Unauthorised
copying or distribution of this email is not permitted.

Data protection information: Privacy policy
<https://www.mtg.de/en/privacy-policy>
Re: Adding new public key KEM API [ In reply to ]
On Wed, 18 Oct 2023 11:00, Falko Strenzke said:

> hash functions, MAC, etc. Or is there a specific reason to make the
> type obscure specifically in this case?

Yes, because they depend on the algorithm. Opaque things should ise a
void pointer to avoid unnecessary casting. Remember that we are doing C
and not C++.


Salam-Shalom,

Werner

--
The pioneers of a warless world are the youth that
refuse military service. - A. Einstein
Re: Adding new public key KEM API [ In reply to ]
Sure, it is dependent on the algorithm. So it is the case also in the
case of gcry_mac_handle which then internally uses a union for the
different algorithm types. gcry_md_handle uses different approach by
adding space at the end of the struct depending on the algorithm.

So my question would be why we don't use one of these existing
approaches for APIs as well for the KEM API.

I think the union approach used in the case of the MAC API is much more
transparent then the approach taken for the hash API and would be my
recommendation for the KEM API. Overly large reservations in the struct
for specific KEM algorithms can be prevented by the algorithm specific
code allocating heap memory for them during the open() call.

- Falko

Am 18.10.23 um 11:21 schrieb Werner Koch:
> On Wed, 18 Oct 2023 11:00, Falko Strenzke said:
>
>> hash functions, MAC, etc. Or is there a specific reason to make the
>> type obscure specifically in this case?
> Yes, because they depend on the algorithm. Opaque things should ise a
> void pointer to avoid unnecessary casting. Remember that we are doing C
> and not C++.
>
>
> Salam-Shalom,
>
> Werner
>
--

*MTG AG*
Dr. Falko Strenzke
Executive System Architect

Phone: +49 6151 8000 24
E-Mail: falko.strenzke@mtg.de
Web: mtg.de <https://www.mtg.de>


------------------------------------------------------------------------

MTG AG - Dolivostr. 11 - 64293 Darmstadt, Germany
Commercial register: HRB 8901
Register Court: Amtsgericht Darmstadt
Management Board: Jürgen Ruf (CEO), Tamer Kemeröz
Chairman of the Supervisory Board: Dr. Thomas Milde

This email may contain confidential and/or privileged information. If
you are not the correct recipient or have received this email in error,
please inform the sender immediately and delete this email. Unauthorised
copying or distribution of this email is not permitted.

Data protection information: Privacy policy
<https://www.mtg.de/en/privacy-policy>
Re: Adding new public key KEM API [ In reply to ]
Werner Koch via Gcrypt-devel <gcrypt-devel@gnupg.org> writes:

> On Wed, 18 Oct 2023 11:00, Falko Strenzke said:
>
>> hash functions, MAC, etc. Or is there a specific reason to make the
>> type obscure specifically in this case?
>
> Yes, because they depend on the algorithm. Opaque things should ise a
> void pointer to avoid unnecessary casting. Remember that we are doing C
> and not C++.

I don't follow this -- I think the output variables should be 'unsigned
char *' or 'uint8_t *'. Are there any KEM algorithm that won't have a
standardized byte-oriented output format? If the output really was
opaque (which I think is not the intention), callers MUST NOT use them
even with a cast and libgcrypt should have some other function to
convert the 'void*' opaque pointer into a byte-stream for use by those
who want a byte-stream -- but I think that is not needed, and that all
the "opaque" outputs from KEM's will be treated as byte streams by all
callers. Using 'void*' for things that always will be 'uint8_t*' loses
type safety features of C.

/Simon
Re: Adding new public key KEM API [ In reply to ]
On Wed, 18 Oct 2023 15:35, Simon Josefsson said:

> callers. Using 'void*' for things that always will be 'uint8_t*' loses
> type safety features of C.

A memory buffer has no defined type so you can't have type safety.

I also tend to use unsigned char * for memory buffers (and char * for
Nul-termnated string) but in Libgcrypt we have always used void* for
data and keys. Adding something else would be surprising.


Shalom-Salam,

Werner

--
The pioneers of a warless world are the youth that
refuse military service. - A. Einstein
Re: Adding new public key KEM API [ In reply to ]
Werner Koch via Gcrypt-devel <gcrypt-devel@gnupg.org> writes:

> On Wed, 18 Oct 2023 15:35, Simon Josefsson said:
>
>> callers. Using 'void*' for things that always will be 'uint8_t*' loses
>> type safety features of C.
>
> A memory buffer has no defined type so you can't have type safety.

All KEM's I am aware of specify its outputs as byte vectors, not as
opaque memory buffers. Same for symmetric algorithms like hashes and
encryption. The only example to the contrary that I know of are some
asymmetric algorithms that provide outputs as multi-precision integers.

If we insist that outputs are opaque, there should be an API to convert
the opaque memory buffer into a byte-stream (which would most likely
just be an identity macro); otherwise this approach is inconsistent. I
think treating the outputs as opaque does not give any significant
advantage though.

> I also tend to use unsigned char * for memory buffers (and char * for
> Nul-termnated string) but in Libgcrypt we have always used void* for
> data and keys. Adding something else would be surprising.

Yes, consistency with existing APIs seems like a reasonable reason.
However I would trade that in to gain type checking.

/Simon
Re: Adding new public key KEM API [ In reply to ]
Hello, again,

Thank you all for your inputs and discussion.

I don't have any objections for adding features, but something can be
done in higher layer. Please note that the API in question is for lower
level, and adding complexity in lower layer should be avoided.
(I realized that I might be pursuing many in lower level API, too.)

This is the first step toward incorporating Hybrid PQC efforts into
libgcrypt.

So, let us focus on concrete targets of NTRU Prime, Kyber, and ECDH KEM
in Hybrid PQC, and providing an API for those functions by libgcrypt, so
that people can use for their applications.

In this case, I think it's good to have following API:

gcry_error_t gcry_kem_keypair (int algo,
void *pubkey,
void *seckey);

gcry_error_t gcry_kem_encap (int algo,
const void *pubkey,
void *ciphertext,
void *shared_secret);

gcry_error_t gcry_kem_decap (int algo,
const void *seckey,
const void *ciphertext,
void *shared_secret);

If needed, we will be able to add another API for KEM.


This development is tracked by:
https://dev.gnupg.org/T6755

--
Famous Haiku of Autumn, by Kobayashi Issa

"Gimme that harvest moon!"
cries the crying
child

Translated by David G. Lanoue

_______________________________________________
Gcrypt-devel mailing list
Gcrypt-devel@gnupg.org
https://lists.gnupg.org/mailman/listinfo/gcrypt-devel
Re: Adding new public key KEM API [ In reply to ]
On Thu, 19 Oct 2023 16:37, NIIBE Yutaka said:

> gcry_error_t gcry_kem_decap (int algo,
> const void *seckey,
> const void *ciphertext,
> void *shared_secret);

I still don't feel comfortable without a size argument. And if we add 3
more args we can also add con context one which we won't use. For the
caller it does not make a difference. Switching to a open-use-close
scheme would mahe a large difference.

> If needed, we will be able to add another API for KEM.

Which needs to be maintained etc. I am more in favor of preparing for
the future. With the void pointers this is easy but a forsafety checks
we should have size args.


Salam-Shalom,

Werner

--
The pioneers of a warless world are the youth that
refuse military service. - A. Einstein
Re: Adding new public key KEM API [ In reply to ]
Werner Koch <wk@gnupg.org> wrote:
> On Thu, 19 Oct 2023 16:37, NIIBE Yutaka said:
>
>> gcry_error_t gcry_kem_decap (int algo,
>> const void *seckey,
>> const void *ciphertext,
>> void *shared_secret);
>
> I still don't feel comfortable without a size argument.

Assumption here (for lower level API) is:

It's caller side (user of libgcrypt) which does static
compile-time check against ALGO and the length of each
byte-array.

If not static, caller side can do run-time check, if needed,
before the call.

Having a size argument would mean,

libgcrypt does run-time check of the length (for each call)

I wonder if this kind of run-time check in libgcrypt is useful in lower
level API.

I could imagine having an API offering static compile-time check. In
this case, it would provide a macro something like gcry_kem_decap_check
which has length arguments. The ABI is gcry_kem_decap.
--

_______________________________________________
Gcrypt-devel mailing list
Gcrypt-devel@gnupg.org
https://lists.gnupg.org/mailman/listinfo/gcrypt-devel
Re: Adding new public key KEM API [ In reply to ]
Am 24.10.23 um 08:25 schrieb NIIBE Yutaka:
> Werner Koch<wk@gnupg.org> wrote:
>> On Thu, 19 Oct 2023 16:37, NIIBE Yutaka said:
>>
>>> gcry_error_t gcry_kem_decap (int algo,
>>> const void *seckey,
>>> const void *ciphertext,
>>> void *shared_secret);
>> I still don't feel comfortable without a size argument.
> Assumption here (for lower level API) is:
>
> It's caller side (user of libgcrypt) which does static
> compile-time check against ALGO and the length of each
> byte-array.
>
> If not static, caller side can do run-time check, if needed,
> before the call.
But the point is, that what you refer to as static or run-time check is
still error prone. As far as I can see, you did not yet specify what it
is that the caller has to check the length against. But in any case this
is another call to a macro or function which can contain an error, and
thus, as Werner pointed out, incurs the risk of memory access errors.
>
> Having a size argument would mean,
>
> libgcrypt does run-time check of the length (for each call)
>
> I wonder if this kind of run-time check in libgcrypt is useful in lower
> level API.

What exactly do you mean by "lower level" API? If this what we are
currently discussing is a lower level API, then does this mean

- that it is not intended to be used by client applications but just
internally by Libgcrypt? In that case I would refer to it as an internal
API for clarity.
- that there will be another "higher level" API that is intended for
client applications?

Turning the whole question around: what in your point of view speaks
against including length parameters for each input/output byte array (on
whatever level of API)?


- Falko

>
> I could imagine having an API offering static compile-time check. In
> this case, it would provide a macro something like gcry_kem_decap_check
> which has length arguments. The ABI is gcry_kem_decap.
--

*MTG AG*
Dr. Falko Strenzke
Executive System Architect

Phone: +49 6151 8000 24
E-Mail: falko.strenzke@mtg.de
Web: mtg.de <https://www.mtg.de>


------------------------------------------------------------------------

MTG AG - Dolivostr. 11 - 64293 Darmstadt, Germany
Commercial register: HRB 8901
Register Court: Amtsgericht Darmstadt
Management Board: Jürgen Ruf (CEO), Tamer Kemeröz
Chairman of the Supervisory Board: Dr. Thomas Milde

This email may contain confidential and/or privileged information. If
you are not the correct recipient or have received this email in error,
please inform the sender immediately and delete this email. Unauthorised
copying or distribution of this email is not permitted.

Data protection information: Privacy policy
<https://www.mtg.de/en/privacy-policy>
Re: Adding new public key KEM API [ In reply to ]
On Tue, 24 Oct 2023 15:25, NIIBE Yutaka said:

> I wonder if this kind of run-time check in libgcrypt is useful in lower
> level API.

For internal use in libgcrypt we don't need a size argument. For the
piblic API we should have one; we nearly always do this. One exception
which comes to mind is gcry_md_read but this function just returns data
and does not take data.

Of course we could also switch back to s-expressions as used by all
other public key functions. But your gaol is to have an asier to use
API than one where you first need to construct an s-expression and later
parse the result from it (and I agree with you here).


Shalom-Salam,

Werner


--
The pioneers of a warless world are the youth that
refuse military service. - A. Einstein
Re: Adding new public key KEM API [ In reply to ]
There is another point to consider for the design of a generic KEM API:
the use of the public in the key derivation, which makes it necessary to
pass the public key to the decapsulation function if one doesn't want to
run the computation of the public key from the private key in the
decapsulation function.

We are using using this now for instance in our OpenPGP PQC draft
(https://github.com/openpgp-pqc/draft-openpgp-pqc/pull/66 corrects the
ECC-KEM function signature regarding that matter).

- Falko

Am 24.10.23 um 08:25 schrieb NIIBE Yutaka:
> Werner Koch<wk@gnupg.org> wrote:
>> On Thu, 19 Oct 2023 16:37, NIIBE Yutaka said:
>>
>>> gcry_error_t gcry_kem_decap (int algo,
>>> const void *seckey,
>>> const void *ciphertext,
>>> void *shared_secret);
>> I still don't feel comfortable without a size argument.
> Assumption here (for lower level API) is:
>
> It's caller side (user of libgcrypt) which does static
> compile-time check against ALGO and the length of each
> byte-array.
>
> If not static, caller side can do run-time check, if needed,
> before the call.
>
> Having a size argument would mean,
>
> libgcrypt does run-time check of the length (for each call)
>
> I wonder if this kind of run-time check in libgcrypt is useful in lower
> level API.
>
> I could imagine having an API offering static compile-time check. In
> this case, it would provide a macro something like gcry_kem_decap_check
> which has length arguments. The ABI is gcry_kem_decap.
--

*MTG AG*
Dr. Falko Strenzke
Executive System Architect

Phone: +49 6151 8000 24
E-Mail: falko.strenzke@mtg.de
Web: mtg.de <https://www.mtg.de>

<https://www.linkedin.com/search/results/all/?fetchDeterministicClustersOnly=true&heroEntityKey=urn%3Ali%3Aorganization%3A13983133&keywords=mtg%20ag&origin=RICH_QUERY_SUGGESTION&position=0&searchId=d5bc71c3-97f7-4cae-83e7-e9e16d497dc2&sid=3S5&spellCorrectionEnabled=false>
Follow us
------------------------------------------------------------------------
<https://www.mtg.de/de/aktuelles/MTG-AG-erhaelt-Innovationspreis-des-Bundesverbands-IT-Sicherheit-e.V-00001.-TeleTrust/>
<https://www.itsa365.de/de-de/companies/m/mtg-ag>

MTG AG - Dolivostr. 11 - 64293 Darmstadt, Germany
Commercial register: HRB 8901
Register Court: Amtsgericht Darmstadt
Management Board: Jürgen Ruf (CEO), Tamer Kemeröz
Chairman of the Supervisory Board: Dr. Thomas Milde

This email may contain confidential and/or privileged information. If
you are not the correct recipient or have received this email in error,
please inform the sender immediately and delete this email.Unauthorised
copying or distribution of this email is not permitted.

Data protection information: Privacy policy
<https://www.mtg.de/en/privacy-policy>
Re: Adding new public key KEM API [ In reply to ]
Hello,

Falko Strenzke <falko.strenzke@mtg.de> wrote:
> There is another point to consider for the design of a generic KEM API:
> the use of the public in the key derivation, which makes it necessary to
> pass the public key to the decapsulation function if one doesn't want to
> run the computation of the public key from the private key in the
> decapsulation function.

Thank you for the input.

I encounter this exact issue when I did an experiment for DHKEM(X25519,
HKDF-SHA256). Currently, it computes public key from secret key.

My experiment is here:

https://dev.gnupg.org/source/libgcrypt/history/gniibe%252Fkem2/

This is the branch on top of master.

Last month, I created the gniibe/kem branch on top of 1.10 branch. I
need HKDF function for the DHKEM, so, I did again on top of master.
--

_______________________________________________
Gcrypt-devel mailing list
Gcrypt-devel@gnupg.org
https://lists.gnupg.org/mailman/listinfo/gcrypt-devel
Re: Adding new public key KEM API [ In reply to ]
One common solution to that problem is to include the public key in the
data array holding the private key. The SNTRUP761 implementations I've
worked with does that by default, and I thought it was a fairly common
design pattern.

/Simon

Falko Strenzke <falko.strenzke@mtg.de> writes:

> There is another point to consider for the design of a generic KEM API: the use of the public in the
> key derivation, which makes it necessary to pass the public key to the decapsulation function if one
> doesn't want to run the computation of the public key from the private key in the decapsulation
> function.
>
> We are using using this now for instance in our OpenPGP PQC draft
> (https://github.com/openpgp-pqc/draft-openpgp-pqc/pull/66 corrects the ECC-KEM function
> signature regarding that matter).
>
> - Falko
>
> Am 24.10.23 um 08:25 schrieb NIIBE Yutaka:
>
> Werner Koch <wk@gnupg.org> wrote:
>
> On Thu, 19 Oct 2023 16:37, NIIBE Yutaka said:
>
> gcry_error_t gcry_kem_decap (int algo,
> const void *seckey,
> const void *ciphertext,
> void *shared_secret);
>
>
> I still don't feel comfortable without a size argument.
>
>
> Assumption here (for lower level API) is:
>
> It's caller side (user of libgcrypt) which does static
> compile-time check against ALGO and the length of each
> byte-array.
>
> If not static, caller side can do run-time check, if needed,
> before the call.
>
> Having a size argument would mean,
>
> libgcrypt does run-time check of the length (for each call)
>
> I wonder if this kind of run-time check in libgcrypt is useful in lower
> level API.
>
> I could imagine having an API offering static compile-time check. In
> this case, it would provide a macro something like gcry_kem_decap_check
> which has length arguments. The ABI is gcry_kem_decap.
Re: Adding new public key KEM API [ In reply to ]
On Mon 2023-11-20 09:28:49 +0100, Simon Josefsson via Gcrypt-devel wrote:
> One common solution to that problem is to include the public key in the
> data array holding the private key. The SNTRUP761 implementations I've
> worked with does that by default, and I thought it was a fairly common
> design pattern.

This doesn't seem like an unreasonable approach, but it also requires a
well-documented serialization (and deserialization) convention for the
public key material when aggregated with the private key. That might be
as simple as mere concatenation of already well-defined, fixed-length
byte arrays for public and private key material. but it's not
necessarily the case, depending on the KEM.

That said, an abstract KEM API that only works for KEMs that do have
such well-defined serialization and aggregation conventions sounds like
it hits a sweet spot to me:

- The API surface is minimal

- Most callers don't want to have to fiddle with thinking about sizes
or relative strengths of parameterized algorithm choices anyway, and
would prefer to treat the components as bytestrings in the first
place.

- And it aggressively selects for/prefers well-defined KEM abstractions
in the first place.

A simple, narrow API that makes it convenient to use reasonable
algorithms is a net win, even (especially?) if it discourages users of
the library from trying to adopt other more complex algorithms that
require something more ungainly or idiosyncratic.

--dkg
Re: Adding new public key KEM API [ In reply to ]
Hello,

NIIBE Yutaka <gniibe@fsij.org> wrote:
> I encounter this exact issue when I did an experiment for DHKEM(X25519,
> HKDF-SHA256). Currently, it computes public key from secret key.
>
> My experiment is here:
>
> https://dev.gnupg.org/source/libgcrypt/history/gniibe%252Fkem2/
>
> This is the branch on top of master.

For next experiment, I added GCRY_KEM_OPENPGP_X25519. My target use
case in mind is using this KEM for OpenPGP.

For this use case, I need to supply KDF parameter to the API, so, I
added optional argument for the API for this experiment.

gcry_error_t gcry_kem_keypair (int algo,
void *pubkey,
void *seckey);

gcry_error_t gcry_kem_encap (int algo,
const void *pubkey,
void *ciphertext,
void *shared_secret, const void *optional);

gcry_error_t gcry_kem_decap (int algo,
const void *seckey,
const void *ciphertext,
void *shared_secret, const void *optional);

In the tests/t-kem.c of my branch of experiment, it is used like:

const uint8_t kdf_param[N_TESTS_OPENPGP][56] = {
{
/* Curve OID of Curve25519 in OpenPGP v4. */
0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55,
0x01, 0x05, 0x01,
/**/
0x12, /* ECDH algo in OpenPGP */
/**/
0x03, 0x01, 0x08 /*SHA256*/, 0x07 /*AES128*/,
/**/
0x41, 0x6e, 0x6f, 0x6e, 0x79, 0x6d, 0x6f, 0x75,
0x73, 0x20, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72,
0x20, 0x20, 0x20, 0x20, /* "Anonymous Sender " */
/**/
0x25, 0xd4, 0x45, 0xfa, 0xc1, 0x96, 0x49, 0xc4,
0x6a, 0x6b, 0x2f, 0xb3, 0xcd, 0xfc, 0x22, 0x19,
0xc5, 0x53, 0xd3, 0x92 /* public key fingerprint */
}
[...]
err = gcry_kem_decap (GCRY_KEM_OPENPGP_X25519, seckey[testno],
ciphertext[testno], kek2, kdf_param[testno]);


I investigated how this API can be used in GnuPG. I realized that in
the current GnuPG implementation, gcry_kem_decap with
GCRY_KEM_OPENPGP_X25519 cannot be used directly; We need to change the
demarcation between gpg and gpg-agent, beforehand.

In the current GnuPG implementation:

gpg-agent does: ECDH
gpg does: KDF, key unwrap, and symmetric decryption

If gcry_kem_decap with GCRY_KEM_OPENPGP_X25519 is used, it will be:

gpg-agent does: KEM decapsulation (ECDH and KDF)
gpg does: key unwrap and symmetric decryption

This means that, gpg-agent will need to know (a part of) OpenPGP public
key, to do gcry_kem_decap operation. Possibly, we need to enhance
gpg-agent protocol so that PKDECRYPT command can optionally inquire (a
part of) OpenPGP public key to gpg frontend.
--

_______________________________________________
Gcrypt-devel mailing list
Gcrypt-devel@gnupg.org
https://lists.gnupg.org/mailman/listinfo/gcrypt-devel