Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
Loading items

Target

Select target project
  • briansmith/nettle
  • justus/nettle
  • nettle/nettle
  • michaelweiser/nettle
  • aberaud/nettle
  • npocs/nettle
  • ajlawrence/nettle
  • mhoffmann/nettle
  • lumag/nettle
  • mamonet/nettle
  • devnexen/nettle
  • babelouest/nettle
  • ueno/nettle
  • rth/nettle
  • wiml/nettle
15 results
Select Git revision
Loading items
Show changes
Commits on Source (2)
...@@ -223,7 +223,10 @@ hogweed_SOURCES = sexp.c sexp-format.c \ ...@@ -223,7 +223,10 @@ hogweed_SOURCES = sexp.c sexp-format.c \
ed25519-sha512.c ed25519-sha512-pubkey.c \ ed25519-sha512.c ed25519-sha512-pubkey.c \
ed25519-sha512-sign.c ed25519-sha512-verify.c \ ed25519-sha512-sign.c ed25519-sha512-verify.c \
ed448-shake256.c ed448-shake256-pubkey.c \ ed448-shake256.c ed448-shake256-pubkey.c \
ed448-shake256-sign.c ed448-shake256-verify.c ed448-shake256-sign.c ed448-shake256-verify.c \
hpke-dhkem.c hpke-hkdf.c hpke-hkdf-hpke.c hpke-hkdf-kem.c \
hpke.c hpke-types.c hpke-dhkem-p256.c \
hpke-hkdf-sha256.c hpke-aead-aes128.c hpke-aead-export.c
OPT_SOURCES = fat-arm.c fat-arm64.c fat-ppc.c fat-s390x.c fat-x86_64.c mini-gmp.c OPT_SOURCES = fat-arm.c fat-arm64.c fat-ppc.c fat-s390x.c fat-x86_64.c mini-gmp.c
...@@ -235,6 +238,7 @@ HEADERS = aes.h arcfour.h arctwo.h asn1.h blowfish.h balloon.h \ ...@@ -235,6 +238,7 @@ HEADERS = aes.h arcfour.h arctwo.h asn1.h blowfish.h balloon.h \
gcm.h gostdsa.h gosthash94.h hmac.h \ gcm.h gostdsa.h gosthash94.h hmac.h \
knuth-lfib.h hkdf.h \ knuth-lfib.h hkdf.h \
macros.h \ macros.h \
hpke.h \
cmac.h siv-cmac.h siv-gcm.h \ cmac.h siv-cmac.h siv-gcm.h \
md2.h md4.h \ md2.h md4.h \
md5.h md5-compat.h \ md5.h md5-compat.h \
...@@ -276,7 +280,7 @@ DISTFILES = $(SOURCES) $(HEADERS) getopt.h getopt_int.h \ ...@@ -276,7 +280,7 @@ DISTFILES = $(SOURCES) $(HEADERS) getopt.h getopt_int.h \
ctr-internal.h chacha-internal.h sha3-internal.h \ ctr-internal.h chacha-internal.h sha3-internal.h \
salsa20-internal.h umac-internal.h hogweed-internal.h \ salsa20-internal.h umac-internal.h hogweed-internal.h \
rsa-internal.h pkcs1-internal.h dsa-internal.h eddsa-internal.h \ rsa-internal.h pkcs1-internal.h dsa-internal.h eddsa-internal.h \
gmp-glue.h ecc-internal.h fat-setup.h \ gmp-glue.h ecc-internal.h fat-setup.h hpke-internal.h \
mini-gmp.h asm.m4 m4-utils.m4 \ mini-gmp.h asm.m4 m4-utils.m4 \
nettle.texinfo nettle.info nettle.html nettle.pdf sha-example.c nettle.texinfo nettle.info nettle.html nettle.pdf sha-example.c
......
/* hpke-aead-aes128.c
Copyright (C) 2022 Red Hat, Inc.
Author: Norbert Pócs
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include "hpke-internal.h"
const struct hpke_aead nettle_hpke_aead_aes128 =
{
HPKE_AEAD_AES_128_GCM,
16,
&nettle_gcm_aes128,
};
/* hpke-aead-export.c
Copyright (C) 2022 Red Hat, Inc.
Author: Norbert Pócs
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include "hpke-internal.h"
const struct hpke_aead nettle_hpke_aead_export =
{
HPKE_AEAD_EXPORT_ONLY,
0, NULL,
};
/* hpke-dhkem-p256.c
Copyright (C) 2022 Red Hat, Inc.
Author: Norbert Pócs
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include "hpke-internal.h"
#include "ecc-internal.h"
#include "ecc.h"
const struct hpke_dhkem nettle_hpke_dhkem_p256 =
{
HPKE_DHKEM_P256,
32, 32, 0xff,
&_nettle_secp_256r1,
&nettle_hmac_sha256,
_nettle_hpke_encap_prime,
_nettle_hpke_decap_prime,
NULL, NULL,
};
/* hpke-dhkem->h
DHKEM Encapsulation and Decapsulation.
Copyright (C) 2022 Red Hat, Inc.
Author: Norbert Pócs
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <string.h>
#include <stdlib.h>
#include "hpke.h"
#include "ecc.h"
#include "ecc-curve.h"
#include "gmp-glue.h"
#include "nettle-internal.h"
#include "curve25519.h"
#include "curve448.h"
int
_nettle_hpke_encap_prime (const struct hpke_dhkem *dhkem,
uint8_t *pkr, size_t pkr_len,
uint8_t **dh_ser, size_t *dh_ser_len,
uint8_t **enc, size_t *enc_len,
uint8_t *entropy)
{
struct ecc_point p, dh, pR;
struct ecc_scalar key;
mpz_t x;
int r = 1;
ecc_point_init (&pR, dhkem->ecc);
_nettle_octet_to_ecc_point (&pR, pkr, pkr_len);
ecc_point_init (&p, dhkem->ecc);
ecc_scalar_init (&key, dhkem->ecc);
r = _nettle_derive_key_pair_p (entropy, dhkem->nsk, dhkem, &key, &p);
if (!r)
return 0;
ecc_point_init (&dh, dhkem->ecc);
ecc_point_mul (&dh, &key, &pR);
mpz_init (x);
ecc_point_get (&dh, x, NULL);
*dh_ser_len = (ecc_bit_size(dhkem->ecc) + 7) / 8;
*dh_ser = malloc (*dh_ser_len);
if (!dh_ser)
{
r = 0;
goto out;
}
nettle_mpz_get_str_256 (*dh_ser_len, *dh_ser, x);
_nettle_ecc_point_to_octet (enc, enc_len, &p, dhkem);
out:
mpz_clear (x);
ecc_point_clear (&p);
ecc_point_clear (&pR);
ecc_point_clear (&dh);
ecc_scalar_clear (&key);
return r;
}
int
_nettle_hpke_decap_prime (const struct hpke_dhkem *dhkem,
uint8_t *enc, size_t enc_len,
uint8_t *skr, size_t skr_len,
uint8_t **dh_ser, size_t *dh_ser_len)
{
struct ecc_point pkE, dh;
struct ecc_scalar skR;
mpz_t x, z;
ecc_point_init (&pkE, dhkem->ecc);
ecc_point_init (&dh, dhkem->ecc);
ecc_scalar_init (&skR, dhkem->ecc);
int r = 1;
mpz_init (z);
nettle_mpz_set_str_256_u (z, skr_len, skr);
ecc_scalar_set (&skR, z);
mpz_clear (z);
r = _nettle_octet_to_ecc_point (&pkE, enc, enc_len);
if (!r)
goto out;
ecc_point_mul (&dh, &skR, &pkE);
mpz_init (x);
ecc_point_get (&dh, x, NULL);
*dh_ser_len = (ecc_bit_size(dhkem->ecc) + 7) / 8;
*dh_ser = malloc (*dh_ser_len);
if (!dh_ser)
{
r = 0;
goto out;
}
nettle_mpz_get_str_256 (*dh_ser_len, *dh_ser, x);
out:
mpz_clear (x);
ecc_point_clear (&pkE);
ecc_point_clear (&dh);
ecc_scalar_clear (&skR);
return r;
}
/* pkR is an octet string representing the
* point on the ec */
int
nettle_hpke_encap (uint8_t *pkr, size_t pkr_len,
uint8_t **enc, size_t *enc_len,
uint8_t **shared_secret,
const struct hpke_dhkem *dhkem,
void *random_ctx, nettle_random_func *random)
{
uint8_t *dh_ser;
size_t dh_ser_len;
uint8_t entropy[HPKE_NSK_MAX];
int r;
random (random_ctx, HPKE_NSK_MAX, entropy);
r = dhkem->encap (dhkem, pkr, pkr_len, &dh_ser, &dh_ser_len,
enc, enc_len, (uint8_t*)entropy);
if (!r)
return 0;
TMP_DECL (kem_context, uint8_t, *enc_len + pkr_len);
TMP_ALLOC (kem_context, *enc_len + pkr_len);
memcpy (kem_context, *enc, *enc_len);
memcpy (kem_context + *enc_len, pkr, pkr_len);
*shared_secret = _nettle_extract_and_expand_kem (dh_ser,
dh_ser_len,
kem_context,
*enc_len+pkr_len,
dhkem);
free (dh_ser);
if (!shared_secret)
return 0;
return 1;
}
int
nettle_hpke_decap (uint8_t *enc, size_t enc_len, uint8_t *pkr, size_t pkr_len,
uint8_t *skr, size_t skr_len, const struct hpke_dhkem *dhkem,
uint8_t **shared_secret)
{
uint8_t *dh_ser;
size_t dh_ser_len;
int r;
r = dhkem->decap (dhkem, enc, enc_len, skr, skr_len, &dh_ser, &dh_ser_len);
if (!r)
return 0;
TMP_DECL (kem_context, uint8_t, enc_len + pkr_len);
TMP_ALLOC (kem_context, enc_len + pkr_len);
memcpy (kem_context, enc, enc_len);
memcpy (kem_context + enc_len, pkr, pkr_len);
*shared_secret = _nettle_extract_and_expand_kem (dh_ser,
dh_ser_len,
kem_context,
enc_len+pkr_len,
dhkem);
free (dh_ser);
if (!*shared_secret)
return 0;
return 1;
}
/* hpke-hkdf-hpke.h
HKDF used anywhere else than the KEM part.
Copyright (C) 2022 Red Hat, Inc.
Author: Norbert Pócs
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <string.h>
#include <stdlib.h>
#include "hpke-internal.h"
#include "hpke.h"
#include "gmp-glue.h"
#include "hkdf.h"
#include "nettle-internal.h"
#include "hmac.h"
uint8_t *
_nettle_labeled_extract_hpke (uint8_t *salt, size_t salt_len, char *label,
uint8_t *ikm, size_t ikm_len,
const struct hpke_dhkem *dhkem,
const struct hpke_hkdf *hkdf,
const struct hpke_aead *aead)
{
uint8_t *dst;
mpz_t id_conv;
size_t labeled_ikm_offset = HPKE_RFC_NUM_LEN;
const size_t label_len = strlen(label);
const size_t labeled_ikm_len = HPKE_RFC_NUM_LEN + 10
+ label_len + ikm_len;
const struct nettle_mac *hmac_s = hkdf->hmac;
TMP_DECL (labeled_ikm, uint8_t, labeled_ikm_len);
TMP_ALLOC (labeled_ikm, labeled_ikm_len);
memcpy (labeled_ikm, HPKE_RFC_NUM, HPKE_RFC_NUM_LEN);
uint8_t id[2];
mpz_init_set_ui (id_conv, dhkem->dhkem);
nettle_mpz_get_str_256 (2, id, id_conv);
mpz_clear (id_conv);
memcpy (labeled_ikm + labeled_ikm_offset, "HPKE", 4);
labeled_ikm_offset += 4;
memcpy (labeled_ikm + labeled_ikm_offset, id, 2);
labeled_ikm_offset += 2;
mpz_init_set_ui (id_conv, hkdf->hkdf);
nettle_mpz_get_str_256 (2, id, id_conv);
mpz_clear (id_conv);
memcpy (labeled_ikm + labeled_ikm_offset, id, 2);
labeled_ikm_offset += 2;
mpz_init_set_ui (id_conv, aead->aead);
nettle_mpz_get_str_256 (2, id, id_conv);
mpz_clear (id_conv);
memcpy (labeled_ikm + labeled_ikm_offset, id, 2);
labeled_ikm_offset += 2;
memcpy (labeled_ikm + labeled_ikm_offset, label, label_len);
labeled_ikm_offset += label_len;
memcpy (labeled_ikm + labeled_ikm_offset, ikm, ikm_len);
TMP_DECL_ALIGN (ctx, hmac_s->context_size);
TMP_ALLOC_ALIGN (ctx, hmac_s->context_size);
if (hkdf->hkdf == HPKE_HKDF_SHA256)
hmac_sha256_set_key (ctx, salt_len, salt);
else
hmac_sha512_set_key (ctx, salt_len, salt);
dst = gmp_alloc (hmac_s->digest_size);
if (!dst)
return NULL;
hkdf_extract (ctx,
hmac_s->update,
hmac_s->digest,
hmac_s->digest_size,
labeled_ikm_len,
labeled_ikm,
dst);
return dst;
}
uint8_t *
_nettle_labeled_expand_hpke (uint8_t *prk, char *label,
uint8_t *info, size_t info_len, uint16_t l,
const struct hpke_dhkem *dhkem,
const struct hpke_hkdf *hkdf,
const struct hpke_aead *aead)
{
uint8_t id[2];
uint8_t *dst;
mpz_t id_conv;
size_t labeled_info_offset = 2;
const size_t label_len = strlen(label);
const size_t labeled_info_len = 2 + HPKE_RFC_NUM_LEN + 10
+ label_len + info_len;
const struct nettle_mac *hmac_s = hkdf->hmac;
TMP_DECL (labeled_info, uint8_t, labeled_info_len);
TMP_ALLOC (labeled_info, labeled_info_len);
dst = gmp_alloc (l);
if (!dst)
return NULL;
mpz_init_set_ui (id_conv, l);
nettle_mpz_get_str_256 (2, id, id_conv);
mpz_clear (id_conv);
memcpy (labeled_info, id, 2);
memcpy (labeled_info + labeled_info_offset, HPKE_RFC_NUM, HPKE_RFC_NUM_LEN);
labeled_info_offset += HPKE_RFC_NUM_LEN;
mpz_init_set_ui (id_conv, dhkem->dhkem);
nettle_mpz_get_str_256 (2, id, id_conv);
mpz_clear (id_conv);
memcpy (labeled_info + labeled_info_offset, "HPKE", 4);
labeled_info_offset += 4;
memcpy (labeled_info + labeled_info_offset, id, 2);
labeled_info_offset += 2;
mpz_init_set_ui (id_conv, hkdf->hkdf);
nettle_mpz_get_str_256 (2, id, id_conv);
mpz_clear (id_conv);
memcpy (labeled_info + labeled_info_offset, id, 2);
labeled_info_offset += 2;
mpz_init_set_ui (id_conv, aead->aead);
nettle_mpz_get_str_256 (2, id, id_conv);
mpz_clear (id_conv);
memcpy (labeled_info + labeled_info_offset, id, 2);
labeled_info_offset += 2;
memcpy (labeled_info + labeled_info_offset, label, label_len);
labeled_info_offset += label_len;
memcpy (labeled_info + labeled_info_offset, info, info_len);
TMP_DECL_ALIGN (ctx, hmac_s->context_size);
TMP_ALLOC_ALIGN (ctx, hmac_s->context_size);
hmac_s->set_key (ctx, prk);
hkdf_expand (ctx,
hmac_s->update,
hmac_s->digest,
hmac_s->digest_size,
labeled_info_len,
labeled_info,
l,
dst);
return dst;
}
/* hpke-hkdf-kem.h
HKDF used in KEM part of HPKE.
Copyright (C) 2022 Red Hat, Inc.
Author: Norbert Pócs
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <string.h>
#include <stdlib.h>
#include "hpke-internal.h"
#include "hpke.h"
#include "gmp-glue.h"
#include "hkdf.h"
#include "nettle-internal.h"
#include "hmac.h"
uint8_t *
_nettle_labeled_extract_kem (uint8_t *salt, size_t salt_len, char *label,
uint8_t *ikm, size_t ikm_len,
const struct hpke_dhkem *dhkem)
{
uint8_t id[2];
uint8_t *dst;
mpz_t id_conv;
size_t labeled_ikm_offset = HPKE_RFC_NUM_LEN;
const size_t label_len = strlen(label);
const size_t labeled_ikm_len = HPKE_RFC_NUM_LEN + 5
+ label_len + ikm_len;
const struct nettle_mac *hmac_s = dhkem->hmac;
TMP_DECL (labeled_ikm, uint8_t, labeled_ikm_len);
TMP_ALLOC (labeled_ikm, labeled_ikm_len);
memcpy (labeled_ikm, HPKE_RFC_NUM, HPKE_RFC_NUM_LEN);
mpz_init_set_ui (id_conv, dhkem->dhkem);
nettle_mpz_get_str_256 (2, id, id_conv);
mpz_clear (id_conv);
memcpy (labeled_ikm + labeled_ikm_offset, "KEM", 3);
labeled_ikm_offset += 3;
memcpy (labeled_ikm + labeled_ikm_offset, id, 2);
labeled_ikm_offset += 2;
memcpy (labeled_ikm + labeled_ikm_offset, label, label_len);
labeled_ikm_offset += label_len;
memcpy (labeled_ikm + labeled_ikm_offset, ikm, ikm_len);
TMP_DECL_ALIGN (ctx, hmac_s->context_size);
TMP_ALLOC_ALIGN (ctx, hmac_s->context_size);
if (dhkem->dhkem == HPKE_DHKEM_P256)
hmac_sha256_set_key (ctx, salt_len, salt);
else
hmac_sha512_set_key (ctx, salt_len, salt);
dst = gmp_alloc (hmac_s->digest_size);
if (!dst)
return NULL;
hkdf_extract (ctx,
hmac_s->update,
hmac_s->digest,
hmac_s->digest_size,
labeled_ikm_len,
labeled_ikm,
dst);
return dst;
}
uint8_t *
_nettle_labeled_expand_kem (uint8_t *prk, char *label,
uint8_t *info, size_t info_len, uint16_t l,
const struct hpke_dhkem *dhkem)
{
uint8_t id[2];
uint8_t *dst;
mpz_t id_conv;
size_t labeled_info_offset = 2;
const size_t label_len = strlen(label);
const size_t labeled_info_len = 2 + HPKE_RFC_NUM_LEN + 5
+ label_len + info_len;
const struct nettle_mac *hmac_s = dhkem->hmac;
TMP_DECL (labeled_info, uint8_t, labeled_info_len);
TMP_ALLOC (labeled_info, labeled_info_len);
dst = gmp_alloc (l);
if (!dst)
return NULL;
mpz_init_set_ui (id_conv, l);
nettle_mpz_get_str_256 (2, id, id_conv);
mpz_clear (id_conv);
memcpy (labeled_info, id, 2);
memcpy (labeled_info + labeled_info_offset, HPKE_RFC_NUM, HPKE_RFC_NUM_LEN);
labeled_info_offset += HPKE_RFC_NUM_LEN;
mpz_init_set_ui (id_conv, dhkem->dhkem);
nettle_mpz_get_str_256 (2, id, id_conv);
mpz_clear (id_conv);
memcpy (labeled_info + labeled_info_offset, "KEM", 3);
labeled_info_offset += 3;
memcpy (labeled_info + labeled_info_offset, id, 2);
labeled_info_offset += 2;
memcpy (labeled_info + labeled_info_offset, label, label_len);
labeled_info_offset += label_len;
memcpy (labeled_info + labeled_info_offset, info, info_len);
TMP_DECL_ALIGN (ctx, hmac_s->context_size);
TMP_ALLOC_ALIGN (ctx, hmac_s->context_size);
if (prk != NULL)
hmac_s->set_key (ctx, prk);
hkdf_expand (ctx,
hmac_s->update,
hmac_s->digest,
hmac_s->digest_size,
labeled_info_len,
labeled_info,
l,
dst);
return dst;
}
uint8_t *
_nettle_extract_and_expand_kem (uint8_t *dh, size_t dh_len,
uint8_t *kem_context, size_t kem_context_len,
const struct hpke_dhkem *dhkem)
{
uint8_t *eae_prk;
uint8_t *ret;
eae_prk = _nettle_labeled_extract_kem (NULL, 0, "eae_prk",
dh, dh_len, dhkem);
ret = _nettle_labeled_expand_kem (eae_prk, "shared_secret", kem_context,
kem_context_len, dhkem->Nsecret,
dhkem);
free (eae_prk);
return ret;
}
/* hpke-hkdf-sha256.c
Copyright (C) 2022 Red Hat, Inc.
Author: Norbert Pócs
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include "hpke-internal.h"
const struct hpke_hkdf nettle_hpke_hkdf_sha256 =
{
HPKE_HKDF_SHA256,
32,
&nettle_hmac_sha256,
};
/* hpke-hkdf.h
HKDF for P and X curves.
Copyright (C) 2022 Red Hat, Inc.
Author: Norbert Pócs
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include "hpke-internal.h"
#include "hpke.h"
#include "gmp-glue.h"
int
_nettle_derive_key_pair_p (uint8_t *ikm, size_t ikm_len,
const struct hpke_dhkem *dhkem,
struct ecc_scalar *sk, struct ecc_point *pk)
{
int r = 1, counter = 0;
uint8_t *dkp_prk = NULL, *bytes = NULL;
mpz_t z, t;
mpz_init (z);
dkp_prk = _nettle_labeled_extract_kem (NULL, 0, "dkp_prk", ikm, ikm_len,
dhkem);
if (!dkp_prk)
{
r = 0;
goto out;
}
while (mpz_cmp_ui (z, 0) == 0 ||
mpz_cmp (z, mpz_roinit_n(t,
dhkem->ecc->q.m,
dhkem->ecc->p.size)) != -1)
{
if (counter > 255)
{
r = 0;
goto out;
}
uint8_t counter_oct[1];
nettle_mpz_get_str_256 (1, counter_oct, z);
bytes = _nettle_labeled_expand_kem (dkp_prk,
"candidate",
counter_oct,
1,
dhkem->nsk,
dhkem);
if (!bytes)
{
r = 0;
goto out;
}
bytes[0] &= dhkem->byte_mask;
/*
* keeping this here as a note when other algos
* will be added
if (dhkem->dhkem == HPKE_DHKEM_P256)
bytes[0] &= 0xff;
else
bytes[0] &= 0x01;
*/
nettle_mpz_set_str_256_u (z, dhkem->nsk, bytes);
counter++;
free (bytes);
}
ecc_scalar_set (sk, z);
ecc_point_mul_g (pk, sk);
out:
free (dkp_prk);
mpz_clear (z);
return r;
}
/* hpke-internal.h
HPKE private functions.
Copyright (C) 2022 Red Hat, Inc.
Author: Norbert Pócs
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#ifndef __HPKE_INTERNAL__
#define __HPKE_INTERNAL__
#include <stdint.h>
#include "ecc.h"
#include "nettle-meta.h"
#include "ecc-internal.h"
#ifdef __cplusplus
extern "C" {
#endif
#define HPKE_RFC_NUM "HPKE-v1"
#define HPKE_RFC_NUM_LEN 7
#define HPKE_AEAD_NN 12
#define HPKE_NSK_MAX 66
struct hpke_dhkem;
typedef int nettle_hpke_encap_helper (const struct hpke_dhkem *dhkem,
uint8_t *pkr, size_t pkr_len,
uint8_t **dh_ser, size_t *dh_ser_len,
uint8_t **enc, size_t *enc_len,
uint8_t *entropy);
typedef int nettle_hpke_decap_helper (const struct hpke_dhkem *dhkem,
uint8_t *enc, size_t enc_len,
uint8_t *skr, size_t skr_len,
uint8_t **dh_ser, size_t *dh_ser_len);
enum hpke_mode_e {
HPKE_MODE_BASE=0,
HPKE_MODE_PSK=1,
HPKE_MODE_AUTH,
HPKE_MODE_AUTH_PSK,
};
enum hpke_hkdf_e {
HPKE_HKDF_SHA256=1,
HPKE_HKDF_SHA384,
HPKE_HKDF_SHA512,
};
enum hpke_aead_e {
HPKE_AEAD_AES_128_GCM=1,
HPKE_AEAD_AES_256_GCM,
HPKE_AEAD_CHACHA20POLY1305,
HPKE_AEAD_EXPORT_ONLY=0xffff,
};
enum hpke_dhkem_e {
HPKE_DHKEM_P256=0x0010,
HPKE_DHKEM_P384=0x0011,
HPKE_DHKEM_P521=0x0012,
HPKE_DHKEM_X25519=0x0020,
HPKE_DHKEM_X448=0x0021,
};
struct hpke_dhkem
{
enum hpke_dhkem_e dhkem;
uint8_t Nsecret;
uint8_t nsk;
uint8_t byte_mask;
const struct ecc_curve *ecc;
const struct nettle_mac *hmac;
nettle_hpke_encap_helper *encap;
nettle_hpke_decap_helper *decap;
void (*mul)(uint8_t *q, const uint8_t *n, const uint8_t *p);
void (*mul_g)(uint8_t *q, const uint8_t *n);
};
struct hpke_hkdf
{
enum hpke_hkdf_e hkdf;
uint8_t nh;
const struct nettle_mac *hmac;
};
struct hpke_aead
{
enum hpke_aead_e aead;
uint8_t nk;
const struct nettle_aead *alg;
};
int
_nettle_ecc_point_to_octet (uint8_t **s, size_t *s_len, struct ecc_point *p,
const struct hpke_dhkem *dhkem);
int
_nettle_octet_to_ecc_point (struct ecc_point *p, uint8_t *s, size_t s_len);
/* the sizes of the outputs of extract and expand functions are
* dependent on the digest size */
uint8_t *
_nettle_labeled_extract_kem (uint8_t *salt, size_t salt_len, char *label,
uint8_t *ikm, size_t ikm_len,
const struct hpke_dhkem *dhkem);
uint8_t *
_nettle_labeled_expand_kem (uint8_t *prk, char *label,
uint8_t *info, size_t info_len, uint16_t l,
const struct hpke_dhkem *dhkem);
uint8_t *
_nettle_extract_and_expand_kem (uint8_t *dh, size_t dh_len,
uint8_t *kem_context, size_t kem_context_len,
const struct hpke_dhkem *dhkem);
uint8_t *
_nettle_labeled_extract_hpke (uint8_t *salt, size_t salt_len, char *label,
uint8_t *ikm, size_t ikm_len,
const struct hpke_dhkem *dhkem,
const struct hpke_hkdf *hkdf,
const struct hpke_aead *aead);
uint8_t *
_nettle_labeled_expand_hpke (uint8_t *prk, char *label,
uint8_t *info, size_t info_len, uint16_t l,
const struct hpke_dhkem *dhkem,
const struct hpke_hkdf *hkdf,
const struct hpke_aead *aead);
int
_nettle_derive_key_pair_p (uint8_t *ikm, size_t ikm_len,
const struct hpke_dhkem *dhkem,
struct ecc_scalar *sk, struct ecc_point *pk);
nettle_hpke_encap_helper _nettle_hpke_encap_prime;
nettle_hpke_decap_helper _nettle_hpke_decap_prime;
#ifdef __cplusplus
}
#endif
#endif /* __HPKE_INTERNAL__ */
/* hpke-types.h
Helper and context functions.
Copyright (C) 2022 Red Hat, Inc.
Author: Norbert Pócs
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include "hpke-internal.h"
#include "hpke.h"
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "gmp-glue.h"
#include "hmac.h"
#include "ecc.h"
#include "ecc-internal.h"
#include "ecc-curve.h"
#include "curve25519.h"
#include "curve448.h"
int
_nettle_ecc_point_to_octet (uint8_t **s, size_t *s_len, struct ecc_point *p,
const struct hpke_dhkem *dhkem)
{
if (!*p->p)
{
*s = gmp_alloc (1);
**s = 0x00;
return 1;
}
size_t bit_size = (ecc_bit_size(dhkem->ecc) + 7) / 8;
mpz_t x,y;
mpz_init (x);
mpz_init (y);
ecc_point_get (p, x, y);
*s_len = 2*bit_size+1;
*s = gmp_alloc (*s_len);
if (!*s)
return 0;
**s = 0x04;
nettle_mpz_get_str_256 (bit_size, (*s)+1, x);
nettle_mpz_get_str_256 (bit_size, (*s)+1+bit_size, y);
mpz_clear (x);
mpz_clear (y);
return 1;
}
int
_nettle_octet_to_ecc_point (struct ecc_point *p, uint8_t *s, size_t s_len)
{
mpz_t x, y;
int r = 1;
mpz_init (x);
mpz_init (y);
if (!s[0])
r = ecc_point_set (p, x, y);
else if (s[0] == 0x04)
{
unsigned bit_size = ((s_len-1)/2);
nettle_mpz_set_str_256_u (x, bit_size, s+1);
nettle_mpz_set_str_256_u (y, bit_size, s+1+bit_size);
r = ecc_point_set (p, x, y);
}
mpz_clear (x);
mpz_clear (y);
return r;
}
/* hpke.h
Main HPKE workflow.
Copyright (C) 2022 Red Hat, Inc.
Author: Norbert Pócs
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include "hpke.h"
#include "gmp-glue.h"
#include "nettle-internal.h"
#include "memxor.h"
#include "gcm.h"
#include "chacha-poly1305.h"
#include "sha2.h"
// FIXME remove later
#define HPKE_SKIP_NON_BASIC
int
hpke_key_schedule (uint8_t *psk, size_t psk_len,
uint8_t *psk_id, size_t psk_id_len,
uint8_t *info, size_t info_len,
uint8_t *shared_secret,
const struct hpke_dhkem *dhkem,
const struct hpke_hkdf *hkdf,
const struct hpke_aead *aead,
enum hpke_mode_e mode,
uint8_t **key,
uint8_t **base_nonce,
uint8_t **exporter_secret)
{
uint8_t *psk_id_hash = NULL, *info_hash = NULL, *secret = NULL;
int r;
psk_id_hash = _nettle_labeled_extract_hpke (NULL,
0,
"psk_id_hash",
psk_id,
psk_id_len,
dhkem,
hkdf,
aead);
if (!psk_id_hash)
return 0;
info_hash = _nettle_labeled_extract_hpke (NULL,
0,
"info_hash",
info,
info_len,
dhkem,
hkdf,
aead);
if (!info_hash)
return 0;
const size_t key_schedule_cnt_len = 2*(hkdf->hmac->digest_size)+1;
TMP_DECL (key_schedule_cnt, uint8_t, key_schedule_cnt_len);
TMP_ALLOC (key_schedule_cnt, key_schedule_cnt_len);
*key_schedule_cnt = mode;
memcpy (key_schedule_cnt+1, psk_id_hash, hkdf->hmac->digest_size);
memcpy (key_schedule_cnt+1+hkdf->hmac->digest_size, info_hash,
hkdf->hmac->digest_size);
secret = _nettle_labeled_extract_hpke (shared_secret,
hkdf->nh,
"secret",
psk,
psk_len,
dhkem,
hkdf,
aead);
if (!secret)
return 0;
if (aead->aead != HPKE_AEAD_EXPORT_ONLY)
{
*key = _nettle_labeled_expand_hpke (secret,
"key",
key_schedule_cnt,
key_schedule_cnt_len,
aead->nk,
dhkem,
hkdf,
aead);
if (!key)
return 0;
*base_nonce = _nettle_labeled_expand_hpke (secret,
"base_nonce",
key_schedule_cnt,
key_schedule_cnt_len,
HPKE_AEAD_NN,
dhkem,
hkdf,
aead);
if (!base_nonce)
{
free (key);
key = NULL;
return 0;
}
}
*exporter_secret = _nettle_labeled_expand_hpke (secret,
"exp",
key_schedule_cnt,
key_schedule_cnt_len,
hkdf->nh,
dhkem,
hkdf,
aead);
if (!exporter_secret)
{
free (key);
free (base_nonce);
key = NULL;
base_nonce = NULL;
return 0;
}
free (psk_id_hash);
free (info_hash);
return r;
}
#ifndef HPKE_SKIP_NON_BASIC
// TODO maybe these setup functions can be emitted and shown as example
int
hpke_setup_base_s (uint8_t *pkr, size_t pkr_len, uint8_t **enc,
size_t *enc_len, uint8_t *info,
size_t info_len, void *random_ctx,
nettle_random_func *random,
const struct hpke_dhkem *dhkem,
const struct hpke_hkdf *hkdf,
const struct hpke_aead *aead,
uint8_t **key, uint8_t **base_nonce,
uint8_t **exporter_secret)
{
int r;
uint8_t *shared_secret = NULL;
r = nettle_hpke_encap (pkr, pkr_len, enc, enc_len,
&shared_secret, dhkem, random_ctx, random);
if (!r)
return r;
r = hpke_key_schedule (NULL, 0,
NULL, 0,
info, info_len,
shared_secret,
dhkem, hkdf, aead,
HPKE_MODE_BASE,
key, base_nonce, exporter_secret);
free (shared_secret);
return r;
}
int
hpke_setup_base_r (uint8_t *enc, size_t enc_len, uint8_t *pkr, size_t pkr_len,
uint8_t *skr, size_t skr_len, uint8_t *info,
size_t info_len, const struct hpke_dhkem *dhkem,
const struct hpke_hkdf *hkdf, const struct hpke_aead *aead,
uint8_t **key, uint8_t **base_nonce,
uint8_t **exporter_secret)
{
int r;
uint8_t *shared_secret = NULL;
r = nettle_hpke_decap (enc, enc_len, pkr, pkr_len,
skr, skr_len, dhkem, &shared_secret);
if (!r)
return r;
r = hpke_key_schedule (NULL, 0,
NULL, 0,
info, info_len,
shared_secret,
dhkem, hkdf, aead,
HPKE_MODE_BASE,
key, base_nonce, exporter_secret);
free (shared_secret);
return r;
}
#endif /* HPKE_SKIP_NON_BASIC */
int
hpke_seal (uint8_t *aad, size_t aad_len, uint8_t *pt,
size_t pt_len, uint8_t **ct, size_t *ct_len,
const struct hpke_aead *aead, uint8_t *key,
uint8_t *base_nonce, uint64_t *seq_n)
{
if (aead->aead == HPKE_AEAD_EXPORT_ONLY)
return -1;
uint8_t seq_octet[HPKE_AEAD_NN] = {0};
uint8_t nonce[HPKE_AEAD_NN];
mpz_t seq;
const struct nettle_aead *n_aead = aead->alg;
mpz_init_set_ui (seq, *seq_n);
nettle_mpz_get_str_256 (HPKE_AEAD_NN, seq_octet, seq);
mpz_clear (seq);
memxor3 (nonce, base_nonce, seq_octet, HPKE_AEAD_NN);
*ct_len = pt_len + n_aead->digest_size;
*ct = gmp_alloc (*ct_len);
TMP_DECL_ALIGN (c, n_aead->context_size);
TMP_ALLOC_ALIGN (c, n_aead->context_size);
n_aead->set_encrypt_key (c, key);
n_aead->set_nonce (c, nonce);
n_aead->update (c, aad_len, aad);
n_aead->encrypt (c, pt_len, *ct, pt);
n_aead->digest (c, n_aead->digest_size, (*ct)+pt_len);
++*seq_n;
return 1;
}
int
hpke_open (uint8_t *aad, size_t aad_len, uint8_t *ct,
size_t ct_len, uint8_t **pt, size_t *pt_len,
const struct hpke_aead *aead, uint8_t *key,
uint8_t *base_nonce, uint64_t *seq_n)
{
if (aead->aead == HPKE_AEAD_EXPORT_ONLY)
return 0;
int r;
uint8_t seq_octet[HPKE_AEAD_NN] = {0};
uint8_t nonce[HPKE_AEAD_NN];
uint8_t tag[GCM_DIGEST_SIZE];
mpz_t seq;
const struct nettle_aead *n_aead = aead->alg;
mpz_init_set_ui (seq, *seq_n);
nettle_mpz_get_str_256 (HPKE_AEAD_NN, seq_octet, seq);
mpz_clear (seq);
memxor3 (nonce, base_nonce, seq_octet, HPKE_AEAD_NN);
*pt_len = ct_len - n_aead->digest_size;
*pt = gmp_alloc (*pt_len);
TMP_DECL_ALIGN (c, n_aead->context_size);
TMP_ALLOC_ALIGN (c, n_aead->context_size);
n_aead->set_decrypt_key (c, key);
n_aead->set_nonce (c, nonce);
n_aead->update (c, aad_len, aad);
n_aead->decrypt (c, ct_len-n_aead->digest_size, *pt, ct);
n_aead->digest (c, n_aead->digest_size, tag);
memxor (tag, ct+(ct_len - n_aead->digest_size), n_aead->digest_size);
int tag_cmp = 0;
for (int i = 0; i < n_aead->digest_size; i++)
tag_cmp += tag[i];
r = tag_cmp == 0;
++*seq_n;
return !r;
}
uint8_t *
hpke_export_secret (const struct hpke_dhkem *dhkem,
const struct hpke_hkdf *hkdf,
const struct hpke_aead *aead,
uint8_t *exporter_secret, uint8_t *exporter_context,
size_t exporter_context_len, size_t l)
{
if (l > 255 * hkdf->nh)
return NULL;
return _nettle_labeled_expand_hpke (exporter_secret,
"sec",
exporter_context,
exporter_context_len,
l,
dhkem,
hkdf,
aead);
}
/* hpke.h
HPKE public functions.
Copyright (C) 2022 Red Hat, Inc.
Author: Norbert Pócs
This file is part of GNU Nettle.
GNU Nettle is free software: you can redistribute it and/or
modify it under the terms of either:
* the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your
option) any later version.
or
* the GNU General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your
option) any later version.
or both in parallel, as here.
GNU Nettle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received copies of the GNU General Public License and
the GNU Lesser General Public License along with this program. If
not, see http://www.gnu.org/licenses/.
*/
#ifndef __HPKE_HPKE_H__
#define __HPKE_HPKE_H__
#include <stdint.h>
#include "ecc.h"
#include "hpke-internal.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Name mangling */
#define hpke_setup_base_s nettle_hpke_setup_base_s
#define hpke_setup_base_r nettle_hpke_setup_base_r
#define hpke_encap nettle_hpke_encap
#define hpke_decap nettle_hpke_decap
#define hpke_seal nettle_hpke_seal
#define hpke_open nettle_hpke_open
#define hpke_export_secret nettle_hpke_export_secret
#define hpke_key_schedule nettle_hpke_key_schedule
extern const struct hpke_dhkem nettle_hpke_dhkem_p256;
extern const struct hpke_hkdf nettle_hpke_hkdf_sha256;
extern const struct hpke_aead nettle_hpke_aead_aes128;
extern const struct hpke_aead nettle_hpke_aead_export;
enum hpke_mode_e;
int
hpke_encap (uint8_t *pkr, size_t pkr_len,
uint8_t **enc, size_t *enc_len,
uint8_t **shared_secret,
const struct hpke_dhkem *dhkem,
void *random_ctx, nettle_random_func *random);
int
hpke_decap (uint8_t *enc, size_t enc_len, uint8_t *pkr, size_t pkr_len,
uint8_t *skr, size_t skr_len, const struct hpke_dhkem *dhkem,
uint8_t **shared_secret);
/*
* lengths:
* key - aead->nk
* base_nonce - HPKE_AEAD_NN
* exporter_secret - hkdf->nh
*/
int
hpke_key_schedule (uint8_t *psk, size_t psk_len,
uint8_t *psk_id, size_t psk_id_len,
uint8_t *info, size_t info_len,
uint8_t *shared_secret,
const struct hpke_dhkem *dhkem,
const struct hpke_hkdf *hkdf,
const struct hpke_aead *aead,
enum hpke_mode_e mode,
uint8_t **key,
uint8_t **base_nonce,
uint8_t **exporter_secret);
int
hpke_seal (uint8_t *aad, size_t aad_len, uint8_t *pt,
size_t pt_len, uint8_t **ct, size_t *ct_len,
const struct hpke_aead *aead, uint8_t *key,
uint8_t *base_nonce, uint64_t *seq_n);
int
hpke_open (uint8_t *aad, size_t aad_len, uint8_t *ct,
size_t ct_len, uint8_t **pt, size_t *pt_len,
const struct hpke_aead *aead, uint8_t *key,
uint8_t *base_nonce, uint64_t *seq_n);
uint8_t *
hpke_export_secret (const struct hpke_dhkem *dhkem,
const struct hpke_hkdf *hkdf,
const struct hpke_aead *aead,
uint8_t *exporter_secret, uint8_t *exporter_context,
size_t exporter_context_len, size_t l);
#ifdef __cplusplus
}
#endif
#endif /* __HPKE_HPKE_H__ */
...@@ -139,6 +139,7 @@ Public-key algorithms ...@@ -139,6 +139,7 @@ Public-key algorithms
* RSA:: The RSA public key algorithm. * RSA:: The RSA public key algorithm.
* DSA:: The DSA digital signature algorithm. * DSA:: The DSA digital signature algorithm.
* Elliptic curves:: Elliptic curves and ECDSA * Elliptic curves:: Elliptic curves and ECDSA
* HPKE:: Hybrid Public Key Encryption scheme
Elliptic curves Elliptic curves
...@@ -4884,6 +4885,7 @@ key, and to no others''. ...@@ -4884,6 +4885,7 @@ key, and to no others''.
* RSA:: The RSA public key algorithm. * RSA:: The RSA public key algorithm.
* DSA:: The DSA digital signature algorithm. * DSA:: The DSA digital signature algorithm.
* Elliptic curves:: Elliptic curves and ECDSA * Elliptic curves:: Elliptic curves and ECDSA
* HPKE:: Hybrid Public Key Encryption scheme
@end menu @end menu
@node RSA @node RSA
...@@ -5976,6 +5978,87 @@ Verifies a message using the provided public key. Returns 1 if the ...@@ -5976,6 +5978,87 @@ Verifies a message using the provided public key. Returns 1 if the
signature is valid, otherwise 0. signature is valid, otherwise 0.
@end deftypefun @end deftypefun
@node HPKE
@subsection @acronym{HPKE}
Hybrid public key encryption scheme is combining symmetric and
asymmetric algorithms to create encapsulation with the approach: "generate the
symmetric key and its encapsulation with the public key". The scheme is described in RFC9180.
HPKE consists of three building blocks: @acronym{HKDF} for key derivation, DHKEM - a
diffie-hellman key encapsulation method and @acronym{AEAD} for encryption. Each one
supports a list of algorithms, which can be used independently of each other to
create an encryption context, then the context can be used for encrypted one-way communication.
Provides 3 authenticated variants: base mode, authentication using a pre-shared key, an
asymmetric key and using both pre-shared and asymmetric key.
HPKE supports single message and multi message communication too.
@deftp {Context struct} {hpke_ctx}
@end deftp
@deftypefun void hpke_ctx_init (struct hpke_ctx *@var{c}, const struct hpke_dhkem @var{dhkem}, const struct hpke_hkdf @var{hkdf}, const struct hpke_aead @var{aead}, enum hpke_mode_e @var{mode})
Inits the context based upon the provided algorithms by the given algorithms and mode.
@end deftypefun
@deftypefun void hpke_ctx_clear (struct hpke_ctx *@var{c})
Deallocates the context.
@end deftypefun
@deftypefun int hpke_setup_base_s (uint8_t *@var{pkr}, size_t @var{pkr_len}, uint8_t *@var{info}, size_t @var{info_len}, struct hpke_ctx *@var{h_ctx}, void *@var{random_ctx}, nettle_random_func *@var{random})
Creates and sets up the context (@var{h_ctx}) used for encryption and decryption for the Sender. To set up the context,
some data is needed: public key of the Receiver, application-supplied information (optional), random function for key generation.
This function generates internally an ephemeral key pair used only for the setup of the context. This context works in Base mode of hpke.
@end deftypefun
@deftypefun int hpke_setup_base_r (uint8_t *@var{enc}, size_t @var{enc_len}, uint8_t *@var{pkr}, size_t @var{pkr_len}, uint8_t *@var{skr}, size_t @var{skr_len}, uint8_t *@var{info}, size_t @var{info_len}, struct hpke_ctx *@var{h_ctx})
Creates and sets up the context (@var{h_ctx}) used for encryption and decryption for the Receiver. To set up the context,
some data is needed: The ephemeral public key generated by the Sender, the public and private key
of the Receiver, application-supplied information (optional). This context works in Base mode of hpke.
@end deftypefun
@deftypefun int hpke_setup_psk_s (uint8_t *@var{pkr}, size_t @var{pkr_len}, uint8_t *@var{info}, size_t @var{info_len}, uint8_t *@var{psk}, size_t @var{psk_len}, uint8_t *@var{psk_id}, size_t @var{psk_id_len}, struct hpke_ctx *@var{h_ctx}, void *@var{random_ctx}, nettle_random_func *@var{random})
Same as @code{hpke_setup_base_s} with the difference that it creates a context which works in Psk mode. This mode
authenticates with a symmetric pre-shared key. @var{psk_id} is used to determine which PSK to use.
@end deftypefun
@deftypefun int hpke_setup_psk_r (uint8_t *@var{enc}, size_t @var{enc_len}, uint8_t *@var{pkr}, size_t @var{pkr_len}, uint8_t *@var{skr}, size_t @var{skr_len}, uint8_t *@var{info}, size_t @var{info_len}, uint8_t *@var{psk}, size_t @var{psk_len}, uint8_t *@var{psk_id}, size_t @var{psk_id_len}, struct hpke_ctx *@var{h_ctx})
Same as @code{hpke_setup_base_r} with the difference that it creates a context wich works in Psk mode. This mode
authenticates with a symmetric pre-shared key. @var{psk_id} is used to determine which PSK to use.
@end deftypefun
@deftypefun int hpke_setup_auth_s (uint8_t *@var{pkr}, size_t @var{pkr_len}, uint8_t *@var{pks}, size_t @var{pks_len}, uint8_t *@var{sks}, size_t @var{sks_len}, uint8_t *@var{info}, size_t @var{info_len}, struct hpke_ctx *@var{h_ctx}, void *@var{random_ctx}, nettle_random_func *@var{random})
Same as @code{hpke_setup_base_s} with the difference that it creates a context which works in Auth mode. This mode
authenticates with an assymmetric key.
@end deftypefun
@deftypefun int hpke_setup_auth_r (uint8_t *@var{enc}, size_t @var{enc_len}, uint8_t *@var{pks}, size_t @var{pks_len}, uint8_t *@var{pkr}, size_t @var{pkr_len}, uint8_t *@var{skr}, size_t @var{skr_len}, uint8_t *@var{info}, size_t @var{info_len}, struct hpke_ctx *@var{h_ctx})
Same as @code{hpke_setup_base_r} with the difference that it creates a context wich works in Auth mode. This mode
authenticates with an asymmetric key.
@end deftypefun
@deftypefun int hpke_setup_auth_psk_s (uint8_t *@var{pkr}, size_t @var{pkr_len}, uint8_t *@var{pks}, size_t @var{pks_len}, uint8_t *@var{sks}, size_t @var{sks_len}, uint8_t *@var{psk}, size_t @var{psk_len}, uint8_t *@var{psk_id}, size_t @var{psk_id_len}, uint8_t *@var{info}, size_t @var{info_len}, struct hpke_ctx *@var{h_ctx}, void *@var{random_ctx}, nettle_random_func *@var{random})
Same as @code{hpke_setup_base_s} with the difference that this function creates a context which works in AuthPsk mode. This combines both authentication with a pre-shared symmetric key and an assymmetric key.
@end deftypefun
@deftypefun int hpke_setup_auth_psk_r (uint8_t *@var{enc}, size_t @var{enc_len}, uint8_t *@var{pks}, size_t @var{pks_len}, uint8_t *@var{pkr}, size_t @var{pkr_len}, uint8_t *@var{skr}, size_t @var{skr_len}, uint8_t *@var{psk}, size_t @var{psk_len}, uint8_t *@var{psk_id}, size_t @var{psk_id_len}, uint8_t *@var{info}, size_t @var{info_len}, struct hpke_ctx *@var{h_ctx})
Same as @code{hpke_setup_base_r} with the difference that this function creates a context which works in AuthPsk mode. This combines both authentication with a pre-shared symmetric key and an assymmetric key.
@end deftypefun
@deftypefun int hpke_seal (struct hpke_ctx @var{ctx}, uint8_t *@var{aad}, size_t @var{aad_len}, uint8_t *@var{pt}, size_t @var{pt_len}, uint8_t **@var{ct}, size_t *@var{ct_len})
Encrypts a plaintext using an hpke context and an
optional additional authenticated data into ciphertext.
@end deftypefun
@deftypefun int hpke_open (struct hpke_ctx @var{ctx}. uint8_t *@var{aad}, size_t @var{aad_len}, uint8_t *@var{ct}, size_t @var{ct_len}, uint8_t **@var{pt}, size_t *@var{pt_len})
Decrypts a ciphertext using an hpke context and an optional additional
authenticated data into plaintext.
@end deftypefun
@deftypefun uint8_t *hpke_export_secret (struct hpke_ctx *@var{h_ctx}, uint8_t *@var{exporter_context}, size_t @var{exporter_context_len}, size_t @var{l});
Exports a secret derived from the internal secret of a desired @var{l} length. The max size of @var{l} is 255*Nh (Nh is defined by the hkdf in use). This function takes @var{exporter_context} as an input to the derivation.
@end deftypefun
@node Randomness @node Randomness
@section Randomness @section Randomness
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
/ecc-mul-g-test /ecc-mul-g-test
/ecc-redc-test /ecc-redc-test
/ecc-sqrt-test /ecc-sqrt-test
/ecc-mod-arith-test
/ecdh-test /ecdh-test
/ecdsa-keygen-test /ecdsa-keygen-test
/ecdsa-sign-test /ecdsa-sign-test
...@@ -52,6 +53,7 @@ ...@@ -52,6 +53,7 @@
/gosthash94-test /gosthash94-test
/hkdf-test /hkdf-test
/hmac-test /hmac-test
/hpke-test
/knuth-lfib-test /knuth-lfib-test
/md2-test /md2-test
/md4-test /md4-test
...@@ -64,6 +66,7 @@ ...@@ -64,6 +66,7 @@
/meta-cipher-test /meta-cipher-test
/meta-hash-test /meta-hash-test
/meta-mac-test /meta-mac-test
/ocb-test
/pbkdf2-test /pbkdf2-test
/pkcs1-test /pkcs1-test
/pkcs1-sec-decrypt-test /pkcs1-sec-decrypt-test
......
...@@ -56,7 +56,8 @@ TS_HOGWEED_SOURCES = sexp-test.c sexp-format-test.c \ ...@@ -56,7 +56,8 @@ TS_HOGWEED_SOURCES = sexp-test.c sexp-format-test.c \
eddsa-compress-test.c eddsa-sign-test.c \ eddsa-compress-test.c eddsa-sign-test.c \
eddsa-verify-test.c ed25519-test.c ed448-test.c \ eddsa-verify-test.c ed25519-test.c ed448-test.c \
gostdsa-sign-test.c gostdsa-verify-test.c \ gostdsa-sign-test.c gostdsa-verify-test.c \
gostdsa-keygen-test.c gostdsa-vko-test.c gostdsa-keygen-test.c gostdsa-vko-test.c \
hpke-test.c
TS_SOURCES = $(TS_NETTLE_SOURCES) $(TS_HOGWEED_SOURCES) TS_SOURCES = $(TS_NETTLE_SOURCES) $(TS_HOGWEED_SOURCES)
CXX_SOURCES = cxx-test.cxx CXX_SOURCES = cxx-test.cxx
......
This diff is collapsed.