From 1c4d99e19099b959b0d81176d0c7c44bf0666511 Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Mon, 2 Jun 2025 17:30:58 +0200 Subject: [PATCH 01/17] Extract static function as `x509_get_pka()` Signed-off-by: Steffen Jaeckel --- src/headers/tomcrypt_private.h | 2 ++ src/misc/pem/pem_pkcs.c | 30 ++------------------------ src/pk/asn1/x509/x509_get_pka.c | 38 +++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 28 deletions(-) create mode 100644 src/pk/asn1/x509/x509_get_pka.c diff --git a/src/headers/tomcrypt_private.h b/src/headers/tomcrypt_private.h index c0edbb912..9e4de0309 100644 --- a/src/headers/tomcrypt_private.h +++ b/src/headers/tomcrypt_private.h @@ -646,6 +646,8 @@ int x509_decode_subject_public_key_info(const unsigned char *in, unsigned long i enum ltc_oid_id algorithm, void *public_key, unsigned long *public_key_len, ltc_asn1_type parameters_type, ltc_asn1_list* parameters, unsigned long *parameters_len); +int x509_get_pka(ltc_asn1_list *pub, enum ltc_pka_id *pka); + int pk_oid_cmp_with_asn1(const char *o1, const ltc_asn1_list *o2); #endif /* LTC_DER */ diff --git a/src/misc/pem/pem_pkcs.c b/src/misc/pem/pem_pkcs.c index e99f29ea0..fc9f63965 100644 --- a/src/misc/pem/pem_pkcs.c +++ b/src/misc/pem/pem_pkcs.c @@ -41,32 +41,6 @@ static int s_decrypt_pem(unsigned char *asn1_cert, unsigned long *asn1_len, cons return err; } -static int s_get_pka(ltc_asn1_list *pub, enum ltc_pka_id *pka) -{ - der_flexi_check flexi_should[4]; - ltc_asn1_list *seqid, *id; - enum ltc_oid_id oid_id; - int err; - unsigned long n = 0; - LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_SEQUENCE, &seqid); - LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_BIT_STRING, NULL); - LTC_SET_DER_FLEXI_CHECK(flexi_should, n, LTC_ASN1_EOL, NULL); - if ((err = der_flexi_sequence_cmp(pub, flexi_should)) != CRYPT_OK) { - return err; - } - n = 0; - LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_OBJECT_IDENTIFIER, &id); - LTC_SET_DER_FLEXI_CHECK(flexi_should, n, LTC_ASN1_EOL, NULL); - err = der_flexi_sequence_cmp(seqid, flexi_should); - if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) { - return err; - } - if ((err = pk_get_oid_from_asn1(id, &oid_id)) != CRYPT_OK) { - return err; - } - return pk_get_pka_id(oid_id, pka); -} - typedef int (*import_fn)(const unsigned char *, unsigned long, void*); static const import_fn s_import_x509_fns[LTC_PKA_NUM] = { @@ -90,7 +64,7 @@ static int s_import_x509(unsigned char *asn1_cert, unsigned long asn1_len, ltc_p if ((err = x509_decode_spki(asn1_cert, asn1_len, &d, &spki)) != CRYPT_OK) { return err; } - err = s_get_pka(spki, &pka); + err = x509_get_pka(spki, &pka); der_free_sequence_flexi(d); if (err != CRYPT_OK) { return err; @@ -171,7 +145,7 @@ static int s_extract_pka(unsigned char *asn1_cert, unsigned long asn1_len, enum if ((err = der_decode_sequence_flexi(asn1_cert, &asn1_len, &pub)) != CRYPT_OK) { return err; } - err = s_get_pka(pub, pka); + err = x509_get_pka(pub, pka); der_sequence_free(pub); return err; } diff --git a/src/pk/asn1/x509/x509_get_pka.c b/src/pk/asn1/x509/x509_get_pka.c new file mode 100644 index 000000000..23a12edd7 --- /dev/null +++ b/src/pk/asn1/x509/x509_get_pka.c @@ -0,0 +1,38 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file x509_get_pka.c + Extract the PKA from an X.509 cert, Steffen Jaeckel +*/ + +#ifdef LTC_DER + +int x509_get_pka(ltc_asn1_list *pub, enum ltc_pka_id *pka) +{ + der_flexi_check flexi_should[4]; + ltc_asn1_list *seqid, *id = NULL; + enum ltc_oid_id oid_id; + int err; + unsigned long n = 0; + LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_SEQUENCE, &seqid); + LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_BIT_STRING, NULL); + LTC_SET_DER_FLEXI_CHECK(flexi_should, n, LTC_ASN1_EOL, NULL); + if ((err = der_flexi_sequence_cmp(pub, flexi_should)) != CRYPT_OK) { + return err; + } + n = 0; + LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_OBJECT_IDENTIFIER, &id); + LTC_SET_DER_FLEXI_CHECK(flexi_should, n, LTC_ASN1_EOL, NULL); + err = der_flexi_sequence_cmp(seqid, flexi_should); + if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) { + return err; + } + if ((err = pk_get_oid_from_asn1(id, &oid_id)) != CRYPT_OK) { + return err; + } + return pk_get_pka_id(oid_id, pka); +} + +#endif /* LTC_DER */ From 61f8af4cc981aa3496dbdc78a4de3fe88292cc0f Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Wed, 4 Jun 2025 15:28:57 +0200 Subject: [PATCH 02/17] Export static function as `x509_import_spki()` Signed-off-by: Steffen Jaeckel --- src/headers/tomcrypt_private.h | 1 + src/misc/pem/pem_pkcs.c | 41 +-------------------- src/pk/asn1/x509/x509_import_spki.c | 56 +++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 40 deletions(-) create mode 100644 src/pk/asn1/x509/x509_import_spki.c diff --git a/src/headers/tomcrypt_private.h b/src/headers/tomcrypt_private.h index 9e4de0309..359e5a5d3 100644 --- a/src/headers/tomcrypt_private.h +++ b/src/headers/tomcrypt_private.h @@ -647,6 +647,7 @@ int x509_decode_subject_public_key_info(const unsigned char *in, unsigned long i ltc_asn1_type parameters_type, ltc_asn1_list* parameters, unsigned long *parameters_len); int x509_get_pka(ltc_asn1_list *pub, enum ltc_pka_id *pka); +int x509_import_spki(const unsigned char *asn1_cert, unsigned long asn1_len, ltc_pka_key *k, ltc_asn1_list **root); int pk_oid_cmp_with_asn1(const char *o1, const ltc_asn1_list *o2); diff --git a/src/misc/pem/pem_pkcs.c b/src/misc/pem/pem_pkcs.c index fc9f63965..d3db284cd 100644 --- a/src/misc/pem/pem_pkcs.c +++ b/src/misc/pem/pem_pkcs.c @@ -41,45 +41,6 @@ static int s_decrypt_pem(unsigned char *asn1_cert, unsigned long *asn1_len, cons return err; } -typedef int (*import_fn)(const unsigned char *, unsigned long, void*); - -static const import_fn s_import_x509_fns[LTC_PKA_NUM] = { -#ifdef LTC_MRSA - [LTC_PKA_RSA] = (import_fn)rsa_import_x509, -#endif -#ifdef LTC_MECC - [LTC_PKA_EC] = (import_fn)ecc_import_x509, -#endif -#ifdef LTC_CURVE25519 - [LTC_PKA_X25519] = (import_fn)x25519_import_x509, - [LTC_PKA_ED25519] = (import_fn)ed25519_import_x509, -#endif -}; - -static int s_import_x509(unsigned char *asn1_cert, unsigned long asn1_len, ltc_pka_key *k) -{ - enum ltc_pka_id pka = LTC_PKA_UNDEF; - ltc_asn1_list *d, *spki; - int err; - if ((err = x509_decode_spki(asn1_cert, asn1_len, &d, &spki)) != CRYPT_OK) { - return err; - } - err = x509_get_pka(spki, &pka); - der_free_sequence_flexi(d); - if (err != CRYPT_OK) { - return err; - } - if (pka < 0 - || pka > LTC_ARRAY_SIZE(s_import_x509_fns) - || s_import_x509_fns[pka] == NULL) { - return CRYPT_PK_INVALID_TYPE; - } - if ((err = s_import_x509_fns[pka](asn1_cert, asn1_len, &k->u)) == CRYPT_OK) { - k->id = pka; - } - return err; -} - static int s_import_pkcs8(unsigned char *asn1_cert, unsigned long asn1_len, ltc_pka_key *k, const password_ctx *pw_ctx) { int err; @@ -198,7 +159,7 @@ static int s_decode(struct get_char *g, ltc_pka_key *k, const password_ctx *pw_c err = s_import_pkcs8(asn1_cert, asn1_len, k, pw_ctx); goto cleanup; } else if (hdr.id->flags == pf_x509) { - err = s_import_x509(asn1_cert, asn1_len, k); + err = x509_import_spki(asn1_cert, asn1_len, k, NULL); goto cleanup; } else if ((hdr.id->flags & pf_public) && hdr.id->pka == LTC_PKA_UNDEF) { if ((err = s_extract_pka(asn1_cert, asn1_len, &pka)) != CRYPT_OK) { diff --git a/src/pk/asn1/x509/x509_import_spki.c b/src/pk/asn1/x509/x509_import_spki.c new file mode 100644 index 000000000..1e7f3b2ce --- /dev/null +++ b/src/pk/asn1/x509/x509_import_spki.c @@ -0,0 +1,56 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file x509_import_spki.c + Import the SubjectPublicKeyInfo of an X.509 cert, Steffen Jaeckel +*/ + +#ifdef LTC_DER + +typedef int (*import_fn)(const unsigned char *, unsigned long, void*); + +static const import_fn s_import_x509_fns[LTC_PKA_NUM] = { +#ifdef LTC_MRSA + [LTC_PKA_RSA] = (import_fn)rsa_import_x509, +#endif +#ifdef LTC_MECC + [LTC_PKA_EC] = (import_fn)ecc_import_x509, +#endif +#ifdef LTC_CURVE25519 + [LTC_PKA_X25519] = (import_fn)x25519_import_x509, + [LTC_PKA_ED25519] = (import_fn)ed25519_import_x509, +#endif +}; + +int x509_import_spki(const unsigned char *asn1_cert, unsigned long asn1_len, ltc_pka_key *k, ltc_asn1_list **root) +{ + enum ltc_pka_id pka = LTC_PKA_UNDEF; + ltc_asn1_list *d, *spki; + int err; + if ((err = x509_decode_spki(asn1_cert, asn1_len, &d, &spki)) != CRYPT_OK) { + return err; + } + if ((err = x509_get_pka(spki, &pka)) != CRYPT_OK) { + goto err_out; + } + if (pka < 0 + || pka > LTC_ARRAY_SIZE(s_import_x509_fns) + || s_import_x509_fns[pka] == NULL) { + err = CRYPT_PK_INVALID_TYPE; + goto err_out; + } + if ((err = s_import_x509_fns[pka](asn1_cert, asn1_len, &k->u)) == CRYPT_OK) { + k->id = pka; + } +err_out: + if (err == CRYPT_OK && root) { + *root = d; + d = NULL; + } + der_free_sequence_flexi(d); + return err; +} + +#endif /* LTC_DER */ From 3dd5c8846c82ecbc0bacd6ef14888ebae4d02bbb Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Wed, 4 Jun 2025 15:30:21 +0200 Subject: [PATCH 03/17] Re-factor `s_import_pkcs8()` Signed-off-by: Steffen Jaeckel --- src/misc/pem/pem_pkcs.c | 75 ++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 39 deletions(-) diff --git a/src/misc/pem/pem_pkcs.c b/src/misc/pem/pem_pkcs.c index d3db284cd..7d726645c 100644 --- a/src/misc/pem/pem_pkcs.c +++ b/src/misc/pem/pem_pkcs.c @@ -41,55 +41,50 @@ static int s_decrypt_pem(unsigned char *asn1_cert, unsigned long *asn1_len, cons return err; } -static int s_import_pkcs8(unsigned char *asn1_cert, unsigned long asn1_len, ltc_pka_key *k, const password_ctx *pw_ctx) -{ - int err; - enum ltc_oid_id pka; - ltc_asn1_list *alg_id, *priv_key; - ltc_asn1_list *p8_asn1 = NULL; - if ((err = pkcs8_decode_flexi(asn1_cert, asn1_len, pw_ctx, &p8_asn1)) != CRYPT_OK) { - goto cleanup; - } - if ((err = pkcs8_get_children(p8_asn1, &pka, &alg_id, &priv_key)) != CRYPT_OK) { - goto cleanup; - } - switch (pka) { +typedef int (*pkcs8_import_fn)(ltc_asn1_list *, ltc_asn1_list *, void*); + +static const struct { + enum ltc_pka_id id; + pkcs8_import_fn fn; +} s_import_pkcs8_map[LTC_OID_NUM] = { #ifdef LTC_MDH - case LTC_OID_DH: - err = dh_import_pkcs8_asn1(alg_id, priv_key, &k->u.dh); - k->id = LTC_PKA_DH; - break; + [LTC_OID_DH] = { LTC_PKA_DH, (pkcs8_import_fn)dh_import_pkcs8_asn1 }, #endif #ifdef LTC_MDSA - case LTC_OID_DSA: - err = dsa_import_pkcs8_asn1(alg_id, priv_key, &k->u.dsa); - k->id = LTC_PKA_DSA; - break; + [LTC_OID_DSA] = { LTC_PKA_DSA, (pkcs8_import_fn)dsa_import_pkcs8_asn1 }, #endif #ifdef LTC_MRSA - case LTC_OID_RSA: - err = rsa_import_pkcs8_asn1(alg_id, priv_key, &k->u.rsa); - k->id = LTC_PKA_RSA; - break; + [LTC_OID_RSA] = { LTC_PKA_RSA, (pkcs8_import_fn)rsa_import_pkcs8_asn1 }, #endif #ifdef LTC_MECC - case LTC_OID_EC: - err = ecc_import_pkcs8_asn1(alg_id, priv_key, &k->u.ecc); - k->id = LTC_PKA_EC; - break; + [LTC_OID_EC] = { LTC_PKA_EC, (pkcs8_import_fn)ecc_import_pkcs8_asn1 }, #endif #ifdef LTC_CURVE25519 - case LTC_OID_X25519: - err = x25519_import_pkcs8_asn1(alg_id, priv_key, &k->u.x25519); - k->id = LTC_PKA_X25519; - break; - case LTC_OID_ED25519: - err = ed25519_import_pkcs8_asn1(alg_id, priv_key, &k->u.ed25519); - k->id = LTC_PKA_ED25519; - break; + [LTC_OID_X25519] = { LTC_PKA_X25519, (pkcs8_import_fn)x25519_import_pkcs8_asn1 }, + [LTC_OID_ED25519] = { LTC_PKA_ED25519, (pkcs8_import_fn)ed25519_import_pkcs8_asn1 }, #endif - default: - err = CRYPT_PK_INVALID_TYPE; +}; + +static int s_import_pkcs8(unsigned char *asn1_cert, unsigned long asn1_len, ltc_pka_key *k, const password_ctx *pw_ctx) +{ + int err; + enum ltc_oid_id oid_id; + ltc_asn1_list *alg_id, *priv_key; + ltc_asn1_list *p8_asn1 = NULL; + if ((err = pkcs8_decode_flexi(asn1_cert, asn1_len, pw_ctx, &p8_asn1)) != CRYPT_OK) { + goto cleanup; + } + if ((err = pkcs8_get_children(p8_asn1, &oid_id, &alg_id, &priv_key)) != CRYPT_OK) { + goto cleanup; + } + if (oid_id < 0 + || oid_id > LTC_ARRAY_SIZE(s_import_pkcs8_map) + || s_import_pkcs8_map[oid_id].fn == NULL) { + err = CRYPT_PK_INVALID_TYPE; + goto cleanup; + } + if ((err = s_import_pkcs8_map[oid_id].fn(alg_id, priv_key, &k->u)) == CRYPT_OK) { + k->id = s_import_pkcs8_map[oid_id].id; } cleanup: @@ -111,6 +106,8 @@ static int s_extract_pka(unsigned char *asn1_cert, unsigned long asn1_len, enum return err; } +typedef int (*import_fn)(const unsigned char *, unsigned long, void*); + static const import_fn s_import_openssl_fns[LTC_PKA_NUM] = { #ifdef LTC_MRSA [LTC_PKA_RSA] = (import_fn)rsa_import, From 88a7d2b5fcb292b372041b2cb1c583bfdabd1017 Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Mon, 16 Jun 2025 14:26:24 +0200 Subject: [PATCH 04/17] Extend `der_flexi_sequence_cmp()` To be able to do a bit more, add an optional handler callback function. Additional to that, also make it possible to mark elements as optional. Signed-off-by: Steffen Jaeckel --- src/headers/tomcrypt_private.h | 24 ++++++++++++++----- .../der/sequence/der_flexi_sequence_cmp.c | 11 ++++++++- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/headers/tomcrypt_private.h b/src/headers/tomcrypt_private.h index 359e5a5d3..0b06e98ef 100644 --- a/src/headers/tomcrypt_private.h +++ b/src/headers/tomcrypt_private.h @@ -600,17 +600,29 @@ int der_printable_value_decode(int v); unsigned long der_utf8_charsize(const wchar_t c); -typedef struct { +typedef int (*der_flexi_handler)(const ltc_asn1_list*, void*); + +typedef struct der_flexi_check { ltc_asn1_type t; + int optional; ltc_asn1_list **pp; + der_flexi_handler handler; + void *userdata; } der_flexi_check; -#define LTC_SET_DER_FLEXI_CHECK(list, index, Type, P) \ - do { \ - int LTC_SDFC_temp##__LINE__ = (index); \ - list[LTC_SDFC_temp##__LINE__].t = Type; \ - list[LTC_SDFC_temp##__LINE__].pp = P; \ +#define LTC_PRIV_SET_DER_FLEXI_CHECK(list, index, Type, P, Opt, Hndl, Udata) \ + do { \ + int LTC_SDFC_temp##__LINE__ = (index); \ + list[LTC_SDFC_temp##__LINE__].t = Type; \ + list[LTC_SDFC_temp##__LINE__].pp = P; \ + list[LTC_SDFC_temp##__LINE__].optional = Opt; \ + list[LTC_SDFC_temp##__LINE__].handler = (der_flexi_handler)Hndl; \ + list[LTC_SDFC_temp##__LINE__].userdata = Udata; \ } while (0) +#define LTC_SET_DER_FLEXI_CHECK(list, index, Type, P) LTC_PRIV_SET_DER_FLEXI_CHECK(list, index, Type, P, 0, NULL, NULL) +#define LTC_SET_DER_FLEXI_CHECK_OPT(list, index, Type, P) LTC_PRIV_SET_DER_FLEXI_CHECK(list, index, Type, P, 1, NULL, NULL) +#define LTC_SET_DER_FLEXI_HANDLER(list, index, Type, Hndl, Udata) LTC_PRIV_SET_DER_FLEXI_CHECK(list, index, Type, NULL, 0, Hndl, Udata) +#define LTC_SET_DER_FLEXI_HANDLER_OPT(list, index, Type, Hndl, Udata) LTC_PRIV_SET_DER_FLEXI_CHECK(list, index, Type, NULL, 1, Hndl, Udata) extern const ltc_asn1_type der_asn1_tag_to_type_map[]; diff --git a/src/pk/asn1/der/sequence/der_flexi_sequence_cmp.c b/src/pk/asn1/der/sequence/der_flexi_sequence_cmp.c index 026eb504a..535483f59 100644 --- a/src/pk/asn1/der/sequence/der_flexi_sequence_cmp.c +++ b/src/pk/asn1/der/sequence/der_flexi_sequence_cmp.c @@ -24,11 +24,20 @@ int der_flexi_sequence_cmp(const ltc_asn1_list *flexi, der_flexi_check *check) return CRYPT_INVALID_PACKET; } cur = flexi->child; - while(check->t != LTC_ASN1_EOL) { + while(check->t != LTC_ASN1_EOL && cur) { if (!LTC_ASN1_IS_TYPE(cur, check->t)) { + if (check->optional) { + check++; + continue; + } return CRYPT_INVALID_PACKET; } if (check->pp != NULL) *check->pp = cur; + else if (check->handler) { + int err = check->handler(cur, check->userdata); + if (err != CRYPT_OK) + return err; + } cur = cur->next; check++; } From 45eb4312676881648af4621a97ef7fc717cbe50d Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Tue, 2 Sep 2025 14:41:36 +0200 Subject: [PATCH 05/17] Use `rsa_init()` to initialize an `rsa_key` (and you should do that too) Signed-off-by: Steffen Jaeckel --- tests/pkcs_1_eme_test.c | 3 +-- tests/pkcs_1_emsa_test.c | 3 +-- tests/pkcs_1_oaep_test.c | 3 +-- tests/pkcs_1_pss_test.c | 3 +-- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/tests/pkcs_1_eme_test.c b/tests/pkcs_1_eme_test.c index ca540360b..9e818ace6 100644 --- a/tests/pkcs_1_eme_test.c +++ b/tests/pkcs_1_eme_test.c @@ -24,8 +24,7 @@ int pkcs_1_eme_test(void) for (i = 0; i < LTC_ARRAY_SIZE(testcases_eme); ++i) { testcase_t* t = &testcases_eme[i]; rsa_key k, *key = &k; - DOX(ltc_mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, - &key->dP, &key->qP, &key->p, &key->q, NULL), t->name); + DOX(rsa_init(key), t->name); DOX(ltc_mp_read_unsigned_bin(key->e, t->rsa.e, t->rsa.e_l), t->name); DOX(ltc_mp_read_unsigned_bin(key->d, t->rsa.d, t->rsa.d_l), t->name); diff --git a/tests/pkcs_1_emsa_test.c b/tests/pkcs_1_emsa_test.c index ba66f079a..43fb112ae 100644 --- a/tests/pkcs_1_emsa_test.c +++ b/tests/pkcs_1_emsa_test.c @@ -21,8 +21,7 @@ int pkcs_1_emsa_test(void) for (i = 0; i < LTC_ARRAY_SIZE(testcases_emsa); ++i) { testcase_t* t = &testcases_emsa[i]; rsa_key k, *key = &k; - DOX(ltc_mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, - &key->dP, &key->qP, &key->p, &key->q, NULL), t->name); + DOX(rsa_init(key), t->name); DOX(ltc_mp_read_unsigned_bin(key->e, t->rsa.e, t->rsa.e_l), t->name); DOX(ltc_mp_read_unsigned_bin(key->d, t->rsa.d, t->rsa.d_l), t->name); diff --git a/tests/pkcs_1_oaep_test.c b/tests/pkcs_1_oaep_test.c index 1cb6ca128..76157c2c0 100644 --- a/tests/pkcs_1_oaep_test.c +++ b/tests/pkcs_1_oaep_test.c @@ -24,8 +24,7 @@ int pkcs_1_oaep_test(void) for (i = 0; i < LTC_ARRAY_SIZE(testcases_oaep); ++i) { testcase_t* t = &testcases_oaep[i]; rsa_key k, *key = &k; - DOX(ltc_mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, - &key->dP, &key->qP, &key->p, &key->q, NULL), t->name); + DOX(rsa_init(key), t->name); DOX(ltc_mp_read_unsigned_bin(key->e, t->rsa.e, t->rsa.e_l), t->name); DOX(ltc_mp_read_unsigned_bin(key->d, t->rsa.d, t->rsa.d_l), t->name); diff --git a/tests/pkcs_1_pss_test.c b/tests/pkcs_1_pss_test.c index a62e53ff0..a86e473ac 100644 --- a/tests/pkcs_1_pss_test.c +++ b/tests/pkcs_1_pss_test.c @@ -24,8 +24,7 @@ int pkcs_1_pss_test(void) for (i = 0; i < LTC_ARRAY_SIZE(testcases_pss); ++i) { testcase_t* t = &testcases_pss[i]; rsa_key k, *key = &k; - DOX(ltc_mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, - &key->dP, &key->qP, &key->p, &key->q, NULL), t->name); + DOX(rsa_init(key), t->name); DOX(ltc_mp_read_unsigned_bin(key->e, t->rsa.e, t->rsa.e_l), t->name); DOX(ltc_mp_read_unsigned_bin(key->d, t->rsa.d, t->rsa.d_l), t->name); From 988d4e3509c9e6782b4aaa2ce2c82d504361b40f Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Tue, 26 Aug 2025 18:14:42 +0200 Subject: [PATCH 06/17] Add support for separate MGF1 hashes Update PKCS#1-PSS and RSA APIs that allow passing a separate hash index for the MGF1 hash. Signed-off-by: Steffen Jaeckel --- src/headers/tomcrypt_pk.h | 12 +++++---- src/headers/tomcrypt_private.h | 16 ++++++++++++ src/pk/pkcs1/pkcs_1_pss_decode.c | 38 +++++++++++++++++++++++---- src/pk/pkcs1/pkcs_1_pss_encode.c | 44 +++++++++++++++++++++++++++----- src/pk/rsa/rsa_sign_hash.c | 11 ++++---- src/pk/rsa/rsa_verify_hash.c | 7 ++--- tests/pkcs_1_emsa_test.c | 4 +-- tests/rsa_test.c | 20 +++++++-------- 8 files changed, 115 insertions(+), 37 deletions(-) diff --git a/src/headers/tomcrypt_pk.h b/src/headers/tomcrypt_pk.h index 72e4f992c..beac9fcc4 100644 --- a/src/headers/tomcrypt_pk.h +++ b/src/headers/tomcrypt_pk.h @@ -103,10 +103,10 @@ void rsa_free(rsa_key *key); rsa_decrypt_key_ex(in, inlen, out, outlen, lparam, lparamlen, hash_idx, -1, LTC_PKCS_1_OAEP, stat, key) #define rsa_sign_hash(in, inlen, out, outlen, prng, prng_idx, hash_idx, saltlen, key) \ - rsa_sign_hash_ex(in, inlen, out, outlen, LTC_PKCS_1_PSS, prng, prng_idx, hash_idx, saltlen, key) + rsa_sign_hash_ex(in, inlen, out, outlen, LTC_PKCS_1_PSS, prng, prng_idx, hash_idx, hash_idx, saltlen, key) #define rsa_verify_hash(sig, siglen, hash, hashlen, hash_idx, saltlen, stat, key) \ - rsa_verify_hash_ex(sig, siglen, hash, hashlen, LTC_PKCS_1_PSS, hash_idx, saltlen, stat, key) + rsa_verify_hash_ex(sig, siglen, hash, hashlen, LTC_PKCS_1_PSS, hash_idx, hash_idx, saltlen, stat, key) #define rsa_sign_saltlen_get_max(hash_idx, key) \ rsa_sign_saltlen_get_max_ex(LTC_PKCS_1_PSS, hash_idx, key) @@ -130,14 +130,16 @@ int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, int padding, - prng_state *prng, int prng_idx, - int hash_idx, unsigned long saltlen, + prng_state *prng, int prng_idx, + int hash_idx, int mgf_hash_idx, + unsigned long saltlen, const rsa_key *key); int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen, const unsigned char *hash, unsigned long hashlen, int padding, - int hash_idx, unsigned long saltlen, + int hash_idx, int mgf_hash_idx, + unsigned long saltlen, int *stat, const rsa_key *key); int rsa_sign_saltlen_get_max_ex(int padding, int hash_idx, const rsa_key *key); diff --git a/src/headers/tomcrypt_private.h b/src/headers/tomcrypt_private.h index 0b06e98ef..4fd749dcf 100644 --- a/src/headers/tomcrypt_private.h +++ b/src/headers/tomcrypt_private.h @@ -667,6 +667,22 @@ int pk_oid_cmp_with_asn1(const char *o1, const ltc_asn1_list *o2); /* tomcrypt_pkcs.h */ +#ifdef LTC_PKCS_1 + +int pkcs_1_pss_encode_mgf1(const unsigned char *msghash, unsigned long msghashlen, + unsigned long saltlen, + prng_state *prng, int prng_idx, + int hash_idx, int mgf_hash_idx, + unsigned long modulus_bitlen, + unsigned char *out, unsigned long *outlen); +int pkcs_1_pss_decode_mgf1(const unsigned char *msghash, unsigned long msghashlen, + const unsigned char *sig, unsigned long siglen, + unsigned long saltlen, + int hash_idx, int mgf_hash_idx, + unsigned long modulus_bitlen, int *res); + +#endif /* LTC_PKCS_1 */ + #ifdef LTC_PKCS_8 /* Public-Key Cryptography Standards (PKCS) #8: diff --git a/src/pk/pkcs1/pkcs_1_pss_decode.c b/src/pk/pkcs1/pkcs_1_pss_decode.c index fad401d1b..fc258ea4f 100644 --- a/src/pk/pkcs1/pkcs_1_pss_decode.c +++ b/src/pk/pkcs1/pkcs_1_pss_decode.c @@ -17,14 +17,16 @@ @param siglen The length of the signature data (octets) @param saltlen The length of the salt used (octets) @param hash_idx The index of the hash desired + @param mgf_hash_idx The index of the hash desired for MGF1 @param modulus_bitlen The bit length of the RSA modulus @param res [out] The result of the comparison, 1==valid, 0==invalid @return CRYPT_OK if successful (even if the comparison failed) */ -int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, - const unsigned char *sig, unsigned long siglen, - unsigned long saltlen, int hash_idx, - unsigned long modulus_bitlen, int *res) +int pkcs_1_pss_decode_mgf1(const unsigned char *msghash, unsigned long msghashlen, + const unsigned char *sig, unsigned long siglen, + unsigned long saltlen, + int hash_idx, int mgf_hash_idx, + unsigned long modulus_bitlen, int *res) { unsigned char *DB, *mask, *salt, *hash; unsigned long x, y, hLen, modulus_len; @@ -41,6 +43,11 @@ int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } + if (hash_idx != mgf_hash_idx) { + if ((err = hash_is_valid(mgf_hash_idx)) != CRYPT_OK) { + return err; + } + } hLen = hash_descriptor[hash_idx].hashsize; modulus_bitlen--; @@ -95,7 +102,7 @@ int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, } /* generate mask of length modulus_len - hLen - 1 from hash */ - if ((err = pkcs_1_mgf1(hash_idx, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { + if ((err = pkcs_1_mgf1(mgf_hash_idx, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { goto LBL_ERR; } @@ -163,4 +170,25 @@ int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, return err; } + +/** + PKCS #1 v2.00 PSS decode + @param msghash The hash to verify + @param msghashlen The length of the hash (octets) + @param sig The signature data (encoded data) + @param siglen The length of the signature data (octets) + @param saltlen The length of the salt used (octets) + @param hash_idx The index of the hash desired + @param modulus_bitlen The bit length of the RSA modulus + @param res [out] The result of the comparison, 1==valid, 0==invalid + @return CRYPT_OK if successful (even if the comparison failed) +*/ +int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, + const unsigned char *sig, unsigned long siglen, + unsigned long saltlen, int hash_idx, + unsigned long modulus_bitlen, int *res) +{ + return pkcs_1_pss_decode_mgf1(msghash, msghashlen, sig, siglen, saltlen, hash_idx, hash_idx, modulus_bitlen, res); +} + #endif /* LTC_PKCS_1 */ diff --git a/src/pk/pkcs1/pkcs_1_pss_encode.c b/src/pk/pkcs1/pkcs_1_pss_encode.c index 2a4e3728a..01d9636f9 100644 --- a/src/pk/pkcs1/pkcs_1_pss_encode.c +++ b/src/pk/pkcs1/pkcs_1_pss_encode.c @@ -17,16 +17,18 @@ @param prng An active PRNG context @param prng_idx The index of the PRNG desired @param hash_idx The index of the hash desired + @param mgf_hash_idx The index of the hash desired for MGF1 @param modulus_bitlen The bit length of the RSA modulus @param out [out] The destination of the encoding @param outlen [in/out] The max size and resulting size of the encoded data @return CRYPT_OK if successful */ -int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, - unsigned long saltlen, prng_state *prng, - int prng_idx, int hash_idx, - unsigned long modulus_bitlen, - unsigned char *out, unsigned long *outlen) +int pkcs_1_pss_encode_mgf1(const unsigned char *msghash, unsigned long msghashlen, + unsigned long saltlen, + prng_state *prng, int prng_idx, + int hash_idx, int mgf_hash_idx, + unsigned long modulus_bitlen, + unsigned char *out, unsigned long *outlen) { unsigned char *DB, *mask, *salt, *hash; unsigned long x, y, hLen, modulus_len; @@ -37,10 +39,15 @@ int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); - /* ensure hash and PRNG are valid */ + /* ensure hashes and PRNG are valid */ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } + if (hash_idx != mgf_hash_idx) { + if ((err = hash_is_valid(mgf_hash_idx)) != CRYPT_OK) { + return err; + } + } if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { return err; } @@ -111,7 +118,7 @@ int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, /* x += saltlen; */ /* generate mask of length modulus_len - hLen - 1 from hash */ - if ((err = pkcs_1_mgf1(hash_idx, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { + if ((err = pkcs_1_mgf1(mgf_hash_idx, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { goto LBL_ERR; } @@ -161,4 +168,27 @@ int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, return err; } + +/** + PKCS #1 v2.00 Signature Encoding using MGF1 and both hashes are the same + @param msghash The hash to encode + @param msghashlen The length of the hash (octets) + @param saltlen The length of the salt desired (octets) + @param prng An active PRNG context + @param prng_idx The index of the PRNG desired + @param hash_idx The index of the hash desired + @param modulus_bitlen The bit length of the RSA modulus + @param out [out] The destination of the encoding + @param outlen [in/out] The max size and resulting size of the encoded data + @return CRYPT_OK if successful +*/ +int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, + unsigned long saltlen, prng_state *prng, + int prng_idx, int hash_idx, + unsigned long modulus_bitlen, + unsigned char *out, unsigned long *outlen) +{ + return pkcs_1_pss_encode_mgf1(msghash, msghashlen, saltlen, prng, prng_idx, hash_idx, hash_idx, modulus_bitlen, out, outlen); +} + #endif /* LTC_PKCS_1 */ diff --git a/src/pk/rsa/rsa_sign_hash.c b/src/pk/rsa/rsa_sign_hash.c index bc5e0a89f..a7a18036d 100644 --- a/src/pk/rsa/rsa_sign_hash.c +++ b/src/pk/rsa/rsa_sign_hash.c @@ -26,9 +26,10 @@ int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, int padding, - prng_state *prng, int prng_idx, - int hash_idx, unsigned long saltlen, - const rsa_key *key) + prng_state *prng, int prng_idx, + int hash_idx, int mgf_hash_idx, + unsigned long saltlen, + const rsa_key *key) { unsigned long modulus_bitlen, modulus_bytelen, x, y; int err; @@ -72,8 +73,8 @@ int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, if (padding == LTC_PKCS_1_PSS) { /* PSS pad the key */ x = *outlen; - if ((err = pkcs_1_pss_encode(in, inlen, saltlen, prng, prng_idx, - hash_idx, modulus_bitlen, out, &x)) != CRYPT_OK) { + if ((err = pkcs_1_pss_encode_mgf1(in, inlen, saltlen, prng, prng_idx, + hash_idx, mgf_hash_idx, modulus_bitlen, out, &x)) != CRYPT_OK) { return err; } } else { diff --git a/src/pk/rsa/rsa_verify_hash.c b/src/pk/rsa/rsa_verify_hash.c index 9ca1641a6..7303a7b26 100644 --- a/src/pk/rsa/rsa_verify_hash.c +++ b/src/pk/rsa/rsa_verify_hash.c @@ -25,7 +25,8 @@ int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen, const unsigned char *hash, unsigned long hashlen, int padding, - int hash_idx, unsigned long saltlen, + int hash_idx, int mgf_hash_idx, + unsigned long saltlen, int *stat, const rsa_key *key) { unsigned long modulus_bitlen, modulus_bytelen, x; @@ -87,10 +88,10 @@ int rsa_verify_hash_ex(const unsigned char *sig, unsigned long sigle /* PSS decode and verify it */ if(modulus_bitlen%8 == 1){ - err = pkcs_1_pss_decode(hash, hashlen, tmpbuf+1, x-1, saltlen, hash_idx, modulus_bitlen, stat); + err = pkcs_1_pss_decode_mgf1(hash, hashlen, tmpbuf+1, x-1, saltlen, hash_idx, mgf_hash_idx, modulus_bitlen, stat); } else{ - err = pkcs_1_pss_decode(hash, hashlen, tmpbuf, x, saltlen, hash_idx, modulus_bitlen, stat); + err = pkcs_1_pss_decode_mgf1(hash, hashlen, tmpbuf, x, saltlen, hash_idx, mgf_hash_idx, modulus_bitlen, stat); } } else { diff --git a/tests/pkcs_1_emsa_test.c b/tests/pkcs_1_emsa_test.c index 43fb112ae..327f2b5df 100644 --- a/tests/pkcs_1_emsa_test.c +++ b/tests/pkcs_1_emsa_test.c @@ -39,9 +39,9 @@ int pkcs_1_emsa_test(void) unsigned long buflen = sizeof(buf), obuflen = sizeof(obuf); int stat; DOX(hash_memory(hash_idx, s->o1, s->o1_l, buf, &buflen), s->name); - DOX(rsa_sign_hash_ex(buf, buflen, obuf, &obuflen, LTC_PKCS_1_V1_5, NULL, -1, hash_idx, 0, key), s->name); + DOX(rsa_sign_hash_ex(buf, buflen, obuf, &obuflen, LTC_PKCS_1_V1_5, NULL, -1, hash_idx, -1, 0, key), s->name); COMPARE_TESTVECTOR(obuf, obuflen, s->o2, s->o2_l,s->name, j); - DOX(rsa_verify_hash_ex(obuf, obuflen, buf, buflen, LTC_PKCS_1_V1_5, hash_idx, 0, &stat, key), s->name); + DOX(rsa_verify_hash_ex(obuf, obuflen, buf, buflen, LTC_PKCS_1_V1_5, hash_idx, -1, 0, &stat, key), s->name); DOX(stat == 1?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, s->name); } /* for */ diff --git a/tests/rsa_test.c b/tests/rsa_test.c index c1cfbb2b0..acc82d5b8 100644 --- a/tests/rsa_test.c +++ b/tests/rsa_test.c @@ -191,13 +191,13 @@ static int rsa_compat_test(void) /* sign-verify a message with PKCS #1 v1.5 no ASN.1 */ len = sizeof(buf); - DO(rsa_sign_hash_ex((unsigned char*)"test", 4, buf, &len, LTC_PKCS_1_V1_5_NA1, NULL, 0, 0, 0, &key)); + DO(rsa_sign_hash_ex((unsigned char*)"test", 4, buf, &len, LTC_PKCS_1_V1_5_NA1, NULL, 0, 0, 0, 0, &key)); if (len != sizeof(openssl_rsautl_pkcs) || memcmp(buf, openssl_rsautl_pkcs, len)) { fprintf(stderr, "RSA rsa_sign_hash_ex + LTC_PKCS_1_V1_5_NA1 failed\n"); return 1; } stat = 0; - DO(rsa_verify_hash_ex(openssl_rsautl_pkcs, sizeof(openssl_rsautl_pkcs), (unsigned char*)"test", 4, LTC_PKCS_1_V1_5_NA1, 0, 0, &stat, &pubkey)); + DO(rsa_verify_hash_ex(openssl_rsautl_pkcs, sizeof(openssl_rsautl_pkcs), (unsigned char*)"test", 4, LTC_PKCS_1_V1_5_NA1, 0, 0, 0, &stat, &pubkey)); if (stat != 1) { fprintf(stderr, "RSA rsa_verify_hash_ex + LTC_PKCS_1_V1_5_NA1 failed\n"); return 1; @@ -331,9 +331,9 @@ static int s_rsa_cryptx_issue_69(void) l1 = sizeof(buf1); DO(radix_to_bin(sig1, 16, buf0, &l0)); DO(radix_to_bin(hash, 16, buf1, &l1)); - SHOULD_FAIL(rsa_verify_hash_ex(buf0, l0, buf1, l1, LTC_PKCS_1_V1_5, 0, 0, &stat, &key)); + SHOULD_FAIL(rsa_verify_hash_ex(buf0, l0, buf1, l1, LTC_PKCS_1_V1_5, 0, 0, 0, &stat, &key)); DO(radix_to_bin(sig2, 16, buf0, &l0)); - SHOULD_FAIL(rsa_verify_hash_ex(buf0, l0, buf1, l1, LTC_PKCS_1_V1_5, 0, 0, &stat, &key)); + SHOULD_FAIL(rsa_verify_hash_ex(buf0, l0, buf1, l1, LTC_PKCS_1_V1_5, 0, 0, 0, &stat, &key)); rsa_free(&key); return CRYPT_OK; } @@ -684,11 +684,11 @@ print_hex("q", tmp, len); /* sign a message with PKCS #1 v1.5 */ len = sizeof(out); - DO(rsa_sign_hash_ex(in, 20, out, &len, LTC_PKCS_1_V1_5, &yarrow_prng, prng_idx, hash_idx, 8, &privKey)); - DO(rsa_verify_hash_ex(out, len, in, 20, LTC_PKCS_1_V1_5, hash_idx, 8, &stat, &pubKey)); + DO(rsa_sign_hash_ex(in, 20, out, &len, LTC_PKCS_1_V1_5, &yarrow_prng, prng_idx, hash_idx, 0, 8, &privKey)); + DO(rsa_verify_hash_ex(out, len, in, 20, LTC_PKCS_1_V1_5, hash_idx, 0, 8, &stat, &pubKey)); /* change a byte */ in[0] ^= 1; - DO(rsa_verify_hash_ex(out, len, in, 20, LTC_PKCS_1_V1_5, hash_idx, 8, &stat2, &pubKey)); + DO(rsa_verify_hash_ex(out, len, in, 20, LTC_PKCS_1_V1_5, hash_idx, 0, 8, &stat2, &pubKey)); if (!(stat == 1 && stat2 == 0)) { fprintf(stderr, "rsa_verify_hash_ex failed, %d, %d", stat, stat2); @@ -721,9 +721,9 @@ print_hex("q", tmp, len); len = sizeof(in); len2 = sizeof(out); /* (1) */ - DO(rsa_sign_hash_ex(p, 20, p2, &len2, LTC_PKCS_1_V1_5, &yarrow_prng, prng_idx, hash_idx, 8, &privKey)); + DO(rsa_sign_hash_ex(p, 20, p2, &len2, LTC_PKCS_1_V1_5, &yarrow_prng, prng_idx, hash_idx, 0, 8, &privKey)); /* (2) */ - DOX(rsa_verify_hash_ex(p2, len2, p, 20, LTC_PKCS_1_V1_5, hash_idx, -1, &stat, &pubKey), "should succeed"); + DOX(rsa_verify_hash_ex(p2, len2, p, 20, LTC_PKCS_1_V1_5, hash_idx, 0, -1, &stat, &pubKey), "should succeed"); DOX(stat == 1?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, "should succeed"); len3 = sizeof(tmp); /* (3) */ @@ -757,7 +757,7 @@ print_hex("q", tmp, len); len3 = sizeof(tmp); /* (6) */ - SHOULD_FAIL(rsa_verify_hash_ex(p2, len2, p, 20, LTC_PKCS_1_V1_5, hash_idx, -1, &stat, &pubKey)); + SHOULD_FAIL(rsa_verify_hash_ex(p2, len2, p, 20, LTC_PKCS_1_V1_5, hash_idx, -1, -1, &stat, &pubKey)); DOX(stat == 0?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, "should fail"); } rsa_free(&key); From 5af1b84daab698055cc51b0a11cf6dd7844e908b Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Tue, 26 Aug 2025 18:40:23 +0200 Subject: [PATCH 07/17] Add support for RSA-PSS keys Signed-off-by: Steffen Jaeckel --- src/headers/tomcrypt_custom.h | 4 + src/headers/tomcrypt_pk.h | 16 +- src/headers/tomcrypt_private.h | 17 +- src/misc/crypt/crypt.c | 1 + src/pk/asn1/oid/pk_get.c | 46 +++-- .../x509_decode_public_key_from_certificate.c | 75 +++++--- src/pk/asn1/x509/x509_decode_spki.c | 62 ++++--- src/pk/asn1/x509/x509_get_pka.c | 4 +- src/pk/asn1/x509/x509_import_spki.c | 4 +- src/pk/pka_key.c | 1 + src/pk/rsa/rsa_decrypt_key.c | 12 +- src/pk/rsa/rsa_encrypt_key.c | 12 +- src/pk/rsa/rsa_import.c | 66 +++---- src/pk/rsa/rsa_import_x509.c | 161 +++++++++++++++++- src/pk/rsa/rsa_key.c | 85 +++++++++ src/pk/rsa/rsa_sign_hash.c | 13 +- src/pk/rsa/rsa_verify_hash.c | 14 +- 17 files changed, 441 insertions(+), 152 deletions(-) diff --git a/src/headers/tomcrypt_custom.h b/src/headers/tomcrypt_custom.h index 685a57bfb..4785d1496 100644 --- a/src/headers/tomcrypt_custom.h +++ b/src/headers/tomcrypt_custom.h @@ -604,6 +604,10 @@ /* Maximum recursion limit when processing nested ASN.1 types. */ #define LTC_DER_MAX_RECURSION 30 #endif + #ifndef LTC_DER_OID_DEFAULT_NODES + /* Default number of nodes when decoding an OID. */ + #define LTC_DER_OID_DEFAULT_NODES 12 + #endif #endif #if defined(LTC_MECC) || defined(LTC_MRSA) || defined(LTC_MDSA) || defined(LTC_SSH) diff --git a/src/headers/tomcrypt_pk.h b/src/headers/tomcrypt_pk.h index beac9fcc4..aeb2188c0 100644 --- a/src/headers/tomcrypt_pk.h +++ b/src/headers/tomcrypt_pk.h @@ -40,6 +40,7 @@ enum ltc_pka_id { LTC_PKA_X25519, LTC_PKA_ED25519, LTC_PKA_DH, + LTC_PKA_RSA_PSS, LTC_PKA_NUM }; @@ -62,7 +63,18 @@ int rand_prime(void *N, long len, prng_state *prng, int wprng); /* ---- RSA ---- */ #ifdef LTC_MRSA -/** RSA PKCS style key */ +typedef struct ltc_rsa_parameters { + /** PSS/OAEP or PKCS #1 v1.5 style + * 0 -> PKCS #1 v1.5, 1 -> PSS/OAEP */ + int pss_oaep; + /** saltLength is only defined for PSS + * If saltLength == 0 -> OAEP, else -> PSS */ + unsigned long saltlen; + /** hash and MGF hash algorithms */ + const char *hash_alg, *mgf1_hash_alg; +} ltc_rsa_parameters; + +/** RSA key */ typedef struct Rsa_key { /** Type of key, PK_PRIVATE or PK_PUBLIC */ int type; @@ -82,6 +94,8 @@ typedef struct Rsa_key { void *dP; /** The d mod (q - 1) CRT param */ void *dQ; + /** Further parameters of the RSA key */ + ltc_rsa_parameters params; } rsa_key; int rsa_make_key(prng_state *prng, int wprng, int size, long e, rsa_key *key); diff --git a/src/headers/tomcrypt_private.h b/src/headers/tomcrypt_private.h index 4fd749dcf..39b34caf4 100644 --- a/src/headers/tomcrypt_private.h +++ b/src/headers/tomcrypt_private.h @@ -60,6 +60,9 @@ enum ltc_oid_id { LTC_OID_X25519, LTC_OID_ED25519, LTC_OID_DH, + LTC_OID_RSA_OAEP, + LTC_OID_RSA_MGF1, + LTC_OID_RSA_PSS, LTC_OID_NUM }; @@ -411,8 +414,14 @@ int pk_oid_cmp_with_ulong(const char *o1, const unsigned long *o2, unsigned long /* ---- DH Routines ---- */ #ifdef LTC_MRSA +typedef enum ltc_rsa_op { + LTC_RSA_CRYPT, + LTC_RSA_SIGN +} ltc_rsa_op; int rsa_init(rsa_key *key); void rsa_shrink_key(rsa_key *key); +int rsa_key_valid_op(const rsa_key *key, ltc_rsa_op op, int padding, int hash_idx); +int rsa_params_equal(const ltc_rsa_parameters *a, const ltc_rsa_parameters *b); int rsa_make_key_bn_e(prng_state *prng, int wprng, int size, void *e, rsa_key *key); /* used by op-tee */ int rsa_import_pkcs1(const unsigned char *in, unsigned long inlen, rsa_key *key); @@ -647,7 +656,11 @@ int x509_decode_public_key_from_certificate(const unsigned char *in, unsigned lo enum ltc_oid_id algorithm, ltc_asn1_type param_type, ltc_asn1_list* parameters, unsigned long *parameters_len, public_key_decode_cb callback, void *ctx); -int x509_decode_spki(const unsigned char *in, unsigned long inlen, ltc_asn1_list **out, ltc_asn1_list **spki); +int x509_decode_spki(const unsigned char *in, unsigned long inlen, ltc_asn1_list **out, const ltc_asn1_list **spki); +int x509_process_public_key_from_spki(const unsigned char *in, unsigned long inlen, + enum ltc_oid_id algorithm, ltc_asn1_type param_type, + ltc_asn1_list* parameters, unsigned long *parameters_len, + public_key_decode_cb callback, void *ctx); /* SUBJECT PUBLIC KEY INFO */ int x509_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen, @@ -658,7 +671,7 @@ int x509_decode_subject_public_key_info(const unsigned char *in, unsigned long i enum ltc_oid_id algorithm, void *public_key, unsigned long *public_key_len, ltc_asn1_type parameters_type, ltc_asn1_list* parameters, unsigned long *parameters_len); -int x509_get_pka(ltc_asn1_list *pub, enum ltc_pka_id *pka); +int x509_get_pka(const ltc_asn1_list *pub, enum ltc_pka_id *pka); int x509_import_spki(const unsigned char *asn1_cert, unsigned long asn1_len, ltc_pka_key *k, ltc_asn1_list **root); int pk_oid_cmp_with_asn1(const char *o1, const ltc_asn1_list *o2); diff --git a/src/misc/crypt/crypt.c b/src/misc/crypt/crypt.c index 61b5cd050..b16d6318a 100644 --- a/src/misc/crypt/crypt.c +++ b/src/misc/crypt/crypt.c @@ -455,6 +455,7 @@ const char *crypt_build_settings = #if defined(LTC_DER) " DER " " " NAME_VALUE(LTC_DER_MAX_RECURSION) " " + " " NAME_VALUE(LTC_DER_OID_DEFAULT_NODES) " " #endif #if defined(LTC_PKCS_1) " PKCS#1 " diff --git a/src/pk/asn1/oid/pk_get.c b/src/pk/asn1/oid/pk_get.c index 1fd5872e2..81a1b2f3e 100644 --- a/src/pk/asn1/oid/pk_get.c +++ b/src/pk/asn1/oid/pk_get.c @@ -7,18 +7,22 @@ typedef struct { enum ltc_oid_id id; enum ltc_pka_id pka; - const char* oid; + const char *hash; + const char *oid; } oid_table_entry; static const oid_table_entry pka_oids[] = { - { LTC_OID_UNDEF, LTC_PKA_UNDEF, NULL }, - { LTC_OID_RSA, LTC_PKA_RSA, "1.2.840.113549.1.1.1" }, - { LTC_OID_DSA, LTC_PKA_DSA, "1.2.840.10040.4.1" }, - { LTC_OID_EC, LTC_PKA_EC, "1.2.840.10045.2.1" }, - { LTC_OID_EC_PRIMEF, LTC_PKA_EC, "1.2.840.10045.1.1" }, - { LTC_OID_X25519, LTC_PKA_X25519, "1.3.101.110" }, - { LTC_OID_ED25519, LTC_PKA_ED25519, "1.3.101.112" }, - { LTC_OID_DH, LTC_PKA_DH, "1.2.840.113549.1.3.1" }, + { LTC_OID_UNDEF, LTC_PKA_UNDEF, NULL, NULL }, + { LTC_OID_RSA, LTC_PKA_RSA, NULL, "1.2.840.113549.1.1.1" }, + { LTC_OID_DSA, LTC_PKA_DSA, NULL, "1.2.840.10040.4.1" }, + { LTC_OID_EC, LTC_PKA_EC, NULL, "1.2.840.10045.2.1" }, + { LTC_OID_EC_PRIMEF, LTC_PKA_EC, NULL, "1.2.840.10045.1.1" }, + { LTC_OID_X25519, LTC_PKA_X25519, NULL, "1.3.101.110" }, + { LTC_OID_ED25519, LTC_PKA_ED25519, NULL, "1.3.101.112" }, + { LTC_OID_DH, LTC_PKA_DH, NULL, "1.2.840.113549.1.3.1" }, + { LTC_OID_RSA_OAEP, LTC_PKA_RSA, NULL, "1.2.840.113549.1.1.7" }, + { LTC_OID_RSA_MGF1, LTC_PKA_RSA, NULL, "1.2.840.113549.1.1.8" }, + { LTC_OID_RSA_PSS, LTC_PKA_RSA_PSS, NULL, "1.2.840.113549.1.1.10" }, }; static LTC_INLINE const oid_table_entry* s_get_entry(enum ltc_oid_id id) @@ -43,21 +47,35 @@ int pk_get_oid(enum ltc_oid_id id, const char **st) return CRYPT_INVALID_ARG; } -/* - Returns the PKA ID requested. - @return CRYPT_OK if valid -*/ -int pk_get_pka_id(enum ltc_oid_id id, enum ltc_pka_id *pka) +static LTC_INLINE int s_get_values(enum ltc_oid_id id, enum ltc_pka_id *pka, const char **hash) { const oid_table_entry* e = s_get_entry(id); LTC_ARGCHK(pka != NULL); if (e != NULL) { *pka = e->pka; + if (hash) { + *hash = e->hash; + } else if (e->hash) { + /* If we don't want the hash result, but the entry has a hash, we're most likely + * confused and we prefer to stop processing then, instead of continuing with a + * maybe wrong assumption. + */ + return CRYPT_INVALID_ARG; + } return CRYPT_OK; } return CRYPT_INVALID_ARG; } +/* + Returns the PKA ID requested. + @return CRYPT_OK if valid +*/ +int pk_get_pka_id(enum ltc_oid_id id, enum ltc_pka_id *pka) +{ + return s_get_values(id, pka, NULL); +} + /* Returns the OID ID requested. @return CRYPT_OK if valid diff --git a/src/pk/asn1/x509/x509_decode_public_key_from_certificate.c b/src/pk/asn1/x509/x509_decode_public_key_from_certificate.c index 45a1c6f60..65623a956 100644 --- a/src/pk/asn1/x509/x509_decode_public_key_from_certificate.c +++ b/src/pk/asn1/x509/x509_decode_public_key_from_certificate.c @@ -10,7 +10,7 @@ #ifdef LTC_DER /** - Try to decode the public key from a X.509 certificate + Process the public key from the SubjectPublicKeyInfo of a X.509 certificate @param in The input buffer @param inlen The length of the input buffer @param algorithm One out of the enum #public_key_algorithms @@ -19,53 +19,82 @@ @param parameters_len [in/out] The number of parameters to include @param callback The callback @param ctx The context passed to the callback - @return CRYPT_OK on success, - CRYPT_NOP if no SubjectPublicKeyInfo was found, - another error if decoding or memory allocation failed + @return CRYPT_OK on success */ -int x509_decode_public_key_from_certificate(const unsigned char *in, unsigned long inlen, - enum ltc_oid_id algorithm, ltc_asn1_type param_type, - ltc_asn1_list* parameters, unsigned long *parameters_len, - public_key_decode_cb callback, void *ctx) +int x509_process_public_key_from_spki(const unsigned char *in, unsigned long inlen, + enum ltc_oid_id algorithm, ltc_asn1_type param_type, + ltc_asn1_list* parameters, unsigned long *parameters_len, + public_key_decode_cb callback, void *ctx) { int err; unsigned char *tmpbuf = NULL; unsigned long tmpbuf_len; - ltc_asn1_list *decoded_list = NULL, *spki; - - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(inlen != 0); - LTC_ARGCHK(callback != NULL); - if ((err = x509_decode_spki(in, inlen, &decoded_list, &spki)) != CRYPT_OK) { - return err; - } + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(callback != NULL); if (algorithm == LTC_OID_EC) { - err = callback(spki->data, spki->size, ctx); + err = callback(in, inlen, ctx); } else { tmpbuf_len = inlen; tmpbuf = XCALLOC(1, tmpbuf_len); if (tmpbuf == NULL) { - err = CRYPT_MEM; - goto LBL_OUT; + return CRYPT_MEM; } - err = x509_decode_subject_public_key_info(spki->data, spki->size, + err = x509_decode_subject_public_key_info(in, inlen, algorithm, tmpbuf, &tmpbuf_len, param_type, parameters, parameters_len); if (err == CRYPT_OK) { err = callback(tmpbuf, tmpbuf_len, ctx); - goto LBL_OUT; } } -LBL_OUT: - if (decoded_list) der_free_sequence_flexi(decoded_list); if (tmpbuf != NULL) XFREE(tmpbuf); return err; } +/** + Try to decode the public key from a X.509 certificate + @param in The input buffer + @param inlen The length of the input buffer + @param algorithm One out of the enum #public_key_algorithms + @param param_type The parameters' type out of the enum ltc_asn1_type + @param parameters The parameters to include + @param parameters_len [in/out] The number of parameters to include + @param callback The callback + @param ctx The context passed to the callback + @return CRYPT_OK on success, + CRYPT_NOP if no SubjectPublicKeyInfo was found, + another error if decoding or memory allocation failed +*/ +int x509_decode_public_key_from_certificate(const unsigned char *in, unsigned long inlen, + enum ltc_oid_id algorithm, ltc_asn1_type param_type, + ltc_asn1_list* parameters, unsigned long *parameters_len, + public_key_decode_cb callback, void *ctx) +{ + int err; + ltc_asn1_list *decoded_list; + const ltc_asn1_list *spki; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(inlen != 0); + LTC_ARGCHK(callback != NULL); + + if ((err = x509_decode_spki(in, inlen, &decoded_list, &spki)) != CRYPT_OK) { + return err; + } + + err = x509_process_public_key_from_spki(spki->data, spki->size, + algorithm, param_type, + parameters, parameters_len, + callback, ctx); + + if (decoded_list) der_free_sequence_flexi(decoded_list); + + return err; +} + #endif diff --git a/src/pk/asn1/x509/x509_decode_spki.c b/src/pk/asn1/x509/x509_decode_spki.c index 147aaf1c6..144441cd2 100644 --- a/src/pk/asn1/x509/x509_decode_spki.c +++ b/src/pk/asn1/x509/x509_decode_spki.c @@ -26,10 +26,10 @@ @param spki [out] A pointer to the SubjectPublicKeyInfo @return CRYPT_OK on success, CRYPT_NOP if no SubjectPublicKeyInfo was found, another error if decoding failed */ -int x509_decode_spki(const unsigned char *in, unsigned long inlen, ltc_asn1_list **out, ltc_asn1_list **spki) +int x509_decode_spki(const unsigned char *in, unsigned long inlen, ltc_asn1_list **out, const ltc_asn1_list **spki) { int err; - unsigned long tmp_inlen; + unsigned long tmp_inlen, n, element_is_spki; ltc_asn1_list *decoded_list = NULL, *l; LTC_ARGCHK(in != NULL); @@ -49,29 +49,49 @@ int x509_decode_spki(const unsigned char *in, unsigned long inlen, ltc_asn1_list if ((l->type == LTC_ASN1_SEQUENCE) && (l->child != NULL)) { l = l->child; if ((l->type == LTC_ASN1_SEQUENCE) && (l->child != NULL)) { + /* TBSCertificate ::= SEQUENCE { + * version [0] EXPLICIT Version DEFAULT v1, + * serialNumber CertificateSerialNumber, + * signature AlgorithmIdentifier, + * issuer Name, + * validity Validity, + * subject Name, + * subjectPublicKeyInfo SubjectPublicKeyInfo, + * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, + * -- If present, version MUST be v2 or v3 + * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, + * -- If present, version MUST be v2 or v3 + * extensions [3] EXPLICIT Extensions OPTIONAL + * -- If present, version MUST be v3 + * } + */ l = l->child; - /* Move forward in the tree until we find this combination - ... - SEQUENCE - SEQUENCE - OBJECT IDENTIFIER - NULL - BIT STRING + /* `l` points now either to 'version' or 'serialNumber', depending on + * whether 'version' is included or defaults to 'v1'. + * 'version' is represented as a LTC_ASN1_CUSTOM_TYPE + * 'serialNumber' is represented as an LTC_ASN1_INTEGER + * Decide now whether to move 5 or 6 elements forward until + * `l` should point to subjectPublicKeyInfo. */ - do { - /* The additional check for l->data is there to make sure - * we won't try to decode a list that has been 'shrunk' - */ - if ((l->type == LTC_ASN1_SEQUENCE) - && (l->data != NULL) - && LOOKS_LIKE_SPKI(l->child)) { - *out = decoded_list; - *spki = l; - return CRYPT_OK; - } + if (l->type == LTC_ASN1_CUSTOM_TYPE) + element_is_spki = 6; + else + element_is_spki = 5; + for (n = 0; n < element_is_spki && l; ++n) { l = l->next; - } while(l); + } + /* The additional check for l->data is there to make sure + * we won't try to decode a list that has been 'shrunk' + */ + if ((l != NULL) + && (l->type == LTC_ASN1_SEQUENCE) + && (l->data != NULL) + && LOOKS_LIKE_SPKI(l->child)) { + *out = decoded_list; + *spki = l; + return CRYPT_OK; + } } } } diff --git a/src/pk/asn1/x509/x509_get_pka.c b/src/pk/asn1/x509/x509_get_pka.c index 23a12edd7..0236c761e 100644 --- a/src/pk/asn1/x509/x509_get_pka.c +++ b/src/pk/asn1/x509/x509_get_pka.c @@ -9,7 +9,7 @@ #ifdef LTC_DER -int x509_get_pka(ltc_asn1_list *pub, enum ltc_pka_id *pka) +int x509_get_pka(const ltc_asn1_list *pub, enum ltc_pka_id *pka) { der_flexi_check flexi_should[4]; ltc_asn1_list *seqid, *id = NULL; @@ -17,7 +17,7 @@ int x509_get_pka(ltc_asn1_list *pub, enum ltc_pka_id *pka) int err; unsigned long n = 0; LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_SEQUENCE, &seqid); - LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_BIT_STRING, NULL); + LTC_SET_DER_FLEXI_CHECK_OPT(flexi_should, n++, LTC_ASN1_BIT_STRING, NULL); LTC_SET_DER_FLEXI_CHECK(flexi_should, n, LTC_ASN1_EOL, NULL); if ((err = der_flexi_sequence_cmp(pub, flexi_should)) != CRYPT_OK) { return err; diff --git a/src/pk/asn1/x509/x509_import_spki.c b/src/pk/asn1/x509/x509_import_spki.c index 1e7f3b2ce..0132068d5 100644 --- a/src/pk/asn1/x509/x509_import_spki.c +++ b/src/pk/asn1/x509/x509_import_spki.c @@ -14,6 +14,7 @@ typedef int (*import_fn)(const unsigned char *, unsigned long, void*); static const import_fn s_import_x509_fns[LTC_PKA_NUM] = { #ifdef LTC_MRSA [LTC_PKA_RSA] = (import_fn)rsa_import_x509, + [LTC_PKA_RSA_PSS] = (import_fn)rsa_import_x509, #endif #ifdef LTC_MECC [LTC_PKA_EC] = (import_fn)ecc_import_x509, @@ -27,7 +28,8 @@ static const import_fn s_import_x509_fns[LTC_PKA_NUM] = { int x509_import_spki(const unsigned char *asn1_cert, unsigned long asn1_len, ltc_pka_key *k, ltc_asn1_list **root) { enum ltc_pka_id pka = LTC_PKA_UNDEF; - ltc_asn1_list *d, *spki; + ltc_asn1_list *d; + const ltc_asn1_list *spki; int err; if ((err = x509_decode_spki(asn1_cert, asn1_len, &d, &spki)) != CRYPT_OK) { return err; diff --git a/src/pk/pka_key.c b/src/pk/pka_key.c index d88ee3d30..c682cfcbf 100644 --- a/src/pk/pka_key.c +++ b/src/pk/pka_key.c @@ -30,6 +30,7 @@ void pka_key_free(ltc_pka_key *key) #endif break; case LTC_PKA_RSA: + case LTC_PKA_RSA_PSS: #if defined(LTC_MRSA) rsa_free(&key->u.rsa); #endif diff --git a/src/pk/rsa/rsa_decrypt_key.c b/src/pk/rsa/rsa_decrypt_key.c index d8e7a546f..a36ecb021 100644 --- a/src/pk/rsa/rsa_decrypt_key.c +++ b/src/pk/rsa/rsa_decrypt_key.c @@ -45,16 +45,8 @@ int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen *stat = 0; /* valid padding? */ - if ((padding != LTC_PKCS_1_V1_5) && - (padding != LTC_PKCS_1_OAEP)) { - return CRYPT_PK_INVALID_PADDING; - } - - if (padding == LTC_PKCS_1_OAEP) { - /* valid hash ? */ - if ((err = hash_is_valid(mgf_hash)) != CRYPT_OK) { - return err; - } + if ((err = rsa_key_valid_op(key, LTC_RSA_CRYPT, padding, mgf_hash)) != CRYPT_OK) { + return err; } /* get modulus len in bits */ diff --git a/src/pk/rsa/rsa_encrypt_key.c b/src/pk/rsa/rsa_encrypt_key.c index 17dd1af5d..83fb2c5a6 100644 --- a/src/pk/rsa/rsa_encrypt_key.c +++ b/src/pk/rsa/rsa_encrypt_key.c @@ -41,9 +41,8 @@ int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen, LTC_ARGCHK(key != NULL); /* valid padding? */ - if ((padding != LTC_PKCS_1_V1_5) && - (padding != LTC_PKCS_1_OAEP)) { - return CRYPT_PK_INVALID_PADDING; + if ((err = rsa_key_valid_op(key, LTC_RSA_CRYPT, padding, mgf_hash)) != CRYPT_OK) { + return err; } /* valid prng? */ @@ -51,13 +50,6 @@ int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen, return err; } - if (padding == LTC_PKCS_1_OAEP) { - /* valid hash? */ - if ((err = hash_is_valid(mgf_hash)) != CRYPT_OK) { - return err; - } - } - /* get modulus len in bits */ modulus_bitlen = ltc_mp_count_bits( (key->N)); diff --git a/src/pk/rsa/rsa_import.c b/src/pk/rsa/rsa_import.c index 1240a77e7..a52ff154f 100644 --- a/src/pk/rsa/rsa_import.c +++ b/src/pk/rsa/rsa_import.c @@ -9,6 +9,18 @@ #ifdef LTC_MRSA +#ifndef S_RSA_DECODE +#define S_RSA_DECODE +static int s_rsa_decode(const unsigned char *in, unsigned long inlen, rsa_key *key) +{ + /* now it should be SEQUENCE { INTEGER, INTEGER } */ + return der_decode_sequence_multi(in, inlen, + LTC_ASN1_INTEGER, 1UL, key->N, + LTC_ASN1_INTEGER, 1UL, key->e, + LTC_ASN1_EOL, 0UL, NULL); +} +#endif + /** Import an RSAPublicKey or RSAPrivateKey as defined in PKCS #1 v2.1 [two-prime only] @@ -33,10 +45,7 @@ int rsa_import_pkcs1(const unsigned char *in, unsigned long inlen, rsa_key *key) /* the version would fit into an LTC_ASN1_SHORT_INTEGER * so we try to decode as a public key */ - if ((err = der_decode_sequence_multi(in, inlen, - LTC_ASN1_INTEGER, 1UL, key->N, - LTC_ASN1_INTEGER, 1UL, key->e, - LTC_ASN1_EOL, 0UL, NULL)) == CRYPT_OK) { + if ((err = s_rsa_decode(in, inlen, key)) == CRYPT_OK) { key->type = PK_PUBLIC; } goto LBL_OUT; @@ -85,57 +94,30 @@ int rsa_import_pkcs1(const unsigned char *in, unsigned long inlen, rsa_key *key) int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key) { int err; - unsigned char *tmpbuf=NULL; - unsigned long tmpbuf_len, len; LTC_ARGCHK(in != NULL); LTC_ARGCHK(key != NULL); LTC_ARGCHK(ltc_mp.name != NULL); + if ((err = rsa_import_x509(in, inlen, key)) == CRYPT_OK) { /* SubjectPublicKeyInfo format */ + return CRYPT_OK; + } + /* init key */ if ((err = rsa_init(key)) != CRYPT_OK) { return err; } - /* see if the OpenSSL DER format RSA public key will work */ - tmpbuf_len = inlen; - tmpbuf = XCALLOC(1, tmpbuf_len); - if (tmpbuf == NULL) { - err = CRYPT_MEM; - goto LBL_ERR; - } - - len = 0; - err = x509_decode_subject_public_key_info(in, inlen, - LTC_OID_RSA, tmpbuf, &tmpbuf_len, - LTC_ASN1_NULL, NULL, &len); - - if (err == CRYPT_OK) { /* SubjectPublicKeyInfo format */ - - /* now it should be SEQUENCE { INTEGER, INTEGER } */ - if ((err = der_decode_sequence_multi(tmpbuf, tmpbuf_len, - LTC_ASN1_INTEGER, 1UL, key->N, - LTC_ASN1_INTEGER, 1UL, key->e, - LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { - goto LBL_ERR; + if ((err = x509_process_public_key_from_spki(in, inlen, + LTC_OID_RSA, + LTC_ASN1_NULL, NULL, NULL, + (public_key_decode_cb)s_rsa_decode, key)) != CRYPT_OK) { + /* not SSL public key, try to match against PKCS #1 standards */ + if ((err = rsa_import_pkcs1(in, inlen, key)) != CRYPT_OK) { + rsa_free(key); } - key->type = PK_PUBLIC; - err = CRYPT_OK; - goto LBL_FREE; } - /* not SSL public key, try to match against PKCS #1 standards */ - if ((err = rsa_import_pkcs1(in, inlen, key)) == CRYPT_OK) { - goto LBL_FREE; - } - -LBL_ERR: - rsa_free(key); - -LBL_FREE: - if (tmpbuf != NULL) { - XFREE(tmpbuf); - } return err; } diff --git a/src/pk/rsa/rsa_import_x509.c b/src/pk/rsa/rsa_import_x509.c index 4d157ead4..f2a489e9e 100644 --- a/src/pk/rsa/rsa_import_x509.c +++ b/src/pk/rsa/rsa_import_x509.c @@ -9,6 +9,8 @@ #ifdef LTC_MRSA +#ifndef S_RSA_DECODE +#define S_RSA_DECODE static int s_rsa_decode(const unsigned char *in, unsigned long inlen, rsa_key *key) { /* now it should be SEQUENCE { INTEGER, INTEGER } */ @@ -17,6 +19,153 @@ static int s_rsa_decode(const unsigned char *in, unsigned long inlen, rsa_key *k LTC_ASN1_INTEGER, 1UL, key->e, LTC_ASN1_EOL, 0UL, NULL); } +#endif + +typedef struct rsa_pss_parameters_data { + ltc_asn1_list params[4], inner[4], hash_alg[2], mgf[2], mgf_hash_alg[2]; + unsigned long hash_alg_oid[LTC_DER_OID_DEFAULT_NODES]; + unsigned long mgf_alg_oid[LTC_DER_OID_DEFAULT_NODES]; + unsigned long mgf1_hash_alg_oid[LTC_DER_OID_DEFAULT_NODES]; + unsigned long salt_length, trailer_field; +} rsa_pss_parameters_data; + +static LTC_INLINE void s_rsa_pss_parameters_data_setup(rsa_pss_parameters_data *d) +{ + unsigned long n; + /* RSASSA-PSS + * + * RSASSA-PSS-params ::= SEQUENCE { + * hashAlgorithm [0] HashAlgorithm DEFAULT sha1, + * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1, + * saltLength [2] INTEGER DEFAULT 20, + * trailerField [3] TrailerField DEFAULT trailerFieldBC + * } + */ + + /* HashAlgorithm ::= AlgorithmIdentifier { + * {OAEP-PSSDigestAlgorithms} + * } + */ + LTC_SET_ASN1(d->hash_alg, 0, LTC_ASN1_OBJECT_IDENTIFIER, d->hash_alg_oid, LTC_ARRAY_SIZE(d->hash_alg_oid)); + LTC_SET_ASN1(d->hash_alg, 1, LTC_ASN1_NULL, NULL, 0); + d->hash_alg[1].optional = 1; + + /* MaskGenAlgorithm ::= AlgorithmIdentifier { {PKCS1MGFAlgorithms} } */ + LTC_SET_ASN1(d->mgf_hash_alg, 0, LTC_ASN1_OBJECT_IDENTIFIER, d->mgf1_hash_alg_oid, LTC_ARRAY_SIZE(d->mgf1_hash_alg_oid)); + LTC_SET_ASN1(d->mgf_hash_alg, 1, LTC_ASN1_NULL, NULL, 0); + d->mgf_hash_alg[1].optional = 1; + + /* PKCS1MGFAlgorithms ALGORITHM-IDENTIFIER ::= { + * { OID id-mgf1 PARAMETERS HashAlgorithm }, + * ... -- Allows for future expansion -- + * } + */ + LTC_SET_ASN1(d->mgf, 0, LTC_ASN1_OBJECT_IDENTIFIER, d->mgf_alg_oid, LTC_ARRAY_SIZE(d->mgf_alg_oid)); + LTC_SET_ASN1(d->mgf, 1, LTC_ASN1_SEQUENCE, d->mgf_hash_alg, LTC_ARRAY_SIZE(d->mgf_hash_alg)); + + LTC_SET_ASN1(d->inner, 0, LTC_ASN1_SEQUENCE, d->hash_alg, LTC_ARRAY_SIZE(d->hash_alg)); + LTC_SET_ASN1(d->inner, 1, LTC_ASN1_SEQUENCE, d->mgf, LTC_ARRAY_SIZE(d->mgf)); + LTC_SET_ASN1(d->inner, 2, LTC_ASN1_SHORT_INTEGER, &d->salt_length, 1UL); + LTC_SET_ASN1(d->inner, 3, LTC_ASN1_SHORT_INTEGER, &d->trailer_field, 1UL); + + LTC_SET_ASN1_CUSTOM_CONSTRUCTED(d->params, 0, LTC_ASN1_CL_CONTEXT_SPECIFIC, 0, d->inner); /* context specific 0 */ + LTC_SET_ASN1_CUSTOM_CONSTRUCTED(d->params, 1, LTC_ASN1_CL_CONTEXT_SPECIFIC, 1, d->inner + 1); /* context specific 1 */ + LTC_SET_ASN1_CUSTOM_CONSTRUCTED(d->params, 2, LTC_ASN1_CL_CONTEXT_SPECIFIC, 2, d->inner + 2); /* context specific 2 */ + LTC_SET_ASN1_CUSTOM_CONSTRUCTED(d->params, 3, LTC_ASN1_CL_CONTEXT_SPECIFIC, 3, d->inner + 3); /* context specific 3 */ + for (n = 0; n < 4; ++n) { + d->params[n].optional = 1; + } +} + +int rsa_decode_parameters(const ltc_asn1_list *parameters, ltc_rsa_parameters *rsa_params) +{ + rsa_pss_parameters_data d; + unsigned long n; + enum ltc_oid_id oid_id; + int err, idx; + + s_rsa_pss_parameters_data_setup(&d); + + if ((err = der_decode_sequence(parameters->data, parameters->size, d.params, 4)) != CRYPT_OK) { + return err; + } + + rsa_params->saltlen = 20; + rsa_params->hash_alg = rsa_params->mgf1_hash_alg = "sha1"; + + for (n = 0; n < 4; ++n) { + if (d.params[n].used == 0) + continue; + switch (n) { + case 0: + idx = find_hash_oid(d.hash_alg->data, d.hash_alg->size); + if (idx == -1) { + return CRYPT_INVALID_HASH; + } + rsa_params->hash_alg = hash_descriptor[idx].name; + break; + case 1: + if ((err = pk_get_oid_from_asn1(&d.mgf[0], &oid_id)) != CRYPT_OK) { + return err; + } + if (oid_id != LTC_OID_RSA_MGF1) { + return CRYPT_PK_ASN1_ERROR; + } + idx = find_hash_oid(d.mgf_hash_alg->data, d.mgf_hash_alg->size); + if (idx == -1) { + return CRYPT_INVALID_HASH; + } + rsa_params->mgf1_hash_alg = hash_descriptor[idx].name; + break; + case 2: + rsa_params->saltlen = d.salt_length; + break; + case 3: + if (d.trailer_field != 1) { + return CRYPT_PK_ASN1_ERROR; + } + break; + default: + return CRYPT_PK_ASN1_ERROR; + } + } + + + rsa_params->pss_oaep = 1; + + return CRYPT_OK; +} + +static int s_rsa_import_pss(const unsigned char *in, unsigned long inlen, rsa_key *key) +{ + rsa_pss_parameters_data d; + ltc_asn1_list *decoded_list; + const ltc_asn1_list *spki; + int err; + unsigned long n_params = LTC_ARRAY_SIZE(d.params); + + if ((err = x509_process_public_key_from_spki(in, inlen, + LTC_OID_RSA_PSS, + LTC_ASN1_NULL, NULL, NULL, + (public_key_decode_cb)s_rsa_decode, key)) != CRYPT_OK) { + if ((err = x509_decode_spki(in, inlen, &decoded_list, &spki)) != CRYPT_OK) { + return err; + } + if ((err = x509_process_public_key_from_spki(spki->data, spki->size, + LTC_OID_RSA_PSS, + LTC_ASN1_NULL, NULL, NULL, + (public_key_decode_cb)s_rsa_decode, key)) != CRYPT_OK) { + s_rsa_pss_parameters_data_setup(&d); + err = x509_process_public_key_from_spki(spki->data, spki->size, + LTC_OID_RSA_PSS, + LTC_ASN1_SEQUENCE, d.params, &n_params, + (public_key_decode_cb)s_rsa_decode, key); + } + } + + der_free_sequence_flexi(decoded_list); + return err; +} /** Import an RSA key from a X.509 certificate @@ -41,12 +190,18 @@ int rsa_import_x509(const unsigned char *in, unsigned long inlen, rsa_key *key) if ((err = x509_decode_public_key_from_certificate(in, inlen, LTC_OID_RSA, LTC_ASN1_NULL, NULL, NULL, - (public_key_decode_cb)s_rsa_decode, key)) != CRYPT_OK) { - rsa_free(key); - } else { + (public_key_decode_cb)s_rsa_decode, key)) == CRYPT_OK) { key->type = PK_PUBLIC; + return CRYPT_OK; } + if ((err = s_rsa_import_pss(in, inlen, key)) == CRYPT_OK) { + key->type = PK_PUBLIC; + return CRYPT_OK; + } + + rsa_free(key); + return err; } diff --git a/src/pk/rsa/rsa_key.c b/src/pk/rsa/rsa_key.c index 7eb21b843..5bb37f7fb 100644 --- a/src/pk/rsa/rsa_key.c +++ b/src/pk/rsa/rsa_key.c @@ -85,6 +85,7 @@ void rsa_shrink_key(rsa_key *key) int rsa_init(rsa_key *key) { LTC_ARGCHK(key != NULL); + XMEMSET(&key->params, 0, sizeof(key->params)); return ltc_mp_init_multi(&key->e, &key->d, &key->N, &key->dQ, &key->dP, &key->qP, &key->p, &key->q, LTC_NULL); } @@ -96,6 +97,90 @@ void rsa_free(rsa_key *key) { LTC_ARGCHKVD(key != NULL); ltc_mp_cleanup_multi(&key->q, &key->p, &key->qP, &key->dP, &key->dQ, &key->N, &key->d, &key->e, LTC_NULL); + XMEMSET(&key->params, 0, sizeof(key->params)); +} + +static LTC_INLINE int s_rsa_key_valid_pss_algs(const rsa_key *key, int padding, int hash_idx) +{ + if (!key->params.pss_oaep) { + return CRYPT_OK; + } + if (padding != LTC_PKCS_1_PSS) { + return CRYPT_PK_TYPE_MISMATCH; + } + if (key->params.hash_alg == NULL || find_hash(key->params.hash_alg) != hash_idx) { + return CRYPT_INVALID_HASH; + } + if (key->params.mgf1_hash_alg == NULL) { + return CRYPT_INVALID_HASH; + } + return hash_is_valid(find_hash(key->params.mgf1_hash_alg)); +} + +static LTC_INLINE int s_rsa_key_valid_sign(const rsa_key *key, int padding, int hash_idx) +{ + if ((padding != LTC_PKCS_1_V1_5) && + (padding != LTC_PKCS_1_PSS) && + (padding != LTC_PKCS_1_V1_5_NA1)) { + return CRYPT_PK_INVALID_PADDING; + } + + if (padding != LTC_PKCS_1_V1_5_NA1) { + int err; + /* valid hash ? */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + } + return s_rsa_key_valid_pss_algs(key, padding, hash_idx); +} + +static LTC_INLINE int s_rsa_key_valid_crypt(const rsa_key *key, int padding, int hash_idx) +{ + if ((padding != LTC_PKCS_1_V1_5) && + (padding != LTC_PKCS_1_OAEP)) { + return CRYPT_PK_INVALID_PADDING; + } + + if (padding == LTC_PKCS_1_OAEP) { + int err; + /* valid hash? */ + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + return err; + } + } + return s_rsa_key_valid_pss_algs(key, padding, hash_idx); +} + +int rsa_key_valid_op(const rsa_key *key, ltc_rsa_op op, int padding, int hash_idx) +{ + switch (op) { + case LTC_RSA_SIGN: + return s_rsa_key_valid_sign(key, padding, hash_idx); + case LTC_RSA_CRYPT: + return s_rsa_key_valid_crypt(key, padding, hash_idx); + default: + return CRYPT_ERROR; + } +} + +int rsa_params_equal(const ltc_rsa_parameters *a, const ltc_rsa_parameters *b) +{ + if (!a->pss_oaep) + return 0; + if (a->pss_oaep != b->pss_oaep) + return 0; + if (a->saltlen != b->saltlen) + return 0; + if (!a->hash_alg || !b->hash_alg) + return 0; + if (XSTRCMP(a->hash_alg, b->hash_alg)) + return 0; + if (!a->mgf1_hash_alg || !b->mgf1_hash_alg) + return 0; + if (XSTRCMP(a->mgf1_hash_alg, b->mgf1_hash_alg)) + return 0; + return 1; } #endif diff --git a/src/pk/rsa/rsa_sign_hash.c b/src/pk/rsa/rsa_sign_hash.c index a7a18036d..4445f712b 100644 --- a/src/pk/rsa/rsa_sign_hash.c +++ b/src/pk/rsa/rsa_sign_hash.c @@ -40,10 +40,8 @@ int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, LTC_ARGCHK(key != NULL); /* valid padding? */ - if ((padding != LTC_PKCS_1_V1_5) && - (padding != LTC_PKCS_1_PSS) && - (padding != LTC_PKCS_1_V1_5_NA1)) { - return CRYPT_PK_INVALID_PADDING; + if ((err = rsa_key_valid_op(key, LTC_RSA_SIGN, padding, hash_idx)) != CRYPT_OK) { + return err; } if (padding == LTC_PKCS_1_PSS) { @@ -53,13 +51,6 @@ int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, } } - if (padding != LTC_PKCS_1_V1_5_NA1) { - /* valid hash ? */ - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { - return err; - } - } - /* get modulus len in bits */ modulus_bitlen = ltc_mp_count_bits((key->N)); diff --git a/src/pk/rsa/rsa_verify_hash.c b/src/pk/rsa/rsa_verify_hash.c index 7303a7b26..ede234497 100644 --- a/src/pk/rsa/rsa_verify_hash.c +++ b/src/pk/rsa/rsa_verify_hash.c @@ -42,18 +42,8 @@ int rsa_verify_hash_ex(const unsigned char *sig, unsigned long sigle *stat = 0; /* valid padding? */ - - if ((padding != LTC_PKCS_1_V1_5) && - (padding != LTC_PKCS_1_PSS) && - (padding != LTC_PKCS_1_V1_5_NA1)) { - return CRYPT_PK_INVALID_PADDING; - } - - if (padding != LTC_PKCS_1_V1_5_NA1) { - /* valid hash ? */ - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { - return err; - } + if ((err = rsa_key_valid_op(key, LTC_RSA_SIGN, padding, hash_idx)) != CRYPT_OK) { + return err; } /* get modulus len in bits */ From 6d49a98362817c5c5924d66f8a830bf3082c85d5 Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Tue, 2 Sep 2025 17:25:03 +0200 Subject: [PATCH 08/17] Add SubjectPublicKeyInfo support to `dsa_import()` Signed-off-by: Steffen Jaeckel --- src/pk/asn1/x509/x509_import_spki.c | 3 + src/pk/dsa/dsa_import.c | 101 +++++++++++++++++++--------- 2 files changed, 74 insertions(+), 30 deletions(-) diff --git a/src/pk/asn1/x509/x509_import_spki.c b/src/pk/asn1/x509/x509_import_spki.c index 0132068d5..73b4dac73 100644 --- a/src/pk/asn1/x509/x509_import_spki.c +++ b/src/pk/asn1/x509/x509_import_spki.c @@ -16,6 +16,9 @@ static const import_fn s_import_x509_fns[LTC_PKA_NUM] = { [LTC_PKA_RSA] = (import_fn)rsa_import_x509, [LTC_PKA_RSA_PSS] = (import_fn)rsa_import_x509, #endif +#ifdef LTC_MDSA + [LTC_PKA_DSA] = (import_fn)dsa_import, +#endif #ifdef LTC_MECC [LTC_PKA_EC] = (import_fn)ecc_import_x509, #endif diff --git a/src/pk/dsa/dsa_import.c b/src/pk/dsa/dsa_import.c index d2c2d49ec..377a10b17 100644 --- a/src/pk/dsa/dsa_import.c +++ b/src/pk/dsa/dsa_import.c @@ -28,6 +28,69 @@ int dsa_import_pkcs1(const unsigned char *in, unsigned long inlen, dsa_key *key) return err; } +static int s_dsa_import_y(const unsigned char *in, unsigned long inlen, dsa_key *key) +{ + return der_decode_integer(in, inlen, key->y); +} + +LTC_INLINE static int s_dsa_set_params(dsa_key *key, ltc_asn1_list *params) +{ + LTC_SET_ASN1(params, 0, LTC_ASN1_INTEGER, key->p, 1UL); + LTC_SET_ASN1(params, 1, LTC_ASN1_INTEGER, key->q, 1UL); + LTC_SET_ASN1(params, 2, LTC_ASN1_INTEGER, key->g, 1UL); + return 3; +} + +static int s_dsa_import_spki(const unsigned char *in, unsigned long inlen, dsa_key *key) +{ + int err; + unsigned char* tmpbuf = NULL; + ltc_asn1_list params[3]; + unsigned long tmpbuf_len = inlen, len; + + len = s_dsa_set_params(key, params); + + tmpbuf = XCALLOC(1, tmpbuf_len); + if (tmpbuf == NULL) { + return CRYPT_MEM; + } + + err = x509_decode_subject_public_key_info(in, inlen, + LTC_OID_DSA, tmpbuf, &tmpbuf_len, + LTC_ASN1_SEQUENCE, params, &len); + if (err != CRYPT_OK) { + goto LBL_ERR; + } + + if ((err = s_dsa_import_y(tmpbuf, tmpbuf_len, key)) != CRYPT_OK) { + goto LBL_ERR; + } + + key->type = PK_PUBLIC; +LBL_ERR: + XFREE(tmpbuf); + return err; +} + +static int s_dsa_import_x509(const unsigned char *in, unsigned long inlen, dsa_key *key) +{ + int err; + ltc_asn1_list params[3]; + unsigned long len; + + len = s_dsa_set_params(key, params); + + if ((err = x509_decode_public_key_from_certificate(in, inlen, + LTC_OID_DSA, + LTC_ASN1_SEQUENCE, params, &len, + (public_key_decode_cb)s_dsa_import_y, key)) == CRYPT_OK) { + key->type = PK_PUBLIC; + return CRYPT_OK; + } + + return err; +} + /** Import a DSA key @param in The binary packet to import from @@ -38,7 +101,6 @@ int dsa_import_pkcs1(const unsigned char *in, unsigned long inlen, dsa_key *key) int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key) { int err, stat; - unsigned char* tmpbuf = NULL; unsigned char flags[1]; LTC_ARGCHK(in != NULL); @@ -86,35 +148,14 @@ int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key) } } - if (dsa_import_pkcs1(in, inlen, key) != CRYPT_OK) { - ltc_asn1_list params[3]; - unsigned long tmpbuf_len = inlen, len; - - LTC_SET_ASN1(params, 0, LTC_ASN1_INTEGER, key->p, 1UL); - LTC_SET_ASN1(params, 1, LTC_ASN1_INTEGER, key->q, 1UL); - LTC_SET_ASN1(params, 2, LTC_ASN1_INTEGER, key->g, 1UL); - len = 3; - - tmpbuf = XCALLOC(1, tmpbuf_len); - if (tmpbuf == NULL) { - return CRYPT_MEM; - } - - err = x509_decode_subject_public_key_info(in, inlen, - LTC_OID_DSA, tmpbuf, &tmpbuf_len, - LTC_ASN1_SEQUENCE, params, &len); - if (err != CRYPT_OK) { - XFREE(tmpbuf); - goto LBL_ERR; - } - - if ((err = der_decode_integer(tmpbuf, tmpbuf_len, key->y)) != CRYPT_OK) { - XFREE(tmpbuf); - goto LBL_ERR; - } - - key->type = PK_PUBLIC; - XFREE(tmpbuf); + if (dsa_import_pkcs1(in, inlen, key) == CRYPT_OK) { + goto LBL_OK; + } + if ((err = s_dsa_import_spki(in, inlen, key)) == CRYPT_OK) { + goto LBL_OK; + } + if ((err = s_dsa_import_x509(in, inlen, key)) != CRYPT_OK) { + goto LBL_ERR; } LBL_OK: From 74a200f9f075acf7d8c071683d0ba1a62573ed7b Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Tue, 2 Sep 2025 17:25:03 +0200 Subject: [PATCH 09/17] Refactor SubjectPublicKeyInfo import Slightly minimize both space and time when importing a SubjectPublicKeyInfo. Time for ECC keys stays the same. Those tests were done with X.509 support already available, but later these commits were split up to be independent of the X.509 feature. Running the entire set of pem files through `x509_verify` via [0] resp. the timing app via [1] resulted in the following data: Before this patch: [0] ``` ==1031519== HEAP SUMMARY: ==1031519== in use at exit: 0 bytes in 0 blocks ==1031519== total heap usage: 424,057 allocs, 424,057 frees, 73,527,730 bytes allocated ``` [1] ``` x509 cert-rsa-pss.pem : 50021 cycles x509 LTC_CA.pem : 10335 cycles x509 LTC_S0.pem : 47284 cycles x509 LTC_SS0.pem : 36687 cycles x509 secp384r1.pem : 1985416 cycles x509 secp521r1.pem : 3287773 cycles x509 LTC_SSS0.pem : 25086 cycles x509 secp224r1.pem : 775807 cycles ``` After this patch: [0] ``` ==1043548== HEAP SUMMARY: ==1043548== in use at exit: 0 bytes in 0 blocks ==1043548== total heap usage: 337,244 allocs, 337,244 frees, 65,047,463 bytes allocated ``` [1] ``` x509 cert-rsa-pss.pem : 32568 cycles x509 LTC_CA.pem : 5478 cycles x509 LTC_S0.pem : 36093 cycles x509 LTC_SS0.pem : 23351 cycles x509 secp384r1.pem : 1984030 cycles x509 secp521r1.pem : 3303396 cycles x509 LTC_SSS0.pem : 13220 cycles x509 secp224r1.pem : 781534 cycles ``` [0] find tests/x509 -name '*.pem' -exec valgrind --leak-check=full --show-leak-kinds=all './x509_verify' {} \+ [1] ./timing x509 Signed-off-by: Steffen Jaeckel --- src/headers/tomcrypt_private.h | 10 +- .../x509_decode_public_key_from_certificate.c | 10 +- src/pk/asn1/x509/x509_import_spki.c | 48 ++++-- src/pk/dsa/dsa_import.c | 60 ++++++-- src/pk/rsa/rsa_import.c | 15 +- src/pk/rsa/rsa_import_x509.c | 144 ++++++++++++------ 6 files changed, 198 insertions(+), 89 deletions(-) diff --git a/src/headers/tomcrypt_private.h b/src/headers/tomcrypt_private.h index 39b34caf4..4c122c25c 100644 --- a/src/headers/tomcrypt_private.h +++ b/src/headers/tomcrypt_private.h @@ -426,6 +426,8 @@ int rsa_make_key_bn_e(prng_state *prng, int wprng, int size, void *e, rsa_key *key); /* used by op-tee */ int rsa_import_pkcs1(const unsigned char *in, unsigned long inlen, rsa_key *key); int rsa_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, rsa_key *key); +int rsa_import_spki(const unsigned char *in, unsigned long inlen, rsa_key *key); +int rsa_decode_parameters(const ltc_asn1_list *parameters, ltc_rsa_parameters *rsa_params); #endif /* LTC_MRSA */ /* ---- DH Routines ---- */ @@ -534,8 +536,8 @@ int dsa_int_validate(const dsa_key *key, int *stat); int dsa_int_validate_xy(const dsa_key *key, int *stat); int dsa_int_validate_pqg(const dsa_key *key, int *stat); int dsa_int_validate_primes(const dsa_key *key, int *stat); -int dsa_import_pkcs1(const unsigned char *in, unsigned long inlen, dsa_key *key); int dsa_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, dsa_key *key); +int dsa_import_spki(const unsigned char *in, unsigned long inlen, dsa_key *key); #endif /* LTC_MDSA */ @@ -650,17 +652,17 @@ int der_teletex_value_decode(int v); int der_utf8_valid_char(const wchar_t c); -typedef int (*public_key_decode_cb)(const unsigned char *in, unsigned long inlen, void *ctx); +typedef int (*public_key_decode_cb)(const unsigned char *in, unsigned long inlen, void *key); int x509_decode_public_key_from_certificate(const unsigned char *in, unsigned long inlen, enum ltc_oid_id algorithm, ltc_asn1_type param_type, ltc_asn1_list* parameters, unsigned long *parameters_len, - public_key_decode_cb callback, void *ctx); + public_key_decode_cb callback, void *key); int x509_decode_spki(const unsigned char *in, unsigned long inlen, ltc_asn1_list **out, const ltc_asn1_list **spki); int x509_process_public_key_from_spki(const unsigned char *in, unsigned long inlen, enum ltc_oid_id algorithm, ltc_asn1_type param_type, ltc_asn1_list* parameters, unsigned long *parameters_len, - public_key_decode_cb callback, void *ctx); + public_key_decode_cb callback, void *key); /* SUBJECT PUBLIC KEY INFO */ int x509_encode_subject_public_key_info(unsigned char *out, unsigned long *outlen, diff --git a/src/pk/asn1/x509/x509_decode_public_key_from_certificate.c b/src/pk/asn1/x509/x509_decode_public_key_from_certificate.c index 65623a956..b96db4438 100644 --- a/src/pk/asn1/x509/x509_decode_public_key_from_certificate.c +++ b/src/pk/asn1/x509/x509_decode_public_key_from_certificate.c @@ -24,7 +24,7 @@ int x509_process_public_key_from_spki(const unsigned char *in, unsigned long inlen, enum ltc_oid_id algorithm, ltc_asn1_type param_type, ltc_asn1_list* parameters, unsigned long *parameters_len, - public_key_decode_cb callback, void *ctx) + public_key_decode_cb callback, void *key) { int err; unsigned char *tmpbuf = NULL; @@ -34,7 +34,7 @@ int x509_process_public_key_from_spki(const unsigned char *in, unsigned long inl LTC_ARGCHK(callback != NULL); if (algorithm == LTC_OID_EC) { - err = callback(in, inlen, ctx); + err = callback(in, inlen, key); } else { tmpbuf_len = inlen; @@ -47,7 +47,7 @@ int x509_process_public_key_from_spki(const unsigned char *in, unsigned long inl algorithm, tmpbuf, &tmpbuf_len, param_type, parameters, parameters_len); if (err == CRYPT_OK) { - err = callback(tmpbuf, tmpbuf_len, ctx); + err = callback(tmpbuf, tmpbuf_len, key); } } @@ -73,7 +73,7 @@ int x509_process_public_key_from_spki(const unsigned char *in, unsigned long inl int x509_decode_public_key_from_certificate(const unsigned char *in, unsigned long inlen, enum ltc_oid_id algorithm, ltc_asn1_type param_type, ltc_asn1_list* parameters, unsigned long *parameters_len, - public_key_decode_cb callback, void *ctx) + public_key_decode_cb callback, void *key) { int err; ltc_asn1_list *decoded_list; @@ -90,7 +90,7 @@ int x509_decode_public_key_from_certificate(const unsigned char *in, unsigned lo err = x509_process_public_key_from_spki(spki->data, spki->size, algorithm, param_type, parameters, parameters_len, - callback, ctx); + callback, key); if (decoded_list) der_free_sequence_flexi(decoded_list); diff --git a/src/pk/asn1/x509/x509_import_spki.c b/src/pk/asn1/x509/x509_import_spki.c index 73b4dac73..13057bd31 100644 --- a/src/pk/asn1/x509/x509_import_spki.c +++ b/src/pk/asn1/x509/x509_import_spki.c @@ -9,22 +9,48 @@ #ifdef LTC_DER -typedef int (*import_fn)(const unsigned char *, unsigned long, void*); +typedef int (*import_fn)(const unsigned char *, unsigned long, void *); -static const import_fn s_import_x509_fns[LTC_PKA_NUM] = { +#ifdef LTC_CURVE25519 +static int s_x25519_import_pub(const unsigned char *in, unsigned long inlen, void *key) +{ + return x25519_import_raw(in, inlen, PK_PUBLIC, key); +} +static int s_x25519_import_spki(const unsigned char *in, unsigned long inlen, void *key) +{ + return x509_process_public_key_from_spki(in, inlen, + LTC_OID_X25519, + LTC_ASN1_EOL, NULL, NULL, + s_x25519_import_pub, key); +} + +static int s_ed25519_import_pub(const unsigned char *in, unsigned long inlen, void *key) +{ + return ed25519_import_raw(in, inlen, PK_PUBLIC, key); +} +static int s_ed25519_import_spki(const unsigned char *in, unsigned long inlen, void *key) +{ + return x509_process_public_key_from_spki(in, inlen, + LTC_OID_ED25519, + LTC_ASN1_EOL, NULL, NULL, + s_ed25519_import_pub, key); +} +#endif + +static const import_fn s_import_spki_fns[LTC_PKA_NUM] = { #ifdef LTC_MRSA - [LTC_PKA_RSA] = (import_fn)rsa_import_x509, - [LTC_PKA_RSA_PSS] = (import_fn)rsa_import_x509, + [LTC_PKA_RSA] = (import_fn)rsa_import_spki, + [LTC_PKA_RSA_PSS] = (import_fn)rsa_import_spki, #endif #ifdef LTC_MDSA - [LTC_PKA_DSA] = (import_fn)dsa_import, + [LTC_PKA_DSA] = (import_fn)dsa_import_spki, #endif #ifdef LTC_MECC - [LTC_PKA_EC] = (import_fn)ecc_import_x509, + [LTC_PKA_EC] = (import_fn)ecc_import_subject_public_key_info, #endif #ifdef LTC_CURVE25519 - [LTC_PKA_X25519] = (import_fn)x25519_import_x509, - [LTC_PKA_ED25519] = (import_fn)ed25519_import_x509, + [LTC_PKA_X25519] = (import_fn)s_x25519_import_spki, + [LTC_PKA_ED25519] = (import_fn)s_ed25519_import_spki, #endif }; @@ -41,12 +67,12 @@ int x509_import_spki(const unsigned char *asn1_cert, unsigned long asn1_len, ltc goto err_out; } if (pka < 0 - || pka > LTC_ARRAY_SIZE(s_import_x509_fns) - || s_import_x509_fns[pka] == NULL) { + || pka > LTC_ARRAY_SIZE(s_import_spki_fns) + || s_import_spki_fns[pka] == NULL) { err = CRYPT_PK_INVALID_TYPE; goto err_out; } - if ((err = s_import_x509_fns[pka](asn1_cert, asn1_len, &k->u)) == CRYPT_OK) { + if ((err = s_import_spki_fns[pka](spki->data, spki->size, &k->u)) == CRYPT_OK) { k->id = pka; } err_out: diff --git a/src/pk/dsa/dsa_import.c b/src/pk/dsa/dsa_import.c index 377a10b17..91ddcc2be 100644 --- a/src/pk/dsa/dsa_import.c +++ b/src/pk/dsa/dsa_import.c @@ -9,7 +9,7 @@ #ifdef LTC_MDSA -int dsa_import_pkcs1(const unsigned char *in, unsigned long inlen, dsa_key *key) +static int s_dsa_import_pkcs1(const unsigned char *in, unsigned long inlen, dsa_key *key) { int err; unsigned long zero = 0; @@ -33,7 +33,7 @@ static int s_dsa_import_y(const unsigned char *in, unsigned long inlen, dsa_key return der_decode_integer(in, inlen, key->y); } -LTC_INLINE static int s_dsa_set_params(dsa_key *key, ltc_asn1_list *params) +static LTC_INLINE int s_dsa_set_params(dsa_key *key, ltc_asn1_list *params) { LTC_SET_ASN1(params, 0, LTC_ASN1_INTEGER, key->p, 1UL); LTC_SET_ASN1(params, 1, LTC_ASN1_INTEGER, key->q, 1UL); @@ -41,6 +41,24 @@ LTC_INLINE static int s_dsa_set_params(dsa_key *key, ltc_asn1_list *params) return 3; } +static LTC_INLINE int s_dsa_validate(dsa_key *key) +{ + int err, stat; + key->qord = ltc_mp_unsigned_bin_size(key->q); + + /* quick p, q, g validation, without primality testing + * + x, y validation */ + if ((err = dsa_int_validate(key, &stat)) != CRYPT_OK) { + return err; + } + + if (stat == 0) { + return CRYPT_INVALID_PACKET; + } + + return CRYPT_OK; +} + static int s_dsa_import_spki(const unsigned char *in, unsigned long inlen, dsa_key *key) { int err; @@ -72,6 +90,28 @@ static int s_dsa_import_spki(const unsigned char *in, unsigned long inlen, dsa_k return err; } +int dsa_import_spki(const unsigned char *in, unsigned long inlen, dsa_key *key) +{ + int err; + + LTC_ARGCHK(in != NULL); + + /* init key */ + if ((err = dsa_int_init(key)) != CRYPT_OK) return err; + + if ((err = s_dsa_import_spki(in, inlen, key)) != CRYPT_OK) { + goto LBL_ERR; + } + if ((err = s_dsa_validate(key)) != CRYPT_OK) { + goto LBL_ERR; + } + + return CRYPT_OK; +LBL_ERR: + dsa_free(key); + return err; +} + static int s_dsa_import_x509(const unsigned char *in, unsigned long inlen, dsa_key *key) { int err; @@ -100,7 +140,7 @@ static int s_dsa_import_x509(const unsigned char *in, unsigned long inlen, dsa_k */ int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key) { - int err, stat; + int err; unsigned char flags[1]; LTC_ARGCHK(in != NULL); @@ -148,10 +188,10 @@ int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key) } } - if (dsa_import_pkcs1(in, inlen, key) == CRYPT_OK) { + if (s_dsa_import_pkcs1(in, inlen, key) == CRYPT_OK) { goto LBL_OK; } - if ((err = s_dsa_import_spki(in, inlen, key)) == CRYPT_OK) { + if (s_dsa_import_spki(in, inlen, key) == CRYPT_OK) { goto LBL_OK; } if ((err = s_dsa_import_x509(in, inlen, key)) != CRYPT_OK) { @@ -159,15 +199,7 @@ int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key) } LBL_OK: - key->qord = ltc_mp_unsigned_bin_size(key->q); - - /* quick p, q, g validation, without primality testing - * + x, y validation */ - if ((err = dsa_int_validate(key, &stat)) != CRYPT_OK) { - goto LBL_ERR; - } - if (stat == 0) { - err = CRYPT_INVALID_PACKET; + if ((err = s_dsa_validate(key)) != CRYPT_OK) { goto LBL_ERR; } diff --git a/src/pk/rsa/rsa_import.c b/src/pk/rsa/rsa_import.c index a52ff154f..bc201ad97 100644 --- a/src/pk/rsa/rsa_import.c +++ b/src/pk/rsa/rsa_import.c @@ -99,7 +99,8 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key) LTC_ARGCHK(key != NULL); LTC_ARGCHK(ltc_mp.name != NULL); - if ((err = rsa_import_x509(in, inlen, key)) == CRYPT_OK) { /* SubjectPublicKeyInfo format */ + /* SubjectPublicKeyInfo or X.509 certificate format */ + if (rsa_import_x509(in, inlen, key) == CRYPT_OK) { return CRYPT_OK; } @@ -107,15 +108,9 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key) if ((err = rsa_init(key)) != CRYPT_OK) { return err; } - - if ((err = x509_process_public_key_from_spki(in, inlen, - LTC_OID_RSA, - LTC_ASN1_NULL, NULL, NULL, - (public_key_decode_cb)s_rsa_decode, key)) != CRYPT_OK) { - /* not SSL public key, try to match against PKCS #1 standards */ - if ((err = rsa_import_pkcs1(in, inlen, key)) != CRYPT_OK) { - rsa_free(key); - } + /* Try to match against PKCS #1 standards */ + if ((err = rsa_import_pkcs1(in, inlen, key)) != CRYPT_OK) { + rsa_free(key); } return err; diff --git a/src/pk/rsa/rsa_import_x509.c b/src/pk/rsa/rsa_import_x509.c index f2a489e9e..6ebe55669 100644 --- a/src/pk/rsa/rsa_import_x509.c +++ b/src/pk/rsa/rsa_import_x509.c @@ -77,51 +77,44 @@ static LTC_INLINE void s_rsa_pss_parameters_data_setup(rsa_pss_parameters_data * } } -int rsa_decode_parameters(const ltc_asn1_list *parameters, ltc_rsa_parameters *rsa_params) +static int s_rsa_decode_parameters(const rsa_pss_parameters_data *d, ltc_rsa_parameters *rsa_params) { - rsa_pss_parameters_data d; unsigned long n; enum ltc_oid_id oid_id; int err, idx; - s_rsa_pss_parameters_data_setup(&d); - - if ((err = der_decode_sequence(parameters->data, parameters->size, d.params, 4)) != CRYPT_OK) { - return err; - } - rsa_params->saltlen = 20; rsa_params->hash_alg = rsa_params->mgf1_hash_alg = "sha1"; for (n = 0; n < 4; ++n) { - if (d.params[n].used == 0) + if (d->params[n].used == 0) continue; switch (n) { case 0: - idx = find_hash_oid(d.hash_alg->data, d.hash_alg->size); + idx = find_hash_oid(d->hash_alg->data, d->hash_alg->size); if (idx == -1) { return CRYPT_INVALID_HASH; } rsa_params->hash_alg = hash_descriptor[idx].name; break; case 1: - if ((err = pk_get_oid_from_asn1(&d.mgf[0], &oid_id)) != CRYPT_OK) { + if ((err = pk_get_oid_from_asn1(&d->mgf[0], &oid_id)) != CRYPT_OK) { return err; } if (oid_id != LTC_OID_RSA_MGF1) { return CRYPT_PK_ASN1_ERROR; } - idx = find_hash_oid(d.mgf_hash_alg->data, d.mgf_hash_alg->size); + idx = find_hash_oid(d->mgf_hash_alg->data, d->mgf_hash_alg->size); if (idx == -1) { return CRYPT_INVALID_HASH; } rsa_params->mgf1_hash_alg = hash_descriptor[idx].name; break; case 2: - rsa_params->saltlen = d.salt_length; + rsa_params->saltlen = d->salt_length; break; case 3: - if (d.trailer_field != 1) { + if (d->trailer_field != 1) { return CRYPT_PK_ASN1_ERROR; } break; @@ -130,51 +123,76 @@ int rsa_decode_parameters(const ltc_asn1_list *parameters, ltc_rsa_parameters *r } } - rsa_params->pss_oaep = 1; return CRYPT_OK; } -static int s_rsa_import_pss(const unsigned char *in, unsigned long inlen, rsa_key *key) +int rsa_decode_parameters(const ltc_asn1_list *parameters, ltc_rsa_parameters *rsa_params) { - rsa_pss_parameters_data d; - ltc_asn1_list *decoded_list; - const ltc_asn1_list *spki; int err; + rsa_pss_parameters_data d; + + s_rsa_pss_parameters_data_setup(&d); + + if ((err = der_decode_sequence(parameters->data, parameters->size, d.params, 4)) != CRYPT_OK) { + return err; + } + + return s_rsa_decode_parameters(&d, rsa_params); +} + +static LTC_INLINE int s_rsa_1_5_import_spki(const unsigned char *in, unsigned long inlen, rsa_key *key) +{ + return x509_process_public_key_from_spki(in, inlen, + LTC_OID_RSA, + LTC_ASN1_NULL, NULL, NULL, + (public_key_decode_cb)s_rsa_decode, key); +} + +static LTC_INLINE int s_rsa_pss_import_spki(const unsigned char *in, unsigned long inlen, rsa_key *key) +{ + int err; + rsa_pss_parameters_data d; unsigned long n_params = LTC_ARRAY_SIZE(d.params); + if (x509_process_public_key_from_spki(in, inlen, + LTC_OID_RSA_PSS, + LTC_ASN1_NULL, NULL, NULL, + (public_key_decode_cb)s_rsa_decode, key) == CRYPT_OK) { + return CRYPT_OK; + } + s_rsa_pss_parameters_data_setup(&d); if ((err = x509_process_public_key_from_spki(in, inlen, - LTC_OID_RSA_PSS, - LTC_ASN1_NULL, NULL, NULL, - (public_key_decode_cb)s_rsa_decode, key)) != CRYPT_OK) { - if ((err = x509_decode_spki(in, inlen, &decoded_list, &spki)) != CRYPT_OK) { - return err; - } - if ((err = x509_process_public_key_from_spki(spki->data, spki->size, - LTC_OID_RSA_PSS, - LTC_ASN1_NULL, NULL, NULL, - (public_key_decode_cb)s_rsa_decode, key)) != CRYPT_OK) { - s_rsa_pss_parameters_data_setup(&d); - err = x509_process_public_key_from_spki(spki->data, spki->size, - LTC_OID_RSA_PSS, - LTC_ASN1_SEQUENCE, d.params, &n_params, - (public_key_decode_cb)s_rsa_decode, key); - } + LTC_OID_RSA_PSS, + LTC_ASN1_SEQUENCE, d.params, &n_params, + (public_key_decode_cb)s_rsa_decode, key)) != CRYPT_OK) { + return err; + } + return s_rsa_decode_parameters(&d, &key->params); +} + +static LTC_INLINE int s_rsa_import_spki(const unsigned char *in, unsigned long inlen, rsa_key *key) +{ + int err; + if (s_rsa_1_5_import_spki(in, inlen, key) == CRYPT_OK) { + return CRYPT_OK; } - der_free_sequence_flexi(decoded_list); + if ((err = s_rsa_pss_import_spki(in, inlen, key)) == CRYPT_OK) { + return CRYPT_OK; + } return err; } /** - Import an RSA key from a X.509 certificate + Import an RSA key from SubjectPublicKeyInfo @param in The packet to import from @param inlen It's length (octets) @param key [out] Destination for newly imported key @return CRYPT_OK if successful, upon error allocated memory is freed */ -int rsa_import_x509(const unsigned char *in, unsigned long inlen, rsa_key *key) +int rsa_import_spki(const unsigned char *in, unsigned long inlen, rsa_key *key) { int err; @@ -187,22 +205,58 @@ int rsa_import_x509(const unsigned char *in, unsigned long inlen, rsa_key *key) return err; } - if ((err = x509_decode_public_key_from_certificate(in, inlen, - LTC_OID_RSA, - LTC_ASN1_NULL, NULL, NULL, - (public_key_decode_cb)s_rsa_decode, key)) == CRYPT_OK) { + if ((err = s_rsa_import_spki(in, inlen, key)) == CRYPT_OK) { key->type = PK_PUBLIC; return CRYPT_OK; } - if ((err = s_rsa_import_pss(in, inlen, key)) == CRYPT_OK) { + rsa_free(key); + + return err; +} + +/** + Import an RSA key from a X.509 certificate + @param in The packet to import from + @param inlen It's length (octets) + @param key [out] Destination for newly imported key + @return CRYPT_OK if successful, upon error allocated memory is freed +*/ +int rsa_import_x509(const unsigned char *in, unsigned long inlen, rsa_key *key) +{ + ltc_asn1_list *decoded_list; + const ltc_asn1_list *spki; + int err; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(ltc_mp.name != NULL); + + /* init key */ + if ((err = rsa_init(key)) != CRYPT_OK) { + return err; + } + + /* First try to decode as SubjectPublicKeyInfo */ + if (s_rsa_import_spki(in, inlen, key) == CRYPT_OK) { key->type = PK_PUBLIC; return CRYPT_OK; } - rsa_free(key); + /* Now try to extract the SubjectPublicKeyInfo from the Certificate */ + if ((err = x509_decode_spki(in, inlen, &decoded_list, &spki)) != CRYPT_OK) { + rsa_free(key); + return err; + } + err = s_rsa_import_spki(spki->data, spki->size, key); - return err; + der_free_sequence_flexi(decoded_list); + if (err != CRYPT_OK) { + rsa_free(key); + return err; + } + key->type = PK_PUBLIC; + return CRYPT_OK; } #endif /* LTC_MRSA */ From 807362f1bd61e755c27ee9daf3c9a1dab1eb7f31 Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Thu, 11 Sep 2025 12:25:58 +0200 Subject: [PATCH 10/17] Put realloc logic into `pem_read()` Signed-off-by: Steffen Jaeckel --- src/headers/tomcrypt_private.h | 31 +++++-- src/misc/pem/pem_pkcs.c | 15 ++-- src/misc/pem/pem_read.c | 156 +++++++++++++++++++++------------ src/misc/pem/pem_ssh.c | 19 ++-- 4 files changed, 141 insertions(+), 80 deletions(-) diff --git a/src/headers/tomcrypt_private.h b/src/headers/tomcrypt_private.h index 4c122c25c..153d22438 100644 --- a/src/headers/tomcrypt_private.h +++ b/src/headers/tomcrypt_private.h @@ -355,19 +355,40 @@ struct bufp { }; #define SET_BUFP(n, d, l) n.start = (char*)d, n.work = (char*)d, n.end = (char*)d + l + 1 +#define UPDATE_BUFP(n, d, w, l) n.start = (char*)d, n.work = (char*)d + w, n.end = (char*)d + l + 1 -struct get_char { +struct get_char; +struct get_char_api { int (*get)(struct get_char*); +}; + +struct get_char { + struct get_char_api api; union { #ifndef LTC_NO_FILE - FILE *f; + struct { + FILE *f; + } f; #endif /* LTC_NO_FILE */ struct bufp buf; } data; struct str unget_buf; char unget_buf_[LTC_PEM_DECODE_BUFSZ]; int prev_get; + unsigned long total_read; }; + +#define pem_get_char_init(b, l) { \ + .api = get_char_buffer_api, \ + SET_BUFP(.data.buf, (b), (l)), \ + .total_read = 0, \ +} + +#define pem_get_char_init_filehandle(fi) { \ + .api = get_char_filehandle_api, \ + .data.f.f = (fi), \ + .total_read = 0, \ +} #endif /* others */ @@ -390,10 +411,10 @@ int pem_decrypt(unsigned char *data, unsigned long *datalen, const struct blockcipher_info *info, enum padding_type padding); #ifndef LTC_NO_FILE -int pem_get_char_from_file(struct get_char *g); +extern const struct get_char_api get_char_filehandle_api; #endif /* LTC_NO_FILE */ -int pem_get_char_from_buf(struct get_char *g); -int pem_read(void *asn1_cert, unsigned long *asn1_len, struct pem_headers *hdr, struct get_char *g); +extern const struct get_char_api get_char_buffer_api; +int pem_read(void **dest, unsigned long *len, struct pem_headers *hdr, struct get_char *g); #endif /* tomcrypt_pk.h */ diff --git a/src/misc/pem/pem_pkcs.c b/src/misc/pem/pem_pkcs.c index 7d726645c..17aa47705 100644 --- a/src/misc/pem/pem_pkcs.c +++ b/src/misc/pem/pem_pkcs.c @@ -127,21 +127,16 @@ static const import_fn s_import_openssl_fns[LTC_PKA_NUM] = { static int s_decode(struct get_char *g, ltc_pka_key *k, const password_ctx *pw_ctx) { unsigned char *asn1_cert = NULL; - unsigned long w, asn1_len, n; + unsigned long w = 0, asn1_len, n; int err = CRYPT_ERROR; struct pem_headers hdr = { 0 }; struct password pw = { 0 }; enum ltc_pka_id pka; XMEMSET(k, 0, sizeof(*k)); - w = LTC_PEM_READ_BUFSIZE * 2; -retry: - asn1_cert = XREALLOC(asn1_cert, w); for (n = 0; n < pem_std_headers_num; ++n) { hdr.id = &pem_std_headers[n]; - err = pem_read(asn1_cert, &w, &hdr, g); - if (err == CRYPT_BUFFER_OVERFLOW) { - goto retry; - } else if (err == CRYPT_OK) { + err = pem_read((void**)&asn1_cert, &w, &hdr, g); + if (err == CRYPT_OK) { break; } else if (err != CRYPT_UNKNOWN_PEM) { goto cleanup; @@ -204,7 +199,7 @@ int pem_decode_pkcs_filehandle(FILE *f, ltc_pka_key *k, const password_ctx *pw_c LTC_ARGCHK(f != NULL); LTC_ARGCHK(k != NULL); { - struct get_char g = { .get = pem_get_char_from_file, .data.f = f }; + struct get_char g = pem_get_char_init_filehandle(f); return s_decode(&g, k, pw_ctx); } } @@ -216,7 +211,7 @@ int pem_decode_pkcs(const void *buf, unsigned long len, ltc_pka_key *k, const pa LTC_ARGCHK(len != 0); LTC_ARGCHK(k != NULL); { - struct get_char g = { .get = pem_get_char_from_buf, SET_BUFP(.data.buf, buf, len) }; + struct get_char g = pem_get_char_init(buf, len); return s_decode(&g, k, pw_ctx); } } diff --git a/src/misc/pem/pem_read.c b/src/misc/pem/pem_read.c index abefff924..bbc61cb0d 100644 --- a/src/misc/pem/pem_read.c +++ b/src/misc/pem/pem_read.c @@ -17,14 +17,76 @@ extern const struct str pem_dek_info_start; extern const struct blockcipher_info pem_dek_infos[]; extern const unsigned long pem_dek_infos_num; +static LTC_INLINE unsigned long s_bufp_alloc_len(struct bufp *buf) +{ + if (buf->start == NULL || buf->end == NULL) + return 0; + return buf->end - buf->start - 1; +} + +static LTC_INLINE unsigned long s_bufp_used_len(struct bufp *buf) +{ + if (buf->start == NULL || buf->end == NULL) + return 0; + return buf->work - buf->start; +} + +static LTC_INLINE int s_bufp_grow(struct bufp *buf) +{ + int err = CRYPT_OK; + void *ret; + unsigned long alloc_len = s_bufp_alloc_len(buf), realloc_len; + unsigned long work_offset = s_bufp_used_len(buf); + if (alloc_len == 0) + realloc_len = LTC_PEM_READ_BUFSIZE; + else + realloc_len = alloc_len * 2; + if (realloc_len < alloc_len) + return CRYPT_OVERFLOW; + ret = XREALLOC(buf->start, realloc_len); + if (ret == NULL) { + err = CRYPT_MEM; + } else { + UPDATE_BUFP((*buf), ret, work_offset, realloc_len); + } + return err; +} + +static LTC_INLINE int s_bufp_fits(struct bufp *buf, unsigned long to_write) +{ + char *d = buf->work; + char *e = buf->end; + char *w = d + to_write; + if (d == NULL || w < d || w > e) + return 0; + return 1; +} + +static LTC_INLINE int s_bufp_add(struct bufp *buf, const void *src, unsigned long len) +{ + int err; + if (!s_bufp_fits(buf, len)) { + if ((err = s_bufp_grow(buf)) != CRYPT_OK) { + return err; + } + } + XMEMCPY(buf->work, src, len); + buf->work += len; + return CRYPT_OK; +} + #ifndef LTC_NO_FILE -int pem_get_char_from_file(struct get_char *g) +static int s_pem_get_char_from_file(struct get_char *g) { - return getc(g->data.f); + return getc(g->data.f.f); } + +const struct get_char_api get_char_filehandle_api = { + .get = s_pem_get_char_from_file, +}; #endif /* LTC_NO_FILE */ -int pem_get_char_from_buf(struct get_char *g) +static int s_pem_get_char_from_buf(struct get_char *g) { int ret; if (g->data.buf.work == g->data.buf.end) { @@ -35,6 +97,10 @@ int pem_get_char_from_buf(struct get_char *g) return ret; } +const struct get_char_api get_char_buffer_api = { + .get = s_pem_get_char_from_buf, +}; + static void s_unget_line(char *buf, unsigned long buflen, struct get_char *g) { if (buflen > sizeof(g->unget_buf_)) @@ -81,7 +147,7 @@ static char* s_get_line_i(char *buf, unsigned long *buflen, struct get_char *g, while(blen < *buflen || search_for_start) { wr = blen < *buflen ? blen : *buflen - 1; c_ = g->prev_get; - g->prev_get = g->get(g); + g->prev_get = g->api.get(g); if (g->prev_get == '\n') { buf[wr] = '\0'; if (c_ == '\r') { @@ -89,6 +155,7 @@ static char* s_get_line_i(char *buf, unsigned long *buflen, struct get_char *g, } s_tts(buf, &wr); *buflen = wr; + g->total_read++; return buf; } if (g->prev_get == -1 || g->prev_get == '\0') { @@ -99,30 +166,21 @@ static char* s_get_line_i(char *buf, unsigned long *buflen, struct get_char *g, } buf[wr] = g->prev_get; blen++; + g->total_read++; } return NULL; } -LTC_INLINE static char* s_get_first_line(char *buf, unsigned long *buflen, struct get_char *g) +static LTC_INLINE char* s_get_first_line(char *buf, unsigned long *buflen, struct get_char *g) { return s_get_line_i(buf, buflen, g, 1); } -LTC_INLINE static char* s_get_line(char *buf, unsigned long *buflen, struct get_char *g) +static LTC_INLINE char* s_get_line(char *buf, unsigned long *buflen, struct get_char *g) { return s_get_line_i(buf, buflen, g, 0); } -static LTC_INLINE int s_fits_buf(void *dest, unsigned long to_write, void *end) -{ - unsigned char *d = dest; - unsigned char *e = end; - unsigned char *w = d + to_write; - if (w < d || w > e) - return 0; - return 1; -} - static int s_pem_decode_headers(struct pem_headers *hdr, struct get_char *g) { char buf[LTC_PEM_DECODE_BUFSZ], *alg_start; @@ -190,31 +248,29 @@ static int s_pem_decode_headers(struct pem_headers *hdr, struct get_char *g) return CRYPT_OK; } -int pem_read(void *asn1_cert, unsigned long *asn1_len, struct pem_headers *hdr, struct get_char *g) +int pem_read(void **dest, unsigned long *len, struct pem_headers *hdr, struct get_char *g) { - char buf[LTC_PEM_DECODE_BUFSZ]; - char *wpem = asn1_cert; - char *end = wpem + *asn1_len; + char line[LTC_PEM_DECODE_BUFSZ]; + struct bufp b_ = {0}, *b = &b_; const char pem_start[] = "----"; - unsigned long slen, linelen; + unsigned long slen; int err, hdr_ok = 0; - int would_overflow = 0; unsigned char empty_lines = 0; g->prev_get = 0; do { - linelen = sizeof(buf); - if (s_get_first_line(buf, &linelen, g) == NULL) { + slen = sizeof(line); + if (s_get_first_line(line, &slen, g) == NULL) { if (g->prev_get == -1) return CRYPT_NOP; else return CRYPT_INVALID_PACKET; } - if (linelen < sizeof(pem_start) - 1) + if (slen < sizeof(pem_start) - 1) continue; - } while(XMEMCMP(buf, pem_start, sizeof(pem_start) - 1) != 0); - if (hdr->id->start.len != linelen || XMEMCMP(buf, hdr->id->start.p, hdr->id->start.len)) { - s_unget_line(buf, linelen, g); + } while(XMEMCMP(line, pem_start, sizeof(pem_start) - 1) != 0); + if (hdr->id->start.len != slen || XMEMCMP(line, hdr->id->start.p, hdr->id->start.len)) { + s_unget_line(line, slen, g); return CRYPT_UNKNOWN_PEM; } @@ -223,9 +279,9 @@ int pem_read(void *asn1_cert, unsigned long *asn1_len, struct pem_headers *hdr, return err; /* Read the base64 encoded part of the PEM */ - slen = sizeof(buf); - while (s_get_line(buf, &slen, g)) { - if (slen == hdr->id->end.len && !XMEMCMP(buf, hdr->id->end.p, slen)) { + slen = sizeof(line); + while (s_get_line(line, &slen, g)) { + if (slen == hdr->id->end.len && !XMEMCMP(line, hdr->id->end.p, slen)) { hdr_ok = 1; break; } @@ -234,34 +290,26 @@ int pem_read(void *asn1_cert, unsigned long *asn1_len, struct pem_headers *hdr, break; empty_lines++; } - if (!would_overflow && s_fits_buf(wpem, slen, end)) { - XMEMCPY(wpem, buf, slen); - } else { - would_overflow = 1; + if ((err = s_bufp_add(b, line, slen)) != CRYPT_OK) { + goto error_out; } - wpem += slen; - slen = sizeof(buf); + slen = sizeof(line); } - if (!hdr_ok) - return CRYPT_INVALID_PACKET; - - if (would_overflow || !s_fits_buf(wpem, 1, end)) { - /* NUL termination */ - wpem++; - /* prevent a wrap-around */ - if (wpem < (char*)asn1_cert) - return CRYPT_OVERFLOW; - *asn1_len = wpem - (char*)asn1_cert; - return CRYPT_BUFFER_OVERFLOW; + if (!hdr_ok) { + err = CRYPT_INVALID_PACKET; + } else { + slen = s_bufp_alloc_len(b); + err = base64_strict_decode(b->start, s_bufp_used_len(b), (void*)b->start, &slen); } + if (err == CRYPT_OK) { + *dest = b->start; + *len = slen; - *asn1_len = wpem - (char*)asn1_cert; - *wpem++ = '\0'; - - if ((err = base64_strict_decode(asn1_cert, *asn1_len, asn1_cert, asn1_len)) != CRYPT_OK) { - return err; + } else { +error_out: + XFREE(b->start); } - return CRYPT_OK; + return err; } #endif /* LTC_PEM */ diff --git a/src/misc/pem/pem_ssh.c b/src/misc/pem/pem_ssh.c index 77fa87be9..d4de0865a 100644 --- a/src/misc/pem/pem_ssh.c +++ b/src/misc/pem/pem_ssh.c @@ -712,20 +712,15 @@ static const unsigned long pem_openssh_num = LTC_ARRAY_SIZE(pem_openssh); static int s_decode_openssh(struct get_char *g, ltc_pka_key *k, const password_ctx *pw_ctx) { unsigned char *pem = NULL, *p, *privkey = NULL, *tag; - unsigned long n, w, l, privkey_len, taglen; + unsigned long n, w = 0, l, privkey_len, taglen; int err; struct pem_headers hdr; struct kdf_options opts = { 0 }; XMEMSET(k, 0, sizeof(*k)); - w = LTC_PEM_READ_BUFSIZE * 2; -retry: - pem = XREALLOC(pem, w); for (n = 0; n < pem_openssh_num; ++n) { hdr.id = &pem_openssh[n]; - err = pem_read(pem, &w, &hdr, g); - if (err == CRYPT_BUFFER_OVERFLOW) { - goto retry; - } else if (err == CRYPT_OK) { + err = pem_read((void**)&pem, &w, &hdr, g); + if (err == CRYPT_OK) { break; } else if (err != CRYPT_UNKNOWN_PEM) { goto cleanup; @@ -791,7 +786,9 @@ static int s_decode_openssh(struct get_char *g, ltc_pka_key *k, const password_c zeromem(privkey, privkey_len); XFREE(privkey); } - XFREE(pem); + if (pem) { + XFREE(pem); + } return err; } @@ -801,7 +798,7 @@ int pem_decode_openssh_filehandle(FILE *f, ltc_pka_key *k, const password_ctx *p LTC_ARGCHK(f != NULL); LTC_ARGCHK(k != NULL); { - struct get_char g = { .get = pem_get_char_from_file, .data.f = f }; + struct get_char g = pem_get_char_init_filehandle(f); return s_decode_openssh(&g, k, pw_ctx); } } @@ -841,7 +838,7 @@ int pem_decode_openssh(const void *buf, unsigned long len, ltc_pka_key *k, const LTC_ARGCHK(len != 0); LTC_ARGCHK(k != NULL); { - struct get_char g = { .get = pem_get_char_from_buf, SET_BUFP(.data.buf, buf, len) }; + struct get_char g = pem_get_char_init(buf, len); return s_decode_openssh(&g, k, pw_ctx); } } From 556f26aec5cdb83bc76248c40c57242215c635e1 Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Fri, 3 Oct 2025 10:39:07 +0200 Subject: [PATCH 11/17] Re-order PEM headers to prepare for X.509 APIs Signed-off-by: Steffen Jaeckel --- src/misc/pem/pem.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/misc/pem/pem.c b/src/misc/pem/pem.c index 632515914..1e8cc0132 100644 --- a/src/misc/pem/pem.c +++ b/src/misc/pem/pem.c @@ -10,6 +10,13 @@ #ifdef LTC_PEM const struct pem_header_id pem_std_headers[] = { + { + /* X.509 Certificates */ + SET_CSTR(.start, "-----BEGIN CERTIFICATE-----"), + SET_CSTR(.end, "-----END CERTIFICATE-----"), + .has_more_headers = no, + .flags = pf_x509, + }, { /* PKCS#8 encrypted */ SET_CSTR(.start, "-----BEGIN ENCRYPTED PRIVATE KEY-----"), @@ -24,13 +31,6 @@ const struct pem_header_id pem_std_headers[] = { .has_more_headers = no, .flags = pf_pkcs8, }, - { - /* X.509 Certificates */ - SET_CSTR(.start, "-----BEGIN CERTIFICATE-----"), - SET_CSTR(.end, "-----END CERTIFICATE-----"), - .has_more_headers = no, - .flags = pf_x509, - }, { /* Regular (plain) public keys */ SET_CSTR(.start, "-----BEGIN PUBLIC KEY-----"), From d9f34f549101edff301a7f1fe1316eca8c4c875f Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Thu, 9 Oct 2025 11:28:35 +0200 Subject: [PATCH 12/17] Move RFC6979 hash alg to a new ecc signature options struct Fixes #700 Signed-off-by: Steffen Jaeckel --- demos/timing.c | 12 ++- src/headers/tomcrypt_pk.h | 136 ++++++++++++++---------- src/headers/tomcrypt_private.h | 57 ++++++++++- src/misc/deprecated.c | 82 +++++++++++++++ src/pk/ecc/ecc_make_key.c | 1 - src/pk/ecc/ecc_recover_key.c | 14 +-- src/pk/ecc/ecc_rfc6979_key.c | 6 +- src/pk/ecc/ecc_set_curve.c | 2 - src/pk/ecc/ecc_set_key.c | 1 - src/pk/ecc/ecc_sign_hash.c | 54 +++++----- src/pk/ecc/ecc_sign_hash_eth27.c | 14 ++- src/pk/ecc/ecc_sign_hash_internal.c | 16 +-- src/pk/ecc/ecc_sign_hash_rfc5656.c | 7 +- src/pk/ecc/ecc_sign_hash_rfc7518.c | 31 +----- src/pk/ecc/ecc_sign_hash_x962.c | 44 ++++++++ src/pk/ecc/ecc_verify_hash.c | 53 ++++++---- src/pk/ecc/ecc_verify_hash_eth27.c | 2 +- src/pk/ecc/ecc_verify_hash_rfc7518.c | 14 +-- src/pk/ecc/ecc_verify_hash_x962.c | 37 +++++++ tests/ecc_test.c | 148 +++++++++++++++++---------- 20 files changed, 500 insertions(+), 231 deletions(-) create mode 100644 src/misc/deprecated.c create mode 100644 src/pk/ecc/ecc_sign_hash_x962.c create mode 100644 src/pk/ecc/ecc_verify_hash_x962.c diff --git a/demos/timing.c b/demos/timing.c index 52dd11522..572756dda 100644 --- a/demos/timing.c +++ b/demos/timing.c @@ -872,7 +872,7 @@ static void time_ecc(void) unsigned char buf[2][256] = { 0 }; unsigned long i, w, x, y, z; int err, stat; - static unsigned long sizes[] = { + const unsigned long sizes[] = { #ifdef LTC_ECC_SECP112R1 112/8, #endif @@ -898,6 +898,11 @@ static void time_ecc(void) 521/8, #endif 100000}; + ltc_ecc_sig_opts sig_opts = { + .type = LTC_ECCSIG_RFC7518, + .prng = &yarrow_prng, + .wprng = find_prng ("yarrow") + }; if (ltc_mp.name == NULL) return; @@ -969,8 +974,7 @@ static void time_ecc(void) t_start(); t1 = t_read(); z = sizeof(buf[1]); - if ((err = ecc_sign_hash(buf[0], 20, buf[1], &z, &yarrow_prng, - find_prng("yarrow"), &key)) != CRYPT_OK) { + if ((err = ecc_sign_hash_v2(buf[0], 20, buf[1], &z, &sig_opts, &key)) != CRYPT_OK) { fprintf(stderr, "\n\necc_sign_hash says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); exit(EXIT_FAILURE); } @@ -988,7 +992,7 @@ static void time_ecc(void) for (y = 0; y < 256; y++) { t_start(); t1 = t_read(); - if ((err = ecc_verify_hash(buf[1], z, buf[0], 20, &stat, &key)) != CRYPT_OK) { + if ((err = ecc_verify_hash_v2(buf[1], z, buf[0], 20, &sig_opts, &stat, &key)) != CRYPT_OK) { fprintf(stderr, "\n\necc_verify_hash says %s, wait...no it should say %s...damn you!\n", error_to_string(err), error_to_string(CRYPT_OK)); exit(EXIT_FAILURE); } diff --git a/src/headers/tomcrypt_pk.h b/src/headers/tomcrypt_pk.h index aeb2188c0..d517b2fe4 100644 --- a/src/headers/tomcrypt_pk.h +++ b/src/headers/tomcrypt_pk.h @@ -297,20 +297,10 @@ typedef struct { /** The private key */ void *k; - - /** The hash algorithm to use when creating a signature. - * Setting this will enable RFC6979 compatible signature generation. - * The macro ECC_SET_RFC6979_HASH_ALG() is provided as a helper - * to set this.*/ - const char *rfc6979_hash_alg; } ecc_key; -#define ECC_SET_RFC6979_HASH_ALG(key, alg) do { \ - (key)->rfc6979_hash_alg = (alg); \ -} while(0) - /** Formats of ECC signatures */ -typedef enum ecc_signature_type_ { +typedef enum ecc_signature_type { /* ASN.1 encoded, ANSI X9.62 */ LTC_ECCSIG_ANSIX962 = 0x0, /* raw R, S values */ @@ -321,6 +311,28 @@ typedef enum ecc_signature_type_ { LTC_ECCSIG_RFC5656 = 0x3, } ecc_signature_type; +typedef struct ltc_ecc_sig_opts { + /** Signature type */ + ecc_signature_type type; + /** The PRNG to use. + * This must be set in case deterministic signature generation + * according to RFC6979 is not enabled. + */ + prng_state *prng; + int wprng; + + /** Enable generation of a recovery ID. + * This must be set in case one requires the recovery ID of a + * signature operation. + */ + int *recid; + + /** The hash algorithm to use when creating a signature. + * Setting this will enable RFC6979 compatible signature generation. + */ + const char *rfc6979_hash_alg; +} ltc_ecc_sig_opts; + /** the ECC params provided */ extern const ltc_ecc_curve ltc_ecc_curves[]; @@ -356,6 +368,21 @@ int ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_k int ecc_shared_secret(const ecc_key *private_key, const ecc_key *public_key, unsigned char *out, unsigned long *outlen); +int ecc_sign_hash_v2(const unsigned char *in, + unsigned long inlen, + unsigned char *out, + unsigned long *outlen, + ltc_ecc_sig_opts *opts, + const ecc_key *key); + +int ecc_verify_hash_v2(const unsigned char *sig, + unsigned long siglen, + const unsigned char *hash, + unsigned long hashlen, + ltc_ecc_sig_opts *opts, + int *stat, + const ecc_key *key); + #if defined(LTC_DER) int ecc_encrypt_key(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, @@ -365,7 +392,42 @@ int ecc_encrypt_key(const unsigned char *in, unsigned long inlen, int ecc_decrypt_key(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, const ecc_key *key); - +#endif /* LTC_DER */ + +#define ltc_ecc_sign_hash(i, il, o, ol, p, wp, k) \ + ecc_sign_hash_v2(i, il, o, ol, \ + &(ltc_ecc_sig_opts){ \ + .type = LTC_ECCSIG_ANSIX962, \ + .prng = p, \ + .wprng = wp, \ + }, k) +#define ltc_ecc_sign_hash_rfc7518(i, il, o, ol, p, wp, k) \ + ecc_sign_hash_v2(i, il, o, ol, \ + &(ltc_ecc_sig_opts){ \ + .type = LTC_ECCSIG_RFC7518, \ + .prng = p, \ + .wprng = wp, \ + }, k) + +#define ltc_ecc_verify_hash(s, sl, h, hl, st, k) \ + ecc_verify_hash_v2(s, sl, h, hl, \ + &(ltc_ecc_sig_opts){ \ + .type = LTC_ECCSIG_ANSIX962, \ + }, st, k) +#define ltc_ecc_verify_hash_rfc7518(s, sl, h, hl, st, k) \ + ecc_verify_hash_v2(s, sl, h, hl, \ + &(ltc_ecc_sig_opts){ \ + .type = LTC_ECCSIG_RFC7518, \ + }, st, k) + +#ifdef LTC_NO_DEPRECATED_APIS +#define ecc_sign_hash ltc_ecc_sign_hash +#define ecc_verify_hash ltc_ecc_verify_hash +#define ecc_sign_hash_rfc7518 ltc_ecc_sign_hash_rfc7518 +#define ecc_verify_hash_rfc7518 ltc_ecc_verify_hash_rfc7518 +#else /* LTC_NO_DEPRECATED_APIS */ +#if defined(LTC_DER) +LTC_DEPRECATED(ecc_sign_hash_v2) int ecc_sign_hash(const unsigned char *in, unsigned long inlen, unsigned char *out, @@ -374,14 +436,16 @@ int ecc_sign_hash(const unsigned char *in, int wprng, const ecc_key *key); +LTC_DEPRECATED(ecc_verify_hash_v2) int ecc_verify_hash(const unsigned char *sig, unsigned long siglen, const unsigned char *hash, unsigned long hashlen, int *stat, const ecc_key *key); -#endif +#endif /* LTC_DER */ +LTC_DEPRECATED(ecc_sign_hash_v2) int ecc_sign_hash_rfc7518(const unsigned char *in, unsigned long inlen, unsigned char *out, @@ -390,60 +454,20 @@ int ecc_sign_hash_rfc7518(const unsigned char *in, int wprng, const ecc_key *key); -int ecc_sign_hash_rfc7518_ex(const unsigned char *in, - unsigned long inlen, - unsigned char *out, - unsigned long *outlen, - prng_state *prng, - int wprng, - int *recid, - const ecc_key *key); - +LTC_DEPRECATED(ecc_verify_hash_v2) int ecc_verify_hash_rfc7518(const unsigned char *sig, unsigned long siglen, const unsigned char *hash, unsigned long hashlen, int *stat, const ecc_key *key); - -#if defined(LTC_SSH) -int ecc_sign_hash_rfc5656(const unsigned char *in, - unsigned long inlen, - unsigned char *out, - unsigned long *outlen, - prng_state *prng, - int wprng, - const ecc_key *key); - -int ecc_verify_hash_rfc5656(const unsigned char *sig, - unsigned long siglen, - const unsigned char *hash, - unsigned long hashlen, - int *stat, - const ecc_key *key); -#endif - -int ecc_sign_hash_eth27(const unsigned char *in, - unsigned long inlen, - unsigned char *out, - unsigned long *outlen, - prng_state *prng, - int wprng, - const ecc_key *key); - -int ecc_verify_hash_eth27(const unsigned char *sig, - unsigned long siglen, - const unsigned char *hash, - unsigned long hashlen, - int *stat, - const ecc_key *key); +#endif /* LTC_NO_DEPRECATED_APIS */ int ecc_recover_key(const unsigned char *sig, unsigned long siglen, const unsigned char *hash, unsigned long hashlen, - int recid, - ecc_signature_type sigformat, + ltc_ecc_sig_opts *opts, ecc_key *key); #endif diff --git a/src/headers/tomcrypt_private.h b/src/headers/tomcrypt_private.h index 153d22438..2a68b6276 100644 --- a/src/headers/tomcrypt_private.h +++ b/src/headers/tomcrypt_private.h @@ -473,15 +473,66 @@ int ecc_import_pkcs8_asn1(ltc_asn1_list *alg_id, ltc_asn1_list *priv_key, ecc_ke int ecc_import_with_curve(const unsigned char *in, unsigned long inlen, int type, ecc_key *key); int ecc_import_with_oid(const unsigned char *in, unsigned long inlen, unsigned long *oid, unsigned long oid_len, int type, ecc_key *key); +int ecc_sign_hash_rfc7518_internal(const unsigned char *in, + unsigned long inlen, + unsigned char *out, + unsigned long *outlen, + ltc_ecc_sig_opts *opts, + const ecc_key *key); + +int ecc_verify_hash_rfc7518_internal(const unsigned char *sig, + unsigned long siglen, + const unsigned char *hash, + unsigned long hashlen, + int *stat, + const ecc_key *key); + +#ifdef LTC_DER +int ecc_verify_hash_x962(const unsigned char *sig, + unsigned long siglen, + const unsigned char *hash, + unsigned long hashlen, + int *stat, + const ecc_key *key); +int ecc_sign_hash_x962(const unsigned char *in, + unsigned long inlen, + unsigned char *out, + unsigned long *outlen, + ltc_ecc_sig_opts *opts, + const ecc_key *key); +#endif + +#if defined(LTC_SSH) +int ecc_sign_hash_rfc5656(const unsigned char *in, + unsigned long inlen, + unsigned char *out, + unsigned long *outlen, + ltc_ecc_sig_opts *opts, + const ecc_key *key); + +int ecc_verify_hash_rfc5656(const unsigned char *sig, + unsigned long siglen, + const unsigned char *hash, + unsigned long hashlen, + int *stat, + const ecc_key *key); +#endif + +int ecc_sign_hash_eth27(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + ltc_ecc_sig_opts *opts, const ecc_key *key); + +int ecc_verify_hash_eth27(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int *stat, const ecc_key *key); int ecc_sign_hash_internal(const unsigned char *in, unsigned long inlen, - void *r, void *s, prng_state *prng, int wprng, - int *recid, const ecc_key *key); + void *r, void *s, ltc_ecc_sig_opts *opts, const ecc_key *key); int ecc_verify_hash_internal(void *r, void *s, const unsigned char *hash, unsigned long hashlen, int *stat, const ecc_key *key); -int ecc_rfc6979_key(const ecc_key *priv, const unsigned char *in, unsigned long inlen, ecc_key *key); +int ecc_rfc6979_key(const ecc_key *priv, const unsigned char *in, unsigned long inlen, const char *rfc6979_hash_alg, ecc_key *key); #ifdef LTC_SSH int ecc_ssh_ecdsa_encode_name(char *buffer, unsigned long *buflen, const ecc_key *key); diff --git a/src/misc/deprecated.c b/src/misc/deprecated.c new file mode 100644 index 000000000..051ce7ed4 --- /dev/null +++ b/src/misc/deprecated.c @@ -0,0 +1,82 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#ifndef LTC_NO_DEPRECATED_APIS + +#ifdef LTC_MECC +/** + Sign a message digest (ANSI X9.62 format) + @param in The message digest to sign + @param inlen The length of the digest + @param out [out] The destination for the signature + @param outlen [in/out] The max size and resulting size of the signature + @param prng An active PRNG state + @param wprng The index of the PRNG you wish to use + @param key A private ECC key + @return CRYPT_OK if successful +*/ +int ecc_sign_hash(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, const ecc_key *key) +{ + return ltc_ecc_sign_hash(in, inlen, out, outlen, prng, wprng, key); +} + +/** + Verify an ECC signature (ANSI X9.62 format) + @param sig The signature to verify + @param siglen The length of the signature (octets) + @param hash The hash (message digest) that was signed + @param hashlen The length of the hash (octets) + @param stat [out] Result of signature, 1==valid, 0==invalid + @param key The corresponding public ECC key + @return CRYPT_OK if successful (even if the signature is not valid) +*/ +int ecc_verify_hash(const unsigned char *sig, + unsigned long siglen, + const unsigned char *hash, + unsigned long hashlen, + int *stat, + const ecc_key *key) +{ + return ltc_ecc_verify_hash(sig, siglen, hash, hashlen, stat, key); +} + +/** + Sign a message digest (RFC7518 format) + @param in The message digest to sign + @param inlen The length of the digest + @param out [out] The destination for the signature + @param outlen [in/out] The max size and resulting size of the signature + @param opts The signature options that shall be applied + @param key A private ECC key + @return CRYPT_OK if successful +*/ +int ecc_sign_hash_rfc7518(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, const ecc_key *key) +{ + return ltc_ecc_sign_hash_rfc7518(in, inlen, out, outlen, prng, wprng, key); +} + +/** + Verify an ECC signature (RFC7518 format) + @param sig The signature to verify + @param siglen The length of the signature (octets) + @param hash The hash (message digest) that was signed + @param hashlen The length of the hash (octets) + @param stat [out] Result of signature, 1==valid, 0==invalid + @param key The corresponding public ECC key + @return CRYPT_OK if successful (even if the signature is not valid) +*/ +int ecc_verify_hash_rfc7518(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int *stat, const ecc_key *key) +{ + return ltc_ecc_verify_hash_rfc7518(sig, siglen, hash, hashlen, stat, key); +} +#endif /* LTC_MECC */ + +#endif /* LTC_NO_DEPRECATED_APIS */ diff --git a/src/pk/ecc/ecc_make_key.c b/src/pk/ecc/ecc_make_key.c index c8239cf1d..1b047417b 100644 --- a/src/pk/ecc/ecc_make_key.c +++ b/src/pk/ecc/ecc_make_key.c @@ -59,7 +59,6 @@ int ecc_generate_key(prng_state *prng, int wprng, ecc_key *key) goto error; } key->type = PK_PRIVATE; - key->rfc6979_hash_alg = NULL; /* success */ err = CRYPT_OK; diff --git a/src/pk/ecc/ecc_recover_key.c b/src/pk/ecc/ecc_recover_key.c index 3b6332b54..ebd1a410d 100644 --- a/src/pk/ecc/ecc_recover_key.c +++ b/src/pk/ecc/ecc_recover_key.c @@ -23,20 +23,21 @@ */ int ecc_recover_key(const unsigned char *sig, unsigned long siglen, const unsigned char *hash, unsigned long hashlen, - int recid, ecc_signature_type sigformat, ecc_key *key) + ltc_ecc_sig_opts *opts, ecc_key *key) { ecc_point *mG = NULL, *mQ = NULL, *mR = NULL; void *p, *m, *a, *b; void *r, *s, *v, *w, *t1, *t2, *u1, *u2, *v1, *v2, *e, *x, *y, *a_plus3; void *mu = NULL, *ma = NULL; void *mp = NULL; - int err; + int err, recid; unsigned long pbits, pbytes, i, shift_right; unsigned char ch, buf[MAXBLOCKSIZE]; LTC_ARGCHK(sig != NULL); LTC_ARGCHK(hash != NULL); LTC_ARGCHK(key != NULL); + LTC_ARGCHK(opts != NULL); /* BEWARE: requires sqrtmod_prime */ if (ltc_mp.sqrtmod_prime == NULL) { @@ -64,8 +65,9 @@ int ecc_recover_key(const unsigned char *sig, unsigned long siglen, err = CRYPT_MEM; goto error; } + recid = (opts->recid != NULL) ? *(opts->recid) : -1; - if (sigformat == LTC_ECCSIG_RFC7518) { + if (opts->type == LTC_ECCSIG_RFC7518) { /* RFC7518 format - raw (r,s) */ i = ltc_mp_unsigned_bin_size(key->dp.order); if (siglen != (2*i)) { @@ -75,7 +77,7 @@ int ecc_recover_key(const unsigned char *sig, unsigned long siglen, if ((err = ltc_mp_read_unsigned_bin(r, sig, i)) != CRYPT_OK) { goto error; } if ((err = ltc_mp_read_unsigned_bin(s, sig+i, i)) != CRYPT_OK) { goto error; } } - else if (sigformat == LTC_ECCSIG_ETH27) { + else if (opts->type == LTC_ECCSIG_ETH27) { /* Ethereum (v,r,s) format */ if (pk_oid_cmp_with_ulong("1.3.132.0.10", key->dp.oid, key->dp.oidlen) != CRYPT_OK) { /* Only valid for secp256k1 - OID 1.3.132.0.10 */ @@ -97,7 +99,7 @@ int ecc_recover_key(const unsigned char *sig, unsigned long siglen, if ((err = ltc_mp_read_unsigned_bin(s, sig+32, 32)) != CRYPT_OK) { goto error; } } #ifdef LTC_DER - else if (sigformat == LTC_ECCSIG_ANSIX962) { + else if (opts->type == LTC_ECCSIG_ANSIX962) { /* ANSI X9.62 format - ASN.1 encoded SEQUENCE{ INTEGER(r), INTEGER(s) } */ if ((err = der_decode_sequence_multi_ex(sig, siglen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT, LTC_ASN1_INTEGER, 1UL, r, @@ -106,7 +108,7 @@ int ecc_recover_key(const unsigned char *sig, unsigned long siglen, } #endif #ifdef LTC_SSH - else if (sigformat == LTC_ECCSIG_RFC5656) { + else if (opts->type == LTC_ECCSIG_RFC5656) { char name[64], name2[64]; unsigned long namelen = sizeof(name); unsigned long name2len = sizeof(name2); diff --git a/src/pk/ecc/ecc_rfc6979_key.c b/src/pk/ecc/ecc_rfc6979_key.c index f2bf9db71..1f313bd34 100644 --- a/src/pk/ecc/ecc_rfc6979_key.c +++ b/src/pk/ecc/ecc_rfc6979_key.c @@ -19,7 +19,7 @@ @param key [out] Newly created deterministic key @return CRYPT_OK if successful, upon error all allocated memory will be freed */ -int ecc_rfc6979_key(const ecc_key *priv, const unsigned char *in, unsigned long inlen, ecc_key *key) +int ecc_rfc6979_key(const ecc_key *priv, const unsigned char *in, unsigned long inlen, const char *rfc6979_hash_alg, ecc_key *key) { int err, hash = -1; unsigned char v[MAXBLOCKSIZE], k[MAXBLOCKSIZE]; @@ -32,10 +32,10 @@ int ecc_rfc6979_key(const ecc_key *priv, const unsigned char *in, unsigned long LTC_ARGCHK(key != NULL); LTC_ARGCHK(key->dp.size > 0); - if (priv->rfc6979_hash_alg == NULL) { + if (rfc6979_hash_alg == NULL) { return CRYPT_INVALID_ARG; } - hash = find_hash(priv->rfc6979_hash_alg); + hash = find_hash(rfc6979_hash_alg); if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } diff --git a/src/pk/ecc/ecc_set_curve.c b/src/pk/ecc/ecc_set_curve.c index ce9055a85..7947c6ebb 100644 --- a/src/pk/ecc/ecc_set_curve.c +++ b/src/pk/ecc/ecc_set_curve.c @@ -19,8 +19,6 @@ int ecc_set_curve(const ltc_ecc_curve *cu, ecc_key *key) return err; } - key->rfc6979_hash_alg = NULL; - /* A, B, order, prime, Gx, Gy */ if ((err = ltc_mp_read_radix(key->dp.prime, cu->prime, 16)) != CRYPT_OK) { goto error; } if ((err = ltc_mp_read_radix(key->dp.order, cu->order, 16)) != CRYPT_OK) { goto error; } diff --git a/src/pk/ecc/ecc_set_key.c b/src/pk/ecc/ecc_set_key.c index b7204b841..df8e7b137 100644 --- a/src/pk/ecc/ecc_set_key.c +++ b/src/pk/ecc/ecc_set_key.c @@ -46,7 +46,6 @@ int ecc_set_key(const unsigned char *in, unsigned long inlen, int type, ecc_key } key->type = type; - key->rfc6979_hash_alg = NULL; return CRYPT_OK; error: diff --git a/src/pk/ecc/ecc_sign_hash.c b/src/pk/ecc/ecc_sign_hash.c index c9c278b31..97023ac80 100644 --- a/src/pk/ecc/ecc_sign_hash.c +++ b/src/pk/ecc/ecc_sign_hash.c @@ -3,7 +3,25 @@ #include "tomcrypt_private.h" -#if defined(LTC_MECC) && defined(LTC_DER) +#if defined(LTC_MECC) + +typedef int (*ecc_sign_fn)(const unsigned char *in, + unsigned long inlen, + unsigned char *out, + unsigned long *outlen, + ltc_ecc_sig_opts *opts, + const ecc_key *key); + +static const ecc_sign_fn s_ecc_sign_hash[] = { +#ifdef LTC_DER + [LTC_ECCSIG_ANSIX962] = ecc_sign_hash_x962, +#endif + [LTC_ECCSIG_RFC7518] = ecc_sign_hash_rfc7518_internal, + [LTC_ECCSIG_ETH27] = ecc_sign_hash_eth27, +#ifdef LTC_SSH + [LTC_ECCSIG_RFC5656] = ecc_sign_hash_rfc5656, +#endif +}; /** Sign a message digest (ANSI X9.62 format) @@ -11,32 +29,22 @@ @param inlen The length of the digest @param out [out] The destination for the signature @param outlen [in/out] The max size and resulting size of the signature - @param prng An active PRNG state - @param wprng The index of the PRNG you wish to use + @param opts The signature options that shall be applied @param key A private ECC key @return CRYPT_OK if successful */ -int ecc_sign_hash(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - prng_state *prng, int wprng, const ecc_key *key) +int ecc_sign_hash_v2(const unsigned char *in, + unsigned long inlen, + unsigned char *out, + unsigned long *outlen, + ltc_ecc_sig_opts *opts, + const ecc_key *key) { - int err; - void *r, *s; - - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); - - if ((err = ltc_mp_init_multi(&r, &s, LTC_NULL)) != CRYPT_OK) return err; - if ((err = ecc_sign_hash_internal(in, inlen, r, s, prng, wprng, NULL, key)) != CRYPT_OK) goto error; - - /* store as ASN.1 SEQUENCE { r, s -- integer } */ - err = der_encode_sequence_multi(out, outlen, - LTC_ASN1_INTEGER, 1UL, r, - LTC_ASN1_INTEGER, 1UL, s, - LTC_ASN1_EOL, 0UL, NULL); -error: - ltc_mp_deinit_multi(r, s, LTC_NULL); - return err; + if (opts->type < 0 || opts->type >= LTC_ARRAY_SIZE(s_ecc_sign_hash)) + return CRYPT_PK_INVALID_TYPE; + if (s_ecc_sign_hash[opts->type] == NULL) + return CRYPT_PK_INVALID_TYPE; + return s_ecc_sign_hash[opts->type](in, inlen, out, outlen, opts, key); } #endif diff --git a/src/pk/ecc/ecc_sign_hash_eth27.c b/src/pk/ecc/ecc_sign_hash_eth27.c index dd06d14cb..4944d4527 100644 --- a/src/pk/ecc/ecc_sign_hash_eth27.c +++ b/src/pk/ecc/ecc_sign_hash_eth27.c @@ -11,14 +11,13 @@ @param inlen The length of the digest @param out [out] The destination for the signature @param outlen [in/out] The max size and resulting size of the signature - @param prng An active PRNG state - @param wprng The index of the PRNG you wish to use + @param opts The signature options that shall be applied @param key A private ECC key @return CRYPT_OK if successful */ int ecc_sign_hash_eth27(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, - prng_state *prng, int wprng, const ecc_key *key) + ltc_ecc_sig_opts *opts, const ecc_key *key) { int err, recid; void *r, *s; @@ -26,6 +25,7 @@ int ecc_sign_hash_eth27(const unsigned char *in, unsigned long inlen, LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(opts != NULL); LTC_ARGCHK(key != NULL); /* Only valid for secp256k1 - OID 1.3.132.0.10 */ @@ -38,7 +38,9 @@ int ecc_sign_hash_eth27(const unsigned char *in, unsigned long inlen, } if ((err = ltc_mp_init_multi(&r, &s, LTC_NULL)) != CRYPT_OK) return err; - if ((err = ecc_sign_hash_internal(in, inlen, r, s, prng, wprng, &recid, key)) != CRYPT_OK) goto error; + if (opts->recid == NULL) + opts->recid = &recid; + if ((err = ecc_sign_hash_internal(in, inlen, r, s, opts, key)) != CRYPT_OK) goto error; zeromem(out, 65); *outlen = 65; @@ -46,10 +48,12 @@ int ecc_sign_hash_eth27(const unsigned char *in, unsigned long inlen, if ((err = ltc_mp_to_unsigned_bin(r, out + 32 - i)) != CRYPT_OK) goto error; i = ltc_mp_unsigned_bin_size(s); if ((err = ltc_mp_to_unsigned_bin(s, out + 64 - i)) != CRYPT_OK) goto error; - out[64] = (unsigned char)(recid + 27); /* Recovery ID is 27/28 for Ethereum */ + out[64] = (unsigned char)(*(opts->recid) + 27); /* Recovery ID is 27/28 for Ethereum */ err = CRYPT_OK; error: + if (opts->recid == &recid) + opts->recid = NULL; ltc_mp_deinit_multi(r, s, LTC_NULL); return err; } diff --git a/src/pk/ecc/ecc_sign_hash_internal.c b/src/pk/ecc/ecc_sign_hash_internal.c index 5321ddefb..9e2db46bc 100644 --- a/src/pk/ecc/ecc_sign_hash_internal.c +++ b/src/pk/ecc/ecc_sign_hash_internal.c @@ -6,8 +6,7 @@ #ifdef LTC_MECC int ecc_sign_hash_internal(const unsigned char *in, unsigned long inlen, - void *r, void *s, prng_state *prng, int wprng, - int *recid, const ecc_key *key) + void *r, void *s, ltc_ecc_sig_opts *opts, const ecc_key *key) { ecc_key pubkey; void *e, *p, *b; @@ -19,6 +18,7 @@ int ecc_sign_hash_internal(const unsigned char *in, unsigned long inlen, LTC_ARGCHK(r != NULL); LTC_ARGCHK(s != NULL); LTC_ARGCHK(in != NULL); + LTC_ARGCHK(opts != NULL); LTC_ARGCHK(key != NULL); /* is this a private key? */ @@ -58,16 +58,16 @@ int ecc_sign_hash_internal(const unsigned char *in, unsigned long inlen, /* make up a key and export the public copy */ do { if ((err = ecc_copy_curve(key, &pubkey)) != CRYPT_OK) { goto errnokey; } - if (key->rfc6979_hash_alg != NULL) { - if ((err = ecc_rfc6979_key(key, in, inlen, &pubkey)) != CRYPT_OK) { goto errnokey; } + if (opts->rfc6979_hash_alg != NULL) { + if ((err = ecc_rfc6979_key(key, in, inlen, opts->rfc6979_hash_alg, &pubkey)) != CRYPT_OK) { goto errnokey; } } else { - if ((err = ecc_generate_key(prng, wprng, &pubkey)) != CRYPT_OK) { goto errnokey; } + if ((err = ecc_generate_key(opts->prng, opts->wprng, &pubkey)) != CRYPT_OK) { goto errnokey; } } /* find r = x1 mod n */ if ((err = ltc_mp_mod(pubkey.pubkey.x, p, r)) != CRYPT_OK) { goto error; } - if (recid) { + if (opts->recid) { /* find recovery ID (if needed) */ v = 0; if (ltc_mp_copy(pubkey.pubkey.x, s) != CRYPT_OK) { goto error; } @@ -82,7 +82,7 @@ int ecc_sign_hash_internal(const unsigned char *in, unsigned long inlen, if (ltc_mp_iszero(r) == LTC_MP_YES) { ecc_free(&pubkey); } else { - if ((err = rand_bn_upto(b, p, prng, wprng)) != CRYPT_OK) { goto error; } /* b = blinding value */ + if ((err = rand_bn_upto(b, p, opts->prng, opts->wprng)) != CRYPT_OK) { goto error; } /* b = blinding value */ /* find s = (e + xr)/k */ if ((err = ltc_mp_mulmod(pubkey.k, b, p, pubkey.k)) != CRYPT_OK) { goto error; } /* k = kb */ if ((err = ltc_mp_invmod(pubkey.k, p, pubkey.k)) != CRYPT_OK) { goto error; } /* k = 1/kb */ @@ -102,7 +102,7 @@ int ecc_sign_hash_internal(const unsigned char *in, unsigned long inlen, goto errnokey; } - if (recid) *recid = v; + if (opts->recid) *opts->recid = v; goto errnokey; error: diff --git a/src/pk/ecc/ecc_sign_hash_rfc5656.c b/src/pk/ecc/ecc_sign_hash_rfc5656.c index fd9f10e24..1330004ca 100644 --- a/src/pk/ecc/ecc_sign_hash_rfc5656.c +++ b/src/pk/ecc/ecc_sign_hash_rfc5656.c @@ -11,14 +11,13 @@ @param inlen The length of the digest @param out [out] The destination for the signature @param outlen [in/out] The max size and resulting size of the signature - @param prng An active PRNG state - @param wprng The index of the PRNG you wish to use + @param opts The signature options that shall be applied @param key A private ECC key @return CRYPT_OK if successful */ int ecc_sign_hash_rfc5656(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, - prng_state *prng, int wprng, const ecc_key *key) + ltc_ecc_sig_opts *opts, const ecc_key *key) { int err; void *r, *s; @@ -32,7 +31,7 @@ int ecc_sign_hash_rfc5656(const unsigned char *in, unsigned long inlen, if ((err = ecc_ssh_ecdsa_encode_name(name, &namelen, key)) != CRYPT_OK) return err; if ((err = ltc_mp_init_multi(&r, &s, LTC_NULL)) != CRYPT_OK) return err; - if ((err = ecc_sign_hash_internal(in, inlen, r, s, prng, wprng, NULL, key)) != CRYPT_OK) goto error; + if ((err = ecc_sign_hash_internal(in, inlen, r, s, opts, key)) != CRYPT_OK) goto error; /* Store as SSH data sequence, per RFC4251 */ err = ssh_encode_sequence_multi(out, outlen, diff --git a/src/pk/ecc/ecc_sign_hash_rfc7518.c b/src/pk/ecc/ecc_sign_hash_rfc7518.c index 1faefca15..a28f0c36c 100644 --- a/src/pk/ecc/ecc_sign_hash_rfc7518.c +++ b/src/pk/ecc/ecc_sign_hash_rfc7518.c @@ -11,16 +11,13 @@ @param inlen The length of the digest @param out [out] The destination for the signature @param outlen [in/out] The max size and resulting size of the signature - @param prng An active PRNG state - @param wprng The index of the PRNG you wish to use - @param recid [out] Recovery ID + @param opts The signature options that shall be applied @param key A private ECC key @return CRYPT_OK if successful */ -int ecc_sign_hash_rfc7518_ex(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - prng_state *prng, int wprng, - int *recid, const ecc_key *key) +int ecc_sign_hash_rfc7518_internal(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + ltc_ecc_sig_opts *opts, const ecc_key *key) { int err; void *r, *s; @@ -38,7 +35,7 @@ int ecc_sign_hash_rfc7518_ex(const unsigned char *in, unsigned long inlen, } if ((err = ltc_mp_init_multi(&r, &s, LTC_NULL)) != CRYPT_OK) return err; - if ((err = ecc_sign_hash_internal(in, inlen, r, s, prng, wprng, recid, key)) != CRYPT_OK) goto error; + if ((err = ecc_sign_hash_internal(in, inlen, r, s, opts, key)) != CRYPT_OK) goto error; zeromem(out, 2 * pbytes); *outlen = 2 * pbytes; @@ -52,22 +49,4 @@ int ecc_sign_hash_rfc7518_ex(const unsigned char *in, unsigned long inlen, return err; } -/** - Sign a message digest (RFC7518 format) - @param in The message digest to sign - @param inlen The length of the digest - @param out [out] The destination for the signature - @param outlen [in/out] The max size and resulting size of the signature - @param prng An active PRNG state - @param wprng The index of the PRNG you wish to use - @param key A private ECC key - @return CRYPT_OK if successful -*/ -int ecc_sign_hash_rfc7518(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - prng_state *prng, int wprng, const ecc_key *key) -{ - return ecc_sign_hash_rfc7518_ex(in, inlen, out, outlen, prng, wprng, NULL, key); -} - #endif diff --git a/src/pk/ecc/ecc_sign_hash_x962.c b/src/pk/ecc/ecc_sign_hash_x962.c new file mode 100644 index 000000000..8bf20fad6 --- /dev/null +++ b/src/pk/ecc/ecc_sign_hash_x962.c @@ -0,0 +1,44 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#if defined(LTC_MECC) && defined(LTC_DER) + +/** + Sign a message digest (ANSI X9.62 format) + @param in The message digest to sign + @param inlen The length of the digest + @param out [out] The destination for the signature + @param outlen [in/out] The max size and resulting size of the signature + @param opts The signature options that shall be applied + @param key A private ECC key + @return CRYPT_OK if successful +*/ +int ecc_sign_hash_x962(const unsigned char *in, + unsigned long inlen, + unsigned char *out, + unsigned long *outlen, + ltc_ecc_sig_opts *opts, + const ecc_key *key) +{ + int err; + void *r, *s; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + + if ((err = ltc_mp_init_multi(&r, &s, LTC_NULL)) != CRYPT_OK) return err; + if ((err = ecc_sign_hash_internal(in, inlen, r, s, opts, key)) != CRYPT_OK) goto error; + + /* store as ASN.1 SEQUENCE { r, s -- integer } */ + err = der_encode_sequence_multi(out, outlen, + LTC_ASN1_INTEGER, 1UL, r, + LTC_ASN1_INTEGER, 1UL, s, + LTC_ASN1_EOL, 0UL, NULL); +error: + ltc_mp_deinit_multi(r, s, LTC_NULL); + return err; +} + +#endif diff --git a/src/pk/ecc/ecc_verify_hash.c b/src/pk/ecc/ecc_verify_hash.c index 494c474e2..14ca74535 100644 --- a/src/pk/ecc/ecc_verify_hash.c +++ b/src/pk/ecc/ecc_verify_hash.c @@ -10,8 +10,26 @@ ECC Crypto, Tom St Denis */ +typedef int (*ecc_verify_fn)(const unsigned char *sig, + unsigned long siglen, + const unsigned char *hash, + unsigned long hashlen, + int *stat, + const ecc_key *key); + +static const ecc_verify_fn s_ecc_verify_hash[] = { +#ifdef LTC_DER + [LTC_ECCSIG_ANSIX962] = ecc_verify_hash_x962, +#endif + [LTC_ECCSIG_RFC7518] = ecc_verify_hash_rfc7518_internal, + [LTC_ECCSIG_ETH27] = ecc_verify_hash_eth27, +#ifdef LTC_SSH + [LTC_ECCSIG_RFC5656] = ecc_verify_hash_rfc5656, +#endif +}; + /** - Verify an ECC signature (ANSI X9.62 format) + Verify an ECC signature @param sig The signature to verify @param siglen The length of the signature (octets) @param hash The hash (message digest) that was signed @@ -20,28 +38,19 @@ @param key The corresponding public ECC key @return CRYPT_OK if successful (even if the signature is not valid) */ -int ecc_verify_hash(const unsigned char *sig, unsigned long siglen, - const unsigned char *hash, unsigned long hashlen, - int *stat, const ecc_key *key) +int ecc_verify_hash_v2(const unsigned char *sig, + unsigned long siglen, + const unsigned char *hash, + unsigned long hashlen, + ltc_ecc_sig_opts *opts, + int *stat, + const ecc_key *key) { - void *r, *s; - int err; - - LTC_ARGCHK(sig != NULL); - - if ((err = ltc_mp_init_multi(&r, &s, NULL)) != CRYPT_OK) return err; - - /* ANSI X9.62 format - ASN.1 encoded SEQUENCE{ INTEGER(r), INTEGER(s) } */ - if ((err = der_decode_sequence_multi_ex(sig, siglen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT, - LTC_ASN1_INTEGER, 1UL, r, - LTC_ASN1_INTEGER, 1UL, s, - LTC_ASN1_EOL, 0UL, LTC_NULL)) != CRYPT_OK) { goto error; } - - err = ecc_verify_hash_internal(r, s, hash, hashlen, stat, key); - -error: - ltc_mp_deinit_multi(r, s, LTC_NULL); - return err; + if (opts->type < 0 || opts->type >= LTC_ARRAY_SIZE(s_ecc_verify_hash)) + return CRYPT_PK_INVALID_TYPE; + if (s_ecc_verify_hash[opts->type] == NULL) + return CRYPT_PK_INVALID_TYPE; + return s_ecc_verify_hash[opts->type](sig, siglen, hash, hashlen, stat, key); } #endif diff --git a/src/pk/ecc/ecc_verify_hash_eth27.c b/src/pk/ecc/ecc_verify_hash_eth27.c index 587ecd2da..4f6394f7f 100644 --- a/src/pk/ecc/ecc_verify_hash_eth27.c +++ b/src/pk/ecc/ecc_verify_hash_eth27.c @@ -6,7 +6,7 @@ #ifdef LTC_MECC /** - @file ecc_verify_hash.c + @file ecc_verify_hash_eth27.c ECC Crypto, Tom St Denis */ diff --git a/src/pk/ecc/ecc_verify_hash_rfc7518.c b/src/pk/ecc/ecc_verify_hash_rfc7518.c index b048bdc20..ce2aa673f 100644 --- a/src/pk/ecc/ecc_verify_hash_rfc7518.c +++ b/src/pk/ecc/ecc_verify_hash_rfc7518.c @@ -6,21 +6,11 @@ #ifdef LTC_MECC /** - @file ecc_verify_hash.c + @file ecc_verify_hash_rfc7518.c ECC Crypto, Tom St Denis */ -/** - Verify an ECC signature (RFC7518 format) - @param sig The signature to verify - @param siglen The length of the signature (octets) - @param hash The hash (message digest) that was signed - @param hashlen The length of the hash (octets) - @param stat [out] Result of signature, 1==valid, 0==invalid - @param key The corresponding public ECC key - @return CRYPT_OK if successful (even if the signature is not valid) -*/ -int ecc_verify_hash_rfc7518(const unsigned char *sig, unsigned long siglen, +int ecc_verify_hash_rfc7518_internal(const unsigned char *sig, unsigned long siglen, const unsigned char *hash, unsigned long hashlen, int *stat, const ecc_key *key) { diff --git a/src/pk/ecc/ecc_verify_hash_x962.c b/src/pk/ecc/ecc_verify_hash_x962.c new file mode 100644 index 000000000..d82b16347 --- /dev/null +++ b/src/pk/ecc/ecc_verify_hash_x962.c @@ -0,0 +1,37 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +#if defined(LTC_MECC) && defined(LTC_DER) + +/** + @file ecc_verify_hash_x962.c + ECC Crypto, Tom St Denis +*/ + +int ecc_verify_hash_x962(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int *stat, const ecc_key *key) +{ + void *r, *s; + int err; + + LTC_ARGCHK(sig != NULL); + + if ((err = ltc_mp_init_multi(&r, &s, NULL)) != CRYPT_OK) return err; + + /* ANSI X9.62 format - ASN.1 encoded SEQUENCE{ INTEGER(r), INTEGER(s) } */ + if ((err = der_decode_sequence_multi_ex(sig, siglen, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT, + LTC_ASN1_INTEGER, 1UL, r, + LTC_ASN1_INTEGER, 1UL, s, + LTC_ASN1_EOL, 0UL, LTC_NULL)) != CRYPT_OK) { goto error; } + + err = ecc_verify_hash_internal(r, s, hash, hashlen, stat, key); + +error: + ltc_mp_deinit_multi(r, s, LTC_NULL); + return err; +} + +#endif diff --git a/tests/ecc_test.c b/tests/ecc_test.c index b70666590..0d3cdf368 100644 --- a/tests/ecc_test.c +++ b/tests/ecc_test.c @@ -316,7 +316,7 @@ static int s_ecc_issue443_447(void) DO(ecc_find_curve("secp256r1", &cu)); DO(ecc_set_curve(cu, &key)); DO(ecc_set_key(pub1, sizeof(pub1), PK_PUBLIC, &key)); - err = ecc_verify_hash_rfc7518(sig1, sizeof(sig1), hash, hashlen, &stat, &key); /* should fail */ + err = ecc_verify_hash_rfc7518_internal(sig1, sizeof(sig1), hash, hashlen, &stat, &key); /* should fail */ ecc_free(&key); if (err != CRYPT_INVALID_PACKET) return CRYPT_FAIL_TESTVECTOR; @@ -325,7 +325,7 @@ static int s_ecc_issue443_447(void) DO(ecc_find_curve("secp521r1", &cu)); DO(ecc_set_curve(cu, &key)); DO(ecc_set_key(pub2, sizeof(pub2), PK_PUBLIC, &key)); - err = ecc_verify_hash_rfc7518(sig2, sizeof(sig2), hash, hashlen, &stat, &key); /* should fail */ + err = ecc_verify_hash_rfc7518_internal(sig2, sizeof(sig2), hash, hashlen, &stat, &key); /* should fail */ ecc_free(&key); if (err != CRYPT_INVALID_PACKET) return CRYPT_FAIL_TESTVECTOR; @@ -401,6 +401,10 @@ static int s_ecc_old_api(void) unsigned long x, y, z, s; int stat, stat2; ecc_key usera, userb, pubKey, privKey; + ltc_ecc_sig_opts sig_opts = { + .prng = &yarrow_prng, + .wprng = find_prng ("yarrow") + }; int low, high; ecc_sizes(&low, &high); @@ -500,10 +504,10 @@ static int s_ecc_old_api(void) buf[0][ch] = ch; } x = sizeof (buf[1]); - DO(ecc_sign_hash (buf[0], 16, buf[1], &x, &yarrow_prng, find_prng ("yarrow"), &privKey)); - DO(ecc_verify_hash (buf[1], x, buf[0], 16, &stat, &pubKey)); + DO(ecc_sign_hash_v2(buf[0], 16, buf[1], &x, &sig_opts, &privKey)); + DO(ecc_verify_hash_v2(buf[1], x, buf[0], 16, &sig_opts, &stat, &pubKey)); buf[0][0] ^= 1; - DO(ecc_verify_hash (buf[1], x, buf[0], 16, &stat2, &privKey)); + DO(ecc_verify_hash_v2(buf[1], x, buf[0], 16, &sig_opts, &stat2, &privKey)); if (!(stat == 1 && stat2 == 0)) { fprintf(stderr, "ecc_verify_hash failed %d, %d, ", stat, stat2); return 1; @@ -513,10 +517,10 @@ static int s_ecc_old_api(void) buf[0][ch] = ch; } x = sizeof (buf[1]); - DO(ecc_sign_hash_rfc7518(buf[0], 16, buf[1], &x, &yarrow_prng, find_prng ("yarrow"), &privKey)); - DO(ecc_verify_hash_rfc7518(buf[1], x, buf[0], 16, &stat, &pubKey)); + DO(ecc_sign_hash_v2(buf[0], 16, buf[1], &x, &sig_opts, &privKey)); + DO(ecc_verify_hash_v2(buf[1], x, buf[0], 16, &sig_opts, &stat, &pubKey)); buf[0][0] ^= 1; - DO(ecc_verify_hash_rfc7518(buf[1], x, buf[0], 16, &stat2, &privKey)); + DO(ecc_verify_hash_v2(buf[1], x, buf[0], 16, &sig_opts, &stat2, &privKey)); if (!(stat == 1 && stat2 == 0)) { fprintf(stderr, "ecc_verify_hash_rfc7518 failed %d, %d, ", stat, stat2); return 1; @@ -549,13 +553,29 @@ int ecc_key_cmp(const int should_type, const ecc_key *should, const ecc_key *is) static int s_ecc_new_api(void) { - int i, j, stat; + int i, stat; const ltc_ecc_curve* dp; ecc_key key, privkey, pubkey; unsigned char buf[1000]; - unsigned long len; - unsigned char data16[16] = { 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1 }; + unsigned long len, j; + unsigned char data16[MAXBLOCKSIZE]; unsigned long len16; + const ecc_signature_type sig_algs[] = { +#ifdef LTC_DER + LTC_ECCSIG_ANSIX962, +#endif + LTC_ECCSIG_RFC7518, + LTC_ECCSIG_ETH27, +#ifdef LTC_SSH + LTC_ECCSIG_RFC5656, +#endif + }; + ltc_ecc_sig_opts sig_opts = { + .type = LTC_ECCSIG_ANSIX962, + .prng = &yarrow_prng, + .wprng = find_prng ("yarrow") + }; + XMEMSET(data16, 0xd1, sizeof(data16)); for (i = 0; i < (int)LTC_ARRAY_SIZE(curvenames); i++) { DO(ecc_find_curve(curvenames[i], &dp)); @@ -606,50 +626,50 @@ static int s_ecc_new_api(void) DO(ecc_set_curve(dp, &pubkey)); DO(ecc_set_key(buf, len, PK_PUBLIC, &pubkey)); - /* test signature */ - len = sizeof(buf); - DO(ecc_sign_hash(data16, 16, buf, &len, &yarrow_prng, find_prng ("yarrow"), &privkey)); - stat = 0; - DO(ecc_verify_hash(buf, len, data16, 16, &stat, &pubkey)); - if (stat != 1) return CRYPT_FAIL_TESTVECTOR; - -#ifdef LTC_SSH - /* test SSH+ECDSA/RFC5656 signature */ - len = sizeof(buf); - DO(ecc_sign_hash_rfc5656(data16, 16, buf, &len, &yarrow_prng, find_prng ("yarrow"), &privkey)); - stat = 0; - DO(ecc_verify_hash_rfc5656(buf, len, data16, 16, &stat, &pubkey)); - if (stat != 1) return CRYPT_FAIL_TESTVECTOR; -#endif + for (j = 0; j < LTC_ARRAY_SIZE(sig_algs); ++j) { + /* test signature */ + if (sig_algs[j] == LTC_ECCSIG_ETH27 && XSTRCMP(dp->OID, "1.3.132.0.10")) + continue; + len = sizeof(buf); + sig_opts.type = sig_algs[j]; + DO(ecc_sign_hash_v2(data16, privkey.dp.size, buf, &len, &sig_opts, &privkey)); + stat = 0; + DO(ecc_verify_hash_v2(buf, len, data16, privkey.dp.size, &sig_opts, &stat, &pubkey)); + if (stat != 1) return CRYPT_FAIL_TESTVECTOR; #ifdef LTC_ECC_SHAMIR - if (strcmp(ltc_mp.name, "TomsFastMath") != 0) { - /* XXX-FIXME: TFM does not support sqrtmod_prime */ - int found = 0; - ecc_key reckey; - /* test recovery */ - len = sizeof(buf); - DO(ecc_sign_hash(data16, 16, buf, &len, &yarrow_prng, find_prng ("yarrow"), &privkey)); - DO(ecc_set_curve(dp, &reckey)); - for (j = 0; j < 2*(1+(int)privkey.dp.cofactor); j++) { - stat = ecc_recover_key(buf, len, data16, 16, j, LTC_ECCSIG_ANSIX962, &reckey); - if (stat != CRYPT_OK) continue; /* last two will almost always fail, only possible if x<(prime mod order) */ - stat = ecc_key_cmp(PK_PUBLIC, &pubkey, &reckey); - if (stat == CRYPT_OK) found++; + if (strcmp(ltc_mp.name, "TomsFastMath") != 0) { + /* XXX-FIXME: TFM does not support sqrtmod_prime */ + int found = 0, recid; + ecc_key reckey; + /* test recovery */ + sig_opts.recid = &recid; + len = sizeof(buf); + DO(ecc_sign_hash_v2(data16, privkey.dp.size, buf, &len, &sig_opts, &privkey)); + DO(ecc_set_curve(dp, &reckey)); + for (j = 0; j < 2*(1+privkey.dp.cofactor); j++) { + recid = j; + stat = ecc_recover_key(buf, len, data16, privkey.dp.size, &sig_opts, &reckey); + if (stat != CRYPT_OK) continue; /* last two will almost always fail, only possible if x<(prime mod order) */ + stat = ecc_key_cmp(PK_PUBLIC, &pubkey, &reckey); + if (stat == CRYPT_OK) found++; + } + sig_opts.recid = NULL; + if (found != 1) return CRYPT_FAIL_TESTVECTOR; /* unique match */ + ecc_free(&reckey); } - if (found != 1) return CRYPT_FAIL_TESTVECTOR; /* unique match */ - ecc_free(&reckey); - } #endif + } + /* test encryption */ len = sizeof(buf); DO(ecc_encrypt_key(data16, 16, buf, &len, &yarrow_prng, find_prng("yarrow"), find_hash("sha256"), &pubkey)); zeromem(data16, 16); len16 = 16; DO(ecc_decrypt_key(buf, len, data16, &len16, &privkey)); - if (len16 != 16) return CRYPT_FAIL_TESTVECTOR; - for (j = 0; j < 16; j++) if (data16[j] != 0xd1) return CRYPT_FAIL_TESTVECTOR; + if ((int)len16 != 16) return CRYPT_FAIL_TESTVECTOR; + for (j = 0; (int)j < 16; j++) if (data16[j] != 0xd1) return CRYPT_FAIL_TESTVECTOR; /* cleanup */ ecc_free(&privkey); @@ -993,6 +1013,11 @@ static int s_ecc_rfc6979(void) char name[128], tmp[MAXBLOCKSIZE]; unsigned int t, s, i, h; unsigned long pklen, hashlen, curvelen, inputlen, siglen, shouldlen, shouldlen2; + ltc_ecc_sig_opts sig_opts = { + .type = LTC_ECCSIG_RFC7518, + .prng = &yarrow_prng, + .wprng = find_prng ("yarrow") + }; for (t = 0; tests[t].curve; ++t) { curvelen = XSTRLEN(tests[t].curve); XMEMCPY(name, tests[t].curve, curvelen); @@ -1020,9 +1045,9 @@ static int s_ecc_rfc6979(void) XMEMCPY(&name[curvelen + inputlen], hashes[h], 7); hashlen = sizeof(hash); DOX(hash_memory(find_hash(hashes[h]), inputs[i], XSTRLEN(inputs[i]), hash, &hashlen), name); - ECC_SET_RFC6979_HASH_ALG(&key, hashes[h]); + sig_opts.rfc6979_hash_alg = hashes[h]; siglen = sizeof(sig); - DOX(ecc_sign_hash_rfc7518(hash, hashlen, sig, &siglen, &yarrow_prng, find_prng ("yarrow"), &key), name); + DOX(ecc_sign_hash_v2(hash, hashlen, sig, &siglen, &sig_opts, &key), name); XMEMSET(should, 0, sizeof(should)); shouldlen = sizeof(should); DOX(base16_decode(tests[t].signatures[s].r, XSTRLEN(tests[t].signatures[s].r), should, &shouldlen), name); @@ -1907,6 +1932,11 @@ static int s_ecc_test_ethereum(void) unsigned char buf[128]; unsigned long len; unsigned char data16[16] = { 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1 }; + ltc_ecc_sig_opts sig_opts = { + .type = LTC_ECCSIG_ETH27, + .prng = &yarrow_prng, + .wprng = find_prng ("yarrow"), + }; DO(ecc_find_curve("SECP256K1", &dp)); @@ -1914,15 +1944,15 @@ static int s_ecc_test_ethereum(void) /* test Ethereum signature */ len = sizeof(buf); - DO(ecc_sign_hash_eth27(data16, 16, buf, &len, &yarrow_prng, find_prng ("yarrow"), &key)); + DO(ecc_sign_hash_v2(data16, 16, buf, &len, &sig_opts, &key)); stat = 0; - DO(ecc_verify_hash_eth27(buf, len, data16, 16, &stat, &key)); + DO(ecc_verify_hash_v2(buf, len, data16, 16, &sig_opts, &stat, &key)); if (stat != 1) return CRYPT_FAIL_TESTVECTOR; /* XXX-FIXME: TFM does not support sqrtmod_prime */ if (strcmp(ltc_mp.name, "TomsFastMath") != 0) { DO(ecc_set_curve(dp, &reckey)); - DO(ecc_recover_key(buf, len, data16, 16, -1, LTC_ECCSIG_ETH27, &reckey)); + DO(ecc_recover_key(buf, len, data16, 16, &sig_opts, &reckey)); DO(ecc_key_cmp(PK_PUBLIC, &key, &reckey)); /* cleanup */ @@ -1962,6 +1992,11 @@ static int s_ecc_test_recovery(void) 0xb7, 0x3c, 0x97, 0x55, 0xfa, 0x69, 0xf8, 0xef, 0xe9, 0xcf, 0x12, 0xaf, 0x48, 0x25, 0xe3, 0xe0, 0x1b }; + ltc_ecc_sig_opts sig_opts = { + .prng = &yarrow_prng, + .wprng = find_prng ("yarrow"), + .recid = &recid + }; /* XXX-FIXME: TFM does not support sqrtmod_prime */ if (strcmp(ltc_mp.name, "TomsFastMath") == 0) return CRYPT_NOP; @@ -1973,18 +2008,23 @@ static int s_ecc_test_recovery(void) DO(ecc_set_key(eth_pubkey, sizeof(eth_pubkey), PK_PUBLIC, &pubkey)); DO(ecc_set_curve(dp, &reckey)); - DO(ecc_recover_key(eth_sig, sizeof(eth_sig)-1, eth_hash, sizeof(eth_hash), 0, LTC_ECCSIG_RFC7518, &reckey)); + recid = 0; + sig_opts.type = LTC_ECCSIG_RFC7518; + DO(ecc_recover_key(eth_sig, sizeof(eth_sig)-1, eth_hash, sizeof(eth_hash), &sig_opts, &reckey)); DO(ecc_key_cmp(PK_PUBLIC, &pubkey, &reckey)); ecc_free(&reckey); DO(ecc_set_curve(dp, &reckey)); - DO(ecc_recover_key(eth_sig, sizeof(eth_sig), eth_hash, sizeof(eth_hash), -1, LTC_ECCSIG_ETH27, &reckey)); + recid = -1; + sig_opts.type = LTC_ECCSIG_ETH27; + DO(ecc_recover_key(eth_sig, sizeof(eth_sig), eth_hash, sizeof(eth_hash), &sig_opts, &reckey)); DO(ecc_key_cmp(PK_PUBLIC, &pubkey, &reckey)); ecc_free(&reckey); ecc_free(&pubkey); #endif + sig_opts.type = LTC_ECCSIG_RFC7518; for (i = 0; i < (int)LTC_ARRAY_SIZE(curvenames); i++) { DO(ecc_find_curve(curvenames[i], &dp)); @@ -2013,16 +2053,16 @@ static int s_ecc_test_recovery(void) /* test signature */ len = sizeof(buf); recid = 0; - DO(ecc_sign_hash_rfc7518_ex(data16, 16, buf, &len, &yarrow_prng, find_prng ("yarrow"), &recid, &privkey)); + DO(ecc_sign_hash_v2(data16, 16, buf, &len, &sig_opts, &privkey)); /* test verification */ stat = 0; - DO(ecc_verify_hash_rfc7518(buf, len, data16, 16, &stat, &pubkey)); + DO(ecc_verify_hash_v2(buf, len, data16, 16, &sig_opts, &stat, &pubkey)); if (stat != 1) return CRYPT_FAIL_TESTVECTOR; /* test recovery */ DO(ecc_set_curve(dp, &reckey)); - stat = ecc_recover_key(buf, len, data16, 16, recid, LTC_ECCSIG_RFC7518, &reckey); + stat = ecc_recover_key(buf, len, data16, 16, &sig_opts, &reckey); if (stat != CRYPT_OK) return CRYPT_FAIL_TESTVECTOR; DO(ecc_key_cmp(PK_PUBLIC, &pubkey, &reckey)); From 20cce10545884c157b15e90f39db19711253f205 Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Thu, 16 Oct 2025 10:30:42 +0200 Subject: [PATCH 13/17] Add tests for deprecated APIs Signed-off-by: Steffen Jaeckel --- .github/workflows/main.yml | 1 + src/misc/crypt/crypt.c | 3 +++ tests/deprecated_test.c | 48 ++++++++++++++++++++++++++++++++++++++ tests/sources.cmake | 1 + tests/test.c | 1 + tests/tomcrypt_test.h | 1 + 6 files changed, 55 insertions(+) create mode 100644 tests/deprecated_test.c diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index bac91dea0..14be6ec0a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -52,6 +52,7 @@ jobs: - { BUILDNAME: 'NO_FAST', BUILDOPTIONS: '-DLTC_NO_FAST', BUILDSCRIPT: '.ci/run.sh' } - { BUILDNAME: 'NO_FAST+SMALL+NO_TABLES', BUILDOPTIONS: '-DLTC_NO_FAST -DLTC_SMALL_CODE -DLTC_NO_TABLES', BUILDSCRIPT: '.ci/run.sh' } - { BUILDNAME: 'NO_ASM', BUILDOPTIONS: '-DLTC_NO_ASM', BUILDSCRIPT: '.ci/run.sh' } + - { BUILDNAME: 'NO_DEPRECATED_APIS', BUILDOPTIONS: '-DLTC_NO_DEPRECATED_APIS', BUILDSCRIPT: '.ci/run.sh' } - { BUILDNAME: 'NO_TIMING_RESISTANCE', BUILDOPTIONS: '-DLTC_NO_ECC_TIMING_RESISTANT -DLTC_NO_RSA_BLINDING', BUILDSCRIPT: '.ci/run.sh' } - { BUILDNAME: 'FORTUNA_CUSTOM_OPTIONS', BUILDOPTIONS: '-DLTC_FORTUNA_USE_ENCRYPT_ONLY -DLTC_FORTUNA_RESEED_RATELIMIT_STATIC', BUILDSCRIPT: '.ci/run.sh' } - { BUILDNAME: 'PTHREAD', BUILDOPTIONS: '-DLTC_PTHREAD', BUILDSCRIPT: '.ci/run.sh' } diff --git a/src/misc/crypt/crypt.c b/src/misc/crypt/crypt.c index b16d6318a..62d2e2c82 100644 --- a/src/misc/crypt/crypt.c +++ b/src/misc/crypt/crypt.c @@ -581,6 +581,9 @@ const char *crypt_build_settings = #endif #if defined(LTC_CLOCK_GETTIME) " LTC_CLOCK_GETTIME " +#endif +#if defined(LTC_NO_DEPRECATED_APIS) + " LTC_NO_DEPRECATED_APIS " #endif "\n" ; diff --git a/tests/deprecated_test.c b/tests/deprecated_test.c new file mode 100644 index 000000000..f2ed3638b --- /dev/null +++ b/tests/deprecated_test.c @@ -0,0 +1,48 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#define LTC_DEPRECATED(x) +#include + +#ifdef LTC_MECC +static void s_ecc_test(void) +{ + const ltc_ecc_curve* dp; + unsigned char buf[128]; + unsigned long len; + ecc_key key; + int stat; + unsigned char data16[16] = { 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1 }; + + /* We need an MPI provider for ECC */ + if (ltc_mp.name == NULL) return; + + ENSURE(ltc_ecc_curves[0].OID != NULL); + + DO(ecc_find_curve(ltc_ecc_curves[0].OID, &dp)); + DO(ecc_make_key_ex(&yarrow_prng, find_prng ("yarrow"), &key, dp)); + + len = sizeof(buf); + DO(ecc_sign_hash(data16, 16, buf, &len, &yarrow_prng, find_prng ("yarrow"), &key)); + stat = 0; + DO(ecc_verify_hash(buf, len, data16, 16, &stat, &key)); + + SHOULD_FAIL(ecc_verify_hash_rfc7518(buf, len, data16, 16, &stat, &key)); + + len = sizeof(buf); + DO(ecc_sign_hash_rfc7518(data16, 16, buf, &len, &yarrow_prng, find_prng ("yarrow"), &key)); + stat = 0; + DO(ecc_verify_hash_rfc7518(buf, len, data16, 16, &stat, &key)); + + SHOULD_FAIL(ecc_verify_hash(buf, len, data16, 16, &stat, &key)); + + ecc_free(&key); +} +#endif + +int deprecated_test(void) +{ +#ifdef LTC_MECC + s_ecc_test(); +#endif + return 0; +} diff --git a/tests/sources.cmake b/tests/sources.cmake index 590607aa4..b6eed361f 100644 --- a/tests/sources.cmake +++ b/tests/sources.cmake @@ -5,6 +5,7 @@ base64_test.c bcrypt_test.c cipher_hash_test.c common.c +deprecated_test.c der_test.c dh_test.c dsa_test.c diff --git a/tests/test.c b/tests/test.c index 836720c63..e77b292cd 100644 --- a/tests/test.c +++ b/tests/test.c @@ -37,6 +37,7 @@ static const test_function test_functions[] = LTC_TEST_FN(file_test), LTC_TEST_FN(multi_test), LTC_TEST_FN(pem_test), + LTC_TEST_FN(deprecated_test), /* keep the prng_test always at the end as * it has to be handled specially when * testing with LTC_PTHREAD enabled diff --git a/tests/tomcrypt_test.h b/tests/tomcrypt_test.h index c2a582e7d..4488a450c 100644 --- a/tests/tomcrypt_test.h +++ b/tests/tomcrypt_test.h @@ -45,6 +45,7 @@ int ssh_test(void); int bcrypt_test(void); int no_null_termination_check_test(void); int pk_oid_test(void); +int deprecated_test(void); #ifdef LTC_PKCS_1 struct ltc_prng_descriptor* no_prng_desc_get(void); From b90d84b9d31889621e2a9bca338af2b2e15741a8 Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Thu, 16 Oct 2025 10:30:51 +0200 Subject: [PATCH 14/17] Update makefiles --- libtomcrypt_VS2008.vcproj | 20 ++++++++++++++++ makefile.mingw | 50 ++++++++++++++++++++------------------- makefile.msvc | 50 ++++++++++++++++++++------------------- makefile.unix | 50 ++++++++++++++++++++------------------- makefile_include.mk | 50 ++++++++++++++++++++------------------- sources.cmake | 5 ++++ 6 files changed, 129 insertions(+), 96 deletions(-) diff --git a/libtomcrypt_VS2008.vcproj b/libtomcrypt_VS2008.vcproj index 72d7fb779..200dc670a 100644 --- a/libtomcrypt_VS2008.vcproj +++ b/libtomcrypt_VS2008.vcproj @@ -1387,6 +1387,10 @@ RelativePath="src\misc\crc32.c" > + + @@ -2277,6 +2281,14 @@ RelativePath="src\pk\asn1\x509\x509_encode_subject_public_key_info.c" > + + + + + + @@ -2558,6 +2574,10 @@ RelativePath="src\pk\ecc\ecc_verify_hash_rfc7518.c" > + + diff --git a/makefile.mingw b/makefile.mingw index 1c323f103..2dc38b9c5 100644 --- a/makefile.mingw +++ b/makefile.mingw @@ -109,8 +109,8 @@ src/misc/crypt/crypt_register_all_ciphers.o src/misc/crypt/crypt_register_all_ha src/misc/crypt/crypt_register_all_prngs.o src/misc/crypt/crypt_register_cipher.o \ src/misc/crypt/crypt_register_hash.o src/misc/crypt/crypt_register_prng.o src/misc/crypt/crypt_sizes.o \ src/misc/crypt/crypt_unregister_cipher.o src/misc/crypt/crypt_unregister_hash.o \ -src/misc/crypt/crypt_unregister_prng.o src/misc/error_to_string.o src/misc/hkdf/hkdf.o \ -src/misc/hkdf/hkdf_test.o src/misc/mem_neq.o src/misc/padding/padding_depad.o \ +src/misc/crypt/crypt_unregister_prng.o src/misc/deprecated.o src/misc/error_to_string.o \ +src/misc/hkdf/hkdf.o src/misc/hkdf/hkdf_test.o src/misc/mem_neq.o src/misc/padding/padding_depad.o \ src/misc/padding/padding_pad.o src/misc/password_free.o src/misc/pbes/pbes.o src/misc/pbes/pbes1.o \ src/misc/pbes/pbes2.o src/misc/pem/pem.o src/misc/pem/pem_pkcs.o src/misc/pem/pem_read.o \ src/misc/pem/pem_ssh.o src/misc/pkcs12/pkcs12_kdf.o src/misc/pkcs12/pkcs12_utf8_to_utf16.o \ @@ -176,9 +176,10 @@ src/pk/asn1/oid/pk_get.o src/pk/asn1/oid/pk_oid_cmp.o src/pk/asn1/oid/pk_oid_str src/pk/asn1/pkcs8/pkcs8_decode_flexi.o src/pk/asn1/pkcs8/pkcs8_get.o \ src/pk/asn1/x509/x509_decode_public_key_from_certificate.o src/pk/asn1/x509/x509_decode_spki.o \ src/pk/asn1/x509/x509_decode_subject_public_key_info.o \ -src/pk/asn1/x509/x509_encode_subject_public_key_info.o src/pk/dh/dh.o src/pk/dh/dh_check_pubkey.o \ -src/pk/dh/dh_export.o src/pk/dh/dh_export_key.o src/pk/dh/dh_free.o src/pk/dh/dh_generate_key.o \ -src/pk/dh/dh_import.o src/pk/dh/dh_import_pkcs8.o src/pk/dh/dh_set.o src/pk/dh/dh_set_pg_dhparam.o \ +src/pk/asn1/x509/x509_encode_subject_public_key_info.o src/pk/asn1/x509/x509_get_pka.o \ +src/pk/asn1/x509/x509_import_spki.o src/pk/dh/dh.o src/pk/dh/dh_check_pubkey.o src/pk/dh/dh_export.o \ +src/pk/dh/dh_export_key.o src/pk/dh/dh_free.o src/pk/dh/dh_generate_key.o src/pk/dh/dh_import.o \ +src/pk/dh/dh_import_pkcs8.o src/pk/dh/dh_set.o src/pk/dh/dh_set_pg_dhparam.o \ src/pk/dh/dh_shared_secret.o src/pk/dsa/dsa_decrypt_key.o src/pk/dsa/dsa_encrypt_key.o \ src/pk/dsa/dsa_export.o src/pk/dsa/dsa_free.o src/pk/dsa/dsa_generate_key.o \ src/pk/dsa/dsa_generate_pqg.o src/pk/dsa/dsa_import.o src/pk/dsa/dsa_import_pkcs8.o \ @@ -194,18 +195,19 @@ src/pk/ecc/ecc_import_pkcs8.o src/pk/ecc/ecc_import_x509.o src/pk/ecc/ecc_make_k src/pk/ecc/ecc_recover_key.o src/pk/ecc/ecc_rfc6979_key.o src/pk/ecc/ecc_set_curve.o \ src/pk/ecc/ecc_set_curve_internal.o src/pk/ecc/ecc_set_key.o src/pk/ecc/ecc_shared_secret.o \ src/pk/ecc/ecc_sign_hash.o src/pk/ecc/ecc_sign_hash_eth27.o src/pk/ecc/ecc_sign_hash_internal.o \ -src/pk/ecc/ecc_sign_hash_rfc5656.o src/pk/ecc/ecc_sign_hash_rfc7518.o src/pk/ecc/ecc_sizes.o \ -src/pk/ecc/ecc_ssh_ecdsa_encode_name.o src/pk/ecc/ecc_verify_hash.o src/pk/ecc/ecc_verify_hash_eth27.o \ -src/pk/ecc/ecc_verify_hash_internal.o src/pk/ecc/ecc_verify_hash_rfc5656.o \ -src/pk/ecc/ecc_verify_hash_rfc7518.o src/pk/ecc/ltc_ecc_export_point.o \ -src/pk/ecc/ltc_ecc_import_point.o src/pk/ecc/ltc_ecc_is_point.o \ -src/pk/ecc/ltc_ecc_is_point_at_infinity.o src/pk/ecc/ltc_ecc_map.o src/pk/ecc/ltc_ecc_mul2add.o \ -src/pk/ecc/ltc_ecc_mulmod.o src/pk/ecc/ltc_ecc_mulmod_timing.o src/pk/ecc/ltc_ecc_points.o \ -src/pk/ecc/ltc_ecc_projective_add_point.o src/pk/ecc/ltc_ecc_projective_dbl_point.o \ -src/pk/ecc/ltc_ecc_verify_key.o src/pk/ed25519/ed25519_export.o src/pk/ed25519/ed25519_import.o \ -src/pk/ed25519/ed25519_import_pkcs8.o src/pk/ed25519/ed25519_import_raw.o \ -src/pk/ed25519/ed25519_import_x509.o src/pk/ed25519/ed25519_make_key.o src/pk/ed25519/ed25519_sign.o \ -src/pk/ed25519/ed25519_verify.o src/pk/pka_key.o src/pk/pkcs1/pkcs_1_i2osp.o src/pk/pkcs1/pkcs_1_mgf1.o \ +src/pk/ecc/ecc_sign_hash_rfc5656.o src/pk/ecc/ecc_sign_hash_rfc7518.o src/pk/ecc/ecc_sign_hash_x962.o \ +src/pk/ecc/ecc_sizes.o src/pk/ecc/ecc_ssh_ecdsa_encode_name.o src/pk/ecc/ecc_verify_hash.o \ +src/pk/ecc/ecc_verify_hash_eth27.o src/pk/ecc/ecc_verify_hash_internal.o \ +src/pk/ecc/ecc_verify_hash_rfc5656.o src/pk/ecc/ecc_verify_hash_rfc7518.o \ +src/pk/ecc/ecc_verify_hash_x962.o src/pk/ecc/ltc_ecc_export_point.o src/pk/ecc/ltc_ecc_import_point.o \ +src/pk/ecc/ltc_ecc_is_point.o src/pk/ecc/ltc_ecc_is_point_at_infinity.o src/pk/ecc/ltc_ecc_map.o \ +src/pk/ecc/ltc_ecc_mul2add.o src/pk/ecc/ltc_ecc_mulmod.o src/pk/ecc/ltc_ecc_mulmod_timing.o \ +src/pk/ecc/ltc_ecc_points.o src/pk/ecc/ltc_ecc_projective_add_point.o \ +src/pk/ecc/ltc_ecc_projective_dbl_point.o src/pk/ecc/ltc_ecc_verify_key.o \ +src/pk/ed25519/ed25519_export.o src/pk/ed25519/ed25519_import.o src/pk/ed25519/ed25519_import_pkcs8.o \ +src/pk/ed25519/ed25519_import_raw.o src/pk/ed25519/ed25519_import_x509.o \ +src/pk/ed25519/ed25519_make_key.o src/pk/ed25519/ed25519_sign.o src/pk/ed25519/ed25519_verify.o \ +src/pk/pka_key.o src/pk/pkcs1/pkcs_1_i2osp.o src/pk/pkcs1/pkcs_1_mgf1.o \ src/pk/pkcs1/pkcs_1_oaep_decode.o src/pk/pkcs1/pkcs_1_oaep_encode.o src/pk/pkcs1/pkcs_1_os2ip.o \ src/pk/pkcs1/pkcs_1_pss_decode.o src/pk/pkcs1/pkcs_1_pss_encode.o src/pk/pkcs1/pkcs_1_v1_5_decode.o \ src/pk/pkcs1/pkcs_1_v1_5_encode.o src/pk/rsa/rsa_decrypt_key.o src/pk/rsa/rsa_encrypt_key.o \ @@ -233,13 +235,13 @@ src/stream/sosemanuk/sosemanuk_memory.o src/stream/sosemanuk/sosemanuk_test.o #List of test objects to compile TOBJECTS=tests/base16_test.o tests/base32_test.o tests/base64_test.o tests/bcrypt_test.o \ -tests/cipher_hash_test.o tests/common.o tests/der_test.o tests/dh_test.o tests/dsa_test.o \ -tests/ecc_test.o tests/ed25519_test.o tests/file_test.o tests/mac_test.o tests/misc_test.o \ -tests/modes_test.o tests/mpi_test.o tests/multi_test.o tests/no_null_termination_check_test.o \ -tests/no_prng.o tests/padding_test.o tests/pem_test.o tests/pk_oid_test.o tests/pkcs_1_eme_test.o \ -tests/pkcs_1_emsa_test.o tests/pkcs_1_oaep_test.o tests/pkcs_1_pss_test.o tests/pkcs_1_test.o \ -tests/prng_test.o tests/rotate_test.o tests/rsa_test.o tests/ssh_test.o tests/store_test.o tests/test.o \ -tests/x25519_test.o +tests/cipher_hash_test.o tests/common.o tests/deprecated_test.o tests/der_test.o tests/dh_test.o \ +tests/dsa_test.o tests/ecc_test.o tests/ed25519_test.o tests/file_test.o tests/mac_test.o \ +tests/misc_test.o tests/modes_test.o tests/mpi_test.o tests/multi_test.o \ +tests/no_null_termination_check_test.o tests/no_prng.o tests/padding_test.o tests/pem_test.o \ +tests/pk_oid_test.o tests/pkcs_1_eme_test.o tests/pkcs_1_emsa_test.o tests/pkcs_1_oaep_test.o \ +tests/pkcs_1_pss_test.o tests/pkcs_1_test.o tests/prng_test.o tests/rotate_test.o tests/rsa_test.o \ +tests/ssh_test.o tests/store_test.o tests/test.o tests/x25519_test.o #The following headers will be installed by "make install" HEADERS_PUB=src/headers/tomcrypt.h src/headers/tomcrypt_argchk.h src/headers/tomcrypt_cfg.h \ diff --git a/makefile.msvc b/makefile.msvc index 91d17f9bd..6fdf20715 100644 --- a/makefile.msvc +++ b/makefile.msvc @@ -102,8 +102,8 @@ src/misc/crypt/crypt_register_all_ciphers.obj src/misc/crypt/crypt_register_all_ src/misc/crypt/crypt_register_all_prngs.obj src/misc/crypt/crypt_register_cipher.obj \ src/misc/crypt/crypt_register_hash.obj src/misc/crypt/crypt_register_prng.obj src/misc/crypt/crypt_sizes.obj \ src/misc/crypt/crypt_unregister_cipher.obj src/misc/crypt/crypt_unregister_hash.obj \ -src/misc/crypt/crypt_unregister_prng.obj src/misc/error_to_string.obj src/misc/hkdf/hkdf.obj \ -src/misc/hkdf/hkdf_test.obj src/misc/mem_neq.obj src/misc/padding/padding_depad.obj \ +src/misc/crypt/crypt_unregister_prng.obj src/misc/deprecated.obj src/misc/error_to_string.obj \ +src/misc/hkdf/hkdf.obj src/misc/hkdf/hkdf_test.obj src/misc/mem_neq.obj src/misc/padding/padding_depad.obj \ src/misc/padding/padding_pad.obj src/misc/password_free.obj src/misc/pbes/pbes.obj src/misc/pbes/pbes1.obj \ src/misc/pbes/pbes2.obj src/misc/pem/pem.obj src/misc/pem/pem_pkcs.obj src/misc/pem/pem_read.obj \ src/misc/pem/pem_ssh.obj src/misc/pkcs12/pkcs12_kdf.obj src/misc/pkcs12/pkcs12_utf8_to_utf16.obj \ @@ -169,9 +169,10 @@ src/pk/asn1/oid/pk_get.obj src/pk/asn1/oid/pk_oid_cmp.obj src/pk/asn1/oid/pk_oid src/pk/asn1/pkcs8/pkcs8_decode_flexi.obj src/pk/asn1/pkcs8/pkcs8_get.obj \ src/pk/asn1/x509/x509_decode_public_key_from_certificate.obj src/pk/asn1/x509/x509_decode_spki.obj \ src/pk/asn1/x509/x509_decode_subject_public_key_info.obj \ -src/pk/asn1/x509/x509_encode_subject_public_key_info.obj src/pk/dh/dh.obj src/pk/dh/dh_check_pubkey.obj \ -src/pk/dh/dh_export.obj src/pk/dh/dh_export_key.obj src/pk/dh/dh_free.obj src/pk/dh/dh_generate_key.obj \ -src/pk/dh/dh_import.obj src/pk/dh/dh_import_pkcs8.obj src/pk/dh/dh_set.obj src/pk/dh/dh_set_pg_dhparam.obj \ +src/pk/asn1/x509/x509_encode_subject_public_key_info.obj src/pk/asn1/x509/x509_get_pka.obj \ +src/pk/asn1/x509/x509_import_spki.obj src/pk/dh/dh.obj src/pk/dh/dh_check_pubkey.obj src/pk/dh/dh_export.obj \ +src/pk/dh/dh_export_key.obj src/pk/dh/dh_free.obj src/pk/dh/dh_generate_key.obj src/pk/dh/dh_import.obj \ +src/pk/dh/dh_import_pkcs8.obj src/pk/dh/dh_set.obj src/pk/dh/dh_set_pg_dhparam.obj \ src/pk/dh/dh_shared_secret.obj src/pk/dsa/dsa_decrypt_key.obj src/pk/dsa/dsa_encrypt_key.obj \ src/pk/dsa/dsa_export.obj src/pk/dsa/dsa_free.obj src/pk/dsa/dsa_generate_key.obj \ src/pk/dsa/dsa_generate_pqg.obj src/pk/dsa/dsa_import.obj src/pk/dsa/dsa_import_pkcs8.obj \ @@ -187,18 +188,19 @@ src/pk/ecc/ecc_import_pkcs8.obj src/pk/ecc/ecc_import_x509.obj src/pk/ecc/ecc_ma src/pk/ecc/ecc_recover_key.obj src/pk/ecc/ecc_rfc6979_key.obj src/pk/ecc/ecc_set_curve.obj \ src/pk/ecc/ecc_set_curve_internal.obj src/pk/ecc/ecc_set_key.obj src/pk/ecc/ecc_shared_secret.obj \ src/pk/ecc/ecc_sign_hash.obj src/pk/ecc/ecc_sign_hash_eth27.obj src/pk/ecc/ecc_sign_hash_internal.obj \ -src/pk/ecc/ecc_sign_hash_rfc5656.obj src/pk/ecc/ecc_sign_hash_rfc7518.obj src/pk/ecc/ecc_sizes.obj \ -src/pk/ecc/ecc_ssh_ecdsa_encode_name.obj src/pk/ecc/ecc_verify_hash.obj src/pk/ecc/ecc_verify_hash_eth27.obj \ -src/pk/ecc/ecc_verify_hash_internal.obj src/pk/ecc/ecc_verify_hash_rfc5656.obj \ -src/pk/ecc/ecc_verify_hash_rfc7518.obj src/pk/ecc/ltc_ecc_export_point.obj \ -src/pk/ecc/ltc_ecc_import_point.obj src/pk/ecc/ltc_ecc_is_point.obj \ -src/pk/ecc/ltc_ecc_is_point_at_infinity.obj src/pk/ecc/ltc_ecc_map.obj src/pk/ecc/ltc_ecc_mul2add.obj \ -src/pk/ecc/ltc_ecc_mulmod.obj src/pk/ecc/ltc_ecc_mulmod_timing.obj src/pk/ecc/ltc_ecc_points.obj \ -src/pk/ecc/ltc_ecc_projective_add_point.obj src/pk/ecc/ltc_ecc_projective_dbl_point.obj \ -src/pk/ecc/ltc_ecc_verify_key.obj src/pk/ed25519/ed25519_export.obj src/pk/ed25519/ed25519_import.obj \ -src/pk/ed25519/ed25519_import_pkcs8.obj src/pk/ed25519/ed25519_import_raw.obj \ -src/pk/ed25519/ed25519_import_x509.obj src/pk/ed25519/ed25519_make_key.obj src/pk/ed25519/ed25519_sign.obj \ -src/pk/ed25519/ed25519_verify.obj src/pk/pka_key.obj src/pk/pkcs1/pkcs_1_i2osp.obj src/pk/pkcs1/pkcs_1_mgf1.obj \ +src/pk/ecc/ecc_sign_hash_rfc5656.obj src/pk/ecc/ecc_sign_hash_rfc7518.obj src/pk/ecc/ecc_sign_hash_x962.obj \ +src/pk/ecc/ecc_sizes.obj src/pk/ecc/ecc_ssh_ecdsa_encode_name.obj src/pk/ecc/ecc_verify_hash.obj \ +src/pk/ecc/ecc_verify_hash_eth27.obj src/pk/ecc/ecc_verify_hash_internal.obj \ +src/pk/ecc/ecc_verify_hash_rfc5656.obj src/pk/ecc/ecc_verify_hash_rfc7518.obj \ +src/pk/ecc/ecc_verify_hash_x962.obj src/pk/ecc/ltc_ecc_export_point.obj src/pk/ecc/ltc_ecc_import_point.obj \ +src/pk/ecc/ltc_ecc_is_point.obj src/pk/ecc/ltc_ecc_is_point_at_infinity.obj src/pk/ecc/ltc_ecc_map.obj \ +src/pk/ecc/ltc_ecc_mul2add.obj src/pk/ecc/ltc_ecc_mulmod.obj src/pk/ecc/ltc_ecc_mulmod_timing.obj \ +src/pk/ecc/ltc_ecc_points.obj src/pk/ecc/ltc_ecc_projective_add_point.obj \ +src/pk/ecc/ltc_ecc_projective_dbl_point.obj src/pk/ecc/ltc_ecc_verify_key.obj \ +src/pk/ed25519/ed25519_export.obj src/pk/ed25519/ed25519_import.obj src/pk/ed25519/ed25519_import_pkcs8.obj \ +src/pk/ed25519/ed25519_import_raw.obj src/pk/ed25519/ed25519_import_x509.obj \ +src/pk/ed25519/ed25519_make_key.obj src/pk/ed25519/ed25519_sign.obj src/pk/ed25519/ed25519_verify.obj \ +src/pk/pka_key.obj src/pk/pkcs1/pkcs_1_i2osp.obj src/pk/pkcs1/pkcs_1_mgf1.obj \ src/pk/pkcs1/pkcs_1_oaep_decode.obj src/pk/pkcs1/pkcs_1_oaep_encode.obj src/pk/pkcs1/pkcs_1_os2ip.obj \ src/pk/pkcs1/pkcs_1_pss_decode.obj src/pk/pkcs1/pkcs_1_pss_encode.obj src/pk/pkcs1/pkcs_1_v1_5_decode.obj \ src/pk/pkcs1/pkcs_1_v1_5_encode.obj src/pk/rsa/rsa_decrypt_key.obj src/pk/rsa/rsa_encrypt_key.obj \ @@ -226,13 +228,13 @@ src/stream/sosemanuk/sosemanuk_memory.obj src/stream/sosemanuk/sosemanuk_test.ob #List of test objects to compile TOBJECTS=tests/base16_test.obj tests/base32_test.obj tests/base64_test.obj tests/bcrypt_test.obj \ -tests/cipher_hash_test.obj tests/common.obj tests/der_test.obj tests/dh_test.obj tests/dsa_test.obj \ -tests/ecc_test.obj tests/ed25519_test.obj tests/file_test.obj tests/mac_test.obj tests/misc_test.obj \ -tests/modes_test.obj tests/mpi_test.obj tests/multi_test.obj tests/no_null_termination_check_test.obj \ -tests/no_prng.obj tests/padding_test.obj tests/pem_test.obj tests/pk_oid_test.obj tests/pkcs_1_eme_test.obj \ -tests/pkcs_1_emsa_test.obj tests/pkcs_1_oaep_test.obj tests/pkcs_1_pss_test.obj tests/pkcs_1_test.obj \ -tests/prng_test.obj tests/rotate_test.obj tests/rsa_test.obj tests/ssh_test.obj tests/store_test.obj tests/test.obj \ -tests/x25519_test.obj +tests/cipher_hash_test.obj tests/common.obj tests/deprecated_test.obj tests/der_test.obj tests/dh_test.obj \ +tests/dsa_test.obj tests/ecc_test.obj tests/ed25519_test.obj tests/file_test.obj tests/mac_test.obj \ +tests/misc_test.obj tests/modes_test.obj tests/mpi_test.obj tests/multi_test.obj \ +tests/no_null_termination_check_test.obj tests/no_prng.obj tests/padding_test.obj tests/pem_test.obj \ +tests/pk_oid_test.obj tests/pkcs_1_eme_test.obj tests/pkcs_1_emsa_test.obj tests/pkcs_1_oaep_test.obj \ +tests/pkcs_1_pss_test.obj tests/pkcs_1_test.obj tests/prng_test.obj tests/rotate_test.obj tests/rsa_test.obj \ +tests/ssh_test.obj tests/store_test.obj tests/test.obj tests/x25519_test.obj #The following headers will be installed by "make install" HEADERS_PUB=src/headers/tomcrypt.h src/headers/tomcrypt_argchk.h src/headers/tomcrypt_cfg.h \ diff --git a/makefile.unix b/makefile.unix index 7db447417..d68a3850f 100644 --- a/makefile.unix +++ b/makefile.unix @@ -123,8 +123,8 @@ src/misc/crypt/crypt_register_all_ciphers.o src/misc/crypt/crypt_register_all_ha src/misc/crypt/crypt_register_all_prngs.o src/misc/crypt/crypt_register_cipher.o \ src/misc/crypt/crypt_register_hash.o src/misc/crypt/crypt_register_prng.o src/misc/crypt/crypt_sizes.o \ src/misc/crypt/crypt_unregister_cipher.o src/misc/crypt/crypt_unregister_hash.o \ -src/misc/crypt/crypt_unregister_prng.o src/misc/error_to_string.o src/misc/hkdf/hkdf.o \ -src/misc/hkdf/hkdf_test.o src/misc/mem_neq.o src/misc/padding/padding_depad.o \ +src/misc/crypt/crypt_unregister_prng.o src/misc/deprecated.o src/misc/error_to_string.o \ +src/misc/hkdf/hkdf.o src/misc/hkdf/hkdf_test.o src/misc/mem_neq.o src/misc/padding/padding_depad.o \ src/misc/padding/padding_pad.o src/misc/password_free.o src/misc/pbes/pbes.o src/misc/pbes/pbes1.o \ src/misc/pbes/pbes2.o src/misc/pem/pem.o src/misc/pem/pem_pkcs.o src/misc/pem/pem_read.o \ src/misc/pem/pem_ssh.o src/misc/pkcs12/pkcs12_kdf.o src/misc/pkcs12/pkcs12_utf8_to_utf16.o \ @@ -190,9 +190,10 @@ src/pk/asn1/oid/pk_get.o src/pk/asn1/oid/pk_oid_cmp.o src/pk/asn1/oid/pk_oid_str src/pk/asn1/pkcs8/pkcs8_decode_flexi.o src/pk/asn1/pkcs8/pkcs8_get.o \ src/pk/asn1/x509/x509_decode_public_key_from_certificate.o src/pk/asn1/x509/x509_decode_spki.o \ src/pk/asn1/x509/x509_decode_subject_public_key_info.o \ -src/pk/asn1/x509/x509_encode_subject_public_key_info.o src/pk/dh/dh.o src/pk/dh/dh_check_pubkey.o \ -src/pk/dh/dh_export.o src/pk/dh/dh_export_key.o src/pk/dh/dh_free.o src/pk/dh/dh_generate_key.o \ -src/pk/dh/dh_import.o src/pk/dh/dh_import_pkcs8.o src/pk/dh/dh_set.o src/pk/dh/dh_set_pg_dhparam.o \ +src/pk/asn1/x509/x509_encode_subject_public_key_info.o src/pk/asn1/x509/x509_get_pka.o \ +src/pk/asn1/x509/x509_import_spki.o src/pk/dh/dh.o src/pk/dh/dh_check_pubkey.o src/pk/dh/dh_export.o \ +src/pk/dh/dh_export_key.o src/pk/dh/dh_free.o src/pk/dh/dh_generate_key.o src/pk/dh/dh_import.o \ +src/pk/dh/dh_import_pkcs8.o src/pk/dh/dh_set.o src/pk/dh/dh_set_pg_dhparam.o \ src/pk/dh/dh_shared_secret.o src/pk/dsa/dsa_decrypt_key.o src/pk/dsa/dsa_encrypt_key.o \ src/pk/dsa/dsa_export.o src/pk/dsa/dsa_free.o src/pk/dsa/dsa_generate_key.o \ src/pk/dsa/dsa_generate_pqg.o src/pk/dsa/dsa_import.o src/pk/dsa/dsa_import_pkcs8.o \ @@ -208,18 +209,19 @@ src/pk/ecc/ecc_import_pkcs8.o src/pk/ecc/ecc_import_x509.o src/pk/ecc/ecc_make_k src/pk/ecc/ecc_recover_key.o src/pk/ecc/ecc_rfc6979_key.o src/pk/ecc/ecc_set_curve.o \ src/pk/ecc/ecc_set_curve_internal.o src/pk/ecc/ecc_set_key.o src/pk/ecc/ecc_shared_secret.o \ src/pk/ecc/ecc_sign_hash.o src/pk/ecc/ecc_sign_hash_eth27.o src/pk/ecc/ecc_sign_hash_internal.o \ -src/pk/ecc/ecc_sign_hash_rfc5656.o src/pk/ecc/ecc_sign_hash_rfc7518.o src/pk/ecc/ecc_sizes.o \ -src/pk/ecc/ecc_ssh_ecdsa_encode_name.o src/pk/ecc/ecc_verify_hash.o src/pk/ecc/ecc_verify_hash_eth27.o \ -src/pk/ecc/ecc_verify_hash_internal.o src/pk/ecc/ecc_verify_hash_rfc5656.o \ -src/pk/ecc/ecc_verify_hash_rfc7518.o src/pk/ecc/ltc_ecc_export_point.o \ -src/pk/ecc/ltc_ecc_import_point.o src/pk/ecc/ltc_ecc_is_point.o \ -src/pk/ecc/ltc_ecc_is_point_at_infinity.o src/pk/ecc/ltc_ecc_map.o src/pk/ecc/ltc_ecc_mul2add.o \ -src/pk/ecc/ltc_ecc_mulmod.o src/pk/ecc/ltc_ecc_mulmod_timing.o src/pk/ecc/ltc_ecc_points.o \ -src/pk/ecc/ltc_ecc_projective_add_point.o src/pk/ecc/ltc_ecc_projective_dbl_point.o \ -src/pk/ecc/ltc_ecc_verify_key.o src/pk/ed25519/ed25519_export.o src/pk/ed25519/ed25519_import.o \ -src/pk/ed25519/ed25519_import_pkcs8.o src/pk/ed25519/ed25519_import_raw.o \ -src/pk/ed25519/ed25519_import_x509.o src/pk/ed25519/ed25519_make_key.o src/pk/ed25519/ed25519_sign.o \ -src/pk/ed25519/ed25519_verify.o src/pk/pka_key.o src/pk/pkcs1/pkcs_1_i2osp.o src/pk/pkcs1/pkcs_1_mgf1.o \ +src/pk/ecc/ecc_sign_hash_rfc5656.o src/pk/ecc/ecc_sign_hash_rfc7518.o src/pk/ecc/ecc_sign_hash_x962.o \ +src/pk/ecc/ecc_sizes.o src/pk/ecc/ecc_ssh_ecdsa_encode_name.o src/pk/ecc/ecc_verify_hash.o \ +src/pk/ecc/ecc_verify_hash_eth27.o src/pk/ecc/ecc_verify_hash_internal.o \ +src/pk/ecc/ecc_verify_hash_rfc5656.o src/pk/ecc/ecc_verify_hash_rfc7518.o \ +src/pk/ecc/ecc_verify_hash_x962.o src/pk/ecc/ltc_ecc_export_point.o src/pk/ecc/ltc_ecc_import_point.o \ +src/pk/ecc/ltc_ecc_is_point.o src/pk/ecc/ltc_ecc_is_point_at_infinity.o src/pk/ecc/ltc_ecc_map.o \ +src/pk/ecc/ltc_ecc_mul2add.o src/pk/ecc/ltc_ecc_mulmod.o src/pk/ecc/ltc_ecc_mulmod_timing.o \ +src/pk/ecc/ltc_ecc_points.o src/pk/ecc/ltc_ecc_projective_add_point.o \ +src/pk/ecc/ltc_ecc_projective_dbl_point.o src/pk/ecc/ltc_ecc_verify_key.o \ +src/pk/ed25519/ed25519_export.o src/pk/ed25519/ed25519_import.o src/pk/ed25519/ed25519_import_pkcs8.o \ +src/pk/ed25519/ed25519_import_raw.o src/pk/ed25519/ed25519_import_x509.o \ +src/pk/ed25519/ed25519_make_key.o src/pk/ed25519/ed25519_sign.o src/pk/ed25519/ed25519_verify.o \ +src/pk/pka_key.o src/pk/pkcs1/pkcs_1_i2osp.o src/pk/pkcs1/pkcs_1_mgf1.o \ src/pk/pkcs1/pkcs_1_oaep_decode.o src/pk/pkcs1/pkcs_1_oaep_encode.o src/pk/pkcs1/pkcs_1_os2ip.o \ src/pk/pkcs1/pkcs_1_pss_decode.o src/pk/pkcs1/pkcs_1_pss_encode.o src/pk/pkcs1/pkcs_1_v1_5_decode.o \ src/pk/pkcs1/pkcs_1_v1_5_encode.o src/pk/rsa/rsa_decrypt_key.o src/pk/rsa/rsa_encrypt_key.o \ @@ -247,13 +249,13 @@ src/stream/sosemanuk/sosemanuk_memory.o src/stream/sosemanuk/sosemanuk_test.o #List of test objects to compile (all goes to libtomcrypt_prof.a) TOBJECTS=tests/base16_test.o tests/base32_test.o tests/base64_test.o tests/bcrypt_test.o \ -tests/cipher_hash_test.o tests/common.o tests/der_test.o tests/dh_test.o tests/dsa_test.o \ -tests/ecc_test.o tests/ed25519_test.o tests/file_test.o tests/mac_test.o tests/misc_test.o \ -tests/modes_test.o tests/mpi_test.o tests/multi_test.o tests/no_null_termination_check_test.o \ -tests/no_prng.o tests/padding_test.o tests/pem_test.o tests/pk_oid_test.o tests/pkcs_1_eme_test.o \ -tests/pkcs_1_emsa_test.o tests/pkcs_1_oaep_test.o tests/pkcs_1_pss_test.o tests/pkcs_1_test.o \ -tests/prng_test.o tests/rotate_test.o tests/rsa_test.o tests/ssh_test.o tests/store_test.o tests/test.o \ -tests/x25519_test.o +tests/cipher_hash_test.o tests/common.o tests/deprecated_test.o tests/der_test.o tests/dh_test.o \ +tests/dsa_test.o tests/ecc_test.o tests/ed25519_test.o tests/file_test.o tests/mac_test.o \ +tests/misc_test.o tests/modes_test.o tests/mpi_test.o tests/multi_test.o \ +tests/no_null_termination_check_test.o tests/no_prng.o tests/padding_test.o tests/pem_test.o \ +tests/pk_oid_test.o tests/pkcs_1_eme_test.o tests/pkcs_1_emsa_test.o tests/pkcs_1_oaep_test.o \ +tests/pkcs_1_pss_test.o tests/pkcs_1_test.o tests/prng_test.o tests/rotate_test.o tests/rsa_test.o \ +tests/ssh_test.o tests/store_test.o tests/test.o tests/x25519_test.o #The following headers will be installed by "make install" HEADERS_PUB=src/headers/tomcrypt.h src/headers/tomcrypt_argchk.h src/headers/tomcrypt_cfg.h \ diff --git a/makefile_include.mk b/makefile_include.mk index fcb6ed8a8..cc6f33e4e 100644 --- a/makefile_include.mk +++ b/makefile_include.mk @@ -294,8 +294,8 @@ src/misc/crypt/crypt_register_all_ciphers.o src/misc/crypt/crypt_register_all_ha src/misc/crypt/crypt_register_all_prngs.o src/misc/crypt/crypt_register_cipher.o \ src/misc/crypt/crypt_register_hash.o src/misc/crypt/crypt_register_prng.o src/misc/crypt/crypt_sizes.o \ src/misc/crypt/crypt_unregister_cipher.o src/misc/crypt/crypt_unregister_hash.o \ -src/misc/crypt/crypt_unregister_prng.o src/misc/error_to_string.o src/misc/hkdf/hkdf.o \ -src/misc/hkdf/hkdf_test.o src/misc/mem_neq.o src/misc/padding/padding_depad.o \ +src/misc/crypt/crypt_unregister_prng.o src/misc/deprecated.o src/misc/error_to_string.o \ +src/misc/hkdf/hkdf.o src/misc/hkdf/hkdf_test.o src/misc/mem_neq.o src/misc/padding/padding_depad.o \ src/misc/padding/padding_pad.o src/misc/password_free.o src/misc/pbes/pbes.o src/misc/pbes/pbes1.o \ src/misc/pbes/pbes2.o src/misc/pem/pem.o src/misc/pem/pem_pkcs.o src/misc/pem/pem_read.o \ src/misc/pem/pem_ssh.o src/misc/pkcs12/pkcs12_kdf.o src/misc/pkcs12/pkcs12_utf8_to_utf16.o \ @@ -361,9 +361,10 @@ src/pk/asn1/oid/pk_get.o src/pk/asn1/oid/pk_oid_cmp.o src/pk/asn1/oid/pk_oid_str src/pk/asn1/pkcs8/pkcs8_decode_flexi.o src/pk/asn1/pkcs8/pkcs8_get.o \ src/pk/asn1/x509/x509_decode_public_key_from_certificate.o src/pk/asn1/x509/x509_decode_spki.o \ src/pk/asn1/x509/x509_decode_subject_public_key_info.o \ -src/pk/asn1/x509/x509_encode_subject_public_key_info.o src/pk/dh/dh.o src/pk/dh/dh_check_pubkey.o \ -src/pk/dh/dh_export.o src/pk/dh/dh_export_key.o src/pk/dh/dh_free.o src/pk/dh/dh_generate_key.o \ -src/pk/dh/dh_import.o src/pk/dh/dh_import_pkcs8.o src/pk/dh/dh_set.o src/pk/dh/dh_set_pg_dhparam.o \ +src/pk/asn1/x509/x509_encode_subject_public_key_info.o src/pk/asn1/x509/x509_get_pka.o \ +src/pk/asn1/x509/x509_import_spki.o src/pk/dh/dh.o src/pk/dh/dh_check_pubkey.o src/pk/dh/dh_export.o \ +src/pk/dh/dh_export_key.o src/pk/dh/dh_free.o src/pk/dh/dh_generate_key.o src/pk/dh/dh_import.o \ +src/pk/dh/dh_import_pkcs8.o src/pk/dh/dh_set.o src/pk/dh/dh_set_pg_dhparam.o \ src/pk/dh/dh_shared_secret.o src/pk/dsa/dsa_decrypt_key.o src/pk/dsa/dsa_encrypt_key.o \ src/pk/dsa/dsa_export.o src/pk/dsa/dsa_free.o src/pk/dsa/dsa_generate_key.o \ src/pk/dsa/dsa_generate_pqg.o src/pk/dsa/dsa_import.o src/pk/dsa/dsa_import_pkcs8.o \ @@ -379,18 +380,19 @@ src/pk/ecc/ecc_import_pkcs8.o src/pk/ecc/ecc_import_x509.o src/pk/ecc/ecc_make_k src/pk/ecc/ecc_recover_key.o src/pk/ecc/ecc_rfc6979_key.o src/pk/ecc/ecc_set_curve.o \ src/pk/ecc/ecc_set_curve_internal.o src/pk/ecc/ecc_set_key.o src/pk/ecc/ecc_shared_secret.o \ src/pk/ecc/ecc_sign_hash.o src/pk/ecc/ecc_sign_hash_eth27.o src/pk/ecc/ecc_sign_hash_internal.o \ -src/pk/ecc/ecc_sign_hash_rfc5656.o src/pk/ecc/ecc_sign_hash_rfc7518.o src/pk/ecc/ecc_sizes.o \ -src/pk/ecc/ecc_ssh_ecdsa_encode_name.o src/pk/ecc/ecc_verify_hash.o src/pk/ecc/ecc_verify_hash_eth27.o \ -src/pk/ecc/ecc_verify_hash_internal.o src/pk/ecc/ecc_verify_hash_rfc5656.o \ -src/pk/ecc/ecc_verify_hash_rfc7518.o src/pk/ecc/ltc_ecc_export_point.o \ -src/pk/ecc/ltc_ecc_import_point.o src/pk/ecc/ltc_ecc_is_point.o \ -src/pk/ecc/ltc_ecc_is_point_at_infinity.o src/pk/ecc/ltc_ecc_map.o src/pk/ecc/ltc_ecc_mul2add.o \ -src/pk/ecc/ltc_ecc_mulmod.o src/pk/ecc/ltc_ecc_mulmod_timing.o src/pk/ecc/ltc_ecc_points.o \ -src/pk/ecc/ltc_ecc_projective_add_point.o src/pk/ecc/ltc_ecc_projective_dbl_point.o \ -src/pk/ecc/ltc_ecc_verify_key.o src/pk/ed25519/ed25519_export.o src/pk/ed25519/ed25519_import.o \ -src/pk/ed25519/ed25519_import_pkcs8.o src/pk/ed25519/ed25519_import_raw.o \ -src/pk/ed25519/ed25519_import_x509.o src/pk/ed25519/ed25519_make_key.o src/pk/ed25519/ed25519_sign.o \ -src/pk/ed25519/ed25519_verify.o src/pk/pka_key.o src/pk/pkcs1/pkcs_1_i2osp.o src/pk/pkcs1/pkcs_1_mgf1.o \ +src/pk/ecc/ecc_sign_hash_rfc5656.o src/pk/ecc/ecc_sign_hash_rfc7518.o src/pk/ecc/ecc_sign_hash_x962.o \ +src/pk/ecc/ecc_sizes.o src/pk/ecc/ecc_ssh_ecdsa_encode_name.o src/pk/ecc/ecc_verify_hash.o \ +src/pk/ecc/ecc_verify_hash_eth27.o src/pk/ecc/ecc_verify_hash_internal.o \ +src/pk/ecc/ecc_verify_hash_rfc5656.o src/pk/ecc/ecc_verify_hash_rfc7518.o \ +src/pk/ecc/ecc_verify_hash_x962.o src/pk/ecc/ltc_ecc_export_point.o src/pk/ecc/ltc_ecc_import_point.o \ +src/pk/ecc/ltc_ecc_is_point.o src/pk/ecc/ltc_ecc_is_point_at_infinity.o src/pk/ecc/ltc_ecc_map.o \ +src/pk/ecc/ltc_ecc_mul2add.o src/pk/ecc/ltc_ecc_mulmod.o src/pk/ecc/ltc_ecc_mulmod_timing.o \ +src/pk/ecc/ltc_ecc_points.o src/pk/ecc/ltc_ecc_projective_add_point.o \ +src/pk/ecc/ltc_ecc_projective_dbl_point.o src/pk/ecc/ltc_ecc_verify_key.o \ +src/pk/ed25519/ed25519_export.o src/pk/ed25519/ed25519_import.o src/pk/ed25519/ed25519_import_pkcs8.o \ +src/pk/ed25519/ed25519_import_raw.o src/pk/ed25519/ed25519_import_x509.o \ +src/pk/ed25519/ed25519_make_key.o src/pk/ed25519/ed25519_sign.o src/pk/ed25519/ed25519_verify.o \ +src/pk/pka_key.o src/pk/pkcs1/pkcs_1_i2osp.o src/pk/pkcs1/pkcs_1_mgf1.o \ src/pk/pkcs1/pkcs_1_oaep_decode.o src/pk/pkcs1/pkcs_1_oaep_encode.o src/pk/pkcs1/pkcs_1_os2ip.o \ src/pk/pkcs1/pkcs_1_pss_decode.o src/pk/pkcs1/pkcs_1_pss_encode.o src/pk/pkcs1/pkcs_1_v1_5_decode.o \ src/pk/pkcs1/pkcs_1_v1_5_encode.o src/pk/rsa/rsa_decrypt_key.o src/pk/rsa/rsa_encrypt_key.o \ @@ -423,13 +425,13 @@ endif # List of test objects to compile (all goes to libtomcrypt_prof.a) TOBJECTS=tests/base16_test.o tests/base32_test.o tests/base64_test.o tests/bcrypt_test.o \ -tests/cipher_hash_test.o tests/common.o tests/der_test.o tests/dh_test.o tests/dsa_test.o \ -tests/ecc_test.o tests/ed25519_test.o tests/file_test.o tests/mac_test.o tests/misc_test.o \ -tests/modes_test.o tests/mpi_test.o tests/multi_test.o tests/no_null_termination_check_test.o \ -tests/no_prng.o tests/padding_test.o tests/pem_test.o tests/pk_oid_test.o tests/pkcs_1_eme_test.o \ -tests/pkcs_1_emsa_test.o tests/pkcs_1_oaep_test.o tests/pkcs_1_pss_test.o tests/pkcs_1_test.o \ -tests/prng_test.o tests/rotate_test.o tests/rsa_test.o tests/ssh_test.o tests/store_test.o tests/test.o \ -tests/x25519_test.o +tests/cipher_hash_test.o tests/common.o tests/deprecated_test.o tests/der_test.o tests/dh_test.o \ +tests/dsa_test.o tests/ecc_test.o tests/ed25519_test.o tests/file_test.o tests/mac_test.o \ +tests/misc_test.o tests/modes_test.o tests/mpi_test.o tests/multi_test.o \ +tests/no_null_termination_check_test.o tests/no_prng.o tests/padding_test.o tests/pem_test.o \ +tests/pk_oid_test.o tests/pkcs_1_eme_test.o tests/pkcs_1_emsa_test.o tests/pkcs_1_oaep_test.o \ +tests/pkcs_1_pss_test.o tests/pkcs_1_test.o tests/prng_test.o tests/rotate_test.o tests/rsa_test.o \ +tests/ssh_test.o tests/store_test.o tests/test.o tests/x25519_test.o # The following headers will be installed by "make install" HEADERS_PUB=src/headers/tomcrypt.h src/headers/tomcrypt_argchk.h src/headers/tomcrypt_cfg.h \ diff --git a/sources.cmake b/sources.cmake index 45682cf68..85cc37fde 100644 --- a/sources.cmake +++ b/sources.cmake @@ -232,6 +232,7 @@ src/misc/crypt/crypt_sizes.c src/misc/crypt/crypt_unregister_cipher.c src/misc/crypt/crypt_unregister_hash.c src/misc/crypt/crypt_unregister_prng.c +src/misc/deprecated.c src/misc/error_to_string.c src/misc/hkdf/hkdf.c src/misc/hkdf/hkdf_test.c @@ -372,6 +373,8 @@ src/pk/asn1/x509/x509_decode_public_key_from_certificate.c src/pk/asn1/x509/x509_decode_spki.c src/pk/asn1/x509/x509_decode_subject_public_key_info.c src/pk/asn1/x509/x509_encode_subject_public_key_info.c +src/pk/asn1/x509/x509_get_pka.c +src/pk/asn1/x509/x509_import_spki.c src/pk/dh/dh.c src/pk/dh/dh_check_pubkey.c src/pk/dh/dh_export.c @@ -431,6 +434,7 @@ src/pk/ecc/ecc_sign_hash_eth27.c src/pk/ecc/ecc_sign_hash_internal.c src/pk/ecc/ecc_sign_hash_rfc5656.c src/pk/ecc/ecc_sign_hash_rfc7518.c +src/pk/ecc/ecc_sign_hash_x962.c src/pk/ecc/ecc_sizes.c src/pk/ecc/ecc_ssh_ecdsa_encode_name.c src/pk/ecc/ecc_verify_hash.c @@ -438,6 +442,7 @@ src/pk/ecc/ecc_verify_hash_eth27.c src/pk/ecc/ecc_verify_hash_internal.c src/pk/ecc/ecc_verify_hash_rfc5656.c src/pk/ecc/ecc_verify_hash_rfc7518.c +src/pk/ecc/ecc_verify_hash_x962.c src/pk/ecc/ltc_ecc_export_point.c src/pk/ecc/ltc_ecc_import_point.c src/pk/ecc/ltc_ecc_is_point.c From 971d1ac87b4713fbf304303c5d535a13aadcc66d Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Thu, 23 Oct 2025 00:09:05 +0200 Subject: [PATCH 15/17] Introduce new RSA API. This also: a) deprecates the old RSA and PKCS#1 API. b) reverts the changes done to them in order to make them API compatible again with the last release. The fixes commit mentioned is the testcase for the Bleichenbacher attack, which works now again as expected. Fixes: 9d03c38e ("add flags to `der_decode_sequence()`") Signed-off-by: Steffen Jaeckel --- src/headers/tomcrypt_pk.h | 71 ++++++-- src/headers/tomcrypt_pkcs.h | 15 +- src/headers/tomcrypt_private.h | 72 +++++++-- src/misc/deprecated.c | 259 ++++++++++++++++++++++++++++++ src/pk/pkcs1/pkcs_1_oaep_decode.c | 43 ++--- src/pk/pkcs1/pkcs_1_oaep_encode.c | 50 ++---- src/pk/pkcs1/pkcs_1_pss_decode.c | 64 +++----- src/pk/pkcs1/pkcs_1_pss_encode.c | 71 +++----- src/pk/rsa/rsa_decrypt_key.c | 30 ++-- src/pk/rsa/rsa_encrypt_key.c | 53 +++--- src/pk/rsa/rsa_key.c | 151 +++++++++++++---- src/pk/rsa/rsa_sign_hash.c | 78 ++++----- src/pk/rsa/rsa_verify_hash.c | 48 +++--- tests/pkcs_1_eme_test.c | 4 +- tests/pkcs_1_emsa_test.c | 4 +- tests/pkcs_1_test.c | 4 +- tests/rsa_test.c | 109 ++++++++----- 17 files changed, 723 insertions(+), 403 deletions(-) diff --git a/src/headers/tomcrypt_pk.h b/src/headers/tomcrypt_pk.h index d517b2fe4..12833ba5e 100644 --- a/src/headers/tomcrypt_pk.h +++ b/src/headers/tomcrypt_pk.h @@ -70,7 +70,10 @@ typedef struct ltc_rsa_parameters { /** saltLength is only defined for PSS * If saltLength == 0 -> OAEP, else -> PSS */ unsigned long saltlen; - /** hash and MGF hash algorithms */ + /** lparam hash for OAEP + * resp. + * signature hash for PSS + * and MGF hash algorithms */ const char *hash_alg, *mgf1_hash_alg; } ltc_rsa_parameters; @@ -109,51 +112,93 @@ int rsa_exptmod(const unsigned char *in, unsigned long inlen, void rsa_free(rsa_key *key); +typedef struct ltc_rsa_op_parameters { + /* pss_oaep flag is unused */ + ltc_rsa_parameters params; + /* The padding type */ + int padding; + /* The PRNG to use. + * Only required for signing and encryption. */ + int wprng; + prng_state *prng; + /* Operation-specific parameters */ + union { + struct { + const unsigned char *lparam; + unsigned long lparamlen; + } crypt; + /* let's make space for potential future extensions */ + ulong64 dummy[8]; + } u; +} ltc_rsa_op_parameters; + +int rsa_encrypt_key_v2(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + ltc_rsa_op_parameters *opts, + const rsa_key *key); + +int rsa_decrypt_key_v2(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + ltc_rsa_op_parameters *opts, + int *stat, + const rsa_key *key); + +int rsa_sign_hash_v2(const unsigned char *hash, unsigned long hashlen, + unsigned char *sig, unsigned long *siglen, + ltc_rsa_op_parameters *opts, + const rsa_key *key); + +int rsa_verify_hash_v2(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + ltc_rsa_op_parameters *opts, + int *stat, + const rsa_key *key); + /* These use PKCS #1 v2.0 padding */ #define rsa_encrypt_key(in, inlen, out, outlen, lparam, lparamlen, prng, prng_idx, hash_idx, key) \ - rsa_encrypt_key_ex(in, inlen, out, outlen, lparam, lparamlen, prng, prng_idx, hash_idx, -1, LTC_PKCS_1_OAEP, key) + rsa_encrypt_key_ex(in, inlen, out, outlen, lparam, lparamlen, prng, prng_idx, hash_idx, LTC_PKCS_1_OAEP, key) #define rsa_decrypt_key(in, inlen, out, outlen, lparam, lparamlen, hash_idx, stat, key) \ - rsa_decrypt_key_ex(in, inlen, out, outlen, lparam, lparamlen, hash_idx, -1, LTC_PKCS_1_OAEP, stat, key) + rsa_decrypt_key_ex(in, inlen, out, outlen, lparam, lparamlen, hash_idx, LTC_PKCS_1_OAEP, stat, key) #define rsa_sign_hash(in, inlen, out, outlen, prng, prng_idx, hash_idx, saltlen, key) \ - rsa_sign_hash_ex(in, inlen, out, outlen, LTC_PKCS_1_PSS, prng, prng_idx, hash_idx, hash_idx, saltlen, key) + rsa_sign_hash_ex(in, inlen, out, outlen, LTC_PKCS_1_PSS, prng, prng_idx, hash_idx, saltlen, key) #define rsa_verify_hash(sig, siglen, hash, hashlen, hash_idx, saltlen, stat, key) \ - rsa_verify_hash_ex(sig, siglen, hash, hashlen, LTC_PKCS_1_PSS, hash_idx, hash_idx, saltlen, stat, key) + rsa_verify_hash_ex(sig, siglen, hash, hashlen, LTC_PKCS_1_PSS, hash_idx, saltlen, stat, key) #define rsa_sign_saltlen_get_max(hash_idx, key) \ rsa_sign_saltlen_get_max_ex(LTC_PKCS_1_PSS, hash_idx, key) /* These can be switched between PKCS #1 v2.x and PKCS #1 v1.5 paddings */ +LTC_DEPRECATED(rsa_encrypt_key_v2) int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, const unsigned char *lparam, unsigned long lparamlen, prng_state *prng, int prng_idx, - int mgf_hash, int lparam_hash, - int padding, + int hash_idx, int padding, const rsa_key *key); +LTC_DEPRECATED(rsa_decrypt_key_v2) int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, const unsigned char *lparam, unsigned long lparamlen, - int mgf_hash, int lparam_hash, - int padding, + int hash_idx, int padding, int *stat, const rsa_key *key); +LTC_DEPRECATED(rsa_sign_hash_v2) int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, int padding, prng_state *prng, int prng_idx, - int hash_idx, int mgf_hash_idx, - unsigned long saltlen, + int hash_idx, unsigned long saltlen, const rsa_key *key); +LTC_DEPRECATED(rsa_verify_hash_v2) int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen, const unsigned char *hash, unsigned long hashlen, int padding, - int hash_idx, int mgf_hash_idx, - unsigned long saltlen, + int hash_idx, unsigned long saltlen, int *stat, const rsa_key *key); int rsa_sign_saltlen_get_max_ex(int padding, int hash_idx, const rsa_key *key); diff --git a/src/headers/tomcrypt_pkcs.h b/src/headers/tomcrypt_pkcs.h index cca013c07..5d1d4cf42 100644 --- a/src/headers/tomcrypt_pkcs.h +++ b/src/headers/tomcrypt_pkcs.h @@ -20,14 +20,18 @@ enum ltc_pkcs_1_paddings LTC_PKCS_1_V1_5_NA1 = 4 /* PKCS #1 v1.5 padding - No ASN.1 (\sa ltc_pkcs_1_v1_5_blocks) */ }; +LTC_DEPRECATED(nothing. API will be internal) int pkcs_1_mgf1( int hash_idx, const unsigned char *seed, unsigned long seedlen, unsigned char *mask, unsigned long masklen); +LTC_DEPRECATED(nothing. API will be removed) int pkcs_1_i2osp(void *n, unsigned long modulus_len, unsigned char *out); +LTC_DEPRECATED(nothing. API will be removed) int pkcs_1_os2ip(void *n, unsigned char *in, unsigned long inlen); /* *** v1.5 padding */ +LTC_DEPRECATED(nothing. API will be internal) int pkcs_1_v1_5_encode(const unsigned char *msg, unsigned long msglen, int block_type, @@ -37,6 +41,7 @@ int pkcs_1_v1_5_encode(const unsigned char *msg, unsigned char *out, unsigned long *outlen); +LTC_DEPRECATED(nothing. API will be internal) int pkcs_1_v1_5_decode(const unsigned char *msg, unsigned long msglen, int block_type, @@ -46,26 +51,28 @@ int pkcs_1_v1_5_decode(const unsigned char *msg, int *is_valid); /* *** v2.1 padding */ +LTC_DEPRECATED(nothing. API will be internal) int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, const unsigned char *lparam, unsigned long lparamlen, unsigned long modulus_bitlen, prng_state *prng, - int prng_idx, - int mgf_hash, int lparam_hash, + int prng_idx, int hash_idx, unsigned char *out, unsigned long *outlen); +LTC_DEPRECATED(nothing. API will be internal) int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, const unsigned char *lparam, unsigned long lparamlen, - unsigned long modulus_bitlen, - int mgf_hash, int lparam_hash, + unsigned long modulus_bitlen, int hash_idx, unsigned char *out, unsigned long *outlen, int *res); +LTC_DEPRECATED(nothing. API will be internal) int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, unsigned long saltlen, prng_state *prng, int prng_idx, int hash_idx, unsigned long modulus_bitlen, unsigned char *out, unsigned long *outlen); +LTC_DEPRECATED(nothing. API will be internal) int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, const unsigned char *sig, unsigned long siglen, unsigned long saltlen, int hash_idx, diff --git a/src/headers/tomcrypt_private.h b/src/headers/tomcrypt_private.h index 2a68b6276..dbb0f44bd 100644 --- a/src/headers/tomcrypt_private.h +++ b/src/headers/tomcrypt_private.h @@ -435,13 +435,51 @@ int pk_oid_cmp_with_ulong(const char *o1, const unsigned long *o2, unsigned long /* ---- DH Routines ---- */ #ifdef LTC_MRSA +/* Receiving side, i.e. Decrypt or Verify */ +#define LTC_RSA_OP_RECV 0x00u +/* Sending side, i.e. Encrypt or Sign */ +#define LTC_RSA_OP_SEND 0x01u +/* En- or Decrypt */ +#define LTC_RSA_OP_CRYPT 0x00u +/* Sign or Verify */ +#define LTC_RSA_OP_SIGN 0x02u +/* All combinations of the above + * but only the PKCS#1 de-/encoding part */ +#define LTC_RSA_OP_PKCS1 0x04u + typedef enum ltc_rsa_op { - LTC_RSA_CRYPT, - LTC_RSA_SIGN + LTC_RSA_DECRYPT = LTC_RSA_OP_CRYPT | LTC_RSA_OP_RECV, + LTC_RSA_ENCRYPT = LTC_RSA_OP_CRYPT | LTC_RSA_OP_SEND, + LTC_RSA_VERIFY = LTC_RSA_OP_SIGN | LTC_RSA_OP_RECV, + LTC_RSA_SIGN = LTC_RSA_OP_SIGN | LTC_RSA_OP_SEND, + LTC_PKCS1_ENCRYPT = LTC_RSA_OP_PKCS1 | LTC_RSA_ENCRYPT, + LTC_PKCS1_DECRYPT = LTC_RSA_OP_PKCS1 | LTC_RSA_DECRYPT, + LTC_PKCS1_SIGN = LTC_RSA_OP_PKCS1 | LTC_RSA_SIGN, + LTC_PKCS1_VERIFY = LTC_RSA_OP_PKCS1 | LTC_RSA_VERIFY, } ltc_rsa_op; + +typedef struct ltc_rsa_op_check { + const rsa_key *key; + ltc_rsa_op_parameters *params; + int hash_alg, mgf1_hash_alg; +} ltc_rsa_op_checked; + +#define ltc_rsa_op_checked_init(k, p) { \ + .key = k, \ + .params = p, \ + .hash_alg = -1, \ + .mgf1_hash_alg = -1, \ +} + +#define ltc_pkcs1_op_checked_init(p) ltc_rsa_op_checked_init(NULL, p) + int rsa_init(rsa_key *key); void rsa_shrink_key(rsa_key *key); -int rsa_key_valid_op(const rsa_key *key, ltc_rsa_op op, int padding, int hash_idx); +int rsa_args_to_op_params(const unsigned char *lparam, unsigned long lparamlen, + prng_state *prng, int prng_idx, int hash_idx, + int padding, unsigned long saltlen, + ltc_rsa_op_parameters *params); +int rsa_key_valid_op(ltc_rsa_op op, ltc_rsa_op_checked *params); int rsa_params_equal(const ltc_rsa_parameters *a, const ltc_rsa_parameters *b); int rsa_make_key_bn_e(prng_state *prng, int wprng, int size, void *e, rsa_key *key); /* used by op-tee */ @@ -756,17 +794,23 @@ int pk_oid_cmp_with_asn1(const char *o1, const ltc_asn1_list *o2); #ifdef LTC_PKCS_1 -int pkcs_1_pss_encode_mgf1(const unsigned char *msghash, unsigned long msghashlen, - unsigned long saltlen, - prng_state *prng, int prng_idx, - int hash_idx, int mgf_hash_idx, - unsigned long modulus_bitlen, - unsigned char *out, unsigned long *outlen); -int pkcs_1_pss_decode_mgf1(const unsigned char *msghash, unsigned long msghashlen, - const unsigned char *sig, unsigned long siglen, - unsigned long saltlen, - int hash_idx, int mgf_hash_idx, - unsigned long modulus_bitlen, int *res); +int ltc_pkcs_1_pss_encode_mgf1(const unsigned char *msghash, unsigned long msghashlen, + ltc_rsa_op_parameters *params, + unsigned long modulus_bitlen, + unsigned char *out, unsigned long *outlen); +int ltc_pkcs_1_pss_decode_mgf1(const unsigned char *msghash, unsigned long msghashlen, + const unsigned char *sig, unsigned long siglen, + ltc_rsa_op_parameters *params, + unsigned long modulus_bitlen, int *res); +int ltc_pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, + unsigned long modulus_bitlen, + ltc_rsa_op_parameters *params, + unsigned char *out, unsigned long *outlen); +int ltc_pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, + unsigned long modulus_bitlen, + ltc_rsa_op_parameters *params, + unsigned char *out, unsigned long *outlen, + int *res); #endif /* LTC_PKCS_1 */ diff --git a/src/misc/deprecated.c b/src/misc/deprecated.c index 051ce7ed4..e7b116a12 100644 --- a/src/misc/deprecated.c +++ b/src/misc/deprecated.c @@ -79,4 +79,263 @@ int ecc_verify_hash_rfc7518(const unsigned char *sig, unsigned long siglen, } #endif /* LTC_MECC */ +#ifdef LTC_MRSA +/** + (PKCS #1 v2.0) OAEP pad then encrypt + @param in The plaintext + @param inlen The length of the plaintext (octets) + @param out [out] The ciphertext + @param outlen [in/out] The max size and resulting size of the ciphertext + @param lparam The system "lparam" for the encryption + @param lparamlen The length of lparam (octets) + @param prng An active PRNG + @param prng_idx The index of the desired prng + @param hash_idx The index of the desired hash + @param padding Type of padding (LTC_PKCS_1_OAEP or LTC_PKCS_1_V1_5) + @param key The RSA key to encrypt to + @return CRYPT_OK if successful +*/ +int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + const unsigned char *lparam, unsigned long lparamlen, + prng_state *prng, int prng_idx, + int hash_idx, int padding, + const rsa_key *key) +{ + int err; + ltc_rsa_op_parameters params; + if ((err = rsa_args_to_op_params(lparam, lparamlen, + prng, prng_idx, + hash_idx, + padding, 0, + ¶ms)) != CRYPT_OK) { + return err; + } + return rsa_encrypt_key_v2(in, inlen, out, outlen, ¶ms, key); +} + +/** + PKCS #1 decrypt then v1.5 or OAEP depad + @param in The ciphertext + @param inlen The length of the ciphertext (octets) + @param out [out] The plaintext + @param outlen [in/out] The max size and resulting size of the plaintext (octets) + @param lparam The system "lparam" value + @param lparamlen The length of the lparam value (octets) + @param hash_idx The hash algorithm used + @param padding Type of padding (LTC_PKCS_1_OAEP or LTC_PKCS_1_V1_5) + @param stat [out] Result of the decryption, 1==valid, 0==invalid + @param key The corresponding private RSA key + @return CRYPT_OK if succcessul (even if invalid) +*/ +int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + const unsigned char *lparam, unsigned long lparamlen, + int hash_idx, int padding, + int *stat, const rsa_key *key) +{ + int err; + ltc_rsa_op_parameters params; + if ((err = rsa_args_to_op_params(lparam, lparamlen, + NULL, -1, + hash_idx, + padding, 0, + ¶ms)) != CRYPT_OK) { + return err; + } + return rsa_decrypt_key_v2(in, inlen, out, outlen, ¶ms, stat, key); +} + +/** + PKCS #1 pad then sign + @param in The hash to sign + @param inlen The length of the hash to sign (octets) + @param out [out] The signature + @param outlen [in/out] The max size and resulting size of the signature + @param padding Type of padding (LTC_PKCS_1_PSS, LTC_PKCS_1_V1_5 or LTC_PKCS_1_V1_5_NA1) + @param prng An active PRNG state + @param prng_idx The index of the PRNG desired + @param hash_idx The index of the hash desired + @param saltlen The length of the salt desired (octets) + @param key The private RSA key to use + @return CRYPT_OK if successful +*/ +int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + int padding, + prng_state *prng, int prng_idx, + int hash_idx, unsigned long saltlen, + const rsa_key *key) +{ + int err; + ltc_rsa_op_parameters params; + if ((err = rsa_args_to_op_params(NULL, 0, + prng, prng_idx, + hash_idx, + padding, saltlen, + ¶ms)) != CRYPT_OK) { + return err; + } + return rsa_sign_hash_v2(in, inlen, out, outlen, ¶ms, key); +} + +/** + PKCS #1 de-sign then v1.5 or PSS depad + @param sig The signature data + @param siglen The length of the signature data (octets) + @param hash The hash of the message that was signed + @param hashlen The length of the hash of the message that was signed (octets) + @param padding Type of padding (LTC_PKCS_1_PSS, LTC_PKCS_1_V1_5 or LTC_PKCS_1_V1_5_NA1) + @param hash_idx The index of the desired hash + @param saltlen The length of the salt used during signature + @param stat [out] The result of the signature comparison, 1==valid, 0==invalid + @param key The public RSA key corresponding to the key that performed the signature + @return CRYPT_OK on success (even if the signature is invalid) +*/ +int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int padding, + int hash_idx, unsigned long saltlen, + int *stat, const rsa_key *key) +{ + int err; + ltc_rsa_op_parameters params; + if ((err = rsa_args_to_op_params(NULL, 0, + NULL, -1, + hash_idx, + padding, saltlen, + ¶ms)) != CRYPT_OK) { + return err; + } + return rsa_verify_hash_v2(sig, siglen, hash, hashlen, ¶ms, stat, key); +} +#endif /* LTC_MRSA */ + + +#ifdef LTC_PKCS_1 +/** + PKCS #1 v2.00 OAEP encode + @param msg The data to encode + @param msglen The length of the data to encode (octets) + @param lparam A session or system parameter (can be NULL) + @param lparamlen The length of the lparam data + @param modulus_bitlen The bit length of the RSA modulus + @param prng An active PRNG state + @param prng_idx The index of the PRNG desired + @param hash_idx The index of the hash desired + @param out [out] The destination for the encoded data + @param outlen [in/out] The max size and resulting size of the encoded data + @return CRYPT_OK if successful +*/ +int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, + const unsigned char *lparam, unsigned long lparamlen, + unsigned long modulus_bitlen, prng_state *prng, + int prng_idx, int hash_idx, + unsigned char *out, unsigned long *outlen) +{ + int err; + ltc_rsa_op_parameters params; + if ((err = rsa_args_to_op_params(lparam, lparamlen, + prng, prng_idx, + hash_idx, + LTC_PKCS_1_OAEP, 0, + ¶ms)) != CRYPT_OK) { + return err; + } + return ltc_pkcs_1_oaep_encode(msg, msglen, modulus_bitlen, ¶ms, out, outlen); +} + +/** + PKCS #1 v2.00 OAEP decode + @param msg The encoded data to decode + @param msglen The length of the encoded data (octets) + @param lparam The session or system data (can be NULL) + @param lparamlen The length of the lparam + @param modulus_bitlen The bit length of the RSA modulus + @param mgf_hash The hash algorithm used for the MGF + @param lparam_hash The hash algorithm used when hashing the lparam (can be -1) + @param out [out] Destination of decoding + @param outlen [in/out] The max size and resulting size of the decoding + @param res [out] Result of decoding, 1==valid, 0==invalid + @return CRYPT_OK if successful +*/ +int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, + const unsigned char *lparam, unsigned long lparamlen, + unsigned long modulus_bitlen, int hash_idx, + unsigned char *out, unsigned long *outlen, + int *res) +{ + int err; + ltc_rsa_op_parameters params; + if ((err = rsa_args_to_op_params(lparam, lparamlen, + NULL, -1, + hash_idx, + LTC_PKCS_1_OAEP, 0, + ¶ms)) != CRYPT_OK) { + return err; + } + return ltc_pkcs_1_oaep_decode(msg, msglen, modulus_bitlen, ¶ms, out, outlen, res); +} + +/** + PKCS #1 v2.00 Signature Encoding using MGF1 and both hashes are the same + @param msghash The hash to encode + @param msghashlen The length of the hash (octets) + @param saltlen The length of the salt desired (octets) + @param prng An active PRNG context + @param prng_idx The index of the PRNG desired + @param hash_idx The index of the hash desired + @param modulus_bitlen The bit length of the RSA modulus + @param out [out] The destination of the encoding + @param outlen [in/out] The max size and resulting size of the encoded data + @return CRYPT_OK if successful +*/ +int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, + unsigned long saltlen, prng_state *prng, + int prng_idx, int hash_idx, + unsigned long modulus_bitlen, + unsigned char *out, unsigned long *outlen) +{ + int err; + ltc_rsa_op_parameters params; + if ((err = rsa_args_to_op_params(NULL, 0, + prng, prng_idx, + hash_idx, + LTC_PKCS_1_PSS, saltlen, + ¶ms)) != CRYPT_OK) { + return err; + } + return ltc_pkcs_1_pss_encode_mgf1(msghash, msghashlen, ¶ms, modulus_bitlen, out, outlen); +} + +/** + PKCS #1 v2.00 PSS decode + @param msghash The hash to verify + @param msghashlen The length of the hash (octets) + @param sig The signature data (encoded data) + @param siglen The length of the signature data (octets) + @param saltlen The length of the salt used (octets) + @param hash_idx The index of the hash desired + @param modulus_bitlen The bit length of the RSA modulus + @param res [out] The result of the comparison, 1==valid, 0==invalid + @return CRYPT_OK if successful (even if the comparison failed) +*/ +int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, + const unsigned char *sig, unsigned long siglen, + unsigned long saltlen, int hash_idx, + unsigned long modulus_bitlen, int *res) +{ + int err; + ltc_rsa_op_parameters params; + if ((err = rsa_args_to_op_params(NULL, 0, + NULL, -1, + hash_idx, + LTC_PKCS_1_PSS, saltlen, + ¶ms)) != CRYPT_OK) { + return err; + } + return ltc_pkcs_1_pss_decode_mgf1(msghash, msghashlen, sig, siglen, ¶ms, modulus_bitlen, res); +} +#endif /* LTC_PKCS_1 */ + #endif /* LTC_NO_DEPRECATED_APIS */ diff --git a/src/pk/pkcs1/pkcs_1_oaep_decode.c b/src/pk/pkcs1/pkcs_1_oaep_decode.c index 14519c1ea..117c7d2ad 100644 --- a/src/pk/pkcs1/pkcs_1_oaep_decode.c +++ b/src/pk/pkcs1/pkcs_1_oaep_decode.c @@ -8,7 +8,6 @@ */ #ifdef LTC_PKCS_1 - /** PKCS #1 v2.00 OAEP decode @param msg The encoded data to decode @@ -23,38 +22,30 @@ @param res [out] Result of decoding, 1==valid, 0==invalid @return CRYPT_OK if successful */ -int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, - const unsigned char *lparam, unsigned long lparamlen, - unsigned long modulus_bitlen, - int mgf_hash, int lparam_hash, - unsigned char *out, unsigned long *outlen, - int *res) +int ltc_pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, + unsigned long modulus_bitlen, + ltc_rsa_op_parameters *params, + unsigned char *out, unsigned long *outlen, + int *res) { unsigned char *DB, *seed, *mask; unsigned long hLen, x, y, modulus_len; - int err, ret, lparam_hash_used; + int err, ret; + ltc_rsa_op_checked op_checked = ltc_pkcs1_op_checked_init(params); LTC_ARGCHK(msg != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); LTC_ARGCHK(res != NULL); + if ((err = rsa_key_valid_op(LTC_PKCS1_DECRYPT, &op_checked)) != CRYPT_OK) { + return err; + } + /* default to invalid packet */ *res = 0; - /* test valid hash */ - if ((err = hash_is_valid(mgf_hash)) != CRYPT_OK) { - return err; - } - if (lparam_hash != -1) { - if ((err = hash_is_valid(lparam_hash)) != CRYPT_OK) { - return err; - } - lparam_hash_used = lparam_hash; - } else { - lparam_hash_used = mgf_hash; - } - hLen = hash_descriptor[lparam_hash_used].hashsize; + hLen = hash_descriptor[op_checked.hash_alg].hashsize; modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); /* test hash/message size */ @@ -104,7 +95,7 @@ int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, x += modulus_len - hLen - 1; /* compute MGF1 of maskedDB (hLen) */ - if ((err = pkcs_1_mgf1(mgf_hash, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) { + if ((err = pkcs_1_mgf1(op_checked.mgf1_hash_alg, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) { goto LBL_ERR; } @@ -114,7 +105,7 @@ int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, } /* compute MGF1 of seed (k - hlen - 1) */ - if ((err = pkcs_1_mgf1(mgf_hash, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { + if ((err = pkcs_1_mgf1(op_checked.mgf1_hash_alg, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { goto LBL_ERR; } @@ -127,13 +118,13 @@ int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, /* compute lhash and store it in seed [reuse temps!] */ x = modulus_len; - if (lparam != NULL) { - if ((err = hash_memory(lparam_hash_used, lparam, lparamlen, seed, &x)) != CRYPT_OK) { + if (op_checked.params->u.crypt.lparam != NULL) { + if ((err = hash_memory(op_checked.hash_alg, op_checked.params->u.crypt.lparam, op_checked.params->u.crypt.lparamlen, seed, &x)) != CRYPT_OK) { goto LBL_ERR; } } else { /* can't pass hash_memory a NULL so use DB with zero length */ - if ((err = hash_memory(lparam_hash_used, DB, 0, seed, &x)) != CRYPT_OK) { + if ((err = hash_memory(op_checked.hash_alg, DB, 0, seed, &x)) != CRYPT_OK) { goto LBL_ERR; } } diff --git a/src/pk/pkcs1/pkcs_1_oaep_encode.c b/src/pk/pkcs1/pkcs_1_oaep_encode.c index 45aa5ce5c..4bcc9bfe2 100644 --- a/src/pk/pkcs1/pkcs_1_oaep_encode.c +++ b/src/pk/pkcs1/pkcs_1_oaep_encode.c @@ -8,55 +8,35 @@ */ #ifdef LTC_PKCS_1 - /** PKCS #1 v2.00 OAEP encode @param msg The data to encode @param msglen The length of the data to encode (octets) - @param lparam A session or system parameter (can be NULL) - @param lparamlen The length of the lparam data @param modulus_bitlen The bit length of the RSA modulus - @param prng An active PRNG state - @param prng_idx The index of the PRNG desired - @param hash_idx The index of the hash desired + @param params The PKCS#1 operation's parameters @param out [out] The destination for the encoded data @param outlen [in/out] The max size and resulting size of the encoded data @return CRYPT_OK if successful */ -int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, - const unsigned char *lparam, unsigned long lparamlen, - unsigned long modulus_bitlen, prng_state *prng, - int prng_idx, - int mgf_hash, int lparam_hash, - unsigned char *out, unsigned long *outlen) +int ltc_pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, + unsigned long modulus_bitlen, + ltc_rsa_op_parameters *params, + unsigned char *out, unsigned long *outlen) { unsigned char *DB, *seed, *mask; unsigned long hLen, x, y, modulus_len; - int err, lparam_hash_used; + int err; + ltc_rsa_op_checked op_checked = ltc_pkcs1_op_checked_init(params); LTC_ARGCHK((msglen == 0) || (msg != NULL)); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); - /* test valid hash */ - if ((err = hash_is_valid(mgf_hash)) != CRYPT_OK) { - return err; - } - if (lparam_hash != -1) { - if ((err = hash_is_valid(lparam_hash)) != CRYPT_OK) { - return err; - } - lparam_hash_used = lparam_hash; - } else { - lparam_hash_used = mgf_hash; - } - - /* valid prng */ - if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { + if ((err = rsa_key_valid_op(LTC_PKCS1_ENCRYPT, &op_checked)) != CRYPT_OK) { return err; } - hLen = hash_descriptor[lparam_hash_used].hashsize; + hLen = hash_descriptor[op_checked.hash_alg].hashsize; modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); /* test message size */ @@ -84,13 +64,13 @@ int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, /* get lhash */ /* DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */ x = modulus_len; - if (lparam != NULL) { - if ((err = hash_memory(lparam_hash_used, lparam, lparamlen, DB, &x)) != CRYPT_OK) { + if (op_checked.params->u.crypt.lparam != NULL) { + if ((err = hash_memory(op_checked.hash_alg, op_checked.params->u.crypt.lparam, op_checked.params->u.crypt.lparamlen, DB, &x)) != CRYPT_OK) { goto LBL_ERR; } } else { /* can't pass hash_memory a NULL so use `out` with zero length */ - if ((err = hash_memory(lparam_hash_used, out, 0, DB, &x)) != CRYPT_OK) { + if ((err = hash_memory(op_checked.hash_alg, out, 0, DB, &x)) != CRYPT_OK) { goto LBL_ERR; } } @@ -111,13 +91,13 @@ int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, } /* now choose a random seed */ - if (prng_descriptor[prng_idx].read(seed, hLen, prng) != hLen) { + if (prng_descriptor[op_checked.params->wprng].read(seed, hLen, op_checked.params->prng) != hLen) { err = CRYPT_ERROR_READPRNG; goto LBL_ERR; } /* compute MGF1 of seed (k - hlen - 1) */ - if ((err = pkcs_1_mgf1(mgf_hash, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { + if ((err = pkcs_1_mgf1(op_checked.mgf1_hash_alg, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { goto LBL_ERR; } @@ -127,7 +107,7 @@ int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, } /* compute MGF1 of maskedDB (hLen) */ - if ((err = pkcs_1_mgf1(mgf_hash, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) { + if ((err = pkcs_1_mgf1(op_checked.mgf1_hash_alg, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) { goto LBL_ERR; } diff --git a/src/pk/pkcs1/pkcs_1_pss_decode.c b/src/pk/pkcs1/pkcs_1_pss_decode.c index fc258ea4f..4e41ede0c 100644 --- a/src/pk/pkcs1/pkcs_1_pss_decode.c +++ b/src/pk/pkcs1/pkcs_1_pss_decode.c @@ -10,46 +10,41 @@ #ifdef LTC_PKCS_1 /** - PKCS #1 v2.00 PSS decode + PKCS #1 v2.00 Signature Verification @param msghash The hash to verify @param msghashlen The length of the hash (octets) @param sig The signature data (encoded data) @param siglen The length of the signature data (octets) - @param saltlen The length of the salt used (octets) - @param hash_idx The index of the hash desired - @param mgf_hash_idx The index of the hash desired for MGF1 + @param params The PKCS#1 operation's parameters @param modulus_bitlen The bit length of the RSA modulus @param res [out] The result of the comparison, 1==valid, 0==invalid @return CRYPT_OK if successful (even if the comparison failed) */ -int pkcs_1_pss_decode_mgf1(const unsigned char *msghash, unsigned long msghashlen, - const unsigned char *sig, unsigned long siglen, - unsigned long saltlen, - int hash_idx, int mgf_hash_idx, - unsigned long modulus_bitlen, int *res) +int ltc_pkcs_1_pss_decode_mgf1(const unsigned char *msghash, unsigned long msghashlen, + const unsigned char *sig, unsigned long siglen, + ltc_rsa_op_parameters *params, + unsigned long modulus_bitlen, int *res) { unsigned char *DB, *mask, *salt, *hash; - unsigned long x, y, hLen, modulus_len; + unsigned long x, y, hLen, modulus_len, saltlen; int err; hash_state md; + ltc_rsa_op_checked op_checked = ltc_pkcs1_op_checked_init(params); LTC_ARGCHK(msghash != NULL); + LTC_ARGCHK(sig != NULL); + LTC_ARGCHK(params != NULL); LTC_ARGCHK(res != NULL); /* default to invalid */ *res = 0; - /* ensure hash is valid */ - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + if ((err = rsa_key_valid_op(LTC_PKCS1_VERIFY, &op_checked)) != CRYPT_OK) { return err; } - if (hash_idx != mgf_hash_idx) { - if ((err = hash_is_valid(mgf_hash_idx)) != CRYPT_OK) { - return err; - } - } - hLen = hash_descriptor[hash_idx].hashsize; + hLen = hash_descriptor[op_checked.hash_alg].hashsize; + saltlen = params->params.saltlen; modulus_bitlen--; modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0); @@ -102,7 +97,7 @@ int pkcs_1_pss_decode_mgf1(const unsigned char *msghash, unsigned long msghashle } /* generate mask of length modulus_len - hLen - 1 from hash */ - if ((err = pkcs_1_mgf1(mgf_hash_idx, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { + if ((err = pkcs_1_mgf1(op_checked.mgf1_hash_alg, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { goto LBL_ERR; } @@ -131,20 +126,20 @@ int pkcs_1_pss_decode_mgf1(const unsigned char *msghash, unsigned long msghashle } /* M = (eight) 0x00 || msghash || salt, mask = H(M) */ - if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) { + if ((err = hash_descriptor[op_checked.hash_alg].init(&md)) != CRYPT_OK) { goto LBL_ERR; } zeromem(mask, 8); - if ((err = hash_descriptor[hash_idx].process(&md, mask, 8)) != CRYPT_OK) { + if ((err = hash_descriptor[op_checked.hash_alg].process(&md, mask, 8)) != CRYPT_OK) { goto LBL_ERR; } - if ((err = hash_descriptor[hash_idx].process(&md, msghash, msghashlen)) != CRYPT_OK) { + if ((err = hash_descriptor[op_checked.hash_alg].process(&md, msghash, msghashlen)) != CRYPT_OK) { goto LBL_ERR; } - if ((err = hash_descriptor[hash_idx].process(&md, DB+x, saltlen)) != CRYPT_OK) { + if ((err = hash_descriptor[op_checked.hash_alg].process(&md, DB+x, saltlen)) != CRYPT_OK) { goto LBL_ERR; } - if ((err = hash_descriptor[hash_idx].done(&md, mask)) != CRYPT_OK) { + if ((err = hash_descriptor[op_checked.hash_alg].done(&md, mask)) != CRYPT_OK) { goto LBL_ERR; } @@ -170,25 +165,4 @@ int pkcs_1_pss_decode_mgf1(const unsigned char *msghash, unsigned long msghashle return err; } - -/** - PKCS #1 v2.00 PSS decode - @param msghash The hash to verify - @param msghashlen The length of the hash (octets) - @param sig The signature data (encoded data) - @param siglen The length of the signature data (octets) - @param saltlen The length of the salt used (octets) - @param hash_idx The index of the hash desired - @param modulus_bitlen The bit length of the RSA modulus - @param res [out] The result of the comparison, 1==valid, 0==invalid - @return CRYPT_OK if successful (even if the comparison failed) -*/ -int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, - const unsigned char *sig, unsigned long siglen, - unsigned long saltlen, int hash_idx, - unsigned long modulus_bitlen, int *res) -{ - return pkcs_1_pss_decode_mgf1(msghash, msghashlen, sig, siglen, saltlen, hash_idx, hash_idx, modulus_bitlen, res); -} - #endif /* LTC_PKCS_1 */ diff --git a/src/pk/pkcs1/pkcs_1_pss_encode.c b/src/pk/pkcs1/pkcs_1_pss_encode.c index 01d9636f9..9820c1e66 100644 --- a/src/pk/pkcs1/pkcs_1_pss_encode.c +++ b/src/pk/pkcs1/pkcs_1_pss_encode.c @@ -13,46 +13,34 @@ PKCS #1 v2.00 Signature Encoding @param msghash The hash to encode @param msghashlen The length of the hash (octets) - @param saltlen The length of the salt desired (octets) - @param prng An active PRNG context - @param prng_idx The index of the PRNG desired - @param hash_idx The index of the hash desired - @param mgf_hash_idx The index of the hash desired for MGF1 + @param params The PKCS#1 operation's parameters @param modulus_bitlen The bit length of the RSA modulus @param out [out] The destination of the encoding @param outlen [in/out] The max size and resulting size of the encoded data @return CRYPT_OK if successful */ -int pkcs_1_pss_encode_mgf1(const unsigned char *msghash, unsigned long msghashlen, - unsigned long saltlen, - prng_state *prng, int prng_idx, - int hash_idx, int mgf_hash_idx, - unsigned long modulus_bitlen, - unsigned char *out, unsigned long *outlen) +int ltc_pkcs_1_pss_encode_mgf1(const unsigned char *msghash, unsigned long msghashlen, + ltc_rsa_op_parameters *params, + unsigned long modulus_bitlen, + unsigned char *out, unsigned long *outlen) { unsigned char *DB, *mask, *salt, *hash; - unsigned long x, y, hLen, modulus_len; + unsigned long x, y, hLen, modulus_len, saltlen; int err; hash_state md; + ltc_rsa_op_checked op_checked = ltc_pkcs1_op_checked_init(params); LTC_ARGCHK(msghash != NULL); + LTC_ARGCHK(params != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); - /* ensure hashes and PRNG are valid */ - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { - return err; - } - if (hash_idx != mgf_hash_idx) { - if ((err = hash_is_valid(mgf_hash_idx)) != CRYPT_OK) { - return err; - } - } - if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { + if ((err = rsa_key_valid_op(LTC_PKCS1_SIGN, &op_checked)) != CRYPT_OK) { return err; } - hLen = hash_descriptor[hash_idx].hashsize; + hLen = hash_descriptor[op_checked.hash_alg].hashsize; + saltlen = params->params.saltlen; modulus_bitlen--; modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0); @@ -85,27 +73,27 @@ int pkcs_1_pss_encode_mgf1(const unsigned char *msghash, unsigned long ms /* generate random salt */ if (saltlen > 0) { - if (prng_descriptor[prng_idx].read(salt, saltlen, prng) != saltlen) { + if (prng_descriptor[params->wprng].read(salt, saltlen, params->prng) != saltlen) { err = CRYPT_ERROR_READPRNG; goto LBL_ERR; } } /* M = (eight) 0x00 || msghash || salt, hash = H(M) */ - if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) { + if ((err = hash_descriptor[op_checked.hash_alg].init(&md)) != CRYPT_OK) { goto LBL_ERR; } zeromem(DB, 8); - if ((err = hash_descriptor[hash_idx].process(&md, DB, 8)) != CRYPT_OK) { + if ((err = hash_descriptor[op_checked.hash_alg].process(&md, DB, 8)) != CRYPT_OK) { goto LBL_ERR; } - if ((err = hash_descriptor[hash_idx].process(&md, msghash, msghashlen)) != CRYPT_OK) { + if ((err = hash_descriptor[op_checked.hash_alg].process(&md, msghash, msghashlen)) != CRYPT_OK) { goto LBL_ERR; } - if ((err = hash_descriptor[hash_idx].process(&md, salt, saltlen)) != CRYPT_OK) { + if ((err = hash_descriptor[op_checked.hash_alg].process(&md, salt, saltlen)) != CRYPT_OK) { goto LBL_ERR; } - if ((err = hash_descriptor[hash_idx].done(&md, hash)) != CRYPT_OK) { + if ((err = hash_descriptor[op_checked.hash_alg].done(&md, hash)) != CRYPT_OK) { goto LBL_ERR; } @@ -118,7 +106,7 @@ int pkcs_1_pss_encode_mgf1(const unsigned char *msghash, unsigned long ms /* x += saltlen; */ /* generate mask of length modulus_len - hLen - 1 from hash */ - if ((err = pkcs_1_mgf1(mgf_hash_idx, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { + if ((err = pkcs_1_mgf1(op_checked.mgf1_hash_alg, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { goto LBL_ERR; } @@ -168,27 +156,4 @@ int pkcs_1_pss_encode_mgf1(const unsigned char *msghash, unsigned long ms return err; } - -/** - PKCS #1 v2.00 Signature Encoding using MGF1 and both hashes are the same - @param msghash The hash to encode - @param msghashlen The length of the hash (octets) - @param saltlen The length of the salt desired (octets) - @param prng An active PRNG context - @param prng_idx The index of the PRNG desired - @param hash_idx The index of the hash desired - @param modulus_bitlen The bit length of the RSA modulus - @param out [out] The destination of the encoding - @param outlen [in/out] The max size and resulting size of the encoded data - @return CRYPT_OK if successful -*/ -int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, - unsigned long saltlen, prng_state *prng, - int prng_idx, int hash_idx, - unsigned long modulus_bitlen, - unsigned char *out, unsigned long *outlen) -{ - return pkcs_1_pss_encode_mgf1(msghash, msghashlen, saltlen, prng, prng_idx, hash_idx, hash_idx, modulus_bitlen, out, outlen); -} - #endif /* LTC_PKCS_1 */ diff --git a/src/pk/rsa/rsa_decrypt_key.c b/src/pk/rsa/rsa_decrypt_key.c index a36ecb021..75de45deb 100644 --- a/src/pk/rsa/rsa_decrypt_key.c +++ b/src/pk/rsa/rsa_decrypt_key.c @@ -8,44 +8,37 @@ */ #ifdef LTC_MRSA - /** - PKCS #1 decrypt then v1.5 or OAEP depad + Decrypt then (PKCS #1 v2.0) OAEP or (PKCS #1 v1.5) EME depad @param in The ciphertext @param inlen The length of the ciphertext (octets) @param out [out] The plaintext @param outlen [in/out] The max size and resulting size of the plaintext (octets) - @param lparam The system "lparam" value - @param lparamlen The length of the lparam value (octets) - @param mgf_hash The hash algorithm used for the MGF - @param lparam_hash The hash algorithm used when hashing the lparam (can be -1) - @param padding Type of padding (LTC_PKCS_1_OAEP or LTC_PKCS_1_V1_5) + @param params The RSA operation's parameters @param stat [out] Result of the decryption, 1==valid, 0==invalid @param key The corresponding private RSA key @return CRYPT_OK if succcessul (even if invalid) */ -int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen, +int rsa_decrypt_key_v2(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, - const unsigned char *lparam, unsigned long lparamlen, - int mgf_hash, int lparam_hash, - int padding, + ltc_rsa_op_parameters *params, int *stat, const rsa_key *key) { - unsigned long modulus_bitlen, modulus_bytelen, x; int err; unsigned char *tmp; + unsigned long modulus_bitlen, modulus_bytelen, x; + ltc_rsa_op_checked op_checked = ltc_rsa_op_checked_init(key, params); LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(key != NULL); LTC_ARGCHK(stat != NULL); /* default to invalid */ *stat = 0; /* valid padding? */ - if ((err = rsa_key_valid_op(key, LTC_RSA_CRYPT, padding, mgf_hash)) != CRYPT_OK) { + if ((err = rsa_key_valid_op(LTC_RSA_DECRYPT, &op_checked)) != CRYPT_OK) { return err; } @@ -64,17 +57,16 @@ int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen return CRYPT_MEM; } - /* rsa decode the packet */ + /* rsa exptmod the packet */ x = inlen; if ((err = ltc_mp.rsa_me(in, inlen, tmp, &x, PK_PRIVATE, key)) != CRYPT_OK) { XFREE(tmp); return err; } - if (padding == LTC_PKCS_1_OAEP) { - /* now OAEP decode the packet */ - err = pkcs_1_oaep_decode(tmp, x, lparam, lparamlen, modulus_bitlen, mgf_hash, - lparam_hash, out, outlen, stat); + if (params->padding == LTC_PKCS_1_OAEP) { + /* now OAEP depad the packet */ + err = ltc_pkcs_1_oaep_decode(tmp, x, modulus_bitlen, params, out, outlen, stat); } else { /* now PKCS #1 v1.5 depad the packet */ err = pkcs_1_v1_5_decode(tmp, x, LTC_PKCS_1_EME, modulus_bitlen, out, outlen, stat); diff --git a/src/pk/rsa/rsa_encrypt_key.c b/src/pk/rsa/rsa_encrypt_key.c index 83fb2c5a6..c43d13869 100644 --- a/src/pk/rsa/rsa_encrypt_key.c +++ b/src/pk/rsa/rsa_encrypt_key.c @@ -8,48 +8,33 @@ */ #ifdef LTC_MRSA - /** - (PKCS #1 v2.0) OAEP pad then encrypt - @param in The plaintext - @param inlen The length of the plaintext (octets) - @param out [out] The ciphertext - @param outlen [in/out] The max size and resulting size of the ciphertext - @param lparam The system "lparam" for the encryption - @param lparamlen The length of lparam (octets) - @param prng An active PRNG - @param prng_idx The index of the desired prng - @param hash_idx The index of the desired hash - @param padding Type of padding (LTC_PKCS_1_OAEP or LTC_PKCS_1_V1_5) - @param key The RSA key to encrypt to - @return CRYPT_OK if successful + (PKCS #1 v2.0) OAEP or (PKCS #1 v1.5) EME pad then encrypt + @param in The plaintext + @param inlen The length of the plaintext (octets) + @param out [out] The ciphertext + @param outlen [in/out] The max size and resulting size of the ciphertext + @param params The RSA operation's parameters + @param key The RSA key to encrypt to + @return CRYPT_OK if successful */ -int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - const unsigned char *lparam, unsigned long lparamlen, - prng_state *prng, int prng_idx, - int mgf_hash, int lparam_hash, - int padding, - const rsa_key *key) +int rsa_encrypt_key_v2(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + ltc_rsa_op_parameters *params, + const rsa_key *key) { - unsigned long modulus_bitlen, modulus_bytelen, x; int err; + unsigned long modulus_bitlen, modulus_bytelen, x; + ltc_rsa_op_checked op_checked = ltc_rsa_op_checked_init(key, params); LTC_ARGCHK((inlen == 0) || (in != NULL)); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); - LTC_ARGCHK(key != NULL); - /* valid padding? */ - if ((err = rsa_key_valid_op(key, LTC_RSA_CRYPT, padding, mgf_hash)) != CRYPT_OK) { + if ((err = rsa_key_valid_op(LTC_RSA_ENCRYPT, &op_checked)) != CRYPT_OK) { return err; } - /* valid prng? */ - if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { - return err; - } - /* get modulus len in bits */ modulus_bitlen = ltc_mp_count_bits( (key->N)); @@ -60,19 +45,17 @@ int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen, return CRYPT_BUFFER_OVERFLOW; } - if (padding == LTC_PKCS_1_OAEP) { + if (params->padding == LTC_PKCS_1_OAEP) { /* OAEP pad the key */ x = *outlen; - if ((err = pkcs_1_oaep_encode(in, inlen, lparam, - lparamlen, modulus_bitlen, prng, prng_idx, mgf_hash, - lparam_hash, out, &x)) != CRYPT_OK) { + if ((err = ltc_pkcs_1_oaep_encode(in, inlen, modulus_bitlen, params, out, &x)) != CRYPT_OK) { return err; } } else { /* PKCS #1 v1.5 pad the key */ x = *outlen; if ((err = pkcs_1_v1_5_encode(in, inlen, LTC_PKCS_1_EME, - modulus_bitlen, prng, prng_idx, + modulus_bitlen, params->prng, params->wprng, out, &x)) != CRYPT_OK) { return err; } diff --git a/src/pk/rsa/rsa_key.c b/src/pk/rsa/rsa_key.c index 5bb37f7fb..319000603 100644 --- a/src/pk/rsa/rsa_key.c +++ b/src/pk/rsa/rsa_key.c @@ -100,68 +100,128 @@ void rsa_free(rsa_key *key) XMEMSET(&key->params, 0, sizeof(key->params)); } -static LTC_INLINE int s_rsa_key_valid_pss_algs(const rsa_key *key, int padding, int hash_idx) +static LTC_INLINE int s_rsa_key_valid_pss_algs(ltc_rsa_op_checked *check) { - if (!key->params.pss_oaep) { + const ltc_rsa_parameters *key_params; + int padding = check->params->padding; + if (check->key == NULL) { + return CRYPT_OK; + } + key_params = &check->key->params; + if (!key_params->pss_oaep + && (!check->params->params.pss_oaep + || padding == LTC_PKCS_1_V1_5 + || padding == LTC_PKCS_1_V1_5_NA1)) { return CRYPT_OK; } if (padding != LTC_PKCS_1_PSS) { return CRYPT_PK_TYPE_MISMATCH; } - if (key->params.hash_alg == NULL || find_hash(key->params.hash_alg) != hash_idx) { + if (key_params->hash_alg == NULL || find_hash(key_params->hash_alg) != check->hash_alg) { + return CRYPT_INVALID_HASH; + } + if (key_params->mgf1_hash_alg == NULL) { return CRYPT_INVALID_HASH; } - if (key->params.mgf1_hash_alg == NULL) { + if ((check->mgf1_hash_alg = find_hash(key_params->mgf1_hash_alg)) == -1) { return CRYPT_INVALID_HASH; } - return hash_is_valid(find_hash(key->params.mgf1_hash_alg)); + return hash_is_valid(check->mgf1_hash_alg); } -static LTC_INLINE int s_rsa_key_valid_sign(const rsa_key *key, int padding, int hash_idx) +static LTC_INLINE int s_rsa_key_set_hash_algs(ltc_rsa_op_checked *check) { - if ((padding != LTC_PKCS_1_V1_5) && - (padding != LTC_PKCS_1_PSS) && - (padding != LTC_PKCS_1_V1_5_NA1)) { - return CRYPT_PK_INVALID_PADDING; + ltc_rsa_op_parameters *params = check->params; + if (params->params.hash_alg == NULL || + (check->hash_alg = find_hash(params->params.hash_alg)) == -1) { + return CRYPT_INVALID_HASH; + } + if (params->params.mgf1_hash_alg == NULL || + (check->mgf1_hash_alg = find_hash(params->params.mgf1_hash_alg)) == -1) { + return CRYPT_INVALID_HASH; } + return CRYPT_OK; +} - if (padding != LTC_PKCS_1_V1_5_NA1) { - int err; - /* valid hash ? */ - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { - return err; +static LTC_INLINE int s_rsa_key_valid_sign(ltc_rsa_op_checked *check) +{ + ltc_rsa_op_parameters *params = check->params; + if ((params->padding != LTC_PKCS_1_V1_5) + && (params->padding != LTC_PKCS_1_PSS) + && (params->padding != LTC_PKCS_1_V1_5_NA1)) { + return CRYPT_PK_INVALID_PADDING; + } + + if (params->padding != LTC_PKCS_1_V1_5_NA1) { + int err = s_rsa_key_set_hash_algs(check); + if (err != CRYPT_OK) { + return err; } } - return s_rsa_key_valid_pss_algs(key, padding, hash_idx); + if (params->padding == LTC_PKCS_1_V1_5) { + /* not all hashes have OIDs... so sad */ + if (check->hash_alg == -1 + || hash_descriptor[check->hash_alg].OIDlen == 0) { + return CRYPT_INVALID_ARG; + } + } + return s_rsa_key_valid_pss_algs(check); } -static LTC_INLINE int s_rsa_key_valid_crypt(const rsa_key *key, int padding, int hash_idx) +static LTC_INLINE int s_rsa_key_valid_crypt(ltc_rsa_op_checked *check) { - if ((padding != LTC_PKCS_1_V1_5) && - (padding != LTC_PKCS_1_OAEP)) { + ltc_rsa_op_parameters *params = check->params; + if ((params->padding != LTC_PKCS_1_V1_5) && + (params->padding != LTC_PKCS_1_OAEP)) { return CRYPT_PK_INVALID_PADDING; } - if (padding == LTC_PKCS_1_OAEP) { - int err; - /* valid hash? */ - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { - return err; + if (params->padding == LTC_PKCS_1_OAEP) { + int err = s_rsa_key_set_hash_algs(check); + if (err != CRYPT_OK) { + return err; } } - return s_rsa_key_valid_pss_algs(key, padding, hash_idx); + return s_rsa_key_valid_pss_algs(check); +} + +static LTC_INLINE int s_rsa_check_prng(ltc_rsa_op_parameters *params) +{ + if (params->padding != LTC_PKCS_1_PSS) + return CRYPT_OK; + if (params->prng == NULL) + return CRYPT_INVALID_PRNG; + /* valid prng ? */ + return prng_is_valid(params->wprng); } -int rsa_key_valid_op(const rsa_key *key, ltc_rsa_op op, int padding, int hash_idx) +int rsa_key_valid_op(ltc_rsa_op op, ltc_rsa_op_checked *check) { + int err; + check->hash_alg = check->mgf1_hash_alg = -1; + LTC_ARGCHK(check->params != NULL); + if ((op & LTC_RSA_OP_PKCS1) != LTC_RSA_OP_PKCS1) { + /* PKCS#1 ops don't need an RSA key */ + LTC_ARGCHK(check->key != NULL); + } + if ((op & LTC_RSA_OP_SEND) == LTC_RSA_OP_SEND) { + if ((err = s_rsa_check_prng(check->params)) != CRYPT_OK) { + return err; + } + } switch (op) { + case LTC_RSA_ENCRYPT: + case LTC_RSA_DECRYPT: + case LTC_PKCS1_ENCRYPT: + case LTC_PKCS1_DECRYPT: + return s_rsa_key_valid_crypt(check); case LTC_RSA_SIGN: - return s_rsa_key_valid_sign(key, padding, hash_idx); - case LTC_RSA_CRYPT: - return s_rsa_key_valid_crypt(key, padding, hash_idx); - default: - return CRYPT_ERROR; + case LTC_RSA_VERIFY: + case LTC_PKCS1_SIGN: + case LTC_PKCS1_VERIFY: + return s_rsa_key_valid_sign(check); } + return CRYPT_ERROR; } int rsa_params_equal(const ltc_rsa_parameters *a, const ltc_rsa_parameters *b) @@ -183,4 +243,33 @@ int rsa_params_equal(const ltc_rsa_parameters *a, const ltc_rsa_parameters *b) return 1; } +int rsa_args_to_op_params(const unsigned char *lparam, unsigned long lparamlen, + prng_state *prng, int prng_idx, int hash_idx, + int padding, unsigned long saltlen, + ltc_rsa_op_parameters *params) +{ + int err; + ltc_rsa_op_parameters p = { + .u.crypt.lparam = lparam, + .u.crypt.lparamlen = lparamlen, + .prng = prng, + .wprng = prng_idx, + .padding = padding, + .params.saltlen = saltlen, + }; + if ((err = hash_is_valid(hash_idx)) == CRYPT_OK) { + if (hash_descriptor[hash_idx].name == NULL) { + return CRYPT_INVALID_HASH; + } + p.params.hash_alg = hash_descriptor[hash_idx].name; + p.params.mgf1_hash_alg = p.params.hash_alg; + *params = p; + } else if (padding == LTC_PKCS_1_V1_5 || padding == LTC_PKCS_1_V1_5_NA1) { + /* PKCS#1 1.5 does not necessarily require a hash */ + err = CRYPT_OK; + *params = p; + } + return err; +} + #endif diff --git a/src/pk/rsa/rsa_sign_hash.c b/src/pk/rsa/rsa_sign_hash.c index 4445f712b..ab3af86ae 100644 --- a/src/pk/rsa/rsa_sign_hash.c +++ b/src/pk/rsa/rsa_sign_hash.c @@ -8,64 +8,48 @@ */ #ifdef LTC_MRSA - /** PKCS #1 pad then sign - @param in The hash to sign - @param inlen The length of the hash to sign (octets) - @param out [out] The signature - @param outlen [in/out] The max size and resulting size of the signature - @param padding Type of padding (LTC_PKCS_1_PSS, LTC_PKCS_1_V1_5 or LTC_PKCS_1_V1_5_NA1) - @param prng An active PRNG state - @param prng_idx The index of the PRNG desired - @param hash_idx The index of the hash desired - @param saltlen The length of the salt desired (octets) + @param hash The hash to sign + @param hashlen The length of the hash to sign (octets) + @param sig [out] The signature + @param siglen [in/out] The max size and resulting size of the signature + @param params The RSA operation parameters @param key The private RSA key to use @return CRYPT_OK if successful */ -int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, - unsigned char *out, unsigned long *outlen, - int padding, - prng_state *prng, int prng_idx, - int hash_idx, int mgf_hash_idx, - unsigned long saltlen, - const rsa_key *key) +int rsa_sign_hash_v2(const unsigned char *hash, unsigned long hashlen, + unsigned char *sig, unsigned long *siglen, + ltc_rsa_op_parameters *params, + const rsa_key *key) { unsigned long modulus_bitlen, modulus_bytelen, x, y; int err; + ltc_rsa_op_checked op_check = ltc_rsa_op_checked_init(key, params); - LTC_ARGCHK(in != NULL); - LTC_ARGCHK(out != NULL); - LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(hash != NULL); + LTC_ARGCHK(sig != NULL); + LTC_ARGCHK(siglen != NULL); LTC_ARGCHK(key != NULL); - /* valid padding? */ - if ((err = rsa_key_valid_op(key, LTC_RSA_SIGN, padding, hash_idx)) != CRYPT_OK) { + if ((err = rsa_key_valid_op(LTC_RSA_SIGN, &op_check)) != CRYPT_OK) { return err; } - if (padding == LTC_PKCS_1_PSS) { - /* valid prng ? */ - if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) { - return err; - } - } - /* get modulus len in bits */ modulus_bitlen = ltc_mp_count_bits((key->N)); - /* outlen must be at least the size of the modulus */ + /* siglen must be at least the size of the modulus */ modulus_bytelen = ltc_mp_unsigned_bin_size((key->N)); - if (modulus_bytelen > *outlen) { - *outlen = modulus_bytelen; + if (modulus_bytelen > *siglen) { + *siglen = modulus_bytelen; return CRYPT_BUFFER_OVERFLOW; } - if (padding == LTC_PKCS_1_PSS) { + if (params->padding == LTC_PKCS_1_PSS) { /* PSS pad the key */ - x = *outlen; - if ((err = pkcs_1_pss_encode_mgf1(in, inlen, saltlen, prng, prng_idx, - hash_idx, mgf_hash_idx, modulus_bitlen, out, &x)) != CRYPT_OK) { + x = *siglen; + if ((err = ltc_pkcs_1_pss_encode_mgf1(hash, hashlen, params, modulus_bitlen, sig, &x)) != CRYPT_OK) { return err; } } else { @@ -73,12 +57,8 @@ int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, unsigned char *tmpin = NULL; const unsigned char *tmpin_ro; - if (padding == LTC_PKCS_1_V1_5) { + if (params->padding == LTC_PKCS_1_V1_5) { ltc_asn1_list digestinfo[2], siginfo[2]; - /* not all hashes have OIDs... so sad */ - if (hash_descriptor[hash_idx].OIDlen == 0) { - return CRYPT_INVALID_ARG; - } /* construct the SEQUENCE SEQUENCE { @@ -88,10 +68,10 @@ int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, hash OCTET STRING } */ - LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[hash_idx].OID, hash_descriptor[hash_idx].OIDlen); + LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, hash_descriptor[op_check.hash_alg].OID, hash_descriptor[op_check.hash_alg].OIDlen); LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0); LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2); - LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, in, inlen); + LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, hash, hashlen); /* allocate memory for the encoding */ y = ltc_mp_unsigned_bin_size(key->N); @@ -107,14 +87,14 @@ int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, tmpin_ro = tmpin; } else { /* set the pointer and data-length to the input values */ - tmpin_ro = in; - y = inlen; + tmpin_ro = hash; + y = hashlen; } - x = *outlen; - err = pkcs_1_v1_5_encode(tmpin_ro, y, LTC_PKCS_1_EMSA, modulus_bitlen, NULL, 0, out, &x); + x = *siglen; + err = pkcs_1_v1_5_encode(tmpin_ro, y, LTC_PKCS_1_EMSA, modulus_bitlen, NULL, 0, sig, &x); - if (padding == LTC_PKCS_1_V1_5) { + if (params->padding == LTC_PKCS_1_V1_5) { XFREE(tmpin); } @@ -124,7 +104,7 @@ int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, } /* RSA encode it */ - return ltc_mp.rsa_me(out, x, out, outlen, PK_PRIVATE, key); + return ltc_mp.rsa_me(sig, x, sig, siglen, PK_PRIVATE, key); } #endif /* LTC_MRSA */ diff --git a/src/pk/rsa/rsa_verify_hash.c b/src/pk/rsa/rsa_verify_hash.c index ede234497..a50f7975a 100644 --- a/src/pk/rsa/rsa_verify_hash.c +++ b/src/pk/rsa/rsa_verify_hash.c @@ -1,5 +1,6 @@ /* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ +#define LTC_DEPRECATED(x) #include "tomcrypt_private.h" /** @@ -8,30 +9,27 @@ */ #ifdef LTC_MRSA - /** PKCS #1 de-sign then v1.5 or PSS depad @param sig The signature data @param siglen The length of the signature data (octets) @param hash The hash of the message that was signed @param hashlen The length of the hash of the message that was signed (octets) - @param padding Type of padding (LTC_PKCS_1_PSS, LTC_PKCS_1_V1_5 or LTC_PKCS_1_V1_5_NA1) - @param hash_idx The index of the desired hash - @param saltlen The length of the salt used during signature + @param params The RSA operation parameters @param stat [out] The result of the signature comparison, 1==valid, 0==invalid @param key The public RSA key corresponding to the key that performed the signature @return CRYPT_OK on success (even if the signature is invalid) */ -int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen, - const unsigned char *hash, unsigned long hashlen, - int padding, - int hash_idx, int mgf_hash_idx, - unsigned long saltlen, - int *stat, const rsa_key *key) +int rsa_verify_hash_v2(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + ltc_rsa_op_parameters *params, + int *stat, + const rsa_key *key) { unsigned long modulus_bitlen, modulus_bytelen, x; int err; unsigned char *tmpbuf; + ltc_rsa_op_checked op_check = ltc_rsa_op_checked_init(key, params); LTC_ARGCHK(hash != NULL); LTC_ARGCHK(sig != NULL); @@ -41,8 +39,7 @@ int rsa_verify_hash_ex(const unsigned char *sig, unsigned long sigle /* default to invalid */ *stat = 0; - /* valid padding? */ - if ((err = rsa_key_valid_op(key, LTC_RSA_SIGN, padding, hash_idx)) != CRYPT_OK) { + if ((err = rsa_key_valid_op(LTC_RSA_VERIFY, &op_check)) != CRYPT_OK) { return err; } @@ -74,14 +71,14 @@ int rsa_verify_hash_ex(const unsigned char *sig, unsigned long sigle return CRYPT_INVALID_PACKET; } - if (padding == LTC_PKCS_1_PSS) { + if (params->padding == LTC_PKCS_1_PSS) { /* PSS decode and verify it */ if(modulus_bitlen%8 == 1){ - err = pkcs_1_pss_decode_mgf1(hash, hashlen, tmpbuf+1, x-1, saltlen, hash_idx, mgf_hash_idx, modulus_bitlen, stat); + err = ltc_pkcs_1_pss_decode_mgf1(hash, hashlen, tmpbuf+1, x-1, params, modulus_bitlen, stat); } else{ - err = pkcs_1_pss_decode_mgf1(hash, hashlen, tmpbuf, x, saltlen, hash_idx, mgf_hash_idx, modulus_bitlen, stat); + err = ltc_pkcs_1_pss_decode_mgf1(hash, hashlen, tmpbuf, x, params, modulus_bitlen, stat); } } else { @@ -103,16 +100,10 @@ int rsa_verify_hash_ex(const unsigned char *sig, unsigned long sigle goto bail_2; } - if (padding == LTC_PKCS_1_V1_5) { + if (params->padding == LTC_PKCS_1_V1_5) { unsigned long loid[16], reallen; ltc_asn1_list digestinfo[2], siginfo[2]; - /* not all hashes have OIDs... so sad */ - if (hash_descriptor[hash_idx].OIDlen == 0) { - err = CRYPT_INVALID_ARG; - goto bail_2; - } - /* now we must decode out[0...outlen-1] using ASN.1, test the OID and then test the hash */ /* construct the SEQUENCE SEQUENCE { @@ -124,16 +115,13 @@ int rsa_verify_hash_ex(const unsigned char *sig, unsigned long sigle */ LTC_SET_ASN1(digestinfo, 0, LTC_ASN1_OBJECT_IDENTIFIER, loid, LTC_ARRAY_SIZE(loid)); LTC_SET_ASN1(digestinfo, 1, LTC_ASN1_NULL, NULL, 0); + digestinfo[1].optional = 1; LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 2); LTC_SET_ASN1(siginfo, 1, LTC_ASN1_OCTET_STRING, tmpbuf, siglen); if (der_decode_sequence_strict(out, outlen, siginfo, 2) != CRYPT_OK) { - /* fallback to Legacy:missing NULL */ - LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE, digestinfo, 1); - if ((err = der_decode_sequence_strict(out, outlen, siginfo, 2)) != CRYPT_OK) { - XFREE(out); - goto bail_2; - } + XFREE(out); + goto bail_2; } if ((err = der_length_sequence(siginfo, 2, &reallen)) != CRYPT_OK) { @@ -143,8 +131,8 @@ int rsa_verify_hash_ex(const unsigned char *sig, unsigned long sigle /* test OID */ if ((reallen == outlen) && - (digestinfo[0].size == hash_descriptor[hash_idx].OIDlen) && - (XMEMCMP(digestinfo[0].data, hash_descriptor[hash_idx].OID, sizeof(unsigned long) * hash_descriptor[hash_idx].OIDlen) == 0) && + (digestinfo[0].size == hash_descriptor[op_check.hash_alg].OIDlen) && + (XMEMCMP(digestinfo[0].data, hash_descriptor[op_check.hash_alg].OID, sizeof(unsigned long) * hash_descriptor[op_check.hash_alg].OIDlen) == 0) && (siginfo[1].size == hashlen) && (XMEMCMP(siginfo[1].data, hash, hashlen) == 0)) { *stat = 1; diff --git a/tests/pkcs_1_eme_test.c b/tests/pkcs_1_eme_test.c index 9e818ace6..1578fab18 100644 --- a/tests/pkcs_1_eme_test.c +++ b/tests/pkcs_1_eme_test.c @@ -42,9 +42,9 @@ int pkcs_1_eme_test(void) unsigned long buflen = sizeof(buf), obuflen = sizeof(obuf); int stat; prng_descriptor[prng_idx].add_entropy(s->o2, s->o2_l, (void*)no_prng_desc); - DOX(rsa_encrypt_key_ex(s->o1, s->o1_l, obuf, &obuflen, NULL, 0, (void*)no_prng_desc, prng_idx, -1, -1, LTC_PKCS_1_V1_5, key), s->name); + DOX(rsa_encrypt_key_ex(s->o1, s->o1_l, obuf, &obuflen, NULL, 0, (void*)no_prng_desc, prng_idx, -1, LTC_PKCS_1_V1_5, key), s->name); COMPARE_TESTVECTOR(obuf, obuflen, s->o3, s->o3_l,s->name, j); - DOX(rsa_decrypt_key_ex(obuf, obuflen, buf, &buflen, NULL, 0, -1, -1, LTC_PKCS_1_V1_5, &stat, key), s->name); + DOX(rsa_decrypt_key_ex(obuf, obuflen, buf, &buflen, NULL, 0, -1, LTC_PKCS_1_V1_5, &stat, key), s->name); DOX(stat == 1?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, s->name); } /* for */ diff --git a/tests/pkcs_1_emsa_test.c b/tests/pkcs_1_emsa_test.c index 327f2b5df..43fb112ae 100644 --- a/tests/pkcs_1_emsa_test.c +++ b/tests/pkcs_1_emsa_test.c @@ -39,9 +39,9 @@ int pkcs_1_emsa_test(void) unsigned long buflen = sizeof(buf), obuflen = sizeof(obuf); int stat; DOX(hash_memory(hash_idx, s->o1, s->o1_l, buf, &buflen), s->name); - DOX(rsa_sign_hash_ex(buf, buflen, obuf, &obuflen, LTC_PKCS_1_V1_5, NULL, -1, hash_idx, -1, 0, key), s->name); + DOX(rsa_sign_hash_ex(buf, buflen, obuf, &obuflen, LTC_PKCS_1_V1_5, NULL, -1, hash_idx, 0, key), s->name); COMPARE_TESTVECTOR(obuf, obuflen, s->o2, s->o2_l,s->name, j); - DOX(rsa_verify_hash_ex(obuf, obuflen, buf, buflen, LTC_PKCS_1_V1_5, hash_idx, -1, 0, &stat, key), s->name); + DOX(rsa_verify_hash_ex(obuf, obuflen, buf, buflen, LTC_PKCS_1_V1_5, hash_idx, 0, &stat, key), s->name); DOX(stat == 1?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, s->name); } /* for */ diff --git a/tests/pkcs_1_test.c b/tests/pkcs_1_test.c index de0f7d307..00d90bfed 100644 --- a/tests/pkcs_1_test.c +++ b/tests/pkcs_1_test.c @@ -46,11 +46,11 @@ int pkcs_1_test(void) /* encode it */ l1 = sizeof(buf[1]); - DO(pkcs_1_oaep_encode(buf[0], l3, lparam, lparamlen, modlen, &yarrow_prng, prng_idx, hash_idx, -1, buf[1], &l1)); + DO(pkcs_1_oaep_encode(buf[0], l3, lparam, lparamlen, modlen, &yarrow_prng, prng_idx, hash_idx, buf[1], &l1)); /* decode it */ l2 = sizeof(buf[2]); - DO(pkcs_1_oaep_decode(buf[1], l1, lparam, lparamlen, modlen, hash_idx, -1, buf[2], &l2, &res1)); + DO(pkcs_1_oaep_decode(buf[1], l1, lparam, lparamlen, modlen, hash_idx, buf[2], &l2, &res1)); if (res1 != 1 || l2 != l3 || memcmp(buf[2], buf[0], l3) != 0) { fprintf(stderr, "Outsize == %lu, should have been %lu, res1 = %d, lparamlen = %lu, msg contents follow.\n", l2, l3, res1, lparamlen); diff --git a/tests/rsa_test.c b/tests/rsa_test.c index acc82d5b8..7b81f7670 100644 --- a/tests/rsa_test.c +++ b/tests/rsa_test.c @@ -184,6 +184,7 @@ static int rsa_compat_test(void) int stat, i; unsigned char buf[1024], key_parts[8][128]; unsigned long len, key_lens[8]; + ltc_rsa_op_parameters rsa_params = {0}; /* try reading the key */ DO(rsa_import(ltc_rsa_private_test_key, sizeof(ltc_rsa_private_test_key), &key)); @@ -191,15 +192,16 @@ static int rsa_compat_test(void) /* sign-verify a message with PKCS #1 v1.5 no ASN.1 */ len = sizeof(buf); - DO(rsa_sign_hash_ex((unsigned char*)"test", 4, buf, &len, LTC_PKCS_1_V1_5_NA1, NULL, 0, 0, 0, 0, &key)); + rsa_params.padding = LTC_PKCS_1_V1_5_NA1; + DO(rsa_sign_hash_v2((unsigned char*)"test", 4, buf, &len, &rsa_params, &key)); if (len != sizeof(openssl_rsautl_pkcs) || memcmp(buf, openssl_rsautl_pkcs, len)) { - fprintf(stderr, "RSA rsa_sign_hash_ex + LTC_PKCS_1_V1_5_NA1 failed\n"); + fprintf(stderr, "RSA rsa_sign_hash_v2 + LTC_PKCS_1_V1_5_NA1 failed\n"); return 1; } stat = 0; - DO(rsa_verify_hash_ex(openssl_rsautl_pkcs, sizeof(openssl_rsautl_pkcs), (unsigned char*)"test", 4, LTC_PKCS_1_V1_5_NA1, 0, 0, 0, &stat, &pubkey)); + DO(rsa_verify_hash_v2(openssl_rsautl_pkcs, sizeof(openssl_rsautl_pkcs), (unsigned char*)"test", 4, &rsa_params, &stat, &pubkey)); if (stat != 1) { - fprintf(stderr, "RSA rsa_verify_hash_ex + LTC_PKCS_1_V1_5_NA1 failed\n"); + fprintf(stderr, "RSA rsa_verify_hash_v2 + LTC_PKCS_1_V1_5_NA1 failed\n"); return 1; } rsa_free(&pubkey); @@ -319,6 +321,7 @@ static int s_rsa_cryptx_issue_69(void) unsigned char buf0[512], buf1[512]; unsigned long l0, l1; int stat; + ltc_rsa_op_parameters rsa_params = {0}; l0 = sizeof(buf0); l1 = sizeof(buf1); @@ -331,9 +334,10 @@ static int s_rsa_cryptx_issue_69(void) l1 = sizeof(buf1); DO(radix_to_bin(sig1, 16, buf0, &l0)); DO(radix_to_bin(hash, 16, buf1, &l1)); - SHOULD_FAIL(rsa_verify_hash_ex(buf0, l0, buf1, l1, LTC_PKCS_1_V1_5, 0, 0, 0, &stat, &key)); + rsa_params.padding = LTC_PKCS_1_V1_5; + SHOULD_FAIL(rsa_verify_hash_v2(buf0, l0, buf1, l1, &rsa_params, &stat, &key)); DO(radix_to_bin(sig2, 16, buf0, &l0)); - SHOULD_FAIL(rsa_verify_hash_ex(buf0, l0, buf1, l1, LTC_PKCS_1_V1_5, 0, 0, 0, &stat, &key)); + SHOULD_FAIL(rsa_verify_hash_v2(buf0, l0, buf1, l1, &rsa_params, &stat, &key)); rsa_free(&key); return CRYPT_OK; } @@ -452,13 +456,14 @@ int rsa_test(void) { unsigned char in[1024], out[1024], tmp[3072]; rsa_key key, privKey, pubKey; - int hash_idx, prng_idx, stat, stat2, i, mgf_hash, label_hash; - unsigned long rsa_msgsize, len, len2, len3, cnt, cnt2, max_msgsize; + int prng_idx, stat, stat2, i, mgf_hash; + unsigned long rsa_msgsize, len, len2, len3, cnt, cnt2, max_msgsize, label_hash; static unsigned char lparam[] = { 0x01, 0x02, 0x03, 0x04 }; void* dP; unsigned char* p; unsigned char* p2; unsigned char* p3; + ltc_rsa_op_parameters rsa_params = {0}; if (ltc_mp.name == NULL) return CRYPT_NOP; @@ -466,12 +471,15 @@ int rsa_test(void) return 1; } - hash_idx = find_hash("sha1"); - prng_idx = find_prng("yarrow"); - if (hash_idx == -1 || prng_idx == -1) { + rsa_params.params.hash_alg = "sha1"; + rsa_params.wprng = find_prng("yarrow"); + mgf_hash = find_hash(rsa_params.params.hash_alg); + if (mgf_hash == -1 || rsa_params.wprng == -1) { fprintf(stderr, "rsa_test requires LTC_SHA1 and yarrow"); return 1; } + rsa_params.prng = &yarrow_prng; + prng_idx = rsa_params.wprng; #ifdef LTC_TEST_READDIR DO(test_process_dir("tests/rsa", &key, s_rsa_import_x509, NULL, (dir_cleanup_cb)rsa_free, "rsa_test")); @@ -512,13 +520,13 @@ print_hex("q", tmp, len); /* make a random key/msg */ ENSURE(yarrow_read(in, 117, &yarrow_prng) == 117); + rsa_params.padding = LTC_PKCS_1_OAEP; #ifdef LTC_TEST_EXT for (mgf_hash = 0; mgf_hash < TAB_SIZE; ++mgf_hash) { if (hash_is_valid(mgf_hash) != CRYPT_OK) continue; #else { - mgf_hash = hash_idx; #endif for (label_hash = 0; label_hash < TAB_SIZE; ++label_hash) { if (hash_is_valid(label_hash) != CRYPT_OK) @@ -526,6 +534,8 @@ print_hex("q", tmp, len); if (2 * hash_descriptor[label_hash].hashsize > 126) continue; max_msgsize = 128 - (2 * hash_descriptor[label_hash].hashsize) - 2; + rsa_params.params.hash_alg = hash_descriptor[label_hash].name; + rsa_params.params.mgf1_hash_alg = hash_descriptor[mgf_hash].name; #if defined(LTC_TEST_DBG) && LTC_TEST_DBG > 1 fprintf(stderr, "Test MGF(%s), Labelhash(%s) with max_msgsize %lu\n", hash_descriptor[mgf_hash].name, hash_descriptor[label_hash].name, max_msgsize); @@ -536,59 +546,66 @@ print_hex("q", tmp, len); len = sizeof(out); len2 = rsa_msgsize; - DO(rsa_encrypt_key_ex(in, rsa_msgsize, out, &len, NULL, 0, &yarrow_prng, prng_idx, mgf_hash, label_hash, LTC_PKCS_1_OAEP, &key)); + DO(rsa_encrypt_key_v2(in, rsa_msgsize, out, &len, &rsa_params, &key)); /* change a byte */ out[8] ^= 1; - SHOULD_FAIL(rsa_decrypt_key_ex(out, len, tmp, &len2, NULL, 0, mgf_hash, label_hash, LTC_PKCS_1_OAEP, &stat2, &key)); + SHOULD_FAIL(rsa_decrypt_key_v2(out, len, tmp, &len2, &rsa_params, &stat2, &key)); /* change a byte back */ out[8] ^= 1; ENSURE(len2 == rsa_msgsize); len2 = rsa_msgsize; - DO(rsa_decrypt_key_ex(out, len, tmp, &len2, NULL, 0, mgf_hash, label_hash, LTC_PKCS_1_OAEP, &stat, &key)); + DO(rsa_decrypt_key_v2(out, len, tmp, &len2, &rsa_params, &stat, &key)); ENSUREX(stat == 1 && stat2 == 0, "rsa_decrypt_key (without lparam)"); COMPARE_TESTVECTOR(tmp, len2, in, rsa_msgsize, "rsa_decrypt_key (without lparam)", cnt << 8 | rsa_msgsize); } /* encrypt the key (with lparam) */ + rsa_params.u.crypt.lparam = lparam; + rsa_params.u.crypt.lparamlen = sizeof(lparam); for (rsa_msgsize = 0; rsa_msgsize <= max_msgsize; rsa_msgsize++) { len = sizeof(out); len2 = rsa_msgsize; - DO(rsa_encrypt_key_ex(rsa_msgsize ? in : NULL, rsa_msgsize, out, &len, lparam, sizeof(lparam), &yarrow_prng, prng_idx, mgf_hash, label_hash, LTC_PKCS_1_OAEP, &key)); + DO(rsa_encrypt_key_v2(rsa_msgsize ? in : NULL, rsa_msgsize, out, &len, &rsa_params, &key)); /* change a byte */ out[8] ^= 1; - SHOULD_FAIL(rsa_decrypt_key_ex(out, len, tmp, &len2, lparam, sizeof(lparam), mgf_hash, label_hash, LTC_PKCS_1_OAEP, &stat2, &key)); + SHOULD_FAIL(rsa_decrypt_key_v2(out, len, tmp, &len2, &rsa_params, &stat2, &key)); ENSURE(len2 == rsa_msgsize); /* change a byte back */ out[8] ^= 1; len2 = rsa_msgsize; - DO(rsa_decrypt_key_ex(out, len, tmp, &len2, lparam, sizeof(lparam), mgf_hash, label_hash, LTC_PKCS_1_OAEP, &stat, &key)); + DO(rsa_decrypt_key_v2(out, len, tmp, &len2, &rsa_params, &stat, &key)); ENSURE(stat == 1 && stat2 == 0); COMPARE_TESTVECTOR(tmp, len2, in, rsa_msgsize, "rsa_decrypt_key (with lparam)", rsa_msgsize); } + rsa_params.u.crypt.lparam = NULL; + rsa_params.u.crypt.lparamlen = 0; } } - + rsa_params.params.hash_alg = "sha1"; + rsa_params.params.mgf1_hash_alg = "sha1"; /* encrypt the key PKCS #1 v1.5 (payload from 1 to 117 bytes) */ + rsa_params.padding = LTC_PKCS_1_V1_5; for (rsa_msgsize = 0; rsa_msgsize <= 117; rsa_msgsize++) { len = sizeof(out); len2 = rsa_msgsize; - DO(rsa_encrypt_key_ex(in, rsa_msgsize, out, &len, NULL, 0, &yarrow_prng, prng_idx, 0, -1, LTC_PKCS_1_V1_5, &key)); + DO(rsa_encrypt_key_v2(in, rsa_msgsize, out, &len, &rsa_params, &key)); len2 = rsa_msgsize; - DO(rsa_decrypt_key_ex(out, len, tmp, &len2, NULL, 0, 0, -1, LTC_PKCS_1_V1_5, &stat, &key)); + DO(rsa_decrypt_key_v2(out, len, tmp, &len2, &rsa_params, &stat, &key)); ENSURE(stat == 1); COMPARE_TESTVECTOR(tmp, len2, in, rsa_msgsize, "rsa_decrypt_key_ex", rsa_msgsize); } /* sign a message (unsalted, lower cholestorol and Atkins approved) now */ len = sizeof(out); - DO(rsa_sign_hash(in, 20, out, &len, &yarrow_prng, prng_idx, hash_idx, 0, &key)); + rsa_params.padding = LTC_PKCS_1_PSS; + DO(rsa_sign_hash_v2(in, 20, out, &len, &rsa_params, &key)); /* export key and import as both private and public */ len2 = sizeof(tmp); @@ -607,20 +624,20 @@ print_hex("q", tmp, len); dbg_malloc_stats(); /* verify with original */ - DO(rsa_verify_hash(out, len, in, 20, hash_idx, 0, &stat, &key)); + DO(rsa_verify_hash_v2(out, len, in, 20, &rsa_params, &stat, &key)); /* change a byte */ in[0] ^= 1; - DO(rsa_verify_hash(out, len, in, 20, hash_idx, 0, &stat2, &key)); + DO(rsa_verify_hash_v2(out, len, in, 20, &rsa_params, &stat2, &key)); ENSUREX(stat == 1 && stat2 == 0, "rsa_verify_hash (unsalted, origKey) failed"); /* verify with privKey */ /* change byte back to original */ in[0] ^= 1; - DO(rsa_verify_hash(out, len, in, 20, hash_idx, 0, &stat, &privKey)); + DO(rsa_verify_hash_v2(out, len, in, 20, &rsa_params, &stat, &privKey)); /* change a byte */ in[0] ^= 1; - DO(rsa_verify_hash(out, len, in, 20, hash_idx, 0, &stat2, &privKey)); + DO(rsa_verify_hash_v2(out, len, in, 20, &rsa_params, &stat2, &privKey)); if (!(stat == 1 && stat2 == 0)) { fprintf(stderr, "rsa_verify_hash (unsalted, privKey) failed, %d, %d", stat, stat2); @@ -636,10 +653,10 @@ print_hex("q", tmp, len); privKey.dP = NULL; /* change byte back to original */ in[0] ^= 1; - DO(rsa_verify_hash(out, len, in, 20, hash_idx, 0, &stat, &privKey)); + DO(rsa_verify_hash_v2(out, len, in, 20, &rsa_params, &stat, &privKey)); /* change a byte */ in[0] ^= 1; - DO(rsa_verify_hash(out, len, in, 20, hash_idx, 0, &stat2, &privKey)); + DO(rsa_verify_hash_v2(out, len, in, 20, &rsa_params, &stat2, &privKey)); if (!(stat == 1 && stat2 == 0)) { fprintf(stderr, "rsa_verify_hash (unsalted, privKey) failed, %d, %d", stat, stat2); @@ -653,10 +670,10 @@ print_hex("q", tmp, len); /* verify with pubKey */ /* change byte back to original */ in[0] ^= 1; - DO(rsa_verify_hash(out, len, in, 20, hash_idx, 0, &stat, &pubKey)); + DO(rsa_verify_hash_v2(out, len, in, 20, &rsa_params, &stat, &pubKey)); /* change a byte */ in[0] ^= 1; - DO(rsa_verify_hash(out, len, in, 20, hash_idx, 0, &stat2, &pubKey)); + DO(rsa_verify_hash_v2(out, len, in, 20, &rsa_params, &stat2, &pubKey)); if (!(stat == 1 && stat2 == 0)) { fprintf(stderr, "rsa_verify_hash (unsalted, pubkey) failed, %d, %d", stat, stat2); @@ -668,11 +685,12 @@ print_hex("q", tmp, len); /* sign a message (salted) now (use privKey to make, pubKey to verify) */ len = sizeof(out); - DO(rsa_sign_hash(in, 20, out, &len, &yarrow_prng, prng_idx, hash_idx, 8, &privKey)); - DO(rsa_verify_hash(out, len, in, 20, hash_idx, 8, &stat, &pubKey)); + rsa_params.params.saltlen = 8; + DO(rsa_sign_hash_v2(in, 20, out, &len, &rsa_params, &privKey)); + DO(rsa_verify_hash_v2(out, len, in, 20, &rsa_params, &stat, &pubKey)); /* change a byte */ in[0] ^= 1; - DO(rsa_verify_hash(out, len, in, 20, hash_idx, 8, &stat2, &pubKey)); + DO(rsa_verify_hash_v2(out, len, in, 20, &rsa_params, &stat2, &pubKey)); if (!(stat == 1 && stat2 == 0)) { fprintf(stderr, "rsa_verify_hash (salted) failed, %d, %d", stat, stat2); @@ -681,17 +699,19 @@ print_hex("q", tmp, len); rsa_free(&privKey); return 1; } + rsa_params.params.saltlen = 0; /* sign a message with PKCS #1 v1.5 */ len = sizeof(out); - DO(rsa_sign_hash_ex(in, 20, out, &len, LTC_PKCS_1_V1_5, &yarrow_prng, prng_idx, hash_idx, 0, 8, &privKey)); - DO(rsa_verify_hash_ex(out, len, in, 20, LTC_PKCS_1_V1_5, hash_idx, 0, 8, &stat, &pubKey)); + rsa_params.padding = LTC_PKCS_1_V1_5; + DO(rsa_sign_hash_v2(in, 20, out, &len, &rsa_params, &privKey)); + DO(rsa_verify_hash_v2(out, len, in, 20, &rsa_params, &stat, &pubKey)); /* change a byte */ in[0] ^= 1; - DO(rsa_verify_hash_ex(out, len, in, 20, LTC_PKCS_1_V1_5, hash_idx, 0, 8, &stat2, &pubKey)); + DO(rsa_verify_hash_v2(out, len, in, 20, &rsa_params, &stat2, &pubKey)); if (!(stat == 1 && stat2 == 0)) { - fprintf(stderr, "rsa_verify_hash_ex failed, %d, %d", stat, stat2); + fprintf(stderr, "rsa_verify_hash_v2 failed, %d, %d", stat, stat2); rsa_free(&key); rsa_free(&pubKey); rsa_free(&privKey); @@ -717,14 +737,14 @@ print_hex("q", tmp, len); p = in; p2 = out; p3 = tmp; - for (i = 0; i < 9; ++i) { + for (i = 0; i < 10; ++i) { len = sizeof(in); len2 = sizeof(out); /* (1) */ - DO(rsa_sign_hash_ex(p, 20, p2, &len2, LTC_PKCS_1_V1_5, &yarrow_prng, prng_idx, hash_idx, 0, 8, &privKey)); + DO(rsa_sign_hash_v2(p, 20, p2, &len2, &rsa_params, &privKey)); /* (2) */ - DOX(rsa_verify_hash_ex(p2, len2, p, 20, LTC_PKCS_1_V1_5, hash_idx, 0, -1, &stat, &pubKey), "should succeed"); - DOX(stat == 1?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, "should succeed"); + DOX(rsa_verify_hash_v2(p2, len2, p, 20, &rsa_params, &stat, &pubKey), "should succeed"); + ENSURE(stat == 1); len3 = sizeof(tmp); /* (3) */ DO(ltc_mp.rsa_me(p2, len2, p3, &len3, PK_PUBLIC, &key)); @@ -757,8 +777,11 @@ print_hex("q", tmp, len); len3 = sizeof(tmp); /* (6) */ - SHOULD_FAIL(rsa_verify_hash_ex(p2, len2, p, 20, LTC_PKCS_1_V1_5, hash_idx, -1, -1, &stat, &pubKey)); - DOX(stat == 0?CRYPT_OK:CRYPT_FAIL_TESTVECTOR, "should fail"); + if (i < 8) + SHOULD_FAIL(rsa_verify_hash_v2(p2, len2, p, 20, &rsa_params, &stat, &pubKey)); + else + DO(rsa_verify_hash_v2(p2, len2, p, 20, &rsa_params, &stat, &pubKey)); + ENSURE(stat == 0); } rsa_free(&key); From 7967b2af5a7e50ad8e61e713b8b1707db9f52c77 Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Thu, 23 Oct 2025 00:39:22 +0200 Subject: [PATCH 16/17] Suppress deprecated warnings for now Signed-off-by: Steffen Jaeckel --- .github/workflows/main.yml | 1 - demos/timing.c | 1 + makefile | 1 + src/pk/pkcs1/pkcs_1_oaep_decode.c | 1 + src/pk/pkcs1/pkcs_1_oaep_encode.c | 1 + src/pk/pkcs1/pkcs_1_pss_decode.c | 1 + src/pk/pkcs1/pkcs_1_pss_encode.c | 1 + src/pk/rsa/rsa_decrypt_key.c | 1 + src/pk/rsa/rsa_encrypt_key.c | 1 + src/pk/rsa/rsa_sign_hash.c | 1 + tests/tomcrypt_test.h | 1 + 11 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 14be6ec0a..bac91dea0 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -52,7 +52,6 @@ jobs: - { BUILDNAME: 'NO_FAST', BUILDOPTIONS: '-DLTC_NO_FAST', BUILDSCRIPT: '.ci/run.sh' } - { BUILDNAME: 'NO_FAST+SMALL+NO_TABLES', BUILDOPTIONS: '-DLTC_NO_FAST -DLTC_SMALL_CODE -DLTC_NO_TABLES', BUILDSCRIPT: '.ci/run.sh' } - { BUILDNAME: 'NO_ASM', BUILDOPTIONS: '-DLTC_NO_ASM', BUILDSCRIPT: '.ci/run.sh' } - - { BUILDNAME: 'NO_DEPRECATED_APIS', BUILDOPTIONS: '-DLTC_NO_DEPRECATED_APIS', BUILDSCRIPT: '.ci/run.sh' } - { BUILDNAME: 'NO_TIMING_RESISTANCE', BUILDOPTIONS: '-DLTC_NO_ECC_TIMING_RESISTANT -DLTC_NO_RSA_BLINDING', BUILDSCRIPT: '.ci/run.sh' } - { BUILDNAME: 'FORTUNA_CUSTOM_OPTIONS', BUILDOPTIONS: '-DLTC_FORTUNA_USE_ENCRYPT_ONLY -DLTC_FORTUNA_RESEED_RATELIMIT_STATIC', BUILDSCRIPT: '.ci/run.sh' } - { BUILDNAME: 'PTHREAD', BUILDOPTIONS: '-DLTC_PTHREAD', BUILDSCRIPT: '.ci/run.sh' } diff --git a/demos/timing.c b/demos/timing.c index 572756dda..d356d0a97 100644 --- a/demos/timing.c +++ b/demos/timing.c @@ -1,5 +1,6 @@ /* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ +#define LTC_DEPRECATED(x) #include "tomcrypt_private.h" #if defined(_WIN32) diff --git a/makefile b/makefile index 72437220c..5ba4de0d3 100644 --- a/makefile +++ b/makefile @@ -154,6 +154,7 @@ pre_gen/tomcrypt_amalgam.c: $(TAB_SOURCES) $(SOURCES) printf "#define LTC_SAFER_TAB_C\n" >> $@ printf "#define LTC_SOBER128TAB_C\n" >> $@ printf "#define LTC_WHIRLTAB_C\n\n" >> $@ + printf "#define LTC_DEPRECATED(x)\n\n" >> $@ printf "#include \"tomcrypt_private.h\"\n\n" >> $@ cat $^ >> $@ diff --git a/src/pk/pkcs1/pkcs_1_oaep_decode.c b/src/pk/pkcs1/pkcs_1_oaep_decode.c index 117c7d2ad..a877b6232 100644 --- a/src/pk/pkcs1/pkcs_1_oaep_decode.c +++ b/src/pk/pkcs1/pkcs_1_oaep_decode.c @@ -1,5 +1,6 @@ /* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ +#define LTC_DEPRECATED(x) #include "tomcrypt_private.h" /** diff --git a/src/pk/pkcs1/pkcs_1_oaep_encode.c b/src/pk/pkcs1/pkcs_1_oaep_encode.c index 4bcc9bfe2..f5ee5010b 100644 --- a/src/pk/pkcs1/pkcs_1_oaep_encode.c +++ b/src/pk/pkcs1/pkcs_1_oaep_encode.c @@ -1,5 +1,6 @@ /* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ +#define LTC_DEPRECATED(x) #include "tomcrypt_private.h" /** diff --git a/src/pk/pkcs1/pkcs_1_pss_decode.c b/src/pk/pkcs1/pkcs_1_pss_decode.c index 4e41ede0c..69c45dc8e 100644 --- a/src/pk/pkcs1/pkcs_1_pss_decode.c +++ b/src/pk/pkcs1/pkcs_1_pss_decode.c @@ -1,5 +1,6 @@ /* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ +#define LTC_DEPRECATED(x) #include "tomcrypt_private.h" /** diff --git a/src/pk/pkcs1/pkcs_1_pss_encode.c b/src/pk/pkcs1/pkcs_1_pss_encode.c index 9820c1e66..95c8fe410 100644 --- a/src/pk/pkcs1/pkcs_1_pss_encode.c +++ b/src/pk/pkcs1/pkcs_1_pss_encode.c @@ -1,5 +1,6 @@ /* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ +#define LTC_DEPRECATED(x) #include "tomcrypt_private.h" /** diff --git a/src/pk/rsa/rsa_decrypt_key.c b/src/pk/rsa/rsa_decrypt_key.c index 75de45deb..d61f25b65 100644 --- a/src/pk/rsa/rsa_decrypt_key.c +++ b/src/pk/rsa/rsa_decrypt_key.c @@ -1,5 +1,6 @@ /* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ +#define LTC_DEPRECATED(x) #include "tomcrypt_private.h" /** diff --git a/src/pk/rsa/rsa_encrypt_key.c b/src/pk/rsa/rsa_encrypt_key.c index c43d13869..ad0bd7ac0 100644 --- a/src/pk/rsa/rsa_encrypt_key.c +++ b/src/pk/rsa/rsa_encrypt_key.c @@ -1,5 +1,6 @@ /* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ +#define LTC_DEPRECATED(x) #include "tomcrypt_private.h" /** diff --git a/src/pk/rsa/rsa_sign_hash.c b/src/pk/rsa/rsa_sign_hash.c index ab3af86ae..325b72542 100644 --- a/src/pk/rsa/rsa_sign_hash.c +++ b/src/pk/rsa/rsa_sign_hash.c @@ -1,5 +1,6 @@ /* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ +#define LTC_DEPRECATED(x) #include "tomcrypt_private.h" /** diff --git a/tests/tomcrypt_test.h b/tests/tomcrypt_test.h index 4488a450c..6761b22f9 100644 --- a/tests/tomcrypt_test.h +++ b/tests/tomcrypt_test.h @@ -4,6 +4,7 @@ #ifndef TOMCRYPT_TEST_H_ #define TOMCRYPT_TEST_H_ +#define LTC_DEPRECATED(x) #include "tomcrypt_private.h" #include "common.h" From 2b65b91c8e6323175f9a41b4111162245fc29c34 Mon Sep 17 00:00:00 2001 From: Steffen Jaeckel Date: Sun, 2 Nov 2025 15:31:37 +0100 Subject: [PATCH 17/17] RSA WIP Signed-off-by: Steffen Jaeckel --- src/headers/tomcrypt_pk.h | 64 ++++++++++++++++++++++++++++++++++++--- src/pk/rsa/rsa_key.c | 9 +++--- tests/deprecated_test.c | 40 ++++++++++++++++++++++++ tests/rsa_test.c | 42 ++++++++++++++++++++++--- 4 files changed, 141 insertions(+), 14 deletions(-) diff --git a/src/headers/tomcrypt_pk.h b/src/headers/tomcrypt_pk.h index 12833ba5e..4b31cf458 100644 --- a/src/headers/tomcrypt_pk.h +++ b/src/headers/tomcrypt_pk.h @@ -154,6 +154,59 @@ int rsa_verify_hash_v2(const unsigned char *sig, unsigned long siglen, int *stat, const rsa_key *key); +/* These use PKCS #1 v2.0 padding */ +#define ltc_rsa_encrypt_key(in, inlen, out, outlen, lp, lplen, prng_, prng_idx, hash_idx, key) \ + rsa_encrypt_key_v2(in, inlen, out, outlen, \ + &(ltc_rsa_op_parameters){ \ + .u.crypt.lparam = lp, \ + .u.crypt.lparamlen = lplen,\ + .prng = prng_, \ + .wprng = prng_idx, \ + .params.mgf1_hash_alg = hash_is_valid(hash_idx) == CRYPT_OK ? hash_descriptor[hash_idx].name : NULL, \ + .params.hash_alg = hash_is_valid(hash_idx) == CRYPT_OK ? hash_descriptor[hash_idx].name : NULL, \ + .padding = LTC_PKCS_1_OAEP, \ + }, key) + +#define ltc_rsa_decrypt_key(in, inlen, out, outlen, lp, lplen, hash_idx, stat, key) \ + rsa_decrypt_key_v2(in, inlen, out, outlen, \ + &(ltc_rsa_op_parameters){ \ + .u.crypt.lparam = lp, \ + .u.crypt.lparamlen = lplen,\ + .params.mgf1_hash_alg = hash_is_valid(hash_idx) == CRYPT_OK ? hash_descriptor[hash_idx].name : NULL, \ + .params.hash_alg = hash_is_valid(hash_idx) == CRYPT_OK ? hash_descriptor[hash_idx].name : NULL, \ + .padding = LTC_PKCS_1_OAEP, \ + }, stat, key) + +#define ltc_rsa_sign_hash(hash, hashlen, sig, siglen, prng_, prng_idx, hash_idx, saltlen_, key) \ + rsa_sign_hash_v2(hash, hashlen, sig, siglen, \ + &(ltc_rsa_op_parameters){ \ + .prng = prng_, \ + .wprng = prng_idx, \ + .params.mgf1_hash_alg = hash_is_valid(hash_idx) == CRYPT_OK ? hash_descriptor[hash_idx].name : NULL, \ + .params.hash_alg = hash_is_valid(hash_idx) == CRYPT_OK ? hash_descriptor[hash_idx].name : NULL, \ + .params.saltlen = saltlen_, \ + .padding = LTC_PKCS_1_PSS, \ + }, key) + +#define ltc_rsa_verify_hash(sig, siglen, hash, hashlen, hash_idx, saltlen_, stat, key) \ + rsa_verify_hash_v2(sig, siglen, hash, hashlen, \ + &(ltc_rsa_op_parameters){ \ + .params.mgf1_hash_alg = hash_is_valid(hash_idx) == CRYPT_OK ? hash_descriptor[hash_idx].name : NULL, \ + .params.hash_alg = hash_is_valid(hash_idx) == CRYPT_OK ? hash_descriptor[hash_idx].name : NULL, \ + .params.saltlen = saltlen_, \ + .padding = LTC_PKCS_1_PSS, \ + }, stat, key) + +//#define LTC_NO_DEPRECATED_APIS +#ifdef LTC_NO_DEPRECATED_APIS + +#define rsa_encrypt_key ltc_rsa_encrypt_key +#define rsa_decrypt_key ltc_rsa_decrypt_key +#define rsa_sign_hash ltc_rsa_sign_hash +#define rsa_verify_hash ltc_rsa_verify_hash + +#else /* LTC_NO_DEPRECATED_APIS */ + /* These use PKCS #1 v2.0 padding */ #define rsa_encrypt_key(in, inlen, out, outlen, lparam, lparamlen, prng, prng_idx, hash_idx, key) \ rsa_encrypt_key_ex(in, inlen, out, outlen, lparam, lparamlen, prng, prng_idx, hash_idx, LTC_PKCS_1_OAEP, key) @@ -161,15 +214,12 @@ int rsa_verify_hash_v2(const unsigned char *sig, unsigned long siglen, #define rsa_decrypt_key(in, inlen, out, outlen, lparam, lparamlen, hash_idx, stat, key) \ rsa_decrypt_key_ex(in, inlen, out, outlen, lparam, lparamlen, hash_idx, LTC_PKCS_1_OAEP, stat, key) -#define rsa_sign_hash(in, inlen, out, outlen, prng, prng_idx, hash_idx, saltlen, key) \ - rsa_sign_hash_ex(in, inlen, out, outlen, LTC_PKCS_1_PSS, prng, prng_idx, hash_idx, saltlen, key) +#define rsa_sign_hash(hash, hashlen, sig, siglen, prng, prng_idx, hash_idx, saltlen, key) \ + rsa_sign_hash_ex(hash, hashlen, sig, siglen, LTC_PKCS_1_PSS, prng, prng_idx, hash_idx, saltlen, key) #define rsa_verify_hash(sig, siglen, hash, hashlen, hash_idx, saltlen, stat, key) \ rsa_verify_hash_ex(sig, siglen, hash, hashlen, LTC_PKCS_1_PSS, hash_idx, saltlen, stat, key) -#define rsa_sign_saltlen_get_max(hash_idx, key) \ - rsa_sign_saltlen_get_max_ex(LTC_PKCS_1_PSS, hash_idx, key) - /* These can be switched between PKCS #1 v2.x and PKCS #1 v1.5 paddings */ LTC_DEPRECATED(rsa_encrypt_key_v2) int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen, @@ -200,6 +250,10 @@ int rsa_verify_hash_ex(const unsigned char *sig, unsigned long sigle int padding, int hash_idx, unsigned long saltlen, int *stat, const rsa_key *key); +#endif /* LTC_NO_DEPRECATED_APIS */ + +#define rsa_sign_saltlen_get_max(hash_idx, key) \ + rsa_sign_saltlen_get_max_ex(LTC_PKCS_1_PSS, hash_idx, key) int rsa_sign_saltlen_get_max_ex(int padding, int hash_idx, const rsa_key *key); diff --git a/src/pk/rsa/rsa_key.c b/src/pk/rsa/rsa_key.c index 319000603..1366d1667 100644 --- a/src/pk/rsa/rsa_key.c +++ b/src/pk/rsa/rsa_key.c @@ -100,7 +100,7 @@ void rsa_free(rsa_key *key) XMEMSET(&key->params, 0, sizeof(key->params)); } -static LTC_INLINE int s_rsa_key_valid_pss_algs(ltc_rsa_op_checked *check) +static LTC_INLINE int s_rsa_key_valid_rsa_params(ltc_rsa_op_checked *check) { const ltc_rsa_parameters *key_params; int padding = check->params->padding; @@ -114,7 +114,8 @@ static LTC_INLINE int s_rsa_key_valid_pss_algs(ltc_rsa_op_checked *check) || padding == LTC_PKCS_1_V1_5_NA1)) { return CRYPT_OK; } - if (padding != LTC_PKCS_1_PSS) { + if (padding != LTC_PKCS_1_PSS + && padding != LTC_PKCS_1_OAEP) { return CRYPT_PK_TYPE_MISMATCH; } if (key_params->hash_alg == NULL || find_hash(key_params->hash_alg) != check->hash_alg) { @@ -165,7 +166,7 @@ static LTC_INLINE int s_rsa_key_valid_sign(ltc_rsa_op_checked *check) return CRYPT_INVALID_ARG; } } - return s_rsa_key_valid_pss_algs(check); + return s_rsa_key_valid_rsa_params(check); } static LTC_INLINE int s_rsa_key_valid_crypt(ltc_rsa_op_checked *check) @@ -182,7 +183,7 @@ static LTC_INLINE int s_rsa_key_valid_crypt(ltc_rsa_op_checked *check) return err; } } - return s_rsa_key_valid_pss_algs(check); + return s_rsa_key_valid_rsa_params(check); } static LTC_INLINE int s_rsa_check_prng(ltc_rsa_op_parameters *params) diff --git a/tests/deprecated_test.c b/tests/deprecated_test.c index f2ed3638b..a7f7f8a81 100644 --- a/tests/deprecated_test.c +++ b/tests/deprecated_test.c @@ -39,10 +39,50 @@ static void s_ecc_test(void) } #endif +#ifdef LTC_MRSA +extern const unsigned char ltc_rsa_private_test_key[]; +extern const unsigned long ltc_rsa_private_test_key_sz; +extern const unsigned char ltc_openssl_public_rsa[]; +extern const unsigned long ltc_openssl_public_rsa_sz; +static void s_rsa_test(void) +{ + rsa_key key, pubkey; + int stat; + const unsigned char tv[] = "test"; + unsigned char buf0[1024], buf1[1024]; + unsigned long buf0len, buf1len; + + /* We need an MPI provider for RSA */ + if (ltc_mp.name == NULL) return; + + DO(rsa_import(ltc_rsa_private_test_key, ltc_rsa_private_test_key_sz, &key)); + DO(rsa_import(ltc_openssl_public_rsa, ltc_openssl_public_rsa_sz, &pubkey)); + + buf0len = sizeof(buf0); + DO(rsa_sign_hash_ex(tv, 4, buf0, &buf0len, LTC_PKCS_1_PSS, &yarrow_prng, find_prng("yarrow"), find_hash("sha1"), 8, &key)); + buf1len = sizeof(buf1); + DO(rsa_verify_hash_ex(buf0, buf0len, tv, 4, LTC_PKCS_1_PSS, find_hash("sha1"), 8, &stat, &pubkey)); + ENSURE(stat == 1); + + buf0len = sizeof(buf0); + DO(rsa_encrypt_key_ex(tv, 4, buf0, &buf0len, NULL, 0, &yarrow_prng, find_prng("yarrow"), find_hash("sha1"), LTC_PKCS_1_OAEP, &pubkey)); + buf1len = sizeof(buf1); + DO(rsa_decrypt_key_ex(buf0, buf0len, buf1, &buf1len, NULL, 0, find_hash("sha1"), LTC_PKCS_1_OAEP, &stat, &key)); + ENSURE(stat == 1); + COMPARE_TESTVECTOR(buf1, buf1len, tv, 4, "s_rsa_test", 0); + + rsa_free(&pubkey); + rsa_free(&key); +} +#endif + int deprecated_test(void) { #ifdef LTC_MECC s_ecc_test(); +#endif +#ifdef LTC_MRSA + s_rsa_test(); #endif return 0; } diff --git a/tests/rsa_test.c b/tests/rsa_test.c index 7b81f7670..d27bd90f9 100644 --- a/tests/rsa_test.c +++ b/tests/rsa_test.c @@ -134,7 +134,7 @@ static const char *hex_key[] = { "DCCC27C8E4DC6248D59BAFF5AB60F621FD53E2B75D09C91AA104A9FC612C5D04583A5A39F14A215667FDCC20A38F78185A793D2E8E7E860AE6A833C104174A9F" }; /*** openssl public RSA key in DER format */ -static const unsigned char openssl_public_rsa[] = { +const unsigned char ltc_openssl_public_rsa[] = { 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xcf, 0x9a, 0xde, 0x64, 0x8a, 0xda, 0xc8, 0x33, 0x20, 0xa9, 0xd7, 0x83, 0x31, 0x19, 0x54, 0xb2, 0x9a, 0x85, 0xa7, @@ -146,6 +146,7 @@ static const unsigned char openssl_public_rsa[] = { 0xe2, 0x76, 0x0c, 0xc9, 0x63, 0x6c, 0x49, 0x58, 0x93, 0xed, 0xcc, 0xaa, 0xdc, 0x25, 0x3b, 0x0a, 0x60, 0x3f, 0x8b, 0x54, 0x3a, 0xc3, 0x4d, 0x31, 0xe7, 0x94, 0xa4, 0x44, 0xfd, 0x02, 0x03, 0x01, 0x00, 0x01, }; +const unsigned long ltc_openssl_public_rsa_sz = sizeof(ltc_openssl_public_rsa); /* same key but with extra headers stripped */ static const unsigned char openssl_public_rsa_stripped[] = { @@ -188,7 +189,7 @@ static int rsa_compat_test(void) /* try reading the key */ DO(rsa_import(ltc_rsa_private_test_key, sizeof(ltc_rsa_private_test_key), &key)); - DO(rsa_import(openssl_public_rsa, sizeof(openssl_public_rsa), &pubkey)); + DO(rsa_import(ltc_openssl_public_rsa, sizeof(ltc_openssl_public_rsa), &pubkey)); /* sign-verify a message with PKCS #1 v1.5 no ASN.1 */ len = sizeof(buf); @@ -224,7 +225,7 @@ static int rsa_compat_test(void) rsa_free(&key); /* try reading the public key */ - DO(rsa_import(openssl_public_rsa, sizeof(openssl_public_rsa), &key)); + DO(rsa_import(ltc_openssl_public_rsa, sizeof(ltc_openssl_public_rsa), &key)); len = sizeof(buf); DO(rsa_export(buf, &len, PK_PUBLIC, &key)); COMPARE_TESTVECTOR(buf, len, openssl_public_rsa_stripped, sizeof(openssl_public_rsa_stripped), "RSA public export (from OpenSSL)", 0); @@ -259,10 +260,10 @@ static int rsa_compat_test(void) rsa_free(&key); /* try export in SubjectPublicKeyInfo format of the public key */ - DO(rsa_import(openssl_public_rsa, sizeof(openssl_public_rsa), &key)); + DO(rsa_import(ltc_openssl_public_rsa, sizeof(ltc_openssl_public_rsa), &key)); len = sizeof(buf); DO(rsa_export(buf, &len, PK_PUBLIC | PK_STD, &key)); - COMPARE_TESTVECTOR(buf, len, openssl_public_rsa, sizeof(openssl_public_rsa), "RSA public export (X.509)", 0); + COMPARE_TESTVECTOR(buf, len, ltc_openssl_public_rsa, sizeof(ltc_openssl_public_rsa), "RSA public export (X.509)", 0); rsa_free(&key); return 0; @@ -452,6 +453,36 @@ static int s_rsa_import_pkcs8(const void *in, unsigned long inlen, void *key) #endif #endif +static int s_rsa_macros_test(void) +{ + rsa_key key, pubkey; + int stat; + const unsigned char tv[] = "test"; + unsigned char buf0[1024], buf1[1024]; + unsigned long buf0len, buf1len; + + DO(rsa_import(ltc_rsa_private_test_key, sizeof(ltc_rsa_private_test_key), &key)); + DO(rsa_import(ltc_openssl_public_rsa, sizeof(ltc_openssl_public_rsa), &pubkey)); + + buf0len = sizeof(buf0); + DO(ltc_rsa_sign_hash(tv, 4, buf0, &buf0len, &yarrow_prng, find_prng("yarrow"), find_hash("sha1"), 8, &key)); + buf1len = sizeof(buf1); + DO(ltc_rsa_verify_hash(buf0, buf0len, tv, 4, find_hash("sha1"), 8, &stat, &key)); + ENSURE(stat == 1); + + buf0len = sizeof(buf0); + DO(ltc_rsa_encrypt_key(tv, 4, buf0, &buf0len, NULL, 0, &yarrow_prng, find_prng("yarrow"), find_hash("sha1"), &pubkey)); + buf1len = sizeof(buf1); + DO(ltc_rsa_decrypt_key(buf0, buf0len, buf1, &buf1len, NULL, 0, find_hash("sha1"), &stat, &key)); + ENSURE(stat == 1); + COMPARE_TESTVECTOR(buf1, buf1len, tv, 4, "s_rsa_macros_test", 0); + + rsa_free(&pubkey); + rsa_free(&key); + + return CRYPT_OK; +} + int rsa_test(void) { unsigned char in[1024], out[1024], tmp[3072]; @@ -489,6 +520,7 @@ int rsa_test(void) DO(test_process_dir("tests/rsa-pkcs8", &key, s_rsa_import_pkcs8, NULL, (dir_cleanup_cb)rsa_free, "rsa_pkcs8_test")); #endif + DO(s_rsa_macros_test()); DO(s_rsa_cryptx_issue_69()); DO(s_rsa_issue_301(prng_idx)); DO(s_rsa_public_ubin_e(prng_idx));