Merge pull request #7296 from valeriosetti/issue7253-part1
driver-only ECDH: enable ECDH-based TLS 1.2 key exchanges -- part 1
diff --git a/ChangeLog.d/driver-only-ecjpake.txt b/ChangeLog.d/driver-only-ecjpake.txt
new file mode 100644
index 0000000..706f304
--- /dev/null
+++ b/ChangeLog.d/driver-only-ecjpake.txt
@@ -0,0 +1,5 @@
+Features
+ * When a PSA driver for EC J-PAKE is present, it is now possible to disable
+ MBEDTLS_ECJPAKE_C in the build in order to save code size. For the
+ corresponding TLS 1.2 key exchange to work, MBEDTLS_USE_PSA_CRYPTO needs
+ to be enabled.
diff --git a/ChangeLog.d/rsa-padding-accessor.txt b/ChangeLog.d/rsa-padding-accessor.txt
new file mode 100644
index 0000000..ad14686
--- /dev/null
+++ b/ChangeLog.d/rsa-padding-accessor.txt
@@ -0,0 +1,4 @@
+Features
+ * Add functions mbedtls_rsa_get_padding_mode() and mbedtls_rsa_get_md_alg()
+ to read non-public fields for padding mode and hash id from
+ an mbedtls_rsa_context, as requested in #6917.
diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h
index af9f9f8..d889e7e 100644
--- a/include/mbedtls/mbedtls_config.h
+++ b/include/mbedtls/mbedtls_config.h
@@ -55,6 +55,7 @@
* library/padlock.h
*
* Required by:
+ * MBEDTLS_AESCE_C
* MBEDTLS_AESNI_C
* MBEDTLS_PADLOCK_C
*
diff --git a/include/mbedtls/rsa.h b/include/mbedtls/rsa.h
index d77a538..da8639b 100644
--- a/include/mbedtls/rsa.h
+++ b/include/mbedtls/rsa.h
@@ -182,6 +182,28 @@
mbedtls_md_type_t hash_id);
/**
+ * \brief This function retrieves padding mode of initialized
+ * RSA context.
+ *
+ * \param ctx The initialized RSA context.
+ *
+ * \return RSA padding mode.
+ *
+ */
+int mbedtls_rsa_get_padding_mode(const mbedtls_rsa_context *ctx);
+
+/**
+ * \brief This function retrieves hash identifier of mbedtls_md_type_t
+ * type.
+ *
+ * \param ctx The initialized RSA context.
+ *
+ * \return Hash identifier of mbedtls_md_type_t type.
+ *
+ */
+int mbedtls_rsa_get_md_alg(const mbedtls_rsa_context *ctx);
+
+/**
* \brief This function imports a set of core parameters into an
* RSA context.
*
diff --git a/library/aesce.c b/library/aesce.c
index 84a804a..fe056dc 100644
--- a/library/aesce.c
+++ b/library/aesce.c
@@ -212,14 +212,14 @@
0x20, 0x40, 0x80, 0x1b, 0x36 };
/* See https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197.pdf
* - Section 5, Nr = Nk + 6
- * - Section 5.2, the key expansion size is Nb*(Nr+1)
+ * - Section 5.2, the length of round keys is Nb*(Nr+1)
*/
const uint32_t key_len_in_words = key_bit_length / 32; /* Nk */
const size_t round_key_len_in_words = 4; /* Nb */
- const size_t round_keys_needed = key_len_in_words + 6; /* Nr */
- const size_t key_expansion_size_in_words =
- round_key_len_in_words * (round_keys_needed + 1); /* Nb*(Nr+1) */
- const uint32_t *rko_end = (uint32_t *) rk + key_expansion_size_in_words;
+ const size_t rounds_needed = key_len_in_words + 6; /* Nr */
+ const size_t round_keys_len_in_words =
+ round_key_len_in_words * (rounds_needed + 1); /* Nb*(Nr+1) */
+ const uint32_t *rko_end = (uint32_t *) rk + round_keys_len_in_words;
memcpy(rk, key, key_len_in_words * 4);
@@ -276,6 +276,126 @@
return 0;
}
+#if defined(MBEDTLS_GCM_C)
+
+#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ == 5
+/* Some intrinsics are not available for GCC 5.X. */
+#define vreinterpretq_p64_u8(a) ((poly64x2_t) a)
+#define vreinterpretq_u8_p128(a) ((uint8x16_t) a)
+static inline poly64_t vget_low_p64(poly64x2_t __a)
+{
+ uint64x2_t tmp = (uint64x2_t) (__a);
+ uint64x1_t lo = vcreate_u64(vgetq_lane_u64(tmp, 0));
+ return (poly64_t) (lo);
+}
+#endif /* !__clang__ && __GNUC__ && __GNUC__ == 5*/
+
+/* vmull_p64/vmull_high_p64 wrappers.
+ *
+ * Older compilers miss some intrinsic functions for `poly*_t`. We use
+ * uint8x16_t and uint8x16x3_t as input/output parameters.
+ */
+static inline uint8x16_t pmull_low(uint8x16_t a, uint8x16_t b)
+{
+ return vreinterpretq_u8_p128(
+ vmull_p64(
+ (poly64_t) vget_low_p64(vreinterpretq_p64_u8(a)),
+ (poly64_t) vget_low_p64(vreinterpretq_p64_u8(b))));
+}
+
+static inline uint8x16_t pmull_high(uint8x16_t a, uint8x16_t b)
+{
+ return vreinterpretq_u8_p128(
+ vmull_high_p64(vreinterpretq_p64_u8(a),
+ vreinterpretq_p64_u8(b)));
+}
+
+/* GHASH does 128b polynomial multiplication on block in GF(2^128) defined by
+ * `x^128 + x^7 + x^2 + x + 1`.
+ *
+ * Arm64 only has 64b->128b polynomial multipliers, we need to do 4 64b
+ * multiplies to generate a 128b.
+ *
+ * `poly_mult_128` executes polynomial multiplication and outputs 256b that
+ * represented by 3 128b due to code size optimization.
+ *
+ * Output layout:
+ * | | | |
+ * |------------|-------------|-------------|
+ * | ret.val[0] | h3:h2:00:00 | high 128b |
+ * | ret.val[1] | :m2:m1:00 | middle 128b |
+ * | ret.val[2] | : :l1:l0 | low 128b |
+ */
+static inline uint8x16x3_t poly_mult_128(uint8x16_t a, uint8x16_t b)
+{
+ uint8x16x3_t ret;
+ uint8x16_t h, m, l; /* retval high/middle/low */
+ uint8x16_t c, d, e;
+
+ h = pmull_high(a, b); /* h3:h2:00:00 = a1*b1 */
+ l = pmull_low(a, b); /* : :l1:l0 = a0*b0 */
+ c = vextq_u8(b, b, 8); /* :c1:c0 = b0:b1 */
+ d = pmull_high(a, c); /* :d2:d1:00 = a1*b0 */
+ e = pmull_low(a, c); /* :e2:e1:00 = a0*b1 */
+ m = veorq_u8(d, e); /* :m2:m1:00 = d + e */
+
+ ret.val[0] = h;
+ ret.val[1] = m;
+ ret.val[2] = l;
+ return ret;
+}
+
+/*
+ * Modulo reduction.
+ *
+ * See: https://www.researchgate.net/publication/285612706_Implementing_GCM_on_ARMv8
+ *
+ * Section 4.3
+ *
+ * Modular reduction is slightly more complex. Write the GCM modulus as f(z) =
+ * z^128 +r(z), where r(z) = z^7+z^2+z+ 1. The well known approach is to
+ * consider that z^128 ≡r(z) (mod z^128 +r(z)), allowing us to write the 256-bit
+ * operand to be reduced as a(z) = h(z)z^128 +l(z)≡h(z)r(z) + l(z). That is, we
+ * simply multiply the higher part of the operand by r(z) and add it to l(z). If
+ * the result is still larger than 128 bits, we reduce again.
+ */
+static inline uint8x16_t poly_mult_reduce(uint8x16x3_t input)
+{
+ uint8x16_t const ZERO = vdupq_n_u8(0);
+ /* use 'asm' as an optimisation barrier to prevent loading MODULO from memory */
+ uint64x2_t r = vreinterpretq_u64_u8(vdupq_n_u8(0x87));
+ asm ("" : "+w" (r));
+ uint8x16_t const MODULO = vreinterpretq_u8_u64(vshrq_n_u64(r, 64 - 8));
+ uint8x16_t h, m, l; /* input high/middle/low 128b */
+ uint8x16_t c, d, e, f, g, n, o;
+ h = input.val[0]; /* h3:h2:00:00 */
+ m = input.val[1]; /* :m2:m1:00 */
+ l = input.val[2]; /* : :l1:l0 */
+ c = pmull_high(h, MODULO); /* :c2:c1:00 = reduction of h3 */
+ d = pmull_low(h, MODULO); /* : :d1:d0 = reduction of h2 */
+ e = veorq_u8(c, m); /* :e2:e1:00 = m2:m1:00 + c2:c1:00 */
+ f = pmull_high(e, MODULO); /* : :f1:f0 = reduction of e2 */
+ g = vextq_u8(ZERO, e, 8); /* : :g1:00 = e1:00 */
+ n = veorq_u8(d, l); /* : :n1:n0 = d1:d0 + l1:l0 */
+ o = veorq_u8(n, f); /* o1:o0 = f1:f0 + n1:n0 */
+ return veorq_u8(o, g); /* = o1:o0 + g1:00 */
+}
+
+/*
+ * GCM multiplication: c = a times b in GF(2^128)
+ */
+void mbedtls_aesce_gcm_mult(unsigned char c[16],
+ const unsigned char a[16],
+ const unsigned char b[16])
+{
+ uint8x16_t va, vb, vc;
+ va = vrbitq_u8(vld1q_u8(&a[0]));
+ vb = vrbitq_u8(vld1q_u8(&b[0]));
+ vc = vrbitq_u8(poly_mult_reduce(poly_mult_128(va, vb)));
+ vst1q_u8(&c[0], vc);
+}
+
+#endif /* MBEDTLS_GCM_C */
#if defined(MBEDTLS_POP_TARGET_PRAGMA)
#if defined(__clang__)
diff --git a/library/aesce.h b/library/aesce.h
index 4e44a68..12ddc74 100644
--- a/library/aesce.h
+++ b/library/aesce.h
@@ -65,6 +65,24 @@
unsigned char output[16]);
/**
+ * \brief Internal GCM multiplication: c = a * b in GF(2^128)
+ *
+ * \note This function is only for internal use by other library
+ * functions; you must not call it directly.
+ *
+ * \param c Result
+ * \param a First operand
+ * \param b Second operand
+ *
+ * \note Both operands and result are bit strings interpreted as
+ * elements of GF(2^128) as per the GCM spec.
+ */
+void mbedtls_aesce_gcm_mult(unsigned char c[16],
+ const unsigned char a[16],
+ const unsigned char b[16]);
+
+
+/**
* \brief Internal round key inversion. This function computes
* decryption round keys from the encryption round keys.
*
diff --git a/library/gcm.c b/library/gcm.c
index 6d4495f..14886bd 100644
--- a/library/gcm.c
+++ b/library/gcm.c
@@ -42,6 +42,10 @@
#include "aesni.h"
#endif
+#if defined(MBEDTLS_AESCE_C)
+#include "aesce.h"
+#endif
+
#if !defined(MBEDTLS_GCM_ALT)
/*
@@ -93,6 +97,12 @@
}
#endif
+#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
+ if (mbedtls_aesce_has_support()) {
+ return 0;
+ }
+#endif
+
/* 0 corresponds to 0 in GF(2^128) */
ctx->HH[0] = 0;
ctx->HL[0] = 0;
@@ -187,6 +197,7 @@
if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
unsigned char h[16];
+ /* mbedtls_aesni_gcm_mult needs big-endian input */
MBEDTLS_PUT_UINT32_BE(ctx->HH[8] >> 32, h, 0);
MBEDTLS_PUT_UINT32_BE(ctx->HH[8], h, 4);
MBEDTLS_PUT_UINT32_BE(ctx->HL[8] >> 32, h, 8);
@@ -197,6 +208,21 @@
}
#endif /* MBEDTLS_AESNI_C && MBEDTLS_HAVE_X86_64 */
+#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
+ if (mbedtls_aesce_has_support()) {
+ unsigned char h[16];
+
+ /* mbedtls_aesce_gcm_mult needs big-endian input */
+ MBEDTLS_PUT_UINT32_BE(ctx->HH[8] >> 32, h, 0);
+ MBEDTLS_PUT_UINT32_BE(ctx->HH[8], h, 4);
+ MBEDTLS_PUT_UINT32_BE(ctx->HL[8] >> 32, h, 8);
+ MBEDTLS_PUT_UINT32_BE(ctx->HL[8], h, 12);
+
+ mbedtls_aesce_gcm_mult(output, x, h);
+ return;
+ }
+#endif
+
lo = x[15] & 0xf;
zh = ctx->HH[lo];
diff --git a/library/rsa.c b/library/rsa.c
index 584b363..01159df 100644
--- a/library/rsa.c
+++ b/library/rsa.c
@@ -503,9 +503,24 @@
}
/*
+ * Get padding mode of initialized RSA context
+ */
+int mbedtls_rsa_get_padding_mode(const mbedtls_rsa_context *ctx)
+{
+ return ctx->padding;
+}
+
+/*
+ * Get hash identifier of mbedtls_md_type_t type
+ */
+int mbedtls_rsa_get_md_alg(const mbedtls_rsa_context *ctx)
+{
+ return ctx->hash_id;
+}
+
+/*
* Get length in bytes of RSA modulus
*/
-
size_t mbedtls_rsa_get_len(const mbedtls_rsa_context *ctx)
{
return ctx->len;
diff --git a/tests/suites/test_suite_pkcs1_v15.function b/tests/suites/test_suite_pkcs1_v15.function
index d0ea23c..09daeb6 100644
--- a/tests/suites/test_suite_pkcs1_v15.function
+++ b/tests/suites/test_suite_pkcs1_v15.function
@@ -28,10 +28,17 @@
mbedtls_mpi_init(&N); mbedtls_mpi_init(&E);
mbedtls_rsa_init(&ctx);
+
+ TEST_EQUAL(mbedtls_rsa_get_padding_mode(&ctx), MBEDTLS_RSA_PKCS_V15);
+ TEST_EQUAL(mbedtls_rsa_get_md_alg(&ctx), MBEDTLS_MD_NONE);
+
TEST_ASSERT(mbedtls_rsa_set_padding(&ctx,
MBEDTLS_RSA_PKCS_V15, hash) == 0);
memset(output, 0x00, sizeof(output));
+ TEST_EQUAL(mbedtls_rsa_get_padding_mode(&ctx), MBEDTLS_RSA_PKCS_V15);
+ TEST_EQUAL(mbedtls_rsa_get_md_alg(&ctx), hash);
+
TEST_ASSERT(mbedtls_test_read_mpi(&N, input_N) == 0);
TEST_ASSERT(mbedtls_test_read_mpi(&E, input_E) == 0);
TEST_ASSERT(mbedtls_rsa_import(&ctx, &N, NULL, NULL, NULL, &E) == 0);
@@ -77,6 +84,9 @@
TEST_ASSERT(mbedtls_rsa_set_padding(&ctx,
MBEDTLS_RSA_PKCS_V15, hash) == 0);
+ TEST_EQUAL(mbedtls_rsa_get_padding_mode(&ctx), MBEDTLS_RSA_PKCS_V15);
+ TEST_EQUAL(mbedtls_rsa_get_md_alg(&ctx), hash);
+
memset(output, 0x00, sizeof(output));
memset(&rnd_info, 0, sizeof(mbedtls_test_rnd_pseudo_info));
@@ -281,6 +291,9 @@
memset(output, 0x00, sizeof(output));
+ TEST_EQUAL(mbedtls_rsa_get_padding_mode(&ctx), MBEDTLS_RSA_PKCS_V15);
+ TEST_EQUAL(mbedtls_rsa_get_md_alg(&ctx), hash);
+
TEST_ASSERT(mbedtls_test_read_mpi(&P, input_P) == 0);
TEST_ASSERT(mbedtls_test_read_mpi(&Q, input_Q) == 0);
TEST_ASSERT(mbedtls_test_read_mpi(&N, input_N) == 0);
@@ -322,6 +335,9 @@
TEST_ASSERT(mbedtls_rsa_set_padding(&ctx,
MBEDTLS_RSA_PKCS_V15, hash) == 0);
+ TEST_EQUAL(mbedtls_rsa_get_padding_mode(&ctx), MBEDTLS_RSA_PKCS_V15);
+ TEST_EQUAL(mbedtls_rsa_get_md_alg(&ctx), hash);
+
TEST_ASSERT(mbedtls_test_read_mpi(&N, input_N) == 0);
TEST_ASSERT(mbedtls_test_read_mpi(&E, input_E) == 0);
TEST_ASSERT(mbedtls_rsa_import(&ctx, &N, NULL, NULL, NULL, &E) == 0);
diff --git a/tests/suites/test_suite_pkcs1_v21.function b/tests/suites/test_suite_pkcs1_v21.function
index 376c752..75dbc35 100644
--- a/tests/suites/test_suite_pkcs1_v21.function
+++ b/tests/suites/test_suite_pkcs1_v21.function
@@ -29,6 +29,9 @@
MBEDTLS_RSA_PKCS_V21, hash) == 0);
memset(output, 0x00, sizeof(output));
+ TEST_EQUAL(mbedtls_rsa_get_padding_mode(&ctx), MBEDTLS_RSA_PKCS_V21);
+ TEST_EQUAL(mbedtls_rsa_get_md_alg(&ctx), hash);
+
TEST_ASSERT(mbedtls_mpi_read_binary(&N, input_N->x, input_N->len) == 0);
TEST_ASSERT(mbedtls_mpi_read_binary(&E, input_E->x, input_E->len) == 0);
TEST_ASSERT(mbedtls_rsa_import(&ctx, &N, NULL, NULL, NULL, &E) == 0);
@@ -73,6 +76,9 @@
TEST_ASSERT(mbedtls_rsa_set_padding(&ctx,
MBEDTLS_RSA_PKCS_V21, hash) == 0);
+ TEST_EQUAL(mbedtls_rsa_get_padding_mode(&ctx), MBEDTLS_RSA_PKCS_V21);
+ TEST_EQUAL(mbedtls_rsa_get_md_alg(&ctx), hash);
+
memset(output, 0x00, sizeof(output));
memset(&rnd_info, 0, sizeof(mbedtls_test_rnd_pseudo_info));
@@ -134,6 +140,9 @@
TEST_ASSERT(mbedtls_rsa_set_padding(&ctx,
MBEDTLS_RSA_PKCS_V21, hash) == 0);
+ TEST_EQUAL(mbedtls_rsa_get_padding_mode(&ctx), MBEDTLS_RSA_PKCS_V21);
+ TEST_EQUAL(mbedtls_rsa_get_md_alg(&ctx), hash);
+
memset(output, 0x00, sizeof(output));
TEST_ASSERT(mbedtls_mpi_read_binary(&P, input_P->x, input_P->len) == 0);
@@ -187,6 +196,9 @@
TEST_ASSERT(mbedtls_rsa_set_padding(&ctx,
MBEDTLS_RSA_PKCS_V21, hash) == 0);
+ TEST_EQUAL(mbedtls_rsa_get_padding_mode(&ctx), MBEDTLS_RSA_PKCS_V21);
+ TEST_EQUAL(mbedtls_rsa_get_md_alg(&ctx), hash);
+
TEST_ASSERT(mbedtls_mpi_read_binary(&N, input_N->x, input_N->len) == 0);
TEST_ASSERT(mbedtls_mpi_read_binary(&E, input_E->x, input_E->len) == 0);
@@ -220,6 +232,9 @@
TEST_ASSERT(mbedtls_rsa_set_padding(&ctx,
MBEDTLS_RSA_PKCS_V21, ctx_hash) == 0);
+ TEST_EQUAL(mbedtls_rsa_get_padding_mode(&ctx), MBEDTLS_RSA_PKCS_V21);
+ TEST_EQUAL(mbedtls_rsa_get_md_alg(&ctx), ctx_hash);
+
TEST_ASSERT(mbedtls_mpi_read_binary(&N, input_N->x, input_N->len) == 0);
TEST_ASSERT(mbedtls_mpi_read_binary(&E, input_E->x, input_E->len) == 0);