Merge branch 'development' into buffer-sharing-merge
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index b6ea73e..47ecf17 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -231,7 +231,7 @@
endif(HAIKU)
if(LINK_WITH_PTHREAD)
- set(libs ${libs} pthread)
+ set(libs ${libs} ${CMAKE_THREAD_LIBS_INIT})
endif()
if(LINK_WITH_TRUSTED_STORAGE)
diff --git a/library/aesce.c b/library/aesce.c
index eaaa5b5..6a9e0a1 100644
--- a/library/aesce.c
+++ b/library/aesce.c
@@ -334,7 +334,7 @@
* - Section 5, Nr = Nk + 6
* - 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 key_len_in_words = key_bit_length / 32; /* Nk */
const size_t round_key_len_in_words = 4; /* Nb */
const size_t rounds_needed = key_len_in_words + 6; /* Nr */
const size_t round_keys_len_in_words =
diff --git a/library/alignment.h b/library/alignment.h
index 248f29b..a17001d 100644
--- a/library/alignment.h
+++ b/library/alignment.h
@@ -53,28 +53,45 @@
typedef uint32_t __packed mbedtls_uint32_unaligned_t;
typedef uint64_t __packed mbedtls_uint64_unaligned_t;
#elif defined(MBEDTLS_COMPILER_IS_GCC) && (MBEDTLS_GCC_VERSION >= 40504) && \
- ((MBEDTLS_GCC_VERSION < 90300) || (!defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS)))
+ ((MBEDTLS_GCC_VERSION < 60300) || (!defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS)))
/*
- * Old versions of gcc, depending on how the target is specified, may generate a branch to memcpy
- * for calls like `memcpy(dest, src, 4)` rather than generating some LDR or LDRB instructions
- * (similar for stores).
- * Recent versions where unaligned access is not enabled also do this.
+ * gcc may generate a branch to memcpy for calls like `memcpy(dest, src, 4)` rather than
+ * generating some LDR or LDRB instructions (similar for stores).
+ *
+ * This is architecture dependent: x86-64 seems fine even with old gcc; 32-bit Arm
+ * is affected. To keep it simple, we enable for all architectures.
+ *
+ * For versions of gcc < 5.4.0 this issue always happens.
+ * For gcc < 6.3.0, this issue happens at -O0
+ * For all versions, this issue happens iff unaligned access is not supported.
+ *
+ * For gcc 4.x, this implementation will generate byte-by-byte loads even if unaligned access is
+ * supported, which is correct but not optimal.
*
* For performance (and code size, in some cases), we want to avoid the branch and just generate
* some inline load/store instructions since the access is small and constant-size.
*
* The manual states:
- * "The aligned attribute specifies a minimum alignment for the variable or structure field,
- * measured in bytes."
- * https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html
+ * "The packed attribute specifies that a variable or structure field should have the smallest
+ * possible alignment—one byte for a variable"
+ * https://gcc.gnu.org/onlinedocs/gcc-4.5.4/gcc/Variable-Attributes.html
*
- * Tested with several versions of GCC from 4.5.0 up to 9.3.0
+ * Previous implementations used __attribute__((__aligned__(1)), but had issues with a gcc bug:
+ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94662
+ *
+ * Tested with several versions of GCC from 4.5.0 up to 13.2.0
* We don't enable for older than 4.5.0 as this has not been tested.
*/
- #define UINT_UNALIGNED
-typedef uint16_t __attribute__((__aligned__(1))) mbedtls_uint16_unaligned_t;
-typedef uint32_t __attribute__((__aligned__(1))) mbedtls_uint32_unaligned_t;
-typedef uint64_t __attribute__((__aligned__(1))) mbedtls_uint64_unaligned_t;
+ #define UINT_UNALIGNED_STRUCT
+typedef struct {
+ uint16_t x;
+} __attribute__((packed)) mbedtls_uint16_unaligned_t;
+typedef struct {
+ uint32_t x;
+} __attribute__((packed)) mbedtls_uint32_unaligned_t;
+typedef struct {
+ uint64_t x;
+} __attribute__((packed)) mbedtls_uint64_unaligned_t;
#endif
/*
@@ -101,6 +118,9 @@
#if defined(UINT_UNALIGNED)
mbedtls_uint16_unaligned_t *p16 = (mbedtls_uint16_unaligned_t *) p;
r = *p16;
+#elif defined(UINT_UNALIGNED_STRUCT)
+ mbedtls_uint16_unaligned_t *p16 = (mbedtls_uint16_unaligned_t *) p;
+ r = p16->x;
#else
memcpy(&r, p, sizeof(r));
#endif
@@ -124,6 +144,9 @@
#if defined(UINT_UNALIGNED)
mbedtls_uint16_unaligned_t *p16 = (mbedtls_uint16_unaligned_t *) p;
*p16 = x;
+#elif defined(UINT_UNALIGNED_STRUCT)
+ mbedtls_uint16_unaligned_t *p16 = (mbedtls_uint16_unaligned_t *) p;
+ p16->x = x;
#else
memcpy(p, &x, sizeof(x));
#endif
@@ -147,6 +170,9 @@
#if defined(UINT_UNALIGNED)
mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p;
r = *p32;
+#elif defined(UINT_UNALIGNED_STRUCT)
+ mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p;
+ r = p32->x;
#else
memcpy(&r, p, sizeof(r));
#endif
@@ -170,6 +196,9 @@
#if defined(UINT_UNALIGNED)
mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p;
*p32 = x;
+#elif defined(UINT_UNALIGNED_STRUCT)
+ mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p;
+ p32->x = x;
#else
memcpy(p, &x, sizeof(x));
#endif
@@ -193,6 +222,9 @@
#if defined(UINT_UNALIGNED)
mbedtls_uint64_unaligned_t *p64 = (mbedtls_uint64_unaligned_t *) p;
r = *p64;
+#elif defined(UINT_UNALIGNED_STRUCT)
+ mbedtls_uint64_unaligned_t *p64 = (mbedtls_uint64_unaligned_t *) p;
+ r = p64->x;
#else
memcpy(&r, p, sizeof(r));
#endif
@@ -216,6 +248,9 @@
#if defined(UINT_UNALIGNED)
mbedtls_uint64_unaligned_t *p64 = (mbedtls_uint64_unaligned_t *) p;
*p64 = x;
+#elif defined(UINT_UNALIGNED_STRUCT)
+ mbedtls_uint64_unaligned_t *p64 = (mbedtls_uint64_unaligned_t *) p;
+ p64->x = x;
#else
memcpy(p, &x, sizeof(x));
#endif
diff --git a/library/aria.c b/library/aria.c
index ba12578..d9f84cc 100644
--- a/library/aria.c
+++ b/library/aria.c
@@ -25,12 +25,6 @@
#include "mbedtls/platform_util.h"
-/* Parameter validation macros */
-#define ARIA_VALIDATE_RET(cond) \
- MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_ARIA_BAD_INPUT_DATA)
-#define ARIA_VALIDATE(cond) \
- MBEDTLS_INTERNAL_VALIDATE(cond)
-
/*
* modify byte order: ( A B C D ) -> ( B A D C ), i.e. swap pairs of bytes
*
@@ -363,8 +357,6 @@
int i;
uint32_t w[4][4], *w2;
- ARIA_VALIDATE_RET(ctx != NULL);
- ARIA_VALIDATE_RET(key != NULL);
if (keybits != 128 && keybits != 192 && keybits != 256) {
return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA;
@@ -418,8 +410,6 @@
const unsigned char *key, unsigned int keybits)
{
int i, j, k, ret;
- ARIA_VALIDATE_RET(ctx != NULL);
- ARIA_VALIDATE_RET(key != NULL);
ret = mbedtls_aria_setkey_enc(ctx, key, keybits);
if (ret != 0) {
@@ -455,9 +445,6 @@
int i;
uint32_t a, b, c, d;
- ARIA_VALIDATE_RET(ctx != NULL);
- ARIA_VALIDATE_RET(input != NULL);
- ARIA_VALIDATE_RET(output != NULL);
a = MBEDTLS_GET_UINT32_LE(input, 0);
b = MBEDTLS_GET_UINT32_LE(input, 4);
@@ -505,7 +492,6 @@
/* Initialize context */
void mbedtls_aria_init(mbedtls_aria_context *ctx)
{
- ARIA_VALIDATE(ctx != NULL);
memset(ctx, 0, sizeof(mbedtls_aria_context));
}
@@ -532,12 +518,9 @@
{
unsigned char temp[MBEDTLS_ARIA_BLOCKSIZE];
- ARIA_VALIDATE_RET(ctx != NULL);
- ARIA_VALIDATE_RET(mode == MBEDTLS_ARIA_ENCRYPT ||
- mode == MBEDTLS_ARIA_DECRYPT);
- ARIA_VALIDATE_RET(length == 0 || input != NULL);
- ARIA_VALIDATE_RET(length == 0 || output != NULL);
- ARIA_VALIDATE_RET(iv != NULL);
+ if ((mode != MBEDTLS_ARIA_ENCRYPT) && (mode != MBEDTLS_ARIA_DECRYPT)) {
+ return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA;
+ }
if (length % MBEDTLS_ARIA_BLOCKSIZE) {
return MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH;
@@ -588,19 +571,14 @@
unsigned char c;
size_t n;
- ARIA_VALIDATE_RET(ctx != NULL);
- ARIA_VALIDATE_RET(mode == MBEDTLS_ARIA_ENCRYPT ||
- mode == MBEDTLS_ARIA_DECRYPT);
- ARIA_VALIDATE_RET(length == 0 || input != NULL);
- ARIA_VALIDATE_RET(length == 0 || output != NULL);
- ARIA_VALIDATE_RET(iv != NULL);
- ARIA_VALIDATE_RET(iv_off != NULL);
+ if ((mode != MBEDTLS_ARIA_ENCRYPT) && (mode != MBEDTLS_ARIA_DECRYPT)) {
+ return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA;
+ }
n = *iv_off;
/* An overly large value of n can lead to an unlimited
- * buffer overflow. Therefore, guard against this
- * outside of parameter validation. */
+ * buffer overflow. */
if (n >= MBEDTLS_ARIA_BLOCKSIZE) {
return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA;
}
@@ -650,17 +628,9 @@
int c, i;
size_t n;
- ARIA_VALIDATE_RET(ctx != NULL);
- ARIA_VALIDATE_RET(length == 0 || input != NULL);
- ARIA_VALIDATE_RET(length == 0 || output != NULL);
- ARIA_VALIDATE_RET(nonce_counter != NULL);
- ARIA_VALIDATE_RET(stream_block != NULL);
- ARIA_VALIDATE_RET(nc_off != NULL);
-
n = *nc_off;
/* An overly large value of n can lead to an unlimited
- * buffer overflow. Therefore, guard against this
- * outside of parameter validation. */
+ * buffer overflow. */
if (n >= MBEDTLS_ARIA_BLOCKSIZE) {
return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA;
}
diff --git a/library/asn1parse.c b/library/asn1parse.c
index c02b233..e33fdf7 100644
--- a/library/asn1parse.c
+++ b/library/asn1parse.c
@@ -7,7 +7,8 @@
#include "common.h"
-#if defined(MBEDTLS_ASN1_PARSE_C) || defined(MBEDTLS_X509_CREATE_C)
+#if defined(MBEDTLS_ASN1_PARSE_C) || defined(MBEDTLS_X509_CREATE_C) || \
+ defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA)
#include "mbedtls/asn1.h"
#include "mbedtls/platform_util.h"
@@ -73,7 +74,7 @@
return mbedtls_asn1_get_len(p, end, len);
}
-#endif /* MBEDTLS_ASN1_PARSE_C || MBEDTLS_X509_CREATE_C */
+#endif /* MBEDTLS_ASN1_PARSE_C || MBEDTLS_X509_CREATE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA */
#if defined(MBEDTLS_ASN1_PARSE_C)
int mbedtls_asn1_get_bool(unsigned char **p,
diff --git a/library/asn1write.c b/library/asn1write.c
index 114091d..775a9ef 100644
--- a/library/asn1write.c
+++ b/library/asn1write.c
@@ -7,7 +7,8 @@
#include "common.h"
-#if defined(MBEDTLS_ASN1_WRITE_C) || defined(MBEDTLS_X509_USE_C)
+#if defined(MBEDTLS_ASN1_WRITE_C) || defined(MBEDTLS_X509_USE_C) || \
+ defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA)
#include "mbedtls/asn1write.h"
#include "mbedtls/error.h"
@@ -62,7 +63,7 @@
return 1;
}
-#endif /* MBEDTLS_ASN1_WRITE_C || MBEDTLS_X509_USE_C */
+#endif /* MBEDTLS_ASN1_WRITE_C || MBEDTLS_X509_USE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA */
#if defined(MBEDTLS_ASN1_WRITE_C)
static int mbedtls_asn1_write_len_and_tag(unsigned char **p,
diff --git a/library/bignum.c b/library/bignum.c
index 1869137..c45fd5b 100644
--- a/library/bignum.c
+++ b/library/bignum.c
@@ -37,10 +37,18 @@
#include "mbedtls/platform.h"
-#define MPI_VALIDATE_RET(cond) \
- MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA)
-#define MPI_VALIDATE(cond) \
- MBEDTLS_INTERNAL_VALIDATE(cond)
+
+
+/*
+ * Conditionally select an MPI sign in constant time.
+ * (MPI sign is the field s in mbedtls_mpi. It is unsigned short and only 1 and -1 are valid
+ * values.)
+ */
+static inline signed short mbedtls_ct_mpi_sign_if(mbedtls_ct_condition_t cond,
+ signed short sign1, signed short sign2)
+{
+ return (signed short) mbedtls_ct_uint_if(cond, sign1 + 1, sign2 + 1) - 1;
+}
/*
* Compare signed values in constant time
@@ -51,10 +59,6 @@
{
mbedtls_ct_condition_t different_sign, X_is_negative, Y_is_negative, result;
- MPI_VALIDATE_RET(X != NULL);
- MPI_VALIDATE_RET(Y != NULL);
- MPI_VALIDATE_RET(ret != NULL);
-
if (X->n != Y->n) {
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
}
@@ -115,15 +119,13 @@
unsigned char assign)
{
int ret = 0;
- MPI_VALIDATE_RET(X != NULL);
- MPI_VALIDATE_RET(Y != NULL);
MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
{
mbedtls_ct_condition_t do_assign = mbedtls_ct_bool(assign);
- X->s = (int) mbedtls_ct_uint_if(do_assign, Y->s, X->s);
+ X->s = mbedtls_ct_mpi_sign_if(do_assign, Y->s, X->s);
mbedtls_mpi_core_cond_assign(X->p, Y->p, Y->n, do_assign);
@@ -149,8 +151,6 @@
{
int ret = 0;
int s;
- MPI_VALIDATE_RET(X != NULL);
- MPI_VALIDATE_RET(Y != NULL);
if (X == Y) {
return 0;
@@ -162,8 +162,8 @@
MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Y, X->n));
s = X->s;
- X->s = (int) mbedtls_ct_uint_if(do_swap, Y->s, X->s);
- Y->s = (int) mbedtls_ct_uint_if(do_swap, s, Y->s);
+ X->s = mbedtls_ct_mpi_sign_if(do_swap, Y->s, X->s);
+ Y->s = mbedtls_ct_mpi_sign_if(do_swap, s, Y->s);
mbedtls_mpi_core_cond_swap(X->p, Y->p, X->n, do_swap);
@@ -179,8 +179,6 @@
*/
void mbedtls_mpi_init(mbedtls_mpi *X)
{
- MPI_VALIDATE(X != NULL);
-
X->s = 1;
X->n = 0;
X->p = NULL;
@@ -210,7 +208,6 @@
int mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs)
{
mbedtls_mpi_uint *p;
- MPI_VALIDATE_RET(X != NULL);
if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
return MBEDTLS_ERR_MPI_ALLOC_FAILED;
@@ -243,7 +240,6 @@
{
mbedtls_mpi_uint *p;
size_t i;
- MPI_VALIDATE_RET(X != NULL);
if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
return MBEDTLS_ERR_MPI_ALLOC_FAILED;
@@ -305,15 +301,12 @@
* This function is not constant-time. Leading zeros in Y may be removed.
*
* Ensure that X does not shrink. This is not guaranteed by the public API,
- * but some code in the bignum module relies on this property, for example
- * in mbedtls_mpi_exp_mod().
+ * but some code in the bignum module might still rely on this property.
*/
int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y)
{
int ret = 0;
size_t i;
- MPI_VALIDATE_RET(X != NULL);
- MPI_VALIDATE_RET(Y != NULL);
if (X == Y) {
return 0;
@@ -355,8 +348,6 @@
void mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y)
{
mbedtls_mpi T;
- MPI_VALIDATE(X != NULL);
- MPI_VALIDATE(Y != NULL);
memcpy(&T, X, sizeof(mbedtls_mpi));
memcpy(X, Y, sizeof(mbedtls_mpi));
@@ -385,7 +376,6 @@
int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- MPI_VALIDATE_RET(X != NULL);
MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, 1));
memset(X->p, 0, X->n * ciL);
@@ -403,8 +393,6 @@
*/
int mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos)
{
- MPI_VALIDATE_RET(X != NULL);
-
if (X->n * biL <= pos) {
return 0;
}
@@ -420,7 +408,6 @@
int ret = 0;
size_t off = pos / biL;
size_t idx = pos % biL;
- MPI_VALIDATE_RET(X != NULL);
if (val != 0 && val != 1) {
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
@@ -448,7 +435,6 @@
size_t mbedtls_mpi_lsb(const mbedtls_mpi *X)
{
size_t i;
- MBEDTLS_INTERNAL_VALIDATE_RET(X != NULL, 0);
#if defined(__has_builtin)
#if (MBEDTLS_MPI_UINT_MAX == UINT_MAX) && __has_builtin(__builtin_ctz)
@@ -530,8 +516,6 @@
int sign = 1;
mbedtls_mpi_uint d;
mbedtls_mpi T;
- MPI_VALIDATE_RET(X != NULL);
- MPI_VALIDATE_RET(s != NULL);
if (radix < 2 || radix > 16) {
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
@@ -634,9 +618,6 @@
size_t n;
char *p;
mbedtls_mpi T;
- MPI_VALIDATE_RET(X != NULL);
- MPI_VALIDATE_RET(olen != NULL);
- MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
if (radix < 2 || radix > 16) {
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
@@ -726,9 +707,6 @@
*/
char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
- MPI_VALIDATE_RET(X != NULL);
- MPI_VALIDATE_RET(fin != NULL);
-
if (radix < 2 || radix > 16) {
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
}
@@ -772,7 +750,6 @@
* newline characters and '\0'
*/
char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
- MPI_VALIDATE_RET(X != NULL);
if (radix < 2 || radix > 16) {
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
@@ -844,9 +821,6 @@
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const size_t limbs = CHARS_TO_LIMBS(buflen);
- MPI_VALIDATE_RET(X != NULL);
- MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
-
/* Ensure that target MPI has exactly the necessary number of limbs */
MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
@@ -887,7 +861,6 @@
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i;
- MPI_VALIDATE_RET(X != NULL);
i = mbedtls_mpi_bitlen(X) + count;
@@ -908,7 +881,6 @@
*/
int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count)
{
- MPI_VALIDATE_RET(X != NULL);
if (X->n != 0) {
mbedtls_mpi_core_shift_r(X->p, X->n, count);
}
@@ -921,8 +893,6 @@
int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y)
{
size_t i, j;
- MPI_VALIDATE_RET(X != NULL);
- MPI_VALIDATE_RET(Y != NULL);
for (i = X->n; i > 0; i--) {
if (X->p[i - 1] != 0) {
@@ -964,8 +934,6 @@
int mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_mpi *Y)
{
size_t i, j;
- MPI_VALIDATE_RET(X != NULL);
- MPI_VALIDATE_RET(Y != NULL);
for (i = X->n; i > 0; i--) {
if (X->p[i - 1] != 0) {
@@ -1016,7 +984,6 @@
{
mbedtls_mpi Y;
mbedtls_mpi_uint p[1];
- MPI_VALIDATE_RET(X != NULL);
*p = mpi_sint_abs(z);
Y.s = TO_SIGN(z);
@@ -1035,9 +1002,6 @@
size_t j;
mbedtls_mpi_uint *p;
mbedtls_mpi_uint c;
- MPI_VALIDATE_RET(X != NULL);
- MPI_VALIDATE_RET(A != NULL);
- MPI_VALIDATE_RET(B != NULL);
if (X == B) {
const mbedtls_mpi *T = A; A = X; B = T;
@@ -1098,9 +1062,6 @@
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n;
mbedtls_mpi_uint carry;
- MPI_VALIDATE_RET(X != NULL);
- MPI_VALIDATE_RET(A != NULL);
- MPI_VALIDATE_RET(B != NULL);
for (n = B->n; n > 0; n--) {
if (B->p[n - 1] != 0) {
@@ -1152,9 +1113,6 @@
int flip_B)
{
int ret, s;
- MPI_VALIDATE_RET(X != NULL);
- MPI_VALIDATE_RET(A != NULL);
- MPI_VALIDATE_RET(B != NULL);
s = A->s;
if (A->s * B->s * flip_B < 0) {
@@ -1203,8 +1161,6 @@
{
mbedtls_mpi B;
mbedtls_mpi_uint p[1];
- MPI_VALIDATE_RET(X != NULL);
- MPI_VALIDATE_RET(A != NULL);
p[0] = mpi_sint_abs(b);
B.s = TO_SIGN(b);
@@ -1221,8 +1177,6 @@
{
mbedtls_mpi B;
mbedtls_mpi_uint p[1];
- MPI_VALIDATE_RET(X != NULL);
- MPI_VALIDATE_RET(A != NULL);
p[0] = mpi_sint_abs(b);
B.s = TO_SIGN(b);
@@ -1241,9 +1195,6 @@
size_t i, j;
mbedtls_mpi TA, TB;
int result_is_zero = 0;
- MPI_VALIDATE_RET(X != NULL);
- MPI_VALIDATE_RET(A != NULL);
- MPI_VALIDATE_RET(B != NULL);
mbedtls_mpi_init(&TA);
mbedtls_mpi_init(&TB);
@@ -1300,9 +1251,6 @@
*/
int mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b)
{
- MPI_VALIDATE_RET(X != NULL);
- MPI_VALIDATE_RET(A != NULL);
-
size_t n = A->n;
while (n > 0 && A->p[n - 1] == 0) {
--n;
@@ -1448,8 +1396,6 @@
size_t i, n, t, k;
mbedtls_mpi X, Y, Z, T1, T2;
mbedtls_mpi_uint TP2[3];
- MPI_VALIDATE_RET(A != NULL);
- MPI_VALIDATE_RET(B != NULL);
if (mbedtls_mpi_cmp_int(B, 0) == 0) {
return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
@@ -1572,7 +1518,6 @@
{
mbedtls_mpi B;
mbedtls_mpi_uint p[1];
- MPI_VALIDATE_RET(A != NULL);
p[0] = mpi_sint_abs(b);
B.s = TO_SIGN(b);
@@ -1588,9 +1533,6 @@
int mbedtls_mpi_mod_mpi(mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- MPI_VALIDATE_RET(R != NULL);
- MPI_VALIDATE_RET(A != NULL);
- MPI_VALIDATE_RET(B != NULL);
if (mbedtls_mpi_cmp_int(B, 0) < 0) {
return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
@@ -1618,8 +1560,6 @@
{
size_t i;
mbedtls_mpi_uint x, y, z;
- MPI_VALIDATE_RET(r != NULL);
- MPI_VALIDATE_RET(A != NULL);
if (b == 0) {
return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
@@ -1670,103 +1610,11 @@
return 0;
}
-static void mpi_montg_init(mbedtls_mpi_uint *mm, const mbedtls_mpi *N)
-{
- *mm = mbedtls_mpi_core_montmul_init(N->p);
-}
-
-/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36)
- *
- * \param[in,out] A One of the numbers to multiply.
- * It must have at least as many limbs as N
- * (A->n >= N->n), and any limbs beyond n are ignored.
- * On successful completion, A contains the result of
- * the multiplication A * B * R^-1 mod N where
- * R = (2^ciL)^n.
- * \param[in] B One of the numbers to multiply.
- * It must be nonzero and must not have more limbs than N
- * (B->n <= N->n).
- * \param[in] N The modulus. \p N must be odd.
- * \param mm The value calculated by `mpi_montg_init(&mm, N)`.
- * This is -N^-1 mod 2^ciL.
- * \param[in,out] T A bignum for temporary storage.
- * It must be at least twice the limb size of N plus 1
- * (T->n >= 2 * N->n + 1).
- * Its initial content is unused and
- * its final content is indeterminate.
- * It does not get reallocated.
- */
-static void mpi_montmul(mbedtls_mpi *A, const mbedtls_mpi *B,
- const mbedtls_mpi *N, mbedtls_mpi_uint mm,
- mbedtls_mpi *T)
-{
- mbedtls_mpi_core_montmul(A->p, A->p, B->p, B->n, N->p, N->n, mm, T->p);
-}
-
-/*
- * Montgomery reduction: A = A * R^-1 mod N
- *
- * See mpi_montmul() regarding constraints and guarantees on the parameters.
- */
-static void mpi_montred(mbedtls_mpi *A, const mbedtls_mpi *N,
- mbedtls_mpi_uint mm, mbedtls_mpi *T)
-{
- mbedtls_mpi_uint z = 1;
- mbedtls_mpi U;
- U.n = 1;
- U.s = 1;
- U.p = &z;
-
- mpi_montmul(A, &U, N, mm, T);
-}
-
-/**
- * Select an MPI from a table without leaking the index.
- *
- * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
- * reads the entire table in order to avoid leaking the value of idx to an
- * attacker able to observe memory access patterns.
- *
- * \param[out] R Where to write the selected MPI.
- * \param[in] T The table to read from.
- * \param[in] T_size The number of elements in the table.
- * \param[in] idx The index of the element to select;
- * this must satisfy 0 <= idx < T_size.
- *
- * \return \c 0 on success, or a negative error code.
- */
-static int mpi_select(mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx)
-{
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-
- for (size_t i = 0; i < T_size; i++) {
- MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign(R, &T[i],
- (unsigned char) mbedtls_ct_uint_eq(i, idx)));
- }
-cleanup:
- return ret;
-}
-
-/*
- * Sliding-window exponentiation: X = A^E mod N (HAC 14.85)
- */
int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
const mbedtls_mpi *E, const mbedtls_mpi *N,
mbedtls_mpi *prec_RR)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- size_t window_bitsize;
- size_t i, j, nblimbs;
- size_t bufsize, nbits;
- size_t exponent_bits_in_window = 0;
- mbedtls_mpi_uint ei, mm, state;
- mbedtls_mpi RR, T, W[(size_t) 1 << MBEDTLS_MPI_WINDOW_SIZE], WW, Apos;
- int neg;
-
- MPI_VALIDATE_RET(X != NULL);
- MPI_VALIDATE_RET(A != NULL);
- MPI_VALIDATE_RET(E != NULL);
- MPI_VALIDATE_RET(N != NULL);
if (mbedtls_mpi_cmp_int(N, 0) <= 0 || (N->p[0] & 1) == 0) {
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
@@ -1782,261 +1630,88 @@
}
/*
- * Init temps and window size
+ * Ensure that the exponent that we are passing to the core is not NULL.
*/
- mpi_montg_init(&mm, N);
- mbedtls_mpi_init(&RR); mbedtls_mpi_init(&T);
- mbedtls_mpi_init(&Apos);
- mbedtls_mpi_init(&WW);
- memset(W, 0, sizeof(W));
-
- i = mbedtls_mpi_bitlen(E);
-
- window_bitsize = (i > 671) ? 6 : (i > 239) ? 5 :
- (i > 79) ? 4 : (i > 23) ? 3 : 1;
-
-#if (MBEDTLS_MPI_WINDOW_SIZE < 6)
- if (window_bitsize > MBEDTLS_MPI_WINDOW_SIZE) {
- window_bitsize = MBEDTLS_MPI_WINDOW_SIZE;
+ if (E->n == 0) {
+ ret = mbedtls_mpi_lset(X, 1);
+ return ret;
}
-#endif
-
- const size_t w_table_used_size = (size_t) 1 << window_bitsize;
/*
- * This function is not constant-trace: its memory accesses depend on the
- * exponent value. To defend against timing attacks, callers (such as RSA
- * and DHM) should use exponent blinding. However this is not enough if the
- * adversary can find the exponent in a single trace, so this function
- * takes extra precautions against adversaries who can observe memory
- * access patterns.
- *
- * This function performs a series of multiplications by table elements and
- * squarings, and we want the prevent the adversary from finding out which
- * table element was used, and from distinguishing between multiplications
- * and squarings. Firstly, when multiplying by an element of the window
- * W[i], we do a constant-trace table lookup to obfuscate i. This leaves
- * squarings as having a different memory access patterns from other
- * multiplications. So secondly, we put the accumulator in the table as
- * well, and also do a constant-trace table lookup to multiply by the
- * accumulator which is W[x_index].
- *
- * This way, all multiplications take the form of a lookup-and-multiply.
- * The number of lookup-and-multiply operations inside each iteration of
- * the main loop still depends on the bits of the exponent, but since the
- * other operations in the loop don't have an easily recognizable memory
- * trace, an adversary is unlikely to be able to observe the exact
- * patterns.
- *
- * An adversary may still be able to recover the exponent if they can
- * observe both memory accesses and branches. However, branch prediction
- * exploitation typically requires many traces of execution over the same
- * data, which is defeated by randomized blinding.
+ * Allocate working memory for mbedtls_mpi_core_exp_mod()
*/
- const size_t x_index = 0;
- mbedtls_mpi_init(&W[x_index]);
-
- j = N->n + 1;
- /* All W[i] including the accumulator must have at least N->n limbs for
- * the mpi_montmul() and mpi_montred() calls later. Here we ensure that
- * W[1] and the accumulator W[x_index] are large enough. later we'll grow
- * other W[i] to the same length. They must not be shrunk midway through
- * this function!
- */
- MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[x_index], j));
- MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], j));
- MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T, j * 2));
-
- /*
- * Compensate for negative A (and correct at the end)
- */
- neg = (A->s == -1);
- if (neg) {
- MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Apos, A));
- Apos.s = 1;
- A = &Apos;
+ size_t T_limbs = mbedtls_mpi_core_exp_mod_working_limbs(N->n, E->n);
+ mbedtls_mpi_uint *T = (mbedtls_mpi_uint *) mbedtls_calloc(T_limbs, sizeof(mbedtls_mpi_uint));
+ if (T == NULL) {
+ return MBEDTLS_ERR_MPI_ALLOC_FAILED;
}
+ mbedtls_mpi RR;
+ mbedtls_mpi_init(&RR);
+
/*
* If 1st call, pre-compute R^2 mod N
*/
if (prec_RR == NULL || prec_RR->p == NULL) {
- MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&RR, 1));
- MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&RR, N->n * 2 * biL));
- MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&RR, &RR, N));
+ MBEDTLS_MPI_CHK(mbedtls_mpi_core_get_mont_r2_unsafe(&RR, N));
if (prec_RR != NULL) {
- memcpy(prec_RR, &RR, sizeof(mbedtls_mpi));
+ *prec_RR = RR;
}
} else {
- memcpy(&RR, prec_RR, sizeof(mbedtls_mpi));
+ MBEDTLS_MPI_CHK(mbedtls_mpi_grow(prec_RR, N->n));
+ RR = *prec_RR;
}
/*
- * W[1] = A * R^2 * R^-1 mod N = A * R mod N
+ * To preserve constness we need to make a copy of A. Using X for this to
+ * save memory.
*/
- if (mbedtls_mpi_cmp_mpi(A, N) >= 0) {
- MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&W[1], A, N));
- /* This should be a no-op because W[1] is already that large before
- * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow
- * in mpi_montmul() below, so let's make sure. */
- MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], N->n + 1));
- } else {
- MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[1], A));
- }
-
- /* Note that this is safe because W[1] always has at least N->n limbs
- * (it grew above and was preserved by mbedtls_mpi_copy()). */
- mpi_montmul(&W[1], &RR, N, mm, &T);
+ MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
/*
- * W[x_index] = R^2 * R^-1 mod N = R mod N
+ * Compensate for negative A (and correct at the end).
*/
- MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[x_index], &RR));
- mpi_montred(&W[x_index], N, mm, &T);
+ X->s = 1;
-
- if (window_bitsize > 1) {
- /*
- * W[i] = W[1] ^ i
- *
- * The first bit of the sliding window is always 1 and therefore we
- * only need to store the second half of the table.
- *
- * (There are two special elements in the table: W[0] for the
- * accumulator/result and W[1] for A in Montgomery form. Both of these
- * are already set at this point.)
- */
- j = w_table_used_size / 2;
-
- MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[j], N->n + 1));
- MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[j], &W[1]));
-
- for (i = 0; i < window_bitsize - 1; i++) {
- mpi_montmul(&W[j], &W[j], N, mm, &T);
- }
-
- /*
- * W[i] = W[i - 1] * W[1]
- */
- for (i = j + 1; i < w_table_used_size; i++) {
- MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[i], N->n + 1));
- MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[i], &W[i - 1]));
-
- mpi_montmul(&W[i], &W[1], N, mm, &T);
- }
+ /*
+ * Make sure that X is in a form that is safe for consumption by
+ * the core functions.
+ *
+ * - The core functions will not touch the limbs of X above N->n. The
+ * result will be correct if those limbs are 0, which the mod call
+ * ensures.
+ * - Also, X must have at least as many limbs as N for the calls to the
+ * core functions.
+ */
+ if (mbedtls_mpi_cmp_mpi(X, N) >= 0) {
+ MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(X, X, N));
}
+ MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, N->n));
- nblimbs = E->n;
- bufsize = 0;
- nbits = 0;
- state = 0;
-
- while (1) {
- if (bufsize == 0) {
- if (nblimbs == 0) {
- break;
- }
-
- nblimbs--;
-
- bufsize = sizeof(mbedtls_mpi_uint) << 3;
- }
-
- bufsize--;
-
- ei = (E->p[nblimbs] >> bufsize) & 1;
-
- /*
- * skip leading 0s
- */
- if (ei == 0 && state == 0) {
- continue;
- }
-
- if (ei == 0 && state == 1) {
- /*
- * out of window, square W[x_index]
- */
- MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
- mpi_montmul(&W[x_index], &WW, N, mm, &T);
- continue;
- }
-
- /*
- * add ei to current window
- */
- state = 2;
-
- nbits++;
- exponent_bits_in_window |= (ei << (window_bitsize - nbits));
-
- if (nbits == window_bitsize) {
- /*
- * W[x_index] = W[x_index]^window_bitsize R^-1 mod N
- */
- for (i = 0; i < window_bitsize; i++) {
- MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
- x_index));
- mpi_montmul(&W[x_index], &WW, N, mm, &T);
- }
-
- /*
- * W[x_index] = W[x_index] * W[exponent_bits_in_window] R^-1 mod N
- */
- MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
- exponent_bits_in_window));
- mpi_montmul(&W[x_index], &WW, N, mm, &T);
-
- state--;
- nbits = 0;
- exponent_bits_in_window = 0;
- }
+ /*
+ * Convert to and from Montgomery around mbedtls_mpi_core_exp_mod().
+ */
+ {
+ mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N->p);
+ mbedtls_mpi_core_to_mont_rep(X->p, X->p, N->p, N->n, mm, RR.p, T);
+ mbedtls_mpi_core_exp_mod(X->p, X->p, N->p, N->n, E->p, E->n, RR.p, T);
+ mbedtls_mpi_core_from_mont_rep(X->p, X->p, N->p, N->n, mm, T);
}
/*
- * process the remaining bits
+ * Correct for negative A.
*/
- for (i = 0; i < nbits; i++) {
- MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
- mpi_montmul(&W[x_index], &WW, N, mm, &T);
+ if (A->s == -1 && (E->p[0] & 1) != 0) {
+ mbedtls_ct_condition_t is_x_non_zero = mbedtls_mpi_core_check_zero_ct(X->p, X->n);
+ X->s = mbedtls_ct_mpi_sign_if(is_x_non_zero, -1, 1);
- exponent_bits_in_window <<= 1;
-
- if ((exponent_bits_in_window & ((size_t) 1 << window_bitsize)) != 0) {
- MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, 1));
- mpi_montmul(&W[x_index], &WW, N, mm, &T);
- }
+ MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(X, N, X));
}
- /*
- * W[x_index] = A^E * R * R^-1 mod N = A^E mod N
- */
- mpi_montred(&W[x_index], N, mm, &T);
-
- if (neg && E->n != 0 && (E->p[0] & 1) != 0) {
- W[x_index].s = -1;
- MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&W[x_index], N, &W[x_index]));
- }
-
- /*
- * Load the result in the output variable.
- */
- MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, &W[x_index]));
-
cleanup:
- /* The first bit of the sliding window is always 1 and therefore the first
- * half of the table was unused. */
- for (i = w_table_used_size/2; i < w_table_used_size; i++) {
- mbedtls_mpi_free(&W[i]);
- }
-
- mbedtls_mpi_free(&W[x_index]);
- mbedtls_mpi_free(&W[1]);
- mbedtls_mpi_free(&T);
- mbedtls_mpi_free(&Apos);
- mbedtls_mpi_free(&WW);
+ mbedtls_mpi_zeroize_and_free(T, T_limbs);
if (prec_RR == NULL || prec_RR->p == NULL) {
mbedtls_mpi_free(&RR);
@@ -2054,10 +1729,6 @@
size_t lz, lzt;
mbedtls_mpi TA, TB;
- MPI_VALIDATE_RET(G != NULL);
- MPI_VALIDATE_RET(A != NULL);
- MPI_VALIDATE_RET(B != NULL);
-
mbedtls_mpi_init(&TA); mbedtls_mpi_init(&TB);
MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A));
@@ -2168,9 +1839,6 @@
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const size_t limbs = CHARS_TO_LIMBS(size);
- MPI_VALIDATE_RET(X != NULL);
- MPI_VALIDATE_RET(f_rng != NULL);
-
/* Ensure that target MPI has exactly the necessary number of limbs */
MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
if (size == 0) {
@@ -2214,9 +1882,6 @@
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
- MPI_VALIDATE_RET(X != NULL);
- MPI_VALIDATE_RET(A != NULL);
- MPI_VALIDATE_RET(N != NULL);
if (mbedtls_mpi_cmp_int(N, 1) <= 0) {
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
@@ -2372,9 +2037,6 @@
size_t i, j, k, s;
mbedtls_mpi W, R, T, A, RR;
- MPI_VALIDATE_RET(X != NULL);
- MPI_VALIDATE_RET(f_rng != NULL);
-
mbedtls_mpi_init(&W); mbedtls_mpi_init(&R);
mbedtls_mpi_init(&T); mbedtls_mpi_init(&A);
mbedtls_mpi_init(&RR);
@@ -2462,8 +2124,6 @@
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi XX;
- MPI_VALIDATE_RET(X != NULL);
- MPI_VALIDATE_RET(f_rng != NULL);
XX.s = 1;
XX.n = X->n;
@@ -2513,9 +2173,6 @@
mbedtls_mpi_uint r;
mbedtls_mpi Y;
- MPI_VALIDATE_RET(X != NULL);
- MPI_VALIDATE_RET(f_rng != NULL);
-
if (nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS) {
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
}
diff --git a/library/bignum_core.c b/library/bignum_core.c
index dfed60d..1a3e0b9 100644
--- a/library/bignum_core.c
+++ b/library/bignum_core.c
@@ -856,16 +856,17 @@
return c;
}
-mbedtls_mpi_uint mbedtls_mpi_core_check_zero_ct(const mbedtls_mpi_uint *A,
- size_t limbs)
+mbedtls_ct_condition_t mbedtls_mpi_core_check_zero_ct(const mbedtls_mpi_uint *A,
+ size_t limbs)
{
+ volatile const mbedtls_mpi_uint *force_read_A = A;
mbedtls_mpi_uint bits = 0;
for (size_t i = 0; i < limbs; i++) {
- bits |= A[i];
+ bits |= force_read_A[i];
}
- return bits;
+ return mbedtls_ct_bool(bits);
}
void mbedtls_mpi_core_to_mont_rep(mbedtls_mpi_uint *X,
diff --git a/library/bignum_core.h b/library/bignum_core.h
index b56be0a..92c8d47 100644
--- a/library/bignum_core.h
+++ b/library/bignum_core.h
@@ -662,11 +662,11 @@
* \param[in] A The MPI to test.
* \param limbs Number of limbs in \p A.
*
- * \return 0 if `A == 0`
- * non-0 (may be any value) if `A != 0`.
+ * \return MBEDTLS_CT_FALSE if `A == 0`
+ * MBEDTLS_CT_TRUE if `A != 0`.
*/
-mbedtls_mpi_uint mbedtls_mpi_core_check_zero_ct(const mbedtls_mpi_uint *A,
- size_t limbs);
+mbedtls_ct_condition_t mbedtls_mpi_core_check_zero_ct(const mbedtls_mpi_uint *A,
+ size_t limbs);
/**
* \brief Returns the number of limbs of working memory required for
diff --git a/library/debug.c b/library/debug.c
index a9d58e5..c36ed3c 100644
--- a/library/debug.c
+++ b/library/debug.c
@@ -11,7 +11,7 @@
#include "mbedtls/platform.h"
-#include "mbedtls/debug.h"
+#include "debug_internal.h"
#include "mbedtls/error.h"
#include <stdarg.h>
diff --git a/library/debug_internal.h b/library/debug_internal.h
new file mode 100644
index 0000000..4523b46
--- /dev/null
+++ b/library/debug_internal.h
@@ -0,0 +1,172 @@
+/**
+ * \file debug_internal.h
+ *
+ * \brief Internal part of the public "debug.h".
+ */
+/*
+ * Copyright The Mbed TLS Contributors
+ * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+#ifndef MBEDTLS_DEBUG_INTERNAL_H
+#define MBEDTLS_DEBUG_INTERNAL_H
+
+#include "mbedtls/debug.h"
+
+/**
+ * \brief Print a message to the debug output. This function is always used
+ * through the MBEDTLS_SSL_DEBUG_MSG() macro, which supplies the ssl
+ * context, file and line number parameters.
+ *
+ * \param ssl SSL context
+ * \param level error level of the debug message
+ * \param file file the message has occurred in
+ * \param line line number the message has occurred at
+ * \param format format specifier, in printf format
+ * \param ... variables used by the format specifier
+ *
+ * \attention This function is intended for INTERNAL usage within the
+ * library only.
+ */
+void mbedtls_debug_print_msg(const mbedtls_ssl_context *ssl, int level,
+ const char *file, int line,
+ const char *format, ...) MBEDTLS_PRINTF_ATTRIBUTE(5, 6);
+
+/**
+ * \brief Print the return value of a function to the debug output. This
+ * function is always used through the MBEDTLS_SSL_DEBUG_RET() macro,
+ * which supplies the ssl context, file and line number parameters.
+ *
+ * \param ssl SSL context
+ * \param level error level of the debug message
+ * \param file file the error has occurred in
+ * \param line line number the error has occurred in
+ * \param text the name of the function that returned the error
+ * \param ret the return code value
+ *
+ * \attention This function is intended for INTERNAL usage within the
+ * library only.
+ */
+void mbedtls_debug_print_ret(const mbedtls_ssl_context *ssl, int level,
+ const char *file, int line,
+ const char *text, int ret);
+
+/**
+ * \brief Output a buffer of size len bytes to the debug output. This function
+ * is always used through the MBEDTLS_SSL_DEBUG_BUF() macro,
+ * which supplies the ssl context, file and line number parameters.
+ *
+ * \param ssl SSL context
+ * \param level error level of the debug message
+ * \param file file the error has occurred in
+ * \param line line number the error has occurred in
+ * \param text a name or label for the buffer being dumped. Normally the
+ * variable or buffer name
+ * \param buf the buffer to be outputted
+ * \param len length of the buffer
+ *
+ * \attention This function is intended for INTERNAL usage within the
+ * library only.
+ */
+void mbedtls_debug_print_buf(const mbedtls_ssl_context *ssl, int level,
+ const char *file, int line, const char *text,
+ const unsigned char *buf, size_t len);
+
+#if defined(MBEDTLS_BIGNUM_C)
+/**
+ * \brief Print a MPI variable to the debug output. This function is always
+ * used through the MBEDTLS_SSL_DEBUG_MPI() macro, which supplies the
+ * ssl context, file and line number parameters.
+ *
+ * \param ssl SSL context
+ * \param level error level of the debug message
+ * \param file file the error has occurred in
+ * \param line line number the error has occurred in
+ * \param text a name or label for the MPI being output. Normally the
+ * variable name
+ * \param X the MPI variable
+ *
+ * \attention This function is intended for INTERNAL usage within the
+ * library only.
+ */
+void mbedtls_debug_print_mpi(const mbedtls_ssl_context *ssl, int level,
+ const char *file, int line,
+ const char *text, const mbedtls_mpi *X);
+#endif
+
+#if defined(MBEDTLS_ECP_LIGHT)
+/**
+ * \brief Print an ECP point to the debug output. This function is always
+ * used through the MBEDTLS_SSL_DEBUG_ECP() macro, which supplies the
+ * ssl context, file and line number parameters.
+ *
+ * \param ssl SSL context
+ * \param level error level of the debug message
+ * \param file file the error has occurred in
+ * \param line line number the error has occurred in
+ * \param text a name or label for the ECP point being output. Normally the
+ * variable name
+ * \param X the ECP point
+ *
+ * \attention This function is intended for INTERNAL usage within the
+ * library only.
+ */
+void mbedtls_debug_print_ecp(const mbedtls_ssl_context *ssl, int level,
+ const char *file, int line,
+ const char *text, const mbedtls_ecp_point *X);
+#endif
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C) && !defined(MBEDTLS_X509_REMOVE_INFO)
+/**
+ * \brief Print a X.509 certificate structure to the debug output. This
+ * function is always used through the MBEDTLS_SSL_DEBUG_CRT() macro,
+ * which supplies the ssl context, file and line number parameters.
+ *
+ * \param ssl SSL context
+ * \param level error level of the debug message
+ * \param file file the error has occurred in
+ * \param line line number the error has occurred in
+ * \param text a name or label for the certificate being output
+ * \param crt X.509 certificate structure
+ *
+ * \attention This function is intended for INTERNAL usage within the
+ * library only.
+ */
+void mbedtls_debug_print_crt(const mbedtls_ssl_context *ssl, int level,
+ const char *file, int line,
+ const char *text, const mbedtls_x509_crt *crt);
+#endif
+
+/* Note: the MBEDTLS_ECDH_C guard here is mandatory because this debug function
+ only works for the built-in implementation. */
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED) && \
+ defined(MBEDTLS_ECDH_C)
+typedef enum {
+ MBEDTLS_DEBUG_ECDH_Q,
+ MBEDTLS_DEBUG_ECDH_QP,
+ MBEDTLS_DEBUG_ECDH_Z,
+} mbedtls_debug_ecdh_attr;
+
+/**
+ * \brief Print a field of the ECDH structure in the SSL context to the debug
+ * output. This function is always used through the
+ * MBEDTLS_SSL_DEBUG_ECDH() macro, which supplies the ssl context, file
+ * and line number parameters.
+ *
+ * \param ssl SSL context
+ * \param level error level of the debug message
+ * \param file file the error has occurred in
+ * \param line line number the error has occurred in
+ * \param ecdh the ECDH context
+ * \param attr the identifier of the attribute being output
+ *
+ * \attention This function is intended for INTERNAL usage within the
+ * library only.
+ */
+void mbedtls_debug_printf_ecdh(const mbedtls_ssl_context *ssl, int level,
+ const char *file, int line,
+ const mbedtls_ecdh_context *ecdh,
+ mbedtls_debug_ecdh_attr attr);
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED &&
+ MBEDTLS_ECDH_C */
+
+#endif /* MBEDTLS_DEBUG_INTERNAL_H */
diff --git a/library/ecdh.c b/library/ecdh.c
index 52b1617..b276c6a 100644
--- a/library/ecdh.c
+++ b/library/ecdh.c
@@ -144,6 +144,15 @@
#endif
}
+mbedtls_ecp_group_id mbedtls_ecdh_get_grp_id(mbedtls_ecdh_context *ctx)
+{
+#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
+ return ctx->MBEDTLS_PRIVATE(grp).id;
+#else
+ return ctx->MBEDTLS_PRIVATE(grp_id);
+#endif
+}
+
/*
* Initialize context
*/
diff --git a/library/ecp.c b/library/ecp.c
index 758d54b..427059b 100644
--- a/library/ecp.c
+++ b/library/ecp.c
@@ -3302,10 +3302,11 @@
/*
* Write a private key.
*/
+#if !defined MBEDTLS_DEPRECATED_REMOVED
int mbedtls_ecp_write_key(mbedtls_ecp_keypair *key,
unsigned char *buf, size_t buflen)
{
- int ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {
@@ -3332,6 +3333,39 @@
return ret;
}
+#endif /* MBEDTLS_DEPRECATED_REMOVED */
+
+int mbedtls_ecp_write_key_ext(const mbedtls_ecp_keypair *key,
+ size_t *olen, unsigned char *buf, size_t buflen)
+{
+ size_t len = (key->grp.nbits + 7) / 8;
+ if (len > buflen) {
+ /* For robustness, ensure *olen <= buflen even on error. */
+ *olen = 0;
+ return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
+ }
+ *olen = len;
+
+ /* Private key not set */
+ if (key->d.n == 0) {
+ return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+ }
+
+#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
+ if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {
+ return mbedtls_mpi_write_binary_le(&key->d, buf, len);
+ }
+#endif
+
+#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
+ if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {
+ return mbedtls_mpi_write_binary(&key->d, buf, len);
+ }
+#endif
+
+ /* Private key set but no recognized curve type? This shouldn't happen. */
+ return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+}
/*
* Write a public key.
diff --git a/library/ecp_curves.c b/library/ecp_curves.c
index 577e23b..c3cd33f 100644
--- a/library/ecp_curves.c
+++ b/library/ecp_curves.c
@@ -23,12 +23,6 @@
#if !defined(MBEDTLS_ECP_ALT)
-/* Parameter validation macros based on platform_util.h */
-#define ECP_VALIDATE_RET(cond) \
- MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA)
-#define ECP_VALIDATE(cond) \
- MBEDTLS_INTERNAL_VALIDATE(cond)
-
#define ECP_MPI_INIT(_p, _n) { .p = (mbedtls_mpi_uint *) (_p), .s = 1, .n = (_n) }
#define ECP_MPI_INIT_ARRAY(x) \
@@ -52,7 +46,7 @@
defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
/* For these curves, we build the group parameters dynamically. */
#define ECP_LOAD_GROUP
-static mbedtls_mpi_uint mpi_one[] = { 1 };
+static const mbedtls_mpi_uint mpi_one[] = { 1 };
#endif
/*
@@ -4511,7 +4505,7 @@
{
X->s = 1;
X->n = 1;
- X->p = mpi_one;
+ X->p = (mbedtls_mpi_uint *) mpi_one; /* X->p will not be modified so the cast is safe */
}
/*
@@ -4722,7 +4716,6 @@
*/
int mbedtls_ecp_group_load(mbedtls_ecp_group *grp, mbedtls_ecp_group_id id)
{
- ECP_VALIDATE_RET(grp != NULL);
mbedtls_ecp_group_free(grp);
mbedtls_ecp_group_init(grp);
@@ -5318,7 +5311,7 @@
*/
#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,
+static inline int ecp_mod_koblitz(mbedtls_mpi *N, const 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;
@@ -5332,7 +5325,7 @@
/* Init R */
R.s = 1;
- R.p = Rp;
+ R.p = (mbedtls_mpi_uint *) Rp; /* R.p will not be modified so the cast is safe */
R.n = P_KOBLITZ_R;
/* Common setup for M */
@@ -5403,7 +5396,7 @@
*/
static int ecp_mod_p192k1(mbedtls_mpi *N)
{
- static mbedtls_mpi_uint Rp[] = {
+ static const mbedtls_mpi_uint Rp[] = {
MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00)
};
@@ -5420,7 +5413,7 @@
*/
static int ecp_mod_p224k1(mbedtls_mpi *N)
{
- static mbedtls_mpi_uint Rp[] = {
+ static const mbedtls_mpi_uint Rp[] = {
MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00)
};
@@ -5442,7 +5435,7 @@
*/
static int ecp_mod_p256k1(mbedtls_mpi *N)
{
- static mbedtls_mpi_uint Rp[] = {
+ static const mbedtls_mpi_uint Rp[] = {
MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00,
0x00)
};
diff --git a/library/ecp_curves_new.c b/library/ecp_curves_new.c
index 4ee0f58..035b23a 100644
--- a/library/ecp_curves_new.c
+++ b/library/ecp_curves_new.c
@@ -28,12 +28,6 @@
#if !defined(MBEDTLS_ECP_ALT)
-/* Parameter validation macros based on platform_util.h */
-#define ECP_VALIDATE_RET(cond) \
- MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA)
-#define ECP_VALIDATE(cond) \
- MBEDTLS_INTERNAL_VALIDATE(cond)
-
#define ECP_MPI_INIT(_p, _n) { .p = (mbedtls_mpi_uint *) (_p), .s = 1, .n = (_n) }
#define ECP_MPI_INIT_ARRAY(x) \
@@ -4764,7 +4758,6 @@
*/
int mbedtls_ecp_group_load(mbedtls_ecp_group *grp, mbedtls_ecp_group_id id)
{
- ECP_VALIDATE_RET(grp != NULL);
mbedtls_ecp_group_free(grp);
mbedtls_ecp_group_init(grp);
diff --git a/library/entropy_poll.c b/library/entropy_poll.c
index bd21e2d..794ee03 100644
--- a/library/entropy_poll.c
+++ b/library/entropy_poll.c
@@ -5,7 +5,7 @@
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
-#if defined(__linux__) && !defined(_GNU_SOURCE)
+#if defined(__linux__) || defined(__midipix__) && !defined(_GNU_SOURCE)
/* Ensure that syscall() is available even when compiling with -std=c99 */
#define _GNU_SOURCE
#endif
diff --git a/library/gcm.c b/library/gcm.c
index c677ca4..90c1d1d 100644
--- a/library/gcm.c
+++ b/library/gcm.c
@@ -41,6 +41,12 @@
#if !defined(MBEDTLS_GCM_ALT)
+/* Used to select the acceleration mechanism */
+#define MBEDTLS_GCM_ACC_SMALLTABLE 0
+#define MBEDTLS_GCM_ACC_LARGETABLE 1
+#define MBEDTLS_GCM_ACC_AESNI 2
+#define MBEDTLS_GCM_ACC_AESCE 3
+
/*
* Initialize a context
*/
@@ -49,6 +55,39 @@
memset(ctx, 0, sizeof(mbedtls_gcm_context));
}
+static inline void gcm_set_acceleration(mbedtls_gcm_context *ctx)
+{
+#if defined(MBEDTLS_GCM_LARGE_TABLE)
+ ctx->acceleration = MBEDTLS_GCM_ACC_LARGETABLE;
+#else
+ ctx->acceleration = MBEDTLS_GCM_ACC_SMALLTABLE;
+#endif
+
+#if defined(MBEDTLS_AESNI_HAVE_CODE)
+ /* With CLMUL support, we need only h, not the rest of the table */
+ if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
+ ctx->acceleration = MBEDTLS_GCM_ACC_AESNI;
+ }
+#endif
+
+#if defined(MBEDTLS_AESCE_HAVE_CODE)
+ if (MBEDTLS_AESCE_HAS_SUPPORT()) {
+ ctx->acceleration = MBEDTLS_GCM_ACC_AESCE;
+ }
+#endif
+}
+
+static inline void gcm_gen_table_rightshift(uint64_t dst[2], const uint64_t src[2])
+{
+ uint8_t *u8Dst = (uint8_t *) dst;
+ uint8_t *u8Src = (uint8_t *) src;
+
+ MBEDTLS_PUT_UINT64_BE(MBEDTLS_GET_UINT64_BE(&src[1], 0) >> 1, &dst[1], 0);
+ u8Dst[8] |= (u8Src[7] & 0x01) << 7;
+ MBEDTLS_PUT_UINT64_BE(MBEDTLS_GET_UINT64_BE(&src[0], 0) >> 1, &dst[0], 0);
+ u8Dst[0] ^= (u8Src[15] & 0x01) ? 0xE1 : 0;
+}
+
/*
* Precompute small multiples of H, that is set
* HH[i] || HL[i] = H times i,
@@ -60,11 +99,8 @@
static int gcm_gen_table(mbedtls_gcm_context *ctx)
{
int ret, i, j;
- uint64_t hi, lo;
- uint64_t vl, vh;
- unsigned char h[16];
-
- memset(h, 0, 16);
+ uint64_t u64h[2] = { 0 };
+ uint8_t *h = (uint8_t *) u64h;
#if defined(MBEDTLS_BLOCK_CIPHER_C)
ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, h, h);
@@ -76,53 +112,48 @@
return ret;
}
- /* pack h as two 64-bits ints, big-endian */
- hi = MBEDTLS_GET_UINT32_BE(h, 0);
- lo = MBEDTLS_GET_UINT32_BE(h, 4);
- vh = (uint64_t) hi << 32 | lo;
+ gcm_set_acceleration(ctx);
- hi = MBEDTLS_GET_UINT32_BE(h, 8);
- lo = MBEDTLS_GET_UINT32_BE(h, 12);
- vl = (uint64_t) hi << 32 | lo;
+ /* MBEDTLS_GCM_HTABLE_SIZE/2 = 1000 corresponds to 1 in GF(2^128) */
+ ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2][0] = u64h[0];
+ ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2][1] = u64h[1];
- /* 8 = 1000 corresponds to 1 in GF(2^128) */
- ctx->HL[8] = vl;
- ctx->HH[8] = vh;
-
+ switch (ctx->acceleration) {
#if defined(MBEDTLS_AESNI_HAVE_CODE)
- /* With CLMUL support, we need only h, not the rest of the table */
- if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
- return 0;
- }
+ case MBEDTLS_GCM_ACC_AESNI:
+ return 0;
#endif
#if defined(MBEDTLS_AESCE_HAVE_CODE)
- if (MBEDTLS_AESCE_HAS_SUPPORT()) {
- return 0;
- }
+ case MBEDTLS_GCM_ACC_AESCE:
+ return 0;
#endif
- /* 0 corresponds to 0 in GF(2^128) */
- ctx->HH[0] = 0;
- ctx->HL[0] = 0;
+ default:
+ /* 0 corresponds to 0 in GF(2^128) */
+ ctx->H[0][0] = 0;
+ ctx->H[0][1] = 0;
- for (i = 4; i > 0; i >>= 1) {
- uint32_t T = (vl & 1) * 0xe1000000U;
- vl = (vh << 63) | (vl >> 1);
- vh = (vh >> 1) ^ ((uint64_t) T << 32);
+ for (i = MBEDTLS_GCM_HTABLE_SIZE/4; i > 0; i >>= 1) {
+ gcm_gen_table_rightshift(ctx->H[i], ctx->H[i*2]);
+ }
- ctx->HL[i] = vl;
- ctx->HH[i] = vh;
- }
+#if !defined(MBEDTLS_GCM_LARGE_TABLE)
+ /* pack elements of H as 64-bits ints, big-endian */
+ for (i = MBEDTLS_GCM_HTABLE_SIZE/2; i > 0; i >>= 1) {
+ MBEDTLS_PUT_UINT64_BE(ctx->H[i][0], &ctx->H[i][0], 0);
+ MBEDTLS_PUT_UINT64_BE(ctx->H[i][1], &ctx->H[i][1], 0);
+ }
+#endif
- for (i = 2; i <= 8; i *= 2) {
- uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
- vh = *HiH;
- vl = *HiL;
- for (j = 1; j < i; j++) {
- HiH[j] = vh ^ ctx->HH[j];
- HiL[j] = vl ^ ctx->HL[j];
- }
+ for (i = 2; i < MBEDTLS_GCM_HTABLE_SIZE; i <<= 1) {
+ for (j = 1; j < i; j++) {
+ mbedtls_xor_no_simd((unsigned char *) ctx->H[i+j],
+ (unsigned char *) ctx->H[i],
+ (unsigned char *) ctx->H[j],
+ 16);
+ }
+ }
}
return 0;
@@ -181,6 +212,80 @@
return 0;
}
+#if defined(MBEDTLS_GCM_LARGE_TABLE)
+static const uint16_t last8[256] = {
+ 0x0000, 0xc201, 0x8403, 0x4602, 0x0807, 0xca06, 0x8c04, 0x4e05,
+ 0x100e, 0xd20f, 0x940d, 0x560c, 0x1809, 0xda08, 0x9c0a, 0x5e0b,
+ 0x201c, 0xe21d, 0xa41f, 0x661e, 0x281b, 0xea1a, 0xac18, 0x6e19,
+ 0x3012, 0xf213, 0xb411, 0x7610, 0x3815, 0xfa14, 0xbc16, 0x7e17,
+ 0x4038, 0x8239, 0xc43b, 0x063a, 0x483f, 0x8a3e, 0xcc3c, 0x0e3d,
+ 0x5036, 0x9237, 0xd435, 0x1634, 0x5831, 0x9a30, 0xdc32, 0x1e33,
+ 0x6024, 0xa225, 0xe427, 0x2626, 0x6823, 0xaa22, 0xec20, 0x2e21,
+ 0x702a, 0xb22b, 0xf429, 0x3628, 0x782d, 0xba2c, 0xfc2e, 0x3e2f,
+ 0x8070, 0x4271, 0x0473, 0xc672, 0x8877, 0x4a76, 0x0c74, 0xce75,
+ 0x907e, 0x527f, 0x147d, 0xd67c, 0x9879, 0x5a78, 0x1c7a, 0xde7b,
+ 0xa06c, 0x626d, 0x246f, 0xe66e, 0xa86b, 0x6a6a, 0x2c68, 0xee69,
+ 0xb062, 0x7263, 0x3461, 0xf660, 0xb865, 0x7a64, 0x3c66, 0xfe67,
+ 0xc048, 0x0249, 0x444b, 0x864a, 0xc84f, 0x0a4e, 0x4c4c, 0x8e4d,
+ 0xd046, 0x1247, 0x5445, 0x9644, 0xd841, 0x1a40, 0x5c42, 0x9e43,
+ 0xe054, 0x2255, 0x6457, 0xa656, 0xe853, 0x2a52, 0x6c50, 0xae51,
+ 0xf05a, 0x325b, 0x7459, 0xb658, 0xf85d, 0x3a5c, 0x7c5e, 0xbe5f,
+ 0x00e1, 0xc2e0, 0x84e2, 0x46e3, 0x08e6, 0xcae7, 0x8ce5, 0x4ee4,
+ 0x10ef, 0xd2ee, 0x94ec, 0x56ed, 0x18e8, 0xdae9, 0x9ceb, 0x5eea,
+ 0x20fd, 0xe2fc, 0xa4fe, 0x66ff, 0x28fa, 0xeafb, 0xacf9, 0x6ef8,
+ 0x30f3, 0xf2f2, 0xb4f0, 0x76f1, 0x38f4, 0xfaf5, 0xbcf7, 0x7ef6,
+ 0x40d9, 0x82d8, 0xc4da, 0x06db, 0x48de, 0x8adf, 0xccdd, 0x0edc,
+ 0x50d7, 0x92d6, 0xd4d4, 0x16d5, 0x58d0, 0x9ad1, 0xdcd3, 0x1ed2,
+ 0x60c5, 0xa2c4, 0xe4c6, 0x26c7, 0x68c2, 0xaac3, 0xecc1, 0x2ec0,
+ 0x70cb, 0xb2ca, 0xf4c8, 0x36c9, 0x78cc, 0xbacd, 0xfccf, 0x3ece,
+ 0x8091, 0x4290, 0x0492, 0xc693, 0x8896, 0x4a97, 0x0c95, 0xce94,
+ 0x909f, 0x529e, 0x149c, 0xd69d, 0x9898, 0x5a99, 0x1c9b, 0xde9a,
+ 0xa08d, 0x628c, 0x248e, 0xe68f, 0xa88a, 0x6a8b, 0x2c89, 0xee88,
+ 0xb083, 0x7282, 0x3480, 0xf681, 0xb884, 0x7a85, 0x3c87, 0xfe86,
+ 0xc0a9, 0x02a8, 0x44aa, 0x86ab, 0xc8ae, 0x0aaf, 0x4cad, 0x8eac,
+ 0xd0a7, 0x12a6, 0x54a4, 0x96a5, 0xd8a0, 0x1aa1, 0x5ca3, 0x9ea2,
+ 0xe0b5, 0x22b4, 0x64b6, 0xa6b7, 0xe8b2, 0x2ab3, 0x6cb1, 0xaeb0,
+ 0xf0bb, 0x32ba, 0x74b8, 0xb6b9, 0xf8bc, 0x3abd, 0x7cbf, 0xbebe
+};
+
+static void gcm_mult_largetable(uint8_t *output, const uint8_t *x, uint64_t H[256][2])
+{
+ int i;
+ uint64_t u64z[2];
+ uint16_t *u16z = (uint16_t *) u64z;
+ uint8_t *u8z = (uint8_t *) u64z;
+ uint8_t rem;
+
+ u64z[0] = 0;
+ u64z[1] = 0;
+
+ if (MBEDTLS_IS_BIG_ENDIAN) {
+ for (i = 15; i > 0; i--) {
+ mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[x[i]], 16);
+ rem = u8z[15];
+
+ u64z[1] >>= 8;
+ u8z[8] = u8z[7];
+ u64z[0] >>= 8;
+
+ u16z[0] ^= MBEDTLS_GET_UINT16_LE(&last8[rem], 0);
+ }
+ } else {
+ for (i = 15; i > 0; i--) {
+ mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[x[i]], 16);
+ rem = u8z[15];
+
+ u64z[1] <<= 8;
+ u8z[8] = u8z[7];
+ u64z[0] <<= 8;
+
+ u16z[0] ^= last8[rem];
+ }
+ }
+
+ mbedtls_xor_no_simd(output, u8z, (uint8_t *) H[x[0]], 16);
+}
+#else
/*
* Shoup's method for multiplication use this table with
* last4[x] = x times P^128
@@ -194,6 +299,47 @@
0x9180, 0x8da0, 0xa9c0, 0xb5e0
};
+static void gcm_mult_smalltable(uint8_t *output, const uint8_t *x, uint64_t H[16][2])
+{
+ int i = 0;
+ unsigned char lo, hi, rem;
+ uint64_t u64z[2];
+ const uint64_t *pu64z = NULL;
+ uint8_t *u8z = (uint8_t *) u64z;
+
+ lo = x[15] & 0xf;
+ hi = (x[15] >> 4) & 0xf;
+
+ pu64z = H[lo];
+
+ rem = (unsigned char) pu64z[1] & 0xf;
+ u64z[1] = (pu64z[0] << 60) | (pu64z[1] >> 4);
+ u64z[0] = (pu64z[0] >> 4);
+ u64z[0] ^= (uint64_t) last4[rem] << 48;
+ mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[hi], 16);
+
+ for (i = 14; i >= 0; i--) {
+ lo = x[i] & 0xf;
+ hi = (x[i] >> 4) & 0xf;
+
+ rem = (unsigned char) u64z[1] & 0xf;
+ u64z[1] = (u64z[0] << 60) | (u64z[1] >> 4);
+ u64z[0] = (u64z[0] >> 4);
+ u64z[0] ^= (uint64_t) last4[rem] << 48;
+ mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[lo], 16);
+
+ rem = (unsigned char) u64z[1] & 0xf;
+ u64z[1] = (u64z[0] << 60) | (u64z[1] >> 4);
+ u64z[0] = (u64z[0] >> 4);
+ u64z[0] ^= (uint64_t) last4[rem] << 48;
+ mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[hi], 16);
+ }
+
+ MBEDTLS_PUT_UINT64_BE(u64z[0], output, 0);
+ MBEDTLS_PUT_UINT64_BE(u64z[1], output, 8);
+}
+#endif
+
/*
* Sets output to x times H using the precomputed tables.
* x and output are seen as elements of GF(2^128) as in [MGV].
@@ -201,71 +347,31 @@
static void gcm_mult(mbedtls_gcm_context *ctx, const unsigned char x[16],
unsigned char output[16])
{
- int i = 0;
- unsigned char lo, hi, rem;
- uint64_t zh, zl;
-
+ switch (ctx->acceleration) {
#if defined(MBEDTLS_AESNI_HAVE_CODE)
- 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);
- MBEDTLS_PUT_UINT32_BE(ctx->HL[8], h, 12);
-
- mbedtls_aesni_gcm_mult(output, x, h);
- return;
- }
-#endif /* MBEDTLS_AESNI_HAVE_CODE */
-
-#if defined(MBEDTLS_AESCE_HAVE_CODE)
- 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;
- }
+ case MBEDTLS_GCM_ACC_AESNI:
+ mbedtls_aesni_gcm_mult(output, x, (uint8_t *) ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2]);
+ break;
#endif
- lo = x[15] & 0xf;
+#if defined(MBEDTLS_AESCE_HAVE_CODE)
+ case MBEDTLS_GCM_ACC_AESCE:
+ mbedtls_aesce_gcm_mult(output, x, (uint8_t *) ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2]);
+ break;
+#endif
- zh = ctx->HH[lo];
- zl = ctx->HL[lo];
-
- for (i = 15; i >= 0; i--) {
- lo = x[i] & 0xf;
- hi = (x[i] >> 4) & 0xf;
-
- if (i != 15) {
- rem = (unsigned char) zl & 0xf;
- zl = (zh << 60) | (zl >> 4);
- zh = (zh >> 4);
- zh ^= (uint64_t) last4[rem] << 48;
- zh ^= ctx->HH[lo];
- zl ^= ctx->HL[lo];
-
- }
-
- rem = (unsigned char) zl & 0xf;
- zl = (zh << 60) | (zl >> 4);
- zh = (zh >> 4);
- zh ^= (uint64_t) last4[rem] << 48;
- zh ^= ctx->HH[hi];
- zl ^= ctx->HL[hi];
+#if defined(MBEDTLS_GCM_LARGE_TABLE)
+ case MBEDTLS_GCM_ACC_LARGETABLE:
+ gcm_mult_largetable(output, x, ctx->H);
+ break;
+#else
+ case MBEDTLS_GCM_ACC_SMALLTABLE:
+ gcm_mult_smalltable(output, x, ctx->H);
+ break;
+#endif
}
- MBEDTLS_PUT_UINT32_BE(zh >> 32, output, 0);
- MBEDTLS_PUT_UINT32_BE(zh, output, 4);
- MBEDTLS_PUT_UINT32_BE(zl >> 32, output, 8);
- MBEDTLS_PUT_UINT32_BE(zl, output, 12);
+ return;
}
int mbedtls_gcm_starts(mbedtls_gcm_context *ctx,
@@ -354,9 +460,17 @@
{
const unsigned char *p;
size_t use_len, offset;
+ uint64_t new_add_len;
- /* IV is limited to 2^64 bits, so 2^61 bytes */
- if ((uint64_t) add_len >> 61 != 0) {
+ /* AD is limited to 2^64 bits, ie 2^61 bytes
+ * Also check for possible overflow */
+#if SIZE_MAX > 0xFFFFFFFFFFFFFFFFULL
+ if (add_len > 0xFFFFFFFFFFFFFFFFULL) {
+ return MBEDTLS_ERR_GCM_BAD_INPUT;
+ }
+#endif
+ new_add_len = ctx->add_len + (uint64_t) add_len;
+ if (new_add_len < ctx->add_len || new_add_len >> 61 != 0) {
return MBEDTLS_ERR_GCM_BAD_INPUT;
}
@@ -539,6 +653,9 @@
(void) output_size;
*output_length = 0;
+ /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
+ * and AD length is restricted to 2^64 bits, ie 2^61 bytes so neither of
+ * the two multiplications would overflow. */
orig_len = ctx->len * 8;
orig_add_len = ctx->add_len * 8;
diff --git a/library/lms.c b/library/lms.c
index 08fe753..8d3cae0 100644
--- a/library/lms.c
+++ b/library/lms.c
@@ -65,7 +65,8 @@
#define H_TREE_HEIGHT_MAX 10
#define MERKLE_TREE_NODE_AM(type) ((size_t) 1 << (MBEDTLS_LMS_H_TREE_HEIGHT(type) + 1u))
#define MERKLE_TREE_LEAF_NODE_AM(type) ((size_t) 1 << MBEDTLS_LMS_H_TREE_HEIGHT(type))
-#define MERKLE_TREE_INTERNAL_NODE_AM(type) ((size_t) 1 << MBEDTLS_LMS_H_TREE_HEIGHT(type))
+#define MERKLE_TREE_INTERNAL_NODE_AM(type) ((unsigned int) \
+ (1u << MBEDTLS_LMS_H_TREE_HEIGHT(type)))
#define D_CONST_LEN (2)
static const unsigned char D_LEAF_CONSTANT_BYTES[D_CONST_LEN] = { 0x82, 0x82 };
diff --git a/library/oid.c b/library/oid.c
index d30a464..1d6b1eb 100644
--- a/library/oid.c
+++ b/library/oid.c
@@ -684,6 +684,18 @@
MBEDTLS_CIPHER_DES_EDE3_CBC,
},
{
+ OID_DESCRIPTOR(MBEDTLS_OID_AES_128_CBC, "aes128-cbc", "AES128-CBC"),
+ MBEDTLS_CIPHER_AES_128_CBC,
+ },
+ {
+ OID_DESCRIPTOR(MBEDTLS_OID_AES_192_CBC, "aes192-cbc", "AES192-CBC"),
+ MBEDTLS_CIPHER_AES_192_CBC,
+ },
+ {
+ OID_DESCRIPTOR(MBEDTLS_OID_AES_256_CBC, "aes256-cbc", "AES256-CBC"),
+ MBEDTLS_CIPHER_AES_256_CBC,
+ },
+ {
NULL_OID_DESCRIPTOR,
MBEDTLS_CIPHER_NONE,
},
diff --git a/library/pem.c b/library/pem.c
index 539134c..0fee5df 100644
--- a/library/pem.c
+++ b/library/pem.c
@@ -240,6 +240,29 @@
}
#endif /* MBEDTLS_AES_C */
+#if defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C)
+static int pem_check_pkcs_padding(unsigned char *input, size_t input_len, size_t *data_len)
+{
+ /* input_len > 0 is guaranteed by mbedtls_pem_read_buffer(). */
+ size_t pad_len = input[input_len - 1];
+ size_t i;
+
+ if (pad_len > input_len) {
+ return MBEDTLS_ERR_PEM_PASSWORD_MISMATCH;
+ }
+
+ *data_len = input_len - pad_len;
+
+ for (i = *data_len; i < input_len; i++) {
+ if (input[i] != pad_len) {
+ return MBEDTLS_ERR_PEM_PASSWORD_MISMATCH;
+ }
+ }
+
+ return 0;
+}
+#endif /* MBEDTLS_DES_C || MBEDTLS_AES_C */
+
#endif /* PEM_RFC1421 */
int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const char *footer,
@@ -389,6 +412,10 @@
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PEM_INVALID_DATA, ret);
}
+ if (len == 0) {
+ return MBEDTLS_ERR_PEM_BAD_INPUT_DATA;
+ }
+
if ((buf = mbedtls_calloc(1, len)) == NULL) {
return MBEDTLS_ERR_PEM_ALLOC_FAILED;
}
@@ -426,20 +453,20 @@
#endif /* MBEDTLS_AES_C */
if (ret != 0) {
- mbedtls_free(buf);
+ mbedtls_zeroize_and_free(buf, len);
return ret;
}
- /*
- * The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3
- * length bytes (allow 4 to be sure) in all known use cases.
- *
- * Use that as a heuristic to try to detect password mismatches.
- */
- if (len <= 2 || buf[0] != 0x30 || buf[1] > 0x83) {
+ /* Check PKCS padding and update data length based on padding info.
+ * This can be used to detect invalid padding data and password
+ * mismatches. */
+ size_t unpadded_len;
+ ret = pem_check_pkcs_padding(buf, len, &unpadded_len);
+ if (ret != 0) {
mbedtls_zeroize_and_free(buf, len);
- return MBEDTLS_ERR_PEM_PASSWORD_MISMATCH;
+ return ret;
}
+ len = unpadded_len;
#else
mbedtls_zeroize_and_free(buf, len);
return MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE;
diff --git a/library/pk.c b/library/pk.c
index 9261837..003ef4a 100644
--- a/library/pk.c
+++ b/library/pk.c
@@ -18,10 +18,8 @@
#if defined(MBEDTLS_RSA_C)
#include "mbedtls/rsa.h"
-#if defined(MBEDTLS_PKCS1_V21) && !defined(MBEDTLS_USE_PSA_CRYPTO)
#include "rsa_internal.h"
#endif
-#endif
#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
#include "mbedtls/ecp.h"
#endif
@@ -29,7 +27,7 @@
#include "mbedtls/ecdsa.h"
#endif
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
#include "psa_util_internal.h"
#include "mbedtls/psa_util.h"
#endif
@@ -378,6 +376,482 @@
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+#if defined(MBEDTLS_RSA_C)
+static psa_algorithm_t psa_algorithm_for_rsa(const mbedtls_rsa_context *rsa,
+ int want_crypt)
+{
+ if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) {
+ if (want_crypt) {
+ mbedtls_md_type_t md_type = (mbedtls_md_type_t) mbedtls_rsa_get_md_alg(rsa);
+ return PSA_ALG_RSA_OAEP(mbedtls_md_psa_alg_from_type(md_type));
+ } else {
+ return PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_ANY_HASH);
+ }
+ } else {
+ if (want_crypt) {
+ return PSA_ALG_RSA_PKCS1V15_CRYPT;
+ } else {
+ return PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH);
+ }
+ }
+}
+#endif /* MBEDTLS_RSA_C */
+
+int mbedtls_pk_get_psa_attributes(const mbedtls_pk_context *pk,
+ psa_key_usage_t usage,
+ psa_key_attributes_t *attributes)
+{
+ mbedtls_pk_type_t pk_type = mbedtls_pk_get_type(pk);
+
+ psa_key_usage_t more_usage = usage;
+ if (usage == PSA_KEY_USAGE_SIGN_MESSAGE) {
+ more_usage |= PSA_KEY_USAGE_VERIFY_MESSAGE;
+ } else if (usage == PSA_KEY_USAGE_SIGN_HASH) {
+ more_usage |= PSA_KEY_USAGE_VERIFY_HASH;
+ } else if (usage == PSA_KEY_USAGE_DECRYPT) {
+ more_usage |= PSA_KEY_USAGE_ENCRYPT;
+ }
+ more_usage |= PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY;
+
+ int want_private = !(usage == PSA_KEY_USAGE_VERIFY_MESSAGE ||
+ usage == PSA_KEY_USAGE_VERIFY_HASH ||
+ usage == PSA_KEY_USAGE_ENCRYPT);
+
+ switch (pk_type) {
+#if defined(MBEDTLS_RSA_C)
+ case MBEDTLS_PK_RSA:
+ {
+ int want_crypt = 0; /* 0: sign/verify; 1: encrypt/decrypt */
+ switch (usage) {
+ case PSA_KEY_USAGE_SIGN_MESSAGE:
+ case PSA_KEY_USAGE_SIGN_HASH:
+ case PSA_KEY_USAGE_VERIFY_MESSAGE:
+ case PSA_KEY_USAGE_VERIFY_HASH:
+ /* Nothing to do. */
+ break;
+ case PSA_KEY_USAGE_DECRYPT:
+ case PSA_KEY_USAGE_ENCRYPT:
+ want_crypt = 1;
+ break;
+ default:
+ return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+ }
+ /* Detect the presence of a private key in a way that works both
+ * in CRT and non-CRT configurations. */
+ mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*pk);
+ int has_private = (mbedtls_rsa_check_privkey(rsa) == 0);
+ if (want_private && !has_private) {
+ return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+ }
+ psa_set_key_type(attributes, (want_private ?
+ PSA_KEY_TYPE_RSA_KEY_PAIR :
+ PSA_KEY_TYPE_RSA_PUBLIC_KEY));
+ psa_set_key_bits(attributes, mbedtls_pk_get_bitlen(pk));
+ psa_set_key_algorithm(attributes,
+ psa_algorithm_for_rsa(rsa, want_crypt));
+ break;
+ }
+#endif /* MBEDTLS_RSA_C */
+
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+ case MBEDTLS_PK_ECKEY:
+ case MBEDTLS_PK_ECKEY_DH:
+ case MBEDTLS_PK_ECDSA:
+ {
+ int sign_ok = (pk_type != MBEDTLS_PK_ECKEY_DH);
+ int derive_ok = (pk_type != MBEDTLS_PK_ECDSA);
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+ psa_ecc_family_t family = pk->ec_family;
+ size_t bits = pk->ec_bits;
+ int has_private = 0;
+ if (pk->priv_id != MBEDTLS_SVC_KEY_ID_INIT) {
+ has_private = 1;
+ }
+#else
+ const mbedtls_ecp_keypair *ec = mbedtls_pk_ec_ro(*pk);
+ int has_private = (ec->d.n != 0);
+ size_t bits = 0;
+ psa_ecc_family_t family =
+ mbedtls_ecc_group_to_psa(ec->grp.id, &bits);
+#endif
+ psa_algorithm_t alg = 0;
+ switch (usage) {
+ case PSA_KEY_USAGE_SIGN_MESSAGE:
+ case PSA_KEY_USAGE_SIGN_HASH:
+ case PSA_KEY_USAGE_VERIFY_MESSAGE:
+ case PSA_KEY_USAGE_VERIFY_HASH:
+ if (!sign_ok) {
+ return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+ }
+#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
+ alg = PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_ANY_HASH);
+#else
+ alg = PSA_ALG_ECDSA(PSA_ALG_ANY_HASH);
+#endif
+ break;
+ case PSA_KEY_USAGE_DERIVE:
+ alg = PSA_ALG_ECDH;
+ if (!derive_ok) {
+ return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+ }
+ break;
+ default:
+ return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+ }
+ if (want_private && !has_private) {
+ return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+ }
+ psa_set_key_type(attributes, (want_private ?
+ PSA_KEY_TYPE_ECC_KEY_PAIR(family) :
+ PSA_KEY_TYPE_ECC_PUBLIC_KEY(family)));
+ psa_set_key_bits(attributes, bits);
+ psa_set_key_algorithm(attributes, alg);
+ break;
+ }
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
+
+#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
+ case MBEDTLS_PK_RSA_ALT:
+ return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ case MBEDTLS_PK_OPAQUE:
+ {
+ psa_key_attributes_t old_attributes = PSA_KEY_ATTRIBUTES_INIT;
+ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+ status = psa_get_key_attributes(pk->priv_id, &old_attributes);
+ if (status != PSA_SUCCESS) {
+ return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+ }
+ psa_key_type_t old_type = psa_get_key_type(&old_attributes);
+ switch (usage) {
+ case PSA_KEY_USAGE_SIGN_MESSAGE:
+ case PSA_KEY_USAGE_SIGN_HASH:
+ case PSA_KEY_USAGE_VERIFY_MESSAGE:
+ case PSA_KEY_USAGE_VERIFY_HASH:
+ if (!(PSA_KEY_TYPE_IS_ECC_KEY_PAIR(old_type) ||
+ old_type == PSA_KEY_TYPE_RSA_KEY_PAIR)) {
+ return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+ }
+ break;
+ case PSA_KEY_USAGE_DECRYPT:
+ case PSA_KEY_USAGE_ENCRYPT:
+ if (old_type != PSA_KEY_TYPE_RSA_KEY_PAIR) {
+ return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+ }
+ break;
+ case PSA_KEY_USAGE_DERIVE:
+ if (!(PSA_KEY_TYPE_IS_ECC_KEY_PAIR(old_type))) {
+ return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+ }
+ break;
+ default:
+ return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+ }
+ psa_key_type_t new_type = old_type;
+ /* Opaque keys are always key pairs, so we don't need a check
+ * on the input if the required usage is private. We just need
+ * to adjust the type correctly if the required usage is public. */
+ if (!want_private) {
+ new_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(new_type);
+ }
+ more_usage = psa_get_key_usage_flags(&old_attributes);
+ if ((usage & more_usage) == 0) {
+ return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+ }
+ psa_set_key_type(attributes, new_type);
+ psa_set_key_bits(attributes, psa_get_key_bits(&old_attributes));
+ psa_set_key_algorithm(attributes, psa_get_key_algorithm(&old_attributes));
+ break;
+ }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+ default:
+ return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+ }
+
+ psa_set_key_usage_flags(attributes, more_usage);
+ psa_set_key_enrollment_algorithm(attributes, PSA_ALG_NONE);
+
+ return 0;
+}
+
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) || defined(MBEDTLS_USE_PSA_CRYPTO)
+static psa_status_t export_import_into_psa(mbedtls_svc_key_id_t old_key_id,
+ const psa_key_attributes_t *attributes,
+ mbedtls_svc_key_id_t *new_key_id)
+{
+ unsigned char key_buffer[PSA_EXPORT_KEY_PAIR_MAX_SIZE];
+ size_t key_length = 0;
+ psa_status_t status = psa_export_key(old_key_id,
+ key_buffer, sizeof(key_buffer),
+ &key_length);
+ if (status != PSA_SUCCESS) {
+ return status;
+ }
+ status = psa_import_key(attributes, key_buffer, key_length, new_key_id);
+ mbedtls_platform_zeroize(key_buffer, key_length);
+ return status;
+}
+
+static int copy_into_psa(mbedtls_svc_key_id_t old_key_id,
+ const psa_key_attributes_t *attributes,
+ mbedtls_svc_key_id_t *new_key_id)
+{
+ /* Normally, we prefer copying: it's more efficient and works even
+ * for non-exportable keys. */
+ psa_status_t status = psa_copy_key(old_key_id, attributes, new_key_id);
+ if (status == PSA_ERROR_NOT_PERMITTED /*missing COPY usage*/ ||
+ status == PSA_ERROR_INVALID_ARGUMENT /*incompatible policy*/) {
+ /* There are edge cases where copying won't work, but export+import
+ * might:
+ * - If the old key does not allow PSA_KEY_USAGE_COPY.
+ * - If the old key's usage does not allow what attributes wants.
+ * Because the key was intended for use in the pk module, and may
+ * have had a policy chosen solely for what pk needs rather than
+ * based on a detailed understanding of PSA policies, we are a bit
+ * more liberal than psa_copy_key() here.
+ */
+ /* Here we need to check that the types match, otherwise we risk
+ * importing nonsensical data. */
+ psa_key_attributes_t old_attributes = PSA_KEY_ATTRIBUTES_INIT;
+ status = psa_get_key_attributes(old_key_id, &old_attributes);
+ if (status != PSA_SUCCESS) {
+ return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+ }
+ psa_key_type_t old_type = psa_get_key_type(&old_attributes);
+ psa_reset_key_attributes(&old_attributes);
+ if (old_type != psa_get_key_type(attributes)) {
+ return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+ }
+ status = export_import_into_psa(old_key_id, attributes, new_key_id);
+ }
+ return PSA_PK_TO_MBEDTLS_ERR(status);
+}
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA || MBEDTLS_USE_PSA_CRYPTO */
+
+static int import_pair_into_psa(const mbedtls_pk_context *pk,
+ const psa_key_attributes_t *attributes,
+ mbedtls_svc_key_id_t *key_id)
+{
+ switch (mbedtls_pk_get_type(pk)) {
+#if defined(MBEDTLS_RSA_C)
+ case MBEDTLS_PK_RSA:
+ {
+ if (psa_get_key_type(attributes) != PSA_KEY_TYPE_RSA_KEY_PAIR) {
+ return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+ }
+ unsigned char key_buffer[
+ PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS)];
+ unsigned char *const key_end = key_buffer + sizeof(key_buffer);
+ unsigned char *key_data = key_end;
+ int ret = mbedtls_rsa_write_key(mbedtls_pk_rsa(*pk),
+ key_buffer, &key_data);
+ if (ret < 0) {
+ return ret;
+ }
+ size_t key_length = key_end - key_data;
+ ret = PSA_PK_TO_MBEDTLS_ERR(psa_import_key(attributes,
+ key_data, key_length,
+ key_id));
+ mbedtls_platform_zeroize(key_data, key_length);
+ return ret;
+ }
+#endif /* MBEDTLS_RSA_C */
+
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+ case MBEDTLS_PK_ECKEY:
+ case MBEDTLS_PK_ECKEY_DH:
+ case MBEDTLS_PK_ECDSA:
+ {
+ /* We need to check the curve family, otherwise the import could
+ * succeed with nonsensical data.
+ * We don't check the bit-size: it's optional in attributes,
+ * and if it's specified, psa_import_key() will know from the key
+ * data length and will check that the bit-size matches. */
+ psa_key_type_t to_type = psa_get_key_type(attributes);
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+ psa_ecc_family_t from_family = pk->ec_family;
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
+ const mbedtls_ecp_keypair *ec = mbedtls_pk_ec_ro(*pk);
+ size_t from_bits = 0;
+ psa_ecc_family_t from_family = mbedtls_ecc_group_to_psa(ec->grp.id,
+ &from_bits);
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
+ if (to_type != PSA_KEY_TYPE_ECC_KEY_PAIR(from_family)) {
+ return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+ }
+
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+ if (mbedtls_svc_key_id_is_null(pk->priv_id)) {
+ /* We have a public key and want a key pair. */
+ return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+ }
+ return copy_into_psa(pk->priv_id, attributes, key_id);
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
+ if (ec->d.n == 0) {
+ /* Private key not set. Assume the input is a public key only.
+ * (The other possibility is that it's an incomplete object
+ * where the group is set but neither the public key nor
+ * the private key. This is not possible through ecp.h
+ * functions, so we don't bother reporting a more suitable
+ * error in that case.) */
+ return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+ }
+ unsigned char key_buffer[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)];
+ size_t key_length = 0;
+ int ret = mbedtls_ecp_write_key_ext(ec, &key_length,
+ key_buffer, sizeof(key_buffer));
+ if (ret < 0) {
+ return ret;
+ }
+ ret = PSA_PK_TO_MBEDTLS_ERR(psa_import_key(attributes,
+ key_buffer, key_length,
+ key_id));
+ mbedtls_platform_zeroize(key_buffer, key_length);
+ return ret;
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
+ }
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ case MBEDTLS_PK_OPAQUE:
+ return copy_into_psa(pk->priv_id, attributes, key_id);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+ default:
+ return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+ }
+}
+
+static int import_public_into_psa(const mbedtls_pk_context *pk,
+ const psa_key_attributes_t *attributes,
+ mbedtls_svc_key_id_t *key_id)
+{
+ psa_key_type_t psa_type = psa_get_key_type(attributes);
+
+#if defined(MBEDTLS_RSA_C) || \
+ (defined(MBEDTLS_PK_HAVE_ECC_KEYS) && !defined(MBEDTLS_PK_USE_PSA_EC_DATA)) || \
+ defined(MBEDTLS_USE_PSA_CRYPTO)
+ unsigned char key_buffer[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE];
+#endif
+ unsigned char *key_data = NULL;
+ size_t key_length = 0;
+
+ switch (mbedtls_pk_get_type(pk)) {
+#if defined(MBEDTLS_RSA_C)
+ case MBEDTLS_PK_RSA:
+ {
+ if (psa_type != PSA_KEY_TYPE_RSA_PUBLIC_KEY) {
+ return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+ }
+ unsigned char *const key_end = key_buffer + sizeof(key_buffer);
+ key_data = key_end;
+ int ret = mbedtls_rsa_write_pubkey(mbedtls_pk_rsa(*pk),
+ key_buffer, &key_data);
+ if (ret < 0) {
+ return ret;
+ }
+ key_length = (size_t) ret;
+ break;
+ }
+#endif /*MBEDTLS_RSA_C */
+
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+ case MBEDTLS_PK_ECKEY:
+ case MBEDTLS_PK_ECKEY_DH:
+ case MBEDTLS_PK_ECDSA:
+ {
+ /* We need to check the curve family, otherwise the import could
+ * succeed with nonsensical data.
+ * We don't check the bit-size: it's optional in attributes,
+ * and if it's specified, psa_import_key() will know from the key
+ * data length and will check that the bit-size matches. */
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+ if (psa_type != PSA_KEY_TYPE_ECC_PUBLIC_KEY(pk->ec_family)) {
+ return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+ }
+ key_data = (unsigned char *) pk->pub_raw;
+ key_length = pk->pub_raw_len;
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
+ const mbedtls_ecp_keypair *ec = mbedtls_pk_ec_ro(*pk);
+ size_t from_bits = 0;
+ psa_ecc_family_t from_family = mbedtls_ecc_group_to_psa(ec->grp.id,
+ &from_bits);
+ if (psa_type != PSA_KEY_TYPE_ECC_PUBLIC_KEY(from_family)) {
+ return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+ }
+ int ret = mbedtls_ecp_write_public_key(
+ ec, MBEDTLS_ECP_PF_UNCOMPRESSED,
+ &key_length, key_buffer, sizeof(key_buffer));
+ if (ret < 0) {
+ return ret;
+ }
+ key_data = key_buffer;
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
+ break;
+ }
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+ case MBEDTLS_PK_OPAQUE:
+ {
+ psa_key_attributes_t old_attributes = PSA_KEY_ATTRIBUTES_INIT;
+ psa_status_t status =
+ psa_get_key_attributes(pk->priv_id, &old_attributes);
+ if (status != PSA_SUCCESS) {
+ return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+ }
+ psa_key_type_t old_type = psa_get_key_type(&old_attributes);
+ psa_reset_key_attributes(&old_attributes);
+ if (psa_type != PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(old_type)) {
+ return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+ }
+ status = psa_export_public_key(pk->priv_id,
+ key_buffer, sizeof(key_buffer),
+ &key_length);
+ if (status != PSA_SUCCESS) {
+ return PSA_PK_TO_MBEDTLS_ERR(status);
+ }
+ key_data = key_buffer;
+ break;
+ }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+ default:
+ return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+ }
+
+ return PSA_PK_TO_MBEDTLS_ERR(psa_import_key(attributes,
+ key_data, key_length,
+ key_id));
+}
+
+int mbedtls_pk_import_into_psa(const mbedtls_pk_context *pk,
+ const psa_key_attributes_t *attributes,
+ mbedtls_svc_key_id_t *key_id)
+{
+ /* Set the output immediately so that it won't contain garbage even
+ * if we error out before calling psa_import_key(). */
+ *key_id = MBEDTLS_SVC_KEY_ID_INIT;
+
+#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
+ if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_RSA_ALT) {
+ return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+ }
+#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */
+
+ int want_public = PSA_KEY_TYPE_IS_PUBLIC_KEY(psa_get_key_type(attributes));
+ if (want_public) {
+ return import_public_into_psa(pk, attributes, key_id);
+ } else {
+ return import_pair_into_psa(pk, attributes, key_id);
+ }
+}
+#endif /* MBEDTLS_PSA_CRYPTO_C */
+
/*
* Helper for mbedtls_pk_sign and mbedtls_pk_verify
*/
@@ -708,9 +1182,32 @@
}
if (mbedtls_pk_get_type(ctx) == MBEDTLS_PK_OPAQUE) {
+ psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
+ psa_algorithm_t psa_alg, psa_enrollment_alg, sign_alg;
psa_status_t status;
- status = psa_sign_hash(ctx->priv_id, PSA_ALG_RSA_PSS(psa_md_alg),
+ status = psa_get_key_attributes(ctx->priv_id, &key_attr);
+ if (status != PSA_SUCCESS) {
+ return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
+ }
+ psa_alg = psa_get_key_algorithm(&key_attr);
+ psa_enrollment_alg = psa_get_key_enrollment_algorithm(&key_attr);
+ psa_reset_key_attributes(&key_attr);
+
+ /* Since we're PK type is MBEDTLS_PK_RSASSA_PSS at least one between
+ * alg and enrollment alg should be of type RSA_PSS. */
+ if (PSA_ALG_IS_RSA_PSS(psa_alg)) {
+ sign_alg = psa_alg;
+ } else if (PSA_ALG_IS_RSA_PSS(psa_enrollment_alg)) {
+ sign_alg = psa_enrollment_alg;
+ } else {
+ /* The opaque key has no RSA PSS algorithm associated. */
+ return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+ }
+ /* Adjust the hashing algorithm. */
+ sign_alg = (sign_alg & ~PSA_ALG_HASH_MASK) | PSA_ALG_GET_HASH(psa_md_alg);
+
+ status = psa_sign_hash(ctx->priv_id, sign_alg,
hash, hash_len,
sig, sig_size, sig_len);
return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
@@ -877,124 +1374,4 @@
return ctx->pk_info->type;
}
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-/*
- * Load the key to a PSA key slot,
- * then turn the PK context into a wrapper for that key slot.
- *
- * Currently only works for EC & RSA private keys.
- */
-int mbedtls_pk_wrap_as_opaque(mbedtls_pk_context *pk,
- mbedtls_svc_key_id_t *key,
- psa_algorithm_t alg,
- psa_key_usage_t usage,
- psa_algorithm_t alg2)
-{
-#if !defined(MBEDTLS_PK_HAVE_ECC_KEYS) && !defined(MBEDTLS_RSA_C)
- ((void) pk);
- ((void) key);
- ((void) alg);
- ((void) usage);
- ((void) alg2);
-#else /* !MBEDTLS_PK_HAVE_ECC_KEYS && !MBEDTLS_RSA_C */
-#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
- if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_ECKEY) {
- size_t d_len;
- psa_ecc_family_t curve_id;
- psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
- psa_key_type_t key_type;
- size_t bits;
- psa_status_t status;
-
- /* export the private key material in the format PSA wants */
-#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
- unsigned char d[MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH];
- status = psa_export_key(pk->priv_id, d, sizeof(d), &d_len);
- if (status != PSA_SUCCESS) {
- return psa_pk_status_to_mbedtls(status);
- }
-
- curve_id = pk->ec_family;
- bits = pk->ec_bits;
-#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
- unsigned char d[MBEDTLS_ECP_MAX_BYTES];
- mbedtls_ecp_keypair *ec = mbedtls_pk_ec_rw(*pk);
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-
- d_len = PSA_BITS_TO_BYTES(ec->grp.nbits);
- if ((ret = mbedtls_ecp_write_key(ec, d, d_len)) != 0) {
- return ret;
- }
-
- curve_id = mbedtls_ecc_group_to_psa(ec->grp.id, &bits);
-#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
- key_type = PSA_KEY_TYPE_ECC_KEY_PAIR(curve_id);
-
- /* prepare the key attributes */
- psa_set_key_type(&attributes, key_type);
- psa_set_key_bits(&attributes, bits);
- psa_set_key_usage_flags(&attributes, usage);
- psa_set_key_algorithm(&attributes, alg);
- if (alg2 != PSA_ALG_NONE) {
- psa_set_key_enrollment_algorithm(&attributes, alg2);
- }
-
- /* import private key into PSA */
- status = psa_import_key(&attributes, d, d_len, key);
- mbedtls_platform_zeroize(d, sizeof(d));
- if (status != PSA_SUCCESS) {
- return PSA_PK_TO_MBEDTLS_ERR(status);
- }
-
- /* make PK context wrap the key slot */
- mbedtls_pk_free(pk);
- mbedtls_pk_init(pk);
-
- return mbedtls_pk_setup_opaque(pk, *key);
- } else
-#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
-#if defined(MBEDTLS_RSA_C)
- if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_RSA) {
- unsigned char buf[MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES];
- psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
- int key_len;
- psa_status_t status;
-
- /* export the private key material in the format PSA wants */
- key_len = mbedtls_pk_write_key_der(pk, buf, sizeof(buf));
- if (key_len <= 0) {
- return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
- }
-
- /* prepare the key attributes */
- psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);
- psa_set_key_bits(&attributes, mbedtls_pk_get_bitlen(pk));
- psa_set_key_usage_flags(&attributes, usage);
- psa_set_key_algorithm(&attributes, alg);
- if (alg2 != PSA_ALG_NONE) {
- psa_set_key_enrollment_algorithm(&attributes, alg2);
- }
-
- /* import private key into PSA */
- status = psa_import_key(&attributes,
- buf + sizeof(buf) - key_len,
- key_len, key);
-
- mbedtls_platform_zeroize(buf, sizeof(buf));
-
- if (status != PSA_SUCCESS) {
- return PSA_PK_TO_MBEDTLS_ERR(status);
- }
-
- /* make PK context wrap the key slot */
- mbedtls_pk_free(pk);
- mbedtls_pk_init(pk);
-
- return mbedtls_pk_setup_opaque(pk, *key);
- } else
-#endif /* MBEDTLS_RSA_C */
-#endif /* !MBEDTLS_PK_HAVE_ECC_KEYS && !MBEDTLS_RSA_C */
- return MBEDTLS_ERR_PK_TYPE_MISMATCH;
-}
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
#endif /* MBEDTLS_PK_C */
diff --git a/library/pk_internal.h b/library/pk_internal.h
index 3d5adf8..f5924ad 100644
--- a/library/pk_internal.h
+++ b/library/pk_internal.h
@@ -17,7 +17,7 @@
#include "mbedtls/ecp.h"
#endif
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
#include "psa/crypto.h"
#include "psa_util_internal.h"
@@ -28,7 +28,7 @@
#define PSA_PK_ECDSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \
psa_to_pk_ecdsa_errors, \
psa_pk_status_to_mbedtls)
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
/* Headers/footers for PEM files */
#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----"
@@ -144,4 +144,8 @@
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng);
#endif
+#if defined(MBEDTLS_FS_IO)
+int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n);
+#endif
+
#endif /* MBEDTLS_PK_INTERNAL_H */
diff --git a/library/pk_wrap.c b/library/pk_wrap.c
index c232650..846175e 100644
--- a/library/pk_wrap.c
+++ b/library/pk_wrap.c
@@ -29,9 +29,11 @@
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#include "psa_util_internal.h"
#include "psa/crypto.h"
+#include "mbedtls/psa_util.h"
#if defined(MBEDTLS_RSA_C)
#include "pkwrite.h"
+#include "rsa_internal.h"
#endif
#if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
@@ -56,7 +58,7 @@
static size_t rsa_get_bitlen(mbedtls_pk_context *pk)
{
const mbedtls_rsa_context *rsa = (const mbedtls_rsa_context *) pk->pk_ctx;
- return 8 * mbedtls_rsa_get_len(rsa);
+ return mbedtls_rsa_get_bitlen(rsa);
}
#if defined(MBEDTLS_USE_PSA_CRYPTO)
@@ -69,11 +71,10 @@
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
psa_status_t status;
- mbedtls_pk_context key;
int key_len;
unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES];
- psa_algorithm_t psa_alg_md =
- PSA_ALG_RSA_PKCS1V15_SIGN(mbedtls_md_psa_alg_from_type(md_alg));
+ unsigned char *p = buf + sizeof(buf);
+ psa_algorithm_t psa_alg_md;
size_t rsa_len = mbedtls_rsa_get_len(rsa);
#if SIZE_MAX > UINT_MAX
@@ -82,15 +83,17 @@
}
#endif
+ if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) {
+ psa_alg_md = PSA_ALG_RSA_PSS(mbedtls_md_psa_alg_from_type(md_alg));
+ } else {
+ psa_alg_md = PSA_ALG_RSA_PKCS1V15_SIGN(mbedtls_md_psa_alg_from_type(md_alg));
+ }
+
if (sig_len < rsa_len) {
return MBEDTLS_ERR_RSA_VERIFY_FAILED;
}
- /* mbedtls_pk_write_pubkey_der() expects a full PK context;
- * re-construct one to make it happy */
- key.pk_info = &mbedtls_rsa_info;
- key.pk_ctx = rsa;
- key_len = mbedtls_pk_write_pubkey_der(&key, buf, sizeof(buf));
+ key_len = mbedtls_rsa_write_pubkey(rsa, buf, &p);
if (key_len <= 0) {
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
}
@@ -172,14 +175,15 @@
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
psa_status_t status;
- mbedtls_pk_context key;
int key_len;
unsigned char *buf = NULL;
+ unsigned char *p;
+
buf = mbedtls_calloc(1, MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES);
if (buf == NULL) {
return MBEDTLS_ERR_PK_ALLOC_FAILED;
}
- mbedtls_pk_info_t pk_info = mbedtls_rsa_info;
+ p = buf + MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES;
*sig_len = mbedtls_rsa_get_len(rsa_ctx);
if (sig_size < *sig_len) {
@@ -187,11 +191,7 @@
return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;
}
- /* mbedtls_pk_write_key_der() expects a full PK context;
- * re-construct one to make it happy */
- key.pk_info = &pk_info;
- key.pk_ctx = rsa_ctx;
- key_len = mbedtls_pk_write_key_der(&key, buf, MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES);
+ key_len = mbedtls_rsa_write_key(rsa_ctx, buf, &p);
if (key_len <= 0) {
mbedtls_free(buf);
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
@@ -240,10 +240,14 @@
if (psa_md_alg == 0) {
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
}
+ psa_algorithm_t psa_alg;
+ if (mbedtls_rsa_get_padding_mode(mbedtls_pk_rsa(*pk)) == MBEDTLS_RSA_PKCS_V21) {
+ psa_alg = PSA_ALG_RSA_PSS(psa_md_alg);
+ } else {
+ psa_alg = PSA_ALG_RSA_PKCS1V15_SIGN(psa_md_alg);
+ }
- return mbedtls_pk_psa_rsa_sign_ext(PSA_ALG_RSA_PKCS1V15_SIGN(
- psa_md_alg),
- pk->pk_ctx, hash, hash_len,
+ return mbedtls_pk_psa_rsa_sign_ext(psa_alg, pk->pk_ctx, hash, hash_len,
sig, sig_size, sig_len);
}
#else /* MBEDTLS_USE_PSA_CRYPTO */
@@ -281,36 +285,33 @@
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
+ psa_algorithm_t psa_md_alg, decrypt_alg;
psa_status_t status;
- mbedtls_pk_context key;
int key_len;
unsigned char buf[MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES];
+ unsigned char *p = buf + sizeof(buf);
((void) f_rng);
((void) p_rng);
-#if !defined(MBEDTLS_RSA_ALT)
- if (rsa->padding != MBEDTLS_RSA_PKCS_V15) {
- return MBEDTLS_ERR_RSA_INVALID_PADDING;
- }
-#endif /* !MBEDTLS_RSA_ALT */
-
if (ilen != mbedtls_rsa_get_len(rsa)) {
return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
}
- /* mbedtls_pk_write_key_der() expects a full PK context;
- * re-construct one to make it happy */
- key.pk_info = &mbedtls_rsa_info;
- key.pk_ctx = rsa;
- key_len = mbedtls_pk_write_key_der(&key, buf, sizeof(buf));
+ key_len = mbedtls_rsa_write_key(rsa, buf, &p);
if (key_len <= 0) {
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
}
psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);
- psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT);
+ if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) {
+ psa_md_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) mbedtls_rsa_get_md_alg(rsa));
+ decrypt_alg = PSA_ALG_RSA_OAEP(psa_md_alg);
+ } else {
+ decrypt_alg = PSA_ALG_RSA_PKCS1V15_CRYPT;
+ }
+ psa_set_key_algorithm(&attributes, decrypt_alg);
status = psa_import_key(&attributes,
buf + sizeof(buf) - key_len, key_len,
@@ -320,7 +321,7 @@
goto cleanup;
}
- status = psa_asymmetric_decrypt(key_id, PSA_ALG_RSA_PKCS1V15_CRYPT,
+ status = psa_asymmetric_decrypt(key_id, decrypt_alg,
input, ilen,
NULL, 0,
output, osize, olen);
@@ -367,35 +368,31 @@
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
+ psa_algorithm_t psa_md_alg;
psa_status_t status;
- mbedtls_pk_context key;
int key_len;
unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES];
+ unsigned char *p = buf + sizeof(buf);
((void) f_rng);
((void) p_rng);
-#if !defined(MBEDTLS_RSA_ALT)
- if (rsa->padding != MBEDTLS_RSA_PKCS_V15) {
- return MBEDTLS_ERR_RSA_INVALID_PADDING;
- }
-#endif
-
if (mbedtls_rsa_get_len(rsa) > osize) {
return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE;
}
- /* mbedtls_pk_write_pubkey_der() expects a full PK context;
- * re-construct one to make it happy */
- key.pk_info = &mbedtls_rsa_info;
- key.pk_ctx = rsa;
- key_len = mbedtls_pk_write_pubkey_der(&key, buf, sizeof(buf));
+ key_len = mbedtls_rsa_write_pubkey(rsa, buf, &p);
if (key_len <= 0) {
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
}
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
- psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT);
+ if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) {
+ psa_md_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) mbedtls_rsa_get_md_alg(rsa));
+ psa_set_key_algorithm(&attributes, PSA_ALG_RSA_OAEP(psa_md_alg));
+ } else {
+ psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT);
+ }
psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY);
status = psa_import_key(&attributes,
@@ -536,66 +533,6 @@
#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY)
#if defined(MBEDTLS_USE_PSA_CRYPTO)
-/*
- * An ASN.1 encoded signature is a sequence of two ASN.1 integers. Parse one of
- * those integers and convert it to the fixed-length encoding expected by PSA.
- */
-static int extract_ecdsa_sig_int(unsigned char **from, const unsigned char *end,
- unsigned char *to, size_t to_len)
-{
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- size_t unpadded_len, padding_len;
-
- if ((ret = mbedtls_asn1_get_tag(from, end, &unpadded_len,
- MBEDTLS_ASN1_INTEGER)) != 0) {
- return ret;
- }
-
- while (unpadded_len > 0 && **from == 0x00) {
- (*from)++;
- unpadded_len--;
- }
-
- if (unpadded_len > to_len || unpadded_len == 0) {
- return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
- }
-
- padding_len = to_len - unpadded_len;
- memset(to, 0x00, padding_len);
- memcpy(to + padding_len, *from, unpadded_len);
- (*from) += unpadded_len;
-
- return 0;
-}
-
-/*
- * Convert a signature from an ASN.1 sequence of two integers
- * to a raw {r,s} buffer. Note: the provided sig buffer must be at least
- * twice as big as int_size.
- */
-static int extract_ecdsa_sig(unsigned char **p, const unsigned char *end,
- unsigned char *sig, size_t int_size)
-{
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- size_t tmp_size;
-
- if ((ret = mbedtls_asn1_get_tag(p, end, &tmp_size,
- MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
- return ret;
- }
-
- /* Extract r */
- if ((ret = extract_ecdsa_sig_int(p, end, sig, int_size)) != 0) {
- return ret;
- }
- /* Extract s */
- if ((ret = extract_ecdsa_sig_int(p, end, sig + int_size, int_size)) != 0) {
- return ret;
- }
-
- return 0;
-}
-
/* Common helper for ECDSA verify using PSA functions. */
static int ecdsa_verify_psa(unsigned char *key, size_t key_len,
psa_ecc_family_t curve, size_t curve_bits,
@@ -607,6 +544,7 @@
mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
psa_algorithm_t psa_sig_md = PSA_ALG_ECDSA_ANY;
size_t signature_len = PSA_ECDSA_SIGNATURE_SIZE(curve_bits);
+ size_t converted_sig_len;
unsigned char extracted_sig[PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE];
unsigned char *p;
psa_status_t status;
@@ -631,11 +569,14 @@
}
p = (unsigned char *) sig;
- /* extract_ecdsa_sig's last parameter is the size
- * of each integer to be parsed, so it's actually half
- * the size of the signature. */
- if ((ret = extract_ecdsa_sig(&p, sig + sig_len, extracted_sig,
- signature_len/2)) != 0) {
+ ret = mbedtls_ecdsa_der_to_raw(curve_bits, p, sig_len, extracted_sig,
+ sizeof(extracted_sig), &converted_sig_len);
+ if (ret != 0) {
+ goto cleanup;
+ }
+
+ if (converted_sig_len != signature_len) {
+ ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA;
goto cleanup;
}
@@ -646,10 +587,6 @@
goto cleanup;
}
- if (p != sig + sig_len) {
- ret = MBEDTLS_ERR_PK_SIG_LEN_MISMATCH;
- goto cleanup;
- }
ret = 0;
cleanup:
@@ -751,90 +688,6 @@
#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
#if defined(MBEDTLS_USE_PSA_CRYPTO)
-/*
- * Simultaneously convert and move raw MPI from the beginning of a buffer
- * to an ASN.1 MPI at the end of the buffer.
- * See also mbedtls_asn1_write_mpi().
- *
- * p: pointer to the end of the output buffer
- * start: start of the output buffer, and also of the mpi to write at the end
- * n_len: length of the mpi to read from start
- */
-static int asn1_write_mpibuf(unsigned char **p, unsigned char *start,
- size_t n_len)
-{
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- size_t len = 0;
-
- if ((size_t) (*p - start) < n_len) {
- return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
- }
-
- len = n_len;
- *p -= len;
- memmove(*p, start, len);
-
- /* ASN.1 DER encoding requires minimal length, so skip leading 0s.
- * Neither r nor s should be 0, but as a failsafe measure, still detect
- * that rather than overflowing the buffer in case of a PSA error. */
- while (len > 0 && **p == 0x00) {
- ++(*p);
- --len;
- }
-
- /* this is only reached if the signature was invalid */
- if (len == 0) {
- return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
- }
-
- /* if the msb is 1, ASN.1 requires that we prepend a 0.
- * Neither r nor s can be 0, so we can assume len > 0 at all times. */
- if (**p & 0x80) {
- if (*p - start < 1) {
- return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
- }
-
- *--(*p) = 0x00;
- len += 1;
- }
-
- MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
- MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start,
- MBEDTLS_ASN1_INTEGER));
-
- return (int) len;
-}
-
-/* Transcode signature from PSA format to ASN.1 sequence.
- * See ecdsa_signature_to_asn1 in ecdsa.c, but with byte buffers instead of
- * MPIs, and in-place.
- *
- * [in/out] sig: the signature pre- and post-transcoding
- * [in/out] sig_len: signature length pre- and post-transcoding
- * [int] buf_len: the available size the in/out buffer
- */
-static int pk_ecdsa_sig_asn1_from_psa(unsigned char *sig, size_t *sig_len,
- size_t buf_len)
-{
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- size_t len = 0;
- const size_t rs_len = *sig_len / 2;
- unsigned char *p = sig + buf_len;
-
- MBEDTLS_ASN1_CHK_ADD(len, asn1_write_mpibuf(&p, sig + rs_len, rs_len));
- MBEDTLS_ASN1_CHK_ADD(len, asn1_write_mpibuf(&p, sig, rs_len));
-
- MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, sig, len));
- MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, sig,
- MBEDTLS_ASN1_CONSTRUCTED |
- MBEDTLS_ASN1_SEQUENCE));
-
- memmove(sig, p, len);
- *sig_len = len;
-
- return 0;
-}
-
/* Common helper for ECDSA sign using PSA functions.
* Instead of extracting key's properties in order to check which kind of ECDSA
* signature it supports, we try both deterministic and non-deterministic.
@@ -845,6 +698,15 @@
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
psa_status_t status;
+ psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
+ size_t key_bits = 0;
+
+ status = psa_get_key_attributes(key_id, &key_attr);
+ if (status != PSA_SUCCESS) {
+ return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
+ }
+ key_bits = psa_get_key_bits(&key_attr);
+ psa_reset_key_attributes(&key_attr);
status = psa_sign_hash(key_id,
PSA_ALG_DETERMINISTIC_ECDSA(mbedtls_md_psa_alg_from_type(md_alg)),
@@ -863,7 +725,7 @@
}
done:
- ret = pk_ecdsa_sig_asn1_from_psa(sig, sig_len, sig_size);
+ ret = mbedtls_ecdsa_raw_to_der(key_bits, sig, *sig_len, sig, sig_size, sig_len);
return ret;
}
diff --git a/library/pkcs7.c b/library/pkcs7.c
index 0869c2e..3aac662 100644
--- a/library/pkcs7.c
+++ b/library/pkcs7.c
@@ -7,7 +7,7 @@
#include "mbedtls/build_info.h"
#if defined(MBEDTLS_PKCS7_C)
#include "mbedtls/pkcs7.h"
-#include "mbedtls/x509.h"
+#include "x509_internal.h"
#include "mbedtls/asn1.h"
#include "mbedtls/x509_crt.h"
#include "mbedtls/x509_crl.h"
diff --git a/library/pkparse.c b/library/pkparse.c
index 5f95545..5a3d3b2 100644
--- a/library/pkparse.c
+++ b/library/pkparse.c
@@ -28,6 +28,7 @@
/* Key types */
#if defined(MBEDTLS_RSA_C)
#include "mbedtls/rsa.h"
+#include "rsa_internal.h"
#endif
/* Extended formats */
@@ -757,68 +758,6 @@
#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
-#if defined(MBEDTLS_RSA_C)
-/*
- * RSAPublicKey ::= SEQUENCE {
- * modulus INTEGER, -- n
- * publicExponent INTEGER -- e
- * }
- */
-static int pk_get_rsapubkey(unsigned char **p,
- const unsigned char *end,
- mbedtls_rsa_context *rsa)
-{
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- size_t len;
-
- if ((ret = mbedtls_asn1_get_tag(p, end, &len,
- MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
- }
-
- if (*p + len != end) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
- MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
- }
-
- /* Import N */
- if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
- }
-
- if ((ret = mbedtls_rsa_import_raw(rsa, *p, len, NULL, 0, NULL, 0,
- NULL, 0, NULL, 0)) != 0) {
- return MBEDTLS_ERR_PK_INVALID_PUBKEY;
- }
-
- *p += len;
-
- /* Import E */
- if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
- }
-
- if ((ret = mbedtls_rsa_import_raw(rsa, NULL, 0, NULL, 0, NULL, 0,
- NULL, 0, *p, len)) != 0) {
- return MBEDTLS_ERR_PK_INVALID_PUBKEY;
- }
-
- *p += len;
-
- if (mbedtls_rsa_complete(rsa) != 0 ||
- mbedtls_rsa_check_pubkey(rsa) != 0) {
- return MBEDTLS_ERR_PK_INVALID_PUBKEY;
- }
-
- if (*p != end) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
- MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
- }
-
- return 0;
-}
-#endif /* MBEDTLS_RSA_C */
-
/* Get a PK algorithm identifier
*
* AlgorithmIdentifier ::= SEQUENCE {
@@ -911,7 +850,17 @@
#if defined(MBEDTLS_RSA_C)
if (pk_alg == MBEDTLS_PK_RSA) {
- ret = pk_get_rsapubkey(p, end, mbedtls_pk_rsa(*pk));
+ ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*pk), *p, (size_t) (end - *p));
+ if (ret == 0) {
+ /* On success all the input has been consumed by the parsing function. */
+ *p += end - *p;
+ } else if ((ret <= MBEDTLS_ERR_ASN1_OUT_OF_DATA) &&
+ (ret >= MBEDTLS_ERR_ASN1_BUF_TOO_SMALL)) {
+ /* In case of ASN1 error codes add MBEDTLS_ERR_PK_INVALID_PUBKEY. */
+ ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
+ } else {
+ ret = MBEDTLS_ERR_PK_INVALID_PUBKEY;
+ }
} else
#endif /* MBEDTLS_RSA_C */
#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
@@ -944,195 +893,6 @@
return ret;
}
-#if defined(MBEDTLS_RSA_C)
-/*
- * Wrapper around mbedtls_asn1_get_mpi() that rejects zero.
- *
- * The value zero is:
- * - never a valid value for an RSA parameter
- * - interpreted as "omitted, please reconstruct" by mbedtls_rsa_complete().
- *
- * Since values can't be omitted in PKCS#1, passing a zero value to
- * rsa_complete() would be incorrect, so reject zero values early.
- */
-static int asn1_get_nonzero_mpi(unsigned char **p,
- const unsigned char *end,
- mbedtls_mpi *X)
-{
- int ret;
-
- ret = mbedtls_asn1_get_mpi(p, end, X);
- if (ret != 0) {
- return ret;
- }
-
- if (mbedtls_mpi_cmp_int(X, 0) == 0) {
- return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
- }
-
- return 0;
-}
-
-/*
- * Parse a PKCS#1 encoded private RSA key
- */
-static int pk_parse_key_pkcs1_der(mbedtls_rsa_context *rsa,
- const unsigned char *key,
- size_t keylen)
-{
- int ret, version;
- size_t len;
- unsigned char *p, *end;
-
- mbedtls_mpi T;
- mbedtls_mpi_init(&T);
-
- p = (unsigned char *) key;
- end = p + keylen;
-
- /*
- * This function parses the RSAPrivateKey (PKCS#1)
- *
- * RSAPrivateKey ::= SEQUENCE {
- * version Version,
- * modulus INTEGER, -- n
- * publicExponent INTEGER, -- e
- * privateExponent INTEGER, -- d
- * prime1 INTEGER, -- p
- * prime2 INTEGER, -- q
- * exponent1 INTEGER, -- d mod (p-1)
- * exponent2 INTEGER, -- d mod (q-1)
- * coefficient INTEGER, -- (inverse of q) mod p
- * otherPrimeInfos OtherPrimeInfos OPTIONAL
- * }
- */
- if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
- MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
- }
-
- end = p + len;
-
- if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
- }
-
- if (version != 0) {
- return MBEDTLS_ERR_PK_KEY_INVALID_VERSION;
- }
-
- /* Import N */
- if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
- (ret = mbedtls_rsa_import(rsa, &T, NULL, NULL,
- NULL, NULL)) != 0) {
- goto cleanup;
- }
-
- /* Import E */
- if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
- (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL,
- NULL, &T)) != 0) {
- goto cleanup;
- }
-
- /* Import D */
- if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
- (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL,
- &T, NULL)) != 0) {
- goto cleanup;
- }
-
- /* Import P */
- if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
- (ret = mbedtls_rsa_import(rsa, NULL, &T, NULL,
- NULL, NULL)) != 0) {
- goto cleanup;
- }
-
- /* Import Q */
- if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
- (ret = mbedtls_rsa_import(rsa, NULL, NULL, &T,
- NULL, NULL)) != 0) {
- goto cleanup;
- }
-
-#if !defined(MBEDTLS_RSA_NO_CRT) && !defined(MBEDTLS_RSA_ALT)
- /*
- * The RSA CRT parameters DP, DQ and QP are nominally redundant, in
- * that they can be easily recomputed from D, P and Q. However by
- * parsing them from the PKCS1 structure it is possible to avoid
- * recalculating them which both reduces the overhead of loading
- * RSA private keys into memory and also avoids side channels which
- * can arise when computing those values, since all of D, P, and Q
- * are secret. See https://eprint.iacr.org/2020/055 for a
- * description of one such attack.
- */
-
- /* Import DP */
- if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
- (ret = mbedtls_mpi_copy(&rsa->DP, &T)) != 0) {
- goto cleanup;
- }
-
- /* Import DQ */
- if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
- (ret = mbedtls_mpi_copy(&rsa->DQ, &T)) != 0) {
- goto cleanup;
- }
-
- /* Import QP */
- if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
- (ret = mbedtls_mpi_copy(&rsa->QP, &T)) != 0) {
- goto cleanup;
- }
-
-#else
- /* Verify existence of the CRT params */
- if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
- (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
- (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0) {
- goto cleanup;
- }
-#endif
-
- /* rsa_complete() doesn't complete anything with the default
- * implementation but is still called:
- * - for the benefit of alternative implementation that may want to
- * pre-compute stuff beyond what's provided (eg Montgomery factors)
- * - as is also sanity-checks the key
- *
- * Furthermore, we also check the public part for consistency with
- * mbedtls_pk_parse_pubkey(), as it includes size minima for example.
- */
- if ((ret = mbedtls_rsa_complete(rsa)) != 0 ||
- (ret = mbedtls_rsa_check_pubkey(rsa)) != 0) {
- goto cleanup;
- }
-
- if (p != end) {
- ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
- MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
- }
-
-cleanup:
-
- mbedtls_mpi_free(&T);
-
- if (ret != 0) {
- /* Wrap error code if it's coming from a lower level */
- if ((ret & 0xff80) == 0) {
- ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
- } else {
- ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
- }
-
- mbedtls_rsa_free(rsa);
- }
-
- return ret;
-}
-#endif /* MBEDTLS_RSA_C */
-
#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
/*
* Parse a SEC1 encoded private EC key
@@ -1348,7 +1108,7 @@
#if defined(MBEDTLS_RSA_C)
if (pk_alg == MBEDTLS_PK_RSA) {
- if ((ret = pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), p, len)) != 0) {
+ if ((ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), p, len)) != 0) {
mbedtls_pk_free(pk);
return ret;
}
@@ -1538,8 +1298,8 @@
if (ret == 0) {
pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 ||
- (ret = pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk),
- pem.buf, pem.buflen)) != 0) {
+ (ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk),
+ pem.buf, pem.buflen)) != 0) {
mbedtls_pk_free(pk);
}
@@ -1679,7 +1439,7 @@
pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
if (mbedtls_pk_setup(pk, pk_info) == 0 &&
- pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), key, keylen) == 0) {
+ mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), key, keylen) == 0) {
return 0;
}
@@ -1754,7 +1514,7 @@
return ret;
}
- if ((ret = pk_get_rsapubkey(&p, p + pem.buflen, mbedtls_pk_rsa(*ctx))) != 0) {
+ if ((ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*ctx), p, pem.buflen)) != 0) {
mbedtls_pk_free(ctx);
}
@@ -1801,13 +1561,12 @@
}
p = (unsigned char *) key;
- ret = pk_get_rsapubkey(&p, p + keylen, mbedtls_pk_rsa(*ctx));
+ ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*ctx), p, keylen);
if (ret == 0) {
return ret;
}
mbedtls_pk_free(ctx);
- if (ret != (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
- MBEDTLS_ERR_ASN1_UNEXPECTED_TAG))) {
+ if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
return ret;
}
#endif /* MBEDTLS_RSA_C */
diff --git a/library/pkwrite.c b/library/pkwrite.c
index 1f0d399..5e009c5 100644
--- a/library/pkwrite.c
+++ b/library/pkwrite.c
@@ -32,6 +32,9 @@
#if defined(MBEDTLS_PEM_WRITE_C)
#include "mbedtls/pem.h"
#endif
+#if defined(MBEDTLS_RSA_C)
+#include "rsa_internal.h"
+#endif
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#include "psa/crypto.h"
@@ -56,60 +59,13 @@
* Internal functions for RSA keys.
******************************************************************************/
#if defined(MBEDTLS_RSA_C)
-/*
- * RSAPublicKey ::= SEQUENCE {
- * modulus INTEGER, -- n
- * publicExponent INTEGER -- e
- * }
- */
-static int pk_write_rsa_pubkey(unsigned char **p, unsigned char *start,
- const mbedtls_pk_context *pk)
-{
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- size_t len = 0;
- mbedtls_mpi T;
- mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*pk);
-
- mbedtls_mpi_init(&T);
-
- /* Export E */
- if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &T)) != 0 ||
- (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
- goto end_of_export;
- }
- len += ret;
-
- /* Export N */
- if ((ret = mbedtls_rsa_export(rsa, &T, NULL, NULL, NULL, NULL)) != 0 ||
- (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
- goto end_of_export;
- }
- len += ret;
-
-end_of_export:
-
- mbedtls_mpi_free(&T);
- if (ret < 0) {
- return ret;
- }
-
- MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
- MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED |
- MBEDTLS_ASN1_SEQUENCE));
-
- return (int) len;
-}
-
static int pk_write_rsa_der(unsigned char **p, unsigned char *buf,
const mbedtls_pk_context *pk)
{
- size_t len = 0;
- int ret;
-
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
uint8_t tmp[PSA_EXPORT_KEY_PAIR_MAX_SIZE];
- size_t tmp_len = 0;
+ size_t len = 0, tmp_len = 0;
if (psa_export_key(pk->priv_id, tmp, sizeof(tmp), &tmp_len) != PSA_SUCCESS) {
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
@@ -118,94 +74,11 @@
memcpy(*p, tmp, tmp_len);
len += tmp_len;
mbedtls_platform_zeroize(tmp, sizeof(tmp));
- } else
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
- {
- mbedtls_mpi T; /* Temporary holding the exported parameters */
- mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*pk);
- /*
- * Export the parameters one after another to avoid simultaneous copies.
- */
-
- mbedtls_mpi_init(&T);
-
- /* Export QP */
- if ((ret = mbedtls_rsa_export_crt(rsa, NULL, NULL, &T)) != 0 ||
- (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) {
- goto end_of_export;
- }
- len += ret;
-
- /* Export DQ */
- if ((ret = mbedtls_rsa_export_crt(rsa, NULL, &T, NULL)) != 0 ||
- (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) {
- goto end_of_export;
- }
- len += ret;
-
- /* Export DP */
- if ((ret = mbedtls_rsa_export_crt(rsa, &T, NULL, NULL)) != 0 ||
- (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) {
- goto end_of_export;
- }
- len += ret;
-
- /* Export Q */
- if ((ret = mbedtls_rsa_export(rsa, NULL, NULL,
- &T, NULL, NULL)) != 0 ||
- (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) {
- goto end_of_export;
- }
- len += ret;
-
- /* Export P */
- if ((ret = mbedtls_rsa_export(rsa, NULL, &T,
- NULL, NULL, NULL)) != 0 ||
- (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) {
- goto end_of_export;
- }
- len += ret;
-
- /* Export D */
- if ((ret = mbedtls_rsa_export(rsa, NULL, NULL,
- NULL, &T, NULL)) != 0 ||
- (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) {
- goto end_of_export;
- }
- len += ret;
-
- /* Export E */
- if ((ret = mbedtls_rsa_export(rsa, NULL, NULL,
- NULL, NULL, &T)) != 0 ||
- (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) {
- goto end_of_export;
- }
- len += ret;
-
- /* Export N */
- if ((ret = mbedtls_rsa_export(rsa, &T, NULL,
- NULL, NULL, NULL)) != 0 ||
- (ret = mbedtls_asn1_write_mpi(p, buf, &T)) < 0) {
- goto end_of_export;
- }
- len += ret;
-
-end_of_export:
-
- mbedtls_mpi_free(&T);
- if (ret < 0) {
- return ret;
- }
-
- MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 0));
- MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len));
- MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p,
- buf, MBEDTLS_ASN1_CONSTRUCTED |
- MBEDTLS_ASN1_SEQUENCE));
+ return (int) len;
}
-
- return (int) len;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+ return mbedtls_rsa_write_key(mbedtls_pk_rsa(*pk), buf, p);
}
#endif /* MBEDTLS_RSA_C */
@@ -329,7 +202,7 @@
mbedtls_ecp_keypair *ec = mbedtls_pk_ec_rw(*pk);
byte_length = (ec->grp.pbits + 7) / 8;
- ret = mbedtls_ecp_write_key(ec, tmp, byte_length);
+ ret = mbedtls_ecp_write_key_ext(ec, &byte_length, tmp, sizeof(tmp));
if (ret != 0) {
goto exit;
}
@@ -543,7 +416,7 @@
#if defined(MBEDTLS_RSA_C)
if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) {
- MBEDTLS_ASN1_CHK_ADD(len, pk_write_rsa_pubkey(p, start, key));
+ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_rsa_write_pubkey(mbedtls_pk_rsa(*key), start, p));
} else
#endif
#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
diff --git a/library/platform_util.c b/library/platform_util.c
index 9f5dcb8..0741bf5 100644
--- a/library/platform_util.c
+++ b/library/platform_util.c
@@ -93,8 +93,6 @@
void mbedtls_platform_zeroize(void *buf, size_t len)
{
- MBEDTLS_INTERNAL_VALIDATE(len == 0 || buf != NULL);
-
if (len > 0) {
#if defined(MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO)
explicit_bzero(buf, len);
@@ -151,10 +149,10 @@
#include <time.h>
#if !defined(_WIN32) && (defined(unix) || \
defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \
- defined(__MACH__)))
+ defined(__MACH__)) || defined__midipix__)
#include <unistd.h>
#endif /* !_WIN32 && (unix || __unix || __unix__ ||
- * (__APPLE__ && __MACH__)) */
+ * (__APPLE__ && __MACH__) || __midipix__) */
#if !((defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L) || \
(defined(_POSIX_THREAD_SAFE_FUNCTIONS) && \
@@ -222,9 +220,10 @@
#include <time.h>
#if !defined(_WIN32) && \
(defined(unix) || defined(__unix) || defined(__unix__) || \
- (defined(__APPLE__) && defined(__MACH__)) || defined(__HAIKU__))
+ (defined(__APPLE__) && defined(__MACH__)) || defined(__HAIKU__) || defined(__midipix__))
#include <unistd.h>
-#endif /* !_WIN32 && (unix || __unix || __unix__ || (__APPLE__ && __MACH__) || __HAIKU__) */
+#endif \
+ /* !_WIN32 && (unix || __unix || __unix__ || (__APPLE__ && __MACH__) || __HAIKU__ || __midipix__) */
#if (defined(_POSIX_VERSION) && _POSIX_VERSION >= 199309L) || defined(__HAIKU__)
mbedtls_ms_time_t mbedtls_ms_time(void)
{
@@ -232,7 +231,7 @@
struct timespec tv;
mbedtls_ms_time_t current_ms;
-#if defined(__linux__) && defined(CLOCK_BOOTTIME)
+#if defined(__linux__) && defined(CLOCK_BOOTTIME) || defined(__midipix__)
ret = clock_gettime(CLOCK_BOOTTIME, &tv);
#else
ret = clock_gettime(CLOCK_MONOTONIC, &tv);
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index 7473aef..089751a 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -101,11 +101,6 @@
static psa_global_data_t global_data;
-#if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
-mbedtls_psa_drbg_context_t *const mbedtls_psa_random_state =
- &global_data.rng.drbg;
-#endif
-
#define GUARD_MODULE_INITIALIZED \
if (global_data.initialized == 0) \
return PSA_ERROR_BAD_STATE;
@@ -260,12 +255,30 @@
defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE)
static int psa_is_dh_key_size_valid(size_t bits)
{
- if (bits != 2048 && bits != 3072 && bits != 4096 &&
- bits != 6144 && bits != 8192) {
- return 0;
+ switch (bits) {
+#if defined(PSA_WANT_DH_RFC7919_2048)
+ case 2048:
+ return 1;
+#endif /* PSA_WANT_DH_RFC7919_2048 */
+#if defined(PSA_WANT_DH_RFC7919_3072)
+ case 3072:
+ return 1;
+#endif /* PSA_WANT_DH_RFC7919_3072 */
+#if defined(PSA_WANT_DH_RFC7919_4096)
+ case 4096:
+ return 1;
+#endif /* PSA_WANT_DH_RFC7919_4096 */
+#if defined(PSA_WANT_DH_RFC7919_6144)
+ case 6144:
+ return 1;
+#endif /* PSA_WANT_DH_RFC7919_6144 */
+#if defined(PSA_WANT_DH_RFC7919_8192)
+ case 8192:
+ return 1;
+#endif /* PSA_WANT_DH_RFC7919_8192 */
+ default:
+ return 0;
}
-
- return 1;
}
#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT ||
MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY ||
@@ -681,7 +694,7 @@
size_t *key_buffer_length, size_t *bits)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
- psa_key_type_t type = attributes->core.type;
+ psa_key_type_t type = attributes->type;
/* zero-length keys are never supported. */
if (data_length == 0) {
@@ -691,7 +704,7 @@
if (key_type_is_raw_bytes(type)) {
*bits = PSA_BYTES_TO_BITS(data_length);
- status = psa_validate_unstructured_key_bit_size(attributes->core.type,
+ status = psa_validate_unstructured_key_bit_size(attributes->type,
*bits);
if (status != PSA_SUCCESS) {
return status;
@@ -708,7 +721,7 @@
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY)
if (PSA_KEY_TYPE_IS_DH(type)) {
if (psa_is_dh_key_size_valid(PSA_BYTES_TO_BITS(data_length)) == 0) {
- return PSA_ERROR_INVALID_ARGUMENT;
+ return PSA_ERROR_NOT_SUPPORTED;
}
return mbedtls_psa_ffdh_import_key(attributes,
data, data_length,
@@ -1022,8 +1035,13 @@
* into a key slot if not already done.
*
* On success, the returned key slot has been registered for reading.
- * It is the responsibility of the caller to call psa_unregister_read(slot)
- * when they have finished reading the contents of the slot.
+ * It is the responsibility of the caller to then unregister
+ * once they have finished reading the contents of the slot.
+ * The caller unregisters by calling psa_unregister_read() or
+ * psa_unregister_read_under_mutex(). psa_unregister_read() must be called
+ * if and only if the caller already holds the global key slot mutex
+ * (when mutexes are enabled). psa_unregister_read_under_mutex() encapsulates
+ * the unregister with mutex lock and unlock operations.
*/
static psa_status_t psa_get_and_lock_key_slot_with_policy(
mbedtls_svc_key_id_t key,
@@ -1067,7 +1085,7 @@
error:
*p_slot = NULL;
- psa_unregister_read(slot);
+ psa_unregister_read_under_mutex(slot);
return status;
}
@@ -1083,8 +1101,13 @@
* for a cryptographic operation.
*
* On success, the returned key slot has been registered for reading.
- * It is the responsibility of the caller to call psa_unregister_read(slot)
- * when they have finished reading the contents of the slot.
+ * It is the responsibility of the caller to then unregister
+ * once they have finished reading the contents of the slot.
+ * The caller unregisters by calling psa_unregister_read() or
+ * psa_unregister_read_under_mutex(). psa_unregister_read() must be called
+ * if and only if the caller already holds the global key slot mutex
+ * (when mutexes are enabled). psa_unregister_read_under_mutex() encapsulates
+ * psa_unregister_read() with mutex lock and unlock operations.
*/
static psa_status_t psa_get_and_lock_transparent_key_slot_with_policy(
mbedtls_svc_key_id_t key,
@@ -1099,7 +1122,7 @@
}
if (psa_key_lifetime_is_external((*p_slot)->attr.lifetime)) {
- psa_unregister_read(*p_slot);
+ psa_unregister_read_under_mutex(*p_slot);
*p_slot = NULL;
return PSA_ERROR_NOT_SUPPORTED;
}
@@ -1202,6 +1225,25 @@
return status;
}
+#if defined(MBEDTLS_THREADING_C)
+ /* We cannot unlock between setting the state to PENDING_DELETION
+ * and destroying the key in storage, as otherwise another thread
+ * could load the key into a new slot and the key will not be
+ * fully destroyed. */
+ PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(
+ &mbedtls_threading_key_slot_mutex));
+
+ if (slot->state == PSA_SLOT_PENDING_DELETION) {
+ /* Another thread has destroyed the key between us locking the slot
+ * and us gaining the mutex. Unregister from the slot,
+ * and report that the key does not exist. */
+ status = psa_unregister_read(slot);
+
+ PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+ &mbedtls_threading_key_slot_mutex));
+ return (status == PSA_SUCCESS) ? PSA_ERROR_INVALID_HANDLE : status;
+ }
+#endif
/* Set the key slot containing the key description's state to
* PENDING_DELETION. This stops new operations from registering
* to read the slot. Current readers can safely continue to access
@@ -1210,7 +1252,12 @@
* If the key is persistent, we can now delete the copy of the key
* from memory. If the key is opaque, we require the driver to
* deal with the deletion. */
- slot->state = PSA_SLOT_PENDING_DELETION;
+ overall_status = psa_key_slot_state_transition(slot, PSA_SLOT_FULL,
+ PSA_SLOT_PENDING_DELETION);
+
+ if (overall_status != PSA_SUCCESS) {
+ goto exit;
+ }
if (PSA_KEY_LIFETIME_IS_READ_ONLY(slot->attr.lifetime)) {
/* Refuse the destruction of a read-only key (which may or may not work
@@ -1265,11 +1312,6 @@
if (overall_status == PSA_SUCCESS) {
overall_status = status;
}
-
- /* TODO: other slots may have a copy of the same key. We should
- * invalidate them.
- * https://github.com/ARMmbed/mbed-crypto/issues/214
- */
}
#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
@@ -1295,61 +1337,23 @@
if (status != PSA_SUCCESS) {
overall_status = status;
}
+
+#if defined(MBEDTLS_THREADING_C)
+ /* Don't overwrite existing errors if the unlock fails. */
+ status = overall_status;
+ PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+ &mbedtls_threading_key_slot_mutex));
+#endif
+
return overall_status;
}
-#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \
- defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
-static psa_status_t psa_get_rsa_public_exponent(
- const mbedtls_rsa_context *rsa,
- psa_key_attributes_t *attributes)
-{
- mbedtls_mpi mpi;
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- uint8_t *buffer = NULL;
- size_t buflen;
- mbedtls_mpi_init(&mpi);
-
- ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &mpi);
- if (ret != 0) {
- goto exit;
- }
- if (mbedtls_mpi_cmp_int(&mpi, 65537) == 0) {
- /* It's the default value, which is reported as an empty string,
- * so there's nothing to do. */
- goto exit;
- }
-
- buflen = mbedtls_mpi_size(&mpi);
- buffer = mbedtls_calloc(1, buflen);
- if (buffer == NULL) {
- ret = MBEDTLS_ERR_MPI_ALLOC_FAILED;
- goto exit;
- }
- ret = mbedtls_mpi_write_binary(&mpi, buffer, buflen);
- if (ret != 0) {
- goto exit;
- }
- attributes->domain_parameters = buffer;
- attributes->domain_parameters_size = buflen;
-
-exit:
- mbedtls_mpi_free(&mpi);
- if (ret != 0) {
- mbedtls_free(buffer);
- }
- return mbedtls_to_psa_error(ret);
-}
-#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) ||
- * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
-
/** Retrieve all the publicly-accessible attributes of a key.
*/
psa_status_t psa_get_key_attributes(mbedtls_svc_key_id_t key,
psa_key_attributes_t *attributes)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
- psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
psa_key_slot_t *slot;
psa_reset_key_attributes(attributes);
@@ -1359,9 +1363,7 @@
return status;
}
- attributes->core = slot->attr;
- attributes->core.flags &= (MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY |
- MBEDTLS_PSA_KA_MASK_DUAL_USE);
+ *attributes = slot->attr;
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
if (psa_get_se_driver_entry(slot->attr.lifetime) != NULL) {
@@ -1370,55 +1372,7 @@
}
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
- switch (slot->attr.type) {
-#if (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && \
- defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) || \
- defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
- case PSA_KEY_TYPE_RSA_KEY_PAIR:
- case PSA_KEY_TYPE_RSA_PUBLIC_KEY:
- /* TODO: This is a temporary situation where domain parameters are deprecated,
- * but we need it for namely generating an RSA key with a non-default exponent.
- * This would be improved after https://github.com/Mbed-TLS/mbedtls/issues/6494.
- */
- if (!psa_key_lifetime_is_external(slot->attr.lifetime)) {
- mbedtls_rsa_context *rsa = NULL;
-
- status = mbedtls_psa_rsa_load_representation(
- slot->attr.type,
- slot->key.data,
- slot->key.bytes,
- &rsa);
- if (status != PSA_SUCCESS) {
- break;
- }
-
- status = psa_get_rsa_public_exponent(rsa,
- attributes);
- mbedtls_rsa_free(rsa);
- mbedtls_free(rsa);
- }
- break;
-#else
- case PSA_KEY_TYPE_RSA_KEY_PAIR:
- case PSA_KEY_TYPE_RSA_PUBLIC_KEY:
- attributes->domain_parameters = NULL;
- attributes->domain_parameters_size = SIZE_MAX;
- break;
-#endif /* (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && \
- * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) ||
- * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
- default:
- /* Nothing else to do. */
- break;
- }
-
- if (status != PSA_SUCCESS) {
- psa_reset_key_attributes(attributes);
- }
-
- unlock_status = psa_unregister_read(slot);
-
- return (status == PSA_SUCCESS) ? unlock_status : status;
+ return psa_unregister_read_under_mutex(slot);
}
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
@@ -1426,7 +1380,7 @@
const psa_key_attributes_t *attributes,
psa_key_slot_number_t *slot_number)
{
- if (attributes->core.flags & MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER) {
+ if (attributes->has_slot_number) {
*slot_number = attributes->slot_number;
return PSA_SUCCESS;
} else {
@@ -1456,7 +1410,7 @@
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length)
{
- psa_key_type_t type = attributes->core.type;
+ psa_key_type_t type = attributes->type;
if (key_type_is_raw_bytes(type) ||
PSA_KEY_TYPE_IS_RSA(type) ||
@@ -1508,17 +1462,14 @@
LOCAL_OUTPUT_ALLOC(data_external, data_size, data);
- psa_key_attributes_t attributes = {
- .core = slot->attr
- };
- status = psa_driver_wrapper_export_key(&attributes,
+ status = psa_driver_wrapper_export_key(&slot->attr,
slot->key.data, slot->key.bytes,
data, data_size, data_length);
#if defined(MBEDTLS_PSA_COPY_CALLER_BUFFERS)
exit:
#endif
- unlock_status = psa_unregister_read(slot);
+ unlock_status = psa_unregister_read_under_mutex(slot);
LOCAL_OUTPUT_FREE(data_external, data);
return (status == PSA_SUCCESS) ? unlock_status : status;
@@ -1532,7 +1483,7 @@
size_t data_size,
size_t *data_length)
{
- psa_key_type_t type = attributes->core.type;
+ psa_key_type_t type = attributes->type;
if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type) &&
(PSA_KEY_TYPE_IS_RSA(type) || PSA_KEY_TYPE_IS_ECC(type) ||
@@ -1599,7 +1550,7 @@
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
psa_key_slot_t *slot;
- psa_key_attributes_t attributes;
+
LOCAL_OUTPUT_DECLARE(data_external, data);
/* Reject a zero-length output buffer now, since this can never be a
@@ -1628,30 +1579,17 @@
goto exit;
}
- attributes = (psa_key_attributes_t) {
- .core = slot->attr
- };
status = psa_driver_wrapper_export_public_key(
- &attributes, slot->key.data, slot->key.bytes,
+ &slot->attr, slot->key.data, slot->key.bytes,
data, data_size, data_length);
exit:
- unlock_status = psa_unregister_read(slot);
+ unlock_status = psa_unregister_read_under_mutex(slot);
LOCAL_OUTPUT_FREE(data_external, data);
return (status == PSA_SUCCESS) ? unlock_status : status;
}
-MBEDTLS_STATIC_ASSERT(
- (MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_DUAL_USE) == 0,
- "One or more key attribute flag is listed as both external-only and dual-use")
-MBEDTLS_STATIC_ASSERT(
- (PSA_KA_MASK_INTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_DUAL_USE) == 0,
- "One or more key attribute flag is listed as both internal-only and dual-use")
-MBEDTLS_STATIC_ASSERT(
- (PSA_KA_MASK_INTERNAL_ONLY & MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY) == 0,
- "One or more key attribute flag is listed as both internal-only and external-only")
-
/** Validate that a key policy is internally well-formed.
*
* This function only rejects invalid policies. It does not validate the
@@ -1717,7 +1655,7 @@
}
}
- status = psa_validate_key_policy(&attributes->core.policy);
+ status = psa_validate_key_policy(&attributes->policy);
if (status != PSA_SUCCESS) {
return status;
}
@@ -1730,12 +1668,6 @@
return PSA_ERROR_NOT_SUPPORTED;
}
- /* Reject invalid flags. These should not be reachable through the API. */
- if (attributes->core.flags & ~(MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY |
- MBEDTLS_PSA_KA_MASK_DUAL_USE)) {
- return PSA_ERROR_INVALID_ARGUMENT;
- }
-
return PSA_SUCCESS;
}
@@ -1787,7 +1719,15 @@
return status;
}
+#if defined(MBEDTLS_THREADING_C)
+ PSA_THREADING_CHK_RET(mbedtls_mutex_lock(
+ &mbedtls_threading_key_slot_mutex));
+#endif
status = psa_reserve_free_key_slot(&volatile_key_id, p_slot);
+#if defined(MBEDTLS_THREADING_C)
+ PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+ &mbedtls_threading_key_slot_mutex));
+#endif
if (status != PSA_SUCCESS) {
return status;
}
@@ -1801,7 +1741,7 @@
* volatile key identifier associated to the slot returned to contain its
* definition. */
- slot->attr = attributes->core;
+ slot->attr = *attributes;
if (PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) {
#if !defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)
slot->attr.id = volatile_key_id;
@@ -1810,13 +1750,6 @@
#endif
}
- /* Erase external-only flags from the internal copy. To access
- * external-only flags, query `attributes`. Thanks to the check
- * in psa_validate_key_attributes(), this leaves the dual-use
- * flags and any internal flag that psa_reserve_free_key_slot()
- * may have set. */
- slot->attr.flags &= ~MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY;
-
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
/* For a key in a secure element, we need to do three things
* when creating or registering a persistent key:
@@ -1843,7 +1776,7 @@
return status;
}
- if (!PSA_KEY_LIFETIME_IS_VOLATILE(attributes->core.lifetime)) {
+ if (!PSA_KEY_LIFETIME_IS_VOLATILE(attributes->lifetime)) {
psa_crypto_prepare_transaction(PSA_CRYPTO_TRANSACTION_CREATE_KEY);
psa_crypto_transaction.key.lifetime = slot->attr.lifetime;
psa_crypto_transaction.key.slot = slot_number;
@@ -1907,6 +1840,11 @@
(void) slot;
(void) driver;
+#if defined(MBEDTLS_THREADING_C)
+ PSA_THREADING_CHK_RET(mbedtls_mutex_lock(
+ &mbedtls_threading_key_slot_mutex));
+#endif
+
#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
if (!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) {
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
@@ -1946,6 +1884,11 @@
status = psa_save_se_persistent_data(driver);
if (status != PSA_SUCCESS) {
psa_destroy_persistent_key(slot->attr.id);
+
+#if defined(MBEDTLS_THREADING_C)
+ PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+ &mbedtls_threading_key_slot_mutex));
+#endif
return status;
}
status = psa_crypto_stop_transaction();
@@ -1961,6 +1904,10 @@
}
}
+#if defined(MBEDTLS_THREADING_C)
+ PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+ &mbedtls_threading_key_slot_mutex));
+#endif
return status;
}
@@ -1985,6 +1932,13 @@
return;
}
+#if defined(MBEDTLS_THREADING_C)
+ /* If the lock operation fails we still wipe the slot.
+ * Operations will no longer work after a failed lock,
+ * but we still need to wipe the slot of confidential data. */
+ mbedtls_mutex_lock(&mbedtls_threading_key_slot_mutex);
+#endif
+
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
/* TODO: If the key has already been created in the secure
* element, and the failure happened later (when saving metadata
@@ -2003,6 +1957,10 @@
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
psa_wipe_key_slot(slot);
+
+#if defined(MBEDTLS_THREADING_C)
+ mbedtls_mutex_unlock(&mbedtls_threading_key_slot_mutex);
+#endif
}
/** Validate optional attributes during key creation.
@@ -2018,65 +1976,14 @@
const psa_key_slot_t *slot,
const psa_key_attributes_t *attributes)
{
- if (attributes->core.type != 0) {
- if (attributes->core.type != slot->attr.type) {
+ if (attributes->type != 0) {
+ if (attributes->type != slot->attr.type) {
return PSA_ERROR_INVALID_ARGUMENT;
}
}
- if (attributes->domain_parameters_size != 0) {
-#if (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && \
- defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) || \
- defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
- if (PSA_KEY_TYPE_IS_RSA(slot->attr.type)) {
- mbedtls_rsa_context *rsa = NULL;
- mbedtls_mpi actual, required;
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-
- psa_status_t status = mbedtls_psa_rsa_load_representation(
- slot->attr.type,
- slot->key.data,
- slot->key.bytes,
- &rsa);
- if (status != PSA_SUCCESS) {
- return status;
- }
-
- mbedtls_mpi_init(&actual);
- mbedtls_mpi_init(&required);
- ret = mbedtls_rsa_export(rsa,
- NULL, NULL, NULL, NULL, &actual);
- mbedtls_rsa_free(rsa);
- mbedtls_free(rsa);
- if (ret != 0) {
- goto rsa_exit;
- }
- ret = mbedtls_mpi_read_binary(&required,
- attributes->domain_parameters,
- attributes->domain_parameters_size);
- if (ret != 0) {
- goto rsa_exit;
- }
- if (mbedtls_mpi_cmp_mpi(&actual, &required) != 0) {
- ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
- }
-rsa_exit:
- mbedtls_mpi_free(&actual);
- mbedtls_mpi_free(&required);
- if (ret != 0) {
- return mbedtls_to_psa_error(ret);
- }
- } else
-#endif /* (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) &&
- * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) ||
- * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
- {
- return PSA_ERROR_INVALID_ARGUMENT;
- }
- }
-
- if (attributes->core.bits != 0) {
- if (attributes->core.bits != slot->attr.bits) {
+ if (attributes->bits != 0) {
+ if (attributes->bits != slot->attr.bits) {
return PSA_ERROR_INVALID_ARGUMENT;
}
}
@@ -2123,7 +2030,7 @@
* with storage ( MBEDTLS_PSA_CRYPTO_SE_C ) ),we have to allocate a
* buffer to hold the imported key material. */
if (slot->key.data == NULL) {
- if (psa_key_lifetime_is_external(attributes->core.lifetime)) {
+ if (psa_key_lifetime_is_external(attributes->lifetime)) {
status = psa_driver_wrapper_get_key_buffer_size_from_key_data(
attributes, data, data_length, &storage_size);
if (status != PSA_SUCCESS) {
@@ -2244,12 +2151,12 @@
* equal to the ones of the source key. So it is safe to inherit
* them from the source key now."
* */
- actual_attributes.core.bits = source_slot->attr.bits;
- actual_attributes.core.type = source_slot->attr.type;
+ actual_attributes.bits = source_slot->attr.bits;
+ actual_attributes.type = source_slot->attr.type;
status = psa_restrict_key_policy(source_slot->attr.type,
- &actual_attributes.core.policy,
+ &actual_attributes.policy,
&source_slot->attr.policy);
if (status != PSA_SUCCESS) {
goto exit;
@@ -2278,7 +2185,7 @@
* - For opaque keys this translates to an invocation of the drivers'
* copy_key entry point through the dispatch layer.
* */
- if (psa_key_lifetime_is_external(actual_attributes.core.lifetime)) {
+ if (psa_key_lifetime_is_external(actual_attributes.lifetime)) {
status = psa_driver_wrapper_get_key_buffer_size(&actual_attributes,
&storage_size);
if (status != PSA_SUCCESS) {
@@ -2313,7 +2220,7 @@
psa_fail_key_creation(target_slot, driver);
}
- unlock_status = psa_unregister_read(source_slot);
+ unlock_status = psa_unregister_read_under_mutex(source_slot);
return (status == PSA_SUCCESS) ? unlock_status : status;
}
@@ -2639,7 +2546,6 @@
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
psa_key_slot_t *slot = NULL;
- psa_key_attributes_t attributes;
/* A context must be freshly initialized before it can be set up. */
if (operation->id != 0) {
@@ -2656,11 +2562,7 @@
goto exit;
}
- attributes = (psa_key_attributes_t) {
- .core = slot->attr
- };
-
- status = psa_mac_finalize_alg_and_key_validation(alg, &attributes,
+ status = psa_mac_finalize_alg_and_key_validation(alg, &slot->attr,
&operation->mac_size);
if (status != PSA_SUCCESS) {
goto exit;
@@ -2670,13 +2572,13 @@
/* Dispatch the MAC setup call with validated input */
if (is_sign) {
status = psa_driver_wrapper_mac_sign_setup(operation,
- &attributes,
+ &slot->attr,
slot->key.data,
slot->key.bytes,
alg);
} else {
status = psa_driver_wrapper_mac_verify_setup(operation,
- &attributes,
+ &slot->attr,
slot->key.data,
slot->key.bytes,
alg);
@@ -2687,7 +2589,7 @@
psa_mac_abort(operation);
}
- unlock_status = psa_unregister_read(slot);
+ unlock_status = psa_unregister_read_under_mutex(slot);
return (status == PSA_SUCCESS) ? unlock_status : status;
}
@@ -2846,7 +2748,6 @@
psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
psa_key_slot_t *slot;
uint8_t operation_mac_size = 0;
- psa_key_attributes_t attributes;
status = psa_get_and_lock_key_slot_with_policy(
key,
@@ -2857,11 +2758,7 @@
goto exit;
}
- attributes = (psa_key_attributes_t) {
- .core = slot->attr
- };
-
- status = psa_mac_finalize_alg_and_key_validation(alg, &attributes,
+ status = psa_mac_finalize_alg_and_key_validation(alg, &slot->attr,
&operation_mac_size);
if (status != PSA_SUCCESS) {
goto exit;
@@ -2873,7 +2770,7 @@
}
status = psa_driver_wrapper_mac_compute(
- &attributes,
+ &slot->attr,
slot->key.data, slot->key.bytes,
alg,
input, input_length,
@@ -2893,7 +2790,7 @@
psa_wipe_tag_output_buffer(mac, status, mac_size, *mac_length);
- unlock_status = psa_unregister_read(slot);
+ unlock_status = psa_unregister_read_under_mutex(slot);
return (status == PSA_SUCCESS) ? unlock_status : status;
}
@@ -3004,7 +2901,6 @@
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
psa_key_slot_t *slot;
- psa_key_attributes_t attributes;
*signature_length = 0;
@@ -3036,19 +2932,15 @@
goto exit;
}
- attributes = (psa_key_attributes_t) {
- .core = slot->attr
- };
-
if (input_is_message) {
status = psa_driver_wrapper_sign_message(
- &attributes, slot->key.data, slot->key.bytes,
+ &slot->attr, slot->key.data, slot->key.bytes,
alg, input, input_length,
signature, signature_size, signature_length);
} else {
status = psa_driver_wrapper_sign_hash(
- &attributes, slot->key.data, slot->key.bytes,
+ &slot->attr, slot->key.data, slot->key.bytes,
alg, input, input_length,
signature, signature_size, signature_length);
}
@@ -3058,7 +2950,7 @@
psa_wipe_tag_output_buffer(signature, status, signature_size,
*signature_length);
- unlock_status = psa_unregister_read(slot);
+ unlock_status = psa_unregister_read_under_mutex(slot);
return (status == PSA_SUCCESS) ? unlock_status : status;
}
@@ -3090,23 +2982,19 @@
return status;
}
- psa_key_attributes_t attributes = {
- .core = slot->attr
- };
-
if (input_is_message) {
status = psa_driver_wrapper_verify_message(
- &attributes, slot->key.data, slot->key.bytes,
+ &slot->attr, slot->key.data, slot->key.bytes,
alg, input, input_length,
signature, signature_length);
} else {
status = psa_driver_wrapper_verify_hash(
- &attributes, slot->key.data, slot->key.bytes,
+ &slot->attr, slot->key.data, slot->key.bytes,
alg, input, input_length,
signature, signature_length);
}
- unlock_status = psa_unregister_read(slot);
+ unlock_status = psa_unregister_read_under_mutex(slot);
return (status == PSA_SUCCESS) ? unlock_status : status;
@@ -3237,7 +3125,7 @@
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
uint8_t *signature, size_t signature_size, size_t *signature_length)
{
- if (attributes->core.type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
+ if (attributes->type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) ||
PSA_ALG_IS_RSA_PSS(alg)) {
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
@@ -3252,7 +3140,7 @@
} else {
return PSA_ERROR_INVALID_ARGUMENT;
}
- } else if (PSA_KEY_TYPE_IS_ECC(attributes->core.type)) {
+ } else if (PSA_KEY_TYPE_IS_ECC(attributes->type)) {
if (PSA_ALG_IS_ECDSA(alg)) {
#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
@@ -3311,7 +3199,7 @@
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
const uint8_t *signature, size_t signature_length)
{
- if (PSA_KEY_TYPE_IS_RSA(attributes->core.type)) {
+ if (PSA_KEY_TYPE_IS_RSA(attributes->type)) {
if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) ||
PSA_ALG_IS_RSA_PSS(alg)) {
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
@@ -3326,7 +3214,7 @@
} else {
return PSA_ERROR_INVALID_ARGUMENT;
}
- } else if (PSA_KEY_TYPE_IS_ECC(attributes->core.type)) {
+ } else if (PSA_KEY_TYPE_IS_ECC(attributes->type)) {
if (PSA_ALG_IS_ECDSA(alg)) {
#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
@@ -3390,7 +3278,7 @@
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
psa_key_slot_t *slot;
- psa_key_attributes_t attributes;
+
LOCAL_INPUT_DECLARE(input_external, input);
LOCAL_INPUT_DECLARE(salt_external, salt);
LOCAL_OUTPUT_DECLARE(output_external, output);
@@ -3418,19 +3306,16 @@
goto exit;
}
- attributes = (psa_key_attributes_t) {
- .core = slot->attr
- };
-
LOCAL_INPUT_ALLOC(input_external, input_length, input);
LOCAL_INPUT_ALLOC(salt_external, salt_length, salt);
LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
+
status = psa_driver_wrapper_asymmetric_encrypt(
- &attributes, slot->key.data, slot->key.bytes,
+ &slot->attr, slot->key.data, slot->key.bytes,
alg, input, input_length, salt, salt_length,
output, output_size, output_length);
exit:
- unlock_status = psa_unregister_read(slot);
+ unlock_status = psa_unregister_read_under_mutex(slot);
LOCAL_INPUT_FREE(input_external, input);
LOCAL_INPUT_FREE(salt_external, salt);
@@ -3452,7 +3337,6 @@
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
psa_key_slot_t *slot;
- psa_key_attributes_t attributes;
LOCAL_INPUT_DECLARE(input_external, input);
LOCAL_INPUT_DECLARE(salt_external, salt);
@@ -3480,20 +3364,17 @@
goto exit;
}
- attributes = (psa_key_attributes_t) {
- .core = slot->attr
- };
-
LOCAL_INPUT_ALLOC(input_external, input_length, input);
LOCAL_INPUT_ALLOC(salt_external, salt_length, salt);
LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
+
status = psa_driver_wrapper_asymmetric_decrypt(
- &attributes, slot->key.data, slot->key.bytes,
+ &slot->attr, slot->key.data, slot->key.bytes,
alg, input, input_length, salt, salt_length,
output, output_size, output_length);
exit:
- unlock_status = psa_unregister_read(slot);
+ unlock_status = psa_unregister_read_under_mutex(slot);
LOCAL_INPUT_FREE(input_external, input);
LOCAL_INPUT_FREE(salt_external, salt);
@@ -3561,7 +3442,6 @@
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
psa_key_slot_t *slot;
- psa_key_attributes_t attributes;
LOCAL_INPUT_DECLARE(hash_external, hash);
@@ -3592,14 +3472,10 @@
LOCAL_INPUT_ALLOC(hash_external, hash_length, hash);
- attributes = (psa_key_attributes_t) {
- .core = slot->attr
- };
-
/* Ensure ops count gets reset, in case of operation re-use. */
operation->num_ops = 0;
- status = psa_driver_wrapper_sign_hash_start(operation, &attributes,
+ status = psa_driver_wrapper_sign_hash_start(operation, &slot->attr,
slot->key.data,
slot->key.bytes, alg,
hash, hash_length);
@@ -3610,7 +3486,7 @@
psa_sign_hash_abort_internal(operation);
}
- unlock_status = psa_unregister_read(slot);
+ unlock_status = psa_unregister_read_under_mutex(slot);
if (unlock_status != PSA_SUCCESS) {
operation->error_occurred = 1;
@@ -3753,14 +3629,10 @@
LOCAL_INPUT_ALLOC(hash_external, hash_length, hash);
LOCAL_INPUT_ALLOC(signature_external, signature_length, signature);
- psa_key_attributes_t attributes = {
- .core = slot->attr
- };
-
/* Ensure ops count gets reset, in case of operation re-use. */
operation->num_ops = 0;
- status = psa_driver_wrapper_verify_hash_start(operation, &attributes,
+ status = psa_driver_wrapper_verify_hash_start(operation, &slot->attr,
slot->key.data,
slot->key.bytes,
alg, hash, hash_length,
@@ -3774,7 +3646,7 @@
psa_verify_hash_abort_internal(operation);
}
- unlock_status = psa_unregister_read(slot);
+ unlock_status = psa_unregister_read_under_mutex(slot);
if (unlock_status != PSA_SUCCESS) {
operation->error_occurred = 1;
@@ -3901,7 +3773,7 @@
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
size_t required_hash_length;
- if (!PSA_KEY_TYPE_IS_ECC(attributes->core.type)) {
+ if (!PSA_KEY_TYPE_IS_ECC(attributes->type)) {
return PSA_ERROR_NOT_SUPPORTED;
}
@@ -3918,8 +3790,8 @@
/* Ensure num_ops is zero'ed in case of context re-use. */
operation->num_ops = 0;
- status = mbedtls_psa_ecp_load_representation(attributes->core.type,
- attributes->core.bits,
+ status = mbedtls_psa_ecp_load_representation(attributes->type,
+ attributes->bits,
key_buffer,
key_buffer_size,
&operation->ctx);
@@ -4117,7 +3989,7 @@
size_t coordinate_bytes = 0;
size_t required_hash_length = 0;
- if (!PSA_KEY_TYPE_IS_ECC(attributes->core.type)) {
+ if (!PSA_KEY_TYPE_IS_ECC(attributes->type)) {
return PSA_ERROR_NOT_SUPPORTED;
}
@@ -4136,8 +4008,8 @@
/* Ensure num_ops is zero'ed in case of context re-use. */
operation->num_ops = 0;
- status = mbedtls_psa_ecp_load_representation(attributes->core.type,
- attributes->core.bits,
+ status = mbedtls_psa_ecp_load_representation(attributes->type,
+ attributes->bits,
key_buffer,
key_buffer_size,
&operation->ctx);
@@ -4285,8 +4157,6 @@
{
GUARD_MODULE_INITIALIZED;
- psa_status_t status;
-
#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
size_t output_length = 0;
@@ -4307,24 +4177,24 @@
#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
while (output_size > 0) {
+ int ret = MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;
size_t request_size =
(output_size > MBEDTLS_PSA_RANDOM_MAX_REQUEST ?
MBEDTLS_PSA_RANDOM_MAX_REQUEST :
output_size);
- int ret = mbedtls_psa_get_random(MBEDTLS_PSA_RANDOM_STATE,
- output, request_size);
+#if defined(MBEDTLS_CTR_DRBG_C)
+ ret = mbedtls_ctr_drbg_random(&global_data.rng.drbg, output, request_size);
+#elif defined(MBEDTLS_HMAC_DRBG_C)
+ ret = mbedtls_hmac_drbg_random(&global_data.rng.drbg, output, request_size);
+#endif /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C */
if (ret != 0) {
- status = mbedtls_to_psa_error(ret);
- goto exit;
+ return mbedtls_to_psa_error(ret);
}
output_size -= request_size;
output += request_size;
}
- status = PSA_SUCCESS;
+ return PSA_SUCCESS;
#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
-
-exit:
- return status;
}
@@ -4343,7 +4213,6 @@
psa_key_usage_t usage = (cipher_operation == MBEDTLS_ENCRYPT ?
PSA_KEY_USAGE_ENCRYPT :
PSA_KEY_USAGE_DECRYPT);
- psa_key_attributes_t attributes;
/* A context must be freshly initialized before it can be set up. */
if (operation->id != 0) {
@@ -4373,20 +4242,16 @@
}
operation->default_iv_length = PSA_CIPHER_IV_LENGTH(slot->attr.type, alg);
- attributes = (psa_key_attributes_t) {
- .core = slot->attr
- };
-
/* Try doing the operation through a driver before using software fallback. */
if (cipher_operation == MBEDTLS_ENCRYPT) {
status = psa_driver_wrapper_cipher_encrypt_setup(operation,
- &attributes,
+ &slot->attr,
slot->key.data,
slot->key.bytes,
alg);
} else {
status = psa_driver_wrapper_cipher_decrypt_setup(operation,
- &attributes,
+ &slot->attr,
slot->key.data,
slot->key.bytes,
alg);
@@ -4397,7 +4262,7 @@
psa_cipher_abort(operation);
}
- unlock_status = psa_unregister_read(slot);
+ unlock_status = psa_unregister_read_under_mutex(slot);
return (status == PSA_SUCCESS) ? unlock_status : status;
}
@@ -4627,7 +4492,6 @@
psa_key_slot_t *slot = NULL;
uint8_t local_iv[PSA_CIPHER_IV_MAX_SIZE];
size_t default_iv_length = 0;
- psa_key_attributes_t attributes;
LOCAL_INPUT_DECLARE(input_external, input);
LOCAL_OUTPUT_DECLARE(output_external, output);
@@ -4644,10 +4508,6 @@
goto exit;
}
- attributes = (psa_key_attributes_t) {
- .core = slot->attr
- };
-
default_iv_length = PSA_CIPHER_IV_LENGTH(slot->attr.type, alg);
if (default_iv_length > PSA_CIPHER_IV_MAX_SIZE) {
status = PSA_ERROR_GENERIC_ERROR;
@@ -4670,13 +4530,13 @@
LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
status = psa_driver_wrapper_cipher_encrypt(
- &attributes, slot->key.data, slot->key.bytes,
+ &slot->attr, slot->key.data, slot->key.bytes,
alg, local_iv, default_iv_length, input, input_length,
psa_crypto_buffer_offset(output, default_iv_length),
output_size - default_iv_length, output_length);
exit:
- unlock_status = psa_unregister_read(slot);
+ unlock_status = psa_unregister_read_under_mutex(slot);
if (status == PSA_SUCCESS) {
status = unlock_status;
}
@@ -4707,7 +4567,6 @@
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
psa_key_slot_t *slot = NULL;
- psa_key_attributes_t attributes;
LOCAL_INPUT_DECLARE(input_external, input);
LOCAL_OUTPUT_DECLARE(output_external, output);
@@ -4724,10 +4583,6 @@
goto exit;
}
- attributes = (psa_key_attributes_t) {
- .core = slot->attr
- };
-
if (alg == PSA_ALG_CCM_STAR_NO_TAG &&
input_length < PSA_BLOCK_CIPHER_BLOCK_LENGTH(slot->attr.type)) {
status = PSA_ERROR_INVALID_ARGUMENT;
@@ -4741,12 +4596,12 @@
LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
status = psa_driver_wrapper_cipher_decrypt(
- &attributes, slot->key.data, slot->key.bytes,
+ &slot->attr, slot->key.data, slot->key.bytes,
alg, input, input_length,
output, output_size, output_length);
exit:
- unlock_status = psa_unregister_read(slot);
+ unlock_status = psa_unregister_read_under_mutex(slot);
if (status == PSA_SUCCESS) {
status = unlock_status;
}
@@ -4858,10 +4713,6 @@
return status;
}
- psa_key_attributes_t attributes = {
- .core = slot->attr
- };
-
LOCAL_INPUT_ALLOC(nonce_external, nonce_length, nonce);
LOCAL_INPUT_ALLOC(additional_data_external, additional_data_length, additional_data);
LOCAL_INPUT_ALLOC(plaintext_external, plaintext_length, plaintext);
@@ -4873,7 +4724,7 @@
}
status = psa_driver_wrapper_aead_encrypt(
- &attributes, slot->key.data, slot->key.bytes,
+ &slot->attr, slot->key.data, slot->key.bytes,
alg,
nonce, nonce_length,
additional_data, additional_data_length,
@@ -4890,7 +4741,7 @@
LOCAL_INPUT_FREE(plaintext_external, plaintext);
LOCAL_OUTPUT_FREE(ciphertext_external, ciphertext);
- psa_unregister_read(slot);
+ psa_unregister_read_under_mutex(slot);
return status;
}
@@ -4928,10 +4779,6 @@
return status;
}
- psa_key_attributes_t attributes = {
- .core = slot->attr
- };
-
LOCAL_INPUT_ALLOC(nonce_external, nonce_length, nonce);
LOCAL_INPUT_ALLOC(additional_data_external, additional_data_length,
additional_data);
@@ -4944,7 +4791,7 @@
}
status = psa_driver_wrapper_aead_decrypt(
- &attributes, slot->key.data, slot->key.bytes,
+ &slot->attr, slot->key.data, slot->key.bytes,
alg,
nonce, nonce_length,
additional_data, additional_data_length,
@@ -4961,7 +4808,7 @@
LOCAL_INPUT_FREE(ciphertext_external, ciphertext);
LOCAL_OUTPUT_FREE(plaintext_external, plaintext);
- psa_unregister_read(slot);
+ psa_unregister_read_under_mutex(slot);
return status;
}
@@ -5015,7 +4862,6 @@
psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
psa_key_slot_t *slot = NULL;
psa_key_usage_t key_usage = 0;
- psa_key_attributes_t attributes;
status = psa_aead_check_algorithm(alg);
if (status != PSA_SUCCESS) {
@@ -5045,23 +4891,19 @@
goto exit;
}
- attributes = (psa_key_attributes_t) {
- .core = slot->attr
- };
-
if ((status = psa_validate_tag_length(alg)) != PSA_SUCCESS) {
goto exit;
}
if (is_encrypt) {
status = psa_driver_wrapper_aead_encrypt_setup(operation,
- &attributes,
+ &slot->attr,
slot->key.data,
slot->key.bytes,
alg);
} else {
status = psa_driver_wrapper_aead_decrypt_setup(operation,
- &attributes,
+ &slot->attr,
slot->key.data,
slot->key.bytes,
alg);
@@ -5070,10 +4912,10 @@
goto exit;
}
- operation->key_type = psa_get_key_type(&attributes);
+ operation->key_type = psa_get_key_type(&slot->attr);
exit:
- unlock_status = psa_unregister_read(slot);
+ unlock_status = psa_unregister_read_under_mutex(slot);
if (status == PSA_SUCCESS) {
status = unlock_status;
@@ -6445,7 +6287,6 @@
size_t bytes = PSA_BITS_TO_BYTES(bits);
size_t storage_size = bytes;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
- psa_key_attributes_t attributes;
if (PSA_KEY_TYPE_IS_PUBLIC_KEY(slot->attr.type)) {
return PSA_ERROR_INVALID_ARGUMENT;
@@ -6494,12 +6335,9 @@
}
slot->attr.bits = (psa_key_bits_t) bits;
- attributes = (psa_key_attributes_t) {
- .core = slot->attr
- };
- if (psa_key_lifetime_is_external(attributes.core.lifetime)) {
- status = psa_driver_wrapper_get_key_buffer_size(&attributes,
+ if (psa_key_lifetime_is_external(slot->attr.lifetime)) {
+ status = psa_driver_wrapper_get_key_buffer_size(&slot->attr,
&storage_size);
if (status != PSA_SUCCESS) {
goto exit;
@@ -6510,7 +6348,7 @@
goto exit;
}
- status = psa_driver_wrapper_import_key(&attributes,
+ status = psa_driver_wrapper_import_key(&slot->attr,
data, bytes,
slot->key.data,
slot->key.bytes,
@@ -6524,9 +6362,28 @@
return status;
}
-psa_status_t psa_key_derivation_output_key(const psa_key_attributes_t *attributes,
- psa_key_derivation_operation_t *operation,
- mbedtls_svc_key_id_t *key)
+static const psa_key_production_parameters_t default_production_parameters =
+ PSA_KEY_PRODUCTION_PARAMETERS_INIT;
+
+int psa_key_production_parameters_are_default(
+ const psa_key_production_parameters_t *params,
+ size_t params_data_length)
+{
+ if (params->flags != 0) {
+ return 0;
+ }
+ if (params_data_length != 0) {
+ return 0;
+ }
+ return 1;
+}
+
+psa_status_t psa_key_derivation_output_key_ext(
+ const psa_key_attributes_t *attributes,
+ psa_key_derivation_operation_t *operation,
+ const psa_key_production_parameters_t *params,
+ size_t params_data_length,
+ mbedtls_svc_key_id_t *key)
{
psa_status_t status;
psa_key_slot_t *slot = NULL;
@@ -6540,6 +6397,10 @@
return PSA_ERROR_INVALID_ARGUMENT;
}
+ if (!psa_key_production_parameters_are_default(params, params_data_length)) {
+ return PSA_ERROR_INVALID_ARGUMENT;
+ }
+
if (operation->alg == PSA_ALG_NONE) {
return PSA_ERROR_BAD_STATE;
}
@@ -6558,7 +6419,7 @@
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
if (status == PSA_SUCCESS) {
status = psa_generate_derived_key_internal(slot,
- attributes->core.bits,
+ attributes->bits,
operation);
}
if (status == PSA_SUCCESS) {
@@ -6571,6 +6432,15 @@
return status;
}
+psa_status_t psa_key_derivation_output_key(
+ const psa_key_attributes_t *attributes,
+ psa_key_derivation_operation_t *operation,
+ mbedtls_svc_key_id_t *key)
+{
+ return psa_key_derivation_output_key_ext(attributes, operation,
+ &default_production_parameters, 0,
+ key);
+}
/****************************************************************/
@@ -6631,6 +6501,91 @@
return status;
}
+static psa_status_t psa_key_derivation_set_maximum_capacity(
+ psa_key_derivation_operation_t *operation,
+ psa_algorithm_t kdf_alg)
+{
+#if defined(PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS)
+ if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) {
+ operation->capacity = PSA_HASH_LENGTH(PSA_ALG_SHA_256);
+ return PSA_SUCCESS;
+ }
+#endif
+#if defined(PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128)
+ if (kdf_alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128) {
+#if (SIZE_MAX > UINT32_MAX)
+ operation->capacity = UINT32_MAX * (size_t) PSA_MAC_LENGTH(
+ PSA_KEY_TYPE_AES,
+ 128U,
+ PSA_ALG_CMAC);
+#else
+ operation->capacity = SIZE_MAX;
+#endif
+ return PSA_SUCCESS;
+ }
+#endif /* PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 */
+
+ /* After this point, if kdf_alg is not valid then value of hash_alg may be
+ * invalid or meaningless but it does not affect this function */
+ psa_algorithm_t hash_alg = PSA_ALG_GET_HASH(kdf_alg);
+ size_t hash_size = PSA_HASH_LENGTH(hash_alg);
+ if (hash_size == 0) {
+ return PSA_ERROR_NOT_SUPPORTED;
+ }
+
+ /* Make sure that hash_alg is a supported hash algorithm. Otherwise
+ * we might fail later, which is somewhat unfriendly and potentially
+ * risk-prone. */
+ psa_status_t status = psa_hash_try_support(hash_alg);
+ if (status != PSA_SUCCESS) {
+ return status;
+ }
+
+#if defined(PSA_WANT_ALG_HKDF)
+ if (PSA_ALG_IS_HKDF(kdf_alg)) {
+ operation->capacity = 255 * hash_size;
+ } else
+#endif
+#if defined(PSA_WANT_ALG_HKDF_EXTRACT)
+ if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) {
+ operation->capacity = hash_size;
+ } else
+#endif
+#if defined(PSA_WANT_ALG_HKDF_EXPAND)
+ if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) {
+ operation->capacity = 255 * hash_size;
+ } else
+#endif
+#if defined(PSA_WANT_ALG_TLS12_PRF)
+ if (PSA_ALG_IS_TLS12_PRF(kdf_alg) &&
+ (hash_alg == PSA_ALG_SHA_256 || hash_alg == PSA_ALG_SHA_384)) {
+ operation->capacity = SIZE_MAX;
+ } else
+#endif
+#if defined(PSA_WANT_ALG_TLS12_PSK_TO_MS)
+ if (PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg) &&
+ (hash_alg == PSA_ALG_SHA_256 || hash_alg == PSA_ALG_SHA_384)) {
+ /* Master Secret is always 48 bytes
+ * https://datatracker.ietf.org/doc/html/rfc5246.html#section-8.1 */
+ operation->capacity = 48U;
+ } else
+#endif
+#if defined(PSA_WANT_ALG_PBKDF2_HMAC)
+ if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) {
+#if (SIZE_MAX > UINT32_MAX)
+ operation->capacity = UINT32_MAX * hash_size;
+#else
+ operation->capacity = SIZE_MAX;
+#endif
+ } else
+#endif /* PSA_WANT_ALG_PBKDF2_HMAC */
+ {
+ (void) hash_size;
+ status = PSA_ERROR_NOT_SUPPORTED;
+ }
+ return status;
+}
+
static psa_status_t psa_key_derivation_setup_kdf(
psa_key_derivation_operation_t *operation,
psa_algorithm_t kdf_alg)
@@ -6644,43 +6599,9 @@
return PSA_ERROR_NOT_SUPPORTED;
}
- /* All currently supported key derivation algorithms (apart from
- * ecjpake to pms and pbkdf2_aes_cmac_128) are based on a hash algorithm. */
- psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH(kdf_alg);
- size_t hash_size = PSA_HASH_LENGTH(hash_alg);
- if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) {
- hash_size = PSA_HASH_LENGTH(PSA_ALG_SHA_256);
- } else if (kdf_alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128) {
- hash_size = PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC);
- } else {
- if (hash_size == 0) {
- return PSA_ERROR_NOT_SUPPORTED;
- }
-
- /* Make sure that hash_alg is a supported hash algorithm. Otherwise
- * we might fail later, which is somewhat unfriendly and potentially
- * risk-prone. */
- psa_status_t status = psa_hash_try_support(hash_alg);
- if (status != PSA_SUCCESS) {
- return status;
- }
- }
-
- if ((PSA_ALG_IS_TLS12_PRF(kdf_alg) ||
- PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) &&
- !(hash_alg == PSA_ALG_SHA_256 || hash_alg == PSA_ALG_SHA_384)) {
- return PSA_ERROR_NOT_SUPPORTED;
- }
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) || \
- defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS)
- if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg) ||
- (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS)) {
- operation->capacity = hash_size;
- } else
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT ||
- MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */
- operation->capacity = 255 * hash_size;
- return PSA_SUCCESS;
+ psa_status_t status = psa_key_derivation_set_maximum_capacity(operation,
+ kdf_alg);
+ return status;
}
static psa_status_t psa_key_agreement_try_support(psa_algorithm_t alg)
@@ -7478,7 +7399,7 @@
slot->key.data,
slot->key.bytes);
- unlock_status = psa_unregister_read(slot);
+ unlock_status = psa_unregister_read_under_mutex(slot);
return (status == PSA_SUCCESS) ? unlock_status : status;
}
@@ -7553,11 +7474,7 @@
return PSA_ERROR_NOT_SUPPORTED;
}
- psa_key_attributes_t attributes = {
- .core = private_key->attr
- };
-
- return psa_driver_wrapper_key_agreement(&attributes,
+ return psa_driver_wrapper_key_agreement(&private_key->attr,
private_key->key.data,
private_key->key.bytes, alg,
peer_key, peer_key_length,
@@ -7576,7 +7493,7 @@
size_t peer_key_length)
{
psa_status_t status;
- uint8_t shared_secret[PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE];
+ uint8_t shared_secret[PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE] = { 0 };
size_t shared_secret_length = 0;
psa_algorithm_t ka_alg = PSA_ALG_KEY_AGREEMENT_GET_BASE(operation->alg);
@@ -7642,8 +7559,9 @@
}
}
- unlock_status = psa_unregister_read(slot);
+ unlock_status = psa_unregister_read_under_mutex(slot);
LOCAL_INPUT_FREE(peer_key_external, peer_key);
+
return (status == PSA_SUCCESS) ? unlock_status : status;
}
@@ -7714,7 +7632,7 @@
*output_length = 0;
}
- unlock_status = psa_unregister_read(slot);
+ unlock_status = psa_unregister_read_under_mutex(slot);
LOCAL_INPUT_FREE(peer_key_external, peer_key);
LOCAL_OUTPUT_FREE(output_external, output);
@@ -7758,7 +7676,7 @@
MBEDTLS_ENTROPY_SOURCE_STRONG);
#endif
- mbedtls_psa_drbg_init(MBEDTLS_PSA_RANDOM_STATE);
+ mbedtls_psa_drbg_init(&rng->drbg);
#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
}
@@ -7769,7 +7687,7 @@
#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
memset(rng, 0, sizeof(*rng));
#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
- mbedtls_psa_drbg_free(MBEDTLS_PSA_RANDOM_STATE);
+ mbedtls_psa_drbg_free(&rng->drbg);
rng->entropy_free(&rng->entropy);
#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
}
@@ -7784,7 +7702,7 @@
return PSA_SUCCESS;
#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
const unsigned char drbg_seed[] = "PSA";
- int ret = mbedtls_psa_drbg_seed(&rng->entropy,
+ int ret = mbedtls_psa_drbg_seed(&rng->drbg, &rng->entropy,
drbg_seed, sizeof(drbg_seed) - 1);
return mbedtls_to_psa_error(ret);
#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
@@ -7807,39 +7725,6 @@
return status;
}
-/* Wrapper function allowing the classic API to use the PSA RNG.
- *
- * `mbedtls_psa_get_random(MBEDTLS_PSA_RANDOM_STATE, ...)` calls
- * `psa_generate_random(...)`. The state parameter is ignored since the
- * PSA API doesn't support passing an explicit state.
- *
- * In the non-external case, psa_generate_random() calls an
- * `mbedtls_xxx_drbg_random` function which has exactly the same signature
- * and semantics as mbedtls_psa_get_random(). As an optimization,
- * instead of doing this back-and-forth between the PSA API and the
- * classic API, psa_crypto_random_impl.h defines `mbedtls_psa_get_random`
- * as a constant function pointer to `mbedtls_xxx_drbg_random`.
- */
-#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
-int mbedtls_psa_get_random(void *p_rng,
- unsigned char *output,
- size_t output_size)
-{
- /* This function takes a pointer to the RNG state because that's what
- * classic mbedtls functions using an RNG expect. The PSA RNG manages
- * its own state internally and doesn't let the caller access that state.
- * So we just ignore the state parameter, and in practice we'll pass
- * NULL. */
- (void) p_rng;
- psa_status_t status = psa_generate_random(output, output_size);
- if (status == PSA_SUCCESS) {
- return 0;
- } else {
- return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
- }
-}
-#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
-
#if defined(MBEDTLS_PSA_INJECT_ENTROPY)
psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed,
size_t seed_size)
@@ -7864,7 +7749,7 @@
* \param bits The number of bits of the key
*
* \retval #PSA_SUCCESS
- * The key type and size are valid.
+ * The key type and size are valid.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* The size in bits of the key is not valid.
* \retval #PSA_ERROR_NOT_SUPPORTED
@@ -7922,18 +7807,18 @@
psa_status_t psa_generate_key_internal(
const psa_key_attributes_t *attributes,
+ const psa_key_production_parameters_t *params, size_t params_data_length,
uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
- psa_key_type_t type = attributes->core.type;
+ psa_key_type_t type = attributes->type;
- if ((attributes->domain_parameters == NULL) &&
- (attributes->domain_parameters_size != 0)) {
- return PSA_ERROR_INVALID_ARGUMENT;
- }
+ /* Only used for RSA */
+ (void) params;
+ (void) params_data_length;
if (key_type_is_raw_bytes(type)) {
- status = psa_generate_random(key_buffer, key_buffer_size);
+ status = psa_generate_random_internal(key_buffer, key_buffer_size);
if (status != PSA_SUCCESS) {
return status;
}
@@ -7948,6 +7833,7 @@
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
if (type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
return mbedtls_psa_rsa_generate_key(attributes,
+ params, params_data_length,
key_buffer,
key_buffer_size,
key_buffer_length);
@@ -7979,8 +7865,10 @@
return PSA_SUCCESS;
}
-psa_status_t psa_generate_key(const psa_key_attributes_t *attributes,
- mbedtls_svc_key_id_t *key)
+psa_status_t psa_generate_key_ext(const psa_key_attributes_t *attributes,
+ const psa_key_production_parameters_t *params,
+ size_t params_data_length,
+ mbedtls_svc_key_id_t *key)
{
psa_status_t status;
psa_key_slot_t *slot = NULL;
@@ -7996,7 +7884,18 @@
}
/* Reject any attempt to create a public key. */
- if (PSA_KEY_TYPE_IS_PUBLIC_KEY(attributes->core.type)) {
+ if (PSA_KEY_TYPE_IS_PUBLIC_KEY(attributes->type)) {
+ return PSA_ERROR_INVALID_ARGUMENT;
+ }
+
+#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
+ if (attributes->type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
+ if (params->flags != 0) {
+ return PSA_ERROR_INVALID_ARGUMENT;
+ }
+ } else
+#endif
+ if (!psa_key_production_parameters_are_default(params, params_data_length)) {
return PSA_ERROR_INVALID_ARGUMENT;
}
@@ -8011,17 +7910,17 @@
* with storage ( MBEDTLS_PSA_CRYPTO_SE_C ) ),we have to allocate a
* buffer to hold the generated key material. */
if (slot->key.data == NULL) {
- if (PSA_KEY_LIFETIME_GET_LOCATION(attributes->core.lifetime) ==
+ if (PSA_KEY_LIFETIME_GET_LOCATION(attributes->lifetime) ==
PSA_KEY_LOCATION_LOCAL_STORAGE) {
status = psa_validate_key_type_and_size_for_key_generation(
- attributes->core.type, attributes->core.bits);
+ attributes->type, attributes->bits);
if (status != PSA_SUCCESS) {
goto exit;
}
key_buffer_size = PSA_EXPORT_KEY_OUTPUT_SIZE(
- attributes->core.type,
- attributes->core.bits);
+ attributes->type,
+ attributes->bits);
} else {
status = psa_driver_wrapper_get_key_buffer_size(
attributes, &key_buffer_size);
@@ -8037,8 +7936,9 @@
}
status = psa_driver_wrapper_generate_key(attributes,
- slot->key.data, slot->key.bytes, &slot->key.bytes);
-
+ params, params_data_length,
+ slot->key.data, slot->key.bytes,
+ &slot->key.bytes);
if (status != PSA_SUCCESS) {
psa_remove_key_data_from_memory(slot);
}
@@ -8054,6 +7954,14 @@
return status;
}
+psa_status_t psa_generate_key(const psa_key_attributes_t *attributes,
+ mbedtls_svc_key_id_t *key)
+{
+ return psa_generate_key_ext(attributes,
+ &default_production_parameters, 0,
+ key);
+}
+
/****************************************************************/
/* Module setup */
/****************************************************************/
@@ -8326,7 +8234,6 @@
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
psa_key_slot_t *slot = NULL;
- psa_key_attributes_t attributes;
psa_key_type_t type;
if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) {
@@ -8341,11 +8248,7 @@
goto exit;
}
- attributes = (psa_key_attributes_t) {
- .core = slot->attr
- };
-
- type = psa_get_key_type(&attributes);
+ type = psa_get_key_type(&slot->attr);
if (type != PSA_KEY_TYPE_PASSWORD &&
type != PSA_KEY_TYPE_PASSWORD_HASH) {
@@ -8361,12 +8264,13 @@
memcpy(operation->data.inputs.password, slot->key.data, slot->key.bytes);
operation->data.inputs.password_len = slot->key.bytes;
- operation->data.inputs.attributes = attributes;
+ operation->data.inputs.attributes = slot->attr;
+
exit:
if (status != PSA_SUCCESS) {
psa_pake_abort(operation);
}
- unlock_status = psa_unregister_read(slot);
+ unlock_status = psa_unregister_read_under_mutex(slot);
return (status == PSA_SUCCESS) ? unlock_status : status;
}
diff --git a/library/psa_crypto_aead.c b/library/psa_crypto_aead.c
index 49aa961..a201985 100644
--- a/library/psa_crypto_aead.c
+++ b/library/psa_crypto_aead.c
@@ -33,10 +33,10 @@
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_cipher_id_t cipher_id;
mbedtls_cipher_mode_t mode;
- size_t key_bits = attributes->core.bits;
+ size_t key_bits = attributes->bits;
(void) key_buffer_size;
- status = mbedtls_cipher_values_from_psa(alg, attributes->core.type,
+ status = mbedtls_cipher_values_from_psa(alg, attributes->type,
&key_bits, &mode, &cipher_id);
if (status != PSA_SUCCESS) {
return status;
@@ -49,7 +49,7 @@
/* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16.
* The call to mbedtls_ccm_encrypt_and_tag or
* mbedtls_ccm_auth_decrypt will validate the tag length. */
- if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(attributes->core.type) != 16) {
+ if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(attributes->type) != 16) {
return PSA_ERROR_INVALID_ARGUMENT;
}
@@ -69,7 +69,7 @@
/* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16.
* The call to mbedtls_gcm_crypt_and_tag or
* mbedtls_gcm_auth_decrypt will validate the tag length. */
- if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(attributes->core.type) != 16) {
+ if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(attributes->type) != 16) {
return PSA_ERROR_INVALID_ARGUMENT;
}
diff --git a/library/psa_crypto_cipher.c b/library/psa_crypto_cipher.c
index d70a275..881d673 100644
--- a/library/psa_crypto_cipher.c
+++ b/library/psa_crypto_cipher.c
@@ -289,14 +289,14 @@
int ret = 0;
size_t key_bits;
const mbedtls_cipher_info_t *cipher_info = NULL;
- psa_key_type_t key_type = attributes->core.type;
+ psa_key_type_t key_type = attributes->type;
(void) key_buffer_size;
mbedtls_cipher_init(&operation->ctx.cipher);
operation->alg = alg;
- key_bits = attributes->core.bits;
+ key_bits = attributes->bits;
cipher_info = mbedtls_cipher_info_from_psa(alg, key_type,
key_bits, NULL);
if (cipher_info == NULL) {
diff --git a/library/psa_crypto_client.c b/library/psa_crypto_client.c
index 472d3d3..72f671d 100644
--- a/library/psa_crypto_client.c
+++ b/library/psa_crypto_client.c
@@ -16,57 +16,7 @@
void psa_reset_key_attributes(psa_key_attributes_t *attributes)
{
- mbedtls_free(attributes->domain_parameters);
memset(attributes, 0, sizeof(*attributes));
}
-psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes,
- psa_key_type_t type,
- const uint8_t *data,
- size_t data_length)
-{
- uint8_t *copy = NULL;
-
- if (data_length != 0) {
- copy = mbedtls_calloc(1, data_length);
- if (copy == NULL) {
- return PSA_ERROR_INSUFFICIENT_MEMORY;
- }
- memcpy(copy, data, data_length);
- }
- /* After this point, this function is guaranteed to succeed, so it
- * can start modifying `*attributes`. */
-
- if (attributes->domain_parameters != NULL) {
- mbedtls_free(attributes->domain_parameters);
- attributes->domain_parameters = NULL;
- attributes->domain_parameters_size = 0;
- }
-
- attributes->domain_parameters = copy;
- attributes->domain_parameters_size = data_length;
- attributes->core.type = type;
- return PSA_SUCCESS;
-}
-
-psa_status_t psa_get_key_domain_parameters(
- const psa_key_attributes_t *attributes,
- uint8_t *data, size_t data_size, size_t *data_length)
-{
- if (attributes->domain_parameters == NULL &&
- attributes->domain_parameters_size == SIZE_MAX) {
- return PSA_ERROR_NOT_SUPPORTED;
- }
-
- if (attributes->domain_parameters_size > data_size) {
- return PSA_ERROR_BUFFER_TOO_SMALL;
- }
- *data_length = attributes->domain_parameters_size;
- if (attributes->domain_parameters_size != 0) {
- memcpy(data, attributes->domain_parameters,
- attributes->domain_parameters_size);
- }
- return PSA_SUCCESS;
-}
-
#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
diff --git a/library/psa_crypto_core.h b/library/psa_crypto_core.h
index 67966f9..4d47594 100644
--- a/library/psa_crypto_core.h
+++ b/library/psa_crypto_core.h
@@ -20,6 +20,9 @@
#include "psa/crypto.h"
#include "psa/crypto_se_driver.h"
+#if defined(MBEDTLS_THREADING_C)
+#include "mbedtls/threading.h"
+#endif
/**
* Tell if PSA is ready for this hash.
@@ -56,7 +59,7 @@
* and metadata for one key.
*/
typedef struct {
- psa_core_key_attributes_t attr;
+ psa_key_attributes_t attr;
/*
* The current state of the key slot, as described in
@@ -86,7 +89,9 @@
* A function must call psa_register_read(slot) before reading the current
* contents of the slot for an operation.
* They then must call psa_unregister_read(slot) once they have finished
- * reading the current contents of the slot.
+ * reading the current contents of the slot. If the key slot mutex is not
+ * held (when mutexes are enabled), this call must be done via a call to
+ * psa_unregister_read_under_mutex(slot).
* A function must call psa_key_slot_has_readers(slot) to check if
* the slot is in use for reading.
*
@@ -111,10 +116,48 @@
} key;
} psa_key_slot_t;
-/* A mask of key attribute flags used only internally.
- * Currently there aren't any. */
-#define PSA_KA_MASK_INTERNAL_ONLY ( \
- 0)
+#if defined(MBEDTLS_THREADING_C)
+
+/** Perform a mutex operation and return immediately upon failure.
+ *
+ * Returns PSA_ERROR_SERVICE_FAILURE if the operation fails
+ * and status was PSA_SUCCESS.
+ *
+ * Assumptions:
+ * psa_status_t status exists.
+ * f is a mutex operation which returns 0 upon success.
+ */
+#define PSA_THREADING_CHK_RET(f) \
+ do \
+ { \
+ if ((f) != 0) { \
+ if (status == PSA_SUCCESS) { \
+ return PSA_ERROR_SERVICE_FAILURE; \
+ } \
+ return status; \
+ } \
+ } while (0);
+
+/** Perform a mutex operation and goto exit on failure.
+ *
+ * Sets status to PSA_ERROR_SERVICE_FAILURE if status was PSA_SUCCESS.
+ *
+ * Assumptions:
+ * psa_status_t status exists.
+ * Label exit: exists.
+ * f is a mutex operation which returns 0 upon success.
+ */
+#define PSA_THREADING_CHK_GOTO_EXIT(f) \
+ do \
+ { \
+ if ((f) != 0) { \
+ if (status == PSA_SUCCESS) { \
+ status = PSA_ERROR_SERVICE_FAILURE; \
+ } \
+ goto exit; \
+ } \
+ } while (0);
+#endif
/** Test whether a key slot has any registered readers.
* If multi-threading is enabled, the caller must hold the
@@ -129,56 +172,6 @@
return slot->registered_readers > 0;
}
-/** Retrieve flags from psa_key_slot_t::attr::core::flags.
- *
- * \param[in] slot The key slot to query.
- * \param mask The mask of bits to extract.
- *
- * \return The key attribute flags in the given slot,
- * bitwise-anded with \p mask.
- */
-static inline uint16_t psa_key_slot_get_flags(const psa_key_slot_t *slot,
- uint16_t mask)
-{
- return slot->attr.flags & mask;
-}
-
-/** Set flags in psa_key_slot_t::attr::core::flags.
- *
- * \param[in,out] slot The key slot to modify.
- * \param mask The mask of bits to modify.
- * \param value The new value of the selected bits.
- */
-static inline void psa_key_slot_set_flags(psa_key_slot_t *slot,
- uint16_t mask,
- uint16_t value)
-{
- slot->attr.flags = ((~mask & slot->attr.flags) |
- (mask & value));
-}
-
-/** Turn on flags in psa_key_slot_t::attr::core::flags.
- *
- * \param[in,out] slot The key slot to modify.
- * \param mask The mask of bits to set.
- */
-static inline void psa_key_slot_set_bits_in_flags(psa_key_slot_t *slot,
- uint16_t mask)
-{
- slot->attr.flags |= mask;
-}
-
-/** Turn off flags in psa_key_slot_t::attr::core::flags.
- *
- * \param[in,out] slot The key slot to modify.
- * \param mask The mask of bits to clear.
- */
-static inline void psa_key_slot_clear_bits(psa_key_slot_t *slot,
- uint16_t mask)
-{
- slot->attr.flags &= ~mask;
-}
-
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
/** Get the SE slot number of a key from the key slot storing its description.
*
@@ -350,6 +343,18 @@
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length);
+/** Whether a key production parameters structure is the default.
+ *
+ * Calls to a key generation driver with non-default production parameters
+ * require a driver supporting custom production parameters.
+ *
+ * \param[in] params The key production parameters to check.
+ * \param params_data_length Size of `params->data` in bytes.
+ */
+int psa_key_production_parameters_are_default(
+ const psa_key_production_parameters_t *params,
+ size_t params_data_length);
+
/**
* \brief Generate a key.
*
@@ -357,6 +362,9 @@
* entry point.
*
* \param[in] attributes The attributes for the key to generate.
+ * \param[in] params The production parameters from
+ * psa_generate_key_ext().
+ * \param params_data_length The size of `params->data` in bytes.
* \param[out] key_buffer Buffer where the key data is to be written.
* \param[in] key_buffer_size Size of \p key_buffer in bytes.
* \param[out] key_buffer_length On success, the number of bytes written in
@@ -371,6 +379,8 @@
* The size of \p key_buffer is too small.
*/
psa_status_t psa_generate_key_internal(const psa_key_attributes_t *attributes,
+ const psa_key_production_parameters_t *params,
+ size_t params_data_length,
uint8_t *key_buffer,
size_t key_buffer_size,
size_t *key_buffer_length);
diff --git a/library/psa_crypto_ecp.c b/library/psa_crypto_ecp.c
index db08541..95baff6 100644
--- a/library/psa_crypto_ecp.c
+++ b/library/psa_crypto_ecp.c
@@ -216,8 +216,8 @@
mbedtls_ecp_keypair *ecp = NULL;
/* Parse input */
- status = mbedtls_psa_ecp_load_representation(attributes->core.type,
- attributes->core.bits,
+ status = mbedtls_psa_ecp_load_representation(attributes->type,
+ attributes->bits,
data,
data_length,
&ecp);
@@ -225,7 +225,7 @@
goto exit;
}
- if (PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->core.type) ==
+ if (PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->type) ==
PSA_ECC_FAMILY_MONTGOMERY) {
*bits = ecp->grp.nbits + 1;
} else {
@@ -235,7 +235,7 @@
/* Re-export the data to PSA export format. There is currently no support
* for other input formats then the export format, so this is a 1-1
* copy operation. */
- status = mbedtls_psa_ecp_export_key(attributes->core.type,
+ status = mbedtls_psa_ecp_export_key(attributes->type,
ecp,
key_buffer,
key_buffer_size,
@@ -281,20 +281,8 @@
return status;
} else {
- if (data_size < PSA_BITS_TO_BYTES(ecp->grp.nbits)) {
- return PSA_ERROR_BUFFER_TOO_SMALL;
- }
-
status = mbedtls_to_psa_error(
- mbedtls_ecp_write_key(ecp,
- data,
- PSA_BITS_TO_BYTES(ecp->grp.nbits)));
- if (status == PSA_SUCCESS) {
- *data_length = PSA_BITS_TO_BYTES(ecp->grp.nbits);
- } else {
- memset(data, 0, data_size);
- }
-
+ mbedtls_ecp_write_key_ext(ecp, data_length, data, data_size));
return status;
}
}
@@ -308,7 +296,7 @@
mbedtls_ecp_keypair *ecp = NULL;
status = mbedtls_psa_ecp_load_representation(
- attributes->core.type, attributes->core.bits,
+ attributes->type, attributes->bits,
key_buffer, key_buffer_size, &ecp);
if (status != PSA_SUCCESS) {
return status;
@@ -316,7 +304,7 @@
status = mbedtls_psa_ecp_export_key(
PSA_KEY_TYPE_ECC_PUBLIC_KEY(
- PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->core.type)),
+ PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->type)),
ecp, data, data_size, data_length);
mbedtls_ecp_keypair_free(ecp);
@@ -337,18 +325,14 @@
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY(
- attributes->core.type);
+ attributes->type);
mbedtls_ecp_group_id grp_id =
- mbedtls_ecc_group_from_psa(curve, attributes->core.bits);
+ mbedtls_ecc_group_from_psa(curve, attributes->bits);
const mbedtls_ecp_curve_info *curve_info =
mbedtls_ecp_curve_info_from_grp_id(grp_id);
mbedtls_ecp_keypair ecp;
- if (attributes->domain_parameters_size != 0) {
- return PSA_ERROR_NOT_SUPPORTED;
- }
-
if (grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL) {
return PSA_ERROR_NOT_SUPPORTED;
}
@@ -363,14 +347,11 @@
}
status = mbedtls_to_psa_error(
- mbedtls_ecp_write_key(&ecp, key_buffer, key_buffer_size));
+ mbedtls_ecp_write_key_ext(&ecp, key_buffer_length,
+ key_buffer, key_buffer_size));
mbedtls_ecp_keypair_free(&ecp);
- if (status == PSA_SUCCESS) {
- *key_buffer_length = key_buffer_size;
- }
-
return status;
}
#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE */
@@ -393,8 +374,8 @@
size_t curve_bytes;
mbedtls_mpi r, s;
- status = mbedtls_psa_ecp_load_representation(attributes->core.type,
- attributes->core.bits,
+ status = mbedtls_psa_ecp_load_representation(attributes->type,
+ attributes->bits,
key_buffer,
key_buffer_size,
&ecp);
@@ -480,8 +461,8 @@
(void) alg;
- status = mbedtls_psa_ecp_load_representation(attributes->core.type,
- attributes->core.bits,
+ status = mbedtls_psa_ecp_load_representation(attributes->type,
+ attributes->bits,
key_buffer,
key_buffer_size,
&ecp);
@@ -545,14 +526,14 @@
size_t *shared_secret_length)
{
psa_status_t status;
- if (!PSA_KEY_TYPE_IS_ECC_KEY_PAIR(attributes->core.type) ||
+ if (!PSA_KEY_TYPE_IS_ECC_KEY_PAIR(attributes->type) ||
!PSA_ALG_IS_ECDH(alg)) {
return PSA_ERROR_INVALID_ARGUMENT;
}
mbedtls_ecp_keypair *ecp = NULL;
status = mbedtls_psa_ecp_load_representation(
- attributes->core.type,
- attributes->core.bits,
+ attributes->type,
+ attributes->bits,
key_buffer,
key_buffer_size,
&ecp);
diff --git a/library/psa_crypto_ffdh.c b/library/psa_crypto_ffdh.c
index a57f02e..ae38f6d 100644
--- a/library/psa_crypto_ffdh.c
+++ b/library/psa_crypto_ffdh.c
@@ -10,6 +10,12 @@
#if defined(MBEDTLS_PSA_CRYPTO_C)
+/* This header is only needed because it defines
+ * MBEDTLS_DHM_RFC7919_FFDHEXXXX_[P|G]_BIN symbols that are used in
+ * mbedtls_psa_ffdh_set_prime_generator(). Apart from that, this module
+ * only uses bignum functions for arithmetic. */
+#include <mbedtls/dhm.h>
+
#include <psa/crypto.h>
#include "psa_crypto_core.h"
#include "psa_crypto_ffdh.h"
@@ -35,58 +41,78 @@
return PSA_ERROR_INVALID_ARGUMENT;
}
+#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048)
static const unsigned char dhm_P_2048[] =
MBEDTLS_DHM_RFC7919_FFDHE2048_P_BIN;
- static const unsigned char dhm_P_3072[] =
- MBEDTLS_DHM_RFC7919_FFDHE3072_P_BIN;
- static const unsigned char dhm_P_4096[] =
- MBEDTLS_DHM_RFC7919_FFDHE4096_P_BIN;
- static const unsigned char dhm_P_6144[] =
- MBEDTLS_DHM_RFC7919_FFDHE6144_P_BIN;
- static const unsigned char dhm_P_8192[] =
- MBEDTLS_DHM_RFC7919_FFDHE8192_P_BIN;
static const unsigned char dhm_G_2048[] =
MBEDTLS_DHM_RFC7919_FFDHE2048_G_BIN;
+#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 */
+#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072)
+ static const unsigned char dhm_P_3072[] =
+ MBEDTLS_DHM_RFC7919_FFDHE3072_P_BIN;
static const unsigned char dhm_G_3072[] =
MBEDTLS_DHM_RFC7919_FFDHE3072_G_BIN;
+#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 */
+#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096)
+ static const unsigned char dhm_P_4096[] =
+ MBEDTLS_DHM_RFC7919_FFDHE4096_P_BIN;
static const unsigned char dhm_G_4096[] =
MBEDTLS_DHM_RFC7919_FFDHE4096_G_BIN;
+#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 */
+#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144)
+ static const unsigned char dhm_P_6144[] =
+ MBEDTLS_DHM_RFC7919_FFDHE6144_P_BIN;
static const unsigned char dhm_G_6144[] =
MBEDTLS_DHM_RFC7919_FFDHE6144_G_BIN;
+#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 */
+#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192)
+ static const unsigned char dhm_P_8192[] =
+ MBEDTLS_DHM_RFC7919_FFDHE8192_P_BIN;
static const unsigned char dhm_G_8192[] =
MBEDTLS_DHM_RFC7919_FFDHE8192_G_BIN;
+#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 */
switch (key_size) {
+#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048)
case sizeof(dhm_P_2048):
dhm_P = dhm_P_2048;
dhm_G = dhm_G_2048;
dhm_size_P = sizeof(dhm_P_2048);
dhm_size_G = sizeof(dhm_G_2048);
break;
+#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 */
+#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072)
case sizeof(dhm_P_3072):
dhm_P = dhm_P_3072;
dhm_G = dhm_G_3072;
dhm_size_P = sizeof(dhm_P_3072);
dhm_size_G = sizeof(dhm_G_3072);
break;
+#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 */
+#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096)
case sizeof(dhm_P_4096):
dhm_P = dhm_P_4096;
dhm_G = dhm_G_4096;
dhm_size_P = sizeof(dhm_P_4096);
dhm_size_G = sizeof(dhm_G_4096);
break;
+#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 */
+#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144)
case sizeof(dhm_P_6144):
dhm_P = dhm_P_6144;
dhm_G = dhm_G_6144;
dhm_size_P = sizeof(dhm_P_6144);
dhm_size_G = sizeof(dhm_G_6144);
break;
+#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 */
+#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192)
case sizeof(dhm_P_8192):
dhm_P = dhm_P_8192;
dhm_G = dhm_G_8192;
dhm_size_P = sizeof(dhm_P_8192);
dhm_size_G = sizeof(dhm_G_8192);
break;
+#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 */
default:
return PSA_ERROR_INVALID_ARGUMENT;
}
@@ -125,7 +151,7 @@
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi GX, G, X, P;
- psa_key_type_t type = attributes->core.type;
+ psa_key_type_t type = attributes->type;
if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) {
if (key_buffer_size > data_size) {
@@ -141,7 +167,7 @@
mbedtls_mpi_init(&GX); mbedtls_mpi_init(&G);
mbedtls_mpi_init(&X); mbedtls_mpi_init(&P);
- size_t key_len = PSA_BITS_TO_BYTES(attributes->core.bits);
+ size_t key_len = PSA_BITS_TO_BYTES(attributes->bits);
status = mbedtls_psa_ffdh_set_prime_generator(key_len, &P, &G);
@@ -257,7 +283,7 @@
mbedtls_mpi_init(&K);
status = mbedtls_psa_ffdh_set_prime_generator(
- PSA_BITS_TO_BYTES(attributes->core.bits), &P, &G);
+ PSA_BITS_TO_BYTES(attributes->bits), &P, &G);
if (status != PSA_SUCCESS) {
goto cleanup;
diff --git a/library/psa_crypto_ffdh.h b/library/psa_crypto_ffdh.h
index baeb928..79accd1 100644
--- a/library/psa_crypto_ffdh.h
+++ b/library/psa_crypto_ffdh.h
@@ -10,7 +10,6 @@
#define PSA_CRYPTO_FFDH_H
#include <psa/crypto.h>
-#include <mbedtls/dhm.h>
/** Perform a key agreement and return the FFDH shared secret.
*
diff --git a/library/psa_crypto_random_impl.h b/library/psa_crypto_random_impl.h
index 64b8949..533fb2e 100644
--- a/library/psa_crypto_random_impl.h
+++ b/library/psa_crypto_random_impl.h
@@ -1,14 +1,6 @@
/** \file psa_crypto_random_impl.h
*
* \brief PSA crypto random generator implementation abstraction.
- *
- * The definitions here need to be consistent with the declarations
- * in include/psa_util_internal.h. This file contains some redundant
- * declarations to increase the chance that a compiler will detect
- * inconsistencies if one file is changed without updating the other,
- * but not all potential inconsistencies can be enforced, so make sure
- * to check the public declarations and contracts in
- * include/psa_util_internal.h if you modify this file.
*/
/*
* Copyright The Mbed TLS Contributors
@@ -22,22 +14,12 @@
#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
-#include <string.h>
-#include <mbedtls/entropy.h> // only for error codes
-#include <psa/crypto.h>
-
typedef mbedtls_psa_external_random_context_t mbedtls_psa_random_context_t;
-/* Trivial wrapper around psa_generate_random(). */
-int mbedtls_psa_get_random(void *p_rng,
- unsigned char *output,
- size_t output_size);
-
-/* The PSA RNG API doesn't need any externally maintained state. */
-#define MBEDTLS_PSA_RANDOM_STATE NULL
-
#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+#include "mbedtls/entropy.h"
+
/* Choose a DRBG based on configuration and availability */
#if defined(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE)
@@ -67,11 +49,37 @@
#error "No hash algorithm available for HMAC_DBRG."
#endif
-#else
+#else /* !MBEDTLS_PSA_HMAC_DRBG_MD_TYPE && !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C*/
+
#error "No DRBG module available for the psa_crypto module."
+
+#endif /* !MBEDTLS_PSA_HMAC_DRBG_MD_TYPE && !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C*/
+
+#if defined(MBEDTLS_CTR_DRBG_C)
+#include "mbedtls/ctr_drbg.h"
+#elif defined(MBEDTLS_HMAC_DRBG_C)
+#include "mbedtls/hmac_drbg.h"
+#endif /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C */
+
+/* The maximum number of bytes that mbedtls_psa_get_random() is expected to return. */
+#if defined(MBEDTLS_CTR_DRBG_C)
+#define MBEDTLS_PSA_RANDOM_MAX_REQUEST MBEDTLS_CTR_DRBG_MAX_REQUEST
+#elif defined(MBEDTLS_HMAC_DRBG_C)
+#define MBEDTLS_PSA_RANDOM_MAX_REQUEST MBEDTLS_HMAC_DRBG_MAX_REQUEST
#endif
-#include "mbedtls/entropy.h"
+#if defined(MBEDTLS_CTR_DRBG_C)
+typedef mbedtls_ctr_drbg_context mbedtls_psa_drbg_context_t;
+#elif defined(MBEDTLS_HMAC_DRBG_C)
+typedef mbedtls_hmac_drbg_context mbedtls_psa_drbg_context_t;
+#endif /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C */
+
+typedef struct {
+ void (* entropy_init)(mbedtls_entropy_context *ctx);
+ void (* entropy_free)(mbedtls_entropy_context *ctx);
+ mbedtls_entropy_context entropy;
+ mbedtls_psa_drbg_context_t drbg;
+} mbedtls_psa_random_context_t;
/** Initialize the PSA DRBG.
*
@@ -99,63 +107,6 @@
#endif
}
-/** The type of the PSA random generator context.
- *
- * The random generator context is composed of an entropy context and
- * a DRBG context.
- */
-typedef struct {
- void (* entropy_init)(mbedtls_entropy_context *ctx);
- void (* entropy_free)(mbedtls_entropy_context *ctx);
- mbedtls_entropy_context entropy;
- mbedtls_psa_drbg_context_t drbg;
-} mbedtls_psa_random_context_t;
-
-/* Defined in include/psa_util_internal.h so that it's visible to
- * application code. The declaration here is redundant, but included
- * as a safety net to make it more likely that a future change that
- * accidentally causes the implementation to diverge from the interface
- * will be noticed. */
-/* Do not include the declaration under MSVC because it doesn't accept it
- * ("error C2370: 'mbedtls_psa_get_random' : redefinition; different storage class").
- * Observed with Visual Studio 2013. A known bug apparently:
- * https://stackoverflow.com/questions/8146541/duplicate-external-static-declarations-not-allowed-in-visual-studio
- */
-#if !defined(_MSC_VER)
-static mbedtls_f_rng_t *const mbedtls_psa_get_random;
-#endif
-
-/** The maximum number of bytes that mbedtls_psa_get_random() is expected to
- * return.
- */
-#if defined(MBEDTLS_CTR_DRBG_C)
-#define MBEDTLS_PSA_RANDOM_MAX_REQUEST MBEDTLS_CTR_DRBG_MAX_REQUEST
-#elif defined(MBEDTLS_HMAC_DRBG_C)
-#define MBEDTLS_PSA_RANDOM_MAX_REQUEST MBEDTLS_HMAC_DRBG_MAX_REQUEST
-#endif
-
-/** A pointer to the PSA DRBG state.
- *
- * This variable is only intended to be used through the macro
- * #MBEDTLS_PSA_RANDOM_STATE.
- */
-/* psa_crypto.c sets this variable to a pointer to the DRBG state in the
- * global PSA crypto state. */
-/* The type `mbedtls_psa_drbg_context_t` is defined in
- * include/psa_util_internal.h so that `mbedtls_psa_random_state` can be
- * declared there and be visible to application code. */
-extern mbedtls_psa_drbg_context_t *const mbedtls_psa_random_state;
-
-/** A pointer to the PSA DRBG state.
- *
- * This macro expands to an expression that is suitable as the \c p_rng
- * parameter to pass to mbedtls_psa_get_random().
- *
- * This macro exists in all configurations where the psa_crypto module is
- * enabled. Its expansion depends on the configuration.
- */
-#define MBEDTLS_PSA_RANDOM_STATE mbedtls_psa_random_state
-
/** Seed the PSA DRBG.
*
* \param entropy An entropy context to read the seed from.
@@ -167,23 +118,15 @@
* \return \c 0 on success.
* \return An Mbed TLS error code (\c MBEDTLS_ERR_xxx) on failure.
*/
-static inline int mbedtls_psa_drbg_seed(
- mbedtls_entropy_context *entropy,
- const unsigned char *custom, size_t len)
+static inline int mbedtls_psa_drbg_seed(mbedtls_psa_drbg_context_t *drbg_ctx,
+ mbedtls_entropy_context *entropy,
+ const unsigned char *custom, size_t len)
{
#if defined(MBEDTLS_CTR_DRBG_C)
- return mbedtls_ctr_drbg_seed(MBEDTLS_PSA_RANDOM_STATE,
- mbedtls_entropy_func,
- entropy,
- custom, len);
+ return mbedtls_ctr_drbg_seed(drbg_ctx, mbedtls_entropy_func, entropy, custom, len);
#elif defined(MBEDTLS_HMAC_DRBG_C)
- const mbedtls_md_info_t *md_info =
- mbedtls_md_info_from_type(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE);
- return mbedtls_hmac_drbg_seed(MBEDTLS_PSA_RANDOM_STATE,
- md_info,
- mbedtls_entropy_func,
- entropy,
- custom, len);
+ const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE);
+ return mbedtls_hmac_drbg_seed(drbg_ctx, md_info, mbedtls_entropy_func, entropy, custom, len);
#endif
}
diff --git a/library/psa_crypto_rsa.c b/library/psa_crypto_rsa.c
index 7b58ea2..2f613b3 100644
--- a/library/psa_crypto_rsa.c
+++ b/library/psa_crypto_rsa.c
@@ -24,8 +24,7 @@
#include <mbedtls/rsa.h>
#include <mbedtls/error.h>
-#include <mbedtls/pk.h>
-#include "pk_wrap.h"
+#include "rsa_internal.h"
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || \
@@ -62,50 +61,38 @@
mbedtls_rsa_context **p_rsa)
{
psa_status_t status;
- mbedtls_pk_context ctx;
size_t bits;
- mbedtls_pk_init(&ctx);
+
+ *p_rsa = mbedtls_calloc(1, sizeof(mbedtls_rsa_context));
+ if (*p_rsa == NULL) {
+ return PSA_ERROR_INSUFFICIENT_MEMORY;
+ }
+ mbedtls_rsa_init(*p_rsa);
/* Parse the data. */
if (PSA_KEY_TYPE_IS_KEY_PAIR(type)) {
- status = mbedtls_to_psa_error(
- mbedtls_pk_parse_key(&ctx, data, data_length, NULL, 0,
- mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE));
+ status = mbedtls_to_psa_error(mbedtls_rsa_parse_key(*p_rsa, data, data_length));
} else {
- status = mbedtls_to_psa_error(
- mbedtls_pk_parse_public_key(&ctx, data, data_length));
+ status = mbedtls_to_psa_error(mbedtls_rsa_parse_pubkey(*p_rsa, data, data_length));
}
if (status != PSA_SUCCESS) {
goto exit;
}
- /* We have something that the pkparse module recognizes. If it is a
- * valid RSA key, store it. */
- if (mbedtls_pk_get_type(&ctx) != MBEDTLS_PK_RSA) {
- status = PSA_ERROR_INVALID_ARGUMENT;
- goto exit;
- }
-
/* The size of an RSA key doesn't have to be a multiple of 8. Mbed TLS
* supports non-byte-aligned key sizes, but not well. For example,
* mbedtls_rsa_get_len() returns the key size in bytes, not in bits. */
- bits = PSA_BYTES_TO_BITS(mbedtls_rsa_get_len(mbedtls_pk_rsa(ctx)));
+ bits = PSA_BYTES_TO_BITS(mbedtls_rsa_get_len(*p_rsa));
if (bits > PSA_VENDOR_RSA_MAX_KEY_BITS) {
status = PSA_ERROR_NOT_SUPPORTED;
goto exit;
}
- status = psa_check_rsa_key_byte_aligned(mbedtls_pk_rsa(ctx));
+ status = psa_check_rsa_key_byte_aligned(*p_rsa);
if (status != PSA_SUCCESS) {
goto exit;
}
- /* Copy out the pointer to the RSA context, and reset the PK context
- * such that pk_free doesn't free the RSA context we just grabbed. */
- *p_rsa = mbedtls_pk_rsa(ctx);
- ctx.pk_info = NULL;
-
exit:
- mbedtls_pk_free(&ctx);
return status;
}
#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) ||
@@ -129,7 +116,7 @@
mbedtls_rsa_context *rsa = NULL;
/* Parse input */
- status = mbedtls_psa_rsa_load_representation(attributes->core.type,
+ status = mbedtls_psa_rsa_load_representation(attributes->type,
data,
data_length,
&rsa);
@@ -143,7 +130,7 @@
* representation in the key slot. Export representation in case of RSA is
* the smallest representation that's allowed as input, so a straight-up
* allocation of the same size as the input buffer will be large enough. */
- status = mbedtls_psa_rsa_export_key(attributes->core.type,
+ status = mbedtls_psa_rsa_export_key(attributes->type,
rsa,
key_buffer,
key_buffer_size,
@@ -168,20 +155,15 @@
size_t *data_length)
{
int ret;
- mbedtls_pk_context pk;
- uint8_t *pos = data + data_size;
-
- mbedtls_pk_init(&pk);
- pk.pk_info = &mbedtls_rsa_info;
- pk.pk_ctx = rsa;
+ uint8_t *end = data + data_size;
/* PSA Crypto API defines the format of an RSA key as a DER-encoded
* representation of the non-encrypted PKCS#1 RSAPrivateKey for a
* private key and of the RFC3279 RSAPublicKey for a public key. */
if (PSA_KEY_TYPE_IS_KEY_PAIR(type)) {
- ret = mbedtls_pk_write_key_der(&pk, data, data_size);
+ ret = mbedtls_rsa_write_key(rsa, data, &end);
} else {
- ret = mbedtls_pk_write_pubkey(&pos, data, &pk);
+ ret = mbedtls_rsa_write_pubkey(rsa, data, &end);
}
if (ret < 0) {
@@ -214,7 +196,7 @@
mbedtls_rsa_context *rsa = NULL;
status = mbedtls_psa_rsa_load_representation(
- attributes->core.type, key_buffer, key_buffer_size, &rsa);
+ attributes->type, key_buffer, key_buffer_size, &rsa);
if (status != PSA_SUCCESS) {
return status;
}
@@ -234,26 +216,21 @@
* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
-static psa_status_t psa_rsa_read_exponent(const uint8_t *domain_parameters,
- size_t domain_parameters_size,
+static psa_status_t psa_rsa_read_exponent(const uint8_t *e_bytes,
+ size_t e_length,
int *exponent)
{
size_t i;
uint32_t acc = 0;
- if (domain_parameters_size == 0) {
- *exponent = 65537;
- return PSA_SUCCESS;
- }
-
/* Mbed TLS encodes the public exponent as an int. For simplicity, only
* support values that fit in a 32-bit integer, which is larger than
* int on just about every platform anyway. */
- if (domain_parameters_size > sizeof(acc)) {
+ if (e_length > sizeof(acc)) {
return PSA_ERROR_NOT_SUPPORTED;
}
- for (i = 0; i < domain_parameters_size; i++) {
- acc = (acc << 8) | domain_parameters[i];
+ for (i = 0; i < e_length; i++) {
+ acc = (acc << 8) | e_bytes[i];
}
if (acc > INT_MAX) {
return PSA_ERROR_NOT_SUPPORTED;
@@ -264,31 +241,33 @@
psa_status_t mbedtls_psa_rsa_generate_key(
const psa_key_attributes_t *attributes,
+ const psa_key_production_parameters_t *params, size_t params_data_length,
uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length)
{
psa_status_t status;
mbedtls_rsa_context rsa;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- int exponent;
+ int exponent = 65537;
- status = psa_rsa_read_exponent(attributes->domain_parameters,
- attributes->domain_parameters_size,
- &exponent);
- if (status != PSA_SUCCESS) {
- return status;
+ if (params_data_length != 0) {
+ status = psa_rsa_read_exponent(params->data, params_data_length,
+ &exponent);
+ if (status != PSA_SUCCESS) {
+ return status;
+ }
}
mbedtls_rsa_init(&rsa);
ret = mbedtls_rsa_gen_key(&rsa,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE,
- (unsigned int) attributes->core.bits,
+ (unsigned int) attributes->bits,
exponent);
if (ret != 0) {
return mbedtls_to_psa_error(ret);
}
- status = mbedtls_psa_rsa_export_key(attributes->core.type,
+ status = mbedtls_psa_rsa_export_key(attributes->type,
&rsa, key_buffer, key_buffer_size,
key_buffer_length);
mbedtls_rsa_free(&rsa);
@@ -346,7 +325,7 @@
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_md_type_t md_alg;
- status = mbedtls_psa_rsa_load_representation(attributes->core.type,
+ status = mbedtls_psa_rsa_load_representation(attributes->type,
key_buffer,
key_buffer_size,
&rsa);
@@ -445,7 +424,7 @@
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_md_type_t md_alg;
- status = mbedtls_psa_rsa_load_representation(attributes->core.type,
+ status = mbedtls_psa_rsa_load_representation(attributes->type,
key_buffer,
key_buffer_size,
&rsa);
@@ -557,11 +536,11 @@
(void) output_size;
(void) output_length;
- if (PSA_KEY_TYPE_IS_RSA(attributes->core.type)) {
+ if (PSA_KEY_TYPE_IS_RSA(attributes->type)) {
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
mbedtls_rsa_context *rsa = NULL;
- status = mbedtls_psa_rsa_load_representation(attributes->core.type,
+ status = mbedtls_psa_rsa_load_representation(attributes->type,
key_buffer,
key_buffer_size,
&rsa);
@@ -653,11 +632,11 @@
*output_length = 0;
- if (attributes->core.type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
+ if (attributes->type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
mbedtls_rsa_context *rsa = NULL;
- status = mbedtls_psa_rsa_load_representation(attributes->core.type,
+ status = mbedtls_psa_rsa_load_representation(attributes->type,
key_buffer,
key_buffer_size,
&rsa);
diff --git a/library/psa_crypto_rsa.h b/library/psa_crypto_rsa.h
index e4c5caf..ffeef26 100644
--- a/library/psa_crypto_rsa.h
+++ b/library/psa_crypto_rsa.h
@@ -109,6 +109,15 @@
* entry point.
*
* \param[in] attributes The attributes for the RSA key to generate.
+ * \param[in] params Production parameters for the key
+ * generation. This function only uses
+ * `params->data`,
+ * which contains the public exponent.
+ * This can be a null pointer if
+ * \c params_data_length is 0.
+ * \param params_data_length Length of `params->data` in bytes.
+ * This can be 0, in which case the
+ * public exponent will be 65537.
* \param[out] key_buffer Buffer where the key data is to be written.
* \param[in] key_buffer_size Size of \p key_buffer in bytes.
* \param[out] key_buffer_length On success, the number of bytes written in
@@ -123,6 +132,7 @@
*/
psa_status_t mbedtls_psa_rsa_generate_key(
const psa_key_attributes_t *attributes,
+ const psa_key_production_parameters_t *params, size_t params_data_length,
uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length);
/** Sign an already-calculated hash with an RSA private key.
diff --git a/library/psa_crypto_slot_management.c b/library/psa_crypto_slot_management.c
index 47ace35..5dee32f 100644
--- a/library/psa_crypto_slot_management.c
+++ b/library/psa_crypto_slot_management.c
@@ -70,6 +70,9 @@
* On success, the function locks the key slot. It is the responsibility of
* the caller to unlock the key slot when it does not access it anymore.
*
+ * If multi-threading is enabled, the caller must hold the
+ * global key slot mutex.
+ *
* \param key Key identifier to query.
* \param[out] p_slot On success, `*p_slot` contains a pointer to the
* key slot containing the description of the key
@@ -94,16 +97,14 @@
if (psa_key_id_is_volatile(key_id)) {
slot = &global_data.key_slots[key_id - PSA_KEY_ID_VOLATILE_MIN];
- /*
- * Check if both the PSA key identifier key_id and the owner
- * identifier of key match those of the key slot.
- *
- * Note that, if the key slot is not occupied, its PSA key identifier
- * is equal to zero. This is an invalid value for a PSA key identifier
- * and thus cannot be equal to the valid PSA key identifier key_id.
- */
- status = mbedtls_svc_key_id_equal(key, slot->attr.id) ?
- PSA_SUCCESS : PSA_ERROR_DOES_NOT_EXIST;
+ /* Check if both the PSA key identifier key_id and the owner
+ * identifier of key match those of the key slot. */
+ if ((slot->state == PSA_SLOT_FULL) &&
+ (mbedtls_svc_key_id_equal(key, slot->attr.id))) {
+ status = PSA_SUCCESS;
+ } else {
+ status = PSA_ERROR_DOES_NOT_EXIST;
+ }
} else {
if (!psa_is_valid_key_id(key, 1)) {
return PSA_ERROR_INVALID_HANDLE;
@@ -248,11 +249,6 @@
data = (psa_se_key_data_storage_t *) key_data;
status = psa_copy_key_material_into_slot(
slot, data->slot_number, sizeof(data->slot_number));
-
- if (status == PSA_SUCCESS) {
- status = psa_key_slot_state_transition(slot, PSA_SLOT_FILLING,
- PSA_SLOT_FULL);
- }
goto exit;
}
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
@@ -262,9 +258,6 @@
goto exit;
}
- status = psa_key_slot_state_transition(slot, PSA_SLOT_FILLING,
- PSA_SLOT_FULL);
-
exit:
psa_free_persistent_key_data(key_data, key_data_length);
return status;
@@ -336,10 +329,7 @@
/* Copy actual key length and core attributes into the slot on success */
slot->key.bytes = key_buffer_length;
- slot->attr = attributes.core;
-
- status = psa_key_slot_state_transition(slot, PSA_SLOT_FILLING,
- PSA_SLOT_FULL);
+ slot->attr = attributes;
exit:
if (status != PSA_SUCCESS) {
psa_remove_key_data_from_memory(slot);
@@ -358,12 +348,27 @@
return PSA_ERROR_BAD_STATE;
}
+#if defined(MBEDTLS_THREADING_C)
+ /* We need to set status as success, otherwise CORRUPTION_DETECTED
+ * would be returned if the lock fails. */
+ status = PSA_SUCCESS;
+ /* If the key is persistent and not loaded, we cannot unlock the mutex
+ * between checking if the key is loaded and setting the slot as FULL,
+ * as otherwise another thread may load and then destroy the key
+ * in the meantime. */
+ PSA_THREADING_CHK_RET(mbedtls_mutex_lock(
+ &mbedtls_threading_key_slot_mutex));
+#endif
/*
* On success, the pointer to the slot is passed directly to the caller
* thus no need to unlock the key slot here.
*/
status = psa_get_and_lock_key_slot_in_memory(key, p_slot);
if (status != PSA_ERROR_DOES_NOT_EXIST) {
+#if defined(MBEDTLS_THREADING_C)
+ PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+ &mbedtls_threading_key_slot_mutex));
+#endif
return status;
}
@@ -374,6 +379,10 @@
status = psa_reserve_free_key_slot(&volatile_key_id, p_slot);
if (status != PSA_SUCCESS) {
+#if defined(MBEDTLS_THREADING_C)
+ PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+ &mbedtls_threading_key_slot_mutex));
+#endif
return status;
}
@@ -407,10 +416,15 @@
status = psa_register_read(*p_slot);
}
- return status;
#else /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
- return PSA_ERROR_INVALID_HANDLE;
+ status = PSA_ERROR_INVALID_HANDLE;
#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
+
+#if defined(MBEDTLS_THREADING_C)
+ PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+ &mbedtls_threading_key_slot_mutex));
+#endif
+ return status;
}
psa_status_t psa_unregister_read(psa_key_slot_t *slot)
@@ -447,6 +461,24 @@
return PSA_ERROR_CORRUPTION_DETECTED;
}
+psa_status_t psa_unregister_read_under_mutex(psa_key_slot_t *slot)
+{
+ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+#if defined(MBEDTLS_THREADING_C)
+ /* We need to set status as success, otherwise CORRUPTION_DETECTED
+ * would be returned if the lock fails. */
+ status = PSA_SUCCESS;
+ PSA_THREADING_CHK_RET(mbedtls_mutex_lock(
+ &mbedtls_threading_key_slot_mutex));
+#endif
+ status = psa_unregister_read(slot);
+#if defined(MBEDTLS_THREADING_C)
+ PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+ &mbedtls_threading_key_slot_mutex));
+#endif
+ return status;
+}
+
psa_status_t psa_validate_key_location(psa_key_lifetime_t lifetime,
psa_se_drv_table_entry_t **p_drv)
{
@@ -510,7 +542,7 @@
*handle = key;
- return psa_unregister_read(slot);
+ return psa_unregister_read_under_mutex(slot);
#else /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
(void) key;
@@ -521,44 +553,78 @@
psa_status_t psa_close_key(psa_key_handle_t handle)
{
- psa_status_t status;
+ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
psa_key_slot_t *slot;
if (psa_key_handle_is_null(handle)) {
return PSA_SUCCESS;
}
+#if defined(MBEDTLS_THREADING_C)
+ /* We need to set status as success, otherwise CORRUPTION_DETECTED
+ * would be returned if the lock fails. */
+ status = PSA_SUCCESS;
+ PSA_THREADING_CHK_RET(mbedtls_mutex_lock(
+ &mbedtls_threading_key_slot_mutex));
+#endif
status = psa_get_and_lock_key_slot_in_memory(handle, &slot);
if (status != PSA_SUCCESS) {
if (status == PSA_ERROR_DOES_NOT_EXIST) {
status = PSA_ERROR_INVALID_HANDLE;
}
-
+#if defined(MBEDTLS_THREADING_C)
+ PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+ &mbedtls_threading_key_slot_mutex));
+#endif
return status;
}
+
if (slot->registered_readers == 1) {
- return psa_wipe_key_slot(slot);
+ status = psa_wipe_key_slot(slot);
} else {
- return psa_unregister_read(slot);
+ status = psa_unregister_read(slot);
}
+#if defined(MBEDTLS_THREADING_C)
+ PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+ &mbedtls_threading_key_slot_mutex));
+#endif
+
+ return status;
}
psa_status_t psa_purge_key(mbedtls_svc_key_id_t key)
{
- psa_status_t status;
+ psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
psa_key_slot_t *slot;
+#if defined(MBEDTLS_THREADING_C)
+ /* We need to set status as success, otherwise CORRUPTION_DETECTED
+ * would be returned if the lock fails. */
+ status = PSA_SUCCESS;
+ PSA_THREADING_CHK_RET(mbedtls_mutex_lock(
+ &mbedtls_threading_key_slot_mutex));
+#endif
status = psa_get_and_lock_key_slot_in_memory(key, &slot);
if (status != PSA_SUCCESS) {
+#if defined(MBEDTLS_THREADING_C)
+ PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+ &mbedtls_threading_key_slot_mutex));
+#endif
return status;
}
if ((!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) &&
(slot->registered_readers == 1)) {
- return psa_wipe_key_slot(slot);
+ status = psa_wipe_key_slot(slot);
} else {
- return psa_unregister_read(slot);
+ status = psa_unregister_read(slot);
}
+#if defined(MBEDTLS_THREADING_C)
+ PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+ &mbedtls_threading_key_slot_mutex));
+#endif
+
+ return status;
}
void mbedtls_psa_get_stats(mbedtls_psa_stats_t *stats)
diff --git a/library/psa_crypto_slot_management.h b/library/psa_crypto_slot_management.h
index 002429b..bcfc9d8 100644
--- a/library/psa_crypto_slot_management.h
+++ b/library/psa_crypto_slot_management.h
@@ -92,6 +92,8 @@
psa_status_t psa_initialize_key_slots(void);
/** Delete all data from key slots in memory.
+ * This function is not thread safe, it wipes every key slot regardless of
+ * state and reader count. It should only be called when no slot is in use.
*
* This does not affect persistent storage. */
void psa_wipe_all_key_slots(void);
@@ -105,6 +107,9 @@
* It is the responsibility of the caller to change the slot's state to
* PSA_SLOT_EMPTY/FULL once key creation has finished.
*
+ * If multi-threading is enabled, the caller must hold the
+ * global key slot mutex.
+ *
* \param[out] volatile_key_id On success, volatile key identifier
* associated to the returned slot.
* \param[out] p_slot On success, a pointer to the slot.
@@ -200,6 +205,27 @@
*/
psa_status_t psa_unregister_read(psa_key_slot_t *slot);
+/** Wrap a call to psa_unregister_read in the global key slot mutex.
+ *
+ * If threading is disabled, this simply calls psa_unregister_read.
+ *
+ * \note To ease the handling of errors in retrieving a key slot
+ * a NULL input pointer is valid, and the function returns
+ * successfully without doing anything in that case.
+ *
+ * \param[in] slot The key slot.
+ * \retval #PSA_SUCCESS
+ * \p slot is NULL or the key slot reader counter has been
+ * decremented (and potentially wiped) successfully.
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ * The slot's state was neither PSA_SLOT_FULL nor
+ * PSA_SLOT_PENDING_DELETION.
+ * Or a wipe was attempted and the slot's state was not
+ * PSA_SLOT_PENDING_DELETION.
+ * Or registered_readers was equal to 0.
+ */
+psa_status_t psa_unregister_read_under_mutex(psa_key_slot_t *slot);
+
/** Test whether a lifetime designates a key in an external cryptoprocessor.
*
* \param lifetime The lifetime to test.
diff --git a/library/psa_crypto_storage.c b/library/psa_crypto_storage.c
index 13a3c8a..7d1317b 100644
--- a/library/psa_crypto_storage.c
+++ b/library/psa_crypto_storage.c
@@ -235,7 +235,7 @@
void psa_format_key_data_for_storage(const uint8_t *data,
const size_t data_length,
- const psa_core_key_attributes_t *attr,
+ const psa_key_attributes_t *attr,
uint8_t *storage_data)
{
psa_persistent_key_storage_format *storage_format =
@@ -267,7 +267,7 @@
size_t storage_data_length,
uint8_t **key_data,
size_t *key_data_length,
- psa_core_key_attributes_t *attr)
+ psa_key_attributes_t *attr)
{
psa_status_t status;
const psa_persistent_key_storage_format *storage_format =
@@ -314,7 +314,7 @@
return PSA_SUCCESS;
}
-psa_status_t psa_save_persistent_key(const psa_core_key_attributes_t *attr,
+psa_status_t psa_save_persistent_key(const psa_key_attributes_t *attr,
const uint8_t *data,
const size_t data_length)
{
@@ -352,7 +352,7 @@
mbedtls_zeroize_and_free(key_data, key_data_length);
}
-psa_status_t psa_load_persistent_key(psa_core_key_attributes_t *attr,
+psa_status_t psa_load_persistent_key(psa_key_attributes_t *attr,
uint8_t **data,
size_t *data_length)
{
diff --git a/library/psa_crypto_storage.h b/library/psa_crypto_storage.h
index b6b5e15..f1ea265 100644
--- a/library/psa_crypto_storage.h
+++ b/library/psa_crypto_storage.h
@@ -93,7 +93,7 @@
* \retval #PSA_ERROR_DATA_INVALID \emptydescription
* \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
*/
-psa_status_t psa_save_persistent_key(const psa_core_key_attributes_t *attr,
+psa_status_t psa_save_persistent_key(const psa_key_attributes_t *attr,
const uint8_t *data,
const size_t data_length);
@@ -123,7 +123,7 @@
* \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
* \retval #PSA_ERROR_DOES_NOT_EXIST \emptydescription
*/
-psa_status_t psa_load_persistent_key(psa_core_key_attributes_t *attr,
+psa_status_t psa_load_persistent_key(psa_key_attributes_t *attr,
uint8_t **data,
size_t *data_length);
@@ -163,7 +163,7 @@
*/
void psa_format_key_data_for_storage(const uint8_t *data,
const size_t data_length,
- const psa_core_key_attributes_t *attr,
+ const psa_key_attributes_t *attr,
uint8_t *storage_data);
/**
@@ -186,7 +186,7 @@
size_t storage_data_length,
uint8_t **key_data,
size_t *key_data_length,
- psa_core_key_attributes_t *attr);
+ psa_key_attributes_t *attr);
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
/** This symbol is defined if transaction support is required. */
diff --git a/library/psa_util.c b/library/psa_util.c
index 41586e2..4ccc5b0 100644
--- a/library/psa_util.c
+++ b/library/psa_util.c
@@ -8,14 +8,20 @@
#include "common.h"
-#if defined(MBEDTLS_PSA_CRYPTO_C)
+/* This is needed for MBEDTLS_ERR_XXX macros */
+#include <mbedtls/error.h>
-#include <psa/crypto.h>
+#if defined(MBEDTLS_ASN1_WRITE_C)
+#include <mbedtls/asn1write.h>
+#include <psa/crypto_sizes.h>
+#endif
#include "psa_util_internal.h"
-/* The following includes are needed for MBEDTLS_ERR_XXX macros */
-#include <mbedtls/error.h>
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
+
+#include <psa/crypto.h>
+
#if defined(MBEDTLS_MD_LIGHT)
#include <mbedtls/md.h>
#endif
@@ -40,6 +46,7 @@
#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
#include <mbedtls/cipher.h>
#endif
+#include <mbedtls/entropy.h>
/* PSA_SUCCESS is kept at the top of each error table since
* it's the most common status when everything functions properly. */
@@ -158,6 +165,8 @@
return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
case PSA_ERROR_INVALID_ARGUMENT:
return MBEDTLS_ERR_PK_INVALID_ALG;
+ case PSA_ERROR_NOT_PERMITTED:
+ return MBEDTLS_ERR_PK_TYPE_MISMATCH;
case PSA_ERROR_INSUFFICIENT_MEMORY:
return MBEDTLS_ERR_PK_ALLOC_FAILED;
case PSA_ERROR_BAD_STATE:
@@ -330,4 +339,264 @@
}
#endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */
-#endif /* MBEDTLS_PSA_CRYPTO_C */
+/* Wrapper function allowing the classic API to use the PSA RNG.
+ *
+ * `mbedtls_psa_get_random(MBEDTLS_PSA_RANDOM_STATE, ...)` calls
+ * `psa_generate_random(...)`. The state parameter is ignored since the
+ * PSA API doesn't support passing an explicit state.
+ */
+int mbedtls_psa_get_random(void *p_rng,
+ unsigned char *output,
+ size_t output_size)
+{
+ /* This function takes a pointer to the RNG state because that's what
+ * classic mbedtls functions using an RNG expect. The PSA RNG manages
+ * its own state internally and doesn't let the caller access that state.
+ * So we just ignore the state parameter, and in practice we'll pass
+ * NULL. */
+ (void) p_rng;
+ psa_status_t status = psa_generate_random(output, output_size);
+ if (status == PSA_SUCCESS) {
+ return 0;
+ } else {
+ return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
+ }
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
+
+#if defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA)
+
+/**
+ * \brief Convert a single raw coordinate to DER ASN.1 format. The output der
+ * buffer is filled backward (i.e. starting from its end).
+ *
+ * \param raw_buf Buffer containing the raw coordinate to be
+ * converted.
+ * \param raw_len Length of raw_buf in bytes. This must be > 0.
+ * \param der_buf_start Pointer to the beginning of the buffer which
+ * will be filled with the DER converted data.
+ * \param der_buf_end End of the buffer used to store the DER output.
+ *
+ * \return On success, the amount of data (in bytes) written to
+ * the DER buffer.
+ * \return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL if the provided der
+ * buffer is too small to contain all the converted data.
+ * \return MBEDTLS_ERR_ASN1_INVALID_DATA if the input raw
+ * coordinate is null (i.e. all zeros).
+ *
+ * \warning Raw and der buffer must not be overlapping.
+ */
+static int convert_raw_to_der_single_int(const unsigned char *raw_buf, size_t raw_len,
+ unsigned char *der_buf_start,
+ unsigned char *der_buf_end)
+{
+ unsigned char *p = der_buf_end;
+ int len;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+ /* ASN.1 DER encoding requires minimal length, so skip leading 0s.
+ * Provided input MPIs should not be 0, but as a failsafe measure, still
+ * detect that and return error in case. */
+ while (*raw_buf == 0x00) {
+ ++raw_buf;
+ --raw_len;
+ if (raw_len == 0) {
+ return MBEDTLS_ERR_ASN1_INVALID_DATA;
+ }
+ }
+ len = (int) raw_len;
+
+ /* Copy the raw coordinate to the end of der_buf. */
+ if ((p - der_buf_start) < len) {
+ return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+ }
+ p -= len;
+ memcpy(p, raw_buf, len);
+
+ /* If MSb is 1, ASN.1 requires that we prepend a 0. */
+ if (*p & 0x80) {
+ if ((p - der_buf_start) < 1) {
+ return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+ }
+ --p;
+ *p = 0x00;
+ ++len;
+ }
+
+ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, der_buf_start, len));
+ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, der_buf_start, MBEDTLS_ASN1_INTEGER));
+
+ return len;
+}
+
+int mbedtls_ecdsa_raw_to_der(size_t bits, const unsigned char *raw, size_t raw_len,
+ unsigned char *der, size_t der_size, size_t *der_len)
+{
+ unsigned char r[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)];
+ unsigned char s[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)];
+ const size_t coordinate_len = PSA_BITS_TO_BYTES(bits);
+ size_t len = 0;
+ unsigned char *p = der + der_size;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+ if (raw_len != (2 * coordinate_len)) {
+ return MBEDTLS_ERR_ASN1_INVALID_DATA;
+ }
+
+ /* Since raw and der buffers might overlap, dump r and s before starting
+ * the conversion. */
+ memcpy(r, raw, coordinate_len);
+ memcpy(s, raw + coordinate_len, coordinate_len);
+
+ /* der buffer will initially be written starting from its end so we pick s
+ * first and then r. */
+ ret = convert_raw_to_der_single_int(s, coordinate_len, der, p);
+ if (ret < 0) {
+ return ret;
+ }
+ p -= ret;
+ len += ret;
+
+ ret = convert_raw_to_der_single_int(r, coordinate_len, der, p);
+ if (ret < 0) {
+ return ret;
+ }
+ p -= ret;
+ len += ret;
+
+ /* Add ASN.1 header (len + tag). */
+ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, der, len));
+ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, der,
+ MBEDTLS_ASN1_CONSTRUCTED |
+ MBEDTLS_ASN1_SEQUENCE));
+
+ /* memmove the content of der buffer to its beginnig. */
+ memmove(der, p, len);
+ *der_len = len;
+
+ return 0;
+}
+
+/**
+ * \brief Convert a single integer from ASN.1 DER format to raw.
+ *
+ * \param der Buffer containing the DER integer value to be
+ * converted.
+ * \param der_len Length of the der buffer in bytes.
+ * \param raw Output buffer that will be filled with the
+ * converted data. This should be at least
+ * coordinate_size bytes and it must be zeroed before
+ * calling this function.
+ * \param coordinate_size Size (in bytes) of a single coordinate in raw
+ * format.
+ *
+ * \return On success, the amount of DER data parsed from the
+ * provided der buffer.
+ * \return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the integer tag
+ * is missing in the der buffer.
+ * \return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the integer
+ * is null (i.e. all zeros) or if the output raw buffer
+ * is too small to contain the converted raw value.
+ *
+ * \warning Der and raw buffers must not be overlapping.
+ */
+static int convert_der_to_raw_single_int(unsigned char *der, size_t der_len,
+ unsigned char *raw, size_t coordinate_size)
+{
+ unsigned char *p = der;
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t unpadded_len, padding_len = 0;
+
+ /* Get the length of ASN.1 element (i.e. the integer we need to parse). */
+ ret = mbedtls_asn1_get_tag(&p, p + der_len, &unpadded_len,
+ MBEDTLS_ASN1_INTEGER);
+ if (ret != 0) {
+ return ret;
+ }
+
+ /* It's invalid to have:
+ * - unpadded_len == 0.
+ * - MSb set without a leading 0x00 (leading 0x00 is checked below). */
+ if (((unpadded_len == 0) || (*p & 0x80) != 0)) {
+ return MBEDTLS_ERR_ASN1_INVALID_DATA;
+ }
+
+ /* Skip possible leading zero */
+ if (*p == 0x00) {
+ p++;
+ unpadded_len--;
+ /* It is not allowed to have more than 1 leading zero.
+ * Ignore the case in which unpadded_len = 0 because that's a 0 encoded
+ * in ASN.1 format (i.e. 020100). */
+ if ((unpadded_len > 0) && (*p == 0x00)) {
+ return MBEDTLS_ERR_ASN1_INVALID_DATA;
+ }
+ }
+
+ if (unpadded_len > coordinate_size) {
+ /* Parsed number is longer than the maximum expected value. */
+ return MBEDTLS_ERR_ASN1_INVALID_DATA;
+ }
+ padding_len = coordinate_size - unpadded_len;
+ /* raw buffer was already zeroed by the calling function so zero-padding
+ * operation is skipped here. */
+ memcpy(raw + padding_len, p, unpadded_len);
+ p += unpadded_len;
+
+ return (int) (p - der);
+}
+
+int mbedtls_ecdsa_der_to_raw(size_t bits, const unsigned char *der, size_t der_len,
+ unsigned char *raw, size_t raw_size, size_t *raw_len)
+{
+ unsigned char raw_tmp[PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE];
+ unsigned char *p = (unsigned char *) der;
+ size_t data_len;
+ size_t coordinate_size = PSA_BITS_TO_BYTES(bits);
+ int ret;
+
+ /* The output raw buffer should be at least twice the size of a raw
+ * coordinate in order to store r and s. */
+ if (raw_size < coordinate_size * 2) {
+ return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+ }
+
+ /* Check that the provided input DER buffer has the right header. */
+ ret = mbedtls_asn1_get_tag(&p, der + der_len, &data_len,
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+ if (ret != 0) {
+ return ret;
+ }
+
+ memset(raw_tmp, 0, 2 * coordinate_size);
+
+ /* Extract r */
+ ret = convert_der_to_raw_single_int(p, data_len, raw_tmp, coordinate_size);
+ if (ret < 0) {
+ return ret;
+ }
+ p += ret;
+ data_len -= ret;
+
+ /* Extract s */
+ ret = convert_der_to_raw_single_int(p, data_len, raw_tmp + coordinate_size,
+ coordinate_size);
+ if (ret < 0) {
+ return ret;
+ }
+ p += ret;
+ data_len -= ret;
+
+ /* Check that we consumed all the input der data. */
+ if ((size_t) (p - der) != der_len) {
+ return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
+ }
+
+ memcpy(raw, raw_tmp, 2 * coordinate_size);
+ *raw_len = 2 * coordinate_size;
+
+ return 0;
+}
+
+#endif /* MBEDTLS_PSA_UTIL_HAVE_ECDSA */
diff --git a/library/psa_util_internal.h b/library/psa_util_internal.h
index 3e62d5f..70a08a0 100644
--- a/library/psa_util_internal.h
+++ b/library/psa_util_internal.h
@@ -16,7 +16,7 @@
#include "psa/crypto.h"
-#if defined(MBEDTLS_PSA_CRYPTO_C)
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
/*************************************************************************
* FFDH
@@ -96,5 +96,5 @@
sizeof(error_list)/sizeof(error_list[0]), \
fallback_f)
-#endif /* MBEDTLS_PSA_CRYPTO_C */
+#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
#endif /* MBEDTLS_PSA_UTIL_INTERNAL_H */
diff --git a/library/rsa.c b/library/rsa.c
index a90b83a..5debc69 100644
--- a/library/rsa.c
+++ b/library/rsa.c
@@ -32,6 +32,7 @@
#include "rsa_alt_helpers.h"
#include "rsa_internal.h"
#include "mbedtls/oid.h"
+#include "mbedtls/asn1write.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#include "constant_time_internal.h"
@@ -46,6 +47,369 @@
#include "mbedtls/platform.h"
+/*
+ * Wrapper around mbedtls_asn1_get_mpi() that rejects zero.
+ *
+ * The value zero is:
+ * - never a valid value for an RSA parameter
+ * - interpreted as "omitted, please reconstruct" by mbedtls_rsa_complete().
+ *
+ * Since values can't be omitted in PKCS#1, passing a zero value to
+ * rsa_complete() would be incorrect, so reject zero values early.
+ */
+static int asn1_get_nonzero_mpi(unsigned char **p,
+ const unsigned char *end,
+ mbedtls_mpi *X)
+{
+ int ret;
+
+ ret = mbedtls_asn1_get_mpi(p, end, X);
+ if (ret != 0) {
+ return ret;
+ }
+
+ if (mbedtls_mpi_cmp_int(X, 0) == 0) {
+ return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+ }
+
+ return 0;
+}
+
+int mbedtls_rsa_parse_key(mbedtls_rsa_context *rsa, const unsigned char *key, size_t keylen)
+{
+ int ret, version;
+ size_t len;
+ unsigned char *p, *end;
+
+ mbedtls_mpi T;
+ mbedtls_mpi_init(&T);
+
+ p = (unsigned char *) key;
+ end = p + keylen;
+
+ /*
+ * This function parses the RSAPrivateKey (PKCS#1)
+ *
+ * RSAPrivateKey ::= SEQUENCE {
+ * version Version,
+ * modulus INTEGER, -- n
+ * publicExponent INTEGER, -- e
+ * privateExponent INTEGER, -- d
+ * prime1 INTEGER, -- p
+ * prime2 INTEGER, -- q
+ * exponent1 INTEGER, -- d mod (p-1)
+ * exponent2 INTEGER, -- d mod (q-1)
+ * coefficient INTEGER, -- (inverse of q) mod p
+ * otherPrimeInfos OtherPrimeInfos OPTIONAL
+ * }
+ */
+ if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+ return ret;
+ }
+
+ if (end != p + len) {
+ return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+ }
+
+ if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) {
+ return ret;
+ }
+
+ if (version != 0) {
+ return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+ }
+
+ /* Import N */
+ if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
+ (ret = mbedtls_rsa_import(rsa, &T, NULL, NULL,
+ NULL, NULL)) != 0) {
+ goto cleanup;
+ }
+
+ /* Import E */
+ if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
+ (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL,
+ NULL, &T)) != 0) {
+ goto cleanup;
+ }
+
+ /* Import D */
+ if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
+ (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL,
+ &T, NULL)) != 0) {
+ goto cleanup;
+ }
+
+ /* Import P */
+ if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
+ (ret = mbedtls_rsa_import(rsa, NULL, &T, NULL,
+ NULL, NULL)) != 0) {
+ goto cleanup;
+ }
+
+ /* Import Q */
+ if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
+ (ret = mbedtls_rsa_import(rsa, NULL, NULL, &T,
+ NULL, NULL)) != 0) {
+ goto cleanup;
+ }
+
+#if !defined(MBEDTLS_RSA_NO_CRT) && !defined(MBEDTLS_RSA_ALT)
+ /*
+ * The RSA CRT parameters DP, DQ and QP are nominally redundant, in
+ * that they can be easily recomputed from D, P and Q. However by
+ * parsing them from the PKCS1 structure it is possible to avoid
+ * recalculating them which both reduces the overhead of loading
+ * RSA private keys into memory and also avoids side channels which
+ * can arise when computing those values, since all of D, P, and Q
+ * are secret. See https://eprint.iacr.org/2020/055 for a
+ * description of one such attack.
+ */
+
+ /* Import DP */
+ if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
+ (ret = mbedtls_mpi_copy(&rsa->DP, &T)) != 0) {
+ goto cleanup;
+ }
+
+ /* Import DQ */
+ if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
+ (ret = mbedtls_mpi_copy(&rsa->DQ, &T)) != 0) {
+ goto cleanup;
+ }
+
+ /* Import QP */
+ if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
+ (ret = mbedtls_mpi_copy(&rsa->QP, &T)) != 0) {
+ goto cleanup;
+ }
+
+#else
+ /* Verify existence of the CRT params */
+ if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
+ (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
+ (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0) {
+ goto cleanup;
+ }
+#endif
+
+ /* rsa_complete() doesn't complete anything with the default
+ * implementation but is still called:
+ * - for the benefit of alternative implementation that may want to
+ * pre-compute stuff beyond what's provided (eg Montgomery factors)
+ * - as is also sanity-checks the key
+ *
+ * Furthermore, we also check the public part for consistency with
+ * mbedtls_pk_parse_pubkey(), as it includes size minima for example.
+ */
+ if ((ret = mbedtls_rsa_complete(rsa)) != 0 ||
+ (ret = mbedtls_rsa_check_pubkey(rsa)) != 0) {
+ goto cleanup;
+ }
+
+ if (p != end) {
+ ret = MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
+ }
+
+cleanup:
+
+ mbedtls_mpi_free(&T);
+
+ if (ret != 0) {
+ mbedtls_rsa_free(rsa);
+ }
+
+ return ret;
+}
+
+int mbedtls_rsa_parse_pubkey(mbedtls_rsa_context *rsa, const unsigned char *key, size_t keylen)
+{
+ unsigned char *p = (unsigned char *) key;
+ unsigned char *end = (unsigned char *) (key + keylen);
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t len;
+
+ /*
+ * RSAPublicKey ::= SEQUENCE {
+ * modulus INTEGER, -- n
+ * publicExponent INTEGER -- e
+ * }
+ */
+
+ if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+ return ret;
+ }
+
+ if (end != p + len) {
+ return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+ }
+
+ /* Import N */
+ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {
+ return ret;
+ }
+
+ if ((ret = mbedtls_rsa_import_raw(rsa, p, len, NULL, 0, NULL, 0,
+ NULL, 0, NULL, 0)) != 0) {
+ return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+ }
+
+ p += len;
+
+ /* Import E */
+ if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {
+ return ret;
+ }
+
+ if ((ret = mbedtls_rsa_import_raw(rsa, NULL, 0, NULL, 0, NULL, 0,
+ NULL, 0, p, len)) != 0) {
+ return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+ }
+
+ p += len;
+
+ if (mbedtls_rsa_complete(rsa) != 0 ||
+ mbedtls_rsa_check_pubkey(rsa) != 0) {
+ return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+ }
+
+ if (p != end) {
+ return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
+ }
+
+ return 0;
+}
+
+int mbedtls_rsa_write_key(const mbedtls_rsa_context *rsa, unsigned char *start,
+ unsigned char **p)
+{
+ size_t len = 0;
+ int ret;
+
+ mbedtls_mpi T; /* Temporary holding the exported parameters */
+
+ /*
+ * Export the parameters one after another to avoid simultaneous copies.
+ */
+
+ mbedtls_mpi_init(&T);
+
+ /* Export QP */
+ if ((ret = mbedtls_rsa_export_crt(rsa, NULL, NULL, &T)) != 0 ||
+ (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
+ goto end_of_export;
+ }
+ len += ret;
+
+ /* Export DQ */
+ if ((ret = mbedtls_rsa_export_crt(rsa, NULL, &T, NULL)) != 0 ||
+ (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
+ goto end_of_export;
+ }
+ len += ret;
+
+ /* Export DP */
+ if ((ret = mbedtls_rsa_export_crt(rsa, &T, NULL, NULL)) != 0 ||
+ (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
+ goto end_of_export;
+ }
+ len += ret;
+
+ /* Export Q */
+ if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, &T, NULL, NULL)) != 0 ||
+ (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
+ goto end_of_export;
+ }
+ len += ret;
+
+ /* Export P */
+ if ((ret = mbedtls_rsa_export(rsa, NULL, &T, NULL, NULL, NULL)) != 0 ||
+ (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
+ goto end_of_export;
+ }
+ len += ret;
+
+ /* Export D */
+ if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, &T, NULL)) != 0 ||
+ (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
+ goto end_of_export;
+ }
+ len += ret;
+
+ /* Export E */
+ if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &T)) != 0 ||
+ (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
+ goto end_of_export;
+ }
+ len += ret;
+
+ /* Export N */
+ if ((ret = mbedtls_rsa_export(rsa, &T, NULL, NULL, NULL, NULL)) != 0 ||
+ (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
+ goto end_of_export;
+ }
+ len += ret;
+
+end_of_export:
+
+ mbedtls_mpi_free(&T);
+ if (ret < 0) {
+ return ret;
+ }
+
+ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, start, 0));
+ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
+ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start,
+ MBEDTLS_ASN1_CONSTRUCTED |
+ MBEDTLS_ASN1_SEQUENCE));
+
+ return (int) len;
+}
+
+/*
+ * RSAPublicKey ::= SEQUENCE {
+ * modulus INTEGER, -- n
+ * publicExponent INTEGER -- e
+ * }
+ */
+int mbedtls_rsa_write_pubkey(const mbedtls_rsa_context *rsa, unsigned char *start,
+ unsigned char **p)
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t len = 0;
+ mbedtls_mpi T;
+
+ mbedtls_mpi_init(&T);
+
+ /* Export E */
+ if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &T)) != 0 ||
+ (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
+ goto end_of_export;
+ }
+ len += ret;
+
+ /* Export N */
+ if ((ret = mbedtls_rsa_export(rsa, &T, NULL, NULL, NULL, NULL)) != 0 ||
+ (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
+ goto end_of_export;
+ }
+ len += ret;
+
+end_of_export:
+
+ mbedtls_mpi_free(&T);
+ if (ret < 0) {
+ return ret;
+ }
+
+ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
+ MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED |
+ MBEDTLS_ASN1_SEQUENCE));
+
+ return (int) len;
+}
#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)
@@ -653,6 +1017,14 @@
}
/*
+ * Get length in bits of RSA modulus
+ */
+size_t mbedtls_rsa_get_bitlen(const mbedtls_rsa_context *ctx)
+{
+ return mbedtls_mpi_bitlen(&ctx->N);
+}
+
+/*
* Get length in bytes of RSA modulus
*/
size_t mbedtls_rsa_get_len(const mbedtls_rsa_context *ctx)
@@ -660,7 +1032,6 @@
return ctx->len;
}
-
#if defined(MBEDTLS_GENPRIME)
/*
diff --git a/library/rsa_internal.h b/library/rsa_internal.h
index 4081ac6..f79c3b7 100644
--- a/library/rsa_internal.h
+++ b/library/rsa_internal.h
@@ -15,6 +15,85 @@
#define MBEDTLS_RSA_INTERNAL_H
#include "mbedtls/rsa.h"
+#include "mbedtls/asn1.h"
+
+/**
+ * \brief Parse a PKCS#1 (ASN.1) encoded private RSA key.
+ *
+ * \param rsa The RSA context where parsed data will be stored.
+ * \param key The buffer that contains the key.
+ * \param keylen The length of the key buffer in bytes.
+ *
+ * \return 0 on success.
+ * \return MBEDTLS_ERR_ASN1_xxx in case of ASN.1 parsing errors.
+ * \return MBEDTLS_ERR_RSA_xxx in case of RSA internal failures while
+ * parsing data.
+ * \return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED if validity checks on the
+ * provided key fail.
+ */
+int mbedtls_rsa_parse_key(mbedtls_rsa_context *rsa, const unsigned char *key, size_t keylen);
+
+/**
+ * \brief Parse a PKCS#1 (ASN.1) encoded public RSA key.
+ *
+ * \param rsa The RSA context where parsed data will be stored.
+ * \param key The buffer that contains the key.
+ * \param keylen The length of the key buffer in bytes.
+ *
+ * \return 0 on success.
+ * \return MBEDTLS_ERR_ASN1_xxx in case of ASN.1 parsing errors.
+ * \return MBEDTLS_ERR_RSA_xxx in case of RSA internal failures while
+ * parsing data.
+ * \return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED if validity checks on the
+ * provided key fail.
+ */
+int mbedtls_rsa_parse_pubkey(mbedtls_rsa_context *rsa, const unsigned char *key, size_t keylen);
+
+/**
+ * \brief Write a PKCS#1 (ASN.1) encoded private RSA key.
+ *
+ * \param rsa The RSA context which contains the data to be written.
+ * \param start Beginning of the buffer that will be filled with the
+ * private key.
+ * \param p End of the buffer that will be filled with the private key.
+ * On successful return, the referenced pointer will be
+ * updated in order to point to the beginning of written data.
+ *
+ * \return On success, the number of bytes written to the output buffer
+ * (i.e. a value > 0).
+ * \return MBEDTLS_ERR_RSA_BAD_INPUT_DATA if the RSA context does not
+ * contain a valid key pair.
+ * \return MBEDTLS_ERR_ASN1_xxx in case of failure while writing to the
+ * output buffer.
+ *
+ * \note The output buffer is filled backward, i.e. starting from its
+ * end and moving toward its start.
+ */
+int mbedtls_rsa_write_key(const mbedtls_rsa_context *rsa, unsigned char *start,
+ unsigned char **p);
+
+/**
+ * \brief Parse a PKCS#1 (ASN.1) encoded public RSA key.
+ *
+ * \param rsa The RSA context which contains the data to be written.
+ * \param start Beginning of the buffer that will be filled with the
+ * private key.
+ * \param p End of the buffer that will be filled with the private key.
+ * On successful return, the referenced pointer will be
+ * updated in order to point to the beginning of written data.
+ *
+ * \return On success, the number of bytes written to the output buffer
+ * (i.e. a value > 0).
+ * \return MBEDTLS_ERR_RSA_BAD_INPUT_DATA if the RSA context does not
+ * contain a valid public key.
+ * \return MBEDTLS_ERR_ASN1_xxx in case of failure while writing to the
+ * output buffer.
+ *
+ * \note The output buffer is filled backward, i.e. starting from its
+ * end and moving toward its start.
+ */
+int mbedtls_rsa_write_pubkey(const mbedtls_rsa_context *rsa, unsigned char *start,
+ unsigned char **p);
#if defined(MBEDTLS_PKCS1_V21)
/**
diff --git a/library/sha3.c b/library/sha3.c
index d90fefa..5738559 100644
--- a/library/sha3.c
+++ b/library/sha3.c
@@ -14,6 +14,33 @@
#if defined(MBEDTLS_SHA3_C)
+/*
+ * These macros select manually unrolled implementations of parts of the main permutation function.
+ *
+ * Unrolling has a major impact on both performance and code size. gcc performance benefits a lot
+ * from manually unrolling at higher optimisation levels.
+ *
+ * Depending on your size/perf priorities, compiler and target, it may be beneficial to adjust
+ * these; the defaults here should give sensible trade-offs for gcc and clang on aarch64 and
+ * x86-64.
+ */
+#if !defined(MBEDTLS_SHA3_THETA_UNROLL)
+ #define MBEDTLS_SHA3_THETA_UNROLL 0 //no-check-names
+#endif
+#if !defined(MBEDTLS_SHA3_CHI_UNROLL)
+ #if defined(__OPTIMIZE_SIZE__)
+ #define MBEDTLS_SHA3_CHI_UNROLL 0 //no-check-names
+ #else
+ #define MBEDTLS_SHA3_CHI_UNROLL 1 //no-check-names
+ #endif
+#endif
+#if !defined(MBEDTLS_SHA3_PI_UNROLL)
+ #define MBEDTLS_SHA3_PI_UNROLL 1 //no-check-names
+#endif
+#if !defined(MBEDTLS_SHA3_RHO_UNROLL)
+ #define MBEDTLS_SHA3_RHO_UNROLL 1 //no-check-names
+#endif
+
#include "mbedtls/sha3.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
@@ -26,46 +53,45 @@
#define XOR_BYTE 0x6
-typedef struct mbedtls_sha3_family_functions {
- mbedtls_sha3_id id;
-
- uint16_t r;
- uint16_t olen;
-}
-mbedtls_sha3_family_functions;
-
-/*
- * List of supported SHA-3 families
+/* Precomputed masks for the iota transform.
+ *
+ * Each round uses a 64-bit mask value. In each mask values, only
+ * bits whose position is of the form 2^k-1 can be set, thus only
+ * 7 of 64 bits of the mask need to be known for each mask value.
+ *
+ * We use a compressed encoding of the mask where bits 63, 31 and 15
+ * are moved to bits 4-6. This allows us to make each mask value
+ * 1 byte rather than 8 bytes, saving 7*24 = 168 bytes of data (with
+ * perhaps a little variation due to alignment). Decompressing this
+ * requires a little code, but much less than the savings on the table.
+ *
+ * The impact on performance depends on the platform and compiler.
+ * There's a bit more computation, but less memory bandwidth. A quick
+ * benchmark on x86_64 shows a 7% speed improvement with GCC and a
+ * 5% speed penalty with Clang, compared to the naive uint64_t[24] table.
+ * YMMV.
*/
-static mbedtls_sha3_family_functions sha3_families[] = {
- { MBEDTLS_SHA3_224, 1152, 224 },
- { MBEDTLS_SHA3_256, 1088, 256 },
- { MBEDTLS_SHA3_384, 832, 384 },
- { MBEDTLS_SHA3_512, 576, 512 },
- { MBEDTLS_SHA3_NONE, 0, 0 }
+/* Helper macro to set the values of the higher bits in unused low positions */
+#define H(b63, b31, b15) (b63 << 6 | b31 << 5 | b15 << 4)
+static const uint8_t iota_r_packed[24] = {
+ H(0, 0, 0) | 0x01, H(0, 0, 1) | 0x82, H(1, 0, 1) | 0x8a, H(1, 1, 1) | 0x00,
+ H(0, 0, 1) | 0x8b, H(0, 1, 0) | 0x01, H(1, 1, 1) | 0x81, H(1, 0, 1) | 0x09,
+ H(0, 0, 0) | 0x8a, H(0, 0, 0) | 0x88, H(0, 1, 1) | 0x09, H(0, 1, 0) | 0x0a,
+ H(0, 1, 1) | 0x8b, H(1, 0, 0) | 0x8b, H(1, 0, 1) | 0x89, H(1, 0, 1) | 0x03,
+ H(1, 0, 1) | 0x02, H(1, 0, 0) | 0x80, H(0, 0, 1) | 0x0a, H(1, 1, 0) | 0x0a,
+ H(1, 1, 1) | 0x81, H(1, 0, 1) | 0x80, H(0, 1, 0) | 0x01, H(1, 1, 1) | 0x08,
+};
+#undef H
+
+static const uint32_t rho[6] = {
+ 0x3f022425, 0x1c143a09, 0x2c3d3615, 0x27191713, 0x312b382e, 0x3e030832
};
-static const uint64_t rc[24] = {
- 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, 0x8000000080008000,
- 0x000000000000808b, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009,
- 0x000000000000008a, 0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
- 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, 0x8000000000008003,
- 0x8000000000008002, 0x8000000000000080, 0x000000000000800a, 0x800000008000000a,
- 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008,
+static const uint32_t pi[6] = {
+ 0x110b070a, 0x10050312, 0x04181508, 0x0d13170f, 0x0e14020c, 0x01060916
};
-static const uint8_t rho[24] = {
- 1, 62, 28, 27, 36, 44, 6, 55, 20,
- 3, 10, 43, 25, 39, 41, 45, 15,
- 21, 8, 18, 2, 61, 56, 14
-};
-
-static const uint8_t pi[24] = {
- 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4,
- 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1,
-};
-
-#define ROT64(x, y) (((x) << (y)) | ((x) >> (64U - (y))))
+#define ROTR64(x, y) (((x) << (64U - (y))) | ((x) >> (y))) // 64-bit rotate right
#define ABSORB(ctx, idx, v) do { ctx->state[(idx) >> 3] ^= ((uint64_t) (v)) << (((idx) & 0x7) << 3); \
} while (0)
#define SQUEEZE(ctx, idx) ((uint8_t) (ctx->state[(idx) >> 3] >> (((idx) & 0x7) << 3)))
@@ -82,39 +108,97 @@
uint64_t t;
/* Theta */
+#if MBEDTLS_SHA3_THETA_UNROLL == 0 //no-check-names
+ for (i = 0; i < 5; i++) {
+ lane[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20];
+ }
+ for (i = 0; i < 5; i++) {
+ t = lane[(i + 4) % 5] ^ ROTR64(lane[(i + 1) % 5], 63);
+ s[i] ^= t; s[i + 5] ^= t; s[i + 10] ^= t; s[i + 15] ^= t; s[i + 20] ^= t;
+ }
+#else
lane[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20];
lane[1] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21];
lane[2] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22];
lane[3] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23];
lane[4] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24];
- t = lane[4] ^ ROT64(lane[1], 1);
+ t = lane[4] ^ ROTR64(lane[1], 63);
s[0] ^= t; s[5] ^= t; s[10] ^= t; s[15] ^= t; s[20] ^= t;
- t = lane[0] ^ ROT64(lane[2], 1);
+ t = lane[0] ^ ROTR64(lane[2], 63);
s[1] ^= t; s[6] ^= t; s[11] ^= t; s[16] ^= t; s[21] ^= t;
- t = lane[1] ^ ROT64(lane[3], 1);
+ t = lane[1] ^ ROTR64(lane[3], 63);
s[2] ^= t; s[7] ^= t; s[12] ^= t; s[17] ^= t; s[22] ^= t;
- t = lane[2] ^ ROT64(lane[4], 1);
+ t = lane[2] ^ ROTR64(lane[4], 63);
s[3] ^= t; s[8] ^= t; s[13] ^= t; s[18] ^= t; s[23] ^= t;
- t = lane[3] ^ ROT64(lane[0], 1);
+ t = lane[3] ^ ROTR64(lane[0], 63);
s[4] ^= t; s[9] ^= t; s[14] ^= t; s[19] ^= t; s[24] ^= t;
+#endif
/* Rho */
- for (i = 1; i < 25; i++) {
- s[i] = ROT64(s[i], rho[i-1]);
+ for (i = 1; i < 25; i += 4) {
+ uint32_t r = rho[(i - 1) >> 2];
+#if MBEDTLS_SHA3_RHO_UNROLL == 0
+ for (int j = i; j < i + 4; j++) {
+ uint8_t r8 = (uint8_t) (r >> 24);
+ r <<= 8;
+ s[j] = ROTR64(s[j], r8);
+ }
+#else
+ s[i + 0] = ROTR64(s[i + 0], MBEDTLS_BYTE_3(r));
+ s[i + 1] = ROTR64(s[i + 1], MBEDTLS_BYTE_2(r));
+ s[i + 2] = ROTR64(s[i + 2], MBEDTLS_BYTE_1(r));
+ s[i + 3] = ROTR64(s[i + 3], MBEDTLS_BYTE_0(r));
+#endif
}
/* Pi */
t = s[1];
- for (i = 0; i < 24; i++) {
- SWAP(s[pi[i]], t);
+#if MBEDTLS_SHA3_PI_UNROLL == 0
+ for (i = 0; i < 24; i += 4) {
+ uint32_t p = pi[i >> 2];
+ for (unsigned j = 0; j < 4; j++) {
+ SWAP(s[p & 0xff], t);
+ p >>= 8;
+ }
}
+#else
+ uint32_t p = pi[0];
+ SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
+ SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
+ p = pi[1];
+ SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
+ SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
+ p = pi[2];
+ SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
+ SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
+ p = pi[3];
+ SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
+ SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
+ p = pi[4];
+ SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
+ SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
+ p = pi[5];
+ SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
+ SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
+#endif
/* Chi */
+#if MBEDTLS_SHA3_CHI_UNROLL == 0 //no-check-names
+ for (i = 0; i <= 20; i += 5) {
+ lane[0] = s[i]; lane[1] = s[i + 1]; lane[2] = s[i + 2];
+ lane[3] = s[i + 3]; lane[4] = s[i + 4];
+ s[i + 0] ^= (~lane[1]) & lane[2];
+ s[i + 1] ^= (~lane[2]) & lane[3];
+ s[i + 2] ^= (~lane[3]) & lane[4];
+ s[i + 3] ^= (~lane[4]) & lane[0];
+ s[i + 4] ^= (~lane[0]) & lane[1];
+ }
+#else
lane[0] = s[0]; lane[1] = s[1]; lane[2] = s[2]; lane[3] = s[3]; lane[4] = s[4];
s[0] ^= (~lane[1]) & lane[2];
s[1] ^= (~lane[2]) & lane[3];
@@ -149,9 +233,14 @@
s[22] ^= (~lane[3]) & lane[4];
s[23] ^= (~lane[4]) & lane[0];
s[24] ^= (~lane[0]) & lane[1];
+#endif
/* Iota */
- s[0] ^= rc[round];
+ /* Decompress the round masks (see definition of rc) */
+ s[0] ^= ((iota_r_packed[round] & 0x40ull) << 57 |
+ (iota_r_packed[round] & 0x20ull) << 26 |
+ (iota_r_packed[round] & 0x10ull) << 11 |
+ (iota_r_packed[round] & 0x8f));
}
}
@@ -180,21 +269,27 @@
*/
int mbedtls_sha3_starts(mbedtls_sha3_context *ctx, mbedtls_sha3_id id)
{
- mbedtls_sha3_family_functions *p = NULL;
-
- for (p = sha3_families; p->id != MBEDTLS_SHA3_NONE; p++) {
- if (p->id == id) {
+ switch (id) {
+ case MBEDTLS_SHA3_224:
+ ctx->olen = 224 / 8;
+ ctx->max_block_size = 1152 / 8;
break;
- }
+ case MBEDTLS_SHA3_256:
+ ctx->olen = 256 / 8;
+ ctx->max_block_size = 1088 / 8;
+ break;
+ case MBEDTLS_SHA3_384:
+ ctx->olen = 384 / 8;
+ ctx->max_block_size = 832 / 8;
+ break;
+ case MBEDTLS_SHA3_512:
+ ctx->olen = 512 / 8;
+ ctx->max_block_size = 576 / 8;
+ break;
+ default:
+ return MBEDTLS_ERR_SHA3_BAD_INPUT_DATA;
}
- if (p->id == MBEDTLS_SHA3_NONE) {
- return MBEDTLS_ERR_SHA3_BAD_INPUT_DATA;
- }
-
- ctx->olen = p->olen / 8;
- ctx->max_block_size = p->r / 8;
-
memset(ctx->state, 0, sizeof(ctx->state));
ctx->index = 0;
diff --git a/library/sha512.c b/library/sha512.c
index 6011254..6dcea8d 100644
--- a/library/sha512.c
+++ b/library/sha512.c
@@ -102,6 +102,14 @@
# if defined(__linux__)
/* Our preferred method of detection is getauxval() */
# include <sys/auxv.h>
+# if !defined(HWCAP_SHA512)
+/* The same header that declares getauxval() should provide the HWCAP_xxx
+ * constants to analyze its return value. However, the libc may be too
+ * old to have the constant that we need. So if it's missing, assume that
+ * the value is the same one used by the Linux kernel ABI.
+ */
+# define HWCAP_SHA512 (1 << 21)
+# endif
# endif
/* Use SIGILL on Unix, and fall back to it on Linux */
# include <signal.h>
diff --git a/library/ssl_ciphersuites_internal.h b/library/ssl_ciphersuites_internal.h
new file mode 100644
index 0000000..27ff721
--- /dev/null
+++ b/library/ssl_ciphersuites_internal.h
@@ -0,0 +1,154 @@
+/**
+ * \file ssl_ciphersuites_internal.h
+ *
+ * \brief Internal part of the public "ssl_ciphersuites.h".
+ */
+/*
+ * Copyright The Mbed TLS Contributors
+ * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+#ifndef MBEDTLS_SSL_CIPHERSUITES_INTERNAL_H
+#define MBEDTLS_SSL_CIPHERSUITES_INTERNAL_H
+
+#include "mbedtls/pk.h"
+
+#if defined(MBEDTLS_PK_C)
+mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg(const mbedtls_ssl_ciphersuite_t *info);
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+psa_algorithm_t mbedtls_ssl_get_ciphersuite_sig_pk_psa_alg(const mbedtls_ssl_ciphersuite_t *info);
+psa_key_usage_t mbedtls_ssl_get_ciphersuite_sig_pk_psa_usage(const mbedtls_ssl_ciphersuite_t *info);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg(const mbedtls_ssl_ciphersuite_t *info);
+#endif /* MBEDTLS_PK_C */
+
+int mbedtls_ssl_ciphersuite_uses_ec(const mbedtls_ssl_ciphersuite_t *info);
+int mbedtls_ssl_ciphersuite_uses_psk(const mbedtls_ssl_ciphersuite_t *info);
+
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED)
+static inline int mbedtls_ssl_ciphersuite_has_pfs(const mbedtls_ssl_ciphersuite_t *info)
+{
+ switch (info->MBEDTLS_PRIVATE(key_exchange)) {
+ case MBEDTLS_KEY_EXCHANGE_DHE_RSA:
+ case MBEDTLS_KEY_EXCHANGE_DHE_PSK:
+ case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
+ case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK:
+ case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
+ case MBEDTLS_KEY_EXCHANGE_ECJPAKE:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED)
+static inline int mbedtls_ssl_ciphersuite_no_pfs(const mbedtls_ssl_ciphersuite_t *info)
+{
+ switch (info->MBEDTLS_PRIVATE(key_exchange)) {
+ case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
+ case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
+ case MBEDTLS_KEY_EXCHANGE_RSA:
+ case MBEDTLS_KEY_EXCHANGE_PSK:
+ case MBEDTLS_KEY_EXCHANGE_RSA_PSK:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED)
+static inline int mbedtls_ssl_ciphersuite_uses_ecdh(const mbedtls_ssl_ciphersuite_t *info)
+{
+ switch (info->MBEDTLS_PRIVATE(key_exchange)) {
+ case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
+ case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED */
+
+static inline int mbedtls_ssl_ciphersuite_cert_req_allowed(const mbedtls_ssl_ciphersuite_t *info)
+{
+ switch (info->MBEDTLS_PRIVATE(key_exchange)) {
+ case MBEDTLS_KEY_EXCHANGE_RSA:
+ case MBEDTLS_KEY_EXCHANGE_DHE_RSA:
+ case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
+ case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
+ case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
+ case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+static inline int mbedtls_ssl_ciphersuite_uses_srv_cert(const mbedtls_ssl_ciphersuite_t *info)
+{
+ switch (info->MBEDTLS_PRIVATE(key_exchange)) {
+ case MBEDTLS_KEY_EXCHANGE_RSA:
+ case MBEDTLS_KEY_EXCHANGE_RSA_PSK:
+ case MBEDTLS_KEY_EXCHANGE_DHE_RSA:
+ case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
+ case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
+ case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
+ case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED)
+static inline int mbedtls_ssl_ciphersuite_uses_dhe(const mbedtls_ssl_ciphersuite_t *info)
+{
+ switch (info->MBEDTLS_PRIVATE(key_exchange)) {
+ case MBEDTLS_KEY_EXCHANGE_DHE_RSA:
+ case MBEDTLS_KEY_EXCHANGE_DHE_PSK:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED) */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED)
+static inline int mbedtls_ssl_ciphersuite_uses_ecdhe(const mbedtls_ssl_ciphersuite_t *info)
+{
+ switch (info->MBEDTLS_PRIVATE(key_exchange)) {
+ case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
+ case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
+ case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED)
+static inline int mbedtls_ssl_ciphersuite_uses_server_signature(
+ const mbedtls_ssl_ciphersuite_t *info)
+{
+ switch (info->MBEDTLS_PRIVATE(key_exchange)) {
+ case MBEDTLS_KEY_EXCHANGE_DHE_RSA:
+ case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
+ case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */
+
+#endif /* MBEDTLS_SSL_CIPHERSUITES_INTERNAL_H */
diff --git a/library/ssl_client.c b/library/ssl_client.c
index d585ca5..8892acf 100644
--- a/library/ssl_client.c
+++ b/library/ssl_client.c
@@ -12,7 +12,7 @@
#include <string.h>
-#include "mbedtls/debug.h"
+#include "debug_internal.h"
#include "mbedtls/error.h"
#include "mbedtls/platform.h"
@@ -765,11 +765,6 @@
MBEDTLS_SSL_SESSION_TICKETS &&
MBEDTLS_HAVE_TIME */
- if (ssl->conf->f_rng == NULL) {
- MBEDTLS_SSL_DEBUG_MSG(1, ("no RNG provided"));
- return MBEDTLS_ERR_SSL_NO_RNG;
- }
-
/* Bet on the highest configured version if we are not in a TLS 1.2
* renegotiation or session resumption.
*/
diff --git a/library/ssl_debug_helpers.h b/library/ssl_debug_helpers.h
index 2b0e737..a8e3140 100644
--- a/library/ssl_debug_helpers.h
+++ b/library/ssl_debug_helpers.h
@@ -21,6 +21,10 @@
const char *mbedtls_ssl_states_str(mbedtls_ssl_states in);
+#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C)
+const char *mbedtls_ssl_early_data_status_str(mbedtls_ssl_early_data_status in);
+#endif
+
const char *mbedtls_ssl_protocol_version_str(mbedtls_ssl_protocol_version in);
const char *mbedtls_tls_prf_types_str(mbedtls_tls_prf_types in);
diff --git a/library/ssl_misc.h b/library/ssl_misc.h
index 96afe76..883b988 100644
--- a/library/ssl_misc.h
+++ b/library/ssl_misc.h
@@ -44,6 +44,8 @@
#endif
#include "mbedtls/pk.h"
+#include "ssl_ciphersuites_internal.h"
+#include "x509_internal.h"
#include "pk_internal.h"
#include "common.h"
@@ -650,6 +652,10 @@
/* Flag indicating if a CertificateRequest message has been sent
* to the client or not. */
uint8_t certificate_request_sent;
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+ /* Flag indicating if the server has accepted early data or not. */
+ uint8_t early_data_accepted;
+#endif
#endif /* MBEDTLS_SSL_SRV_C */
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
@@ -659,21 +665,21 @@
#if defined(MBEDTLS_SSL_CLI_C)
/** Minimum TLS version to be negotiated.
*
- * It is set up in the ClientHello writing preparation stage and used
- * throughout the ClientHello writing. Not relevant anymore as soon as
- * the protocol version has been negotiated thus as soon as the
- * ServerHello is received.
- * For a fresh handshake not linked to any previous handshake, it is
- * equal to the configured minimum minor version to be negotiated. When
- * renegotiating or resuming a session, it is equal to the previously
- * negotiated minor version.
+ * It is set up in the ClientHello writing preparation stage and used
+ * throughout the ClientHello writing. Not relevant anymore as soon as
+ * the protocol version has been negotiated thus as soon as the
+ * ServerHello is received.
+ * For a fresh handshake not linked to any previous handshake, it is
+ * equal to the configured minimum minor version to be negotiated. When
+ * renegotiating or resuming a session, it is equal to the previously
+ * negotiated minor version.
*
- * There is no maximum TLS version field in this handshake context.
- * From the start of the handshake, we need to define a current protocol
- * version for the record layer which we define as the maximum TLS
- * version to be negotiated. The `tls_version` field of the SSL context is
- * used to store this maximum value until it contains the actual
- * negotiated value.
+ * There is no maximum TLS version field in this handshake context.
+ * From the start of the handshake, we need to define a current protocol
+ * version for the record layer which we define as the maximum TLS
+ * version to be negotiated. The `tls_version` field of the SSL context is
+ * used to store this maximum value until it contains the actual
+ * negotiated value.
*/
mbedtls_ssl_protocol_version min_tls_version;
#endif
@@ -724,15 +730,29 @@
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
uint8_t key_exchange_mode; /*!< Selected key exchange mode */
- /** Number of HelloRetryRequest messages received/sent from/to the server. */
- int hello_retry_request_count;
+ /**
+ * Flag indicating if, in the course of the current handshake, an
+ * HelloRetryRequest message has been sent by the server or received by
+ * the client (<> 0) or not (0).
+ */
+ uint8_t hello_retry_request_flag;
+
+#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
+ /**
+ * Flag indicating if, in the course of the current handshake, a dummy
+ * change_cipher_spec (CCS) record has already been sent. Used to send only
+ * one CCS per handshake while not complicating the handshake state
+ * transitions for that purpose.
+ */
+ uint8_t ccs_sent;
+#endif
#if defined(MBEDTLS_SSL_SRV_C)
- /** selected_group of key_share extension in HelloRetryRequest message. */
- uint16_t hrr_selected_group;
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
uint8_t tls13_kex_modes; /*!< Key exchange modes supported by the client */
#endif
+ /** selected_group of key_share extension in HelloRetryRequest message. */
+ uint16_t hrr_selected_group;
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
uint16_t new_session_tickets_count; /*!< number of session tickets */
#endif
@@ -2131,11 +2151,8 @@
const unsigned char *end,
size_t *out_len);
-#if defined(MBEDTLS_SSL_SRV_C)
-#define MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_RECEIVED \
- MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT
-#endif /* MBEDTLS_SSL_SRV_C */
-
+int mbedtls_ssl_tls13_check_early_data_len(mbedtls_ssl_context *ssl,
+ size_t early_data_len);
#endif /* MBEDTLS_SSL_EARLY_DATA */
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
diff --git a/library/ssl_msg.c b/library/ssl_msg.c
index 6579c96..0c71157 100644
--- a/library/ssl_msg.c
+++ b/library/ssl_msg.c
@@ -18,7 +18,7 @@
#include "mbedtls/ssl.h"
#include "ssl_misc.h"
-#include "mbedtls/debug.h"
+#include "debug_internal.h"
#include "mbedtls/error.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/version.h"
@@ -3985,6 +3985,35 @@
rec)) != 0) {
MBEDTLS_SSL_DEBUG_RET(1, "ssl_decrypt_buf", ret);
+#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_SRV_C)
+ /*
+ * Although the server rejected early data, it might receive early
+ * data as long as it has not received the client Finished message.
+ * It is encrypted with early keys and should be ignored as stated
+ * in section 4.2.10 of RFC 8446:
+ *
+ * "Ignore the extension and return a regular 1-RTT response. The
+ * server then skips past early data by attempting to deprotect
+ * received records using the handshake traffic key, discarding
+ * records which fail deprotection (up to the configured
+ * max_early_data_size). Once a record is deprotected successfully,
+ * it is treated as the start of the client's second flight and the
+ * server proceeds as with an ordinary 1-RTT handshake."
+ */
+ if ((old_msg_type == MBEDTLS_SSL_MSG_APPLICATION_DATA) &&
+ (ssl->discard_early_data_record ==
+ MBEDTLS_SSL_EARLY_DATA_TRY_TO_DEPROTECT_AND_DISCARD)) {
+ MBEDTLS_SSL_DEBUG_MSG(
+ 3, ("EarlyData: deprotect and discard app data records."));
+
+ ret = mbedtls_ssl_tls13_check_early_data_len(ssl, rec->data_len);
+ if (ret != 0) {
+ return ret;
+ }
+ ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;
+ }
+#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_SRV_C */
+
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
if (ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID &&
ssl->conf->ignore_unexpected_cid
@@ -3994,9 +4023,27 @@
}
#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+ /*
+ * The decryption of the record failed, no reason to ignore it,
+ * return in error with the decryption error code.
+ */
return ret;
}
+#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_SRV_C)
+ /*
+ * If the server were discarding protected records that it fails to
+ * deprotect because it has rejected early data, as we have just
+ * deprotected successfully a record, the server has to resume normal
+ * operation and fail the connection if the deprotection of a record
+ * fails.
+ */
+ if (ssl->discard_early_data_record ==
+ MBEDTLS_SSL_EARLY_DATA_TRY_TO_DEPROTECT_AND_DISCARD) {
+ ssl->discard_early_data_record = MBEDTLS_SSL_EARLY_DATA_NO_DISCARD;
+ }
+#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_SRV_C */
+
if (old_msg_type != rec->type) {
MBEDTLS_SSL_DEBUG_MSG(4, ("record type after decrypt (before %d): %d",
old_msg_type, rec->type));
@@ -4070,6 +4117,38 @@
}
+#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_SRV_C)
+ /*
+ * Although the server rejected early data because it needed to send an
+ * HelloRetryRequest message, it might receive early data as long as it has
+ * not received the client Finished message.
+ * The early data is encrypted with early keys and should be ignored as
+ * stated in section 4.2.10 of RFC 8446 (second case):
+ *
+ * "The server then ignores early data by skipping all records with an
+ * external content type of "application_data" (indicating that they are
+ * encrypted), up to the configured max_early_data_size. Ignore application
+ * data message before 2nd ClientHello when early_data was received in 1st
+ * ClientHello."
+ */
+ if (ssl->discard_early_data_record == MBEDTLS_SSL_EARLY_DATA_DISCARD) {
+ if (rec->type == MBEDTLS_SSL_MSG_APPLICATION_DATA) {
+
+ ret = mbedtls_ssl_tls13_check_early_data_len(ssl, rec->data_len);
+ if (ret != 0) {
+ return ret;
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG(
+ 3, ("EarlyData: Ignore application message before 2nd ClientHello"));
+
+ return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;
+ } else if (rec->type == MBEDTLS_SSL_MSG_HANDSHAKE) {
+ ssl->discard_early_data_record = MBEDTLS_SSL_EARLY_DATA_NO_DISCARD;
+ }
+ }
+#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_SRV_C */
+
#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
mbedtls_ssl_dtls_replay_update(ssl);
@@ -5648,12 +5727,53 @@
}
/*
+ * brief Read at most 'len' application data bytes from the input
+ * buffer.
+ *
+ * param ssl SSL context:
+ * - First byte of application data not read yet in the input
+ * buffer located at address `in_offt`.
+ * - The number of bytes of data not read yet is `in_msglen`.
+ * param buf buffer that will hold the data
+ * param len maximum number of bytes to read
+ *
+ * note The function updates the fields `in_offt` and `in_msglen`
+ * according to the number of bytes read.
+ *
+ * return The number of bytes read.
+ */
+static int ssl_read_application_data(
+ mbedtls_ssl_context *ssl, unsigned char *buf, size_t len)
+{
+ size_t n = (len < ssl->in_msglen) ? len : ssl->in_msglen;
+
+ if (len != 0) {
+ memcpy(buf, ssl->in_offt, n);
+ ssl->in_msglen -= n;
+ }
+
+ /* Zeroising the plaintext buffer to erase unused application data
+ from the memory. */
+ mbedtls_platform_zeroize(ssl->in_offt, n);
+
+ if (ssl->in_msglen == 0) {
+ /* all bytes consumed */
+ ssl->in_offt = NULL;
+ ssl->keep_current_message = 0;
+ } else {
+ /* more data available */
+ ssl->in_offt += n;
+ }
+
+ return (int) n;
+}
+
+/*
* Receive application data decrypted from the SSL layer
*/
int mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- size_t n;
if (ssl == NULL || ssl->conf == NULL) {
return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
@@ -5817,32 +5937,34 @@
#endif /* MBEDTLS_SSL_PROTO_DTLS */
}
- n = (len < ssl->in_msglen)
- ? len : ssl->in_msglen;
-
- if (len != 0) {
- memcpy(buf, ssl->in_offt, n);
- ssl->in_msglen -= n;
- }
-
- /* Zeroising the plaintext buffer to erase unused application data
- from the memory. */
- mbedtls_platform_zeroize(ssl->in_offt, n);
-
- if (ssl->in_msglen == 0) {
- /* all bytes consumed */
- ssl->in_offt = NULL;
- ssl->keep_current_message = 0;
- } else {
- /* more data available */
- ssl->in_offt += n;
- }
+ ret = ssl_read_application_data(ssl, buf, len);
MBEDTLS_SSL_DEBUG_MSG(2, ("<= read"));
- return (int) n;
+ return ret;
}
+#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_EARLY_DATA)
+int mbedtls_ssl_read_early_data(mbedtls_ssl_context *ssl,
+ unsigned char *buf, size_t len)
+{
+ if (ssl == NULL || (ssl->conf == NULL)) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+
+ /*
+ * The server may receive early data only while waiting for the End of
+ * Early Data handshake message.
+ */
+ if ((ssl->state != MBEDTLS_SSL_END_OF_EARLY_DATA) ||
+ (ssl->in_offt == NULL)) {
+ return MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA;
+ }
+
+ return ssl_read_application_data(ssl, buf, len);
+}
+#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_EARLY_DATA */
+
/*
* Send application data to be encrypted by the SSL layer, taking care of max
* fragment length and buffer size.
@@ -5946,6 +6068,94 @@
return ret;
}
+#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C)
+int mbedtls_ssl_write_early_data(mbedtls_ssl_context *ssl,
+ const unsigned char *buf, size_t len)
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ const struct mbedtls_ssl_config *conf;
+ int written_data_len = 0;
+
+ MBEDTLS_SSL_DEBUG_MSG(2, ("=> write early_data"));
+
+ if (ssl == NULL || (conf = ssl->conf) == NULL) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+
+ if (conf->endpoint != MBEDTLS_SSL_IS_CLIENT) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+
+ if ((!mbedtls_ssl_conf_is_tls13_enabled(conf)) ||
+ (conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) ||
+ (conf->early_data_enabled != MBEDTLS_SSL_EARLY_DATA_ENABLED)) {
+ return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA;
+ }
+
+ if (ssl->tls_version != MBEDTLS_SSL_VERSION_TLS1_3) {
+ return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA;
+ }
+
+ /*
+ * If we are at the beginning of the handshake, the early data status being
+ * equal to MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN or
+ * MBEDTLS_SSL_EARLY_DATA_STATUS_SENT advance the handshake just
+ * enough to be able to send early data if possible. That way, we can
+ * guarantee that when starting the handshake with this function we will
+ * send at least one record of early data. Note that when the status is
+ * MBEDTLS_SSL_EARLY_DATA_STATUS_SENT and not yet
+ * MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE, we cannot send early data yet
+ * as the early data outbound transform has not been set as we may have to
+ * first send a dummy CCS in clear.
+ */
+ if ((ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN) ||
+ (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_SENT)) {
+ while ((ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN) ||
+ (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_SENT)) {
+ ret = mbedtls_ssl_handshake_step(ssl);
+ if (ret != 0) {
+ MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake_step", ret);
+ return ret;
+ }
+
+ ret = mbedtls_ssl_flush_output(ssl);
+ if (ret != 0) {
+ MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flush_output", ret);
+ return ret;
+ }
+ }
+ } else {
+ /*
+ * If we are past the point where we can send early data, return
+ * immediatly. Otherwise, progress the handshake as much as possible to
+ * not delay it too much. If we reach a point where we can still send
+ * early data, then we will send some.
+ */
+ if ((ssl->early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE) &&
+ (ssl->early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED)) {
+ return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA;
+ }
+
+ ret = mbedtls_ssl_handshake(ssl);
+ if ((ret != 0) && (ret != MBEDTLS_ERR_SSL_WANT_READ)) {
+ MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake", ret);
+ return ret;
+ }
+ }
+
+ if ((ssl->early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE) &&
+ (ssl->early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED)) {
+ return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA;
+ }
+
+ written_data_len = ssl_write_real(ssl, buf, len);
+
+ MBEDTLS_SSL_DEBUG_MSG(2, ("<= write early_data, len=%d", written_data_len));
+
+ return written_data_len;
+}
+#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_CLI_C */
+
/*
* Notify the peer that the connection is being closed
*/
diff --git a/library/ssl_ticket.c b/library/ssl_ticket.c
index cd730fb..5da3887 100644
--- a/library/ssl_ticket.c
+++ b/library/ssl_ticket.c
@@ -75,6 +75,10 @@
#if defined(MBEDTLS_HAVE_TIME)
key->generation_time = mbedtls_time(NULL);
#endif
+ /* The lifetime of a key is the configured lifetime of the tickets when
+ * the key is created.
+ */
+ key->lifetime = ctx->ticket_lifetime;
if ((ret = ctx->f_rng(ctx->p_rng, key->name, sizeof(key->name))) != 0) {
return ret;
@@ -116,16 +120,17 @@
#if !defined(MBEDTLS_HAVE_TIME)
((void) ctx);
#else
- if (ctx->ticket_lifetime != 0) {
+ mbedtls_ssl_ticket_key * const key = ctx->keys + ctx->active;
+ if (key->lifetime != 0) {
mbedtls_time_t current_time = mbedtls_time(NULL);
- mbedtls_time_t key_time = ctx->keys[ctx->active].generation_time;
+ mbedtls_time_t key_time = key->generation_time;
#if defined(MBEDTLS_USE_PSA_CRYPTO)
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
#endif
if (current_time >= key_time &&
- (uint64_t) (current_time - key_time) < ctx->ticket_lifetime) {
+ (uint64_t) (current_time - key_time) < key->lifetime) {
return 0;
}
@@ -198,6 +203,8 @@
#if defined(MBEDTLS_HAVE_TIME)
key->generation_time = mbedtls_time(NULL);
#endif
+ key->lifetime = lifetime;
+
return 0;
}
@@ -331,7 +338,7 @@
key = &ctx->keys[ctx->active];
- *ticket_lifetime = ctx->ticket_lifetime;
+ *ticket_lifetime = key->lifetime;
memcpy(key_name, key->name, TICKET_KEY_NAME_BYTES);
@@ -495,43 +502,22 @@
}
#if defined(MBEDTLS_HAVE_TIME)
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
- if (session->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {
- /* Check for expiration */
- mbedtls_ms_time_t ticket_age = -1;
-#if defined(MBEDTLS_SSL_SRV_C)
- if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {
- ticket_age = mbedtls_ms_time() - session->ticket_creation_time;
- }
-#endif
-#if defined(MBEDTLS_SSL_CLI_C)
- if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {
- ticket_age = mbedtls_ms_time() - session->ticket_reception_time;
- }
-#endif
+ mbedtls_ms_time_t ticket_creation_time, ticket_age;
+ mbedtls_ms_time_t ticket_lifetime =
+ (mbedtls_ms_time_t) ctx->ticket_lifetime * 1000;
- mbedtls_ms_time_t ticket_lifetime =
- (mbedtls_ms_time_t) ctx->ticket_lifetime * 1000;
-
- if (ticket_age < 0 || ticket_age > ticket_lifetime) {
- ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
- goto cleanup;
- }
+ ret = mbedtls_ssl_session_get_ticket_creation_time(session,
+ &ticket_creation_time);
+ if (ret != 0) {
+ goto cleanup;
}
-#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
- if (session->tls_version == MBEDTLS_SSL_VERSION_TLS1_2) {
- /* Check for expiration */
- mbedtls_time_t current_time = mbedtls_time(NULL);
- if (current_time < session->start ||
- (uint32_t) (current_time - session->start) > ctx->ticket_lifetime) {
- ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
- goto cleanup;
- }
+ ticket_age = mbedtls_ms_time() - ticket_creation_time;
+ if (ticket_age < 0 || ticket_age > ticket_lifetime) {
+ ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
+ goto cleanup;
}
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
-#endif /* MBEDTLS_HAVE_TIME */
+#endif
cleanup:
#if defined(MBEDTLS_THREADING_C)
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 0071b06..5002443 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -20,7 +20,7 @@
#include "ssl_debug_helpers.h"
#include "ssl_misc.h"
-#include "mbedtls/debug.h"
+#include "debug_internal.h"
#include "mbedtls/error.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/version.h"
@@ -432,10 +432,6 @@
static int ssl_calc_finished_tls_sha384(mbedtls_ssl_context *, unsigned char *, int);
#endif /* MBEDTLS_MD_CAN_SHA384*/
-static size_t ssl_tls12_session_save(const mbedtls_ssl_session *session,
- unsigned char *buf,
- size_t buf_len);
-
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls12_session_load(mbedtls_ssl_session *session,
const unsigned char *buf,
@@ -631,7 +627,7 @@
[MBEDTLS_SSL_EXT_ID_RECORD_SIZE_LIMIT] = "record_size_limit"
};
-static unsigned int extension_type_table[] = {
+static const unsigned int extension_type_table[] = {
[MBEDTLS_SSL_EXT_ID_UNRECOGNIZED] = 0xff,
[MBEDTLS_SSL_EXT_ID_SERVERNAME] = MBEDTLS_TLS_EXT_SERVERNAME,
[MBEDTLS_SSL_EXT_ID_MAX_FRAGMENT_LENGTH] = MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH,
@@ -1098,6 +1094,16 @@
return MBEDTLS_ERR_SSL_ALLOC_FAILED;
}
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+#if defined(MBEDTLS_SSL_CLI_C)
+ ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_UNKNOWN;
+#endif
+#if defined(MBEDTLS_SSL_SRV_C)
+ ssl->discard_early_data_record = MBEDTLS_SSL_EARLY_DATA_NO_DISCARD;
+#endif
+ ssl->total_early_data_size = 0;
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
/* Initialize structures */
mbedtls_ssl_session_init(ssl->session_negotiate);
ssl_handshake_params_init(ssl->handshake);
@@ -1356,6 +1362,11 @@
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+ if (ssl->conf->f_rng == NULL) {
+ MBEDTLS_SSL_DEBUG_MSG(1, ("no RNG provided"));
+ return MBEDTLS_ERR_SSL_NO_RNG;
+ }
+
/* Space for further checks */
return 0;
@@ -2440,290 +2451,6 @@
#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3)
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
-/* Serialization of TLS 1.3 sessions:
- *
- * struct {
- * opaque hostname<0..2^16-1>;
- * uint64 ticket_reception_time;
- * uint32 ticket_lifetime;
- * opaque ticket<1..2^16-1>;
- * } ClientOnlyData;
- *
- * struct {
- * uint8 endpoint;
- * uint8 ciphersuite[2];
- * uint32 ticket_age_add;
- * uint8 ticket_flags;
- * opaque resumption_key<0..255>;
- * uint32 max_early_data_size;
- * uint16 record_size_limit;
- * select ( endpoint ) {
- * case client: ClientOnlyData;
- * case server: uint64 ticket_creation_time;
- * };
- * } serialized_session_tls13;
- *
- */
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_tls13_session_save(const mbedtls_ssl_session *session,
- unsigned char *buf,
- size_t buf_len,
- size_t *olen)
-{
- unsigned char *p = buf;
-#if defined(MBEDTLS_SSL_CLI_C) && \
- defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
- size_t hostname_len = (session->hostname == NULL) ?
- 0 : strlen(session->hostname) + 1;
-#endif
- size_t needed = 1 /* endpoint */
- + 2 /* ciphersuite */
- + 4 /* ticket_age_add */
- + 1 /* ticket_flags */
- + 1; /* resumption_key length */
- *olen = 0;
-
- if (session->resumption_key_len > MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN) {
- return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
- }
- needed += session->resumption_key_len; /* resumption_key */
-
-#if defined(MBEDTLS_SSL_EARLY_DATA)
- needed += 4; /* max_early_data_size */
-#endif
-#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
- needed += 2; /* record_size_limit */
-#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */
-
-#if defined(MBEDTLS_HAVE_TIME)
- needed += 8; /* ticket_creation_time or ticket_reception_time */
-#endif
-
-#if defined(MBEDTLS_SSL_CLI_C)
- if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {
-#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
- needed += 2 /* hostname_len */
- + hostname_len; /* hostname */
-#endif
-
- needed += 4 /* ticket_lifetime */
- + 2; /* ticket_len */
-
- /* Check size_t overflow */
- if (session->ticket_len > SIZE_MAX - needed) {
- return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
- }
-
- needed += session->ticket_len; /* ticket */
- }
-#endif /* MBEDTLS_SSL_CLI_C */
-
- *olen = needed;
- if (needed > buf_len) {
- return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
- }
-
- p[0] = session->endpoint;
- MBEDTLS_PUT_UINT16_BE(session->ciphersuite, p, 1);
- MBEDTLS_PUT_UINT32_BE(session->ticket_age_add, p, 3);
- p[7] = session->ticket_flags;
-
- /* save resumption_key */
- p[8] = session->resumption_key_len;
- p += 9;
- memcpy(p, session->resumption_key, session->resumption_key_len);
- p += session->resumption_key_len;
-
-#if defined(MBEDTLS_SSL_EARLY_DATA)
- MBEDTLS_PUT_UINT32_BE(session->max_early_data_size, p, 0);
- p += 4;
-#endif
-#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
- MBEDTLS_PUT_UINT16_BE(session->record_size_limit, p, 0);
- p += 2;
-#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */
-
-#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C)
- if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {
- MBEDTLS_PUT_UINT64_BE((uint64_t) session->ticket_creation_time, p, 0);
- p += 8;
- }
-#endif /* MBEDTLS_HAVE_TIME */
-
-#if defined(MBEDTLS_SSL_CLI_C)
- if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {
-#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
- MBEDTLS_PUT_UINT16_BE(hostname_len, p, 0);
- p += 2;
- if (hostname_len > 0) {
- /* save host name */
- memcpy(p, session->hostname, hostname_len);
- p += hostname_len;
- }
-#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
-
-#if defined(MBEDTLS_HAVE_TIME)
- MBEDTLS_PUT_UINT64_BE((uint64_t) session->ticket_reception_time, p, 0);
- p += 8;
-#endif
- MBEDTLS_PUT_UINT32_BE(session->ticket_lifetime, p, 0);
- p += 4;
-
- MBEDTLS_PUT_UINT16_BE(session->ticket_len, p, 0);
- p += 2;
-
- if (session->ticket != NULL && session->ticket_len > 0) {
- memcpy(p, session->ticket, session->ticket_len);
- p += session->ticket_len;
- }
- }
-#endif /* MBEDTLS_SSL_CLI_C */
- return 0;
-}
-
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_tls13_session_load(mbedtls_ssl_session *session,
- const unsigned char *buf,
- size_t len)
-{
- const unsigned char *p = buf;
- const unsigned char *end = buf + len;
-
- if (end - p < 9) {
- return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
- }
- session->endpoint = p[0];
- session->ciphersuite = MBEDTLS_GET_UINT16_BE(p, 1);
- session->ticket_age_add = MBEDTLS_GET_UINT32_BE(p, 3);
- session->ticket_flags = p[7];
-
- /* load resumption_key */
- session->resumption_key_len = p[8];
- p += 9;
-
- if (end - p < session->resumption_key_len) {
- return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
- }
-
- if (sizeof(session->resumption_key) < session->resumption_key_len) {
- return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
- }
- memcpy(session->resumption_key, p, session->resumption_key_len);
- p += session->resumption_key_len;
-
-#if defined(MBEDTLS_SSL_EARLY_DATA)
- if (end - p < 4) {
- return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
- }
- session->max_early_data_size = MBEDTLS_GET_UINT32_BE(p, 0);
- p += 4;
-#endif
-#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
- if (end - p < 2) {
- return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
- }
- session->record_size_limit = MBEDTLS_GET_UINT16_BE(p, 0);
- p += 2;
-#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */
-
-#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C)
- if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {
- if (end - p < 8) {
- return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
- }
- session->ticket_creation_time = MBEDTLS_GET_UINT64_BE(p, 0);
- p += 8;
- }
-#endif /* MBEDTLS_HAVE_TIME */
-
-#if defined(MBEDTLS_SSL_CLI_C)
- if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {
-#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
- size_t hostname_len;
- /* load host name */
- if (end - p < 2) {
- return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
- }
- hostname_len = MBEDTLS_GET_UINT16_BE(p, 0);
- p += 2;
-
- if (end - p < (long int) hostname_len) {
- return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
- }
- if (hostname_len > 0) {
- session->hostname = mbedtls_calloc(1, hostname_len);
- if (session->hostname == NULL) {
- return MBEDTLS_ERR_SSL_ALLOC_FAILED;
- }
- memcpy(session->hostname, p, hostname_len);
- p += hostname_len;
- }
-#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
-
-#if defined(MBEDTLS_HAVE_TIME)
- if (end - p < 8) {
- return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
- }
- session->ticket_reception_time = MBEDTLS_GET_UINT64_BE(p, 0);
- p += 8;
-#endif
- if (end - p < 4) {
- return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
- }
- session->ticket_lifetime = MBEDTLS_GET_UINT32_BE(p, 0);
- p += 4;
-
- if (end - p < 2) {
- return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
- }
- session->ticket_len = MBEDTLS_GET_UINT16_BE(p, 0);
- p += 2;
-
- if (end - p < (long int) session->ticket_len) {
- return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
- }
- if (session->ticket_len > 0) {
- session->ticket = mbedtls_calloc(1, session->ticket_len);
- if (session->ticket == NULL) {
- return MBEDTLS_ERR_SSL_ALLOC_FAILED;
- }
- memcpy(session->ticket, p, session->ticket_len);
- p += session->ticket_len;
- }
- }
-#endif /* MBEDTLS_SSL_CLI_C */
-
- return 0;
-
-}
-#else /* MBEDTLS_SSL_SESSION_TICKETS */
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_tls13_session_save(const mbedtls_ssl_session *session,
- unsigned char *buf,
- size_t buf_len,
- size_t *olen)
-{
- ((void) session);
- ((void) buf);
- ((void) buf_len);
- *olen = 0;
- return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
-}
-
-static int ssl_tls13_session_load(const mbedtls_ssl_session *session,
- unsigned char *buf,
- size_t buf_len)
-{
- ((void) session);
- ((void) buf);
- ((void) buf_len);
- return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
-}
-#endif /* !MBEDTLS_SSL_SESSION_TICKETS */
-#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
-
psa_status_t mbedtls_ssl_cipher_to_psa(mbedtls_cipher_type_t mbedtls_cipher_type,
size_t taglen,
psa_algorithm_t *alg,
@@ -3640,6 +3367,630 @@
}
#endif /* MBEDTLS_SSL_CLI_C */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+
+/* Serialization of TLS 1.2 sessions
+ *
+ * For more detail, see the description of ssl_session_save().
+ */
+static size_t ssl_tls12_session_save(const mbedtls_ssl_session *session,
+ unsigned char *buf,
+ size_t buf_len)
+{
+ unsigned char *p = buf;
+ size_t used = 0;
+
+#if defined(MBEDTLS_HAVE_TIME)
+ uint64_t start;
+#endif
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+ size_t cert_len;
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
+
+ /*
+ * Time
+ */
+#if defined(MBEDTLS_HAVE_TIME)
+ used += 8;
+
+ if (used <= buf_len) {
+ start = (uint64_t) session->start;
+
+ MBEDTLS_PUT_UINT64_BE(start, p, 0);
+ p += 8;
+ }
+#endif /* MBEDTLS_HAVE_TIME */
+
+ /*
+ * Basic mandatory fields
+ */
+ used += 1 /* id_len */
+ + sizeof(session->id)
+ + sizeof(session->master)
+ + 4; /* verify_result */
+
+ if (used <= buf_len) {
+ *p++ = MBEDTLS_BYTE_0(session->id_len);
+ memcpy(p, session->id, 32);
+ p += 32;
+
+ memcpy(p, session->master, 48);
+ p += 48;
+
+ MBEDTLS_PUT_UINT32_BE(session->verify_result, p, 0);
+ p += 4;
+ }
+
+ /*
+ * Peer's end-entity certificate
+ */
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+ if (session->peer_cert == NULL) {
+ cert_len = 0;
+ } else {
+ cert_len = session->peer_cert->raw.len;
+ }
+
+ used += 3 + cert_len;
+
+ if (used <= buf_len) {
+ *p++ = MBEDTLS_BYTE_2(cert_len);
+ *p++ = MBEDTLS_BYTE_1(cert_len);
+ *p++ = MBEDTLS_BYTE_0(cert_len);
+
+ if (session->peer_cert != NULL) {
+ memcpy(p, session->peer_cert->raw.p, cert_len);
+ p += cert_len;
+ }
+ }
+#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+ if (session->peer_cert_digest != NULL) {
+ used += 1 /* type */ + 1 /* length */ + session->peer_cert_digest_len;
+ if (used <= buf_len) {
+ *p++ = (unsigned char) session->peer_cert_digest_type;
+ *p++ = (unsigned char) session->peer_cert_digest_len;
+ memcpy(p, session->peer_cert_digest,
+ session->peer_cert_digest_len);
+ p += session->peer_cert_digest_len;
+ }
+ } else {
+ used += 2;
+ if (used <= buf_len) {
+ *p++ = (unsigned char) MBEDTLS_MD_NONE;
+ *p++ = 0;
+ }
+ }
+#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
+
+ /*
+ * Session ticket if any, plus associated data
+ */
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+#if defined(MBEDTLS_SSL_CLI_C)
+ if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {
+ used += 3 + session->ticket_len + 4; /* len + ticket + lifetime */
+
+ if (used <= buf_len) {
+ *p++ = MBEDTLS_BYTE_2(session->ticket_len);
+ *p++ = MBEDTLS_BYTE_1(session->ticket_len);
+ *p++ = MBEDTLS_BYTE_0(session->ticket_len);
+
+ if (session->ticket != NULL) {
+ memcpy(p, session->ticket, session->ticket_len);
+ p += session->ticket_len;
+ }
+
+ MBEDTLS_PUT_UINT32_BE(session->ticket_lifetime, p, 0);
+ p += 4;
+ }
+ }
+#endif /* MBEDTLS_SSL_CLI_C */
+#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C)
+ if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {
+ used += 8;
+
+ if (used <= buf_len) {
+ MBEDTLS_PUT_UINT64_BE((uint64_t) session->ticket_creation_time, p, 0);
+ p += 8;
+ }
+ }
+#endif /* MBEDTLS_HAVE_TIME && MBEDTLS_SSL_SRV_C */
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+
+ /*
+ * Misc extension-related info
+ */
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+ used += 1;
+
+ if (used <= buf_len) {
+ *p++ = session->mfl_code;
+ }
+#endif
+
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+ used += 1;
+
+ if (used <= buf_len) {
+ *p++ = MBEDTLS_BYTE_0(session->encrypt_then_mac);
+ }
+#endif
+
+ return used;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls12_session_load(mbedtls_ssl_session *session,
+ const unsigned char *buf,
+ size_t len)
+{
+#if defined(MBEDTLS_HAVE_TIME)
+ uint64_t start;
+#endif
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+ size_t cert_len;
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
+
+ const unsigned char *p = buf;
+ const unsigned char * const end = buf + len;
+
+ /*
+ * Time
+ */
+#if defined(MBEDTLS_HAVE_TIME)
+ if (8 > (size_t) (end - p)) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+
+ start = MBEDTLS_GET_UINT64_BE(p, 0);
+ p += 8;
+
+ session->start = (time_t) start;
+#endif /* MBEDTLS_HAVE_TIME */
+
+ /*
+ * Basic mandatory fields
+ */
+ if (1 + 32 + 48 + 4 > (size_t) (end - p)) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+
+ session->id_len = *p++;
+ memcpy(session->id, p, 32);
+ p += 32;
+
+ memcpy(session->master, p, 48);
+ p += 48;
+
+ session->verify_result = MBEDTLS_GET_UINT32_BE(p, 0);
+ p += 4;
+
+ /* Immediately clear invalid pointer values that have been read, in case
+ * we exit early before we replaced them with valid ones. */
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+ session->peer_cert = NULL;
+#else
+ session->peer_cert_digest = NULL;
+#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
+#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
+ session->ticket = NULL;
+#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
+
+ /*
+ * Peer certificate
+ */
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+ /* Deserialize CRT from the end of the ticket. */
+ if (3 > (size_t) (end - p)) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+
+ cert_len = MBEDTLS_GET_UINT24_BE(p, 0);
+ p += 3;
+
+ if (cert_len != 0) {
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+ if (cert_len > (size_t) (end - p)) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+
+ session->peer_cert = mbedtls_calloc(1, sizeof(mbedtls_x509_crt));
+
+ if (session->peer_cert == NULL) {
+ return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+ }
+
+ mbedtls_x509_crt_init(session->peer_cert);
+
+ if ((ret = mbedtls_x509_crt_parse_der(session->peer_cert,
+ p, cert_len)) != 0) {
+ mbedtls_x509_crt_free(session->peer_cert);
+ mbedtls_free(session->peer_cert);
+ session->peer_cert = NULL;
+ return ret;
+ }
+
+ p += cert_len;
+ }
+#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+ /* Deserialize CRT digest from the end of the ticket. */
+ if (2 > (size_t) (end - p)) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+
+ session->peer_cert_digest_type = (mbedtls_md_type_t) *p++;
+ session->peer_cert_digest_len = (size_t) *p++;
+
+ if (session->peer_cert_digest_len != 0) {
+ const mbedtls_md_info_t *md_info =
+ mbedtls_md_info_from_type(session->peer_cert_digest_type);
+ if (md_info == NULL) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+ if (session->peer_cert_digest_len != mbedtls_md_get_size(md_info)) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+
+ if (session->peer_cert_digest_len > (size_t) (end - p)) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+
+ session->peer_cert_digest =
+ mbedtls_calloc(1, session->peer_cert_digest_len);
+ if (session->peer_cert_digest == NULL) {
+ return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+ }
+
+ memcpy(session->peer_cert_digest, p,
+ session->peer_cert_digest_len);
+ p += session->peer_cert_digest_len;
+ }
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
+
+ /*
+ * Session ticket and associated data
+ */
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+#if defined(MBEDTLS_SSL_CLI_C)
+ if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {
+ if (3 > (size_t) (end - p)) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+
+ session->ticket_len = MBEDTLS_GET_UINT24_BE(p, 0);
+ p += 3;
+
+ if (session->ticket_len != 0) {
+ if (session->ticket_len > (size_t) (end - p)) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+
+ session->ticket = mbedtls_calloc(1, session->ticket_len);
+ if (session->ticket == NULL) {
+ return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+ }
+
+ memcpy(session->ticket, p, session->ticket_len);
+ p += session->ticket_len;
+ }
+
+ if (4 > (size_t) (end - p)) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+
+ session->ticket_lifetime = MBEDTLS_GET_UINT32_BE(p, 0);
+ p += 4;
+ }
+#endif /* MBEDTLS_SSL_CLI_C */
+#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C)
+ if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {
+ if (8 > (size_t) (end - p)) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+ session->ticket_creation_time = MBEDTLS_GET_UINT64_BE(p, 0);
+ p += 8;
+ }
+#endif /* MBEDTLS_HAVE_TIME && MBEDTLS_SSL_SRV_C */
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+
+ /*
+ * Misc extension-related info
+ */
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+ if (1 > (size_t) (end - p)) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+
+ session->mfl_code = *p++;
+#endif
+
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+ if (1 > (size_t) (end - p)) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+
+ session->encrypt_then_mac = *p++;
+#endif
+
+ /* Done, should have consumed entire buffer */
+ if (p != end) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+
+ return 0;
+}
+
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+/* Serialization of TLS 1.3 sessions:
+ *
+ * For more detail, see the description of ssl_session_save().
+ */
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_session_save(const mbedtls_ssl_session *session,
+ unsigned char *buf,
+ size_t buf_len,
+ size_t *olen)
+{
+ unsigned char *p = buf;
+#if defined(MBEDTLS_SSL_CLI_C) && \
+ defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+ size_t hostname_len = (session->hostname == NULL) ?
+ 0 : strlen(session->hostname) + 1;
+#endif
+ size_t needed = 4 /* ticket_age_add */
+ + 1 /* ticket_flags */
+ + 1; /* resumption_key length */
+ *olen = 0;
+
+ if (session->resumption_key_len > MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+ needed += session->resumption_key_len; /* resumption_key */
+
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+ needed += 4; /* max_early_data_size */
+#endif
+#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
+ needed += 2; /* record_size_limit */
+#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */
+
+#if defined(MBEDTLS_HAVE_TIME)
+ needed += 8; /* ticket_creation_time or ticket_reception_time */
+#endif
+
+#if defined(MBEDTLS_SSL_CLI_C)
+ if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+ needed += 2 /* hostname_len */
+ + hostname_len; /* hostname */
+#endif
+
+ needed += 4 /* ticket_lifetime */
+ + 2; /* ticket_len */
+
+ /* Check size_t overflow */
+ if (session->ticket_len > SIZE_MAX - needed) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+
+ needed += session->ticket_len; /* ticket */
+ }
+#endif /* MBEDTLS_SSL_CLI_C */
+
+ *olen = needed;
+ if (needed > buf_len) {
+ return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
+ }
+
+ MBEDTLS_PUT_UINT32_BE(session->ticket_age_add, p, 0);
+ p[4] = session->ticket_flags;
+
+ /* save resumption_key */
+ p[5] = session->resumption_key_len;
+ p += 6;
+ memcpy(p, session->resumption_key, session->resumption_key_len);
+ p += session->resumption_key_len;
+
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+ MBEDTLS_PUT_UINT32_BE(session->max_early_data_size, p, 0);
+ p += 4;
+#endif
+#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
+ MBEDTLS_PUT_UINT16_BE(session->record_size_limit, p, 0);
+ p += 2;
+#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */
+
+#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C)
+ if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {
+ MBEDTLS_PUT_UINT64_BE((uint64_t) session->ticket_creation_time, p, 0);
+ p += 8;
+ }
+#endif /* MBEDTLS_HAVE_TIME */
+
+#if defined(MBEDTLS_SSL_CLI_C)
+ if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+ MBEDTLS_PUT_UINT16_BE(hostname_len, p, 0);
+ p += 2;
+ if (hostname_len > 0) {
+ /* save host name */
+ memcpy(p, session->hostname, hostname_len);
+ p += hostname_len;
+ }
+#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
+
+#if defined(MBEDTLS_HAVE_TIME)
+ MBEDTLS_PUT_UINT64_BE((uint64_t) session->ticket_reception_time, p, 0);
+ p += 8;
+#endif
+ MBEDTLS_PUT_UINT32_BE(session->ticket_lifetime, p, 0);
+ p += 4;
+
+ MBEDTLS_PUT_UINT16_BE(session->ticket_len, p, 0);
+ p += 2;
+
+ if (session->ticket != NULL && session->ticket_len > 0) {
+ memcpy(p, session->ticket, session->ticket_len);
+ p += session->ticket_len;
+ }
+ }
+#endif /* MBEDTLS_SSL_CLI_C */
+ return 0;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_session_load(mbedtls_ssl_session *session,
+ const unsigned char *buf,
+ size_t len)
+{
+ const unsigned char *p = buf;
+ const unsigned char *end = buf + len;
+
+ if (end - p < 6) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+ session->ticket_age_add = MBEDTLS_GET_UINT32_BE(p, 0);
+ session->ticket_flags = p[4];
+
+ /* load resumption_key */
+ session->resumption_key_len = p[5];
+ p += 6;
+
+ if (end - p < session->resumption_key_len) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+
+ if (sizeof(session->resumption_key) < session->resumption_key_len) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+ memcpy(session->resumption_key, p, session->resumption_key_len);
+ p += session->resumption_key_len;
+
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+ if (end - p < 4) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+ session->max_early_data_size = MBEDTLS_GET_UINT32_BE(p, 0);
+ p += 4;
+#endif
+#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
+ if (end - p < 2) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+ session->record_size_limit = MBEDTLS_GET_UINT16_BE(p, 0);
+ p += 2;
+#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */
+
+#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C)
+ if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {
+ if (end - p < 8) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+ session->ticket_creation_time = MBEDTLS_GET_UINT64_BE(p, 0);
+ p += 8;
+ }
+#endif /* MBEDTLS_HAVE_TIME */
+
+#if defined(MBEDTLS_SSL_CLI_C)
+ if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+ size_t hostname_len;
+ /* load host name */
+ if (end - p < 2) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+ hostname_len = MBEDTLS_GET_UINT16_BE(p, 0);
+ p += 2;
+
+ if (end - p < (long int) hostname_len) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+ if (hostname_len > 0) {
+ session->hostname = mbedtls_calloc(1, hostname_len);
+ if (session->hostname == NULL) {
+ return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+ }
+ memcpy(session->hostname, p, hostname_len);
+ p += hostname_len;
+ }
+#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
+
+#if defined(MBEDTLS_HAVE_TIME)
+ if (end - p < 8) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+ session->ticket_reception_time = MBEDTLS_GET_UINT64_BE(p, 0);
+ p += 8;
+#endif
+ if (end - p < 4) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+ session->ticket_lifetime = MBEDTLS_GET_UINT32_BE(p, 0);
+ p += 4;
+
+ if (end - p < 2) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+ session->ticket_len = MBEDTLS_GET_UINT16_BE(p, 0);
+ p += 2;
+
+ if (end - p < (long int) session->ticket_len) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+ if (session->ticket_len > 0) {
+ session->ticket = mbedtls_calloc(1, session->ticket_len);
+ if (session->ticket == NULL) {
+ return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+ }
+ memcpy(session->ticket, p, session->ticket_len);
+ p += session->ticket_len;
+ }
+ }
+#endif /* MBEDTLS_SSL_CLI_C */
+
+ return 0;
+
+}
+#else /* MBEDTLS_SSL_SESSION_TICKETS */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_session_save(const mbedtls_ssl_session *session,
+ unsigned char *buf,
+ size_t buf_len,
+ size_t *olen)
+{
+ ((void) session);
+ ((void) buf);
+ ((void) buf_len);
+ *olen = 0;
+ return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+}
+
+static int ssl_tls13_session_load(const mbedtls_ssl_session *session,
+ unsigned char *buf,
+ size_t buf_len)
+{
+ ((void) session);
+ ((void) buf);
+ ((void) buf_len);
+ return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+}
+#endif /* !MBEDTLS_SSL_SESSION_TICKETS */
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+
/*
* Define ticket header determining Mbed TLS version
* and structure of the ticket.
@@ -3662,6 +4013,12 @@
#define SSL_SERIALIZED_SESSION_CONFIG_CRT 0
#endif /* MBEDTLS_X509_CRT_PARSE_C */
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+#define SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT 1
+#else
+#define SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT 0
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+
#if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_SESSION_TICKETS)
#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET 1
#else
@@ -3686,12 +4043,34 @@
#define SSL_SERIALIZED_SESSION_CONFIG_TICKET 0
#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+#define SSL_SERIALIZED_SESSION_CONFIG_SNI 1
+#else
+#define SSL_SERIALIZED_SESSION_CONFIG_SNI 0
+#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
+
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+#define SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA 1
+#else
+#define SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA 0
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
+#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
+#define SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE 1
+#else
+#define SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE 0
+#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */
+
#define SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT 0
#define SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT 1
#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT 2
#define SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT 3
#define SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT 4
#define SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT 5
+#define SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT_BIT 6
+#define SSL_SERIALIZED_SESSION_CONFIG_SNI_BIT 7
+#define SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA_BIT 8
+#define SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE_BIT 9
#define SSL_SERIALIZED_SESSION_CONFIG_BITFLAG \
((uint16_t) ( \
@@ -3701,9 +4080,16 @@
SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT) | \
(SSL_SERIALIZED_SESSION_CONFIG_MFL << SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT) | \
(SSL_SERIALIZED_SESSION_CONFIG_ETM << SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT) | \
- (SSL_SERIALIZED_SESSION_CONFIG_TICKET << SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT)))
+ (SSL_SERIALIZED_SESSION_CONFIG_TICKET << SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT) | \
+ (SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT << \
+ SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT_BIT) | \
+ (SSL_SERIALIZED_SESSION_CONFIG_SNI << SSL_SERIALIZED_SESSION_CONFIG_SNI_BIT) | \
+ (SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA << \
+ SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA_BIT) | \
+ (SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE << \
+ SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE_BIT)))
-static unsigned char ssl_serialized_session_header[] = {
+static const unsigned char ssl_serialized_session_header[] = {
MBEDTLS_VERSION_MAJOR,
MBEDTLS_VERSION_MINOR,
MBEDTLS_VERSION_PATCH,
@@ -3715,7 +4101,77 @@
* Serialize a session in the following format:
* (in the presentation language of TLS, RFC 8446 section 3)
*
- * struct {
+ * TLS 1.2 session:
+ *
+ * struct {
+ * #if defined(MBEDTLS_SSL_SESSION_TICKETS)
+ * opaque ticket<0..2^24-1>; // length 0 means no ticket
+ * uint32 ticket_lifetime;
+ * #endif
+ * } ClientOnlyData;
+ *
+ * struct {
+ * #if defined(MBEDTLS_HAVE_TIME)
+ * uint64 start_time;
+ * #endif
+ * uint8 session_id_len; // at most 32
+ * opaque session_id[32];
+ * opaque master[48]; // fixed length in the standard
+ * uint32 verify_result;
+ * #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE
+ * opaque peer_cert<0..2^24-1>; // length 0 means no peer cert
+ * #else
+ * uint8 peer_cert_digest_type;
+ * opaque peer_cert_digest<0..2^8-1>
+ * #endif
+ * select (endpoint) {
+ * case client: ClientOnlyData;
+ * case server: uint64 ticket_creation_time;
+ * };
+ * #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+ * uint8 mfl_code; // up to 255 according to standard
+ * #endif
+ * #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+ * uint8 encrypt_then_mac; // 0 or 1
+ * #endif
+ * } serialized_session_tls12;
+ *
+ *
+ * TLS 1.3 Session:
+ *
+ * struct {
+ * #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+ * opaque hostname<0..2^16-1>;
+ * #endif
+ * #if defined(MBEDTLS_HAVE_TIME)
+ * uint64 ticket_reception_time;
+ * #endif
+ * uint32 ticket_lifetime;
+ * opaque ticket<1..2^16-1>;
+ * } ClientOnlyData;
+ *
+ * struct {
+ * uint32 ticket_age_add;
+ * uint8 ticket_flags;
+ * opaque resumption_key<0..255>;
+ * #if defined(MBEDTLS_SSL_EARLY_DATA)
+ * uint32 max_early_data_size;
+ * #endif
+ * #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
+ * uint16 record_size_limit;
+ * #endif
+ * select ( endpoint ) {
+ * case client: ClientOnlyData;
+ * #if defined(MBEDTLS_HAVE_TIME)
+ * case server: uint64 ticket_creation_time;
+ * #endif
+ * };
+ * } serialized_session_tls13;
+ *
+ *
+ * SSL session:
+ *
+ * struct {
*
* opaque mbedtls_version[3]; // library version: major, minor, patch
* opaque session_format[2]; // library-version specific 16-bit field
@@ -3733,6 +4189,8 @@
* uint8_t minor_ver; // Protocol minor version. Possible values:
* // - TLS 1.2 (0x0303)
* // - TLS 1.3 (0x0304)
+ * uint8_t endpoint;
+ * uint16_t ciphersuite;
*
* select (serialized_session.tls_version) {
*
@@ -3779,11 +4237,16 @@
}
/*
- * TLS version identifier
+ * TLS version identifier, endpoint, ciphersuite
*/
- used += 1;
+ used += 1 /* TLS version */
+ + 1 /* endpoint */
+ + 2; /* ciphersuite */
if (used <= buf_len) {
*p++ = MBEDTLS_BYTE_0(session->tls_version);
+ *p++ = session->endpoint;
+ MBEDTLS_PUT_UINT16_BE(session->ciphersuite, p, 0);
+ p += 2;
}
/* Forward to version-specific serialization routine. */
@@ -3866,12 +4329,15 @@
}
/*
- * TLS version identifier
+ * TLS version identifier, endpoint, ciphersuite
*/
- if (1 > (size_t) (end - p)) {
+ if (4 > (size_t) (end - p)) {
return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
}
session->tls_version = (mbedtls_ssl_protocol_version) (0x0300 | *p++);
+ session->endpoint = *p++;
+ session->ciphersuite = MBEDTLS_GET_UINT16_BE(p, 0);
+ p += 2;
/* Dispatch according to TLS version. */
remaining_len = (size_t) (end - p);
@@ -4428,7 +4894,7 @@
(SSL_SERIALIZED_CONTEXT_CONFIG_ALPN << SSL_SERIALIZED_CONTEXT_CONFIG_ALPN_BIT) | \
0u))
-static unsigned char ssl_serialized_context_header[] = {
+static const unsigned char ssl_serialized_context_header[] = {
MBEDTLS_VERSION_MAJOR,
MBEDTLS_VERSION_MINOR,
MBEDTLS_VERSION_PATCH,
@@ -5046,7 +5512,7 @@
* See the documentation of mbedtls_ssl_conf_curves() for what we promise
* about this list.
*/
-static uint16_t ssl_preset_default_groups[] = {
+static const uint16_t ssl_preset_default_groups[] = {
#if defined(MBEDTLS_ECP_HAVE_CURVE25519)
MBEDTLS_SSL_IANA_TLS_GROUP_X25519,
#endif
@@ -5097,7 +5563,7 @@
* - ssl_tls12_preset* is for TLS 1.2 use only.
* - ssl_preset_* is for TLS 1.3 only or hybrid TLS 1.3/1.2 handshakes.
*/
-static uint16_t ssl_preset_default_sig_algs[] = {
+static const uint16_t ssl_preset_default_sig_algs[] = {
#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \
defined(MBEDTLS_MD_CAN_SHA256) && \
@@ -5192,7 +5658,7 @@
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
/* NOTICE: see above */
-static uint16_t ssl_preset_suiteb_sig_algs[] = {
+static const uint16_t ssl_preset_suiteb_sig_algs[] = {
#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \
defined(MBEDTLS_MD_CAN_SHA256) && \
@@ -5233,7 +5699,7 @@
#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
-static uint16_t ssl_preset_suiteb_groups[] = {
+static const uint16_t ssl_preset_suiteb_groups[] = {
#if defined(MBEDTLS_ECP_HAVE_SECP256R1)
MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1,
#endif
@@ -5247,7 +5713,7 @@
/* Function for checking `ssl_preset_*_sig_algs` and `ssl_tls12_preset_*_sig_algs`
* to make sure there are no duplicated signature algorithm entries. */
MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_check_no_sig_alg_duplication(uint16_t *sig_algs)
+static int ssl_check_no_sig_alg_duplication(const uint16_t *sig_algs)
{
size_t i, j;
int ret = 0;
@@ -8940,360 +9406,6 @@
#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
-/* Serialization of TLS 1.2 sessions:
- *
- * struct {
- * uint64 start_time;
- * uint8 ciphersuite[2]; // defined by the standard
- * uint8 session_id_len; // at most 32
- * opaque session_id[32];
- * opaque master[48]; // fixed length in the standard
- * uint32 verify_result;
- * opaque peer_cert<0..2^24-1>; // length 0 means no peer cert
- * opaque ticket<0..2^24-1>; // length 0 means no ticket
- * uint32 ticket_lifetime;
- * uint8 mfl_code; // up to 255 according to standard
- * uint8 encrypt_then_mac; // 0 or 1
- * } serialized_session_tls12;
- *
- */
-static size_t ssl_tls12_session_save(const mbedtls_ssl_session *session,
- unsigned char *buf,
- size_t buf_len)
-{
- unsigned char *p = buf;
- size_t used = 0;
-
-#if defined(MBEDTLS_HAVE_TIME)
- uint64_t start;
-#endif
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
-#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
- size_t cert_len;
-#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-#endif /* MBEDTLS_X509_CRT_PARSE_C */
-
- /*
- * Time
- */
-#if defined(MBEDTLS_HAVE_TIME)
- used += 8;
-
- if (used <= buf_len) {
- start = (uint64_t) session->start;
-
- MBEDTLS_PUT_UINT64_BE(start, p, 0);
- p += 8;
- }
-#endif /* MBEDTLS_HAVE_TIME */
-
- /*
- * Basic mandatory fields
- */
- used += 2 /* ciphersuite */
- + 1 /* id_len */
- + sizeof(session->id)
- + sizeof(session->master)
- + 4; /* verify_result */
-
- if (used <= buf_len) {
- MBEDTLS_PUT_UINT16_BE(session->ciphersuite, p, 0);
- p += 2;
-
- *p++ = MBEDTLS_BYTE_0(session->id_len);
- memcpy(p, session->id, 32);
- p += 32;
-
- memcpy(p, session->master, 48);
- p += 48;
-
- MBEDTLS_PUT_UINT32_BE(session->verify_result, p, 0);
- p += 4;
- }
-
- /*
- * Peer's end-entity certificate
- */
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
-#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
- if (session->peer_cert == NULL) {
- cert_len = 0;
- } else {
- cert_len = session->peer_cert->raw.len;
- }
-
- used += 3 + cert_len;
-
- if (used <= buf_len) {
- *p++ = MBEDTLS_BYTE_2(cert_len);
- *p++ = MBEDTLS_BYTE_1(cert_len);
- *p++ = MBEDTLS_BYTE_0(cert_len);
-
- if (session->peer_cert != NULL) {
- memcpy(p, session->peer_cert->raw.p, cert_len);
- p += cert_len;
- }
- }
-#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
- if (session->peer_cert_digest != NULL) {
- used += 1 /* type */ + 1 /* length */ + session->peer_cert_digest_len;
- if (used <= buf_len) {
- *p++ = (unsigned char) session->peer_cert_digest_type;
- *p++ = (unsigned char) session->peer_cert_digest_len;
- memcpy(p, session->peer_cert_digest,
- session->peer_cert_digest_len);
- p += session->peer_cert_digest_len;
- }
- } else {
- used += 2;
- if (used <= buf_len) {
- *p++ = (unsigned char) MBEDTLS_MD_NONE;
- *p++ = 0;
- }
- }
-#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-#endif /* MBEDTLS_X509_CRT_PARSE_C */
-
- /*
- * Session ticket if any, plus associated data
- */
-#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
- used += 3 + session->ticket_len + 4; /* len + ticket + lifetime */
-
- if (used <= buf_len) {
- *p++ = MBEDTLS_BYTE_2(session->ticket_len);
- *p++ = MBEDTLS_BYTE_1(session->ticket_len);
- *p++ = MBEDTLS_BYTE_0(session->ticket_len);
-
- if (session->ticket != NULL) {
- memcpy(p, session->ticket, session->ticket_len);
- p += session->ticket_len;
- }
-
- MBEDTLS_PUT_UINT32_BE(session->ticket_lifetime, p, 0);
- p += 4;
- }
-#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
-
- /*
- * Misc extension-related info
- */
-#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
- used += 1;
-
- if (used <= buf_len) {
- *p++ = session->mfl_code;
- }
-#endif
-
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
- used += 1;
-
- if (used <= buf_len) {
- *p++ = MBEDTLS_BYTE_0(session->encrypt_then_mac);
- }
-#endif
-
- return used;
-}
-
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_tls12_session_load(mbedtls_ssl_session *session,
- const unsigned char *buf,
- size_t len)
-{
-#if defined(MBEDTLS_HAVE_TIME)
- uint64_t start;
-#endif
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
-#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
- size_t cert_len;
-#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-#endif /* MBEDTLS_X509_CRT_PARSE_C */
-
- const unsigned char *p = buf;
- const unsigned char * const end = buf + len;
-
- /*
- * Time
- */
-#if defined(MBEDTLS_HAVE_TIME)
- if (8 > (size_t) (end - p)) {
- return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
- }
-
- start = MBEDTLS_GET_UINT64_BE(p, 0);
- p += 8;
-
- session->start = (time_t) start;
-#endif /* MBEDTLS_HAVE_TIME */
-
- /*
- * Basic mandatory fields
- */
- if (2 + 1 + 32 + 48 + 4 > (size_t) (end - p)) {
- return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
- }
-
- session->ciphersuite = MBEDTLS_GET_UINT16_BE(p, 0);
- p += 2;
-
- session->id_len = *p++;
- memcpy(session->id, p, 32);
- p += 32;
-
- memcpy(session->master, p, 48);
- p += 48;
-
- session->verify_result = MBEDTLS_GET_UINT32_BE(p, 0);
- p += 4;
-
- /* Immediately clear invalid pointer values that have been read, in case
- * we exit early before we replaced them with valid ones. */
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
-#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
- session->peer_cert = NULL;
-#else
- session->peer_cert_digest = NULL;
-#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-#endif /* MBEDTLS_X509_CRT_PARSE_C */
-#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
- session->ticket = NULL;
-#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
-
- /*
- * Peer certificate
- */
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
-#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
- /* Deserialize CRT from the end of the ticket. */
- if (3 > (size_t) (end - p)) {
- return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
- }
-
- cert_len = MBEDTLS_GET_UINT24_BE(p, 0);
- p += 3;
-
- if (cert_len != 0) {
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-
- if (cert_len > (size_t) (end - p)) {
- return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
- }
-
- session->peer_cert = mbedtls_calloc(1, sizeof(mbedtls_x509_crt));
-
- if (session->peer_cert == NULL) {
- return MBEDTLS_ERR_SSL_ALLOC_FAILED;
- }
-
- mbedtls_x509_crt_init(session->peer_cert);
-
- if ((ret = mbedtls_x509_crt_parse_der(session->peer_cert,
- p, cert_len)) != 0) {
- mbedtls_x509_crt_free(session->peer_cert);
- mbedtls_free(session->peer_cert);
- session->peer_cert = NULL;
- return ret;
- }
-
- p += cert_len;
- }
-#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
- /* Deserialize CRT digest from the end of the ticket. */
- if (2 > (size_t) (end - p)) {
- return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
- }
-
- session->peer_cert_digest_type = (mbedtls_md_type_t) *p++;
- session->peer_cert_digest_len = (size_t) *p++;
-
- if (session->peer_cert_digest_len != 0) {
- const mbedtls_md_info_t *md_info =
- mbedtls_md_info_from_type(session->peer_cert_digest_type);
- if (md_info == NULL) {
- return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
- }
- if (session->peer_cert_digest_len != mbedtls_md_get_size(md_info)) {
- return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
- }
-
- if (session->peer_cert_digest_len > (size_t) (end - p)) {
- return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
- }
-
- session->peer_cert_digest =
- mbedtls_calloc(1, session->peer_cert_digest_len);
- if (session->peer_cert_digest == NULL) {
- return MBEDTLS_ERR_SSL_ALLOC_FAILED;
- }
-
- memcpy(session->peer_cert_digest, p,
- session->peer_cert_digest_len);
- p += session->peer_cert_digest_len;
- }
-#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-#endif /* MBEDTLS_X509_CRT_PARSE_C */
-
- /*
- * Session ticket and associated data
- */
-#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
- if (3 > (size_t) (end - p)) {
- return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
- }
-
- session->ticket_len = MBEDTLS_GET_UINT24_BE(p, 0);
- p += 3;
-
- if (session->ticket_len != 0) {
- if (session->ticket_len > (size_t) (end - p)) {
- return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
- }
-
- session->ticket = mbedtls_calloc(1, session->ticket_len);
- if (session->ticket == NULL) {
- return MBEDTLS_ERR_SSL_ALLOC_FAILED;
- }
-
- memcpy(session->ticket, p, session->ticket_len);
- p += session->ticket_len;
- }
-
- if (4 > (size_t) (end - p)) {
- return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
- }
-
- session->ticket_lifetime = MBEDTLS_GET_UINT32_BE(p, 0);
- p += 4;
-#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
-
- /*
- * Misc extension-related info
- */
-#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
- if (1 > (size_t) (end - p)) {
- return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
- }
-
- session->mfl_code = *p++;
-#endif
-
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
- if (1 > (size_t) (end - p)) {
- return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
- }
-
- session->encrypt_then_mac = *p++;
-#endif
-
- /* Done, should have consumed entire buffer */
- if (p != end) {
- return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
- }
-
- return 0;
-}
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
int mbedtls_ssl_validate_ciphersuite(
diff --git a/library/ssl_tls12_client.c b/library/ssl_tls12_client.c
index 0c5af87..eac6a3a 100644
--- a/library/ssl_tls12_client.c
+++ b/library/ssl_tls12_client.c
@@ -14,7 +14,7 @@
#include "mbedtls/ssl.h"
#include "ssl_client.h"
#include "ssl_misc.h"
-#include "mbedtls/debug.h"
+#include "debug_internal.h"
#include "mbedtls/error.h"
#include "mbedtls/constant_time.h"
@@ -1268,6 +1268,7 @@
ssl->tls_version = (mbedtls_ssl_protocol_version) mbedtls_ssl_read_version(buf,
ssl->conf->transport);
ssl->session_negotiate->tls_version = ssl->tls_version;
+ ssl->session_negotiate->endpoint = ssl->conf->endpoint;
if (ssl->tls_version < ssl->conf->min_tls_version ||
ssl->tls_version > ssl->conf->max_tls_version) {
@@ -2005,9 +2006,9 @@
return MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH;
}
-#if defined(MBEDTLS_ECP_C)
+#if !defined(MBEDTLS_PK_USE_PSA_EC_DATA)
const mbedtls_ecp_keypair *peer_key = mbedtls_pk_ec_ro(*peer_pk);
-#endif /* MBEDTLS_ECP_C */
+#endif /* !defined(MBEDTLS_PK_USE_PSA_EC_DATA) */
#if defined(MBEDTLS_USE_PSA_CRYPTO)
uint16_t tls_id = 0;
diff --git a/library/ssl_tls12_server.c b/library/ssl_tls12_server.c
index 5a9f6ca..b49a8ae 100644
--- a/library/ssl_tls12_server.c
+++ b/library/ssl_tls12_server.c
@@ -13,7 +13,7 @@
#include "mbedtls/ssl.h"
#include "ssl_misc.h"
-#include "mbedtls/debug.h"
+#include "debug_internal.h"
#include "mbedtls/error.h"
#include "mbedtls/platform_util.h"
#include "constant_time_internal.h"
@@ -1161,6 +1161,7 @@
ssl->tls_version = (mbedtls_ssl_protocol_version) mbedtls_ssl_read_version(buf,
ssl->conf->transport);
ssl->session_negotiate->tls_version = ssl->tls_version;
+ ssl->session_negotiate->endpoint = ssl->conf->endpoint;
if (ssl->tls_version != MBEDTLS_SSL_VERSION_TLS1_2) {
MBEDTLS_SSL_DEBUG_MSG(1, ("server only supports TLS 1.2"));
@@ -2177,11 +2178,6 @@
}
#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */
- if (ssl->conf->f_rng == NULL) {
- MBEDTLS_SSL_DEBUG_MSG(1, ("no RNG provided"));
- return MBEDTLS_ERR_SSL_NO_RNG;
- }
-
/*
* 0 . 0 handshake type
* 1 . 3 handshake length
@@ -2702,8 +2698,7 @@
PSA_KEY_TYPE_ECC_KEY_PAIR(ssl->handshake->xxdh_psa_type));
psa_set_key_bits(&key_attributes, ssl->handshake->xxdh_psa_bits);
- key_len = PSA_BITS_TO_BYTES(key->grp.pbits);
- ret = mbedtls_ecp_write_key(key, buf, key_len);
+ ret = mbedtls_ecp_write_key_ext(key, &key_len, buf, sizeof(buf));
if (ret != 0) {
mbedtls_platform_zeroize(buf, sizeof(buf));
break;
@@ -4281,6 +4276,9 @@
* 10 . 9+n ticket content
*/
+#if defined(MBEDTLS_HAVE_TIME)
+ ssl->session_negotiate->ticket_creation_time = mbedtls_ms_time();
+#endif
if ((ret = ssl->conf->f_ticket_write(ssl->conf->p_ticket,
ssl->session_negotiate,
ssl->out_msg + 10,
diff --git a/library/ssl_tls13_client.c b/library/ssl_tls13_client.c
index a3d33a3..88d6c9e 100644
--- a/library/ssl_tls13_client.c
+++ b/library/ssl_tls13_client.c
@@ -11,7 +11,7 @@
#include <string.h>
-#include "mbedtls/debug.h"
+#include "debug_internal.h"
#include "mbedtls/error.h"
#include "mbedtls/platform.h"
@@ -1180,25 +1180,29 @@
#endif
#if defined(MBEDTLS_SSL_EARLY_DATA)
- if (mbedtls_ssl_conf_tls13_is_some_psk_enabled(ssl) &&
- ssl_tls13_early_data_has_valid_ticket(ssl) &&
- ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_ENABLED) {
+ /* In the first ClientHello, write the early data indication extension if
+ * necessary and update the early data status.
+ * If an HRR has been received and thus we are currently writing the
+ * second ClientHello, the second ClientHello must not contain an early
+ * data extension and the early data status must stay as it is:
+ * MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT or
+ * MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED.
+ */
+ if (!ssl->handshake->hello_retry_request_flag) {
+ if (mbedtls_ssl_conf_tls13_is_some_psk_enabled(ssl) &&
+ ssl_tls13_early_data_has_valid_ticket(ssl) &&
+ ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_ENABLED) {
+ ret = mbedtls_ssl_tls13_write_early_data_ext(
+ ssl, 0, p, end, &ext_len);
+ if (ret != 0) {
+ return ret;
+ }
+ p += ext_len;
- ret = mbedtls_ssl_tls13_write_early_data_ext(
- ssl, 0, p, end, &ext_len);
- if (ret != 0) {
- return ret;
+ ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_SENT;
+ } else {
+ ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT;
}
- p += ext_len;
-
- /* Initializes the status to `rejected`. It will be updated to
- * `accepted` if the EncryptedExtension message contain an early data
- * indication extension.
- */
- ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED;
- } else {
- MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write early_data extension"));
- ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT;
}
#endif /* MBEDTLS_SSL_EARLY_DATA */
@@ -1235,11 +1239,7 @@
size_t psk_len;
const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
- if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED) {
-#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
- mbedtls_ssl_handshake_set_state(
- ssl, MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO);
-#endif
+ if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_SENT) {
MBEDTLS_SSL_DEBUG_MSG(
1, ("Set hs psk for early data when writing the first psk"));
@@ -1294,6 +1294,16 @@
return ret;
}
+#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
+ mbedtls_ssl_handshake_set_state(
+ ssl, MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO);
+#else
+ MBEDTLS_SSL_DEBUG_MSG(
+ 1, ("Switch to early data keys for outbound traffic"));
+ mbedtls_ssl_set_outbound_transform(
+ ssl, ssl->handshake->transform_earlydata);
+ ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE;
+#endif
}
#endif /* MBEDTLS_SSL_EARLY_DATA */
return 0;
@@ -1476,10 +1486,8 @@
return SSL_SERVER_HELLO_TLS1_2;
}
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
- ssl->session_negotiate->endpoint = ssl->conf->endpoint;
ssl->session_negotiate->tls_version = ssl->tls_version;
-#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+ ssl->session_negotiate->endpoint = ssl->conf->endpoint;
handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE;
@@ -1495,7 +1503,7 @@
* to a HelloRetryRequest), it MUST abort the handshake with an
* "unexpected_message" alert.
*/
- if (handshake->hello_retry_request_count > 0) {
+ if (handshake->hello_retry_request_flag) {
MBEDTLS_SSL_DEBUG_MSG(1, ("Multiple HRRs received"));
MBEDTLS_SSL_PEND_FATAL_ALERT(
MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE,
@@ -1517,7 +1525,7 @@
return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
}
- handshake->hello_retry_request_count++;
+ handshake->hello_retry_request_flag = 1;
break;
}
@@ -1672,7 +1680,7 @@
* proposed in the HRR, we abort the handshake and send an
* "illegal_parameter" alert.
*/
- else if ((!is_hrr) && (handshake->hello_retry_request_count > 0) &&
+ else if ((!is_hrr) && handshake->hello_retry_request_flag &&
(cipher_suite != ssl->session_negotiate->ciphersuite)) {
fatal_alert = MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER;
}
@@ -1965,6 +1973,13 @@
}
ssl->session_negotiate->ciphersuite = ssl->handshake->ciphersuite_info->id;
+
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+ if (ssl->early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT) {
+ ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED;
+ }
+#endif
+
return 0;
}
@@ -2224,6 +2239,8 @@
}
ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED;
+ } else if (ssl->early_data_status != MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT) {
+ ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED;
}
#endif
@@ -2261,6 +2278,7 @@
}
+#if defined(MBEDTLS_SSL_EARLY_DATA)
/*
* Handler for MBEDTLS_SSL_END_OF_EARLY_DATA
*
@@ -2299,6 +2317,32 @@
return ret;
}
+int mbedtls_ssl_get_early_data_status(mbedtls_ssl_context *ssl)
+{
+ if ((ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT) ||
+ (!mbedtls_ssl_is_handshake_over(ssl))) {
+ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+ }
+
+ switch (ssl->early_data_status) {
+ case MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT:
+ return MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT;
+ break;
+
+ case MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED:
+ return MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED;
+ break;
+
+ case MBEDTLS_SSL_EARLY_DATA_STATUS_SERVER_FINISHED_RECEIVED:
+ return MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED;
+ break;
+
+ default:
+ return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+ }
+}
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
/*
* STATE HANDLING: CertificateRequest
@@ -2561,9 +2605,8 @@
#if defined(MBEDTLS_SSL_EARLY_DATA)
if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED) {
+ ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_SERVER_FINISHED_RECEIVED;
mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_END_OF_EARLY_DATA);
- } else if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED) {
- mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE);
} else
#endif /* MBEDTLS_SSL_EARLY_DATA */
{
@@ -3022,9 +3065,11 @@
ret = ssl_tls13_process_server_finished(ssl);
break;
+#if defined(MBEDTLS_SSL_EARLY_DATA)
case MBEDTLS_SSL_END_OF_EARLY_DATA:
ret = ssl_tls13_write_end_of_early_data(ssl);
break;
+#endif
case MBEDTLS_SSL_CLIENT_CERTIFICATE:
ret = ssl_tls13_write_client_certificate(ssl);
@@ -3054,32 +3099,34 @@
#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
case MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO:
ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl);
- if (ret == 0) {
- mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO);
+ if (ret != 0) {
+ break;
}
+ mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO);
break;
case MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED:
ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl);
- if (ret == 0) {
- mbedtls_ssl_handshake_set_state(
- ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE);
+ if (ret != 0) {
+ break;
}
+ mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE);
break;
+#if defined(MBEDTLS_SSL_EARLY_DATA)
case MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO:
ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl);
if (ret == 0) {
mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_HELLO);
-#if defined(MBEDTLS_SSL_EARLY_DATA)
MBEDTLS_SSL_DEBUG_MSG(
1, ("Switch to early data keys for outbound traffic"));
mbedtls_ssl_set_outbound_transform(
ssl, ssl->handshake->transform_earlydata);
-#endif
+ ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_CAN_WRITE;
}
break;
+#endif /* MBEDTLS_SSL_EARLY_DATA */
#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
diff --git a/library/ssl_tls13_generic.c b/library/ssl_tls13_generic.c
index 04ecd8b..d448a05 100644
--- a/library/ssl_tls13_generic.c
+++ b/library/ssl_tls13_generic.c
@@ -12,7 +12,7 @@
#include <string.h>
#include "mbedtls/error.h"
-#include "mbedtls/debug.h"
+#include "debug_internal.h"
#include "mbedtls/oid.h"
#include "mbedtls/platform.h"
#include "mbedtls/constant_time.h"
@@ -1379,6 +1379,12 @@
MBEDTLS_SSL_DEBUG_MSG(2, ("=> write change cipher spec"));
+ /* Only one CCS to send. */
+ if (ssl->handshake->ccs_sent) {
+ ret = 0;
+ goto cleanup;
+ }
+
/* Write CCS message */
MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_change_cipher_spec_body(
ssl, ssl->out_msg,
@@ -1390,6 +1396,8 @@
/* Dispatch message */
MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_write_record(ssl, 0));
+ ssl->handshake->ccs_sent = 1;
+
cleanup:
MBEDTLS_SSL_DEBUG_MSG(2, ("<= write change cipher spec"));
@@ -1446,6 +1454,54 @@
return 0;
}
+
+#if defined(MBEDTLS_SSL_SRV_C)
+int mbedtls_ssl_tls13_check_early_data_len(mbedtls_ssl_context *ssl,
+ size_t early_data_len)
+{
+ /*
+ * This function should be called only while an handshake is in progress
+ * and thus a session under negotiation. Add a sanity check to detect a
+ * misuse.
+ */
+ if (ssl->session_negotiate == NULL) {
+ return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+ }
+
+ /* RFC 8446 section 4.6.1
+ *
+ * A server receiving more than max_early_data_size bytes of 0-RTT data
+ * SHOULD terminate the connection with an "unexpected_message" alert.
+ * Note that if it is still possible to send early_data_len bytes of early
+ * data, it means that early_data_len is smaller than max_early_data_size
+ * (type uint32_t) and can fit in an uint32_t. We use this further
+ * down.
+ */
+ if (early_data_len >
+ (ssl->session_negotiate->max_early_data_size -
+ ssl->total_early_data_size)) {
+
+ MBEDTLS_SSL_DEBUG_MSG(
+ 2, ("EarlyData: Too much early data received, %u + %" MBEDTLS_PRINTF_SIZET " > %u",
+ ssl->total_early_data_size, early_data_len,
+ ssl->session_negotiate->max_early_data_size));
+
+ MBEDTLS_SSL_PEND_FATAL_ALERT(
+ MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE,
+ MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE);
+ return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
+ }
+
+ /*
+ * early_data_len has been checked to be less than max_early_data_size
+ * that is uint32_t. Its cast to an uint32_t below is thus safe. We need
+ * the cast to appease some compilers.
+ */
+ ssl->total_early_data_size += (uint32_t) early_data_len;
+
+ return 0;
+}
+#endif /* MBEDTLS_SSL_SRV_C */
#endif /* MBEDTLS_SSL_EARLY_DATA */
/* Reset SSL context and update hash for handling HRR.
@@ -1539,26 +1595,36 @@
uint16_t tls_id, size_t *bits, psa_key_type_t *key_type)
{
switch (tls_id) {
+#if defined(PSA_WANT_DH_RFC7919_2048)
case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE2048:
*bits = 2048;
*key_type = PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919);
return PSA_SUCCESS;
+#endif /* PSA_WANT_DH_RFC7919_2048 */
+#if defined(PSA_WANT_DH_RFC7919_3072)
case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE3072:
*bits = 3072;
*key_type = PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919);
return PSA_SUCCESS;
+#endif /* PSA_WANT_DH_RFC7919_3072 */
+#if defined(PSA_WANT_DH_RFC7919_4096)
case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE4096:
*bits = 4096;
*key_type = PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919);
return PSA_SUCCESS;
+#endif /* PSA_WANT_DH_RFC7919_4096 */
+#if defined(PSA_WANT_DH_RFC7919_6144)
case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE6144:
*bits = 6144;
*key_type = PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919);
return PSA_SUCCESS;
+#endif /* PSA_WANT_DH_RFC7919_6144 */
+#if defined(PSA_WANT_DH_RFC7919_8192)
case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE8192:
*bits = 8192;
*key_type = PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919);
return PSA_SUCCESS;
+#endif /* PSA_WANT_DH_RFC7919_8192 */
default:
return PSA_ERROR_NOT_SUPPORTED;
}
diff --git a/library/ssl_tls13_keys.c b/library/ssl_tls13_keys.c
index edb453c..739414e 100644
--- a/library/ssl_tls13_keys.c
+++ b/library/ssl_tls13_keys.c
@@ -13,7 +13,7 @@
#include <string.h>
#include "mbedtls/hkdf.h"
-#include "mbedtls/debug.h"
+#include "debug_internal.h"
#include "mbedtls/error.h"
#include "mbedtls/platform.h"
diff --git a/library/ssl_tls13_server.c b/library/ssl_tls13_server.c
index 904bb5b..887c5c6 100644
--- a/library/ssl_tls13_server.c
+++ b/library/ssl_tls13_server.c
@@ -9,7 +9,7 @@
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_PROTO_TLS1_3)
-#include "mbedtls/debug.h"
+#include "debug_internal.h"
#include "mbedtls/error.h"
#include "mbedtls/platform.h"
#include "mbedtls/constant_time.h"
@@ -39,6 +39,63 @@
return ciphersuite_info;
}
+static void ssl_tls13_select_ciphersuite(
+ mbedtls_ssl_context *ssl,
+ const unsigned char *cipher_suites,
+ const unsigned char *cipher_suites_end,
+ int psk_ciphersuite_id,
+ psa_algorithm_t psk_hash_alg,
+ const mbedtls_ssl_ciphersuite_t **selected_ciphersuite_info)
+{
+ *selected_ciphersuite_info = NULL;
+
+ /*
+ * In a compliant ClientHello the byte-length of the list of ciphersuites
+ * is even and this function relies on this fact. This should have been
+ * checked in the main ClientHello parsing function. Double check here.
+ */
+ if ((cipher_suites_end - cipher_suites) & 1) {
+ return;
+ }
+
+ for (const unsigned char *p = cipher_suites;
+ p < cipher_suites_end; p += 2) {
+ /*
+ * "cipher_suites_end - p is even" is an invariant of the loop. As
+ * cipher_suites_end - p > 0, we have cipher_suites_end - p >= 2 and it
+ * is thus safe to read two bytes.
+ */
+ uint16_t id = MBEDTLS_GET_UINT16_BE(p, 0);
+
+ const mbedtls_ssl_ciphersuite_t *info =
+ ssl_tls13_validate_peer_ciphersuite(ssl, id);
+ if (info == NULL) {
+ continue;
+ }
+
+ /*
+ * If a valid PSK ciphersuite identifier has been passed in, we want
+ * an exact match.
+ */
+ if (psk_ciphersuite_id != 0) {
+ if (id != psk_ciphersuite_id) {
+ continue;
+ }
+ } else if (psk_hash_alg != PSA_ALG_NONE) {
+ if (mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) info->mac) !=
+ psk_hash_alg) {
+ continue;
+ }
+ }
+
+ *selected_ciphersuite_info = info;
+ return;
+ }
+
+ MBEDTLS_SSL_DEBUG_MSG(2, ("No matched ciphersuite, psk_ciphersuite_id=%x, psk_hash_alg=%x",
+ (unsigned) psk_ciphersuite_id, psk_hash_alg));
+}
+
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
/* From RFC 8446:
*
@@ -90,8 +147,30 @@
return 0;
}
-#define SSL_TLS1_3_OFFERED_PSK_NOT_MATCH 1
-#define SSL_TLS1_3_OFFERED_PSK_MATCH 0
+/*
+ * Non-error return values of
+ * ssl_tls13_offered_psks_check_identity_match_ticket() and
+ * ssl_tls13_offered_psks_check_identity_match(). They are positive to
+ * not collide with error codes that are negative. Zero
+ * (SSL_TLS1_3_PSK_IDENTITY_MATCH) in case of success as it may be propagated
+ * up by the callers of this function as a generic success condition.
+ *
+ * The return value SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE means
+ * that the pre-shared-key identity matches that of a ticket or an externally-
+ * provisioned pre-shared-key. We have thus been able to retrieve the
+ * attributes of the pre-shared-key but at least one of them does not meet
+ * some criteria and the pre-shared-key cannot be used. For example, a ticket
+ * is expired or its version is not TLS 1.3. Note eventually that the return
+ * value SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE does not have
+ * anything to do with binder check. A binder check is done only when a
+ * suitable pre-shared-key has been selected and only for that selected
+ * pre-shared-key: if the binder check fails, we fail the handshake and we do
+ * not try to find another pre-shared-key for which the binder check would
+ * succeed as recommended by the specification.
+ */
+#define SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH 2
+#define SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE 1
+#define SSL_TLS1_3_PSK_IDENTITY_MATCH 0
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
MBEDTLS_CHECK_RETURN_CRITICAL
@@ -109,7 +188,6 @@
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *ticket_buffer;
- unsigned int key_exchanges;
#if defined(MBEDTLS_HAVE_TIME)
mbedtls_ms_time_t now;
mbedtls_ms_time_t server_age;
@@ -123,7 +201,7 @@
/* Ticket parser is not configured, Skip */
if (ssl->conf->f_ticket_parse == NULL || identity_len == 0) {
- return 0;
+ return SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH;
}
/* We create a copy of the encrypted ticket since the ticket parsing
@@ -133,63 +211,51 @@
*/
ticket_buffer = mbedtls_calloc(1, identity_len);
if (ticket_buffer == NULL) {
- MBEDTLS_SSL_DEBUG_MSG(1, ("buffer too small"));
return MBEDTLS_ERR_SSL_ALLOC_FAILED;
}
memcpy(ticket_buffer, identity, identity_len);
- if ((ret = ssl->conf->f_ticket_parse(ssl->conf->p_ticket,
- session,
- ticket_buffer, identity_len)) != 0) {
- if (ret == MBEDTLS_ERR_SSL_INVALID_MAC) {
- MBEDTLS_SSL_DEBUG_MSG(3, ("ticket is not authentic"));
- } else if (ret == MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED) {
+ ret = ssl->conf->f_ticket_parse(ssl->conf->p_ticket,
+ session,
+ ticket_buffer, identity_len);
+ switch (ret) {
+ case 0:
+ ret = SSL_TLS1_3_PSK_IDENTITY_MATCH;
+ break;
+
+ case MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED:
MBEDTLS_SSL_DEBUG_MSG(3, ("ticket is expired"));
- } else {
+ ret = SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE;
+ break;
+
+ case MBEDTLS_ERR_SSL_INVALID_MAC:
+ MBEDTLS_SSL_DEBUG_MSG(3, ("ticket is not authentic"));
+ ret = SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH;
+ break;
+
+ default:
MBEDTLS_SSL_DEBUG_RET(1, "ticket_parse", ret);
- }
+ ret = SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH;
}
/* We delete the temporary buffer */
mbedtls_free(ticket_buffer);
- if (ret == 0 && session->tls_version != MBEDTLS_SSL_VERSION_TLS1_3) {
- MBEDTLS_SSL_DEBUG_MSG(3, ("Ticket TLS version is not 1.3."));
- /* TODO: Define new return value for this case. */
- ret = MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION;
- }
-
- if (ret != 0) {
+ if (ret != SSL_TLS1_3_PSK_IDENTITY_MATCH) {
goto exit;
}
- /* RFC 8446 section 4.2.9
- *
- * Servers SHOULD NOT send NewSessionTicket with tickets that are not
- * compatible with the advertised modes; however, if a server does so,
- * the impact will just be that the client's attempts at resumption fail.
- *
- * We regard the ticket with incompatible key exchange modes as not match.
+ /*
+ * The identity matches that of a ticket. Now check that it has suitable
+ * attributes and bet it will not be the case.
*/
- ret = MBEDTLS_ERR_ERROR_GENERIC_ERROR;
- MBEDTLS_SSL_PRINT_TICKET_FLAGS(4, session->ticket_flags);
+ ret = SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE;
- key_exchanges = 0;
- if (mbedtls_ssl_tls13_session_ticket_allow_psk_ephemeral(session) &&
- ssl_tls13_key_exchange_is_psk_ephemeral_available(ssl)) {
- key_exchanges |= MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL;
- }
- if (mbedtls_ssl_tls13_session_ticket_allow_psk(session) &&
- ssl_tls13_key_exchange_is_psk_available(ssl)) {
- key_exchanges |= MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK;
- }
-
- if (key_exchanges == 0) {
- MBEDTLS_SSL_DEBUG_MSG(3, ("No suitable key exchange mode"));
+ if (session->tls_version != MBEDTLS_SSL_VERSION_TLS1_3) {
+ MBEDTLS_SSL_DEBUG_MSG(3, ("Ticket TLS version is not 1.3."));
goto exit;
}
- ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
#if defined(MBEDTLS_HAVE_TIME)
now = mbedtls_ms_time();
@@ -242,13 +308,15 @@
age_diff));
goto exit;
}
-
- ret = 0;
-
#endif /* MBEDTLS_HAVE_TIME */
+ /*
+ * All good, we have found a suitable ticket.
+ */
+ ret = SSL_TLS1_3_PSK_IDENTITY_MATCH;
+
exit:
- if (ret != 0) {
+ if (ret != SSL_TLS1_3_PSK_IDENTITY_MATCH) {
mbedtls_ssl_session_free(session);
}
@@ -273,13 +341,11 @@
*psk_type = MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL;
MBEDTLS_SSL_DEBUG_BUF(4, "identity", identity, identity_len);
- ssl->handshake->resume = 0;
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
- if (ssl_tls13_offered_psks_check_identity_match_ticket(
- ssl, identity, identity_len, obfuscated_ticket_age,
- session) == SSL_TLS1_3_OFFERED_PSK_MATCH) {
- ssl->handshake->resume = 1;
+ ret = ssl_tls13_offered_psks_check_identity_match_ticket(
+ ssl, identity, identity_len, obfuscated_ticket_age, session);
+ if (ret == SSL_TLS1_3_PSK_IDENTITY_MATCH) {
*psk_type = MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION;
ret = mbedtls_ssl_set_hs_psk(ssl,
session->resumption_key,
@@ -294,7 +360,9 @@
session->resumption_key_len);
MBEDTLS_SSL_DEBUG_MSG(4, ("ticket: obfuscated_ticket_age: %u",
(unsigned) obfuscated_ticket_age));
- return SSL_TLS1_3_OFFERED_PSK_MATCH;
+ return SSL_TLS1_3_PSK_IDENTITY_MATCH;
+ } else if (ret == SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE) {
+ return SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE;
}
#endif /* MBEDTLS_SSL_SESSION_TICKETS */
@@ -302,9 +370,9 @@
if (ssl->conf->f_psk != NULL) {
if (ssl->conf->f_psk(
ssl->conf->p_psk, ssl, identity, identity_len) == 0) {
- return SSL_TLS1_3_OFFERED_PSK_MATCH;
+ return SSL_TLS1_3_PSK_IDENTITY_MATCH;
}
- return SSL_TLS1_3_OFFERED_PSK_NOT_MATCH;
+ return SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH;
}
MBEDTLS_SSL_DEBUG_BUF(5, "identity", identity, identity_len);
@@ -318,12 +386,20 @@
MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_set_hs_psk", ret);
return ret;
}
- return SSL_TLS1_3_OFFERED_PSK_MATCH;
+ return SSL_TLS1_3_PSK_IDENTITY_MATCH;
}
- return SSL_TLS1_3_OFFERED_PSK_NOT_MATCH;
+ return SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH;
}
+/*
+ * Non-error return values of ssl_tls13_offered_psks_check_binder_match().
+ * They are positive to not collide with error codes that are negative. Zero
+ * (SSL_TLS1_3_BINDER_MATCH) in case of success as it may be propagated up
+ * by the callers of this function as a generic success condition.
+ */
+#define SSL_TLS1_3_BINDER_DOES_NOT_MATCH 1
+#define SSL_TLS1_3_BINDER_MATCH 0
MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls13_offered_psks_check_binder_match(
mbedtls_ssl_context *ssl,
@@ -368,100 +444,16 @@
MBEDTLS_SSL_DEBUG_BUF(3, "psk binder ( received ): ", binder, binder_len);
if (mbedtls_ct_memcmp(server_computed_binder, binder, binder_len) == 0) {
- return SSL_TLS1_3_OFFERED_PSK_MATCH;
+ return SSL_TLS1_3_BINDER_MATCH;
}
mbedtls_platform_zeroize(server_computed_binder,
sizeof(server_computed_binder));
- return SSL_TLS1_3_OFFERED_PSK_NOT_MATCH;
-}
-
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_tls13_select_ciphersuite_for_psk(
- mbedtls_ssl_context *ssl,
- const unsigned char *cipher_suites,
- const unsigned char *cipher_suites_end,
- uint16_t *selected_ciphersuite,
- const mbedtls_ssl_ciphersuite_t **selected_ciphersuite_info)
-{
- psa_algorithm_t psk_hash_alg = PSA_ALG_SHA_256;
-
- *selected_ciphersuite = 0;
- *selected_ciphersuite_info = NULL;
-
- /* RFC 8446, page 55.
- *
- * For externally established PSKs, the Hash algorithm MUST be set when the
- * PSK is established or default to SHA-256 if no such algorithm is defined.
- *
- */
-
- /*
- * Search for a matching ciphersuite
- */
- for (const unsigned char *p = cipher_suites;
- p < cipher_suites_end; p += 2) {
- uint16_t cipher_suite;
- const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
-
- cipher_suite = MBEDTLS_GET_UINT16_BE(p, 0);
- ciphersuite_info = ssl_tls13_validate_peer_ciphersuite(ssl,
- cipher_suite);
- if (ciphersuite_info == NULL) {
- continue;
- }
-
- /* MAC of selected ciphersuite MUST be same with PSK binder if exist.
- * Otherwise, client should reject.
- */
- if (psk_hash_alg ==
- mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac)) {
- *selected_ciphersuite = cipher_suite;
- *selected_ciphersuite_info = ciphersuite_info;
- return 0;
- }
- }
- MBEDTLS_SSL_DEBUG_MSG(2, ("No matched ciphersuite"));
- return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+ return SSL_TLS1_3_BINDER_DOES_NOT_MATCH;
}
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_tls13_select_ciphersuite_for_resumption(
- mbedtls_ssl_context *ssl,
- const unsigned char *cipher_suites,
- const unsigned char *cipher_suites_end,
- mbedtls_ssl_session *session,
- uint16_t *selected_ciphersuite,
- const mbedtls_ssl_ciphersuite_t **selected_ciphersuite_info)
-{
-
- *selected_ciphersuite = 0;
- *selected_ciphersuite_info = NULL;
- for (const unsigned char *p = cipher_suites; p < cipher_suites_end; p += 2) {
- uint16_t cipher_suite = MBEDTLS_GET_UINT16_BE(p, 0);
- const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
-
- if (cipher_suite != session->ciphersuite) {
- continue;
- }
-
- ciphersuite_info = ssl_tls13_validate_peer_ciphersuite(ssl,
- cipher_suite);
- if (ciphersuite_info == NULL) {
- continue;
- }
-
- *selected_ciphersuite = cipher_suite;
- *selected_ciphersuite_info = ciphersuite_info;
-
- return 0;
- }
-
- return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
-}
-
-MBEDTLS_CHECK_RETURN_CRITICAL
static int ssl_tls13_session_copy_ticket(mbedtls_ssl_session *dst,
const mbedtls_ssl_session *src)
{
@@ -481,6 +473,13 @@
}
#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+struct psk_attributes {
+ int type;
+ int key_exchange_mode;
+ const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
+};
+#define PSK_ATTRIBUTES_INIT { 0, 0, NULL }
+
/* Parser for pre_shared_key extension in client hello
* struct {
* opaque identity<1..2^16-1>;
@@ -507,7 +506,8 @@
const unsigned char *pre_shared_key_ext,
const unsigned char *pre_shared_key_ext_end,
const unsigned char *ciphersuites,
- const unsigned char *ciphersuites_end)
+ const unsigned char *ciphersuites_end,
+ struct psk_attributes *psk)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const unsigned char *identities = pre_shared_key_ext;
@@ -558,9 +558,10 @@
uint32_t obfuscated_ticket_age;
const unsigned char *binder;
size_t binder_len;
- int psk_type;
- uint16_t cipher_suite;
- const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
+ int psk_ciphersuite_id;
+ psa_algorithm_t psk_hash_alg;
+ int allowed_key_exchange_modes;
+
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
mbedtls_ssl_session session;
mbedtls_ssl_session_init(&session);
@@ -586,47 +587,74 @@
ret = ssl_tls13_offered_psks_check_identity_match(
ssl, identity, identity_len, obfuscated_ticket_age,
- &psk_type, &session);
- if (ret != SSL_TLS1_3_OFFERED_PSK_MATCH) {
+ &psk->type, &session);
+ if (ret != SSL_TLS1_3_PSK_IDENTITY_MATCH) {
continue;
}
MBEDTLS_SSL_DEBUG_MSG(4, ("found matched identity"));
- switch (psk_type) {
+
+ switch (psk->type) {
case MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL:
- ret = ssl_tls13_select_ciphersuite_for_psk(
- ssl, ciphersuites, ciphersuites_end,
- &cipher_suite, &ciphersuite_info);
+ psk_ciphersuite_id = 0;
+ psk_hash_alg = PSA_ALG_SHA_256;
+ allowed_key_exchange_modes =
+ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL;
break;
- case MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION:
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
- ret = ssl_tls13_select_ciphersuite_for_resumption(
- ssl, ciphersuites, ciphersuites_end, &session,
- &cipher_suite, &ciphersuite_info);
- if (ret != 0) {
- mbedtls_ssl_session_free(&session);
- }
-#else
- ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
-#endif
+ case MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION:
+ psk_ciphersuite_id = session.ciphersuite;
+ psk_hash_alg = PSA_ALG_NONE;
+ ssl->session_negotiate->ticket_flags = session.ticket_flags;
+ allowed_key_exchange_modes =
+ session.ticket_flags &
+ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL;
break;
+#endif
default:
return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
}
- if (ret != 0) {
- /* See below, no cipher_suite available, abort handshake */
+
+ psk->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_NONE;
+
+ if ((allowed_key_exchange_modes &
+ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL) &&
+ ssl_tls13_key_exchange_is_psk_ephemeral_available(ssl)) {
+ psk->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL;
+ } else if ((allowed_key_exchange_modes &
+ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK) &&
+ ssl_tls13_key_exchange_is_psk_available(ssl)) {
+ psk->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK;
+ }
+
+ if (psk->key_exchange_mode == MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_NONE) {
+ MBEDTLS_SSL_DEBUG_MSG(3, ("No suitable PSK key exchange mode"));
+ continue;
+ }
+
+ ssl_tls13_select_ciphersuite(ssl, ciphersuites, ciphersuites_end,
+ psk_ciphersuite_id, psk_hash_alg,
+ &psk->ciphersuite_info);
+
+ if (psk->ciphersuite_info == NULL) {
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+ mbedtls_ssl_session_free(&session);
+#endif
+ /*
+ * We consider finding a ciphersuite suitable for the PSK as part
+ * of the validation of its binder. Thus if we do not find one, we
+ * abort the handshake with a decrypt_error alert.
+ */
MBEDTLS_SSL_PEND_FATAL_ALERT(
MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR,
MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);
- MBEDTLS_SSL_DEBUG_RET(
- 2, "ssl_tls13_select_ciphersuite", ret);
- return ret;
+ return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
}
ret = ssl_tls13_offered_psks_check_binder_match(
- ssl, binder, binder_len, psk_type,
- mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac));
- if (ret != SSL_TLS1_3_OFFERED_PSK_MATCH) {
+ ssl, binder, binder_len, psk->type,
+ mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) psk->ciphersuite_info->mac));
+ if (ret != SSL_TLS1_3_BINDER_MATCH) {
/* For security reasons, the handshake should be aborted when we
* fail to validate a binder value. See RFC 8446 section 4.2.11.2
* and appendix E.6. */
@@ -644,13 +672,8 @@
matched_identity = identity_id;
- /* Update handshake parameters */
- ssl->handshake->ciphersuite_info = ciphersuite_info;
- ssl->session_negotiate->ciphersuite = cipher_suite;
- MBEDTLS_SSL_DEBUG_MSG(2, ("overwrite ciphersuite: %04x - %s",
- cipher_suite, ciphersuite_info->name));
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
- if (psk_type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION) {
+ if (psk->type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION) {
ret = ssl_tls13_session_copy_ticket(ssl->session_negotiate,
&session);
mbedtls_ssl_session_free(&session);
@@ -676,7 +699,7 @@
return ret;
}
if (matched_identity == -1) {
- MBEDTLS_SSL_DEBUG_MSG(3, ("No matched PSK or ticket."));
+ MBEDTLS_SSL_DEBUG_MSG(3, ("No usable PSK or ticket."));
return MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY;
}
@@ -1003,21 +1026,29 @@
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_tls13_ticket_is_kex_mode_permitted(mbedtls_ssl_context *ssl,
- unsigned int kex_mode)
+static int ssl_tls13_key_exchange_is_psk_available(mbedtls_ssl_context *ssl)
{
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
- if (ssl->handshake->resume) {
- if (!mbedtls_ssl_tls13_session_ticket_has_flags(
- ssl->session_negotiate, kex_mode)) {
- return 0;
- }
- }
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED)
+ return mbedtls_ssl_conf_tls13_is_psk_enabled(ssl) &&
+ mbedtls_ssl_tls13_is_psk_supported(ssl) &&
+ ssl_tls13_client_hello_has_exts_for_psk_key_exchange(ssl);
#else
((void) ssl);
- ((void) kex_mode);
+ return 0;
#endif
- return 1;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_key_exchange_is_psk_ephemeral_available(mbedtls_ssl_context *ssl)
+{
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED)
+ return mbedtls_ssl_conf_tls13_is_psk_ephemeral_enabled(ssl) &&
+ mbedtls_ssl_tls13_is_psk_ephemeral_supported(ssl) &&
+ ssl_tls13_client_hello_has_exts_for_psk_ephemeral_key_exchange(ssl);
+#else
+ ((void) ssl);
+ return 0;
+#endif
}
#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */
@@ -1033,83 +1064,6 @@
#endif
}
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_tls13_key_exchange_is_psk_available(mbedtls_ssl_context *ssl)
-{
-#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED)
- return ssl_tls13_ticket_is_kex_mode_permitted(
- ssl, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK) &&
- mbedtls_ssl_conf_tls13_is_psk_enabled(ssl) &&
- mbedtls_ssl_tls13_is_psk_supported(ssl) &&
- ssl_tls13_client_hello_has_exts_for_psk_key_exchange(ssl);
-#else
- ((void) ssl);
- return 0;
-#endif
-}
-
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_tls13_key_exchange_is_psk_ephemeral_available(mbedtls_ssl_context *ssl)
-{
-#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED)
- return ssl_tls13_ticket_is_kex_mode_permitted(
- ssl, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL) &&
- mbedtls_ssl_conf_tls13_is_psk_ephemeral_enabled(ssl) &&
- mbedtls_ssl_tls13_is_psk_ephemeral_supported(ssl) &&
- ssl_tls13_client_hello_has_exts_for_psk_ephemeral_key_exchange(ssl);
-#else
- ((void) ssl);
- return 0;
-#endif
-}
-
-static int ssl_tls13_determine_key_exchange_mode(mbedtls_ssl_context *ssl)
-{
- /*
- * Determine the key exchange algorithm to use.
- * There are three types of key exchanges supported in TLS 1.3:
- * - (EC)DH with ECDSA,
- * - (EC)DH with PSK,
- * - plain PSK.
- *
- * The PSK-based key exchanges may additionally be used with 0-RTT.
- *
- * Our built-in order of preference is
- * 1 ) (EC)DHE-PSK Mode ( psk_ephemeral )
- * 2 ) Certificate Mode ( ephemeral )
- * 3 ) Plain PSK Mode ( psk )
- */
-
- ssl->handshake->key_exchange_mode =
- MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_NONE;
-
- if (ssl_tls13_key_exchange_is_psk_ephemeral_available(ssl)) {
- ssl->handshake->key_exchange_mode =
- MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL;
- MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: psk_ephemeral"));
- } else
- if (ssl_tls13_key_exchange_is_ephemeral_available(ssl)) {
- ssl->handshake->key_exchange_mode =
- MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL;
- MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: ephemeral"));
- } else
- if (ssl_tls13_key_exchange_is_psk_available(ssl)) {
- ssl->handshake->key_exchange_mode =
- MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK;
- MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: psk"));
- } else {
- MBEDTLS_SSL_DEBUG_MSG(
- 1,
- ("ClientHello message misses mandatory extensions."));
- MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_MISSING_EXTENSION,
- MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
- return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
- }
-
- return 0;
-
-}
-
#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
@@ -1301,6 +1255,8 @@
int no_usable_share_for_key_agreement = 0;
#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+ int got_psk = 0;
+ struct psk_attributes psk = PSK_ATTRIBUTES_INIT;
const unsigned char *pre_shared_key_ext = NULL;
const unsigned char *pre_shared_key_ext_end = NULL;
#endif
@@ -1437,12 +1393,8 @@
* We negotiate TLS 1.3.
*/
ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_3;
-
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
- /* Store minor version for later use with ticket serialization. */
ssl->session_negotiate->tls_version = MBEDTLS_SSL_VERSION_TLS1_3;
ssl->session_negotiate->endpoint = ssl->conf->endpoint;
-#endif
/*
* We are negotiating the version 1.3 of the protocol. Do what we have
@@ -1468,37 +1420,20 @@
*/
MBEDTLS_SSL_DEBUG_BUF(3, "client hello, list of cipher suites",
cipher_suites, cipher_suites_len);
- for (const unsigned char *cipher_suites_p = cipher_suites;
- cipher_suites_p < cipher_suites_end; cipher_suites_p += 2) {
- uint16_t cipher_suite;
- const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
- /*
- * "cipher_suites_end - cipher_suites_p is even" is an invariant of the
- * loop. As cipher_suites_end - cipher_suites_p > 0, we have
- * cipher_suites_end - cipher_suites_p >= 2 and it is thus safe to read
- * two bytes.
- */
- cipher_suite = MBEDTLS_GET_UINT16_BE(cipher_suites_p, 0);
- ciphersuite_info = ssl_tls13_validate_peer_ciphersuite(
- ssl, cipher_suite);
- if (ciphersuite_info == NULL) {
- continue;
- }
-
- ssl->session_negotiate->ciphersuite = cipher_suite;
- handshake->ciphersuite_info = ciphersuite_info;
- MBEDTLS_SSL_DEBUG_MSG(2, ("selected ciphersuite: %04x - %s",
- cipher_suite,
- ciphersuite_info->name));
- break;
- }
+ ssl_tls13_select_ciphersuite(ssl, cipher_suites, cipher_suites_end,
+ 0, PSA_ALG_NONE, &handshake->ciphersuite_info);
if (handshake->ciphersuite_info == NULL) {
MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,
MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);
return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
}
+ ssl->session_negotiate->ciphersuite = handshake->ciphersuite_info->id;
+
+ MBEDTLS_SSL_DEBUG_MSG(2, ("selected ciphersuite: %04x - %s",
+ ((unsigned) handshake->ciphersuite_info->id),
+ handshake->ciphersuite_info->name));
/* ...
* opaque legacy_compression_methods<1..2^8-1>;
@@ -1533,6 +1468,12 @@
unsigned int extension_type;
size_t extension_data_len;
const unsigned char *extension_data_end;
+ uint32_t allowed_exts = MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CH;
+
+ if (ssl->handshake->hello_retry_request_flag) {
+ /* Do not accept early data extension in 2nd ClientHello */
+ allowed_exts &= ~MBEDTLS_SSL_EXT_MASK(EARLY_DATA);
+ }
/* RFC 8446, section 4.2.11
*
@@ -1560,7 +1501,7 @@
ret = mbedtls_ssl_tls13_check_received_extension(
ssl, MBEDTLS_SSL_HS_CLIENT_HELLO, extension_type,
- MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CH);
+ allowed_exts);
if (ret != 0) {
return ret;
}
@@ -1732,10 +1673,11 @@
/* Update checksum with either
* - The entire content of the CH message, if no PSK extension is present
* - The content up to but excluding the PSK extension, if present.
+ * Always parse the pre-shared-key extension when present in the
+ * ClientHello even if some pre-requisites for PSK key exchange modes are
+ * not met. That way we always validate the syntax of the extension.
*/
- /* If we've settled on a PSK-based exchange, parse PSK identity ext */
- if (ssl_tls13_key_exchange_is_psk_available(ssl) ||
- ssl_tls13_key_exchange_is_psk_ephemeral_available(ssl)) {
+ if (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY)) {
ret = handshake->update_checksum(ssl, buf,
pre_shared_key_ext - buf);
if (0 != ret) {
@@ -1746,10 +1688,11 @@
pre_shared_key_ext,
pre_shared_key_ext_end,
cipher_suites,
- cipher_suites_end);
- if (ret == MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY) {
- handshake->received_extensions &= ~MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY);
- } else if (ret != 0) {
+ cipher_suites_end,
+ &psk);
+ if (ret == 0) {
+ got_psk = 1;
+ } else if (ret != MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY) {
MBEDTLS_SSL_DEBUG_RET(
1, "ssl_tls13_parse_pre_shared_key_ext", ret);
return ret;
@@ -1764,12 +1707,68 @@
}
}
- ret = ssl_tls13_determine_key_exchange_mode(ssl);
- if (ret < 0) {
- return ret;
+ /*
+ * Determine the key exchange algorithm to use.
+ * There are three types of key exchanges supported in TLS 1.3:
+ * - (EC)DH with ECDSA,
+ * - (EC)DH with PSK,
+ * - plain PSK.
+ *
+ * The PSK-based key exchanges may additionally be used with 0-RTT.
+ *
+ * Our built-in order of preference is
+ * 1 ) (EC)DHE-PSK Mode ( psk_ephemeral )
+ * 2 ) Certificate Mode ( ephemeral )
+ * 3 ) Plain PSK Mode ( psk )
+ */
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+ if (got_psk && (psk.key_exchange_mode ==
+ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL)) {
+ handshake->key_exchange_mode =
+ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL;
+ MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: psk_ephemeral"));
+
+ } else
+#endif
+ if (ssl_tls13_key_exchange_is_ephemeral_available(ssl)) {
+ handshake->key_exchange_mode =
+ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL;
+ MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: ephemeral"));
+
+ }
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+ else if (got_psk && (psk.key_exchange_mode ==
+ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK)) {
+ handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK;
+ MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: psk"));
+ }
+#endif
+ else {
+ MBEDTLS_SSL_DEBUG_MSG(
+ 1,
+ ("ClientHello message misses mandatory extensions."));
+ MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_MISSING_EXTENSION,
+ MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
+ return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
}
- if (ssl->handshake->key_exchange_mode !=
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+ if (handshake->key_exchange_mode &
+ MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL) {
+ handshake->ciphersuite_info = psk.ciphersuite_info;
+ ssl->session_negotiate->ciphersuite = psk.ciphersuite_info->id;
+
+ MBEDTLS_SSL_DEBUG_MSG(2, ("Select PSK ciphersuite: %04x - %s",
+ ((unsigned) psk.ciphersuite_info->id),
+ psk.ciphersuite_info->name));
+
+ if (psk.type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION) {
+ handshake->resume = 1;
+ }
+ }
+#endif
+
+ if (handshake->key_exchange_mode !=
MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK) {
hrr_required = (no_usable_share_for_key_agreement != 0);
}
@@ -1780,25 +1779,15 @@
}
#if defined(MBEDTLS_SSL_EARLY_DATA)
-static void ssl_tls13_update_early_data_status(mbedtls_ssl_context *ssl)
+static int ssl_tls13_check_early_data_requirements(mbedtls_ssl_context *ssl)
{
mbedtls_ssl_handshake_params *handshake = ssl->handshake;
- if ((handshake->received_extensions &
- MBEDTLS_SSL_EXT_MASK(EARLY_DATA)) == 0) {
- MBEDTLS_SSL_DEBUG_MSG(
- 1, ("EarlyData: no early data extension received."));
- ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_RECEIVED;
- return;
- }
-
- ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED;
-
if (ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_DISABLED) {
MBEDTLS_SSL_DEBUG_MSG(
1,
("EarlyData: rejected, feature disabled in server configuration."));
- return;
+ return -1;
}
if (!handshake->resume) {
@@ -1807,7 +1796,7 @@
resumption. */
MBEDTLS_SSL_DEBUG_MSG(
1, ("EarlyData: rejected, not a session resumption."));
- return;
+ return -1;
}
/* RFC 8446 4.2.10
@@ -1830,7 +1819,7 @@
MBEDTLS_SSL_DEBUG_MSG(
1, ("EarlyData: rejected, the selected key in "
"`pre_shared_key` is not the first one."));
- return;
+ return -1;
}
if (handshake->ciphersuite_info->id !=
@@ -1838,7 +1827,7 @@
MBEDTLS_SSL_DEBUG_MSG(
1, ("EarlyData: rejected, the selected ciphersuite is not the one "
"of the selected pre-shared key."));
- return;
+ return -1;
}
@@ -1847,18 +1836,18 @@
1,
("EarlyData: rejected, early_data not allowed in ticket "
"permission bits."));
- return;
+ return -1;
}
- ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED;
-
+ return 0;
}
#endif /* MBEDTLS_SSL_EARLY_DATA */
/* Update the handshake state machine */
MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_tls13_postprocess_client_hello(mbedtls_ssl_context *ssl)
+static int ssl_tls13_postprocess_client_hello(mbedtls_ssl_context *ssl,
+ int hrr_required)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -1882,17 +1871,26 @@
}
#if defined(MBEDTLS_SSL_EARLY_DATA)
- /* There is enough information, update early data state. */
- ssl_tls13_update_early_data_status(ssl);
+ if (ssl->handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(EARLY_DATA)) {
+ ssl->handshake->early_data_accepted =
+ (!hrr_required) && (ssl_tls13_check_early_data_requirements(ssl) == 0);
- if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED) {
- ret = mbedtls_ssl_tls13_compute_early_transform(ssl);
- if (ret != 0) {
- MBEDTLS_SSL_DEBUG_RET(
- 1, "mbedtls_ssl_tls13_compute_early_transform", ret);
- return ret;
+ if (ssl->handshake->early_data_accepted) {
+ ret = mbedtls_ssl_tls13_compute_early_transform(ssl);
+ if (ret != 0) {
+ MBEDTLS_SSL_DEBUG_RET(
+ 1, "mbedtls_ssl_tls13_compute_early_transform", ret);
+ return ret;
+ }
+ } else {
+ ssl->discard_early_data_record =
+ hrr_required ?
+ MBEDTLS_SSL_EARLY_DATA_DISCARD :
+ MBEDTLS_SSL_EARLY_DATA_TRY_TO_DEPROTECT_AND_DISCARD;
}
}
+#else
+ ((void) hrr_required);
#endif /* MBEDTLS_SSL_EARLY_DATA */
return 0;
@@ -1947,7 +1945,9 @@
return 0;
}
- MBEDTLS_SSL_PROC_CHK(ssl_tls13_postprocess_client_hello(ssl));
+ MBEDTLS_SSL_PROC_CHK(
+ ssl_tls13_postprocess_client_hello(ssl, parse_client_hello_ret ==
+ SSL_CLIENT_HELLO_HRR_REQUIRED));
if (SSL_CLIENT_HELLO_OK == parse_client_hello_ret) {
mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_HELLO);
@@ -1970,10 +1970,6 @@
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *server_randbytes =
ssl->handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN;
- if (ssl->conf->f_rng == NULL) {
- MBEDTLS_SSL_DEBUG_MSG(1, ("no RNG provided"));
- return MBEDTLS_ERR_SSL_NO_RNG;
- }
if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, server_randbytes,
MBEDTLS_SERVER_HELLO_RANDOM_LEN)) != 0) {
@@ -2424,7 +2420,7 @@
static int ssl_tls13_prepare_hello_retry_request(mbedtls_ssl_context *ssl)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- if (ssl->handshake->hello_retry_request_count > 0) {
+ if (ssl->handshake->hello_retry_request_flag) {
MBEDTLS_SSL_DEBUG_MSG(1, ("Too many HRRs"));
MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,
MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);
@@ -2471,7 +2467,7 @@
MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(ssl, buf_len,
msg_len));
- ssl->handshake->hello_retry_request_count++;
+ ssl->handshake->hello_retry_request_flag = 1;
#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
/* The server sends a dummy change_cipher_spec record immediately
@@ -2530,7 +2526,7 @@
#endif /* MBEDTLS_SSL_ALPN */
#if defined(MBEDTLS_SSL_EARLY_DATA)
- if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED) {
+ if (ssl->handshake->early_data_accepted) {
ret = mbedtls_ssl_tls13_write_early_data_ext(
ssl, 0, p, end, &output_len);
if (ret != 0) {
@@ -2857,7 +2853,7 @@
}
#if defined(MBEDTLS_SSL_EARLY_DATA)
- if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED) {
+ if (ssl->handshake->early_data_accepted) {
/* See RFC 8446 section A.2 for more information */
MBEDTLS_SSL_DEBUG_MSG(
1, ("Switch to early keys for inbound traffic. "
@@ -2910,7 +2906,15 @@
}
if (ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA) {
- MBEDTLS_SSL_DEBUG_MSG(3, ("Received early data"));
+ if (ssl->in_offt == NULL) {
+ MBEDTLS_SSL_DEBUG_MSG(3, ("Received early data"));
+ /* Set the reading pointer */
+ ssl->in_offt = ssl->in_msg;
+ ret = mbedtls_ssl_tls13_check_early_data_len(ssl, ssl->in_msglen);
+ if (ret != 0) {
+ return ret;
+ }
+ }
return SSL_GOT_EARLY_DATA;
}
@@ -2936,37 +2940,6 @@
return 0;
}
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_tls13_process_early_application_data(mbedtls_ssl_context *ssl)
-{
- int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-
- if ((ret = mbedtls_ssl_read_record(ssl, 0)) != 0) {
- MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret);
- return ret;
- }
-
- /*
- * Output early data
- *
- * For the time being, we print received data via debug message.
- *
- * TODO: Remove it when `mbedtls_ssl_read_early_data` is ready.
- */
- ssl->in_msg[ssl->in_msglen] = 0;
- MBEDTLS_SSL_DEBUG_MSG(3, ("\n%s", ssl->in_msg));
-
- /* RFC 8446 section 4.6.1
- *
- * A server receiving more than max_early_data_size bytes of 0-RTT data
- * SHOULD terminate the connection with an "unexpected_message" alert.
- *
- * TODO: Add received data size check here.
- */
-
- return 0;
-}
-
/*
* RFC 8446 section A.2
*
@@ -3037,7 +3010,8 @@
ssl_tls13_prepare_for_handshake_second_flight(ssl);
} else if (ret == SSL_GOT_EARLY_DATA) {
- MBEDTLS_SSL_PROC_CHK(ssl_tls13_process_early_application_data(ssl));
+ ret = MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA;
+ goto cleanup;
} else {
MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
@@ -3144,10 +3118,6 @@
MBEDTLS_SSL_DEBUG_MSG(2, ("=> prepare NewSessionTicket msg"));
-#if defined(MBEDTLS_HAVE_TIME)
- session->ticket_creation_time = mbedtls_ms_time();
-#endif
-
/* Set ticket_flags depends on the advertised psk key exchange mode */
mbedtls_ssl_tls13_session_clear_ticket_flags(
session, MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK);
@@ -3161,6 +3131,7 @@
ssl->conf->max_early_data_size > 0) {
mbedtls_ssl_tls13_session_set_ticket_flags(
session, MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA);
+ session->max_early_data_size = ssl->conf->max_early_data_size;
}
#endif /* MBEDTLS_SSL_EARLY_DATA */
@@ -3282,6 +3253,9 @@
MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4 + 4 + 1 + ticket_nonce_size + 2);
/* Generate ticket and ticket_lifetime */
+#if defined(MBEDTLS_HAVE_TIME)
+ session->ticket_creation_time = mbedtls_ms_time();
+#endif
ret = ssl->conf->f_ticket_write(ssl->conf->p_ticket,
session,
p + 9 + ticket_nonce_size + 2,
@@ -3495,9 +3469,10 @@
case MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO:
ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl);
- if (ret == 0) {
- mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS);
+ if (ret != 0) {
+ break;
}
+ mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS);
break;
#endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */
diff --git a/library/x509.c b/library/x509.c
index b7b71f3..f97fb44 100644
--- a/library/x509.c
+++ b/library/x509.c
@@ -19,7 +19,7 @@
#if defined(MBEDTLS_X509_USE_C)
-#include "mbedtls/x509.h"
+#include "x509_internal.h"
#include "mbedtls/asn1.h"
#include "mbedtls/error.h"
#include "mbedtls/oid.h"
diff --git a/library/x509_create.c b/library/x509_create.c
index f7a17e7..839b5df 100644
--- a/library/x509_create.c
+++ b/library/x509_create.c
@@ -9,7 +9,7 @@
#if defined(MBEDTLS_X509_CREATE_C)
-#include "mbedtls/x509.h"
+#include "x509_internal.h"
#include "mbedtls/asn1write.h"
#include "mbedtls/error.h"
#include "mbedtls/oid.h"
diff --git a/library/x509_crl.c b/library/x509_crl.c
index fdbad23..7901992 100644
--- a/library/x509_crl.c
+++ b/library/x509_crl.c
@@ -20,6 +20,7 @@
#if defined(MBEDTLS_X509_CRL_PARSE_C)
#include "mbedtls/x509_crl.h"
+#include "x509_internal.h"
#include "mbedtls/error.h"
#include "mbedtls/oid.h"
#include "mbedtls/platform_util.h"
diff --git a/library/x509_crt.c b/library/x509_crt.c
index 84b92a8..2fd56fb 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -22,6 +22,7 @@
#if defined(MBEDTLS_X509_CRT_PARSE_C)
#include "mbedtls/x509_crt.h"
+#include "x509_internal.h"
#include "mbedtls/error.h"
#include "mbedtls/oid.h"
#include "mbedtls/platform_util.h"
@@ -3289,4 +3290,12 @@
}
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+int mbedtls_x509_crt_get_ca_istrue(const mbedtls_x509_crt *crt)
+{
+ if ((crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS) != 0) {
+ return crt->MBEDTLS_PRIVATE(ca_istrue);
+ }
+ return MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
+}
+
#endif /* MBEDTLS_X509_CRT_PARSE_C */
diff --git a/library/x509_csr.c b/library/x509_csr.c
index 79b1589..813d644 100644
--- a/library/x509_csr.c
+++ b/library/x509_csr.c
@@ -20,6 +20,7 @@
#if defined(MBEDTLS_X509_CSR_PARSE_C)
#include "mbedtls/x509_csr.h"
+#include "x509_internal.h"
#include "mbedtls/error.h"
#include "mbedtls/oid.h"
#include "mbedtls/platform_util.h"
diff --git a/library/x509_internal.h b/library/x509_internal.h
new file mode 100644
index 0000000..8a2d2ed
--- /dev/null
+++ b/library/x509_internal.h
@@ -0,0 +1,86 @@
+/**
+ * \file x509.h
+ *
+ * \brief Internal part of the public "x509.h".
+ */
+/*
+ * Copyright The Mbed TLS Contributors
+ * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+#ifndef MBEDTLS_X509_INTERNAL_H
+#define MBEDTLS_X509_INTERNAL_H
+#include "mbedtls/private_access.h"
+
+#include "mbedtls/build_info.h"
+
+#include "mbedtls/x509.h"
+#include "mbedtls/asn1.h"
+#include "pk_internal.h"
+
+#if defined(MBEDTLS_RSA_C)
+#include "mbedtls/rsa.h"
+#endif
+
+int mbedtls_x509_get_name(unsigned char **p, const unsigned char *end,
+ mbedtls_x509_name *cur);
+int mbedtls_x509_get_alg_null(unsigned char **p, const unsigned char *end,
+ mbedtls_x509_buf *alg);
+int mbedtls_x509_get_alg(unsigned char **p, const unsigned char *end,
+ mbedtls_x509_buf *alg, mbedtls_x509_buf *params);
+#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
+int mbedtls_x509_get_rsassa_pss_params(const mbedtls_x509_buf *params,
+ mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md,
+ int *salt_len);
+#endif
+int mbedtls_x509_get_sig(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig);
+int mbedtls_x509_get_sig_alg(const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params,
+ mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg,
+ void **sig_opts);
+int mbedtls_x509_get_time(unsigned char **p, const unsigned char *end,
+ mbedtls_x509_time *t);
+int mbedtls_x509_get_serial(unsigned char **p, const unsigned char *end,
+ mbedtls_x509_buf *serial);
+int mbedtls_x509_get_ext(unsigned char **p, const unsigned char *end,
+ mbedtls_x509_buf *ext, int tag);
+#if !defined(MBEDTLS_X509_REMOVE_INFO)
+int mbedtls_x509_sig_alg_gets(char *buf, size_t size, const mbedtls_x509_buf *sig_oid,
+ mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg,
+ const void *sig_opts);
+#endif
+int mbedtls_x509_key_size_helper(char *buf, size_t buf_size, const char *name);
+int mbedtls_x509_set_extension(mbedtls_asn1_named_data **head, const char *oid, size_t oid_len,
+ int critical, const unsigned char *val,
+ size_t val_len);
+int mbedtls_x509_write_extensions(unsigned char **p, unsigned char *start,
+ mbedtls_asn1_named_data *first);
+int mbedtls_x509_write_names(unsigned char **p, unsigned char *start,
+ mbedtls_asn1_named_data *first);
+int mbedtls_x509_write_sig(unsigned char **p, unsigned char *start,
+ const char *oid, size_t oid_len,
+ unsigned char *sig, size_t size,
+ mbedtls_pk_type_t pk_alg);
+int mbedtls_x509_get_ns_cert_type(unsigned char **p,
+ const unsigned char *end,
+ unsigned char *ns_cert_type);
+int mbedtls_x509_get_key_usage(unsigned char **p,
+ const unsigned char *end,
+ unsigned int *key_usage);
+int mbedtls_x509_get_subject_alt_name(unsigned char **p,
+ const unsigned char *end,
+ mbedtls_x509_sequence *subject_alt_name);
+int mbedtls_x509_get_subject_alt_name_ext(unsigned char **p,
+ const unsigned char *end,
+ mbedtls_x509_sequence *subject_alt_name);
+int mbedtls_x509_info_subject_alt_name(char **buf, size_t *size,
+ const mbedtls_x509_sequence
+ *subject_alt_name,
+ const char *prefix);
+int mbedtls_x509_info_cert_type(char **buf, size_t *size,
+ unsigned char ns_cert_type);
+int mbedtls_x509_info_key_usage(char **buf, size_t *size,
+ unsigned int key_usage);
+
+int mbedtls_x509_write_set_san_common(mbedtls_asn1_named_data **extensions,
+ const mbedtls_x509_san_list *san_list);
+
+#endif /* MBEDTLS_X509_INTERNAL_H */
diff --git a/library/x509write.c b/library/x509write.c
index d434df5..4704900 100644
--- a/library/x509write.c
+++ b/library/x509write.c
@@ -8,6 +8,7 @@
#if defined(MBEDTLS_X509_CSR_WRITE_C) || defined(MBEDTLS_X509_CRT_WRITE_C)
#include "mbedtls/x509_crt.h"
+#include "x509_internal.h"
#include "mbedtls/asn1write.h"
#include "mbedtls/error.h"
#include "mbedtls/oid.h"
diff --git a/library/x509write_crt.c b/library/x509write_crt.c
index 913b15a..72f5a10 100644
--- a/library/x509write_crt.c
+++ b/library/x509write_crt.c
@@ -16,6 +16,7 @@
#if defined(MBEDTLS_X509_CRT_WRITE_C)
#include "mbedtls/x509_crt.h"
+#include "x509_internal.h"
#include "mbedtls/asn1write.h"
#include "mbedtls/error.h"
#include "mbedtls/oid.h"
diff --git a/library/x509write_csr.c b/library/x509write_csr.c
index af75e7f..d3ddbcc 100644
--- a/library/x509write_csr.c
+++ b/library/x509write_csr.c
@@ -14,7 +14,7 @@
#if defined(MBEDTLS_X509_CSR_WRITE_C)
-#include "mbedtls/x509.h"
+#include "x509_internal.h"
#include "mbedtls/x509_csr.h"
#include "mbedtls/asn1write.h"
#include "mbedtls/error.h"