* cipher/dilithium.h (dilithium_keypair, dilithium_sign)
(dilithium_verify): Return gpg_err_code_t.
* cipher/dilithium.c (dilithium_keypair): Return gpg_err_code_t.
(dilithium_sign, dilithium_verify): Ditto. Check CTXLEN.
* cipher/pubkey-dilithium.c (mldsa_generate): Follow the change.
(mldsa_sign, mldsa_verify): Likewise.
--
Reported by Calif.io in collaboration with Claude and Anthropic
Research.
GnuPG-bug-id: 8208
Co-authored-by: Thai Duong <[email protected]>
Signed-off-by: NIIBE Yutaka <[email protected]>
---
cipher/dilithium.c | 101 ++++++++++++++++++++++++++++----------
cipher/dilithium.h | 20 ++++----
cipher/pubkey-dilithium.c | 32 +++++-------
3 files changed, 99 insertions(+), 54 deletions(-)
diff --git a/cipher/dilithium.c b/cipher/dilithium.c
index 955feb2a..212c4afe 100644
--- a/cipher/dilithium.c
+++ b/cipher/dilithium.c
@@ -82,6 +82,7 @@
#include "gcrypt-int.h"
#include "const-time.h"
+/* With glue code, we only use the "_internal" API of Dilithium. */
#define DILITHIUM_INTERNAL_API_ONLY 1
#include "dilithium.h"
@@ -120,23 +121,33 @@ static int crypto_sign_verify_internal_5 (const uint8_t *sig, size_t siglen,
const uint8_t *pre, size_t prelen,
const uint8_t *pk);
-int
+gpg_err_code_t
dilithium_keypair (int algo, uint8_t *pk, uint8_t *sk,
const uint8_t seed[SEEDBYTES])
{
+ int r;
+
switch (algo)
{
case GCRY_MLDSA44:
- return crypto_sign_keypair_internal_2 (pk, sk, seed);
+ r = crypto_sign_keypair_internal_2 (pk, sk, seed);
+ break;
case GCRY_MLDSA65:
default:
- return crypto_sign_keypair_internal_3 (pk, sk, seed);
+ r = crypto_sign_keypair_internal_3 (pk, sk, seed);
+ break;
case GCRY_MLDSA87:
- return crypto_sign_keypair_internal_5 (pk, sk, seed);
+ r = crypto_sign_keypair_internal_5 (pk, sk, seed);
+ break;
}
+
+ if (r < 0)
+ return GPG_ERR_INTERNAL;
+
+ return 0;
}
-int
+gpg_err_code_t
dilithium_sign (int algo, uint8_t *sig, size_t siglen,
const uint8_t *m, size_t mlen,
const uint8_t *ctx, size_t ctxlen,
@@ -145,9 +156,17 @@ dilithium_sign (int algo, uint8_t *sig, size_t siglen,
size_t i;
uint8_t pre[257];
size_t prelen;
+ int r;
- if (ctx == NULL && ctxlen == -1)
- prelen = 0;
+ if (ctx == NULL)
+ {
+ if (ctxlen == -1)
+ prelen = 0;
+ else
+ return GPG_ERR_INV_DATA;
+ }
+ else if (ctxlen > 255)
+ return GPG_ERR_INV_DATA;
else
{
/* Prepare pre = (0, ctxlen, ctx) */
@@ -158,28 +177,44 @@ dilithium_sign (int algo, uint8_t *sig, size_t siglen,
prelen = 2 + ctxlen;
}
+ /*
+ * Note that the second argument of the upstream routine is the
+ * pointer to output length of signature. It assumes the first
+ * argument (pointer to output signature) should have correct (or
+ * more) length, beforehand.
+ *
+ * Before calling the routine, we should check the length.
+ */
switch (algo)
{
case GCRY_MLDSA44:
if (siglen != CRYPTO_BYTES_2)
- return -1;
- return crypto_sign_signature_internal_2 (sig, &siglen, m, mlen,
- pre, prelen, rnd, sk);
+ return GPG_ERR_INV_DATA;
+ r = crypto_sign_signature_internal_2 (sig, &siglen, m, mlen,
+ pre, prelen, rnd, sk);
+ break;
case GCRY_MLDSA65:
default:
if (siglen != CRYPTO_BYTES_3)
- return -1;
- return crypto_sign_signature_internal_3 (sig, &siglen, m, mlen,
- pre, prelen, rnd, sk);
+ return GPG_ERR_INV_DATA;
+ r = crypto_sign_signature_internal_3 (sig, &siglen, m, mlen,
+ pre, prelen, rnd, sk);
+ break;
case GCRY_MLDSA87:
if (siglen != CRYPTO_BYTES_5)
- return -1;
- return crypto_sign_signature_internal_5 (sig, &siglen, m, mlen,
- pre, prelen, rnd, sk);
+ return GPG_ERR_INV_DATA;
+ r = crypto_sign_signature_internal_5 (sig, &siglen, m, mlen,
+ pre, prelen, rnd, sk);
+ break;
}
+
+ if (r < 0)
+ return GPG_ERR_INTERNAL;
+
+ return 0;
}
-int
+gpg_err_code_t
dilithium_verify (int algo, const uint8_t *sig, size_t siglen,
const uint8_t *m, size_t mlen,
const uint8_t *ctx, size_t ctxlen,
@@ -188,9 +223,17 @@ dilithium_verify (int algo, const uint8_t *sig, size_t siglen,
size_t i;
uint8_t pre[257];
size_t prelen;
+ int r;
- if (ctx == NULL && ctxlen == -1)
- prelen = 0;
+ if (ctx == NULL)
+ {
+ if (ctxlen == -1)
+ prelen = 0;
+ else
+ return GPG_ERR_INV_DATA;
+ }
+ else if (ctxlen > 255)
+ return GPG_ERR_INV_DATA;
else
{
/* Prepare pre = (0, ctxlen, ctx) */
@@ -204,16 +247,24 @@ dilithium_verify (int algo, const uint8_t *sig, size_t siglen,
switch (algo)
{
case GCRY_MLDSA44:
- return crypto_sign_verify_internal_2 (sig, siglen, m, mlen,
- pre, prelen, pk);
+ r = crypto_sign_verify_internal_2 (sig, siglen, m, mlen,
+ pre, prelen, pk);
+ break;
case GCRY_MLDSA65:
default:
- return crypto_sign_verify_internal_3 (sig, siglen, m, mlen,
- pre, prelen, pk);
+ r = crypto_sign_verify_internal_3 (sig, siglen, m, mlen,
+ pre, prelen, pk);
+ break;
case GCRY_MLDSA87:
- return crypto_sign_verify_internal_5 (sig, siglen, m, mlen,
- pre, prelen, pk);
+ r = crypto_sign_verify_internal_5 (sig, siglen, m, mlen,
+ pre, prelen, pk);
+ break;
}
+
+ if (r < 0)
+ return GPG_ERR_BAD_SIGNATURE;
+
+ return 0;
}
typedef struct {
diff --git a/cipher/dilithium.h b/cipher/dilithium.h
index dd3597a5..1e868e1e 100644
--- a/cipher/dilithium.h
+++ b/cipher/dilithium.h
@@ -64,16 +64,16 @@
#define DILITHIUM_SIGN_STACK_BURN (161 * 1024)
#define DILITHIUM_VERIFY_STACK_BURN (122 * 1024)
-int dilithium_keypair (int algo, uint8_t *pk, uint8_t *sk,
- const uint8_t seed[SEEDBYTES]);
-int dilithium_sign (int algo, uint8_t *sig, size_t siglen,
- const uint8_t *m, size_t mlen,
- const uint8_t *ctx, size_t ctxlen,
- const uint8_t *sk, const uint8_t rnd[RNDBYTES]);
-int dilithium_verify (int algo, const uint8_t *sig, size_t siglen,
- const uint8_t *m, size_t mlen,
- const uint8_t *ctx, size_t ctxlen,
- const uint8_t *pk);
+gpg_err_code_t dilithium_keypair (int algo, uint8_t *pk, uint8_t *sk,
+ const uint8_t seed[SEEDBYTES]);
+gpg_err_code_t dilithium_sign (int algo, uint8_t *sig, size_t siglen,
+ const uint8_t *m, size_t mlen,
+ const uint8_t *ctx, size_t ctxlen,
+ const uint8_t *sk, const uint8_t rnd[RNDBYTES]);
+gpg_err_code_t dilithium_verify (int algo, const uint8_t *sig, size_t siglen,
+ const uint8_t *m, size_t mlen,
+ const uint8_t *ctx, size_t ctxlen,
+ const uint8_t *pk);
#endif
#if defined(DILITHIUM_MODE)
diff --git a/cipher/pubkey-dilithium.c b/cipher/pubkey-dilithium.c
index 03958bb0..4e1b2fc2 100644
--- a/cipher/pubkey-dilithium.c
+++ b/cipher/pubkey-dilithium.c
@@ -170,7 +170,7 @@ mldsa_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
memcpy (seed, seed_supplied, SEEDBYTES);
}
- dilithium_keypair (info->algo, pk, sk, seed);
+ rc = dilithium_keypair (info->algo, pk, sk, seed);
_gcry_burn_stack (DILITHIUM_KEYPAIR_STACK_BURN);
if (!rc)
@@ -258,17 +258,14 @@ mldsa_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
else
randombytes (rnd, RNDBYTES);
if (ctx.flags & PUBKEY_FLAG_NO_PREFIX)
- r = dilithium_sign (info->algo, sig, info->sig_len, data, data_len,
- NULL, -1, sk, rnd);
+ rc = dilithium_sign (info->algo, sig, info->sig_len, data, data_len,
+ NULL, -1, sk, rnd);
else
- r = dilithium_sign (info->algo, sig, info->sig_len, data, data_len,
- ctx.label, ctx.labellen, sk, rnd);
+ rc = dilithium_sign (info->algo, sig, info->sig_len, data, data_len,
+ ctx.label, ctx.labellen, sk, rnd);
_gcry_burn_stack (DILITHIUM_SIGN_STACK_BURN);
- if (r < 0)
- {
- rc = GPG_ERR_INTERNAL;
- goto leave;
- }
+ if (rc)
+ goto leave;
rc = sexp_build (r_sig, NULL, "(sig-val(%s(s%b)))", info->name,
info->sig_len, sig);
@@ -350,17 +347,14 @@ mldsa_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms)
}
if (ctx.flags & PUBKEY_FLAG_NO_PREFIX)
- r = dilithium_verify (info->algo, sig, info->sig_len, data, data_len,
- NULL, -1, pk);
+ rc = dilithium_verify (info->algo, sig, info->sig_len, data, data_len,
+ NULL, -1, pk);
else
- r = dilithium_verify (info->algo, sig, info->sig_len, data, data_len,
- ctx.label, ctx.labellen, pk);
+ rc = dilithium_verify (info->algo, sig, info->sig_len, data, data_len,
+ ctx.label, ctx.labellen, pk);
_gcry_burn_stack (DILITHIUM_VERIFY_STACK_BURN);
- if (r < 0)
- {
- rc = GPG_ERR_BAD_SIGNATURE;
- goto leave;
- }
+ if (rc)
+ goto leave;
leave:
_gcry_pk_util_free_encoding_ctx (&ctx);
_______________________________________________
Gcrypt-devel mailing list
[email protected]
https://lists.gnupg.org/mailman/listinfo/gcrypt-devel