From 8183c5dcc3624267493c3cc2f88488de587e9359 Mon Sep 17 00:00:00 2001 From: Gabor Mezei Date: Thu, 20 Apr 2023 15:50:59 +0200 Subject: [PATCH 1/8] Use core API in `ecp_mod_koblitz()` Signed-off-by: Gabor Mezei --- library/ecp_curves.c | 92 +++++++++++++++++++++++++------------------- 1 file changed, 52 insertions(+), 40 deletions(-) diff --git a/library/ecp_curves.c b/library/ecp_curves.c index 16401079c6..029b515d82 100644 --- a/library/ecp_curves.c +++ b/library/ecp_curves.c @@ -25,6 +25,8 @@ #include "mbedtls/platform_util.h" #include "mbedtls/error.h" +#include "mbedtls/platform.h" + #include "bn_mul.h" #include "bignum_core.h" #include "ecp_invasive.h" @@ -5526,60 +5528,69 @@ cleanup: */ #define P_KOBLITZ_MAX (256 / 8 / sizeof(mbedtls_mpi_uint)) // Max limbs in P #define P_KOBLITZ_R (8 / sizeof(mbedtls_mpi_uint)) // Limbs in R -static inline int ecp_mod_koblitz(mbedtls_mpi *N, mbedtls_mpi_uint *Rp, size_t p_limbs, - size_t adjust, size_t shift, mbedtls_mpi_uint mask) -{ - int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - mbedtls_mpi M, R; - mbedtls_mpi_uint Mp[P_KOBLITZ_MAX + P_KOBLITZ_R + 1]; - if (N->n < p_limbs) { - return 0; +static inline int ecp_mod_koblitz(mbedtls_mpi_uint *X, + size_t X_limbs, + mbedtls_mpi_uint *R, + size_t P_limbs, + size_t adjust, + size_t shift, + mbedtls_mpi_uint mask) +{ + int ret = 0; + + size_t R_limbs = P_KOBLITZ_R; + size_t M_limbs = X_limbs + R_limbs + adjust; + mbedtls_mpi_uint *M = mbedtls_calloc(M_limbs, ciL); + if (M == NULL) { + return MBEDTLS_ERR_ECP_ALLOC_FAILED; } - /* Init R */ - R.s = 1; - R.p = Rp; - R.n = P_KOBLITZ_R; - - /* Common setup for M */ - M.s = 1; - M.p = Mp; + size_t A1_limbs = X_limbs - (P_limbs - adjust); + if (A1_limbs > P_limbs + adjust) { + A1_limbs = P_limbs + adjust; + } + mbedtls_mpi_uint *A1 = mbedtls_calloc(A1_limbs, ciL); + if (A1 == NULL) { + ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; + goto cleanup; + } for (size_t pass = 0; pass < 2; pass++) { - /* M = A1 */ - M.n = N->n - (p_limbs - adjust); - if (M.n > p_limbs + adjust) { - M.n = p_limbs + adjust; - } - memset(Mp, 0, sizeof(Mp)); - memcpy(Mp, N->p + p_limbs - adjust, M.n * sizeof(mbedtls_mpi_uint)); + /* Copy A1 */ + memcpy(A1, X + P_limbs - adjust, A1_limbs * ciL); if (shift != 0) { - MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&M, shift)); + mbedtls_mpi_core_shift_r(A1, A1_limbs, shift); } - M.n += R.n; /* Make room for multiplication by R */ - /* N = A0 */ + /* X = A0 */ if (mask != 0) { - N->p[p_limbs - 1] &= mask; - } - for (size_t i = p_limbs; i < N->n; i++) { - N->p[i] = 0; + X[P_limbs - 1] &= mask; } - /* N = A0 + R * A1 */ - MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&M, &M, &R)); - MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(N, N, &M)); + /* Zeroize the A1 part of X to keep only the A0 part */ + for (size_t i = P_limbs; i < X_limbs; i++) { + X[i] = 0; + } + + /* X = A0 + R * A1 */ + mbedtls_mpi_core_mul(M, A1, A1_limbs, R, R_limbs); + mbedtls_mpi_core_add(X, X, M, A1_limbs + R_limbs); } cleanup: + mbedtls_free(M); + mbedtls_free(A1); + return ret; } + #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED) || MBEDTLS_ECP_DP_SECP224K1_ENABLED) || MBEDTLS_ECP_DP_SECP256K1_ENABLED) */ #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + /* * Fast quasi-reduction modulo p192k1 = 2^192 - R, * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x0100001119 @@ -5597,9 +5608,10 @@ int mbedtls_ecp_mod_p192k1(mbedtls_mpi *N) 0x00) }; - return ecp_mod_koblitz(N, Rp, 192 / 8 / sizeof(mbedtls_mpi_uint), 0, 0, - 0); + return ecp_mod_koblitz(N->p, N->n, Rp, + 192 / 8 / sizeof(mbedtls_mpi_uint), 0, 0, 0); } + #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) @@ -5622,10 +5634,10 @@ int mbedtls_ecp_mod_p224k1(mbedtls_mpi *N) }; #if defined(MBEDTLS_HAVE_INT64) - return ecp_mod_koblitz(N, Rp, 4, 1, 32, 0xFFFFFFFF); + return ecp_mod_koblitz(N->p, N->n, Rp, 4, 1, 32, 0xFFFFFFFF); #else - return ecp_mod_koblitz(N, Rp, 224 / 8 / sizeof(mbedtls_mpi_uint), 0, 0, - 0); + return ecp_mod_koblitz(N->p, N->n, Rp, + 224 / 8 / sizeof(mbedtls_mpi_uint), 0, 0, 0); #endif } @@ -5649,8 +5661,8 @@ int mbedtls_ecp_mod_p256k1(mbedtls_mpi *N) MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00) }; - return ecp_mod_koblitz(N, Rp, 256 / 8 / sizeof(mbedtls_mpi_uint), 0, 0, - 0); + return ecp_mod_koblitz(N->p, N->n, Rp, + 256 / 8 / sizeof(mbedtls_mpi_uint), 0, 0, 0); } #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ From 7097447b84c6c31c8ffb7862c72143d089d6db81 Mon Sep 17 00:00:00 2001 From: Gabor Mezei Date: Fri, 21 Apr 2023 17:28:25 +0200 Subject: [PATCH 2/8] Ensure input parameter size for Koblitz reduction Signed-off-by: Gabor Mezei --- library/ecp_curves.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/library/ecp_curves.c b/library/ecp_curves.c index 029b515d82..55428d6d4e 100644 --- a/library/ecp_curves.c +++ b/library/ecp_curves.c @@ -5597,7 +5597,13 @@ cleanup: */ static int ecp_mod_p192k1(mbedtls_mpi *N) { - return mbedtls_ecp_mod_p192k1(N); + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t expected_width = 2 * ((192 + biL - 1) / biL); + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); + ret = mbedtls_ecp_mod_p192k1(N); + +cleanup: + return ret; } MBEDTLS_STATIC_TESTABLE @@ -5618,7 +5624,13 @@ int mbedtls_ecp_mod_p192k1(mbedtls_mpi *N) static int ecp_mod_p224k1(mbedtls_mpi *N) { - return mbedtls_ecp_mod_p224k1(N); + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t expected_width = 2 * 224 / biL; + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); + ret = mbedtls_ecp_mod_p224k1(N); + +cleanup: + return ret; } /* @@ -5647,7 +5659,13 @@ int mbedtls_ecp_mod_p224k1(mbedtls_mpi *N) static int ecp_mod_p256k1(mbedtls_mpi *N) { - return mbedtls_ecp_mod_p256k1(N); + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t expected_width = 2 * ((256 + biL - 1) / biL); + MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width)); + ret = mbedtls_ecp_mod_p256k1(N); + +cleanup: + return ret; } /* From d2c0ba172c2682e984c95d748939788a82ad5f82 Mon Sep 17 00:00:00 2001 From: Gabor Mezei Date: Mon, 24 Apr 2023 16:33:17 +0200 Subject: [PATCH 3/8] Fix value in comment Signed-off-by: Gabor Mezei --- library/ecp_curves.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/ecp_curves.c b/library/ecp_curves.c index 55428d6d4e..96aae31047 100644 --- a/library/ecp_curves.c +++ b/library/ecp_curves.c @@ -5593,7 +5593,7 @@ cleanup: /* * Fast quasi-reduction modulo p192k1 = 2^192 - R, - * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x0100001119 + * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x01000011C9 */ static int ecp_mod_p192k1(mbedtls_mpi *N) { From 03367fe42d8577c1a0bf238d3aacdb7faea0623c Mon Sep 17 00:00:00 2001 From: Gabor Mezei Date: Mon, 24 Apr 2023 16:34:29 +0200 Subject: [PATCH 4/8] Ignore carry since it can not be generated Signed-off-by: Gabor Mezei --- library/ecp_curves.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/library/ecp_curves.c b/library/ecp_curves.c index 96aae31047..aa2815ae7e 100644 --- a/library/ecp_curves.c +++ b/library/ecp_curves.c @@ -5575,7 +5575,14 @@ static inline int ecp_mod_koblitz(mbedtls_mpi_uint *X, /* X = A0 + R * A1 */ mbedtls_mpi_core_mul(M, A1, A1_limbs, R, R_limbs); - mbedtls_mpi_core_add(X, X, M, A1_limbs + R_limbs); + (void) mbedtls_mpi_core_add(X, X, M, A1_limbs + R_limbs); + + /* Carry can not be generated since R is a 33-bit value and stored in + * 64 bits. The result value of the multiplication is at most + * P length + 33 bits in length and the result value of the addition + * is at most P length + 34 bits in length. So the result of the + * addition always fits in P length + 64 bits. + */ } cleanup: From fead53311bf366fb795b789842a1a50c23485d06 Mon Sep 17 00:00:00 2001 From: Gabor Mezei Date: Wed, 26 Apr 2023 15:20:01 +0200 Subject: [PATCH 5/8] Remove unused macro Signed-off-by: Gabor Mezei --- library/ecp_curves.c | 1 - 1 file changed, 1 deletion(-) diff --git a/library/ecp_curves.c b/library/ecp_curves.c index aa2815ae7e..a660f5724b 100644 --- a/library/ecp_curves.c +++ b/library/ecp_curves.c @@ -5526,7 +5526,6 @@ cleanup: * Write N as A0 + 2^224 A1, return A0 + R * A1. * Actually do two passes, since R is big. */ -#define P_KOBLITZ_MAX (256 / 8 / sizeof(mbedtls_mpi_uint)) // Max limbs in P #define P_KOBLITZ_R (8 / sizeof(mbedtls_mpi_uint)) // Limbs in R static inline int ecp_mod_koblitz(mbedtls_mpi_uint *X, From 19c6f47dbca05c2b8179b3fdd73770e85cec7995 Mon Sep 17 00:00:00 2001 From: Gabor Mezei Date: Wed, 26 Apr 2023 15:22:11 +0200 Subject: [PATCH 6/8] Allocate the right amount of memory Signed-off-by: Gabor Mezei --- library/ecp_curves.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/library/ecp_curves.c b/library/ecp_curves.c index a660f5724b..e7ccd41b34 100644 --- a/library/ecp_curves.c +++ b/library/ecp_curves.c @@ -5538,19 +5538,19 @@ static inline int ecp_mod_koblitz(mbedtls_mpi_uint *X, { int ret = 0; - size_t R_limbs = P_KOBLITZ_R; - size_t M_limbs = X_limbs + R_limbs + adjust; - mbedtls_mpi_uint *M = mbedtls_calloc(M_limbs, ciL); - if (M == NULL) { - return MBEDTLS_ERR_ECP_ALLOC_FAILED; - } - size_t A1_limbs = X_limbs - (P_limbs - adjust); if (A1_limbs > P_limbs + adjust) { A1_limbs = P_limbs + adjust; } mbedtls_mpi_uint *A1 = mbedtls_calloc(A1_limbs, ciL); if (A1 == NULL) { + return MBEDTLS_ERR_ECP_ALLOC_FAILED; + } + + size_t R_limbs = P_KOBLITZ_R; + size_t M_limbs = A1_limbs + R_limbs; + mbedtls_mpi_uint *M = mbedtls_calloc(M_limbs, ciL); + if (M == NULL) { ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; goto cleanup; } From 908f40014cd07e0ab69021df07b07cecfe375511 Mon Sep 17 00:00:00 2001 From: Gabor Mezei Date: Fri, 5 May 2023 15:09:24 +0200 Subject: [PATCH 7/8] Determine special cases in-place in the common Koblitz function Remove parameter used by the special cases and check for special cases in-place. Signed-off-by: Gabor Mezei --- library/ecp_curves.c | 57 ++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 26 deletions(-) diff --git a/library/ecp_curves.c b/library/ecp_curves.c index e7ccd41b34..3f2b798f22 100644 --- a/library/ecp_curves.c +++ b/library/ecp_curves.c @@ -5519,6 +5519,7 @@ cleanup: #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + /* * Fast quasi-reduction modulo P = 2^s - R, * with R about 33 bits, used by the Koblitz curves. @@ -5531,50 +5532,61 @@ cleanup: static inline int ecp_mod_koblitz(mbedtls_mpi_uint *X, size_t X_limbs, mbedtls_mpi_uint *R, - size_t P_limbs, - size_t adjust, - size_t shift, - mbedtls_mpi_uint mask) + size_t bits) { int ret = 0; - size_t A1_limbs = X_limbs - (P_limbs - adjust); - if (A1_limbs > P_limbs + adjust) { - A1_limbs = P_limbs + adjust; - } - mbedtls_mpi_uint *A1 = mbedtls_calloc(A1_limbs, ciL); + /* Determine if A1 is aligned to limb bitsize. If not then the used limbs + * of P, A0 and A1 must be set accordingly and there is a middle limb + * which is shared by A0 and A1 and need to handle accordingly. + */ + size_t shift = bits % biL; + size_t adjust = (shift + biL - 1) / biL; + size_t P_limbs = bits / biL + adjust; + + mbedtls_mpi_uint *A1 = mbedtls_calloc(P_limbs, ciL); if (A1 == NULL) { return MBEDTLS_ERR_ECP_ALLOC_FAILED; } + /* Create a buffer to store the value of `R * A1` */ size_t R_limbs = P_KOBLITZ_R; - size_t M_limbs = A1_limbs + R_limbs; + size_t M_limbs = P_limbs + R_limbs; mbedtls_mpi_uint *M = mbedtls_calloc(M_limbs, ciL); if (M == NULL) { ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; goto cleanup; } + mbedtls_mpi_uint mask = 0; + if (adjust != 0) { + mask = ((mbedtls_mpi_uint) 1 << shift) - 1; + } + for (size_t pass = 0; pass < 2; pass++) { /* Copy A1 */ - memcpy(A1, X + P_limbs - adjust, A1_limbs * ciL); + memcpy(A1, X + P_limbs - adjust, P_limbs * ciL); + + /* Shift A1 to be aligned */ if (shift != 0) { - mbedtls_mpi_core_shift_r(A1, A1_limbs, shift); + mbedtls_mpi_core_shift_r(A1, P_limbs, shift); } - /* X = A0 */ + /* Zeroize the A1 part of the shared limb */ if (mask != 0) { X[P_limbs - 1] &= mask; } - /* Zeroize the A1 part of X to keep only the A0 part */ + /* X = A0 + * Zeroize the A1 part of X to keep only the A0 part. + */ for (size_t i = P_limbs; i < X_limbs; i++) { X[i] = 0; } /* X = A0 + R * A1 */ - mbedtls_mpi_core_mul(M, A1, A1_limbs, R, R_limbs); - (void) mbedtls_mpi_core_add(X, X, M, A1_limbs + R_limbs); + mbedtls_mpi_core_mul(M, A1, P_limbs, R, R_limbs); + (void) mbedtls_mpi_core_add(X, X, M, P_limbs + R_limbs); /* Carry can not be generated since R is a 33-bit value and stored in * 64 bits. The result value of the multiplication is at most @@ -5620,8 +5632,7 @@ int mbedtls_ecp_mod_p192k1(mbedtls_mpi *N) 0x00) }; - return ecp_mod_koblitz(N->p, N->n, Rp, - 192 / 8 / sizeof(mbedtls_mpi_uint), 0, 0, 0); + return ecp_mod_koblitz(N->p, N->n, Rp, 192); } #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ @@ -5651,12 +5662,7 @@ int mbedtls_ecp_mod_p224k1(mbedtls_mpi *N) 0x00) }; -#if defined(MBEDTLS_HAVE_INT64) - return ecp_mod_koblitz(N->p, N->n, Rp, 4, 1, 32, 0xFFFFFFFF); -#else - return ecp_mod_koblitz(N->p, N->n, Rp, - 224 / 8 / sizeof(mbedtls_mpi_uint), 0, 0, 0); -#endif + return ecp_mod_koblitz(N->p, N->n, Rp, 224); } #endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ @@ -5685,8 +5691,7 @@ int mbedtls_ecp_mod_p256k1(mbedtls_mpi *N) MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00) }; - return ecp_mod_koblitz(N->p, N->n, Rp, - 256 / 8 / sizeof(mbedtls_mpi_uint), 0, 0, 0); + return ecp_mod_koblitz(N->p, N->n, Rp, 256); } #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ From 9bf1aaf385c3bb817fd94a1998911fba14b625dc Mon Sep 17 00:00:00 2001 From: Gabor Mezei Date: Fri, 5 May 2023 16:32:28 +0200 Subject: [PATCH 8/8] Fix input parameter alignment in P256K1 test cases Signed-off-by: Gabor Mezei --- scripts/mbedtls_dev/ecp.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/mbedtls_dev/ecp.py b/scripts/mbedtls_dev/ecp.py index b7b66e4181..5d0de26541 100644 --- a/scripts/mbedtls_dev/ecp.py +++ b/scripts/mbedtls_dev/ecp.py @@ -672,8 +672,7 @@ class EcpP256K1Raw(bignum_common.ModOperationCommon, @property def arg_a(self) -> str: - hex_digits = bignum_common.hex_digits_for_limb(448 // self.bits_in_limb, self.bits_in_limb) - return super().format_arg('{:x}'.format(self.int_a)).zfill(hex_digits) + return super().format_arg('{:x}'.format(self.int_a)).zfill(2 * self.hex_digits) def result(self) -> List[str]: result = self.int_a % self.int_n