initial commit, 4.5 stable
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled

This commit is contained in:
2025-09-16 20:46:46 -04:00
commit 9d30169a8d
13378 changed files with 7050105 additions and 0 deletions

2294
thirdparty/mbedtls/library/aes.c vendored Normal file

File diff suppressed because it is too large Load Diff

618
thirdparty/mbedtls/library/aesce.c vendored Normal file
View File

@@ -0,0 +1,618 @@
/*
* Armv8-A Cryptographic Extension support functions for Aarch64
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#if defined(__clang__) && (__clang_major__ >= 4)
/* Ideally, we would simply use MBEDTLS_ARCH_IS_ARMV8_A in the following #if,
* but that is defined by build_info.h, and we need this block to happen first. */
#if defined(__ARM_ARCH)
#if __ARM_ARCH >= 8
#define MBEDTLS_AESCE_ARCH_IS_ARMV8_A
#endif
#endif
#if defined(MBEDTLS_AESCE_ARCH_IS_ARMV8_A) && !defined(__ARM_FEATURE_CRYPTO)
/* TODO: Re-consider above after https://reviews.llvm.org/D131064 merged.
*
* The intrinsic declaration are guarded by predefined ACLE macros in clang:
* these are normally only enabled by the -march option on the command line.
* By defining the macros ourselves we gain access to those declarations without
* requiring -march on the command line.
*
* `arm_neon.h` is included by common.h, so we put these defines
* at the top of this file, before any includes.
*/
#define __ARM_FEATURE_CRYPTO 1
/* See: https://arm-software.github.io/acle/main/acle.html#cryptographic-extensions
*
* `__ARM_FEATURE_CRYPTO` is deprecated, but we need to continue to specify it
* for older compilers.
*/
#define __ARM_FEATURE_AES 1
#define MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG
#endif
#endif /* defined(__clang__) && (__clang_major__ >= 4) */
#include <string.h>
#include "common.h"
#if defined(MBEDTLS_AESCE_C)
#include "aesce.h"
#if defined(MBEDTLS_AESCE_HAVE_CODE)
/* Compiler version checks. */
#if defined(__clang__)
# if defined(MBEDTLS_ARCH_IS_ARM32) && (__clang_major__ < 11)
# error "Minimum version of Clang for MBEDTLS_AESCE_C on 32-bit Arm or Thumb is 11.0."
# elif defined(MBEDTLS_ARCH_IS_ARM64) && (__clang_major__ < 4)
# error "Minimum version of Clang for MBEDTLS_AESCE_C on aarch64 is 4.0."
# endif
#elif defined(__GNUC__)
# if __GNUC__ < 6
# error "Minimum version of GCC for MBEDTLS_AESCE_C is 6.0."
# endif
#elif defined(_MSC_VER)
/* TODO: We haven't verified MSVC from 1920 to 1928. If someone verified that,
* please update this and document of `MBEDTLS_AESCE_C` in
* `mbedtls_config.h`. */
# if _MSC_VER < 1929
# error "Minimum version of MSVC for MBEDTLS_AESCE_C is 2019 version 16.11.2."
# endif
#elif defined(__ARMCC_VERSION)
# if defined(MBEDTLS_ARCH_IS_ARM32) && (__ARMCC_VERSION < 6200002)
/* TODO: We haven't verified armclang for 32-bit Arm/Thumb prior to 6.20.
* If someone verified that, please update this and document of
* `MBEDTLS_AESCE_C` in `mbedtls_config.h`. */
# error "Minimum version of armclang for MBEDTLS_AESCE_C on 32-bit Arm is 6.20."
# elif defined(MBEDTLS_ARCH_IS_ARM64) && (__ARMCC_VERSION < 6060000)
# error "Minimum version of armclang for MBEDTLS_AESCE_C on aarch64 is 6.6."
# endif
#endif
#if !(defined(__ARM_FEATURE_CRYPTO) || defined(__ARM_FEATURE_AES)) || \
defined(MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG)
# if defined(__ARMCOMPILER_VERSION)
# if __ARMCOMPILER_VERSION <= 6090000
# error "Must use minimum -march=armv8-a+crypto for MBEDTLS_AESCE_C"
# else
# pragma clang attribute push (__attribute__((target("aes"))), apply_to=function)
# define MBEDTLS_POP_TARGET_PRAGMA
# endif
# elif defined(__clang__)
# pragma clang attribute push (__attribute__((target("aes"))), apply_to=function)
# define MBEDTLS_POP_TARGET_PRAGMA
# elif defined(__GNUC__)
# pragma GCC push_options
# pragma GCC target ("+crypto")
# define MBEDTLS_POP_TARGET_PRAGMA
# elif defined(_MSC_VER)
# error "Required feature(__ARM_FEATURE_AES) is not enabled."
# endif
#endif /* !(__ARM_FEATURE_CRYPTO || __ARM_FEATURE_AES) ||
MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG */
#if defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
#include <sys/auxv.h>
#if !defined(HWCAP_NEON)
#define HWCAP_NEON (1 << 12)
#endif
#if !defined(HWCAP2_AES)
#define HWCAP2_AES (1 << 0)
#endif
#if !defined(HWCAP_AES)
#define HWCAP_AES (1 << 3)
#endif
#if !defined(HWCAP_ASIMD)
#define HWCAP_ASIMD (1 << 1)
#endif
signed char mbedtls_aesce_has_support_result = -1;
#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
/*
* AES instruction support detection routine
*/
int mbedtls_aesce_has_support_impl(void)
{
/* To avoid many calls to getauxval, cache the result. This is
* thread-safe, because we store the result in a char so cannot
* be vulnerable to non-atomic updates.
* It is possible that we could end up setting result more than
* once, but that is harmless.
*/
if (mbedtls_aesce_has_support_result == -1) {
#if defined(MBEDTLS_ARCH_IS_ARM32)
unsigned long auxval = getauxval(AT_HWCAP);
unsigned long auxval2 = getauxval(AT_HWCAP2);
if (((auxval & HWCAP_NEON) == HWCAP_NEON) &&
((auxval2 & HWCAP2_AES) == HWCAP2_AES)) {
mbedtls_aesce_has_support_result = 1;
} else {
mbedtls_aesce_has_support_result = 0;
}
#else
unsigned long auxval = getauxval(AT_HWCAP);
if ((auxval & (HWCAP_ASIMD | HWCAP_AES)) ==
(HWCAP_ASIMD | HWCAP_AES)) {
mbedtls_aesce_has_support_result = 1;
} else {
mbedtls_aesce_has_support_result = 0;
}
#endif
}
return mbedtls_aesce_has_support_result;
}
#endif
#endif /* defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) */
/* Single round of AESCE encryption */
#define AESCE_ENCRYPT_ROUND \
block = vaeseq_u8(block, vld1q_u8(keys)); \
block = vaesmcq_u8(block); \
keys += 16
/* Two rounds of AESCE encryption */
#define AESCE_ENCRYPT_ROUND_X2 AESCE_ENCRYPT_ROUND; AESCE_ENCRYPT_ROUND
MBEDTLS_OPTIMIZE_FOR_PERFORMANCE
static uint8x16_t aesce_encrypt_block(uint8x16_t block,
unsigned char *keys,
int rounds)
{
/* 10, 12 or 14 rounds. Unroll loop. */
if (rounds == 10) {
goto rounds_10;
}
if (rounds == 12) {
goto rounds_12;
}
AESCE_ENCRYPT_ROUND_X2;
rounds_12:
AESCE_ENCRYPT_ROUND_X2;
rounds_10:
AESCE_ENCRYPT_ROUND_X2;
AESCE_ENCRYPT_ROUND_X2;
AESCE_ENCRYPT_ROUND_X2;
AESCE_ENCRYPT_ROUND_X2;
AESCE_ENCRYPT_ROUND;
/* AES AddRoundKey for the previous round.
* SubBytes, ShiftRows for the final round. */
block = vaeseq_u8(block, vld1q_u8(keys));
keys += 16;
/* Final round: no MixColumns */
/* Final AddRoundKey */
block = veorq_u8(block, vld1q_u8(keys));
return block;
}
/* Single round of AESCE decryption
*
* AES AddRoundKey, SubBytes, ShiftRows
*
* block = vaesdq_u8(block, vld1q_u8(keys));
*
* AES inverse MixColumns for the next round.
*
* This means that we switch the order of the inverse AddRoundKey and
* inverse MixColumns operations. We have to do this as AddRoundKey is
* done in an atomic instruction together with the inverses of SubBytes
* and ShiftRows.
*
* It works because MixColumns is a linear operation over GF(2^8) and
* AddRoundKey is an exclusive or, which is equivalent to addition over
* GF(2^8). (The inverse of MixColumns needs to be applied to the
* affected round keys separately which has been done when the
* decryption round keys were calculated.)
*
* block = vaesimcq_u8(block);
*/
#define AESCE_DECRYPT_ROUND \
block = vaesdq_u8(block, vld1q_u8(keys)); \
block = vaesimcq_u8(block); \
keys += 16
/* Two rounds of AESCE decryption */
#define AESCE_DECRYPT_ROUND_X2 AESCE_DECRYPT_ROUND; AESCE_DECRYPT_ROUND
#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
static uint8x16_t aesce_decrypt_block(uint8x16_t block,
unsigned char *keys,
int rounds)
{
/* 10, 12 or 14 rounds. Unroll loop. */
if (rounds == 10) {
goto rounds_10;
}
if (rounds == 12) {
goto rounds_12;
}
AESCE_DECRYPT_ROUND_X2;
rounds_12:
AESCE_DECRYPT_ROUND_X2;
rounds_10:
AESCE_DECRYPT_ROUND_X2;
AESCE_DECRYPT_ROUND_X2;
AESCE_DECRYPT_ROUND_X2;
AESCE_DECRYPT_ROUND_X2;
AESCE_DECRYPT_ROUND;
/* The inverses of AES AddRoundKey, SubBytes, ShiftRows finishing up the
* last full round. */
block = vaesdq_u8(block, vld1q_u8(keys));
keys += 16;
/* Inverse AddRoundKey for inverting the initial round key addition. */
block = veorq_u8(block, vld1q_u8(keys));
return block;
}
#endif
/*
* AES-ECB block en(de)cryption
*/
int mbedtls_aesce_crypt_ecb(mbedtls_aes_context *ctx,
int mode,
const unsigned char input[16],
unsigned char output[16])
{
uint8x16_t block = vld1q_u8(&input[0]);
unsigned char *keys = (unsigned char *) (ctx->buf + ctx->rk_offset);
#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
if (mode == MBEDTLS_AES_DECRYPT) {
block = aesce_decrypt_block(block, keys, ctx->nr);
} else
#else
(void) mode;
#endif
{
block = aesce_encrypt_block(block, keys, ctx->nr);
}
vst1q_u8(&output[0], block);
return 0;
}
/*
* Compute decryption round keys from encryption round keys
*/
#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
void mbedtls_aesce_inverse_key(unsigned char *invkey,
const unsigned char *fwdkey,
int nr)
{
int i, j;
j = nr;
vst1q_u8(invkey, vld1q_u8(fwdkey + j * 16));
for (i = 1, j--; j > 0; i++, j--) {
vst1q_u8(invkey + i * 16,
vaesimcq_u8(vld1q_u8(fwdkey + j * 16)));
}
vst1q_u8(invkey + i * 16, vld1q_u8(fwdkey + j * 16));
}
#endif
static inline uint32_t aes_rot_word(uint32_t word)
{
return (word << (32 - 8)) | (word >> 8);
}
static inline uint32_t aes_sub_word(uint32_t in)
{
uint8x16_t v = vreinterpretq_u8_u32(vdupq_n_u32(in));
uint8x16_t zero = vdupq_n_u8(0);
/* vaeseq_u8 does both SubBytes and ShiftRows. Taking the first row yields
* the correct result as ShiftRows doesn't change the first row. */
v = vaeseq_u8(zero, v);
return vgetq_lane_u32(vreinterpretq_u32_u8(v), 0);
}
/*
* Key expansion function
*/
static void aesce_setkey_enc(unsigned char *rk,
const unsigned char *key,
const size_t key_bit_length)
{
static uint8_t const rcon[] = { 0x01, 0x02, 0x04, 0x08, 0x10,
0x20, 0x40, 0x80, 0x1b, 0x36 };
/* See https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197.pdf
* - Section 5, Nr = Nk + 6
* - Section 5.2, the length of round keys is Nb*(Nr+1)
*/
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 =
round_key_len_in_words * (rounds_needed + 1); /* Nb*(Nr+1) */
const uint32_t *rko_end = (uint32_t *) rk + round_keys_len_in_words;
memcpy(rk, key, key_len_in_words * 4);
for (uint32_t *rki = (uint32_t *) rk;
rki + key_len_in_words < rko_end;
rki += key_len_in_words) {
size_t iteration = (size_t) (rki - (uint32_t *) rk) / key_len_in_words;
uint32_t *rko;
rko = rki + key_len_in_words;
rko[0] = aes_rot_word(aes_sub_word(rki[key_len_in_words - 1]));
rko[0] ^= rcon[iteration] ^ rki[0];
rko[1] = rko[0] ^ rki[1];
rko[2] = rko[1] ^ rki[2];
rko[3] = rko[2] ^ rki[3];
if (rko + key_len_in_words > rko_end) {
/* Do not write overflow words.*/
continue;
}
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
switch (key_bit_length) {
case 128:
break;
case 192:
rko[4] = rko[3] ^ rki[4];
rko[5] = rko[4] ^ rki[5];
break;
case 256:
rko[4] = aes_sub_word(rko[3]) ^ rki[4];
rko[5] = rko[4] ^ rki[5];
rko[6] = rko[5] ^ rki[6];
rko[7] = rko[6] ^ rki[7];
break;
}
#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
}
}
/*
* Key expansion, wrapper
*/
int mbedtls_aesce_setkey_enc(unsigned char *rk,
const unsigned char *key,
size_t bits)
{
switch (bits) {
case 128:
case 192:
case 256:
aesce_setkey_enc(rk, key, bits);
break;
default:
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
return 0;
}
#if defined(MBEDTLS_GCM_C)
#if defined(MBEDTLS_ARCH_IS_ARM32)
#if defined(__clang__)
/* On clang for A32/T32, work around some missing intrinsics and types which are listed in
* [ACLE](https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#polynomial-1)
* These are only required for GCM.
*/
#define vreinterpretq_u64_p64(a) ((uint64x2_t) a)
typedef uint8x16_t poly128_t;
static inline poly128_t vmull_p64(poly64_t a, poly64_t b)
{
poly128_t r;
asm ("vmull.p64 %[r], %[a], %[b]" : [r] "=w" (r) : [a] "w" (a), [b] "w" (b) :);
return r;
}
/* This is set to cause some more missing intrinsics to be defined below */
#define COMMON_MISSING_INTRINSICS
static inline poly128_t vmull_high_p64(poly64x2_t a, poly64x2_t b)
{
return vmull_p64((poly64_t) (vget_high_u64((uint64x2_t) a)),
(poly64_t) (vget_high_u64((uint64x2_t) b)));
}
#endif /* defined(__clang__) */
static inline uint8x16_t vrbitq_u8(uint8x16_t x)
{
/* There is no vrbitq_u8 instruction in A32/T32, so provide
* an equivalent non-Neon implementation. Reverse bit order in each
* byte with 4x rbit, rev. */
asm ("ldm %[p], { r2-r5 } \n\t"
"rbit r2, r2 \n\t"
"rev r2, r2 \n\t"
"rbit r3, r3 \n\t"
"rev r3, r3 \n\t"
"rbit r4, r4 \n\t"
"rev r4, r4 \n\t"
"rbit r5, r5 \n\t"
"rev r5, r5 \n\t"
"stm %[p], { r2-r5 } \n\t"
:
/* Output: 16 bytes of memory pointed to by &x */
"+m" (*(uint8_t(*)[16]) &x)
:
[p] "r" (&x)
:
"r2", "r3", "r4", "r5"
);
return x;
}
#endif /* defined(MBEDTLS_ARCH_IS_ARM32) */
#if defined(MBEDTLS_COMPILER_IS_GCC) && __GNUC__ == 5
/* Some intrinsics are not available for GCC 5.X. */
#define COMMON_MISSING_INTRINSICS
#endif /* MBEDTLS_COMPILER_IS_GCC && __GNUC__ == 5 */
#if defined(COMMON_MISSING_INTRINSICS)
/* Missing intrinsics common to both GCC 5, and Clang on 32-bit */
#define vreinterpretq_p64_u8(a) ((poly64x2_t) a)
#define vreinterpretq_u8_p128(a) ((uint8x16_t) a)
static inline poly64x1_t vget_low_p64(poly64x2_t a)
{
uint64x1_t r = vget_low_u64(vreinterpretq_u64_p64(a));
return (poly64x1_t) r;
}
#endif /* COMMON_MISSING_INTRINSICS */
/* vmull_p64/vmull_high_p64 wrappers.
*
* Older compilers miss some intrinsic functions for `poly*_t`. We use
* uint8x16_t and uint8x16x3_t as input/output parameters.
*/
#if defined(MBEDTLS_COMPILER_IS_GCC)
/* GCC reports incompatible type error without cast. GCC think poly64_t and
* poly64x1_t are different, that is different with MSVC and Clang. */
#define MBEDTLS_VMULL_P64(a, b) vmull_p64((poly64_t) a, (poly64_t) b)
#else
/* MSVC reports `error C2440: 'type cast'` with cast. Clang does not report
* error with/without cast. And I think poly64_t and poly64x1_t are same, no
* cast for clang also. */
#define MBEDTLS_VMULL_P64(a, b) vmull_p64(a, b)
#endif /* MBEDTLS_COMPILER_IS_GCC */
static inline uint8x16_t pmull_low(uint8x16_t a, uint8x16_t b)
{
return vreinterpretq_u8_p128(
MBEDTLS_VMULL_P64(
(poly64_t) vget_low_p64(vreinterpretq_p64_u8(a)),
(poly64_t) vget_low_p64(vreinterpretq_p64_u8(b))
));
}
static inline uint8x16_t pmull_high(uint8x16_t a, uint8x16_t b)
{
return vreinterpretq_u8_p128(
vmull_high_p64(vreinterpretq_p64_u8(a),
vreinterpretq_p64_u8(b)));
}
/* GHASH does 128b polynomial multiplication on block in GF(2^128) defined by
* `x^128 + x^7 + x^2 + x + 1`.
*
* Arm64 only has 64b->128b polynomial multipliers, we need to do 4 64b
* multiplies to generate a 128b.
*
* `poly_mult_128` executes polynomial multiplication and outputs 256b that
* represented by 3 128b due to code size optimization.
*
* Output layout:
* | | | |
* |------------|-------------|-------------|
* | ret.val[0] | h3:h2:00:00 | high 128b |
* | ret.val[1] | :m2:m1:00 | middle 128b |
* | ret.val[2] | : :l1:l0 | low 128b |
*/
static inline uint8x16x3_t poly_mult_128(uint8x16_t a, uint8x16_t b)
{
uint8x16x3_t ret;
uint8x16_t h, m, l; /* retval high/middle/low */
uint8x16_t c, d, e;
h = pmull_high(a, b); /* h3:h2:00:00 = a1*b1 */
l = pmull_low(a, b); /* : :l1:l0 = a0*b0 */
c = vextq_u8(b, b, 8); /* :c1:c0 = b0:b1 */
d = pmull_high(a, c); /* :d2:d1:00 = a1*b0 */
e = pmull_low(a, c); /* :e2:e1:00 = a0*b1 */
m = veorq_u8(d, e); /* :m2:m1:00 = d + e */
ret.val[0] = h;
ret.val[1] = m;
ret.val[2] = l;
return ret;
}
/*
* Modulo reduction.
*
* See: https://www.researchgate.net/publication/285612706_Implementing_GCM_on_ARMv8
*
* Section 4.3
*
* Modular reduction is slightly more complex. Write the GCM modulus as f(z) =
* z^128 +r(z), where r(z) = z^7+z^2+z+ 1. The well known approach is to
* consider that z^128 ≡r(z) (mod z^128 +r(z)), allowing us to write the 256-bit
* operand to be reduced as a(z) = h(z)z^128 +l(z)≡h(z)r(z) + l(z). That is, we
* simply multiply the higher part of the operand by r(z) and add it to l(z). If
* the result is still larger than 128 bits, we reduce again.
*/
static inline uint8x16_t poly_mult_reduce(uint8x16x3_t input)
{
uint8x16_t const ZERO = vdupq_n_u8(0);
uint64x2_t r = vreinterpretq_u64_u8(vdupq_n_u8(0x87));
#if defined(__GNUC__)
/* use 'asm' as an optimisation barrier to prevent loading MODULO from
* memory. It is for GNUC compatible compilers.
*/
asm volatile ("" : "+w" (r));
#endif
uint8x16_t const MODULO = vreinterpretq_u8_u64(vshrq_n_u64(r, 64 - 8));
uint8x16_t h, m, l; /* input high/middle/low 128b */
uint8x16_t c, d, e, f, g, n, o;
h = input.val[0]; /* h3:h2:00:00 */
m = input.val[1]; /* :m2:m1:00 */
l = input.val[2]; /* : :l1:l0 */
c = pmull_high(h, MODULO); /* :c2:c1:00 = reduction of h3 */
d = pmull_low(h, MODULO); /* : :d1:d0 = reduction of h2 */
e = veorq_u8(c, m); /* :e2:e1:00 = m2:m1:00 + c2:c1:00 */
f = pmull_high(e, MODULO); /* : :f1:f0 = reduction of e2 */
g = vextq_u8(ZERO, e, 8); /* : :g1:00 = e1:00 */
n = veorq_u8(d, l); /* : :n1:n0 = d1:d0 + l1:l0 */
o = veorq_u8(n, f); /* o1:o0 = f1:f0 + n1:n0 */
return veorq_u8(o, g); /* = o1:o0 + g1:00 */
}
/*
* GCM multiplication: c = a times b in GF(2^128)
*/
void mbedtls_aesce_gcm_mult(unsigned char c[16],
const unsigned char a[16],
const unsigned char b[16])
{
uint8x16_t va, vb, vc;
va = vrbitq_u8(vld1q_u8(&a[0]));
vb = vrbitq_u8(vld1q_u8(&b[0]));
vc = vrbitq_u8(poly_mult_reduce(poly_mult_128(va, vb)));
vst1q_u8(&c[0], vc);
}
#endif /* MBEDTLS_GCM_C */
#if defined(MBEDTLS_POP_TARGET_PRAGMA)
#if defined(__clang__)
#pragma clang attribute pop
#elif defined(__GNUC__)
#pragma GCC pop_options
#endif
#undef MBEDTLS_POP_TARGET_PRAGMA
#endif
#endif /* MBEDTLS_AESCE_HAVE_CODE */
#endif /* MBEDTLS_AESCE_C */

136
thirdparty/mbedtls/library/aesce.h vendored Normal file
View File

@@ -0,0 +1,136 @@
/**
* \file aesce.h
*
* \brief Support hardware AES acceleration on Armv8-A processors with
* the Armv8-A Cryptographic Extension.
*
* \warning These functions are only for internal use by other library
* functions; you must not call them directly.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef MBEDTLS_AESCE_H
#define MBEDTLS_AESCE_H
#include "mbedtls/build_info.h"
#include "common.h"
#include "mbedtls/aes.h"
#if defined(MBEDTLS_AESCE_C) \
&& defined(MBEDTLS_ARCH_IS_ARMV8_A) && defined(MBEDTLS_HAVE_NEON_INTRINSICS) \
&& (defined(MBEDTLS_COMPILER_IS_GCC) || defined(__clang__) || defined(MSC_VER))
/* MBEDTLS_AESCE_HAVE_CODE is defined if we have a suitable target platform, and a
* potentially suitable compiler (compiler version & flags are not checked when defining
* this). */
#define MBEDTLS_AESCE_HAVE_CODE
#ifdef __cplusplus
extern "C" {
#endif
#if defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
extern signed char mbedtls_aesce_has_support_result;
/**
* \brief Internal function to detect the crypto extension in CPUs.
*
* \return 1 if CPU has support for the feature, 0 otherwise
*/
int mbedtls_aesce_has_support_impl(void);
#define MBEDTLS_AESCE_HAS_SUPPORT() (mbedtls_aesce_has_support_result == -1 ? \
mbedtls_aesce_has_support_impl() : \
mbedtls_aesce_has_support_result)
#else /* defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) */
/* If we are not on Linux, we can't detect support so assume that it's supported.
* Similarly, assume support if MBEDTLS_AES_USE_HARDWARE_ONLY is set.
*/
#define MBEDTLS_AESCE_HAS_SUPPORT() 1
#endif /* defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) */
/**
* \brief Internal AES-ECB block encryption and decryption
*
* \warning This assumes that the context specifies either 10, 12 or 14
* rounds and will behave incorrectly if this is not the case.
*
* \param ctx AES context
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
* \param input 16-byte input block
* \param output 16-byte output block
*
* \return 0 on success (cannot fail)
*/
int mbedtls_aesce_crypt_ecb(mbedtls_aes_context *ctx,
int mode,
const unsigned char input[16],
unsigned char output[16]);
/**
* \brief Internal GCM multiplication: c = a * b in GF(2^128)
*
* \note This function is only for internal use by other library
* functions; you must not call it directly.
*
* \param c Result
* \param a First operand
* \param b Second operand
*
* \note Both operands and result are bit strings interpreted as
* elements of GF(2^128) as per the GCM spec.
*/
void mbedtls_aesce_gcm_mult(unsigned char c[16],
const unsigned char a[16],
const unsigned char b[16]);
#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
/**
* \brief Internal round key inversion. This function computes
* decryption round keys from the encryption round keys.
*
* \param invkey Round keys for the equivalent inverse cipher
* \param fwdkey Original round keys (for encryption)
* \param nr Number of rounds (that is, number of round keys minus one)
*/
void mbedtls_aesce_inverse_key(unsigned char *invkey,
const unsigned char *fwdkey,
int nr);
#endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */
/**
* \brief Internal key expansion for encryption
*
* \param rk Destination buffer where the round keys are written
* \param key Encryption key
* \param bits Key size in bits (must be 128, 192 or 256)
*
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
*/
int mbedtls_aesce_setkey_enc(unsigned char *rk,
const unsigned char *key,
size_t bits);
#ifdef __cplusplus
}
#endif
#else
#if defined(MBEDTLS_AES_USE_HARDWARE_ONLY) && defined(MBEDTLS_ARCH_IS_ARMV8_A)
#error "AES hardware acceleration not supported on this platform / compiler"
#endif
#endif /* MBEDTLS_AESCE_C && MBEDTLS_ARCH_IS_ARMV8_A && MBEDTLS_HAVE_NEON_INTRINSICS &&
(MBEDTLS_COMPILER_IS_GCC || __clang__ || MSC_VER) */
#endif /* MBEDTLS_AESCE_H */

846
thirdparty/mbedtls/library/aesni.c vendored Normal file
View File

@@ -0,0 +1,846 @@
/*
* AES-NI support functions
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
/*
* [AES-WP] https://www.intel.com/content/www/us/en/developer/articles/tool/intel-advanced-encryption-standard-aes-instructions-set.html
* [CLMUL-WP] https://www.intel.com/content/www/us/en/develop/download/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode.html
*/
#include "common.h"
#if defined(MBEDTLS_AESNI_C)
#include "aesni.h"
#include <string.h>
#if defined(MBEDTLS_AESNI_HAVE_CODE)
#if MBEDTLS_AESNI_HAVE_CODE == 2
#if defined(__GNUC__)
#include <cpuid.h>
#elif defined(_MSC_VER)
#include <intrin.h>
#else
#error "`__cpuid` required by MBEDTLS_AESNI_C is not supported by the compiler"
#endif
#include <immintrin.h>
#endif
#if defined(MBEDTLS_ARCH_IS_X86)
#if defined(MBEDTLS_COMPILER_IS_GCC)
#pragma GCC push_options
#pragma GCC target ("pclmul,sse2,aes")
#define MBEDTLS_POP_TARGET_PRAGMA
#elif defined(__clang__) && (__clang_major__ >= 5)
#pragma clang attribute push (__attribute__((target("pclmul,sse2,aes"))), apply_to=function)
#define MBEDTLS_POP_TARGET_PRAGMA
#endif
#endif
#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
/*
* AES-NI support detection routine
*/
int mbedtls_aesni_has_support(unsigned int what)
{
/* To avoid a race condition, tell the compiler that the assignment
* `done = 1` and the assignment to `c` may not be reordered.
* https://github.com/Mbed-TLS/mbedtls/issues/9840
*
* Note that we may also be worried about memory access reordering,
* but fortunately the x86 memory model is not too wild: stores
* from the same thread are observed consistently by other threads.
* (See example 8-1 in Sewell et al., "x86-TSO: A Rigorous and Usable
* Programmers Model for x86 Multiprocessors", CACM, 2010,
* https://www.cl.cam.ac.uk/~pes20/weakmemory/cacm.pdf)
*/
static volatile int done = 0;
static volatile unsigned int c = 0;
if (!done) {
#if MBEDTLS_AESNI_HAVE_CODE == 2
static int info[4] = { 0, 0, 0, 0 };
#if defined(_MSC_VER)
__cpuid(info, 1);
#else
__cpuid(1, info[0], info[1], info[2], info[3]);
#endif
c = info[2];
#else /* AESNI using asm */
asm ("movl $1, %%eax \n\t"
"cpuid \n\t"
: "=c" (c)
:
: "eax", "ebx", "edx");
#endif /* MBEDTLS_AESNI_HAVE_CODE */
done = 1;
}
return (c & what) != 0;
}
#endif /* !MBEDTLS_AES_USE_HARDWARE_ONLY */
#if MBEDTLS_AESNI_HAVE_CODE == 2
/*
* AES-NI AES-ECB block en(de)cryption
*/
int mbedtls_aesni_crypt_ecb(mbedtls_aes_context *ctx,
int mode,
const unsigned char input[16],
unsigned char output[16])
{
const __m128i *rk = (const __m128i *) (ctx->buf + ctx->rk_offset);
unsigned nr = ctx->nr; // Number of remaining rounds
// Load round key 0
__m128i state;
memcpy(&state, input, 16);
state = _mm_xor_si128(state, rk[0]); // state ^= *rk;
++rk;
--nr;
#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
if (mode == MBEDTLS_AES_DECRYPT) {
while (nr != 0) {
state = _mm_aesdec_si128(state, *rk);
++rk;
--nr;
}
state = _mm_aesdeclast_si128(state, *rk);
} else
#else
(void) mode;
#endif
{
while (nr != 0) {
state = _mm_aesenc_si128(state, *rk);
++rk;
--nr;
}
state = _mm_aesenclast_si128(state, *rk);
}
memcpy(output, &state, 16);
return 0;
}
/*
* GCM multiplication: c = a times b in GF(2^128)
* Based on [CLMUL-WP] algorithms 1 (with equation 27) and 5.
*/
static void gcm_clmul(const __m128i aa, const __m128i bb,
__m128i *cc, __m128i *dd)
{
/*
* Caryless multiplication dd:cc = aa * bb
* using [CLMUL-WP] algorithm 1 (p. 12).
*/
*cc = _mm_clmulepi64_si128(aa, bb, 0x00); // a0*b0 = c1:c0
*dd = _mm_clmulepi64_si128(aa, bb, 0x11); // a1*b1 = d1:d0
__m128i ee = _mm_clmulepi64_si128(aa, bb, 0x10); // a0*b1 = e1:e0
__m128i ff = _mm_clmulepi64_si128(aa, bb, 0x01); // a1*b0 = f1:f0
ff = _mm_xor_si128(ff, ee); // e1+f1:e0+f0
ee = ff; // e1+f1:e0+f0
ff = _mm_srli_si128(ff, 8); // 0:e1+f1
ee = _mm_slli_si128(ee, 8); // e0+f0:0
*dd = _mm_xor_si128(*dd, ff); // d1:d0+e1+f1
*cc = _mm_xor_si128(*cc, ee); // c1+e0+f0:c0
}
static void gcm_shift(__m128i *cc, __m128i *dd)
{
/* [CMUCL-WP] Algorithm 5 Step 1: shift cc:dd one bit to the left,
* taking advantage of [CLMUL-WP] eq 27 (p. 18). */
// // *cc = r1:r0
// // *dd = r3:r2
__m128i cc_lo = _mm_slli_epi64(*cc, 1); // r1<<1:r0<<1
__m128i dd_lo = _mm_slli_epi64(*dd, 1); // r3<<1:r2<<1
__m128i cc_hi = _mm_srli_epi64(*cc, 63); // r1>>63:r0>>63
__m128i dd_hi = _mm_srli_epi64(*dd, 63); // r3>>63:r2>>63
__m128i xmm5 = _mm_srli_si128(cc_hi, 8); // 0:r1>>63
cc_hi = _mm_slli_si128(cc_hi, 8); // r0>>63:0
dd_hi = _mm_slli_si128(dd_hi, 8); // 0:r1>>63
*cc = _mm_or_si128(cc_lo, cc_hi); // r1<<1|r0>>63:r0<<1
*dd = _mm_or_si128(_mm_or_si128(dd_lo, dd_hi), xmm5); // r3<<1|r2>>62:r2<<1|r1>>63
}
static __m128i gcm_reduce(__m128i xx)
{
// // xx = x1:x0
/* [CLMUL-WP] Algorithm 5 Step 2 */
__m128i aa = _mm_slli_epi64(xx, 63); // x1<<63:x0<<63 = stuff:a
__m128i bb = _mm_slli_epi64(xx, 62); // x1<<62:x0<<62 = stuff:b
__m128i cc = _mm_slli_epi64(xx, 57); // x1<<57:x0<<57 = stuff:c
__m128i dd = _mm_slli_si128(_mm_xor_si128(_mm_xor_si128(aa, bb), cc), 8); // a+b+c:0
return _mm_xor_si128(dd, xx); // x1+a+b+c:x0 = d:x0
}
static __m128i gcm_mix(__m128i dx)
{
/* [CLMUL-WP] Algorithm 5 Steps 3 and 4 */
__m128i ee = _mm_srli_epi64(dx, 1); // e1:x0>>1 = e1:e0'
__m128i ff = _mm_srli_epi64(dx, 2); // f1:x0>>2 = f1:f0'
__m128i gg = _mm_srli_epi64(dx, 7); // g1:x0>>7 = g1:g0'
// e0'+f0'+g0' is almost e0+f0+g0, except for some missing
// bits carried from d. Now get those bits back in.
__m128i eh = _mm_slli_epi64(dx, 63); // d<<63:stuff
__m128i fh = _mm_slli_epi64(dx, 62); // d<<62:stuff
__m128i gh = _mm_slli_epi64(dx, 57); // d<<57:stuff
__m128i hh = _mm_srli_si128(_mm_xor_si128(_mm_xor_si128(eh, fh), gh), 8); // 0:missing bits of d
return _mm_xor_si128(_mm_xor_si128(_mm_xor_si128(_mm_xor_si128(ee, ff), gg), hh), dx);
}
void mbedtls_aesni_gcm_mult(unsigned char c[16],
const unsigned char a[16],
const unsigned char b[16])
{
__m128i aa = { 0 }, bb = { 0 }, cc, dd;
/* The inputs are in big-endian order, so byte-reverse them */
for (size_t i = 0; i < 16; i++) {
((uint8_t *) &aa)[i] = a[15 - i];
((uint8_t *) &bb)[i] = b[15 - i];
}
gcm_clmul(aa, bb, &cc, &dd);
gcm_shift(&cc, &dd);
/*
* Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1
* using [CLMUL-WP] algorithm 5 (p. 18).
* Currently dd:cc holds x3:x2:x1:x0 (already shifted).
*/
__m128i dx = gcm_reduce(cc);
__m128i xh = gcm_mix(dx);
cc = _mm_xor_si128(xh, dd); // x3+h1:x2+h0
/* Now byte-reverse the outputs */
for (size_t i = 0; i < 16; i++) {
c[i] = ((uint8_t *) &cc)[15 - i];
}
return;
}
/*
* Compute decryption round keys from encryption round keys
*/
#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
void mbedtls_aesni_inverse_key(unsigned char *invkey,
const unsigned char *fwdkey, int nr)
{
__m128i *ik = (__m128i *) invkey;
const __m128i *fk = (const __m128i *) fwdkey + nr;
*ik = *fk;
for (--fk, ++ik; fk > (const __m128i *) fwdkey; --fk, ++ik) {
*ik = _mm_aesimc_si128(*fk);
}
*ik = *fk;
}
#endif
/*
* Key expansion, 128-bit case
*/
static __m128i aesni_set_rk_128(__m128i state, __m128i xword)
{
/*
* Finish generating the next round key.
*
* On entry state is r3:r2:r1:r0 and xword is X:stuff:stuff:stuff
* with X = rot( sub( r3 ) ) ^ RCON (obtained with AESKEYGENASSIST).
*
* On exit, xword is r7:r6:r5:r4
* with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3
* and this is returned, to be written to the round key buffer.
*/
xword = _mm_shuffle_epi32(xword, 0xff); // X:X:X:X
xword = _mm_xor_si128(xword, state); // X+r3:X+r2:X+r1:r4
state = _mm_slli_si128(state, 4); // r2:r1:r0:0
xword = _mm_xor_si128(xword, state); // X+r3+r2:X+r2+r1:r5:r4
state = _mm_slli_si128(state, 4); // r1:r0:0:0
xword = _mm_xor_si128(xword, state); // X+r3+r2+r1:r6:r5:r4
state = _mm_slli_si128(state, 4); // r0:0:0:0
state = _mm_xor_si128(xword, state); // r7:r6:r5:r4
return state;
}
static void aesni_setkey_enc_128(unsigned char *rk_bytes,
const unsigned char *key)
{
__m128i *rk = (__m128i *) rk_bytes;
memcpy(&rk[0], key, 16);
rk[1] = aesni_set_rk_128(rk[0], _mm_aeskeygenassist_si128(rk[0], 0x01));
rk[2] = aesni_set_rk_128(rk[1], _mm_aeskeygenassist_si128(rk[1], 0x02));
rk[3] = aesni_set_rk_128(rk[2], _mm_aeskeygenassist_si128(rk[2], 0x04));
rk[4] = aesni_set_rk_128(rk[3], _mm_aeskeygenassist_si128(rk[3], 0x08));
rk[5] = aesni_set_rk_128(rk[4], _mm_aeskeygenassist_si128(rk[4], 0x10));
rk[6] = aesni_set_rk_128(rk[5], _mm_aeskeygenassist_si128(rk[5], 0x20));
rk[7] = aesni_set_rk_128(rk[6], _mm_aeskeygenassist_si128(rk[6], 0x40));
rk[8] = aesni_set_rk_128(rk[7], _mm_aeskeygenassist_si128(rk[7], 0x80));
rk[9] = aesni_set_rk_128(rk[8], _mm_aeskeygenassist_si128(rk[8], 0x1B));
rk[10] = aesni_set_rk_128(rk[9], _mm_aeskeygenassist_si128(rk[9], 0x36));
}
/*
* Key expansion, 192-bit case
*/
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
static void aesni_set_rk_192(__m128i *state0, __m128i *state1, __m128i xword,
unsigned char *rk)
{
/*
* Finish generating the next 6 quarter-keys.
*
* On entry state0 is r3:r2:r1:r0, state1 is stuff:stuff:r5:r4
* and xword is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON
* (obtained with AESKEYGENASSIST).
*
* On exit, state0 is r9:r8:r7:r6 and state1 is stuff:stuff:r11:r10
* and those are written to the round key buffer.
*/
xword = _mm_shuffle_epi32(xword, 0x55); // X:X:X:X
xword = _mm_xor_si128(xword, *state0); // X+r3:X+r2:X+r1:X+r0
*state0 = _mm_slli_si128(*state0, 4); // r2:r1:r0:0
xword = _mm_xor_si128(xword, *state0); // X+r3+r2:X+r2+r1:X+r1+r0:X+r0
*state0 = _mm_slli_si128(*state0, 4); // r1:r0:0:0
xword = _mm_xor_si128(xword, *state0); // X+r3+r2+r1:X+r2+r1+r0:X+r1+r0:X+r0
*state0 = _mm_slli_si128(*state0, 4); // r0:0:0:0
xword = _mm_xor_si128(xword, *state0); // X+r3+r2+r1+r0:X+r2+r1+r0:X+r1+r0:X+r0
*state0 = xword; // = r9:r8:r7:r6
xword = _mm_shuffle_epi32(xword, 0xff); // r9:r9:r9:r9
xword = _mm_xor_si128(xword, *state1); // stuff:stuff:r9+r5:r9+r4
*state1 = _mm_slli_si128(*state1, 4); // stuff:stuff:r4:0
xword = _mm_xor_si128(xword, *state1); // stuff:stuff:r9+r5+r4:r9+r4
*state1 = xword; // = stuff:stuff:r11:r10
/* Store state0 and the low half of state1 into rk, which is conceptually
* an array of 24-byte elements. Since 24 is not a multiple of 16,
* rk is not necessarily aligned so just `*rk = *state0` doesn't work. */
memcpy(rk, state0, 16);
memcpy(rk + 16, state1, 8);
}
static void aesni_setkey_enc_192(unsigned char *rk,
const unsigned char *key)
{
/* First round: use original key */
memcpy(rk, key, 24);
/* aes.c guarantees that rk is aligned on a 16-byte boundary. */
__m128i state0 = ((__m128i *) rk)[0];
__m128i state1 = _mm_loadl_epi64(((__m128i *) rk) + 1);
aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x01), rk + 24 * 1);
aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x02), rk + 24 * 2);
aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x04), rk + 24 * 3);
aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x08), rk + 24 * 4);
aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x10), rk + 24 * 5);
aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x20), rk + 24 * 6);
aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x40), rk + 24 * 7);
aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x80), rk + 24 * 8);
}
#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
/*
* Key expansion, 256-bit case
*/
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
static void aesni_set_rk_256(__m128i state0, __m128i state1, __m128i xword,
__m128i *rk0, __m128i *rk1)
{
/*
* Finish generating the next two round keys.
*
* On entry state0 is r3:r2:r1:r0, state1 is r7:r6:r5:r4 and
* xword is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON
* (obtained with AESKEYGENASSIST).
*
* On exit, *rk0 is r11:r10:r9:r8 and *rk1 is r15:r14:r13:r12
*/
xword = _mm_shuffle_epi32(xword, 0xff);
xword = _mm_xor_si128(xword, state0);
state0 = _mm_slli_si128(state0, 4);
xword = _mm_xor_si128(xword, state0);
state0 = _mm_slli_si128(state0, 4);
xword = _mm_xor_si128(xword, state0);
state0 = _mm_slli_si128(state0, 4);
state0 = _mm_xor_si128(state0, xword);
*rk0 = state0;
/* Set xword to stuff:Y:stuff:stuff with Y = subword( r11 )
* and proceed to generate next round key from there */
xword = _mm_aeskeygenassist_si128(state0, 0x00);
xword = _mm_shuffle_epi32(xword, 0xaa);
xword = _mm_xor_si128(xword, state1);
state1 = _mm_slli_si128(state1, 4);
xword = _mm_xor_si128(xword, state1);
state1 = _mm_slli_si128(state1, 4);
xword = _mm_xor_si128(xword, state1);
state1 = _mm_slli_si128(state1, 4);
state1 = _mm_xor_si128(state1, xword);
*rk1 = state1;
}
static void aesni_setkey_enc_256(unsigned char *rk_bytes,
const unsigned char *key)
{
__m128i *rk = (__m128i *) rk_bytes;
memcpy(&rk[0], key, 16);
memcpy(&rk[1], key + 16, 16);
/*
* Main "loop" - Generating one more key than necessary,
* see definition of mbedtls_aes_context.buf
*/
aesni_set_rk_256(rk[0], rk[1], _mm_aeskeygenassist_si128(rk[1], 0x01), &rk[2], &rk[3]);
aesni_set_rk_256(rk[2], rk[3], _mm_aeskeygenassist_si128(rk[3], 0x02), &rk[4], &rk[5]);
aesni_set_rk_256(rk[4], rk[5], _mm_aeskeygenassist_si128(rk[5], 0x04), &rk[6], &rk[7]);
aesni_set_rk_256(rk[6], rk[7], _mm_aeskeygenassist_si128(rk[7], 0x08), &rk[8], &rk[9]);
aesni_set_rk_256(rk[8], rk[9], _mm_aeskeygenassist_si128(rk[9], 0x10), &rk[10], &rk[11]);
aesni_set_rk_256(rk[10], rk[11], _mm_aeskeygenassist_si128(rk[11], 0x20), &rk[12], &rk[13]);
aesni_set_rk_256(rk[12], rk[13], _mm_aeskeygenassist_si128(rk[13], 0x40), &rk[14], &rk[15]);
}
#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
#if defined(MBEDTLS_POP_TARGET_PRAGMA)
#if defined(__clang__)
#pragma clang attribute pop
#elif defined(__GNUC__)
#pragma GCC pop_options
#endif
#undef MBEDTLS_POP_TARGET_PRAGMA
#endif
#else /* MBEDTLS_AESNI_HAVE_CODE == 1 */
#if defined(__has_feature)
#if __has_feature(memory_sanitizer)
#warning \
"MBEDTLS_AESNI_C is known to cause spurious error reports with some memory sanitizers as they do not understand the assembly code."
#endif
#endif
/*
* Binutils needs to be at least 2.19 to support AES-NI instructions.
* Unfortunately, a lot of users have a lower version now (2014-04).
* Emit bytecode directly in order to support "old" version of gas.
*
* Opcodes from the Intel architecture reference manual, vol. 3.
* We always use registers, so we don't need prefixes for memory operands.
* Operand macros are in gas order (src, dst) as opposed to Intel order
* (dst, src) in order to blend better into the surrounding assembly code.
*/
#define AESDEC(regs) ".byte 0x66,0x0F,0x38,0xDE," regs "\n\t"
#define AESDECLAST(regs) ".byte 0x66,0x0F,0x38,0xDF," regs "\n\t"
#define AESENC(regs) ".byte 0x66,0x0F,0x38,0xDC," regs "\n\t"
#define AESENCLAST(regs) ".byte 0x66,0x0F,0x38,0xDD," regs "\n\t"
#define AESIMC(regs) ".byte 0x66,0x0F,0x38,0xDB," regs "\n\t"
#define AESKEYGENA(regs, imm) ".byte 0x66,0x0F,0x3A,0xDF," regs "," imm "\n\t"
#define PCLMULQDQ(regs, imm) ".byte 0x66,0x0F,0x3A,0x44," regs "," imm "\n\t"
#define xmm0_xmm0 "0xC0"
#define xmm0_xmm1 "0xC8"
#define xmm0_xmm2 "0xD0"
#define xmm0_xmm3 "0xD8"
#define xmm0_xmm4 "0xE0"
#define xmm1_xmm0 "0xC1"
#define xmm1_xmm2 "0xD1"
/*
* AES-NI AES-ECB block en(de)cryption
*/
int mbedtls_aesni_crypt_ecb(mbedtls_aes_context *ctx,
int mode,
const unsigned char input[16],
unsigned char output[16])
{
asm ("movdqu (%3), %%xmm0 \n\t" // load input
"movdqu (%1), %%xmm1 \n\t" // load round key 0
"pxor %%xmm1, %%xmm0 \n\t" // round 0
"add $16, %1 \n\t" // point to next round key
"subl $1, %0 \n\t" // normal rounds = nr - 1
"test %2, %2 \n\t" // mode?
"jz 2f \n\t" // 0 = decrypt
"1: \n\t" // encryption loop
"movdqu (%1), %%xmm1 \n\t" // load round key
AESENC(xmm1_xmm0) // do round
"add $16, %1 \n\t" // point to next round key
"subl $1, %0 \n\t" // loop
"jnz 1b \n\t"
"movdqu (%1), %%xmm1 \n\t" // load round key
AESENCLAST(xmm1_xmm0) // last round
#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
"jmp 3f \n\t"
"2: \n\t" // decryption loop
"movdqu (%1), %%xmm1 \n\t"
AESDEC(xmm1_xmm0) // do round
"add $16, %1 \n\t"
"subl $1, %0 \n\t"
"jnz 2b \n\t"
"movdqu (%1), %%xmm1 \n\t" // load round key
AESDECLAST(xmm1_xmm0) // last round
#endif
"3: \n\t"
"movdqu %%xmm0, (%4) \n\t" // export output
:
: "r" (ctx->nr), "r" (ctx->buf + ctx->rk_offset), "r" (mode), "r" (input), "r" (output)
: "memory", "cc", "xmm0", "xmm1", "0", "1");
return 0;
}
/*
* GCM multiplication: c = a times b in GF(2^128)
* Based on [CLMUL-WP] algorithms 1 (with equation 27) and 5.
*/
void mbedtls_aesni_gcm_mult(unsigned char c[16],
const unsigned char a[16],
const unsigned char b[16])
{
unsigned char aa[16], bb[16], cc[16];
size_t i;
/* The inputs are in big-endian order, so byte-reverse them */
for (i = 0; i < 16; i++) {
aa[i] = a[15 - i];
bb[i] = b[15 - i];
}
asm ("movdqu (%0), %%xmm0 \n\t" // a1:a0
"movdqu (%1), %%xmm1 \n\t" // b1:b0
/*
* Caryless multiplication xmm2:xmm1 = xmm0 * xmm1
* using [CLMUL-WP] algorithm 1 (p. 12).
*/
"movdqa %%xmm1, %%xmm2 \n\t" // copy of b1:b0
"movdqa %%xmm1, %%xmm3 \n\t" // same
"movdqa %%xmm1, %%xmm4 \n\t" // same
PCLMULQDQ(xmm0_xmm1, "0x00") // a0*b0 = c1:c0
PCLMULQDQ(xmm0_xmm2, "0x11") // a1*b1 = d1:d0
PCLMULQDQ(xmm0_xmm3, "0x10") // a0*b1 = e1:e0
PCLMULQDQ(xmm0_xmm4, "0x01") // a1*b0 = f1:f0
"pxor %%xmm3, %%xmm4 \n\t" // e1+f1:e0+f0
"movdqa %%xmm4, %%xmm3 \n\t" // same
"psrldq $8, %%xmm4 \n\t" // 0:e1+f1
"pslldq $8, %%xmm3 \n\t" // e0+f0:0
"pxor %%xmm4, %%xmm2 \n\t" // d1:d0+e1+f1
"pxor %%xmm3, %%xmm1 \n\t" // c1+e0+f1:c0
/*
* Now shift the result one bit to the left,
* taking advantage of [CLMUL-WP] eq 27 (p. 18)
*/
"movdqa %%xmm1, %%xmm3 \n\t" // r1:r0
"movdqa %%xmm2, %%xmm4 \n\t" // r3:r2
"psllq $1, %%xmm1 \n\t" // r1<<1:r0<<1
"psllq $1, %%xmm2 \n\t" // r3<<1:r2<<1
"psrlq $63, %%xmm3 \n\t" // r1>>63:r0>>63
"psrlq $63, %%xmm4 \n\t" // r3>>63:r2>>63
"movdqa %%xmm3, %%xmm5 \n\t" // r1>>63:r0>>63
"pslldq $8, %%xmm3 \n\t" // r0>>63:0
"pslldq $8, %%xmm4 \n\t" // r2>>63:0
"psrldq $8, %%xmm5 \n\t" // 0:r1>>63
"por %%xmm3, %%xmm1 \n\t" // r1<<1|r0>>63:r0<<1
"por %%xmm4, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1
"por %%xmm5, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1|r1>>63
/*
* Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1
* using [CLMUL-WP] algorithm 5 (p. 18).
* Currently xmm2:xmm1 holds x3:x2:x1:x0 (already shifted).
*/
/* Step 2 (1) */
"movdqa %%xmm1, %%xmm3 \n\t" // x1:x0
"movdqa %%xmm1, %%xmm4 \n\t" // same
"movdqa %%xmm1, %%xmm5 \n\t" // same
"psllq $63, %%xmm3 \n\t" // x1<<63:x0<<63 = stuff:a
"psllq $62, %%xmm4 \n\t" // x1<<62:x0<<62 = stuff:b
"psllq $57, %%xmm5 \n\t" // x1<<57:x0<<57 = stuff:c
/* Step 2 (2) */
"pxor %%xmm4, %%xmm3 \n\t" // stuff:a+b
"pxor %%xmm5, %%xmm3 \n\t" // stuff:a+b+c
"pslldq $8, %%xmm3 \n\t" // a+b+c:0
"pxor %%xmm3, %%xmm1 \n\t" // x1+a+b+c:x0 = d:x0
/* Steps 3 and 4 */
"movdqa %%xmm1,%%xmm0 \n\t" // d:x0
"movdqa %%xmm1,%%xmm4 \n\t" // same
"movdqa %%xmm1,%%xmm5 \n\t" // same
"psrlq $1, %%xmm0 \n\t" // e1:x0>>1 = e1:e0'
"psrlq $2, %%xmm4 \n\t" // f1:x0>>2 = f1:f0'
"psrlq $7, %%xmm5 \n\t" // g1:x0>>7 = g1:g0'
"pxor %%xmm4, %%xmm0 \n\t" // e1+f1:e0'+f0'
"pxor %%xmm5, %%xmm0 \n\t" // e1+f1+g1:e0'+f0'+g0'
// e0'+f0'+g0' is almost e0+f0+g0, ex\tcept for some missing
// bits carried from d. Now get those\t bits back in.
"movdqa %%xmm1,%%xmm3 \n\t" // d:x0
"movdqa %%xmm1,%%xmm4 \n\t" // same
"movdqa %%xmm1,%%xmm5 \n\t" // same
"psllq $63, %%xmm3 \n\t" // d<<63:stuff
"psllq $62, %%xmm4 \n\t" // d<<62:stuff
"psllq $57, %%xmm5 \n\t" // d<<57:stuff
"pxor %%xmm4, %%xmm3 \n\t" // d<<63+d<<62:stuff
"pxor %%xmm5, %%xmm3 \n\t" // missing bits of d:stuff
"psrldq $8, %%xmm3 \n\t" // 0:missing bits of d
"pxor %%xmm3, %%xmm0 \n\t" // e1+f1+g1:e0+f0+g0
"pxor %%xmm1, %%xmm0 \n\t" // h1:h0
"pxor %%xmm2, %%xmm0 \n\t" // x3+h1:x2+h0
"movdqu %%xmm0, (%2) \n\t" // done
:
: "r" (aa), "r" (bb), "r" (cc)
: "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5");
/* Now byte-reverse the outputs */
for (i = 0; i < 16; i++) {
c[i] = cc[15 - i];
}
return;
}
/*
* Compute decryption round keys from encryption round keys
*/
#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
void mbedtls_aesni_inverse_key(unsigned char *invkey,
const unsigned char *fwdkey, int nr)
{
unsigned char *ik = invkey;
const unsigned char *fk = fwdkey + 16 * nr;
memcpy(ik, fk, 16);
for (fk -= 16, ik += 16; fk > fwdkey; fk -= 16, ik += 16) {
asm ("movdqu (%0), %%xmm0 \n\t"
AESIMC(xmm0_xmm0)
"movdqu %%xmm0, (%1) \n\t"
:
: "r" (fk), "r" (ik)
: "memory", "xmm0");
}
memcpy(ik, fk, 16);
}
#endif
/*
* Key expansion, 128-bit case
*/
static void aesni_setkey_enc_128(unsigned char *rk,
const unsigned char *key)
{
asm ("movdqu (%1), %%xmm0 \n\t" // copy the original key
"movdqu %%xmm0, (%0) \n\t" // as round key 0
"jmp 2f \n\t" // skip auxiliary routine
/*
* Finish generating the next round key.
*
* On entry xmm0 is r3:r2:r1:r0 and xmm1 is X:stuff:stuff:stuff
* with X = rot( sub( r3 ) ) ^ RCON.
*
* On exit, xmm0 is r7:r6:r5:r4
* with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3
* and those are written to the round key buffer.
*/
"1: \n\t"
"pshufd $0xff, %%xmm1, %%xmm1 \n\t" // X:X:X:X
"pxor %%xmm0, %%xmm1 \n\t" // X+r3:X+r2:X+r1:r4
"pslldq $4, %%xmm0 \n\t" // r2:r1:r0:0
"pxor %%xmm0, %%xmm1 \n\t" // X+r3+r2:X+r2+r1:r5:r4
"pslldq $4, %%xmm0 \n\t" // etc
"pxor %%xmm0, %%xmm1 \n\t"
"pslldq $4, %%xmm0 \n\t"
"pxor %%xmm1, %%xmm0 \n\t" // update xmm0 for next time!
"add $16, %0 \n\t" // point to next round key
"movdqu %%xmm0, (%0) \n\t" // write it
"ret \n\t"
/* Main "loop" */
"2: \n\t"
AESKEYGENA(xmm0_xmm1, "0x01") "call 1b \n\t"
AESKEYGENA(xmm0_xmm1, "0x02") "call 1b \n\t"
AESKEYGENA(xmm0_xmm1, "0x04") "call 1b \n\t"
AESKEYGENA(xmm0_xmm1, "0x08") "call 1b \n\t"
AESKEYGENA(xmm0_xmm1, "0x10") "call 1b \n\t"
AESKEYGENA(xmm0_xmm1, "0x20") "call 1b \n\t"
AESKEYGENA(xmm0_xmm1, "0x40") "call 1b \n\t"
AESKEYGENA(xmm0_xmm1, "0x80") "call 1b \n\t"
AESKEYGENA(xmm0_xmm1, "0x1B") "call 1b \n\t"
AESKEYGENA(xmm0_xmm1, "0x36") "call 1b \n\t"
:
: "r" (rk), "r" (key)
: "memory", "cc", "xmm0", "xmm1", "0");
}
/*
* Key expansion, 192-bit case
*/
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
static void aesni_setkey_enc_192(unsigned char *rk,
const unsigned char *key)
{
asm ("movdqu (%1), %%xmm0 \n\t" // copy original round key
"movdqu %%xmm0, (%0) \n\t"
"add $16, %0 \n\t"
"movq 16(%1), %%xmm1 \n\t"
"movq %%xmm1, (%0) \n\t"
"add $8, %0 \n\t"
"jmp 2f \n\t" // skip auxiliary routine
/*
* Finish generating the next 6 quarter-keys.
*
* On entry xmm0 is r3:r2:r1:r0, xmm1 is stuff:stuff:r5:r4
* and xmm2 is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON.
*
* On exit, xmm0 is r9:r8:r7:r6 and xmm1 is stuff:stuff:r11:r10
* and those are written to the round key buffer.
*/
"1: \n\t"
"pshufd $0x55, %%xmm2, %%xmm2 \n\t" // X:X:X:X
"pxor %%xmm0, %%xmm2 \n\t" // X+r3:X+r2:X+r1:r4
"pslldq $4, %%xmm0 \n\t" // etc
"pxor %%xmm0, %%xmm2 \n\t"
"pslldq $4, %%xmm0 \n\t"
"pxor %%xmm0, %%xmm2 \n\t"
"pslldq $4, %%xmm0 \n\t"
"pxor %%xmm2, %%xmm0 \n\t" // update xmm0 = r9:r8:r7:r6
"movdqu %%xmm0, (%0) \n\t"
"add $16, %0 \n\t"
"pshufd $0xff, %%xmm0, %%xmm2 \n\t" // r9:r9:r9:r9
"pxor %%xmm1, %%xmm2 \n\t" // stuff:stuff:r9+r5:r10
"pslldq $4, %%xmm1 \n\t" // r2:r1:r0:0
"pxor %%xmm2, %%xmm1 \n\t" // xmm1 = stuff:stuff:r11:r10
"movq %%xmm1, (%0) \n\t"
"add $8, %0 \n\t"
"ret \n\t"
"2: \n\t"
AESKEYGENA(xmm1_xmm2, "0x01") "call 1b \n\t"
AESKEYGENA(xmm1_xmm2, "0x02") "call 1b \n\t"
AESKEYGENA(xmm1_xmm2, "0x04") "call 1b \n\t"
AESKEYGENA(xmm1_xmm2, "0x08") "call 1b \n\t"
AESKEYGENA(xmm1_xmm2, "0x10") "call 1b \n\t"
AESKEYGENA(xmm1_xmm2, "0x20") "call 1b \n\t"
AESKEYGENA(xmm1_xmm2, "0x40") "call 1b \n\t"
AESKEYGENA(xmm1_xmm2, "0x80") "call 1b \n\t"
:
: "r" (rk), "r" (key)
: "memory", "cc", "xmm0", "xmm1", "xmm2", "0");
}
#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
/*
* Key expansion, 256-bit case
*/
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
static void aesni_setkey_enc_256(unsigned char *rk,
const unsigned char *key)
{
asm ("movdqu (%1), %%xmm0 \n\t"
"movdqu %%xmm0, (%0) \n\t"
"add $16, %0 \n\t"
"movdqu 16(%1), %%xmm1 \n\t"
"movdqu %%xmm1, (%0) \n\t"
"jmp 2f \n\t" // skip auxiliary routine
/*
* Finish generating the next two round keys.
*
* On entry xmm0 is r3:r2:r1:r0, xmm1 is r7:r6:r5:r4 and
* xmm2 is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON
*
* On exit, xmm0 is r11:r10:r9:r8 and xmm1 is r15:r14:r13:r12
* and those have been written to the output buffer.
*/
"1: \n\t"
"pshufd $0xff, %%xmm2, %%xmm2 \n\t"
"pxor %%xmm0, %%xmm2 \n\t"
"pslldq $4, %%xmm0 \n\t"
"pxor %%xmm0, %%xmm2 \n\t"
"pslldq $4, %%xmm0 \n\t"
"pxor %%xmm0, %%xmm2 \n\t"
"pslldq $4, %%xmm0 \n\t"
"pxor %%xmm2, %%xmm0 \n\t"
"add $16, %0 \n\t"
"movdqu %%xmm0, (%0) \n\t"
/* Set xmm2 to stuff:Y:stuff:stuff with Y = subword( r11 )
* and proceed to generate next round key from there */
AESKEYGENA(xmm0_xmm2, "0x00")
"pshufd $0xaa, %%xmm2, %%xmm2 \n\t"
"pxor %%xmm1, %%xmm2 \n\t"
"pslldq $4, %%xmm1 \n\t"
"pxor %%xmm1, %%xmm2 \n\t"
"pslldq $4, %%xmm1 \n\t"
"pxor %%xmm1, %%xmm2 \n\t"
"pslldq $4, %%xmm1 \n\t"
"pxor %%xmm2, %%xmm1 \n\t"
"add $16, %0 \n\t"
"movdqu %%xmm1, (%0) \n\t"
"ret \n\t"
/*
* Main "loop" - Generating one more key than necessary,
* see definition of mbedtls_aes_context.buf
*/
"2: \n\t"
AESKEYGENA(xmm1_xmm2, "0x01") "call 1b \n\t"
AESKEYGENA(xmm1_xmm2, "0x02") "call 1b \n\t"
AESKEYGENA(xmm1_xmm2, "0x04") "call 1b \n\t"
AESKEYGENA(xmm1_xmm2, "0x08") "call 1b \n\t"
AESKEYGENA(xmm1_xmm2, "0x10") "call 1b \n\t"
AESKEYGENA(xmm1_xmm2, "0x20") "call 1b \n\t"
AESKEYGENA(xmm1_xmm2, "0x40") "call 1b \n\t"
:
: "r" (rk), "r" (key)
: "memory", "cc", "xmm0", "xmm1", "xmm2", "0");
}
#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
#endif /* MBEDTLS_AESNI_HAVE_CODE */
/*
* Key expansion, wrapper
*/
int mbedtls_aesni_setkey_enc(unsigned char *rk,
const unsigned char *key,
size_t bits)
{
switch (bits) {
case 128: aesni_setkey_enc_128(rk, key); break;
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
case 192: aesni_setkey_enc_192(rk, key); break;
case 256: aesni_setkey_enc_256(rk, key); break;
#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
default: return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
}
return 0;
}
#endif /* MBEDTLS_AESNI_HAVE_CODE */
#endif /* MBEDTLS_AESNI_C */

162
thirdparty/mbedtls/library/aesni.h vendored Normal file
View File

@@ -0,0 +1,162 @@
/**
* \file aesni.h
*
* \brief AES-NI for hardware AES acceleration on some Intel processors
*
* \warning These functions are only for internal use by other library
* functions; you must not call them directly.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef MBEDTLS_AESNI_H
#define MBEDTLS_AESNI_H
#include "mbedtls/build_info.h"
#include "mbedtls/aes.h"
#define MBEDTLS_AESNI_AES 0x02000000u
#define MBEDTLS_AESNI_CLMUL 0x00000002u
#if defined(MBEDTLS_AESNI_C) && \
(defined(MBEDTLS_ARCH_IS_X64) || defined(MBEDTLS_ARCH_IS_X86))
/* Can we do AESNI with intrinsics?
* (Only implemented with certain compilers, only for certain targets.)
*/
#undef MBEDTLS_AESNI_HAVE_INTRINSICS
#if defined(_MSC_VER) && !defined(__clang__)
/* Visual Studio supports AESNI intrinsics since VS 2008 SP1. We only support
* VS 2013 and up for other reasons anyway, so no need to check the version. */
#define MBEDTLS_AESNI_HAVE_INTRINSICS
#endif
/* GCC-like compilers: currently, we only support intrinsics if the requisite
* target flag is enabled when building the library (e.g. `gcc -mpclmul -msse2`
* or `clang -maes -mpclmul`). */
#if (defined(__GNUC__) || defined(__clang__)) && defined(__AES__) && defined(__PCLMUL__)
#define MBEDTLS_AESNI_HAVE_INTRINSICS
#endif
/* For 32-bit, we only support intrinsics */
#if defined(MBEDTLS_ARCH_IS_X86) && (defined(__GNUC__) || defined(__clang__))
#define MBEDTLS_AESNI_HAVE_INTRINSICS
#endif
/* Choose the implementation of AESNI, if one is available.
*
* Favor the intrinsics-based implementation if it's available, for better
* maintainability.
* Performance is about the same (see #7380).
* In the long run, we will likely remove the assembly implementation. */
#if defined(MBEDTLS_AESNI_HAVE_INTRINSICS)
#define MBEDTLS_AESNI_HAVE_CODE 2 // via intrinsics
#elif defined(MBEDTLS_HAVE_ASM) && \
(defined(__GNUC__) || defined(__clang__)) && defined(MBEDTLS_ARCH_IS_X64)
/* Can we do AESNI with inline assembly?
* (Only implemented with gas syntax, only for 64-bit.)
*/
#define MBEDTLS_AESNI_HAVE_CODE 1 // via assembly
#else
#error "MBEDTLS_AESNI_C defined, but neither intrinsics nor assembly available"
#endif
#if defined(MBEDTLS_AESNI_HAVE_CODE)
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Internal function to detect the AES-NI feature in CPUs.
*
* \note This function is only for internal use by other library
* functions; you must not call it directly.
*
* \param what The feature to detect
* (MBEDTLS_AESNI_AES or MBEDTLS_AESNI_CLMUL)
*
* \return 1 if CPU has support for the feature, 0 otherwise
*/
#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
int mbedtls_aesni_has_support(unsigned int what);
#else
#define mbedtls_aesni_has_support(what) 1
#endif
/**
* \brief Internal AES-NI AES-ECB block encryption and decryption
*
* \note This function is only for internal use by other library
* functions; you must not call it directly.
*
* \param ctx AES context
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
* \param input 16-byte input block
* \param output 16-byte output block
*
* \return 0 on success (cannot fail)
*/
int mbedtls_aesni_crypt_ecb(mbedtls_aes_context *ctx,
int mode,
const unsigned char input[16],
unsigned char output[16]);
/**
* \brief Internal GCM multiplication: c = a * b in GF(2^128)
*
* \note This function is only for internal use by other library
* functions; you must not call it directly.
*
* \param c Result
* \param a First operand
* \param b Second operand
*
* \note Both operands and result are bit strings interpreted as
* elements of GF(2^128) as per the GCM spec.
*/
void mbedtls_aesni_gcm_mult(unsigned char c[16],
const unsigned char a[16],
const unsigned char b[16]);
#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
/**
* \brief Internal round key inversion. This function computes
* decryption round keys from the encryption round keys.
*
* \note This function is only for internal use by other library
* functions; you must not call it directly.
*
* \param invkey Round keys for the equivalent inverse cipher
* \param fwdkey Original round keys (for encryption)
* \param nr Number of rounds (that is, number of round keys minus one)
*/
void mbedtls_aesni_inverse_key(unsigned char *invkey,
const unsigned char *fwdkey,
int nr);
#endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */
/**
* \brief Internal key expansion for encryption
*
* \note This function is only for internal use by other library
* functions; you must not call it directly.
*
* \param rk Destination buffer where the round keys are written
* \param key Encryption key
* \param bits Key size in bits (must be 128, 192 or 256)
*
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
*/
int mbedtls_aesni_setkey_enc(unsigned char *rk,
const unsigned char *key,
size_t bits);
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_AESNI_HAVE_CODE */
#endif /* MBEDTLS_AESNI_C && (MBEDTLS_ARCH_IS_X64 || MBEDTLS_ARCH_IS_X86) */
#endif /* MBEDTLS_AESNI_H */

684
thirdparty/mbedtls/library/alignment.h vendored Normal file
View File

@@ -0,0 +1,684 @@
/**
* \file alignment.h
*
* \brief Utility code for dealing with unaligned memory accesses
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef MBEDTLS_LIBRARY_ALIGNMENT_H
#define MBEDTLS_LIBRARY_ALIGNMENT_H
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
/*
* Define MBEDTLS_EFFICIENT_UNALIGNED_ACCESS for architectures where unaligned memory
* accesses are known to be efficient.
*
* All functions defined here will behave correctly regardless, but might be less
* efficient when this is not defined.
*/
#if defined(__ARM_FEATURE_UNALIGNED) \
|| defined(MBEDTLS_ARCH_IS_X86) || defined(MBEDTLS_ARCH_IS_X64) \
|| defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64)
/*
* __ARM_FEATURE_UNALIGNED is defined where appropriate by armcc, gcc 7, clang 9
* (and later versions) for Arm v7 and later; all x86 platforms should have
* efficient unaligned access.
*
* https://learn.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=msvc-170#alignment
* specifies that on Windows-on-Arm64, unaligned access is safe (except for uncached
* device memory).
*/
#define MBEDTLS_EFFICIENT_UNALIGNED_ACCESS
#endif
#if defined(__IAR_SYSTEMS_ICC__) && \
(defined(MBEDTLS_ARCH_IS_ARM64) || defined(MBEDTLS_ARCH_IS_ARM32) \
|| defined(__ICCRX__) || defined(__ICCRL78__) || defined(__ICCRISCV__))
#pragma language=save
#pragma language=extended
#define MBEDTLS_POP_IAR_LANGUAGE_PRAGMA
/* IAR recommend this technique for accessing unaligned data in
* https://www.iar.com/knowledge/support/technical-notes/compiler/accessing-unaligned-data
* This results in a single load / store instruction (if unaligned access is supported).
* According to that document, this is only supported on certain architectures.
*/
#define UINT_UNALIGNED
typedef uint16_t __packed mbedtls_uint16_unaligned_t;
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 < 60300) || (!defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS)))
/*
* 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 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
*
* 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_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
/*
* We try to force mbedtls_(get|put)_unaligned_uintXX to be always inline, because this results
* in code that is both smaller and faster. IAR and gcc both benefit from this when optimising
* for size.
*/
/**
* Read the unsigned 16 bits integer from the given address, which need not
* be aligned.
*
* \param p pointer to 2 bytes of data
* \return Data at the given address
*/
#if defined(__IAR_SYSTEMS_ICC__)
#pragma inline = forced
#elif defined(__GNUC__)
__attribute__((always_inline))
#endif
static inline uint16_t mbedtls_get_unaligned_uint16(const void *p)
{
uint16_t r;
#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
return r;
}
/**
* Write the unsigned 16 bits integer to the given address, which need not
* be aligned.
*
* \param p pointer to 2 bytes of data
* \param x data to write
*/
#if defined(__IAR_SYSTEMS_ICC__)
#pragma inline = forced
#elif defined(__GNUC__)
__attribute__((always_inline))
#endif
static inline void mbedtls_put_unaligned_uint16(void *p, uint16_t x)
{
#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
}
/**
* Read the unsigned 32 bits integer from the given address, which need not
* be aligned.
*
* \param p pointer to 4 bytes of data
* \return Data at the given address
*/
#if defined(__IAR_SYSTEMS_ICC__)
#pragma inline = forced
#elif defined(__GNUC__)
__attribute__((always_inline))
#endif
static inline uint32_t mbedtls_get_unaligned_uint32(const void *p)
{
uint32_t r;
#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
return r;
}
/**
* Write the unsigned 32 bits integer to the given address, which need not
* be aligned.
*
* \param p pointer to 4 bytes of data
* \param x data to write
*/
#if defined(__IAR_SYSTEMS_ICC__)
#pragma inline = forced
#elif defined(__GNUC__)
__attribute__((always_inline))
#endif
static inline void mbedtls_put_unaligned_uint32(void *p, uint32_t x)
{
#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
}
/**
* Read the unsigned 64 bits integer from the given address, which need not
* be aligned.
*
* \param p pointer to 8 bytes of data
* \return Data at the given address
*/
#if defined(__IAR_SYSTEMS_ICC__)
#pragma inline = forced
#elif defined(__GNUC__)
__attribute__((always_inline))
#endif
static inline uint64_t mbedtls_get_unaligned_uint64(const void *p)
{
uint64_t r;
#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
return r;
}
/**
* Write the unsigned 64 bits integer to the given address, which need not
* be aligned.
*
* \param p pointer to 8 bytes of data
* \param x data to write
*/
#if defined(__IAR_SYSTEMS_ICC__)
#pragma inline = forced
#elif defined(__GNUC__)
__attribute__((always_inline))
#endif
static inline void mbedtls_put_unaligned_uint64(void *p, uint64_t x)
{
#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
}
#if defined(MBEDTLS_POP_IAR_LANGUAGE_PRAGMA)
#pragma language=restore
#endif
/** Byte Reading Macros
*
* Given a multi-byte integer \p x, MBEDTLS_BYTE_n retrieves the n-th
* byte from x, where byte 0 is the least significant byte.
*/
#define MBEDTLS_BYTE_0(x) ((uint8_t) ((x) & 0xff))
#define MBEDTLS_BYTE_1(x) ((uint8_t) (((x) >> 8) & 0xff))
#define MBEDTLS_BYTE_2(x) ((uint8_t) (((x) >> 16) & 0xff))
#define MBEDTLS_BYTE_3(x) ((uint8_t) (((x) >> 24) & 0xff))
#define MBEDTLS_BYTE_4(x) ((uint8_t) (((x) >> 32) & 0xff))
#define MBEDTLS_BYTE_5(x) ((uint8_t) (((x) >> 40) & 0xff))
#define MBEDTLS_BYTE_6(x) ((uint8_t) (((x) >> 48) & 0xff))
#define MBEDTLS_BYTE_7(x) ((uint8_t) (((x) >> 56) & 0xff))
/*
* Detect GCC built-in byteswap routines
*/
#if defined(__GNUC__) && defined(__GNUC_PREREQ)
#if __GNUC_PREREQ(4, 8)
#define MBEDTLS_BSWAP16 __builtin_bswap16
#endif /* __GNUC_PREREQ(4,8) */
#if __GNUC_PREREQ(4, 3)
#define MBEDTLS_BSWAP32 __builtin_bswap32
#define MBEDTLS_BSWAP64 __builtin_bswap64
#endif /* __GNUC_PREREQ(4,3) */
#endif /* defined(__GNUC__) && defined(__GNUC_PREREQ) */
/*
* Detect Clang built-in byteswap routines
*/
#if defined(__clang__) && defined(__has_builtin)
#if __has_builtin(__builtin_bswap16) && !defined(MBEDTLS_BSWAP16)
#define MBEDTLS_BSWAP16 __builtin_bswap16
#endif /* __has_builtin(__builtin_bswap16) */
#if __has_builtin(__builtin_bswap32) && !defined(MBEDTLS_BSWAP32)
#define MBEDTLS_BSWAP32 __builtin_bswap32
#endif /* __has_builtin(__builtin_bswap32) */
#if __has_builtin(__builtin_bswap64) && !defined(MBEDTLS_BSWAP64)
#define MBEDTLS_BSWAP64 __builtin_bswap64
#endif /* __has_builtin(__builtin_bswap64) */
#endif /* defined(__clang__) && defined(__has_builtin) */
/*
* Detect MSVC built-in byteswap routines
*/
#if defined(_MSC_VER)
#if !defined(MBEDTLS_BSWAP16)
#define MBEDTLS_BSWAP16 _byteswap_ushort
#endif
#if !defined(MBEDTLS_BSWAP32)
#define MBEDTLS_BSWAP32 _byteswap_ulong
#endif
#if !defined(MBEDTLS_BSWAP64)
#define MBEDTLS_BSWAP64 _byteswap_uint64
#endif
#endif /* defined(_MSC_VER) */
/* Detect armcc built-in byteswap routine */
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 410000) && !defined(MBEDTLS_BSWAP32)
#if defined(__ARM_ACLE) /* ARM Compiler 6 - earlier versions don't need a header */
#include <arm_acle.h>
#endif
#define MBEDTLS_BSWAP32 __rev
#endif
/* Detect IAR built-in byteswap routine */
#if defined(__IAR_SYSTEMS_ICC__)
#if defined(__ARM_ACLE)
#include <arm_acle.h>
#define MBEDTLS_BSWAP16(x) ((uint16_t) __rev16((uint32_t) (x)))
#define MBEDTLS_BSWAP32 __rev
#define MBEDTLS_BSWAP64 __revll
#endif
#endif
/*
* Where compiler built-ins are not present, fall back to C code that the
* compiler may be able to detect and transform into the relevant bswap or
* similar instruction.
*/
#if !defined(MBEDTLS_BSWAP16)
static inline uint16_t mbedtls_bswap16(uint16_t x)
{
return
(x & 0x00ff) << 8 |
(x & 0xff00) >> 8;
}
#define MBEDTLS_BSWAP16 mbedtls_bswap16
#endif /* !defined(MBEDTLS_BSWAP16) */
#if !defined(MBEDTLS_BSWAP32)
static inline uint32_t mbedtls_bswap32(uint32_t x)
{
return
(x & 0x000000ff) << 24 |
(x & 0x0000ff00) << 8 |
(x & 0x00ff0000) >> 8 |
(x & 0xff000000) >> 24;
}
#define MBEDTLS_BSWAP32 mbedtls_bswap32
#endif /* !defined(MBEDTLS_BSWAP32) */
#if !defined(MBEDTLS_BSWAP64)
static inline uint64_t mbedtls_bswap64(uint64_t x)
{
return
(x & 0x00000000000000ffULL) << 56 |
(x & 0x000000000000ff00ULL) << 40 |
(x & 0x0000000000ff0000ULL) << 24 |
(x & 0x00000000ff000000ULL) << 8 |
(x & 0x000000ff00000000ULL) >> 8 |
(x & 0x0000ff0000000000ULL) >> 24 |
(x & 0x00ff000000000000ULL) >> 40 |
(x & 0xff00000000000000ULL) >> 56;
}
#define MBEDTLS_BSWAP64 mbedtls_bswap64
#endif /* !defined(MBEDTLS_BSWAP64) */
#if !defined(__BYTE_ORDER__)
#if defined(__LITTLE_ENDIAN__)
/* IAR defines __xxx_ENDIAN__, but not __BYTE_ORDER__ */
#define MBEDTLS_IS_BIG_ENDIAN 0
#elif defined(__BIG_ENDIAN__)
#define MBEDTLS_IS_BIG_ENDIAN 1
#else
static const uint16_t mbedtls_byte_order_detector = { 0x100 };
#define MBEDTLS_IS_BIG_ENDIAN (*((unsigned char *) (&mbedtls_byte_order_detector)) == 0x01)
#endif
#else
#if (__BYTE_ORDER__) == (__ORDER_BIG_ENDIAN__)
#define MBEDTLS_IS_BIG_ENDIAN 1
#else
#define MBEDTLS_IS_BIG_ENDIAN 0
#endif
#endif /* !defined(__BYTE_ORDER__) */
/**
* Get the unsigned 32 bits integer corresponding to four bytes in
* big-endian order (MSB first).
*
* \param data Base address of the memory to get the four bytes from.
* \param offset Offset from \p data of the first and most significant
* byte of the four bytes to build the 32 bits unsigned
* integer from.
*/
#define MBEDTLS_GET_UINT32_BE(data, offset) \
((MBEDTLS_IS_BIG_ENDIAN) \
? mbedtls_get_unaligned_uint32((data) + (offset)) \
: MBEDTLS_BSWAP32(mbedtls_get_unaligned_uint32((data) + (offset))) \
)
/**
* Put in memory a 32 bits unsigned integer in big-endian order.
*
* \param n 32 bits unsigned integer to put in memory.
* \param data Base address of the memory where to put the 32
* bits unsigned integer in.
* \param offset Offset from \p data where to put the most significant
* byte of the 32 bits unsigned integer \p n.
*/
#define MBEDTLS_PUT_UINT32_BE(n, data, offset) \
{ \
if (MBEDTLS_IS_BIG_ENDIAN) \
{ \
mbedtls_put_unaligned_uint32((data) + (offset), (uint32_t) (n)); \
} \
else \
{ \
mbedtls_put_unaligned_uint32((data) + (offset), MBEDTLS_BSWAP32((uint32_t) (n))); \
} \
}
/**
* Get the unsigned 32 bits integer corresponding to four bytes in
* little-endian order (LSB first).
*
* \param data Base address of the memory to get the four bytes from.
* \param offset Offset from \p data of the first and least significant
* byte of the four bytes to build the 32 bits unsigned
* integer from.
*/
#define MBEDTLS_GET_UINT32_LE(data, offset) \
((MBEDTLS_IS_BIG_ENDIAN) \
? MBEDTLS_BSWAP32(mbedtls_get_unaligned_uint32((data) + (offset))) \
: mbedtls_get_unaligned_uint32((data) + (offset)) \
)
/**
* Put in memory a 32 bits unsigned integer in little-endian order.
*
* \param n 32 bits unsigned integer to put in memory.
* \param data Base address of the memory where to put the 32
* bits unsigned integer in.
* \param offset Offset from \p data where to put the least significant
* byte of the 32 bits unsigned integer \p n.
*/
#define MBEDTLS_PUT_UINT32_LE(n, data, offset) \
{ \
if (MBEDTLS_IS_BIG_ENDIAN) \
{ \
mbedtls_put_unaligned_uint32((data) + (offset), MBEDTLS_BSWAP32((uint32_t) (n))); \
} \
else \
{ \
mbedtls_put_unaligned_uint32((data) + (offset), ((uint32_t) (n))); \
} \
}
/**
* Get the unsigned 16 bits integer corresponding to two bytes in
* little-endian order (LSB first).
*
* \param data Base address of the memory to get the two bytes from.
* \param offset Offset from \p data of the first and least significant
* byte of the two bytes to build the 16 bits unsigned
* integer from.
*/
#define MBEDTLS_GET_UINT16_LE(data, offset) \
((MBEDTLS_IS_BIG_ENDIAN) \
? MBEDTLS_BSWAP16(mbedtls_get_unaligned_uint16((data) + (offset))) \
: mbedtls_get_unaligned_uint16((data) + (offset)) \
)
/**
* Put in memory a 16 bits unsigned integer in little-endian order.
*
* \param n 16 bits unsigned integer to put in memory.
* \param data Base address of the memory where to put the 16
* bits unsigned integer in.
* \param offset Offset from \p data where to put the least significant
* byte of the 16 bits unsigned integer \p n.
*/
#define MBEDTLS_PUT_UINT16_LE(n, data, offset) \
{ \
if (MBEDTLS_IS_BIG_ENDIAN) \
{ \
mbedtls_put_unaligned_uint16((data) + (offset), MBEDTLS_BSWAP16((uint16_t) (n))); \
} \
else \
{ \
mbedtls_put_unaligned_uint16((data) + (offset), (uint16_t) (n)); \
} \
}
/**
* Get the unsigned 16 bits integer corresponding to two bytes in
* big-endian order (MSB first).
*
* \param data Base address of the memory to get the two bytes from.
* \param offset Offset from \p data of the first and most significant
* byte of the two bytes to build the 16 bits unsigned
* integer from.
*/
#define MBEDTLS_GET_UINT16_BE(data, offset) \
((MBEDTLS_IS_BIG_ENDIAN) \
? mbedtls_get_unaligned_uint16((data) + (offset)) \
: MBEDTLS_BSWAP16(mbedtls_get_unaligned_uint16((data) + (offset))) \
)
/**
* Put in memory a 16 bits unsigned integer in big-endian order.
*
* \param n 16 bits unsigned integer to put in memory.
* \param data Base address of the memory where to put the 16
* bits unsigned integer in.
* \param offset Offset from \p data where to put the most significant
* byte of the 16 bits unsigned integer \p n.
*/
#define MBEDTLS_PUT_UINT16_BE(n, data, offset) \
{ \
if (MBEDTLS_IS_BIG_ENDIAN) \
{ \
mbedtls_put_unaligned_uint16((data) + (offset), (uint16_t) (n)); \
} \
else \
{ \
mbedtls_put_unaligned_uint16((data) + (offset), MBEDTLS_BSWAP16((uint16_t) (n))); \
} \
}
/**
* Get the unsigned 24 bits integer corresponding to three bytes in
* big-endian order (MSB first).
*
* \param data Base address of the memory to get the three bytes from.
* \param offset Offset from \p data of the first and most significant
* byte of the three bytes to build the 24 bits unsigned
* integer from.
*/
#define MBEDTLS_GET_UINT24_BE(data, offset) \
( \
((uint32_t) (data)[(offset)] << 16) \
| ((uint32_t) (data)[(offset) + 1] << 8) \
| ((uint32_t) (data)[(offset) + 2]) \
)
/**
* Put in memory a 24 bits unsigned integer in big-endian order.
*
* \param n 24 bits unsigned integer to put in memory.
* \param data Base address of the memory where to put the 24
* bits unsigned integer in.
* \param offset Offset from \p data where to put the most significant
* byte of the 24 bits unsigned integer \p n.
*/
#define MBEDTLS_PUT_UINT24_BE(n, data, offset) \
{ \
(data)[(offset)] = MBEDTLS_BYTE_2(n); \
(data)[(offset) + 1] = MBEDTLS_BYTE_1(n); \
(data)[(offset) + 2] = MBEDTLS_BYTE_0(n); \
}
/**
* Get the unsigned 24 bits integer corresponding to three bytes in
* little-endian order (LSB first).
*
* \param data Base address of the memory to get the three bytes from.
* \param offset Offset from \p data of the first and least significant
* byte of the three bytes to build the 24 bits unsigned
* integer from.
*/
#define MBEDTLS_GET_UINT24_LE(data, offset) \
( \
((uint32_t) (data)[(offset)]) \
| ((uint32_t) (data)[(offset) + 1] << 8) \
| ((uint32_t) (data)[(offset) + 2] << 16) \
)
/**
* Put in memory a 24 bits unsigned integer in little-endian order.
*
* \param n 24 bits unsigned integer to put in memory.
* \param data Base address of the memory where to put the 24
* bits unsigned integer in.
* \param offset Offset from \p data where to put the least significant
* byte of the 24 bits unsigned integer \p n.
*/
#define MBEDTLS_PUT_UINT24_LE(n, data, offset) \
{ \
(data)[(offset)] = MBEDTLS_BYTE_0(n); \
(data)[(offset) + 1] = MBEDTLS_BYTE_1(n); \
(data)[(offset) + 2] = MBEDTLS_BYTE_2(n); \
}
/**
* Get the unsigned 64 bits integer corresponding to eight bytes in
* big-endian order (MSB first).
*
* \param data Base address of the memory to get the eight bytes from.
* \param offset Offset from \p data of the first and most significant
* byte of the eight bytes to build the 64 bits unsigned
* integer from.
*/
#define MBEDTLS_GET_UINT64_BE(data, offset) \
((MBEDTLS_IS_BIG_ENDIAN) \
? mbedtls_get_unaligned_uint64((data) + (offset)) \
: MBEDTLS_BSWAP64(mbedtls_get_unaligned_uint64((data) + (offset))) \
)
/**
* Put in memory a 64 bits unsigned integer in big-endian order.
*
* \param n 64 bits unsigned integer to put in memory.
* \param data Base address of the memory where to put the 64
* bits unsigned integer in.
* \param offset Offset from \p data where to put the most significant
* byte of the 64 bits unsigned integer \p n.
*/
#define MBEDTLS_PUT_UINT64_BE(n, data, offset) \
{ \
if (MBEDTLS_IS_BIG_ENDIAN) \
{ \
mbedtls_put_unaligned_uint64((data) + (offset), (uint64_t) (n)); \
} \
else \
{ \
mbedtls_put_unaligned_uint64((data) + (offset), MBEDTLS_BSWAP64((uint64_t) (n))); \
} \
}
/**
* Get the unsigned 64 bits integer corresponding to eight bytes in
* little-endian order (LSB first).
*
* \param data Base address of the memory to get the eight bytes from.
* \param offset Offset from \p data of the first and least significant
* byte of the eight bytes to build the 64 bits unsigned
* integer from.
*/
#define MBEDTLS_GET_UINT64_LE(data, offset) \
((MBEDTLS_IS_BIG_ENDIAN) \
? MBEDTLS_BSWAP64(mbedtls_get_unaligned_uint64((data) + (offset))) \
: mbedtls_get_unaligned_uint64((data) + (offset)) \
)
/**
* Put in memory a 64 bits unsigned integer in little-endian order.
*
* \param n 64 bits unsigned integer to put in memory.
* \param data Base address of the memory where to put the 64
* bits unsigned integer in.
* \param offset Offset from \p data where to put the least significant
* byte of the 64 bits unsigned integer \p n.
*/
#define MBEDTLS_PUT_UINT64_LE(n, data, offset) \
{ \
if (MBEDTLS_IS_BIG_ENDIAN) \
{ \
mbedtls_put_unaligned_uint64((data) + (offset), MBEDTLS_BSWAP64((uint64_t) (n))); \
} \
else \
{ \
mbedtls_put_unaligned_uint64((data) + (offset), (uint64_t) (n)); \
} \
}
#endif /* MBEDTLS_LIBRARY_ALIGNMENT_H */

969
thirdparty/mbedtls/library/aria.c vendored Normal file
View File

@@ -0,0 +1,969 @@
/*
* ARIA implementation
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
/*
* This implementation is based on the following standards:
* [1] http://210.104.33.10/ARIA/doc/ARIA-specification-e.pdf
* [2] https://tools.ietf.org/html/rfc5794
*/
#include "common.h"
#if defined(MBEDTLS_ARIA_C)
#include "mbedtls/aria.h"
#include <string.h>
#include "mbedtls/platform.h"
#if !defined(MBEDTLS_ARIA_ALT)
#include "mbedtls/platform_util.h"
/*
* modify byte order: ( A B C D ) -> ( B A D C ), i.e. swap pairs of bytes
*
* This is submatrix P1 in [1] Appendix B.1
*
* Common compilers fail to translate this to minimal number of instructions,
* so let's provide asm versions for common platforms with C fallback.
*/
#if defined(MBEDTLS_HAVE_ASM)
#if defined(__arm__) /* rev16 available from v6 up */
/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */
#if defined(__GNUC__) && \
(!defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000) && \
__ARM_ARCH >= 6
static inline uint32_t aria_p1(uint32_t x)
{
uint32_t r;
__asm("rev16 %0, %1" : "=l" (r) : "l" (x));
return r;
}
#define ARIA_P1 aria_p1
#elif defined(__ARMCC_VERSION) && __ARMCC_VERSION < 6000000 && \
(__TARGET_ARCH_ARM >= 6 || __TARGET_ARCH_THUMB >= 3)
static inline uint32_t aria_p1(uint32_t x)
{
uint32_t r;
__asm("rev16 r, x");
return r;
}
#define ARIA_P1 aria_p1
#endif
#endif /* arm */
#if defined(__GNUC__) && \
defined(__i386__) || defined(__amd64__) || defined(__x86_64__)
/* I couldn't find an Intel equivalent of rev16, so two instructions */
#define ARIA_P1(x) ARIA_P2(ARIA_P3(x))
#endif /* x86 gnuc */
#endif /* MBEDTLS_HAVE_ASM && GNUC */
#if !defined(ARIA_P1)
#define ARIA_P1(x) ((((x) >> 8) & 0x00FF00FF) ^ (((x) & 0x00FF00FF) << 8))
#endif
/*
* modify byte order: ( A B C D ) -> ( C D A B ), i.e. rotate by 16 bits
*
* This is submatrix P2 in [1] Appendix B.1
*
* Common compilers will translate this to a single instruction.
*/
#define ARIA_P2(x) (((x) >> 16) ^ ((x) << 16))
/*
* modify byte order: ( A B C D ) -> ( D C B A ), i.e. change endianness
*
* This is submatrix P3 in [1] Appendix B.1
*/
#define ARIA_P3(x) MBEDTLS_BSWAP32(x)
/*
* ARIA Affine Transform
* (a, b, c, d) = state in/out
*
* If we denote the first byte of input by 0, ..., the last byte by f,
* then inputs are: a = 0123, b = 4567, c = 89ab, d = cdef.
*
* Reading [1] 2.4 or [2] 2.4.3 in columns and performing simple
* rearrangements on adjacent pairs, output is:
*
* a = 3210 + 4545 + 6767 + 88aa + 99bb + dccd + effe
* = 3210 + 4567 + 6745 + 89ab + 98ba + dcfe + efcd
* b = 0101 + 2323 + 5476 + 8998 + baab + eecc + ffdd
* = 0123 + 2301 + 5476 + 89ab + ba98 + efcd + fedc
* c = 0022 + 1133 + 4554 + 7667 + ab89 + dcdc + fefe
* = 0123 + 1032 + 4567 + 7654 + ab89 + dcfe + fedc
* d = 1001 + 2332 + 6644 + 7755 + 9898 + baba + cdef
* = 1032 + 2301 + 6745 + 7654 + 98ba + ba98 + cdef
*
* Note: another presentation of the A transform can be found as the first
* half of App. B.1 in [1] in terms of 4-byte operators P1, P2, P3 and P4.
* The implementation below uses only P1 and P2 as they are sufficient.
*/
static inline void aria_a(uint32_t *a, uint32_t *b,
uint32_t *c, uint32_t *d)
{
uint32_t ta, tb, tc;
ta = *b; // 4567
*b = *a; // 0123
*a = ARIA_P2(ta); // 6745
tb = ARIA_P2(*d); // efcd
*d = ARIA_P1(*c); // 98ba
*c = ARIA_P1(tb); // fedc
ta ^= *d; // 4567+98ba
tc = ARIA_P2(*b); // 2301
ta = ARIA_P1(ta) ^ tc ^ *c; // 2301+5476+89ab+fedc
tb ^= ARIA_P2(*d); // ba98+efcd
tc ^= ARIA_P1(*a); // 2301+7654
*b ^= ta ^ tb; // 0123+2301+5476+89ab+ba98+efcd+fedc OUT
tb = ARIA_P2(tb) ^ ta; // 2301+5476+89ab+98ba+cdef+fedc
*a ^= ARIA_P1(tb); // 3210+4567+6745+89ab+98ba+dcfe+efcd OUT
ta = ARIA_P2(ta); // 0123+7654+ab89+dcfe
*d ^= ARIA_P1(ta) ^ tc; // 1032+2301+6745+7654+98ba+ba98+cdef OUT
tc = ARIA_P2(tc); // 0123+5476
*c ^= ARIA_P1(tc) ^ ta; // 0123+1032+4567+7654+ab89+dcfe+fedc OUT
}
/*
* ARIA Substitution Layer SL1 / SL2
* (a, b, c, d) = state in/out
* (sa, sb, sc, sd) = 256 8-bit S-Boxes (see below)
*
* By passing sb1, sb2, is1, is2 as S-Boxes you get SL1
* By passing is1, is2, sb1, sb2 as S-Boxes you get SL2
*/
static inline void aria_sl(uint32_t *a, uint32_t *b,
uint32_t *c, uint32_t *d,
const uint8_t sa[256], const uint8_t sb[256],
const uint8_t sc[256], const uint8_t sd[256])
{
*a = ((uint32_t) sa[MBEDTLS_BYTE_0(*a)]) ^
(((uint32_t) sb[MBEDTLS_BYTE_1(*a)]) << 8) ^
(((uint32_t) sc[MBEDTLS_BYTE_2(*a)]) << 16) ^
(((uint32_t) sd[MBEDTLS_BYTE_3(*a)]) << 24);
*b = ((uint32_t) sa[MBEDTLS_BYTE_0(*b)]) ^
(((uint32_t) sb[MBEDTLS_BYTE_1(*b)]) << 8) ^
(((uint32_t) sc[MBEDTLS_BYTE_2(*b)]) << 16) ^
(((uint32_t) sd[MBEDTLS_BYTE_3(*b)]) << 24);
*c = ((uint32_t) sa[MBEDTLS_BYTE_0(*c)]) ^
(((uint32_t) sb[MBEDTLS_BYTE_1(*c)]) << 8) ^
(((uint32_t) sc[MBEDTLS_BYTE_2(*c)]) << 16) ^
(((uint32_t) sd[MBEDTLS_BYTE_3(*c)]) << 24);
*d = ((uint32_t) sa[MBEDTLS_BYTE_0(*d)]) ^
(((uint32_t) sb[MBEDTLS_BYTE_1(*d)]) << 8) ^
(((uint32_t) sc[MBEDTLS_BYTE_2(*d)]) << 16) ^
(((uint32_t) sd[MBEDTLS_BYTE_3(*d)]) << 24);
}
/*
* S-Boxes
*/
static const uint8_t aria_sb1[256] =
{
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B,
0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26,
0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2,
0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED,
0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F,
0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC,
0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14,
0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D,
0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F,
0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11,
0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F,
0xB0, 0x54, 0xBB, 0x16
};
static const uint8_t aria_sb2[256] =
{
0xE2, 0x4E, 0x54, 0xFC, 0x94, 0xC2, 0x4A, 0xCC, 0x62, 0x0D, 0x6A, 0x46,
0x3C, 0x4D, 0x8B, 0xD1, 0x5E, 0xFA, 0x64, 0xCB, 0xB4, 0x97, 0xBE, 0x2B,
0xBC, 0x77, 0x2E, 0x03, 0xD3, 0x19, 0x59, 0xC1, 0x1D, 0x06, 0x41, 0x6B,
0x55, 0xF0, 0x99, 0x69, 0xEA, 0x9C, 0x18, 0xAE, 0x63, 0xDF, 0xE7, 0xBB,
0x00, 0x73, 0x66, 0xFB, 0x96, 0x4C, 0x85, 0xE4, 0x3A, 0x09, 0x45, 0xAA,
0x0F, 0xEE, 0x10, 0xEB, 0x2D, 0x7F, 0xF4, 0x29, 0xAC, 0xCF, 0xAD, 0x91,
0x8D, 0x78, 0xC8, 0x95, 0xF9, 0x2F, 0xCE, 0xCD, 0x08, 0x7A, 0x88, 0x38,
0x5C, 0x83, 0x2A, 0x28, 0x47, 0xDB, 0xB8, 0xC7, 0x93, 0xA4, 0x12, 0x53,
0xFF, 0x87, 0x0E, 0x31, 0x36, 0x21, 0x58, 0x48, 0x01, 0x8E, 0x37, 0x74,
0x32, 0xCA, 0xE9, 0xB1, 0xB7, 0xAB, 0x0C, 0xD7, 0xC4, 0x56, 0x42, 0x26,
0x07, 0x98, 0x60, 0xD9, 0xB6, 0xB9, 0x11, 0x40, 0xEC, 0x20, 0x8C, 0xBD,
0xA0, 0xC9, 0x84, 0x04, 0x49, 0x23, 0xF1, 0x4F, 0x50, 0x1F, 0x13, 0xDC,
0xD8, 0xC0, 0x9E, 0x57, 0xE3, 0xC3, 0x7B, 0x65, 0x3B, 0x02, 0x8F, 0x3E,
0xE8, 0x25, 0x92, 0xE5, 0x15, 0xDD, 0xFD, 0x17, 0xA9, 0xBF, 0xD4, 0x9A,
0x7E, 0xC5, 0x39, 0x67, 0xFE, 0x76, 0x9D, 0x43, 0xA7, 0xE1, 0xD0, 0xF5,
0x68, 0xF2, 0x1B, 0x34, 0x70, 0x05, 0xA3, 0x8A, 0xD5, 0x79, 0x86, 0xA8,
0x30, 0xC6, 0x51, 0x4B, 0x1E, 0xA6, 0x27, 0xF6, 0x35, 0xD2, 0x6E, 0x24,
0x16, 0x82, 0x5F, 0xDA, 0xE6, 0x75, 0xA2, 0xEF, 0x2C, 0xB2, 0x1C, 0x9F,
0x5D, 0x6F, 0x80, 0x0A, 0x72, 0x44, 0x9B, 0x6C, 0x90, 0x0B, 0x5B, 0x33,
0x7D, 0x5A, 0x52, 0xF3, 0x61, 0xA1, 0xF7, 0xB0, 0xD6, 0x3F, 0x7C, 0x6D,
0xED, 0x14, 0xE0, 0xA5, 0x3D, 0x22, 0xB3, 0xF8, 0x89, 0xDE, 0x71, 0x1A,
0xAF, 0xBA, 0xB5, 0x81
};
static const uint8_t aria_is1[256] =
{
0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E,
0x81, 0xF3, 0xD7, 0xFB, 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, 0x54, 0x7B, 0x94, 0x32,
0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49,
0x6D, 0x8B, 0xD1, 0x25, 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,
0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, 0x6C, 0x70, 0x48, 0x50,
0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05,
0xB8, 0xB3, 0x45, 0x06, 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,
0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, 0x3A, 0x91, 0x11, 0x41,
0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8,
0x1C, 0x75, 0xDF, 0x6E, 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,
0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, 0xFC, 0x56, 0x3E, 0x4B,
0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59,
0x27, 0x80, 0xEC, 0x5F, 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, 0xA0, 0xE0, 0x3B, 0x4D,
0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63,
0x55, 0x21, 0x0C, 0x7D
};
static const uint8_t aria_is2[256] =
{
0x30, 0x68, 0x99, 0x1B, 0x87, 0xB9, 0x21, 0x78, 0x50, 0x39, 0xDB, 0xE1,
0x72, 0x09, 0x62, 0x3C, 0x3E, 0x7E, 0x5E, 0x8E, 0xF1, 0xA0, 0xCC, 0xA3,
0x2A, 0x1D, 0xFB, 0xB6, 0xD6, 0x20, 0xC4, 0x8D, 0x81, 0x65, 0xF5, 0x89,
0xCB, 0x9D, 0x77, 0xC6, 0x57, 0x43, 0x56, 0x17, 0xD4, 0x40, 0x1A, 0x4D,
0xC0, 0x63, 0x6C, 0xE3, 0xB7, 0xC8, 0x64, 0x6A, 0x53, 0xAA, 0x38, 0x98,
0x0C, 0xF4, 0x9B, 0xED, 0x7F, 0x22, 0x76, 0xAF, 0xDD, 0x3A, 0x0B, 0x58,
0x67, 0x88, 0x06, 0xC3, 0x35, 0x0D, 0x01, 0x8B, 0x8C, 0xC2, 0xE6, 0x5F,
0x02, 0x24, 0x75, 0x93, 0x66, 0x1E, 0xE5, 0xE2, 0x54, 0xD8, 0x10, 0xCE,
0x7A, 0xE8, 0x08, 0x2C, 0x12, 0x97, 0x32, 0xAB, 0xB4, 0x27, 0x0A, 0x23,
0xDF, 0xEF, 0xCA, 0xD9, 0xB8, 0xFA, 0xDC, 0x31, 0x6B, 0xD1, 0xAD, 0x19,
0x49, 0xBD, 0x51, 0x96, 0xEE, 0xE4, 0xA8, 0x41, 0xDA, 0xFF, 0xCD, 0x55,
0x86, 0x36, 0xBE, 0x61, 0x52, 0xF8, 0xBB, 0x0E, 0x82, 0x48, 0x69, 0x9A,
0xE0, 0x47, 0x9E, 0x5C, 0x04, 0x4B, 0x34, 0x15, 0x79, 0x26, 0xA7, 0xDE,
0x29, 0xAE, 0x92, 0xD7, 0x84, 0xE9, 0xD2, 0xBA, 0x5D, 0xF3, 0xC5, 0xB0,
0xBF, 0xA4, 0x3B, 0x71, 0x44, 0x46, 0x2B, 0xFC, 0xEB, 0x6F, 0xD5, 0xF6,
0x14, 0xFE, 0x7C, 0x70, 0x5A, 0x7D, 0xFD, 0x2F, 0x18, 0x83, 0x16, 0xA5,
0x91, 0x1F, 0x05, 0x95, 0x74, 0xA9, 0xC1, 0x5B, 0x4A, 0x85, 0x6D, 0x13,
0x07, 0x4F, 0x4E, 0x45, 0xB2, 0x0F, 0xC9, 0x1C, 0xA6, 0xBC, 0xEC, 0x73,
0x90, 0x7B, 0xCF, 0x59, 0x8F, 0xA1, 0xF9, 0x2D, 0xF2, 0xB1, 0x00, 0x94,
0x37, 0x9F, 0xD0, 0x2E, 0x9C, 0x6E, 0x28, 0x3F, 0x80, 0xF0, 0x3D, 0xD3,
0x25, 0x8A, 0xB5, 0xE7, 0x42, 0xB3, 0xC7, 0xEA, 0xF7, 0x4C, 0x11, 0x33,
0x03, 0xA2, 0xAC, 0x60
};
/*
* Helper for key schedule: r = FO( p, k ) ^ x
*/
static void aria_fo_xor(uint32_t r[4], const uint32_t p[4],
const uint32_t k[4], const uint32_t x[4])
{
uint32_t a, b, c, d;
a = p[0] ^ k[0];
b = p[1] ^ k[1];
c = p[2] ^ k[2];
d = p[3] ^ k[3];
aria_sl(&a, &b, &c, &d, aria_sb1, aria_sb2, aria_is1, aria_is2);
aria_a(&a, &b, &c, &d);
r[0] = a ^ x[0];
r[1] = b ^ x[1];
r[2] = c ^ x[2];
r[3] = d ^ x[3];
}
/*
* Helper for key schedule: r = FE( p, k ) ^ x
*/
static void aria_fe_xor(uint32_t r[4], const uint32_t p[4],
const uint32_t k[4], const uint32_t x[4])
{
uint32_t a, b, c, d;
a = p[0] ^ k[0];
b = p[1] ^ k[1];
c = p[2] ^ k[2];
d = p[3] ^ k[3];
aria_sl(&a, &b, &c, &d, aria_is1, aria_is2, aria_sb1, aria_sb2);
aria_a(&a, &b, &c, &d);
r[0] = a ^ x[0];
r[1] = b ^ x[1];
r[2] = c ^ x[2];
r[3] = d ^ x[3];
}
/*
* Big endian 128-bit rotation: r = a ^ (b <<< n), used only in key setup.
*
* We chose to store bytes into 32-bit words in little-endian format (see
* MBEDTLS_GET_UINT32_LE / MBEDTLS_PUT_UINT32_LE ) so we need to reverse
* bytes here.
*/
static void aria_rot128(uint32_t r[4], const uint32_t a[4],
const uint32_t b[4], uint8_t n)
{
uint8_t i, j;
uint32_t t, u;
const uint8_t n1 = n % 32; // bit offset
const uint8_t n2 = n1 ? 32 - n1 : 0; // reverse bit offset
j = (n / 32) % 4; // initial word offset
t = ARIA_P3(b[j]); // big endian
for (i = 0; i < 4; i++) {
j = (j + 1) % 4; // get next word, big endian
u = ARIA_P3(b[j]);
t <<= n1; // rotate
t |= u >> n2;
t = ARIA_P3(t); // back to little endian
r[i] = a[i] ^ t; // store
t = u; // move to next word
}
}
/*
* Set encryption key
*/
int mbedtls_aria_setkey_enc(mbedtls_aria_context *ctx,
const unsigned char *key, unsigned int keybits)
{
/* round constant masks */
const uint32_t rc[3][4] =
{
{ 0xB7C17C51, 0x940A2227, 0xE8AB13FE, 0xE06E9AFA },
{ 0xCC4AB16D, 0x20C8219E, 0xD5B128FF, 0xB0E25DEF },
{ 0x1D3792DB, 0x70E92621, 0x75972403, 0x0EC9E804 }
};
int i;
uint32_t w[4][4], *w2;
if (keybits != 128 && keybits != 192 && keybits != 256) {
return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA;
}
/* Copy key to W0 (and potential remainder to W1) */
w[0][0] = MBEDTLS_GET_UINT32_LE(key, 0);
w[0][1] = MBEDTLS_GET_UINT32_LE(key, 4);
w[0][2] = MBEDTLS_GET_UINT32_LE(key, 8);
w[0][3] = MBEDTLS_GET_UINT32_LE(key, 12);
memset(w[1], 0, 16);
if (keybits >= 192) {
w[1][0] = MBEDTLS_GET_UINT32_LE(key, 16); // 192 bit key
w[1][1] = MBEDTLS_GET_UINT32_LE(key, 20);
}
if (keybits == 256) {
w[1][2] = MBEDTLS_GET_UINT32_LE(key, 24); // 256 bit key
w[1][3] = MBEDTLS_GET_UINT32_LE(key, 28);
}
i = (keybits - 128) >> 6; // index: 0, 1, 2
ctx->nr = 12 + 2 * i; // no. rounds: 12, 14, 16
aria_fo_xor(w[1], w[0], rc[i], w[1]); // W1 = FO(W0, CK1) ^ KR
i = i < 2 ? i + 1 : 0;
aria_fe_xor(w[2], w[1], rc[i], w[0]); // W2 = FE(W1, CK2) ^ W0
i = i < 2 ? i + 1 : 0;
aria_fo_xor(w[3], w[2], rc[i], w[1]); // W3 = FO(W2, CK3) ^ W1
for (i = 0; i < 4; i++) { // create round keys
w2 = w[(i + 1) & 3];
aria_rot128(ctx->rk[i], w[i], w2, 128 - 19);
aria_rot128(ctx->rk[i + 4], w[i], w2, 128 - 31);
aria_rot128(ctx->rk[i + 8], w[i], w2, 61);
aria_rot128(ctx->rk[i + 12], w[i], w2, 31);
}
aria_rot128(ctx->rk[16], w[0], w[1], 19);
/* w holds enough info to reconstruct the round keys */
mbedtls_platform_zeroize(w, sizeof(w));
return 0;
}
/*
* Set decryption key
*/
#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
int mbedtls_aria_setkey_dec(mbedtls_aria_context *ctx,
const unsigned char *key, unsigned int keybits)
{
int i, j, k, ret;
ret = mbedtls_aria_setkey_enc(ctx, key, keybits);
if (ret != 0) {
return ret;
}
/* flip the order of round keys */
for (i = 0, j = ctx->nr; i < j; i++, j--) {
for (k = 0; k < 4; k++) {
uint32_t t = ctx->rk[i][k];
ctx->rk[i][k] = ctx->rk[j][k];
ctx->rk[j][k] = t;
}
}
/* apply affine transform to middle keys */
for (i = 1; i < ctx->nr; i++) {
aria_a(&ctx->rk[i][0], &ctx->rk[i][1],
&ctx->rk[i][2], &ctx->rk[i][3]);
}
return 0;
}
#endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */
/*
* Encrypt a block
*/
int mbedtls_aria_crypt_ecb(mbedtls_aria_context *ctx,
const unsigned char input[MBEDTLS_ARIA_BLOCKSIZE],
unsigned char output[MBEDTLS_ARIA_BLOCKSIZE])
{
int i;
uint32_t a, b, c, d;
a = MBEDTLS_GET_UINT32_LE(input, 0);
b = MBEDTLS_GET_UINT32_LE(input, 4);
c = MBEDTLS_GET_UINT32_LE(input, 8);
d = MBEDTLS_GET_UINT32_LE(input, 12);
i = 0;
while (1) {
a ^= ctx->rk[i][0];
b ^= ctx->rk[i][1];
c ^= ctx->rk[i][2];
d ^= ctx->rk[i][3];
i++;
aria_sl(&a, &b, &c, &d, aria_sb1, aria_sb2, aria_is1, aria_is2);
aria_a(&a, &b, &c, &d);
a ^= ctx->rk[i][0];
b ^= ctx->rk[i][1];
c ^= ctx->rk[i][2];
d ^= ctx->rk[i][3];
i++;
aria_sl(&a, &b, &c, &d, aria_is1, aria_is2, aria_sb1, aria_sb2);
if (i >= ctx->nr) {
break;
}
aria_a(&a, &b, &c, &d);
}
/* final key mixing */
a ^= ctx->rk[i][0];
b ^= ctx->rk[i][1];
c ^= ctx->rk[i][2];
d ^= ctx->rk[i][3];
MBEDTLS_PUT_UINT32_LE(a, output, 0);
MBEDTLS_PUT_UINT32_LE(b, output, 4);
MBEDTLS_PUT_UINT32_LE(c, output, 8);
MBEDTLS_PUT_UINT32_LE(d, output, 12);
return 0;
}
/* Initialize context */
void mbedtls_aria_init(mbedtls_aria_context *ctx)
{
memset(ctx, 0, sizeof(mbedtls_aria_context));
}
/* Clear context */
void mbedtls_aria_free(mbedtls_aria_context *ctx)
{
if (ctx == NULL) {
return;
}
mbedtls_platform_zeroize(ctx, sizeof(mbedtls_aria_context));
}
#if defined(MBEDTLS_CIPHER_MODE_CBC)
/*
* ARIA-CBC buffer encryption/decryption
*/
int mbedtls_aria_crypt_cbc(mbedtls_aria_context *ctx,
int mode,
size_t length,
unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE],
const unsigned char *input,
unsigned char *output)
{
unsigned char temp[MBEDTLS_ARIA_BLOCKSIZE];
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;
}
if (mode == MBEDTLS_ARIA_DECRYPT) {
while (length > 0) {
memcpy(temp, input, MBEDTLS_ARIA_BLOCKSIZE);
mbedtls_aria_crypt_ecb(ctx, input, output);
mbedtls_xor(output, output, iv, MBEDTLS_ARIA_BLOCKSIZE);
memcpy(iv, temp, MBEDTLS_ARIA_BLOCKSIZE);
input += MBEDTLS_ARIA_BLOCKSIZE;
output += MBEDTLS_ARIA_BLOCKSIZE;
length -= MBEDTLS_ARIA_BLOCKSIZE;
}
} else {
while (length > 0) {
mbedtls_xor(output, input, iv, MBEDTLS_ARIA_BLOCKSIZE);
mbedtls_aria_crypt_ecb(ctx, output, output);
memcpy(iv, output, MBEDTLS_ARIA_BLOCKSIZE);
input += MBEDTLS_ARIA_BLOCKSIZE;
output += MBEDTLS_ARIA_BLOCKSIZE;
length -= MBEDTLS_ARIA_BLOCKSIZE;
}
}
return 0;
}
#endif /* MBEDTLS_CIPHER_MODE_CBC */
#if defined(MBEDTLS_CIPHER_MODE_CFB)
/*
* ARIA-CFB128 buffer encryption/decryption
*/
int mbedtls_aria_crypt_cfb128(mbedtls_aria_context *ctx,
int mode,
size_t length,
size_t *iv_off,
unsigned char iv[MBEDTLS_ARIA_BLOCKSIZE],
const unsigned char *input,
unsigned char *output)
{
unsigned char c;
size_t n;
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. */
if (n >= MBEDTLS_ARIA_BLOCKSIZE) {
return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA;
}
if (mode == MBEDTLS_ARIA_DECRYPT) {
while (length--) {
if (n == 0) {
mbedtls_aria_crypt_ecb(ctx, iv, iv);
}
c = *input++;
*output++ = c ^ iv[n];
iv[n] = c;
n = (n + 1) & 0x0F;
}
} else {
while (length--) {
if (n == 0) {
mbedtls_aria_crypt_ecb(ctx, iv, iv);
}
iv[n] = *output++ = (unsigned char) (iv[n] ^ *input++);
n = (n + 1) & 0x0F;
}
}
*iv_off = n;
return 0;
}
#endif /* MBEDTLS_CIPHER_MODE_CFB */
#if defined(MBEDTLS_CIPHER_MODE_CTR)
/*
* ARIA-CTR buffer encryption/decryption
*/
int mbedtls_aria_crypt_ctr(mbedtls_aria_context *ctx,
size_t length,
size_t *nc_off,
unsigned char nonce_counter[MBEDTLS_ARIA_BLOCKSIZE],
unsigned char stream_block[MBEDTLS_ARIA_BLOCKSIZE],
const unsigned char *input,
unsigned char *output)
{
int c, i;
size_t n;
n = *nc_off;
/* An overly large value of n can lead to an unlimited
* buffer overflow. */
if (n >= MBEDTLS_ARIA_BLOCKSIZE) {
return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA;
}
while (length--) {
if (n == 0) {
mbedtls_aria_crypt_ecb(ctx, nonce_counter,
stream_block);
for (i = MBEDTLS_ARIA_BLOCKSIZE; i > 0; i--) {
if (++nonce_counter[i - 1] != 0) {
break;
}
}
}
c = *input++;
*output++ = (unsigned char) (c ^ stream_block[n]);
n = (n + 1) & 0x0F;
}
*nc_off = n;
return 0;
}
#endif /* MBEDTLS_CIPHER_MODE_CTR */
#endif /* !MBEDTLS_ARIA_ALT */
#if defined(MBEDTLS_SELF_TEST)
/*
* Basic ARIA ECB test vectors from RFC 5794
*/
static const uint8_t aria_test1_ecb_key[32] = // test key
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 128 bit
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, // 192 bit
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F // 256 bit
};
static const uint8_t aria_test1_ecb_pt[MBEDTLS_ARIA_BLOCKSIZE] = // plaintext
{
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // same for all
0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF // key sizes
};
static const uint8_t aria_test1_ecb_ct[3][MBEDTLS_ARIA_BLOCKSIZE] = // ciphertext
{
{ 0xD7, 0x18, 0xFB, 0xD6, 0xAB, 0x64, 0x4C, 0x73, // 128 bit
0x9D, 0xA9, 0x5F, 0x3B, 0xE6, 0x45, 0x17, 0x78 },
{ 0x26, 0x44, 0x9C, 0x18, 0x05, 0xDB, 0xE7, 0xAA, // 192 bit
0x25, 0xA4, 0x68, 0xCE, 0x26, 0x3A, 0x9E, 0x79 },
{ 0xF9, 0x2B, 0xD7, 0xC7, 0x9F, 0xB7, 0x2E, 0x2F, // 256 bit
0x2B, 0x8F, 0x80, 0xC1, 0x97, 0x2D, 0x24, 0xFC }
};
/*
* Mode tests from "Test Vectors for ARIA" Version 1.0
* http://210.104.33.10/ARIA/doc/ARIA-testvector-e.pdf
*/
#if (defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB) || \
defined(MBEDTLS_CIPHER_MODE_CTR))
static const uint8_t aria_test2_key[32] =
{
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // 128 bit
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, // 192 bit
0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff // 256 bit
};
static const uint8_t aria_test2_pt[48] =
{
0x11, 0x11, 0x11, 0x11, 0xaa, 0xaa, 0xaa, 0xaa, // same for all
0x11, 0x11, 0x11, 0x11, 0xbb, 0xbb, 0xbb, 0xbb,
0x11, 0x11, 0x11, 0x11, 0xcc, 0xcc, 0xcc, 0xcc,
0x11, 0x11, 0x11, 0x11, 0xdd, 0xdd, 0xdd, 0xdd,
0x22, 0x22, 0x22, 0x22, 0xaa, 0xaa, 0xaa, 0xaa,
0x22, 0x22, 0x22, 0x22, 0xbb, 0xbb, 0xbb, 0xbb,
};
#endif
#if (defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB))
static const uint8_t aria_test2_iv[MBEDTLS_ARIA_BLOCKSIZE] =
{
0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69, 0x78, // same for CBC, CFB
0x87, 0x96, 0xa5, 0xb4, 0xc3, 0xd2, 0xe1, 0xf0 // CTR has zero IV
};
#endif
#if defined(MBEDTLS_CIPHER_MODE_CBC)
static const uint8_t aria_test2_cbc_ct[3][48] = // CBC ciphertext
{
{ 0x49, 0xd6, 0x18, 0x60, 0xb1, 0x49, 0x09, 0x10, // 128-bit key
0x9c, 0xef, 0x0d, 0x22, 0xa9, 0x26, 0x81, 0x34,
0xfa, 0xdf, 0x9f, 0xb2, 0x31, 0x51, 0xe9, 0x64,
0x5f, 0xba, 0x75, 0x01, 0x8b, 0xdb, 0x15, 0x38,
0xb5, 0x33, 0x34, 0x63, 0x4b, 0xbf, 0x7d, 0x4c,
0xd4, 0xb5, 0x37, 0x70, 0x33, 0x06, 0x0c, 0x15 },
{ 0xaf, 0xe6, 0xcf, 0x23, 0x97, 0x4b, 0x53, 0x3c, // 192-bit key
0x67, 0x2a, 0x82, 0x62, 0x64, 0xea, 0x78, 0x5f,
0x4e, 0x4f, 0x7f, 0x78, 0x0d, 0xc7, 0xf3, 0xf1,
0xe0, 0x96, 0x2b, 0x80, 0x90, 0x23, 0x86, 0xd5,
0x14, 0xe9, 0xc3, 0xe7, 0x72, 0x59, 0xde, 0x92,
0xdd, 0x11, 0x02, 0xff, 0xab, 0x08, 0x6c, 0x1e },
{ 0x52, 0x3a, 0x8a, 0x80, 0x6a, 0xe6, 0x21, 0xf1, // 256-bit key
0x55, 0xfd, 0xd2, 0x8d, 0xbc, 0x34, 0xe1, 0xab,
0x7b, 0x9b, 0x42, 0x43, 0x2a, 0xd8, 0xb2, 0xef,
0xb9, 0x6e, 0x23, 0xb1, 0x3f, 0x0a, 0x6e, 0x52,
0xf3, 0x61, 0x85, 0xd5, 0x0a, 0xd0, 0x02, 0xc5,
0xf6, 0x01, 0xbe, 0xe5, 0x49, 0x3f, 0x11, 0x8b }
};
#endif /* MBEDTLS_CIPHER_MODE_CBC */
#if defined(MBEDTLS_CIPHER_MODE_CFB)
static const uint8_t aria_test2_cfb_ct[3][48] = // CFB ciphertext
{
{ 0x37, 0x20, 0xe5, 0x3b, 0xa7, 0xd6, 0x15, 0x38, // 128-bit key
0x34, 0x06, 0xb0, 0x9f, 0x0a, 0x05, 0xa2, 0x00,
0xc0, 0x7c, 0x21, 0xe6, 0x37, 0x0f, 0x41, 0x3a,
0x5d, 0x13, 0x25, 0x00, 0xa6, 0x82, 0x85, 0x01,
0x7c, 0x61, 0xb4, 0x34, 0xc7, 0xb7, 0xca, 0x96,
0x85, 0xa5, 0x10, 0x71, 0x86, 0x1e, 0x4d, 0x4b },
{ 0x41, 0x71, 0xf7, 0x19, 0x2b, 0xf4, 0x49, 0x54, // 192-bit key
0x94, 0xd2, 0x73, 0x61, 0x29, 0x64, 0x0f, 0x5c,
0x4d, 0x87, 0xa9, 0xa2, 0x13, 0x66, 0x4c, 0x94,
0x48, 0x47, 0x7c, 0x6e, 0xcc, 0x20, 0x13, 0x59,
0x8d, 0x97, 0x66, 0x95, 0x2d, 0xd8, 0xc3, 0x86,
0x8f, 0x17, 0xe3, 0x6e, 0xf6, 0x6f, 0xd8, 0x4b },
{ 0x26, 0x83, 0x47, 0x05, 0xb0, 0xf2, 0xc0, 0xe2, // 256-bit key
0x58, 0x8d, 0x4a, 0x7f, 0x09, 0x00, 0x96, 0x35,
0xf2, 0x8b, 0xb9, 0x3d, 0x8c, 0x31, 0xf8, 0x70,
0xec, 0x1e, 0x0b, 0xdb, 0x08, 0x2b, 0x66, 0xfa,
0x40, 0x2d, 0xd9, 0xc2, 0x02, 0xbe, 0x30, 0x0c,
0x45, 0x17, 0xd1, 0x96, 0xb1, 0x4d, 0x4c, 0xe1 }
};
#endif /* MBEDTLS_CIPHER_MODE_CFB */
#if defined(MBEDTLS_CIPHER_MODE_CTR)
static const uint8_t aria_test2_ctr_ct[3][48] = // CTR ciphertext
{
{ 0xac, 0x5d, 0x7d, 0xe8, 0x05, 0xa0, 0xbf, 0x1c, // 128-bit key
0x57, 0xc8, 0x54, 0x50, 0x1a, 0xf6, 0x0f, 0xa1,
0x14, 0x97, 0xe2, 0xa3, 0x45, 0x19, 0xde, 0xa1,
0x56, 0x9e, 0x91, 0xe5, 0xb5, 0xcc, 0xae, 0x2f,
0xf3, 0xbf, 0xa1, 0xbf, 0x97, 0x5f, 0x45, 0x71,
0xf4, 0x8b, 0xe1, 0x91, 0x61, 0x35, 0x46, 0xc3 },
{ 0x08, 0x62, 0x5c, 0xa8, 0xfe, 0x56, 0x9c, 0x19, // 192-bit key
0xba, 0x7a, 0xf3, 0x76, 0x0a, 0x6e, 0xd1, 0xce,
0xf4, 0xd1, 0x99, 0x26, 0x3e, 0x99, 0x9d, 0xde,
0x14, 0x08, 0x2d, 0xbb, 0xa7, 0x56, 0x0b, 0x79,
0xa4, 0xc6, 0xb4, 0x56, 0xb8, 0x70, 0x7d, 0xce,
0x75, 0x1f, 0x98, 0x54, 0xf1, 0x88, 0x93, 0xdf },
{ 0x30, 0x02, 0x6c, 0x32, 0x96, 0x66, 0x14, 0x17, // 256-bit key
0x21, 0x17, 0x8b, 0x99, 0xc0, 0xa1, 0xf1, 0xb2,
0xf0, 0x69, 0x40, 0x25, 0x3f, 0x7b, 0x30, 0x89,
0xe2, 0xa3, 0x0e, 0xa8, 0x6a, 0xa3, 0xc8, 0x8f,
0x59, 0x40, 0xf0, 0x5a, 0xd7, 0xee, 0x41, 0xd7,
0x13, 0x47, 0xbb, 0x72, 0x61, 0xe3, 0x48, 0xf1 }
};
#endif /* MBEDTLS_CIPHER_MODE_CFB */
#define ARIA_SELF_TEST_ASSERT(cond) \
do { \
if (cond) { \
if (verbose) \
mbedtls_printf("failed\n"); \
goto exit; \
} else { \
if (verbose) \
mbedtls_printf("passed\n"); \
} \
} while (0)
/*
* Checkup routine
*/
int mbedtls_aria_self_test(int verbose)
{
int i;
uint8_t blk[MBEDTLS_ARIA_BLOCKSIZE];
mbedtls_aria_context ctx;
int ret = 1;
#if (defined(MBEDTLS_CIPHER_MODE_CFB) || defined(MBEDTLS_CIPHER_MODE_CTR))
size_t j;
#endif
#if (defined(MBEDTLS_CIPHER_MODE_CBC) || \
defined(MBEDTLS_CIPHER_MODE_CFB) || \
defined(MBEDTLS_CIPHER_MODE_CTR))
uint8_t buf[48], iv[MBEDTLS_ARIA_BLOCKSIZE];
#endif
mbedtls_aria_init(&ctx);
/*
* Test set 1
*/
for (i = 0; i < 3; i++) {
/* test ECB encryption */
if (verbose) {
mbedtls_printf(" ARIA-ECB-%d (enc): ", 128 + 64 * i);
}
mbedtls_aria_setkey_enc(&ctx, aria_test1_ecb_key, 128 + 64 * i);
mbedtls_aria_crypt_ecb(&ctx, aria_test1_ecb_pt, blk);
ARIA_SELF_TEST_ASSERT(
memcmp(blk, aria_test1_ecb_ct[i], MBEDTLS_ARIA_BLOCKSIZE)
!= 0);
/* test ECB decryption */
if (verbose) {
mbedtls_printf(" ARIA-ECB-%d (dec): ", 128 + 64 * i);
#if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
mbedtls_printf("skipped\n");
#endif
}
#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
mbedtls_aria_setkey_dec(&ctx, aria_test1_ecb_key, 128 + 64 * i);
mbedtls_aria_crypt_ecb(&ctx, aria_test1_ecb_ct[i], blk);
ARIA_SELF_TEST_ASSERT(
memcmp(blk, aria_test1_ecb_pt, MBEDTLS_ARIA_BLOCKSIZE)
!= 0);
#endif
}
if (verbose) {
mbedtls_printf("\n");
}
/*
* Test set 2
*/
#if defined(MBEDTLS_CIPHER_MODE_CBC)
for (i = 0; i < 3; i++) {
/* Test CBC encryption */
if (verbose) {
mbedtls_printf(" ARIA-CBC-%d (enc): ", 128 + 64 * i);
}
mbedtls_aria_setkey_enc(&ctx, aria_test2_key, 128 + 64 * i);
memcpy(iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE);
memset(buf, 0x55, sizeof(buf));
mbedtls_aria_crypt_cbc(&ctx, MBEDTLS_ARIA_ENCRYPT, 48, iv,
aria_test2_pt, buf);
ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_cbc_ct[i], 48)
!= 0);
/* Test CBC decryption */
if (verbose) {
mbedtls_printf(" ARIA-CBC-%d (dec): ", 128 + 64 * i);
}
mbedtls_aria_setkey_dec(&ctx, aria_test2_key, 128 + 64 * i);
memcpy(iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE);
memset(buf, 0xAA, sizeof(buf));
mbedtls_aria_crypt_cbc(&ctx, MBEDTLS_ARIA_DECRYPT, 48, iv,
aria_test2_cbc_ct[i], buf);
ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_pt, 48) != 0);
}
if (verbose) {
mbedtls_printf("\n");
}
#endif /* MBEDTLS_CIPHER_MODE_CBC */
#if defined(MBEDTLS_CIPHER_MODE_CFB)
for (i = 0; i < 3; i++) {
/* Test CFB encryption */
if (verbose) {
mbedtls_printf(" ARIA-CFB-%d (enc): ", 128 + 64 * i);
}
mbedtls_aria_setkey_enc(&ctx, aria_test2_key, 128 + 64 * i);
memcpy(iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE);
memset(buf, 0x55, sizeof(buf));
j = 0;
mbedtls_aria_crypt_cfb128(&ctx, MBEDTLS_ARIA_ENCRYPT, 48, &j, iv,
aria_test2_pt, buf);
ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_cfb_ct[i], 48) != 0);
/* Test CFB decryption */
if (verbose) {
mbedtls_printf(" ARIA-CFB-%d (dec): ", 128 + 64 * i);
}
mbedtls_aria_setkey_enc(&ctx, aria_test2_key, 128 + 64 * i);
memcpy(iv, aria_test2_iv, MBEDTLS_ARIA_BLOCKSIZE);
memset(buf, 0xAA, sizeof(buf));
j = 0;
mbedtls_aria_crypt_cfb128(&ctx, MBEDTLS_ARIA_DECRYPT, 48, &j,
iv, aria_test2_cfb_ct[i], buf);
ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_pt, 48) != 0);
}
if (verbose) {
mbedtls_printf("\n");
}
#endif /* MBEDTLS_CIPHER_MODE_CFB */
#if defined(MBEDTLS_CIPHER_MODE_CTR)
for (i = 0; i < 3; i++) {
/* Test CTR encryption */
if (verbose) {
mbedtls_printf(" ARIA-CTR-%d (enc): ", 128 + 64 * i);
}
mbedtls_aria_setkey_enc(&ctx, aria_test2_key, 128 + 64 * i);
memset(iv, 0, MBEDTLS_ARIA_BLOCKSIZE); // IV = 0
memset(buf, 0x55, sizeof(buf));
j = 0;
mbedtls_aria_crypt_ctr(&ctx, 48, &j, iv, blk,
aria_test2_pt, buf);
ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_ctr_ct[i], 48) != 0);
/* Test CTR decryption */
if (verbose) {
mbedtls_printf(" ARIA-CTR-%d (dec): ", 128 + 64 * i);
}
mbedtls_aria_setkey_enc(&ctx, aria_test2_key, 128 + 64 * i);
memset(iv, 0, MBEDTLS_ARIA_BLOCKSIZE); // IV = 0
memset(buf, 0xAA, sizeof(buf));
j = 0;
mbedtls_aria_crypt_ctr(&ctx, 48, &j, iv, blk,
aria_test2_ctr_ct[i], buf);
ARIA_SELF_TEST_ASSERT(memcmp(buf, aria_test2_pt, 48) != 0);
}
if (verbose) {
mbedtls_printf("\n");
}
#endif /* MBEDTLS_CIPHER_MODE_CTR */
ret = 0;
exit:
mbedtls_aria_free(&ctx);
return ret;
}
#endif /* MBEDTLS_SELF_TEST */
#endif /* MBEDTLS_ARIA_C */

468
thirdparty/mbedtls/library/asn1parse.c vendored Normal file
View File

@@ -0,0 +1,468 @@
/*
* Generic ASN.1 parsing
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#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"
#include "mbedtls/error.h"
#include <string.h>
#if defined(MBEDTLS_BIGNUM_C)
#include "mbedtls/bignum.h"
#endif
#include "mbedtls/platform.h"
/*
* ASN.1 DER decoding routines
*/
int mbedtls_asn1_get_len(unsigned char **p,
const unsigned char *end,
size_t *len)
{
if ((end - *p) < 1) {
return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
}
if ((**p & 0x80) == 0) {
*len = *(*p)++;
} else {
int n = (**p) & 0x7F;
if (n == 0 || n > 4) {
return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
}
if ((end - *p) <= n) {
return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
}
*len = 0;
(*p)++;
while (n--) {
*len = (*len << 8) | **p;
(*p)++;
}
}
if (*len > (size_t) (end - *p)) {
return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
}
return 0;
}
int mbedtls_asn1_get_tag(unsigned char **p,
const unsigned char *end,
size_t *len, int tag)
{
if ((end - *p) < 1) {
return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
}
if (**p != tag) {
return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG;
}
(*p)++;
return mbedtls_asn1_get_len(p, end, len);
}
#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,
const unsigned char *end,
int *val)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_BOOLEAN)) != 0) {
return ret;
}
if (len != 1) {
return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
}
*val = (**p != 0) ? 1 : 0;
(*p)++;
return 0;
}
static int asn1_get_tagged_int(unsigned char **p,
const unsigned char *end,
int tag, int *val)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
if ((ret = mbedtls_asn1_get_tag(p, end, &len, tag)) != 0) {
return ret;
}
/*
* len==0 is malformed (0 must be represented as 020100 for INTEGER,
* or 0A0100 for ENUMERATED tags
*/
if (len == 0) {
return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
}
/* This is a cryptography library. Reject negative integers. */
if ((**p & 0x80) != 0) {
return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
}
/* Skip leading zeros. */
while (len > 0 && **p == 0) {
++(*p);
--len;
}
/* Reject integers that don't fit in an int. This code assumes that
* the int type has no padding bit. */
if (len > sizeof(int)) {
return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
}
if (len == sizeof(int) && (**p & 0x80) != 0) {
return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
}
*val = 0;
while (len-- > 0) {
*val = (*val << 8) | **p;
(*p)++;
}
return 0;
}
int mbedtls_asn1_get_int(unsigned char **p,
const unsigned char *end,
int *val)
{
return asn1_get_tagged_int(p, end, MBEDTLS_ASN1_INTEGER, val);
}
int mbedtls_asn1_get_enum(unsigned char **p,
const unsigned char *end,
int *val)
{
return asn1_get_tagged_int(p, end, MBEDTLS_ASN1_ENUMERATED, val);
}
#if defined(MBEDTLS_BIGNUM_C)
int mbedtls_asn1_get_mpi(unsigned char **p,
const unsigned char *end,
mbedtls_mpi *X)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {
return ret;
}
ret = mbedtls_mpi_read_binary(X, *p, len);
*p += len;
return ret;
}
#endif /* MBEDTLS_BIGNUM_C */
int mbedtls_asn1_get_bitstring(unsigned char **p, const unsigned char *end,
mbedtls_asn1_bitstring *bs)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* Certificate type is a single byte bitstring */
if ((ret = mbedtls_asn1_get_tag(p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING)) != 0) {
return ret;
}
/* Check length, subtract one for actual bit string length */
if (bs->len < 1) {
return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
}
bs->len -= 1;
/* Get number of unused bits, ensure unused bits <= 7 */
bs->unused_bits = **p;
if (bs->unused_bits > 7) {
return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
}
(*p)++;
/* Get actual bitstring */
bs->p = *p;
*p += bs->len;
if (*p != end) {
return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
}
return 0;
}
/*
* Traverse an ASN.1 "SEQUENCE OF <tag>"
* and call a callback for each entry found.
*/
int mbedtls_asn1_traverse_sequence_of(
unsigned char **p,
const unsigned char *end,
unsigned char tag_must_mask, unsigned char tag_must_val,
unsigned char tag_may_mask, unsigned char tag_may_val,
int (*cb)(void *ctx, int tag,
unsigned char *start, size_t len),
void *ctx)
{
int ret;
size_t len;
/* Get main sequence tag */
if ((ret = mbedtls_asn1_get_tag(p, end, &len,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
return ret;
}
if (*p + len != end) {
return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
}
while (*p < end) {
unsigned char const tag = *(*p)++;
if ((tag & tag_must_mask) != tag_must_val) {
return MBEDTLS_ERR_ASN1_UNEXPECTED_TAG;
}
if ((ret = mbedtls_asn1_get_len(p, end, &len)) != 0) {
return ret;
}
if ((tag & tag_may_mask) == tag_may_val) {
if (cb != NULL) {
ret = cb(ctx, tag, *p, len);
if (ret != 0) {
return ret;
}
}
}
*p += len;
}
return 0;
}
/*
* Get a bit string without unused bits
*/
int mbedtls_asn1_get_bitstring_null(unsigned char **p, const unsigned char *end,
size_t *len)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if ((ret = mbedtls_asn1_get_tag(p, end, len, MBEDTLS_ASN1_BIT_STRING)) != 0) {
return ret;
}
if (*len == 0) {
return MBEDTLS_ERR_ASN1_INVALID_DATA;
}
--(*len);
if (**p != 0) {
return MBEDTLS_ERR_ASN1_INVALID_DATA;
}
++(*p);
return 0;
}
void mbedtls_asn1_sequence_free(mbedtls_asn1_sequence *seq)
{
while (seq != NULL) {
mbedtls_asn1_sequence *next = seq->next;
mbedtls_free(seq);
seq = next;
}
}
typedef struct {
int tag;
mbedtls_asn1_sequence *cur;
} asn1_get_sequence_of_cb_ctx_t;
static int asn1_get_sequence_of_cb(void *ctx,
int tag,
unsigned char *start,
size_t len)
{
asn1_get_sequence_of_cb_ctx_t *cb_ctx =
(asn1_get_sequence_of_cb_ctx_t *) ctx;
mbedtls_asn1_sequence *cur =
cb_ctx->cur;
if (cur->buf.p != NULL) {
cur->next =
mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));
if (cur->next == NULL) {
return MBEDTLS_ERR_ASN1_ALLOC_FAILED;
}
cur = cur->next;
}
cur->buf.p = start;
cur->buf.len = len;
cur->buf.tag = tag;
cb_ctx->cur = cur;
return 0;
}
/*
* Parses and splits an ASN.1 "SEQUENCE OF <tag>"
*/
int mbedtls_asn1_get_sequence_of(unsigned char **p,
const unsigned char *end,
mbedtls_asn1_sequence *cur,
int tag)
{
asn1_get_sequence_of_cb_ctx_t cb_ctx = { tag, cur };
memset(cur, 0, sizeof(mbedtls_asn1_sequence));
return mbedtls_asn1_traverse_sequence_of(
p, end, 0xFF, tag, 0, 0,
asn1_get_sequence_of_cb, &cb_ctx);
}
int mbedtls_asn1_get_alg(unsigned char **p,
const unsigned char *end,
mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params)
{
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 ret;
}
if ((end - *p) < 1) {
return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
}
alg->tag = **p;
end = *p + len;
if ((ret = mbedtls_asn1_get_tag(p, end, &alg->len, MBEDTLS_ASN1_OID)) != 0) {
return ret;
}
alg->p = *p;
*p += alg->len;
if (*p == end) {
mbedtls_platform_zeroize(params, sizeof(mbedtls_asn1_buf));
return 0;
}
params->tag = **p;
(*p)++;
if ((ret = mbedtls_asn1_get_len(p, end, &params->len)) != 0) {
return ret;
}
params->p = *p;
*p += params->len;
if (*p != end) {
return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
}
return 0;
}
int mbedtls_asn1_get_alg_null(unsigned char **p,
const unsigned char *end,
mbedtls_asn1_buf *alg)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_asn1_buf params;
memset(&params, 0, sizeof(mbedtls_asn1_buf));
if ((ret = mbedtls_asn1_get_alg(p, end, alg, &params)) != 0) {
return ret;
}
if ((params.tag != MBEDTLS_ASN1_NULL && params.tag != 0) || params.len != 0) {
return MBEDTLS_ERR_ASN1_INVALID_DATA;
}
return 0;
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_asn1_free_named_data(mbedtls_asn1_named_data *cur)
{
if (cur == NULL) {
return;
}
mbedtls_free(cur->oid.p);
mbedtls_free(cur->val.p);
mbedtls_platform_zeroize(cur, sizeof(mbedtls_asn1_named_data));
}
#endif /* MBEDTLS_DEPRECATED_REMOVED */
void mbedtls_asn1_free_named_data_list(mbedtls_asn1_named_data **head)
{
mbedtls_asn1_named_data *cur;
while ((cur = *head) != NULL) {
*head = cur->next;
mbedtls_free(cur->oid.p);
mbedtls_free(cur->val.p);
mbedtls_free(cur);
}
}
void mbedtls_asn1_free_named_data_list_shallow(mbedtls_asn1_named_data *name)
{
for (mbedtls_asn1_named_data *next; name != NULL; name = next) {
next = name->next;
mbedtls_free(name);
}
}
const mbedtls_asn1_named_data *mbedtls_asn1_find_named_data(const mbedtls_asn1_named_data *list,
const char *oid, size_t len)
{
while (list != NULL) {
if (list->oid.len == len &&
memcmp(list->oid.p, oid, len) == 0) {
break;
}
list = list->next;
}
return list;
}
#endif /* MBEDTLS_ASN1_PARSE_C */

440
thirdparty/mbedtls/library/asn1write.c vendored Normal file
View File

@@ -0,0 +1,440 @@
/*
* ASN.1 buffer writing functionality
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#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"
#include <string.h>
#include "mbedtls/platform.h"
#if defined(MBEDTLS_ASN1_PARSE_C)
#include "mbedtls/asn1.h"
#endif
int mbedtls_asn1_write_len(unsigned char **p, const unsigned char *start, size_t len)
{
#if SIZE_MAX > 0xFFFFFFFF
if (len > 0xFFFFFFFF) {
return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
}
#endif
int required = 1;
if (len >= 0x80) {
for (size_t l = len; l != 0; l >>= 8) {
required++;
}
}
if (required > (*p - start)) {
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
}
do {
*--(*p) = MBEDTLS_BYTE_0(len);
len >>= 8;
} while (len);
if (required > 1) {
*--(*p) = (unsigned char) (0x80 + required - 1);
}
return required;
}
int mbedtls_asn1_write_tag(unsigned char **p, const unsigned char *start, unsigned char tag)
{
if (*p - start < 1) {
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
}
*--(*p) = tag;
return 1;
}
#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,
const unsigned char *start,
size_t len,
unsigned char tag)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, tag));
return (int) len;
}
int mbedtls_asn1_write_raw_buffer(unsigned char **p, const unsigned char *start,
const unsigned char *buf, size_t size)
{
size_t len = 0;
if (*p < start || (size_t) (*p - start) < size) {
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
}
len = size;
(*p) -= len;
if (len != 0) {
memcpy(*p, buf, len);
}
return (int) len;
}
#if defined(MBEDTLS_BIGNUM_C)
int mbedtls_asn1_write_mpi(unsigned char **p, const unsigned char *start, const mbedtls_mpi *X)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
// Write the MPI
//
len = mbedtls_mpi_size(X);
/* DER represents 0 with a sign bit (0=nonnegative) and 7 value bits, not
* as 0 digits. We need to end up with 020100, not with 0200. */
if (len == 0) {
len = 1;
}
if (*p < start || (size_t) (*p - start) < len) {
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
}
(*p) -= len;
MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(X, *p, len));
// DER format assumes 2s complement for numbers, so the leftmost bit
// should be 0 for positive numbers and 1 for negative numbers.
//
if (X->s == 1 && **p & 0x80) {
if (*p - start < 1) {
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
}
*--(*p) = 0x00;
len += 1;
}
ret = mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_INTEGER);
cleanup:
return ret;
}
#endif /* MBEDTLS_BIGNUM_C */
int mbedtls_asn1_write_null(unsigned char **p, const unsigned char *start)
{
// Write NULL
//
return mbedtls_asn1_write_len_and_tag(p, start, 0, MBEDTLS_ASN1_NULL);
}
int mbedtls_asn1_write_oid(unsigned char **p, const unsigned char *start,
const char *oid, size_t oid_len)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start,
(const unsigned char *) oid, oid_len));
return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_OID);
}
int mbedtls_asn1_write_algorithm_identifier(unsigned char **p, const unsigned char *start,
const char *oid, size_t oid_len,
size_t par_len)
{
return mbedtls_asn1_write_algorithm_identifier_ext(p, start, oid, oid_len, par_len, 1);
}
int mbedtls_asn1_write_algorithm_identifier_ext(unsigned char **p, const unsigned char *start,
const char *oid, size_t oid_len,
size_t par_len, int has_par)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
if (has_par) {
if (par_len == 0) {
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_null(p, start));
} else {
len += par_len;
}
}
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len));
return mbedtls_asn1_write_len_and_tag(p, start, len,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
}
int mbedtls_asn1_write_bool(unsigned char **p, const unsigned char *start, int boolean)
{
size_t len = 0;
if (*p - start < 1) {
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
}
*--(*p) = (boolean) ? 255 : 0;
len++;
return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_BOOLEAN);
}
static int asn1_write_tagged_int(unsigned char **p, const unsigned char *start, int val, int tag)
{
size_t len = 0;
do {
if (*p - start < 1) {
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
}
len += 1;
*--(*p) = val & 0xff;
val >>= 8;
} while (val > 0);
if (**p & 0x80) {
if (*p - start < 1) {
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
}
*--(*p) = 0x00;
len += 1;
}
return mbedtls_asn1_write_len_and_tag(p, start, len, tag);
}
int mbedtls_asn1_write_int(unsigned char **p, const unsigned char *start, int val)
{
return asn1_write_tagged_int(p, start, val, MBEDTLS_ASN1_INTEGER);
}
int mbedtls_asn1_write_enum(unsigned char **p, const unsigned char *start, int val)
{
return asn1_write_tagged_int(p, start, val, MBEDTLS_ASN1_ENUMERATED);
}
int mbedtls_asn1_write_tagged_string(unsigned char **p, const unsigned char *start, int tag,
const char *text, size_t text_len)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start,
(const unsigned char *) text,
text_len));
return mbedtls_asn1_write_len_and_tag(p, start, len, tag);
}
int mbedtls_asn1_write_utf8_string(unsigned char **p, const unsigned char *start,
const char *text, size_t text_len)
{
return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_UTF8_STRING, text, text_len);
}
int mbedtls_asn1_write_printable_string(unsigned char **p, const unsigned char *start,
const char *text, size_t text_len)
{
return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_PRINTABLE_STRING, text,
text_len);
}
int mbedtls_asn1_write_ia5_string(unsigned char **p, const unsigned char *start,
const char *text, size_t text_len)
{
return mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_IA5_STRING, text, text_len);
}
int mbedtls_asn1_write_named_bitstring(unsigned char **p,
const unsigned char *start,
const unsigned char *buf,
size_t bits)
{
size_t unused_bits, byte_len;
const unsigned char *cur_byte;
unsigned char cur_byte_shifted;
unsigned char bit;
byte_len = (bits + 7) / 8;
unused_bits = (byte_len * 8) - bits;
/*
* Named bitstrings require that trailing 0s are excluded in the encoding
* of the bitstring. Trailing 0s are considered part of the 'unused' bits
* when encoding this value in the first content octet
*/
if (bits != 0) {
cur_byte = buf + byte_len - 1;
cur_byte_shifted = *cur_byte >> unused_bits;
for (;;) {
bit = cur_byte_shifted & 0x1;
cur_byte_shifted >>= 1;
if (bit != 0) {
break;
}
bits--;
if (bits == 0) {
break;
}
if (bits % 8 == 0) {
cur_byte_shifted = *--cur_byte;
}
}
}
return mbedtls_asn1_write_bitstring(p, start, buf, bits);
}
int mbedtls_asn1_write_bitstring(unsigned char **p, const unsigned char *start,
const unsigned char *buf, size_t bits)
{
size_t len = 0;
size_t unused_bits, byte_len;
byte_len = (bits + 7) / 8;
unused_bits = (byte_len * 8) - bits;
if (*p < start || (size_t) (*p - start) < byte_len + 1) {
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
}
len = byte_len + 1;
/* Write the bitstring. Ensure the unused bits are zeroed */
if (byte_len > 0) {
byte_len--;
*--(*p) = buf[byte_len] & ~((0x1 << unused_bits) - 1);
(*p) -= byte_len;
memcpy(*p, buf, byte_len);
}
/* Write unused bits */
*--(*p) = (unsigned char) unused_bits;
return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_BIT_STRING);
}
int mbedtls_asn1_write_octet_string(unsigned char **p, const unsigned char *start,
const unsigned char *buf, size_t size)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, buf, size));
return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_OCTET_STRING);
}
#if !defined(MBEDTLS_ASN1_PARSE_C)
/* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(),
* which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */
static mbedtls_asn1_named_data *asn1_find_named_data(
mbedtls_asn1_named_data *list,
const char *oid, size_t len)
{
while (list != NULL) {
if (list->oid.len == len &&
memcmp(list->oid.p, oid, len) == 0) {
break;
}
list = list->next;
}
return list;
}
#else
#define asn1_find_named_data(list, oid, len) \
((mbedtls_asn1_named_data *) mbedtls_asn1_find_named_data(list, oid, len))
#endif
mbedtls_asn1_named_data *mbedtls_asn1_store_named_data(
mbedtls_asn1_named_data **head,
const char *oid, size_t oid_len,
const unsigned char *val,
size_t val_len)
{
mbedtls_asn1_named_data *cur;
if ((cur = asn1_find_named_data(*head, oid, oid_len)) == NULL) {
// Add new entry if not present yet based on OID
//
cur = (mbedtls_asn1_named_data *) mbedtls_calloc(1,
sizeof(mbedtls_asn1_named_data));
if (cur == NULL) {
return NULL;
}
cur->oid.len = oid_len;
cur->oid.p = mbedtls_calloc(1, oid_len);
if (cur->oid.p == NULL) {
mbedtls_free(cur);
return NULL;
}
memcpy(cur->oid.p, oid, oid_len);
cur->val.len = val_len;
if (val_len != 0) {
cur->val.p = mbedtls_calloc(1, val_len);
if (cur->val.p == NULL) {
mbedtls_free(cur->oid.p);
mbedtls_free(cur);
return NULL;
}
}
cur->next = *head;
*head = cur;
} else if (val_len == 0) {
mbedtls_free(cur->val.p);
cur->val.p = NULL;
cur->val.len = 0;
} else if (cur->val.len != val_len) {
/*
* Enlarge existing value buffer if needed
* Preserve old data until the allocation succeeded, to leave list in
* a consistent state in case allocation fails.
*/
void *p = mbedtls_calloc(1, val_len);
if (p == NULL) {
return NULL;
}
mbedtls_free(cur->val.p);
cur->val.p = p;
cur->val.len = val_len;
}
if (val != NULL && val_len != 0) {
memcpy(cur->val.p, val, val_len);
}
return cur;
}
#endif /* MBEDTLS_ASN1_WRITE_C */

323
thirdparty/mbedtls/library/base64.c vendored Normal file
View File

@@ -0,0 +1,323 @@
/*
* RFC 1521 base64 encoding/decoding
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include <limits.h>
#include "common.h"
#if defined(MBEDTLS_BASE64_C)
#include "mbedtls/base64.h"
#include "base64_internal.h"
#include "constant_time_internal.h"
#include "mbedtls/error.h"
#include <stdint.h>
#if defined(MBEDTLS_SELF_TEST)
#include <string.h>
#include "mbedtls/platform.h"
#endif /* MBEDTLS_SELF_TEST */
MBEDTLS_STATIC_TESTABLE
unsigned char mbedtls_ct_base64_enc_char(unsigned char value)
{
unsigned char digit = 0;
/* For each range of values, if value is in that range, mask digit with
* the corresponding value. Since value can only be in a single range,
* only at most one masking will change digit. */
digit |= mbedtls_ct_uchar_in_range_if(0, 25, value, 'A' + value);
digit |= mbedtls_ct_uchar_in_range_if(26, 51, value, 'a' + value - 26);
digit |= mbedtls_ct_uchar_in_range_if(52, 61, value, '0' + value - 52);
digit |= mbedtls_ct_uchar_in_range_if(62, 62, value, '+');
digit |= mbedtls_ct_uchar_in_range_if(63, 63, value, '/');
return digit;
}
MBEDTLS_STATIC_TESTABLE
signed char mbedtls_ct_base64_dec_value(unsigned char c)
{
unsigned char val = 0;
/* For each range of digits, if c is in that range, mask val with
* the corresponding value. Since c can only be in a single range,
* only at most one masking will change val. Set val to one plus
* the desired value so that it stays 0 if c is in none of the ranges. */
val |= mbedtls_ct_uchar_in_range_if('A', 'Z', c, c - 'A' + 0 + 1);
val |= mbedtls_ct_uchar_in_range_if('a', 'z', c, c - 'a' + 26 + 1);
val |= mbedtls_ct_uchar_in_range_if('0', '9', c, c - '0' + 52 + 1);
val |= mbedtls_ct_uchar_in_range_if('+', '+', c, c - '+' + 62 + 1);
val |= mbedtls_ct_uchar_in_range_if('/', '/', c, c - '/' + 63 + 1);
/* At this point, val is 0 if c is an invalid digit and v+1 if c is
* a digit with the value v. */
return val - 1;
}
/*
* Encode a buffer into base64 format
*/
int mbedtls_base64_encode(unsigned char *dst, size_t dlen, size_t *olen,
const unsigned char *src, size_t slen)
{
size_t i, n;
int C1, C2, C3;
unsigned char *p;
if (slen == 0) {
*olen = 0;
return 0;
}
n = slen / 3 + (slen % 3 != 0);
if (n > (SIZE_MAX - 1) / 4) {
*olen = SIZE_MAX;
return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL;
}
n *= 4;
if ((dlen < n + 1) || (NULL == dst)) {
*olen = n + 1;
return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL;
}
n = (slen / 3) * 3;
for (i = 0, p = dst; i < n; i += 3) {
C1 = *src++;
C2 = *src++;
C3 = *src++;
*p++ = mbedtls_ct_base64_enc_char((C1 >> 2) & 0x3F);
*p++ = mbedtls_ct_base64_enc_char((((C1 & 3) << 4) + (C2 >> 4))
& 0x3F);
*p++ = mbedtls_ct_base64_enc_char((((C2 & 15) << 2) + (C3 >> 6))
& 0x3F);
*p++ = mbedtls_ct_base64_enc_char(C3 & 0x3F);
}
if (i < slen) {
C1 = *src++;
C2 = ((i + 1) < slen) ? *src++ : 0;
*p++ = mbedtls_ct_base64_enc_char((C1 >> 2) & 0x3F);
*p++ = mbedtls_ct_base64_enc_char((((C1 & 3) << 4) + (C2 >> 4))
& 0x3F);
if ((i + 1) < slen) {
*p++ = mbedtls_ct_base64_enc_char(((C2 & 15) << 2) & 0x3F);
} else {
*p++ = '=';
}
*p++ = '=';
}
*olen = (size_t) (p - dst);
*p = 0;
return 0;
}
/*
* Decode a base64-formatted buffer
*/
int mbedtls_base64_decode(unsigned char *dst, size_t dlen, size_t *olen,
const unsigned char *src, size_t slen)
{
size_t i; /* index in source */
size_t n; /* number of digits or trailing = in source */
uint32_t x; /* value accumulator */
unsigned accumulated_digits = 0;
unsigned equals = 0;
int spaces_present = 0;
unsigned char *p;
/* First pass: check for validity and get output length */
for (i = n = 0; i < slen; i++) {
/* Skip spaces before checking for EOL */
spaces_present = 0;
while (i < slen && src[i] == ' ') {
++i;
spaces_present = 1;
}
/* Spaces at end of buffer are OK */
if (i == slen) {
break;
}
if ((slen - i) >= 2 &&
src[i] == '\r' && src[i + 1] == '\n') {
continue;
}
if (src[i] == '\n') {
continue;
}
/* Space inside a line is an error */
if (spaces_present) {
return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;
}
if (src[i] > 127) {
return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;
}
if (src[i] == '=') {
if (++equals > 2) {
return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;
}
} else {
if (equals != 0) {
return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;
}
if (mbedtls_ct_base64_dec_value(src[i]) < 0) {
return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;
}
}
n++;
}
/* In valid base64, the number of digits (n-equals) is always of the form
* 4*k, 4*k+2 or *4k+3. Also, the number n of digits plus the number of
* equal signs at the end is always a multiple of 4. */
if ((n - equals) % 4 == 1) {
return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;
}
if (n % 4 != 0) {
return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;
}
/* We've determined that the input is valid, and that it contains
* exactly k blocks of digits-or-equals, with n = 4 * k,
* and equals only present at the end of the last block if at all.
* Now we can calculate the length of the output.
*
* Each block of 4 digits in the input map to 3 bytes of output.
* For the last block:
* - abcd (where abcd are digits) is a full 3-byte block;
* - abc= means 1 byte less than a full 3-byte block of output;
* - ab== means 2 bytes less than a full 3-byte block of output;
* - a==== and ==== is rejected above.
*/
*olen = (n / 4) * 3 - equals;
/* If the output buffer is too small, signal this and stop here.
* Also, as documented, stop here if `dst` is null, independently of
* `dlen`.
*
* There is an edge case when the output is empty: in this case,
* `dlen == 0` with `dst == NULL` is valid (on some platforms,
* `malloc(0)` returns `NULL`). Since the call is valid, we return
* 0 in this case.
*/
if ((*olen != 0 && dst == NULL) || dlen < *olen) {
return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL;
}
for (x = 0, p = dst; i > 0; i--, src++) {
if (*src == '\r' || *src == '\n' || *src == ' ') {
continue;
}
if (*src == '=') {
/* We already know from the first loop that equal signs are
* only at the end. */
break;
}
x = x << 6;
x |= mbedtls_ct_base64_dec_value(*src);
if (++accumulated_digits == 4) {
accumulated_digits = 0;
*p++ = MBEDTLS_BYTE_2(x);
*p++ = MBEDTLS_BYTE_1(x);
*p++ = MBEDTLS_BYTE_0(x);
}
}
if (accumulated_digits == 3) {
*p++ = MBEDTLS_BYTE_2(x << 6);
*p++ = MBEDTLS_BYTE_1(x << 6);
} else if (accumulated_digits == 2) {
*p++ = MBEDTLS_BYTE_2(x << 12);
}
if (*olen != (size_t) (p - dst)) {
return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
}
return 0;
}
#if defined(MBEDTLS_SELF_TEST)
static const unsigned char base64_test_dec[64] =
{
0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13,
0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31,
0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38,
0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B,
0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97
};
static const unsigned char base64_test_enc[] =
"JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK"
"swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw==";
/*
* Checkup routine
*/
int mbedtls_base64_self_test(int verbose)
{
size_t len;
const unsigned char *src;
unsigned char buffer[128];
if (verbose != 0) {
mbedtls_printf(" Base64 encoding test: ");
}
src = base64_test_dec;
if (mbedtls_base64_encode(buffer, sizeof(buffer), &len, src, 64) != 0 ||
memcmp(base64_test_enc, buffer, 88) != 0) {
if (verbose != 0) {
mbedtls_printf("failed\n");
}
return 1;
}
if (verbose != 0) {
mbedtls_printf("passed\n Base64 decoding test: ");
}
src = base64_test_enc;
if (mbedtls_base64_decode(buffer, sizeof(buffer), &len, src, 88) != 0 ||
memcmp(base64_test_dec, buffer, 64) != 0) {
if (verbose != 0) {
mbedtls_printf("failed\n");
}
return 1;
}
if (verbose != 0) {
mbedtls_printf("passed\n\n");
}
return 0;
}
#endif /* MBEDTLS_SELF_TEST */
#endif /* MBEDTLS_BASE64_C */

View File

@@ -0,0 +1,45 @@
/**
* \file base64_internal.h
*
* \brief RFC 1521 base64 encoding/decoding: interfaces for invasive testing
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef MBEDTLS_BASE64_INTERNAL
#define MBEDTLS_BASE64_INTERNAL
#include "common.h"
#if defined(MBEDTLS_TEST_HOOKS)
/** Given a value in the range 0..63, return the corresponding Base64 digit.
*
* The implementation assumes that letters are consecutive (e.g. ASCII
* but not EBCDIC).
*
* \param value A value in the range 0..63.
*
* \return A base64 digit converted from \p value.
*/
unsigned char mbedtls_ct_base64_enc_char(unsigned char value);
/** Given a Base64 digit, return its value.
*
* If c is not a Base64 digit ('A'..'Z', 'a'..'z', '0'..'9', '+' or '/'),
* return -1.
*
* The implementation assumes that letters are consecutive (e.g. ASCII
* but not EBCDIC).
*
* \param c A base64 digit.
*
* \return The value of the base64 digit \p c.
*/
signed char mbedtls_ct_base64_dec_value(unsigned char c);
#endif /* MBEDTLS_TEST_HOOKS */
#endif /* MBEDTLS_BASE64_INTERNAL */

2487
thirdparty/mbedtls/library/bignum.c vendored Normal file

File diff suppressed because it is too large Load Diff

1022
thirdparty/mbedtls/library/bignum_core.c vendored Normal file

File diff suppressed because it is too large Load Diff

825
thirdparty/mbedtls/library/bignum_core.h vendored Normal file
View File

@@ -0,0 +1,825 @@
/**
* Core bignum functions
*
* This interface should only be used by the legacy bignum module (bignum.h)
* and the modular bignum modules (bignum_mod.c, bignum_mod_raw.c). All other
* modules should use the high-level modular bignum interface (bignum_mod.h)
* or the legacy bignum interface (bignum.h).
*
* This module is about processing non-negative integers with a fixed upper
* bound that's of the form 2^n-1 where n is a multiple of #biL.
* These can be thought of integers written in base 2^#biL with a fixed
* number of digits. Digits in this base are called *limbs*.
* Many operations treat these numbers as the principal representation of
* a number modulo 2^n or a smaller bound.
*
* The functions in this module obey the following conventions unless
* explicitly indicated otherwise:
*
* - **Overflow**: some functions indicate overflow from the range
* [0, 2^n-1] by returning carry parameters, while others operate
* modulo and so cannot overflow. This should be clear from the function
* documentation.
* - **Bignum parameters**: Bignums are passed as pointers to an array of
* limbs. A limb has the type #mbedtls_mpi_uint. Unless otherwise specified:
* - Bignum parameters called \p A, \p B, ... are inputs, and are
* not modified by the function.
* - For operations modulo some number, the modulus is called \p N
* and is input-only.
* - Bignum parameters called \p X, \p Y are outputs or input-output.
* The initial content of output-only parameters is ignored.
* - Some functions use different names that reflect traditional
* naming of operands of certain operations (e.g.
* divisor/dividend/quotient/remainder).
* - \p T is a temporary storage area. The initial content of such
* parameter is ignored and the final content is unspecified.
* - **Bignum sizes**: bignum sizes are always expressed in limbs.
* Most functions work on bignums of a given size and take a single
* \p limbs parameter that applies to all parameters that are limb arrays.
* All bignum sizes must be at least 1 and must be significantly less than
* #SIZE_MAX. The behavior if a size is 0 is undefined. The behavior if the
* total size of all parameters overflows #SIZE_MAX is undefined.
* - **Parameter ordering**: for bignum parameters, outputs come before inputs.
* Temporaries come last.
* - **Aliasing**: in general, output bignums may be aliased to one or more
* inputs. As an exception, parameters that are documented as a modulus value
* may not be aliased to an output. Outputs may not be aliased to one another.
* Temporaries may not be aliased to any other parameter.
* - **Overlap**: apart from aliasing of limb array pointers (where two
* arguments are equal pointers), overlap is not supported and may result
* in undefined behavior.
* - **Error handling**: This is a low-level module. Functions generally do not
* try to protect against invalid arguments such as nonsensical sizes or
* null pointers. Note that some functions that operate on bignums of
* different sizes have constraints about their size, and violating those
* constraints may lead to buffer overflows.
* - **Modular representatives**: functions that operate modulo \p N expect
* all modular inputs to be in the range [0, \p N - 1] and guarantee outputs
* in the range [0, \p N - 1]. If an input is out of range, outputs are
* fully unspecified, though bignum values out of range should not cause
* buffer overflows (beware that this is not extensively tested).
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef MBEDTLS_BIGNUM_CORE_H
#define MBEDTLS_BIGNUM_CORE_H
#include "common.h"
#include "mbedtls/bignum.h"
#include "constant_time_internal.h"
#define ciL (sizeof(mbedtls_mpi_uint)) /** chars in limb */
#define biL (ciL << 3) /** bits in limb */
#define biH (ciL << 2) /** half limb size */
/*
* Convert between bits/chars and number of limbs
* Divide first in order to avoid potential overflows
*/
#define BITS_TO_LIMBS(i) ((i) / biL + ((i) % biL != 0))
#define CHARS_TO_LIMBS(i) ((i) / ciL + ((i) % ciL != 0))
/* Get a specific byte, without range checks. */
#define GET_BYTE(X, i) \
(((X)[(i) / ciL] >> (((i) % ciL) * 8)) & 0xff)
/* Constants to identify whether a value is public or secret. If a parameter is marked as secret by
* this constant, the function must be constant time with respect to the parameter.
*
* This is only needed for functions with the _optionally_safe postfix. All other functions have
* fixed behavior that can't be changed at runtime and are constant time with respect to their
* parameters as prescribed by their documentation or by conventions in their module's documentation.
*
* Parameters should be named X_public where X is the name of the
* corresponding input parameter.
*
* Implementation should always check using
* if (X_public == MBEDTLS_MPI_IS_PUBLIC) {
* // unsafe path
* } else {
* // safe path
* }
* not the other way round, in order to prevent misuse. (That is, if a value
* other than the two below is passed, default to the safe path.)
*
* The value of MBEDTLS_MPI_IS_PUBLIC is chosen in a way that is unlikely to happen by accident, but
* which can be used as an immediate value in a Thumb2 comparison (for code size). */
#define MBEDTLS_MPI_IS_PUBLIC 0x2a2a2a2a
#define MBEDTLS_MPI_IS_SECRET 0
#if defined(MBEDTLS_TEST_HOOKS) && !defined(MBEDTLS_THREADING_C)
// Default value for testing that is neither MBEDTLS_MPI_IS_PUBLIC nor MBEDTLS_MPI_IS_SECRET
#define MBEDTLS_MPI_IS_TEST 1
#endif
/** Count leading zero bits in a given integer.
*
* \warning The result is undefined if \p a == 0
*
* \param a Integer to count leading zero bits.
*
* \return The number of leading zero bits in \p a, if \p a != 0.
* If \p a == 0, the result is undefined.
*/
size_t mbedtls_mpi_core_clz(mbedtls_mpi_uint a);
/** Return the minimum number of bits required to represent the value held
* in the MPI.
*
* \note This function returns 0 if all the limbs of \p A are 0.
*
* \param[in] A The address of the MPI.
* \param A_limbs The number of limbs of \p A.
*
* \return The number of bits in \p A.
*/
size_t mbedtls_mpi_core_bitlen(const mbedtls_mpi_uint *A, size_t A_limbs);
/** Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
* into the storage form used by mbedtls_mpi.
*
* \param[in,out] A The address of the MPI.
* \param A_limbs The number of limbs of \p A.
*/
void mbedtls_mpi_core_bigendian_to_host(mbedtls_mpi_uint *A,
size_t A_limbs);
/** \brief Compare a machine integer with an MPI.
*
* This function operates in constant time with respect
* to the values of \p min and \p A.
*
* \param min A machine integer.
* \param[in] A An MPI.
* \param A_limbs The number of limbs of \p A.
* This must be at least 1.
*
* \return MBEDTLS_CT_TRUE if \p min is less than or equal to \p A, otherwise MBEDTLS_CT_FALSE.
*/
mbedtls_ct_condition_t mbedtls_mpi_core_uint_le_mpi(mbedtls_mpi_uint min,
const mbedtls_mpi_uint *A,
size_t A_limbs);
/**
* \brief Check if one unsigned MPI is less than another in constant
* time.
*
* \param A The left-hand MPI. This must point to an array of limbs
* with the same allocated length as \p B.
* \param B The right-hand MPI. This must point to an array of limbs
* with the same allocated length as \p A.
* \param limbs The number of limbs in \p A and \p B.
* This must not be 0.
*
* \return MBEDTLS_CT_TRUE if \p A is less than \p B.
* MBEDTLS_CT_FALSE if \p A is greater than or equal to \p B.
*/
mbedtls_ct_condition_t mbedtls_mpi_core_lt_ct(const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *B,
size_t limbs);
/**
* \brief Perform a safe conditional copy of an MPI which doesn't reveal
* whether assignment was done or not.
*
* \param[out] X The address of the destination MPI.
* This must be initialized. Must have enough limbs to
* store the full value of \p A.
* \param[in] A The address of the source MPI. This must be initialized.
* \param limbs The number of limbs of \p A.
* \param assign The condition deciding whether to perform the
* assignment or not. Callers will need to use
* the constant time interface (e.g. `mbedtls_ct_bool()`)
* to construct this argument.
*
* \note This function avoids leaking any information about whether
* the assignment was done or not.
*/
void mbedtls_mpi_core_cond_assign(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
size_t limbs,
mbedtls_ct_condition_t assign);
/**
* \brief Perform a safe conditional swap of two MPIs which doesn't reveal
* whether the swap was done or not.
*
* \param[in,out] X The address of the first MPI.
* This must be initialized.
* \param[in,out] Y The address of the second MPI.
* This must be initialized.
* \param limbs The number of limbs of \p X and \p Y.
* \param swap The condition deciding whether to perform
* the swap or not.
*
* \note This function avoids leaking any information about whether
* the swap was done or not.
*/
void mbedtls_mpi_core_cond_swap(mbedtls_mpi_uint *X,
mbedtls_mpi_uint *Y,
size_t limbs,
mbedtls_ct_condition_t swap);
/** Import X from unsigned binary data, little-endian.
*
* The MPI needs to have enough limbs to store the full value (including any
* most significant zero bytes in the input).
*
* \param[out] X The address of the MPI.
* \param X_limbs The number of limbs of \p X.
* \param[in] input The input buffer to import from.
* \param input_length The length bytes of \p input.
*
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p X isn't
* large enough to hold the value in \p input.
*/
int mbedtls_mpi_core_read_le(mbedtls_mpi_uint *X,
size_t X_limbs,
const unsigned char *input,
size_t input_length);
/** Import X from unsigned binary data, big-endian.
*
* The MPI needs to have enough limbs to store the full value (including any
* most significant zero bytes in the input).
*
* \param[out] X The address of the MPI.
* May only be #NULL if \p X_limbs is 0 and \p input_length
* is 0.
* \param X_limbs The number of limbs of \p X.
* \param[in] input The input buffer to import from.
* May only be #NULL if \p input_length is 0.
* \param input_length The length in bytes of \p input.
*
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p X isn't
* large enough to hold the value in \p input.
*/
int mbedtls_mpi_core_read_be(mbedtls_mpi_uint *X,
size_t X_limbs,
const unsigned char *input,
size_t input_length);
/** Export A into unsigned binary data, little-endian.
*
* \note If \p output is shorter than \p A the export is still successful if the
* value held in \p A fits in the buffer (that is, if enough of the most
* significant bytes of \p A are 0).
*
* \param[in] A The address of the MPI.
* \param A_limbs The number of limbs of \p A.
* \param[out] output The output buffer to export to.
* \param output_length The length in bytes of \p output.
*
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p output isn't
* large enough to hold the value of \p A.
*/
int mbedtls_mpi_core_write_le(const mbedtls_mpi_uint *A,
size_t A_limbs,
unsigned char *output,
size_t output_length);
/** Export A into unsigned binary data, big-endian.
*
* \note If \p output is shorter than \p A the export is still successful if the
* value held in \p A fits in the buffer (that is, if enough of the most
* significant bytes of \p A are 0).
*
* \param[in] A The address of the MPI.
* \param A_limbs The number of limbs of \p A.
* \param[out] output The output buffer to export to.
* \param output_length The length in bytes of \p output.
*
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p output isn't
* large enough to hold the value of \p A.
*/
int mbedtls_mpi_core_write_be(const mbedtls_mpi_uint *A,
size_t A_limbs,
unsigned char *output,
size_t output_length);
/** \brief Shift an MPI in-place right by a number of bits.
*
* Shifting by more bits than there are bit positions
* in \p X is valid and results in setting \p X to 0.
*
* This function's execution time depends on the value
* of \p count (and of course \p limbs).
*
* \param[in,out] X The number to shift.
* \param limbs The number of limbs of \p X. This must be at least 1.
* \param count The number of bits to shift by.
*/
void mbedtls_mpi_core_shift_r(mbedtls_mpi_uint *X, size_t limbs,
size_t count);
/**
* \brief Shift an MPI in-place left by a number of bits.
*
* Shifting by more bits than there are bit positions
* in \p X will produce an unspecified result.
*
* This function's execution time depends on the value
* of \p count (and of course \p limbs).
* \param[in,out] X The number to shift.
* \param limbs The number of limbs of \p X. This must be at least 1.
* \param count The number of bits to shift by.
*/
void mbedtls_mpi_core_shift_l(mbedtls_mpi_uint *X, size_t limbs,
size_t count);
/**
* \brief Add two fixed-size large unsigned integers, returning the carry.
*
* Calculates `A + B` where `A` and `B` have the same size.
*
* This function operates modulo `2^(biL*limbs)` and returns the carry
* (1 if there was a wraparound, and 0 otherwise).
*
* \p X may be aliased to \p A or \p B.
*
* \param[out] X The result of the addition.
* \param[in] A Little-endian presentation of the left operand.
* \param[in] B Little-endian presentation of the right operand.
* \param limbs Number of limbs of \p X, \p A and \p B.
*
* \return 1 if `A + B >= 2^(biL*limbs)`, 0 otherwise.
*/
mbedtls_mpi_uint mbedtls_mpi_core_add(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *B,
size_t limbs);
/**
* \brief Conditional addition of two fixed-size large unsigned integers,
* returning the carry.
*
* Functionally equivalent to
*
* ```
* if( cond )
* X += A;
* return carry;
* ```
*
* This function operates modulo `2^(biL*limbs)`.
*
* \param[in,out] X The pointer to the (little-endian) array
* representing the bignum to accumulate onto.
* \param[in] A The pointer to the (little-endian) array
* representing the bignum to conditionally add
* to \p X. This may be aliased to \p X but may not
* overlap otherwise.
* \param limbs Number of limbs of \p X and \p A.
* \param cond Condition bit dictating whether addition should
* happen or not. This must be \c 0 or \c 1.
*
* \warning If \p cond is neither 0 nor 1, the result of this function
* is unspecified, and the resulting value in \p X might be
* neither its original value nor \p X + \p A.
*
* \return 1 if `X + cond * A >= 2^(biL*limbs)`, 0 otherwise.
*/
mbedtls_mpi_uint mbedtls_mpi_core_add_if(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
size_t limbs,
unsigned cond);
/**
* \brief Subtract two fixed-size large unsigned integers, returning the borrow.
*
* Calculate `A - B` where \p A and \p B have the same size.
* This function operates modulo `2^(biL*limbs)` and returns the carry
* (1 if there was a wraparound, i.e. if `A < B`, and 0 otherwise).
*
* \p X may be aliased to \p A or \p B, or even both, but may not overlap
* either otherwise.
*
* \param[out] X The result of the subtraction.
* \param[in] A Little-endian presentation of left operand.
* \param[in] B Little-endian presentation of right operand.
* \param limbs Number of limbs of \p X, \p A and \p B.
*
* \return 1 if `A < B`.
* 0 if `A >= B`.
*/
mbedtls_mpi_uint mbedtls_mpi_core_sub(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *B,
size_t limbs);
/**
* \brief Perform a fixed-size multiply accumulate operation: X += b * A
*
* \p X may be aliased to \p A (when \p X_limbs == \p A_limbs), but may not
* otherwise overlap.
*
* This function operates modulo `2^(biL*X_limbs)`.
*
* \param[in,out] X The pointer to the (little-endian) array
* representing the bignum to accumulate onto.
* \param X_limbs The number of limbs of \p X. This must be
* at least \p A_limbs.
* \param[in] A The pointer to the (little-endian) array
* representing the bignum to multiply with.
* This may be aliased to \p X but may not overlap
* otherwise.
* \param A_limbs The number of limbs of \p A.
* \param b X scalar to multiply with.
*
* \return The carry at the end of the operation.
*/
mbedtls_mpi_uint mbedtls_mpi_core_mla(mbedtls_mpi_uint *X, size_t X_limbs,
const mbedtls_mpi_uint *A, size_t A_limbs,
mbedtls_mpi_uint b);
/**
* \brief Perform a known-size multiplication
*
* \p X may not be aliased to any of the inputs for this function.
* \p A may be aliased to \p B.
*
* \param[out] X The pointer to the (little-endian) array to receive
* the product of \p A_limbs and \p B_limbs.
* This must be of length \p A_limbs + \p B_limbs.
* \param[in] A The pointer to the (little-endian) array
* representing the first factor.
* \param A_limbs The number of limbs in \p A.
* \param[in] B The pointer to the (little-endian) array
* representing the second factor.
* \param B_limbs The number of limbs in \p B.
*/
void mbedtls_mpi_core_mul(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A, size_t A_limbs,
const mbedtls_mpi_uint *B, size_t B_limbs);
/**
* \brief Calculate initialisation value for fast Montgomery modular
* multiplication
*
* \param[in] N Little-endian presentation of the modulus. This must have
* at least one limb.
*
* \return The initialisation value for fast Montgomery modular multiplication
*/
mbedtls_mpi_uint mbedtls_mpi_core_montmul_init(const mbedtls_mpi_uint *N);
/**
* \brief Montgomery multiplication: X = A * B * R^-1 mod N (HAC 14.36)
*
* \p A and \p B must be in canonical form. That is, < \p N.
*
* \p X may be aliased to \p A or \p N, or even \p B (if \p AN_limbs ==
* \p B_limbs) but may not overlap any parameters otherwise.
*
* \p A and \p B may alias each other, if \p AN_limbs == \p B_limbs. They may
* not alias \p N (since they must be in canonical form, they cannot == \p N).
*
* \param[out] X The destination MPI, as a little-endian array of
* length \p AN_limbs.
* On successful completion, X contains the result of
* the multiplication `A * B * R^-1` mod N where
* `R = 2^(biL*AN_limbs)`.
* \param[in] A Little-endian presentation of first operand.
* Must have the same number of limbs as \p N.
* \param[in] B Little-endian presentation of second operand.
* \param[in] B_limbs The number of limbs in \p B.
* Must be <= \p AN_limbs.
* \param[in] N Little-endian presentation of the modulus.
* This must be odd, and have exactly the same number
* of limbs as \p A.
* It may alias \p X, but must not alias or otherwise
* overlap any of the other parameters.
* \param[in] AN_limbs The number of limbs in \p X, \p A and \p N.
* \param mm The Montgomery constant for \p N: -N^-1 mod 2^biL.
* This can be calculated by `mbedtls_mpi_core_montmul_init()`.
* \param[in,out] T Temporary storage of size at least 2*AN_limbs+1 limbs.
* Its initial content is unused and
* its final content is indeterminate.
* It must not alias or otherwise overlap any of the
* other parameters.
*/
void mbedtls_mpi_core_montmul(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *B, size_t B_limbs,
const mbedtls_mpi_uint *N, size_t AN_limbs,
mbedtls_mpi_uint mm, mbedtls_mpi_uint *T);
/**
* \brief Calculate the square of the Montgomery constant. (Needed
* for conversion and operations in Montgomery form.)
*
* \param[out] X A pointer to the result of the calculation of
* the square of the Montgomery constant:
* 2^{2*n*biL} mod N.
* \param[in] N Little-endian presentation of the modulus, which must be odd.
*
* \return 0 if successful.
* \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if there is not enough space
* to store the value of Montgomery constant squared.
* \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p N modulus is zero.
* \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p N modulus is negative.
*/
int mbedtls_mpi_core_get_mont_r2_unsafe(mbedtls_mpi *X,
const mbedtls_mpi *N);
#if defined(MBEDTLS_TEST_HOOKS)
/**
* Copy an MPI from a table without leaking the index.
*
* \param dest The destination buffer. This must point to a writable
* buffer of at least \p limbs limbs.
* \param table The address of the table. This must point to a readable
* array of \p count elements of \p limbs limbs each.
* \param limbs The number of limbs in each table entry.
* \param count The number of entries in \p table.
* \param index The (secret) table index to look up. This must be in the
* range `0 .. count-1`.
*/
void mbedtls_mpi_core_ct_uint_table_lookup(mbedtls_mpi_uint *dest,
const mbedtls_mpi_uint *table,
size_t limbs,
size_t count,
size_t index);
#endif /* MBEDTLS_TEST_HOOKS */
/**
* \brief Fill an integer with a number of random bytes.
*
* \param X The destination MPI.
* \param X_limbs The number of limbs of \p X.
* \param bytes The number of random bytes to generate.
* \param f_rng The RNG function to use. This must not be \c NULL.
* \param p_rng The RNG parameter to be passed to \p f_rng. This may be
* \c NULL if \p f_rng doesn't need a context argument.
*
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p X does not have
* enough room for \p bytes bytes.
* \return A negative error code on RNG failure.
*
* \note The bytes obtained from the RNG are interpreted
* as a big-endian representation of an MPI; this can
* be relevant in applications like deterministic ECDSA.
*/
int mbedtls_mpi_core_fill_random(mbedtls_mpi_uint *X, size_t X_limbs,
size_t bytes,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng);
/** Generate a random number uniformly in a range.
*
* This function generates a random number between \p min inclusive and
* \p N exclusive.
*
* The procedure complies with RFC 6979 §3.3 (deterministic ECDSA)
* when the RNG is a suitably parametrized instance of HMAC_DRBG
* and \p min is \c 1.
*
* \note There are `N - min` possible outputs. The lower bound
* \p min can be reached, but the upper bound \p N cannot.
*
* \param X The destination MPI, with \p limbs limbs.
* It must not be aliased with \p N or otherwise overlap it.
* \param min The minimum value to return.
* \param N The upper bound of the range, exclusive, with \p limbs limbs.
* In other words, this is one plus the maximum value to return.
* \p N must be strictly larger than \p min.
* \param limbs The number of limbs of \p N and \p X.
* This must not be 0.
* \param f_rng The RNG function to use. This must not be \c NULL.
* \param p_rng The RNG parameter to be passed to \p f_rng.
*
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was
* unable to find a suitable value within a limited number
* of attempts. This has a negligible probability if \p N
* is significantly larger than \p min, which is the case
* for all usual cryptographic applications.
*/
int mbedtls_mpi_core_random(mbedtls_mpi_uint *X,
mbedtls_mpi_uint min,
const mbedtls_mpi_uint *N,
size_t limbs,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng);
/**
* \brief Returns the number of limbs of working memory required for
* a call to `mbedtls_mpi_core_exp_mod()`.
*
* \note This will always be at least
* `mbedtls_mpi_core_montmul_working_limbs(AN_limbs)`,
* i.e. sufficient for a call to `mbedtls_mpi_core_montmul()`.
*
* \param AN_limbs The number of limbs in the input `A` and the modulus `N`
* (they must be the same size) that will be given to
* `mbedtls_mpi_core_exp_mod()`.
* \param E_limbs The number of limbs in the exponent `E` that will be given
* to `mbedtls_mpi_core_exp_mod()`.
*
* \return The number of limbs of working memory required by
* `mbedtls_mpi_core_exp_mod()`.
*/
size_t mbedtls_mpi_core_exp_mod_working_limbs(size_t AN_limbs, size_t E_limbs);
/**
* \brief Perform a modular exponentiation with public or secret exponent:
* X = A^E mod N, where \p A is already in Montgomery form.
*
* \warning This function is not constant time with respect to \p E (the exponent).
*
* \p X may be aliased to \p A, but not to \p RR or \p E, even if \p E_limbs ==
* \p AN_limbs.
*
* \param[out] X The destination MPI, as a little endian array of length
* \p AN_limbs.
* \param[in] A The base MPI, as a little endian array of length \p AN_limbs.
* Must be in Montgomery form.
* \param[in] N The modulus, as a little endian array of length \p AN_limbs.
* \param AN_limbs The number of limbs in \p X, \p A, \p N, \p RR.
* \param[in] E The exponent, as a little endian array of length \p E_limbs.
* \param E_limbs The number of limbs in \p E.
* \param[in] RR The precomputed residue of 2^{2*biL} modulo N, as a little
* endian array of length \p AN_limbs.
* \param[in,out] T Temporary storage of at least the number of limbs returned
* by `mbedtls_mpi_core_exp_mod_working_limbs()`.
* Its initial content is unused and its final content is
* indeterminate.
* It must not alias or otherwise overlap any of the other
* parameters.
* It is up to the caller to zeroize \p T when it is no
* longer needed, and before freeing it if it was dynamically
* allocated.
*/
void mbedtls_mpi_core_exp_mod_unsafe(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *N, size_t AN_limbs,
const mbedtls_mpi_uint *E, size_t E_limbs,
const mbedtls_mpi_uint *RR,
mbedtls_mpi_uint *T);
/**
* \brief Perform a modular exponentiation with secret exponent:
* X = A^E mod N, where \p A is already in Montgomery form.
*
* \p X may be aliased to \p A, but not to \p RR or \p E, even if \p E_limbs ==
* \p AN_limbs.
*
* \param[out] X The destination MPI, as a little endian array of length
* \p AN_limbs.
* \param[in] A The base MPI, as a little endian array of length \p AN_limbs.
* Must be in Montgomery form.
* \param[in] N The modulus, as a little endian array of length \p AN_limbs.
* \param AN_limbs The number of limbs in \p X, \p A, \p N, \p RR.
* \param[in] E The exponent, as a little endian array of length \p E_limbs.
* \param E_limbs The number of limbs in \p E.
* \param[in] RR The precomputed residue of 2^{2*biL} modulo N, as a little
* endian array of length \p AN_limbs.
* \param[in,out] T Temporary storage of at least the number of limbs returned
* by `mbedtls_mpi_core_exp_mod_working_limbs()`.
* Its initial content is unused and its final content is
* indeterminate.
* It must not alias or otherwise overlap any of the other
* parameters.
* It is up to the caller to zeroize \p T when it is no
* longer needed, and before freeing it if it was dynamically
* allocated.
*/
void mbedtls_mpi_core_exp_mod(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *N, size_t AN_limbs,
const mbedtls_mpi_uint *E, size_t E_limbs,
const mbedtls_mpi_uint *RR,
mbedtls_mpi_uint *T);
/**
* \brief Subtract unsigned integer from known-size large unsigned integers.
* Return the borrow.
*
* \param[out] X The result of the subtraction.
* \param[in] A The left operand.
* \param b The unsigned scalar to subtract.
* \param limbs Number of limbs of \p X and \p A.
*
* \return 1 if `A < b`.
* 0 if `A >= b`.
*/
mbedtls_mpi_uint mbedtls_mpi_core_sub_int(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
mbedtls_mpi_uint b,
size_t limbs);
/**
* \brief Determine if a given MPI has the value \c 0 in constant time with
* respect to the value (but not with respect to the number of limbs).
*
* \param[in] A The MPI to test.
* \param limbs Number of limbs in \p A.
*
* \return MBEDTLS_CT_FALSE if `A == 0`
* MBEDTLS_CT_TRUE if `A != 0`.
*/
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
* a call to `mbedtls_mpi_core_montmul()`.
*
* \param AN_limbs The number of limbs in the input `A` and the modulus `N`
* (they must be the same size) that will be given to
* `mbedtls_mpi_core_montmul()` or one of the other functions
* that specifies this as the amount of working memory needed.
*
* \return The number of limbs of working memory required by
* `mbedtls_mpi_core_montmul()` (or other similar function).
*/
static inline size_t mbedtls_mpi_core_montmul_working_limbs(size_t AN_limbs)
{
return 2 * AN_limbs + 1;
}
/** Convert an MPI into Montgomery form.
*
* \p X may be aliased to \p A, but may not otherwise overlap it.
*
* \p X may not alias \p N (it is in canonical form, so must be strictly less
* than \p N). Nor may it alias or overlap \p rr (this is unlikely to be
* required in practice.)
*
* This function is a thin wrapper around `mbedtls_mpi_core_montmul()` that is
* an alternative to calling `mbedtls_mpi_mod_raw_to_mont_rep()` when we
* don't want to allocate memory.
*
* \param[out] X The result of the conversion.
* Must have the same number of limbs as \p A.
* \param[in] A The MPI to convert into Montgomery form.
* Must have the same number of limbs as the modulus.
* \param[in] N The address of the modulus, which gives the size of
* the base `R` = 2^(biL*N->limbs).
* \param[in] AN_limbs The number of limbs in \p X, \p A, \p N and \p rr.
* \param mm The Montgomery constant for \p N: -N^-1 mod 2^biL.
* This can be determined by calling
* `mbedtls_mpi_core_montmul_init()`.
* \param[in] rr The residue for `2^{2*n*biL} mod N`.
* \param[in,out] T Temporary storage of size at least
* `mbedtls_mpi_core_montmul_working_limbs(AN_limbs)`
* limbs.
* Its initial content is unused and
* its final content is indeterminate.
* It must not alias or otherwise overlap any of the
* other parameters.
*/
void mbedtls_mpi_core_to_mont_rep(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *N,
size_t AN_limbs,
mbedtls_mpi_uint mm,
const mbedtls_mpi_uint *rr,
mbedtls_mpi_uint *T);
/** Convert an MPI from Montgomery form.
*
* \p X may be aliased to \p A, but may not otherwise overlap it.
*
* \p X may not alias \p N (it is in canonical form, so must be strictly less
* than \p N).
*
* This function is a thin wrapper around `mbedtls_mpi_core_montmul()` that is
* an alternative to calling `mbedtls_mpi_mod_raw_from_mont_rep()` when we
* don't want to allocate memory.
*
* \param[out] X The result of the conversion.
* Must have the same number of limbs as \p A.
* \param[in] A The MPI to convert from Montgomery form.
* Must have the same number of limbs as the modulus.
* \param[in] N The address of the modulus, which gives the size of
* the base `R` = 2^(biL*N->limbs).
* \param[in] AN_limbs The number of limbs in \p X, \p A and \p N.
* \param mm The Montgomery constant for \p N: -N^-1 mod 2^biL.
* This can be determined by calling
* `mbedtls_mpi_core_montmul_init()`.
* \param[in,out] T Temporary storage of size at least
* `mbedtls_mpi_core_montmul_working_limbs(AN_limbs)`
* limbs.
* Its initial content is unused and
* its final content is indeterminate.
* It must not alias or otherwise overlap any of the
* other parameters.
*/
void mbedtls_mpi_core_from_mont_rep(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *N,
size_t AN_limbs,
mbedtls_mpi_uint mm,
mbedtls_mpi_uint *T);
#endif /* MBEDTLS_BIGNUM_CORE_H */

View File

@@ -0,0 +1,50 @@
/**
* \file bignum_internal.h
*
* \brief Internal-only bignum public-key cryptosystem API.
*
* This file declares bignum-related functions that are to be used
* only from within the Mbed TLS library itself.
*
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef MBEDTLS_BIGNUM_INTERNAL_H
#define MBEDTLS_BIGNUM_INTERNAL_H
/**
* \brief Perform a modular exponentiation: X = A^E mod N
*
* \warning This function is not constant time with respect to \p E (the exponent).
*
* \param X The destination MPI. This must point to an initialized MPI.
* This must not alias E or N.
* \param A The base of the exponentiation.
* This must point to an initialized MPI.
* \param E The exponent MPI. This must point to an initialized MPI.
* \param N The base for the modular reduction. This must point to an
* initialized MPI.
* \param prec_RR A helper MPI depending solely on \p N which can be used to
* speed-up multiple modular exponentiations for the same value
* of \p N. This may be \c NULL. If it is not \c NULL, it must
* point to an initialized MPI. If it hasn't been used after
* the call to mbedtls_mpi_init(), this function will compute
* the helper value and store it in \p prec_RR for reuse on
* subsequent calls to this function. Otherwise, the function
* will assume that \p prec_RR holds the helper value set by a
* previous call to mbedtls_mpi_exp_mod(), and reuse it.
*
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.
* \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \c N is negative or
* even, or if \c E is negative.
* \return Another negative error code on different kinds of failures.
*
*/
int mbedtls_mpi_exp_mod_unsafe(mbedtls_mpi *X, const mbedtls_mpi *A,
const mbedtls_mpi *E, const mbedtls_mpi *N,
mbedtls_mpi *prec_RR);
#endif /* bignum_internal.h */

452
thirdparty/mbedtls/library/bignum_mod.h vendored Normal file
View File

@@ -0,0 +1,452 @@
/**
* Modular bignum functions
*
* This module implements operations on integers modulo some fixed modulus.
*
* The functions in this module obey the following conventions unless
* explicitly indicated otherwise:
*
* - **Modulus parameters**: the modulus is passed as a pointer to a structure
* of type #mbedtls_mpi_mod_modulus. The structure must be set up with an
* array of limbs storing the bignum value of the modulus. The modulus must
* be odd and is assumed to have no leading zeroes. The modulus is usually
* named \c N and is usually input-only. Functions which take a parameter
* of type \c const #mbedtls_mpi_mod_modulus* must not modify its value.
* - **Bignum parameters**: Bignums are passed as pointers to an array of
* limbs or to a #mbedtls_mpi_mod_residue structure. A limb has the type
* #mbedtls_mpi_uint. Residues must be initialized before use, and must be
* associated with the modulus \c N. Unless otherwise specified:
* - Bignum parameters called \c A, \c B, ... are inputs and are not
* modified by the function. Functions which take a parameter of
* type \c const #mbedtls_mpi_mod_residue* must not modify its value.
* - Bignum parameters called \c X, \c Y, ... are outputs or input-output.
* The initial bignum value of output-only parameters is ignored, but
* they must be set up and associated with the modulus \c N. Some
* functions (typically constant-flow) require that the limbs in an
* output residue are initialized.
* - Bignum parameters called \c p are inputs used to set up a modulus or
* residue. These must be pointers to an array of limbs.
* - \c T is a temporary storage area. The initial content of such a
* parameter is ignored and the final content is unspecified.
* - Some functions use different names, such as \c r for the residue.
* - **Bignum sizes**: bignum sizes are always expressed in limbs. Both
* #mbedtls_mpi_mod_modulus and #mbedtls_mpi_mod_residue have a \c limbs
* member storing its size. All bignum parameters must have the same
* number of limbs as the modulus. All bignum sizes must be at least 1 and
* must be significantly less than #SIZE_MAX. The behavior if a size is 0 is
* undefined.
* - **Bignum representation**: the representation of inputs and outputs is
* specified by the \c int_rep field of the modulus.
* - **Parameter ordering**: for bignum parameters, outputs come before inputs.
* The modulus is passed after residues. Temporaries come last.
* - **Aliasing**: in general, output bignums may be aliased to one or more
* inputs. Modulus values may not be aliased to any other parameter. Outputs
* may not be aliased to one another. Temporaries may not be aliased to any
* other parameter.
* - **Overlap**: apart from aliasing of residue pointers (where two residue
* arguments are equal pointers), overlap is not supported and may result
* in undefined behavior.
* - **Error handling**: functions generally check compatibility of input
* sizes. Most functions will not check that input values are in canonical
* form (i.e. that \c A < \c N), this is only checked during setup of a
* residue structure.
* - **Modular representatives**: all functions expect inputs to be in the
* range [0, \c N - 1] and guarantee outputs in the range [0, \c N - 1].
* Residues are set up with an associated modulus, and operations are only
* guaranteed to work if the modulus is associated with all residue
* parameters. If a residue is passed with a modulus other than the one it
* is associated with, then it may be out of range. If an input is out of
* range, outputs are fully unspecified, though bignum values out of range
* should not cause buffer overflows (beware that this is not extensively
* tested).
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef MBEDTLS_BIGNUM_MOD_H
#define MBEDTLS_BIGNUM_MOD_H
#include "common.h"
#if defined(MBEDTLS_BIGNUM_C)
#include "mbedtls/bignum.h"
#endif
/** How residues associated with a modulus are represented.
*
* This also determines which fields of the modulus structure are valid and
* what their contents are (see #mbedtls_mpi_mod_modulus).
*/
typedef enum {
/** Representation not chosen (makes the modulus structure invalid). */
MBEDTLS_MPI_MOD_REP_INVALID = 0,
/* Skip 1 as it is slightly easier to accidentally pass to functions. */
/** Montgomery representation. */
MBEDTLS_MPI_MOD_REP_MONTGOMERY = 2,
/* Optimised reduction available. This indicates a coordinate modulus (P)
* and one or more of the following have been configured:
* - A nist curve (MBEDTLS_ECP_DP_SECPXXXR1_ENABLED) & MBEDTLS_ECP_NIST_OPTIM.
* - A Kobliz Curve.
* - A Fast Reduction Curve CURVE25519 or CURVE448. */
MBEDTLS_MPI_MOD_REP_OPT_RED,
} mbedtls_mpi_mod_rep_selector;
/* Make mbedtls_mpi_mod_rep_selector and mbedtls_mpi_mod_ext_rep disjoint to
* make it easier to catch when they are accidentally swapped. */
typedef enum {
MBEDTLS_MPI_MOD_EXT_REP_INVALID = 0,
MBEDTLS_MPI_MOD_EXT_REP_LE = 8,
MBEDTLS_MPI_MOD_EXT_REP_BE
} mbedtls_mpi_mod_ext_rep;
typedef struct {
mbedtls_mpi_uint *p;
size_t limbs;
} mbedtls_mpi_mod_residue;
typedef struct {
mbedtls_mpi_uint const *rr; /* The residue for 2^{2*n*biL} mod N */
mbedtls_mpi_uint mm; /* Montgomery const for -N^{-1} mod 2^{ciL} */
} mbedtls_mpi_mont_struct;
typedef int (*mbedtls_mpi_modp_fn)(mbedtls_mpi_uint *X, size_t X_limbs);
typedef struct {
mbedtls_mpi_modp_fn modp; /* The optimised reduction function pointer */
} mbedtls_mpi_opt_red_struct;
typedef struct {
const mbedtls_mpi_uint *p;
size_t limbs; // number of limbs
size_t bits; // bitlen of p
mbedtls_mpi_mod_rep_selector int_rep; // selector to signal the active member of the union
union rep {
/* if int_rep == #MBEDTLS_MPI_MOD_REP_MONTGOMERY */
mbedtls_mpi_mont_struct mont;
/* if int_rep == #MBEDTLS_MPI_MOD_REP_OPT_RED */
mbedtls_mpi_opt_red_struct ored;
} rep;
} mbedtls_mpi_mod_modulus;
/** Setup a residue structure.
*
* The residue will be set up with the buffer \p p and modulus \p N.
*
* The memory pointed to by \p p will be used by the resulting residue structure.
* The value at the pointed-to memory will be the initial value of \p r and must
* hold a value that is less than the modulus. This value will be used as-is
* and interpreted according to the value of the `N->int_rep` field.
*
* The modulus \p N will be the modulus associated with \p r. The residue \p r
* should only be used in operations where the modulus is \p N.
*
* \param[out] r The address of the residue to setup.
* \param[in] N The address of the modulus related to \p r.
* \param[in] p The address of the limb array containing the value of \p r.
* The memory pointed to by \p p will be used by \p r and must
* not be modified in any way until after
* mbedtls_mpi_mod_residue_release() is called. The data
* pointed to by \p p must be less than the modulus (the value
* pointed to by `N->p`) and already in the representation
* indicated by `N->int_rep`.
* \param p_limbs The number of limbs of \p p. Must be the same as the number
* of limbs in the modulus \p N.
*
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p p_limbs is less than the
* limbs in \p N or if \p p is not less than \p N.
*/
int mbedtls_mpi_mod_residue_setup(mbedtls_mpi_mod_residue *r,
const mbedtls_mpi_mod_modulus *N,
mbedtls_mpi_uint *p,
size_t p_limbs);
/** Unbind elements of a residue structure.
*
* This function removes the reference to the limb array that was passed to
* mbedtls_mpi_mod_residue_setup() to make it safe to free or use again.
*
* This function invalidates \p r and it must not be used until after
* mbedtls_mpi_mod_residue_setup() is called on it again.
*
* \param[out] r The address of residue to release.
*/
void mbedtls_mpi_mod_residue_release(mbedtls_mpi_mod_residue *r);
/** Initialize a modulus structure.
*
* \param[out] N The address of the modulus structure to initialize.
*/
void mbedtls_mpi_mod_modulus_init(mbedtls_mpi_mod_modulus *N);
/** Setup a modulus structure.
*
* \param[out] N The address of the modulus structure to populate.
* \param[in] p The address of the limb array storing the value of \p N.
* The memory pointed to by \p p will be used by \p N and must
* not be modified in any way until after
* mbedtls_mpi_mod_modulus_free() is called.
* \param p_limbs The number of limbs of \p p.
*
* \return \c 0 if successful.
*/
int mbedtls_mpi_mod_modulus_setup(mbedtls_mpi_mod_modulus *N,
const mbedtls_mpi_uint *p,
size_t p_limbs);
/** Setup an optimised-reduction compatible modulus structure.
*
* \param[out] N The address of the modulus structure to populate.
* \param[in] p The address of the limb array storing the value of \p N.
* The memory pointed to by \p p will be used by \p N and must
* not be modified in any way until after
* mbedtls_mpi_mod_modulus_free() is called.
* \param p_limbs The number of limbs of \p p.
* \param modp A pointer to the optimised reduction function to use. \p p.
*
* \return \c 0 if successful.
*/
int mbedtls_mpi_mod_optred_modulus_setup(mbedtls_mpi_mod_modulus *N,
const mbedtls_mpi_uint *p,
size_t p_limbs,
mbedtls_mpi_modp_fn modp);
/** Free elements of a modulus structure.
*
* This function frees any memory allocated by mbedtls_mpi_mod_modulus_setup().
*
* \warning This function does not free the limb array passed to
* mbedtls_mpi_mod_modulus_setup() only removes the reference to it,
* making it safe to free or to use it again.
*
* \param[in,out] N The address of the modulus structure to free.
*/
void mbedtls_mpi_mod_modulus_free(mbedtls_mpi_mod_modulus *N);
/** \brief Multiply two residues, returning the residue modulo the specified
* modulus.
*
* \note Currently handles the case when `N->int_rep` is
* MBEDTLS_MPI_MOD_REP_MONTGOMERY.
*
* The size of the operation is determined by \p N. \p A, \p B and \p X must
* all be associated with the modulus \p N and must all have the same number
* of limbs as \p N.
*
* \p X may be aliased to \p A or \p B, or even both, but may not overlap
* either otherwise. They may not alias \p N (since they must be in canonical
* form, they cannot == \p N).
*
* \param[out] X The address of the result MPI. Must have the same
* number of limbs as \p N.
* On successful completion, \p X contains the result of
* the multiplication `A * B * R^-1` mod N where
* `R = 2^(biL * N->limbs)`.
* \param[in] A The address of the first MPI.
* \param[in] B The address of the second MPI.
* \param[in] N The address of the modulus. Used to perform a modulo
* operation on the result of the multiplication.
*
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if all the parameters do not
* have the same number of limbs or \p N is invalid.
* \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
*/
int mbedtls_mpi_mod_mul(mbedtls_mpi_mod_residue *X,
const mbedtls_mpi_mod_residue *A,
const mbedtls_mpi_mod_residue *B,
const mbedtls_mpi_mod_modulus *N);
/**
* \brief Perform a fixed-size modular subtraction.
*
* Calculate `A - B modulo N`.
*
* \p A, \p B and \p X must all have the same number of limbs as \p N.
*
* \p X may be aliased to \p A or \p B, or even both, but may not overlap
* either otherwise.
*
* \note This function does not check that \p A or \p B are in canonical
* form (that is, are < \p N) - that will have been done by
* mbedtls_mpi_mod_residue_setup().
*
* \param[out] X The address of the result MPI. Must be initialized.
* Must have the same number of limbs as the modulus \p N.
* \param[in] A The address of the first MPI.
* \param[in] B The address of the second MPI.
* \param[in] N The address of the modulus. Used to perform a modulo
* operation on the result of the subtraction.
*
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the given MPIs do not
* have the correct number of limbs.
*/
int mbedtls_mpi_mod_sub(mbedtls_mpi_mod_residue *X,
const mbedtls_mpi_mod_residue *A,
const mbedtls_mpi_mod_residue *B,
const mbedtls_mpi_mod_modulus *N);
/**
* \brief Perform modular inversion of an MPI with respect to a modulus \p N.
*
* \p A and \p X must be associated with the modulus \p N and will therefore
* have the same number of limbs as \p N.
*
* \p X may be aliased to \p A.
*
* \warning Currently only supports prime moduli, but does not check for them.
*
* \param[out] X The modular inverse of \p A with respect to \p N.
* \param[in] A The number to calculate the modular inverse of.
* Must not be 0.
* \param[in] N The modulus to use.
*
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p A and \p N do not
* have the same number of limbs.
* \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p A is zero.
* \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if couldn't allocate enough
* memory (needed for conversion to and from Mongtomery form
* when not in Montgomery form already, and for temporary use
* by the inversion calculation itself).
*/
int mbedtls_mpi_mod_inv(mbedtls_mpi_mod_residue *X,
const mbedtls_mpi_mod_residue *A,
const mbedtls_mpi_mod_modulus *N);
/**
* \brief Perform a fixed-size modular addition.
*
* Calculate `A + B modulo N`.
*
* \p A, \p B and \p X must all be associated with the modulus \p N and must
* all have the same number of limbs as \p N.
*
* \p X may be aliased to \p A or \p B, or even both, but may not overlap
* either otherwise.
*
* \note This function does not check that \p A or \p B are in canonical
* form (that is, are < \p N) - that will have been done by
* mbedtls_mpi_mod_residue_setup().
*
* \param[out] X The address of the result residue. Must be initialized.
* Must have the same number of limbs as the modulus \p N.
* \param[in] A The address of the first input residue.
* \param[in] B The address of the second input residue.
* \param[in] N The address of the modulus. Used to perform a modulo
* operation on the result of the addition.
*
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the given MPIs do not
* have the correct number of limbs.
*/
int mbedtls_mpi_mod_add(mbedtls_mpi_mod_residue *X,
const mbedtls_mpi_mod_residue *A,
const mbedtls_mpi_mod_residue *B,
const mbedtls_mpi_mod_modulus *N);
/** Generate a random number uniformly in a range.
*
* This function generates a random number between \p min inclusive and
* \p N exclusive.
*
* The procedure complies with RFC 6979 §3.3 (deterministic ECDSA)
* when the RNG is a suitably parametrized instance of HMAC_DRBG
* and \p min is \c 1.
*
* \note There are `N - min` possible outputs. The lower bound
* \p min can be reached, but the upper bound \p N cannot.
*
* \param X The destination residue.
* \param min The minimum value to return. It must be strictly smaller
* than \b N.
* \param N The modulus.
* This is the upper bound of the output range, exclusive.
* \param f_rng The RNG function to use. This must not be \c NULL.
* \param p_rng The RNG parameter to be passed to \p f_rng.
*
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was
* unable to find a suitable value within a limited number
* of attempts. This has a negligible probability if \p N
* is significantly larger than \p min, which is the case
* for all usual cryptographic applications.
*/
int mbedtls_mpi_mod_random(mbedtls_mpi_mod_residue *X,
mbedtls_mpi_uint min,
const mbedtls_mpi_mod_modulus *N,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng);
/** Read a residue from a byte buffer.
*
* The residue will be automatically converted to the internal representation
* based on the value of the `N->int_rep` field.
*
* The modulus \p N will be the modulus associated with \p r. The residue \p r
* should only be used in operations where the modulus is \p N or a modulus
* equivalent to \p N (in the sense that all their fields or memory pointed by
* their fields hold the same value).
*
* \param[out] r The address of the residue. It must have exactly the same
* number of limbs as the modulus \p N.
* \param[in] N The address of the modulus.
* \param[in] buf The input buffer to import from.
* \param buflen The length in bytes of \p buf.
* \param ext_rep The endianness of the number in the input buffer.
*
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p r isn't
* large enough to hold the value in \p buf.
* \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p ext_rep
* is invalid or the value in the buffer is not less than \p N.
*/
int mbedtls_mpi_mod_read(mbedtls_mpi_mod_residue *r,
const mbedtls_mpi_mod_modulus *N,
const unsigned char *buf,
size_t buflen,
mbedtls_mpi_mod_ext_rep ext_rep);
/** Write a residue into a byte buffer.
*
* The modulus \p N must be the modulus associated with \p r (see
* mbedtls_mpi_mod_residue_setup() and mbedtls_mpi_mod_read()).
*
* The residue will be automatically converted from the internal representation
* based on the value of `N->int_rep` field.
*
* \warning If the buffer is smaller than `N->bits`, the number of
* leading zeroes is leaked through timing. If \p r is
* secret, the caller must ensure that \p buflen is at least
* (`N->bits`+7)/8.
*
* \param[in] r The address of the residue. It must have the same number of
* limbs as the modulus \p N. (\p r is an input parameter, but
* its value will be modified during execution and restored
* before the function returns.)
* \param[in] N The address of the modulus associated with \p r.
* \param[out] buf The output buffer to export to.
* \param buflen The length in bytes of \p buf.
* \param ext_rep The endianness in which the number should be written into
* the output buffer.
*
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p buf isn't
* large enough to hold the value of \p r (without leading
* zeroes).
* \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p ext_rep is invalid.
* \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if couldn't allocate enough
* memory for conversion. Can occur only for moduli with
* MBEDTLS_MPI_MOD_REP_MONTGOMERY.
*/
int mbedtls_mpi_mod_write(const mbedtls_mpi_mod_residue *r,
const mbedtls_mpi_mod_modulus *N,
unsigned char *buf,
size_t buflen,
mbedtls_mpi_mod_ext_rep ext_rep);
#endif /* MBEDTLS_BIGNUM_MOD_H */

View File

@@ -0,0 +1,276 @@
/*
* Low-level modular bignum functions
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_ECP_WITH_MPI_UINT)
#include <string.h>
#include "mbedtls/error.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/platform.h"
#include "bignum_core.h"
#include "bignum_mod_raw.h"
#include "bignum_mod.h"
#include "constant_time_internal.h"
#include "bignum_mod_raw_invasive.h"
void mbedtls_mpi_mod_raw_cond_assign(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_mod_modulus *N,
unsigned char assign)
{
mbedtls_mpi_core_cond_assign(X, A, N->limbs, mbedtls_ct_bool(assign));
}
void mbedtls_mpi_mod_raw_cond_swap(mbedtls_mpi_uint *X,
mbedtls_mpi_uint *Y,
const mbedtls_mpi_mod_modulus *N,
unsigned char swap)
{
mbedtls_mpi_core_cond_swap(X, Y, N->limbs, mbedtls_ct_bool(swap));
}
int mbedtls_mpi_mod_raw_read(mbedtls_mpi_uint *X,
const mbedtls_mpi_mod_modulus *N,
const unsigned char *input,
size_t input_length,
mbedtls_mpi_mod_ext_rep ext_rep)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
switch (ext_rep) {
case MBEDTLS_MPI_MOD_EXT_REP_LE:
ret = mbedtls_mpi_core_read_le(X, N->limbs,
input, input_length);
break;
case MBEDTLS_MPI_MOD_EXT_REP_BE:
ret = mbedtls_mpi_core_read_be(X, N->limbs,
input, input_length);
break;
default:
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
}
if (ret != 0) {
goto cleanup;
}
if (!mbedtls_mpi_core_lt_ct(X, N->p, N->limbs)) {
ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
goto cleanup;
}
cleanup:
return ret;
}
int mbedtls_mpi_mod_raw_write(const mbedtls_mpi_uint *A,
const mbedtls_mpi_mod_modulus *N,
unsigned char *output,
size_t output_length,
mbedtls_mpi_mod_ext_rep ext_rep)
{
switch (ext_rep) {
case MBEDTLS_MPI_MOD_EXT_REP_LE:
return mbedtls_mpi_core_write_le(A, N->limbs,
output, output_length);
case MBEDTLS_MPI_MOD_EXT_REP_BE:
return mbedtls_mpi_core_write_be(A, N->limbs,
output, output_length);
default:
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
}
}
void mbedtls_mpi_mod_raw_sub(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *B,
const mbedtls_mpi_mod_modulus *N)
{
mbedtls_mpi_uint c = mbedtls_mpi_core_sub(X, A, B, N->limbs);
(void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) c);
}
MBEDTLS_STATIC_TESTABLE
void mbedtls_mpi_mod_raw_fix_quasi_reduction(mbedtls_mpi_uint *X,
const mbedtls_mpi_mod_modulus *N)
{
mbedtls_mpi_uint c = mbedtls_mpi_core_sub(X, X, N->p, N->limbs);
(void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) c);
}
void mbedtls_mpi_mod_raw_mul(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *B,
const mbedtls_mpi_mod_modulus *N,
mbedtls_mpi_uint *T)
{
/* Standard (A * B) multiplication stored into pre-allocated T
* buffer of fixed limb size of (2N + 1).
*
* The space may not not fully filled by when
* MBEDTLS_MPI_MOD_REP_OPT_RED is used. */
const size_t T_limbs = BITS_TO_LIMBS(N->bits) * 2;
switch (N->int_rep) {
case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
mbedtls_mpi_core_montmul(X, A, B, N->limbs, N->p, N->limbs,
N->rep.mont.mm, T);
break;
case MBEDTLS_MPI_MOD_REP_OPT_RED:
mbedtls_mpi_core_mul(T, A, N->limbs, B, N->limbs);
/* Optimised Reduction */
(*N->rep.ored.modp)(T, T_limbs);
/* Convert back to canonical representation */
mbedtls_mpi_mod_raw_fix_quasi_reduction(T, N);
memcpy(X, T, N->limbs * sizeof(mbedtls_mpi_uint));
break;
default:
break;
}
}
size_t mbedtls_mpi_mod_raw_inv_prime_working_limbs(size_t AN_limbs)
{
/* mbedtls_mpi_mod_raw_inv_prime() needs a temporary for the exponent,
* which will be the same size as the modulus and input (AN_limbs),
* and additional space to pass to mbedtls_mpi_core_exp_mod(). */
return AN_limbs +
mbedtls_mpi_core_exp_mod_working_limbs(AN_limbs, AN_limbs);
}
void mbedtls_mpi_mod_raw_inv_prime(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *N,
size_t AN_limbs,
const mbedtls_mpi_uint *RR,
mbedtls_mpi_uint *T)
{
/* Inversion by power: g^|G| = 1 => g^(-1) = g^(|G|-1), and
* |G| = N - 1, so we want
* g^(|G|-1) = g^(N - 2)
*/
/* Use the first AN_limbs of T to hold N - 2 */
mbedtls_mpi_uint *Nminus2 = T;
(void) mbedtls_mpi_core_sub_int(Nminus2, N, 2, AN_limbs);
/* Rest of T is given to exp_mod for its working space */
mbedtls_mpi_core_exp_mod(X,
A, N, AN_limbs, Nminus2, AN_limbs,
RR, T + AN_limbs);
}
void mbedtls_mpi_mod_raw_add(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *B,
const mbedtls_mpi_mod_modulus *N)
{
mbedtls_mpi_uint carry, borrow;
carry = mbedtls_mpi_core_add(X, A, B, N->limbs);
borrow = mbedtls_mpi_core_sub(X, X, N->p, N->limbs);
(void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) (carry ^ borrow));
}
int mbedtls_mpi_mod_raw_canonical_to_modulus_rep(
mbedtls_mpi_uint *X,
const mbedtls_mpi_mod_modulus *N)
{
switch (N->int_rep) {
case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
return mbedtls_mpi_mod_raw_to_mont_rep(X, N);
case MBEDTLS_MPI_MOD_REP_OPT_RED:
return 0;
default:
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
}
}
int mbedtls_mpi_mod_raw_modulus_to_canonical_rep(
mbedtls_mpi_uint *X,
const mbedtls_mpi_mod_modulus *N)
{
switch (N->int_rep) {
case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
return mbedtls_mpi_mod_raw_from_mont_rep(X, N);
case MBEDTLS_MPI_MOD_REP_OPT_RED:
return 0;
default:
return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
}
}
int mbedtls_mpi_mod_raw_random(mbedtls_mpi_uint *X,
mbedtls_mpi_uint min,
const mbedtls_mpi_mod_modulus *N,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng)
{
int ret = mbedtls_mpi_core_random(X, min, N->p, N->limbs, f_rng, p_rng);
if (ret != 0) {
return ret;
}
return mbedtls_mpi_mod_raw_canonical_to_modulus_rep(X, N);
}
int mbedtls_mpi_mod_raw_to_mont_rep(mbedtls_mpi_uint *X,
const mbedtls_mpi_mod_modulus *N)
{
mbedtls_mpi_uint *T;
const size_t t_limbs = mbedtls_mpi_core_montmul_working_limbs(N->limbs);
if ((T = (mbedtls_mpi_uint *) mbedtls_calloc(t_limbs, ciL)) == NULL) {
return MBEDTLS_ERR_MPI_ALLOC_FAILED;
}
mbedtls_mpi_core_to_mont_rep(X, X, N->p, N->limbs,
N->rep.mont.mm, N->rep.mont.rr, T);
mbedtls_zeroize_and_free(T, t_limbs * ciL);
return 0;
}
int mbedtls_mpi_mod_raw_from_mont_rep(mbedtls_mpi_uint *X,
const mbedtls_mpi_mod_modulus *N)
{
const size_t t_limbs = mbedtls_mpi_core_montmul_working_limbs(N->limbs);
mbedtls_mpi_uint *T;
if ((T = (mbedtls_mpi_uint *) mbedtls_calloc(t_limbs, ciL)) == NULL) {
return MBEDTLS_ERR_MPI_ALLOC_FAILED;
}
mbedtls_mpi_core_from_mont_rep(X, X, N->p, N->limbs, N->rep.mont.mm, T);
mbedtls_zeroize_and_free(T, t_limbs * ciL);
return 0;
}
void mbedtls_mpi_mod_raw_neg(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_mod_modulus *N)
{
mbedtls_mpi_core_sub(X, N->p, A, N->limbs);
/* If A=0 initially, then X=N now. Detect this by
* subtracting N and catching the carry. */
mbedtls_mpi_uint borrow = mbedtls_mpi_core_sub(X, X, N->p, N->limbs);
(void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) borrow);
}
#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ECP_WITH_MPI_UINT */

View File

@@ -0,0 +1,416 @@
/**
* Low-level modular bignum functions
*
* This interface should only be used by the higher-level modular bignum
* module (bignum_mod.c) and the ECP module (ecp.c, ecp_curves.c). All other
* modules should use the high-level modular bignum interface (bignum_mod.h)
* or the legacy bignum interface (bignum.h).
*
* This is a low-level interface to operations on integers modulo which
* has no protection against passing invalid arguments such as arrays of
* the wrong size. The functions in bignum_mod.h provide a higher-level
* interface that includes protections against accidental misuse, at the
* expense of code size and sometimes more cumbersome memory management.
*
* The functions in this module obey the following conventions unless
* explicitly indicated otherwise:
* - **Modulus parameters**: the modulus is passed as a pointer to a structure
* of type #mbedtls_mpi_mod_modulus. The structure must be set up with an
* array of limbs storing the bignum value of the modulus. The modulus must
* be odd and is assumed to have no leading zeroes. The modulus is usually
* named \c N and is usually input-only.
* - **Bignum parameters**: Bignums are passed as pointers to an array of
* limbs. A limb has the type #mbedtls_mpi_uint. Unless otherwise specified:
* - Bignum parameters called \c A, \c B, ... are inputs, and are not
* modified by the function.
* - Bignum parameters called \c X, \c Y are outputs or input-output.
* The initial content of output-only parameters is ignored.
* - \c T is a temporary storage area. The initial content of such a
* parameter is ignored and the final content is unspecified.
* - **Bignum sizes**: bignum sizes are usually expressed by the \c limbs
* member of the modulus argument. All bignum parameters must have the same
* number of limbs as the modulus. All bignum sizes must be at least 1 and
* must be significantly less than #SIZE_MAX. The behavior if a size is 0 is
* undefined.
* - **Bignum representation**: the representation of inputs and outputs is
* specified by the \c int_rep field of the modulus for arithmetic
* functions. Utility functions may allow for different representation.
* - **Parameter ordering**: for bignum parameters, outputs come before inputs.
* The modulus is passed after other bignum input parameters. Temporaries
* come last.
* - **Aliasing**: in general, output bignums may be aliased to one or more
* inputs. Modulus values may not be aliased to any other parameter. Outputs
* may not be aliased to one another. Temporaries may not be aliased to any
* other parameter.
* - **Overlap**: apart from aliasing of limb array pointers (where two
* arguments are equal pointers), overlap is not supported and may result
* in undefined behavior.
* - **Error handling**: This is a low-level module. Functions generally do not
* try to protect against invalid arguments such as nonsensical sizes or
* null pointers. Note that passing bignums with a different size than the
* modulus may lead to buffer overflows. Some functions which allocate
* memory or handle reading/writing of bignums will return an error if
* memory allocation fails or if buffer sizes are invalid.
* - **Modular representatives**: all functions expect inputs to be in the
* range [0, \c N - 1] and guarantee outputs in the range [0, \c N - 1]. If
* an input is out of range, outputs are fully unspecified, though bignum
* values out of range should not cause buffer overflows (beware that this is
* not extensively tested).
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef MBEDTLS_BIGNUM_MOD_RAW_H
#define MBEDTLS_BIGNUM_MOD_RAW_H
#include "common.h"
#if defined(MBEDTLS_BIGNUM_C)
#include "mbedtls/bignum.h"
#endif
#include "bignum_mod.h"
/**
* \brief Perform a safe conditional copy of an MPI which doesn't reveal
* whether the assignment was done or not.
*
* The size to copy is determined by \p N.
*
* \param[out] X The address of the destination MPI.
* This must be initialized. Must have enough limbs to
* store the full value of \p A.
* \param[in] A The address of the source MPI. This must be initialized.
* \param[in] N The address of the modulus related to \p X and \p A.
* \param assign The condition deciding whether to perform the
* assignment or not. Must be either 0 or 1:
* * \c 1: Perform the assignment `X = A`.
* * \c 0: Keep the original value of \p X.
*
* \note This function avoids leaking any information about whether
* the assignment was done or not.
*
* \warning If \p assign is neither 0 nor 1, the result of this function
* is indeterminate, and the resulting value in \p X might be
* neither its original value nor the value in \p A.
*/
void mbedtls_mpi_mod_raw_cond_assign(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_mod_modulus *N,
unsigned char assign);
/**
* \brief Perform a safe conditional swap of two MPIs which doesn't reveal
* whether the swap was done or not.
*
* The size to swap is determined by \p N.
*
* \param[in,out] X The address of the first MPI. This must be initialized.
* \param[in,out] Y The address of the second MPI. This must be initialized.
* \param[in] N The address of the modulus related to \p X and \p Y.
* \param swap The condition deciding whether to perform
* the swap or not. Must be either 0 or 1:
* * \c 1: Swap the values of \p X and \p Y.
* * \c 0: Keep the original values of \p X and \p Y.
*
* \note This function avoids leaking any information about whether
* the swap was done or not.
*
* \warning If \p swap is neither 0 nor 1, the result of this function
* is indeterminate, and both \p X and \p Y might end up with
* values different to either of the original ones.
*/
void mbedtls_mpi_mod_raw_cond_swap(mbedtls_mpi_uint *X,
mbedtls_mpi_uint *Y,
const mbedtls_mpi_mod_modulus *N,
unsigned char swap);
/** Import X from unsigned binary data.
*
* The MPI needs to have enough limbs to store the full value (including any
* most significant zero bytes in the input).
*
* \param[out] X The address of the MPI. The size is determined by \p N.
* (In particular, it must have at least as many limbs as
* the modulus \p N.)
* \param[in] N The address of the modulus related to \p X.
* \param[in] input The input buffer to import from.
* \param input_length The length in bytes of \p input.
* \param ext_rep The endianness of the number in the input buffer.
*
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p X isn't
* large enough to hold the value in \p input.
* \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the external representation
* of \p N is invalid or \p X is not less than \p N.
*/
int mbedtls_mpi_mod_raw_read(mbedtls_mpi_uint *X,
const mbedtls_mpi_mod_modulus *N,
const unsigned char *input,
size_t input_length,
mbedtls_mpi_mod_ext_rep ext_rep);
/** Export A into unsigned binary data.
*
* \param[in] A The address of the MPI. The size is determined by \p N.
* (In particular, it must have at least as many limbs as
* the modulus \p N.)
* \param[in] N The address of the modulus related to \p A.
* \param[out] output The output buffer to export to.
* \param output_length The length in bytes of \p output.
* \param ext_rep The endianness in which the number should be written into the output buffer.
*
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p output isn't
* large enough to hold the value of \p A.
* \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the external representation
* of \p N is invalid.
*/
int mbedtls_mpi_mod_raw_write(const mbedtls_mpi_uint *A,
const mbedtls_mpi_mod_modulus *N,
unsigned char *output,
size_t output_length,
mbedtls_mpi_mod_ext_rep ext_rep);
/** \brief Subtract two MPIs, returning the residue modulo the specified
* modulus.
*
* The size of the operation is determined by \p N. \p A and \p B must have
* the same number of limbs as \p N.
*
* \p X may be aliased to \p A or \p B, or even both, but may not overlap
* either otherwise.
*
* \param[out] X The address of the result MPI.
* This must be initialized. Must have enough limbs to
* store the full value of the result.
* \param[in] A The address of the first MPI. This must be initialized.
* \param[in] B The address of the second MPI. This must be initialized.
* \param[in] N The address of the modulus. Used to perform a modulo
* operation on the result of the subtraction.
*/
void mbedtls_mpi_mod_raw_sub(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *B,
const mbedtls_mpi_mod_modulus *N);
/** \brief Multiply two MPIs, returning the residue modulo the specified
* modulus.
*
* \note Currently handles the case when `N->int_rep` is
* MBEDTLS_MPI_MOD_REP_MONTGOMERY.
*
* The size of the operation is determined by \p N. \p A, \p B and \p X must
* all be associated with the modulus \p N and must all have the same number
* of limbs as \p N.
*
* \p X may be aliased to \p A or \p B, or even both, but may not overlap
* either otherwise. They may not alias \p N (since they must be in canonical
* form, they cannot == \p N).
*
* \param[out] X The address of the result MPI. Must have the same
* number of limbs as \p N.
* On successful completion, \p X contains the result of
* the multiplication `A * B * R^-1` mod N where
* `R = 2^(biL * N->limbs)`.
* \param[in] A The address of the first MPI.
* \param[in] B The address of the second MPI.
* \param[in] N The address of the modulus. Used to perform a modulo
* operation on the result of the multiplication.
* \param[in,out] T Temporary storage of size at least 2 * N->limbs + 1
* limbs. Its initial content is unused and
* its final content is indeterminate.
* It must not alias or otherwise overlap any of the
* other parameters.
*/
void mbedtls_mpi_mod_raw_mul(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *B,
const mbedtls_mpi_mod_modulus *N,
mbedtls_mpi_uint *T);
/**
* \brief Returns the number of limbs of working memory required for
* a call to `mbedtls_mpi_mod_raw_inv_prime()`.
*
* \note This will always be at least
* `mbedtls_mpi_core_montmul_working_limbs(AN_limbs)`,
* i.e. sufficient for a call to `mbedtls_mpi_core_montmul()`.
*
* \param AN_limbs The number of limbs in the input `A` and the modulus `N`
* (they must be the same size) that will be given to
* `mbedtls_mpi_mod_raw_inv_prime()`.
*
* \return The number of limbs of working memory required by
* `mbedtls_mpi_mod_raw_inv_prime()`.
*/
size_t mbedtls_mpi_mod_raw_inv_prime_working_limbs(size_t AN_limbs);
/**
* \brief Perform fixed-width modular inversion of a Montgomery-form MPI with
* respect to a modulus \p N that must be prime.
*
* \p X may be aliased to \p A, but not to \p N or \p RR.
*
* \param[out] X The modular inverse of \p A with respect to \p N.
* Will be in Montgomery form.
* \param[in] A The number to calculate the modular inverse of.
* Must be in Montgomery form. Must not be 0.
* \param[in] N The modulus, as a little-endian array of length \p AN_limbs.
* Must be prime.
* \param AN_limbs The number of limbs in \p A, \p N and \p RR.
* \param[in] RR The precomputed residue of 2^{2*biL} modulo N, as a little-
* endian array of length \p AN_limbs.
* \param[in,out] T Temporary storage of at least the number of limbs returned
* by `mbedtls_mpi_mod_raw_inv_prime_working_limbs()`.
* Its initial content is unused and its final content is
* indeterminate.
* It must not alias or otherwise overlap any of the other
* parameters.
* It is up to the caller to zeroize \p T when it is no
* longer needed, and before freeing it if it was dynamically
* allocated.
*/
void mbedtls_mpi_mod_raw_inv_prime(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *N,
size_t AN_limbs,
const mbedtls_mpi_uint *RR,
mbedtls_mpi_uint *T);
/**
* \brief Perform a known-size modular addition.
*
* Calculate `A + B modulo N`.
*
* The number of limbs in each operand, and the result, is given by the
* modulus \p N.
*
* \p X may be aliased to \p A or \p B, or even both, but may not overlap
* either otherwise.
*
* \param[out] X The result of the modular addition.
* \param[in] A Little-endian presentation of the left operand. This
* must be smaller than \p N.
* \param[in] B Little-endian presentation of the right operand. This
* must be smaller than \p N.
* \param[in] N The address of the modulus.
*/
void mbedtls_mpi_mod_raw_add(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_uint *B,
const mbedtls_mpi_mod_modulus *N);
/** Convert an MPI from canonical representation (little-endian limb array)
* to the representation associated with the modulus.
*
* \param[in,out] X The limb array to convert.
* It must have as many limbs as \p N.
* It is converted in place.
* If this function returns an error, the content of \p X
* is unspecified.
* \param[in] N The modulus structure.
*
* \return \c 0 if successful.
* Otherwise an \c MBEDTLS_ERR_MPI_xxx error code.
*/
int mbedtls_mpi_mod_raw_canonical_to_modulus_rep(
mbedtls_mpi_uint *X,
const mbedtls_mpi_mod_modulus *N);
/** Convert an MPI from the representation associated with the modulus
* to canonical representation (little-endian limb array).
*
* \param[in,out] X The limb array to convert.
* It must have as many limbs as \p N.
* It is converted in place.
* If this function returns an error, the content of \p X
* is unspecified.
* \param[in] N The modulus structure.
*
* \return \c 0 if successful.
* Otherwise an \c MBEDTLS_ERR_MPI_xxx error code.
*/
int mbedtls_mpi_mod_raw_modulus_to_canonical_rep(
mbedtls_mpi_uint *X,
const mbedtls_mpi_mod_modulus *N);
/** Generate a random number uniformly in a range.
*
* This function generates a random number between \p min inclusive and
* \p N exclusive.
*
* The procedure complies with RFC 6979 §3.3 (deterministic ECDSA)
* when the RNG is a suitably parametrized instance of HMAC_DRBG
* and \p min is \c 1.
*
* \note There are `N - min` possible outputs. The lower bound
* \p min can be reached, but the upper bound \p N cannot.
*
* \param X The destination MPI, in canonical representation modulo \p N.
* It must not be aliased with \p N or otherwise overlap it.
* \param min The minimum value to return. It must be strictly smaller
* than \b N.
* \param N The modulus.
* This is the upper bound of the output range, exclusive.
* \param f_rng The RNG function to use. This must not be \c NULL.
* \param p_rng The RNG parameter to be passed to \p f_rng.
*
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was
* unable to find a suitable value within a limited number
* of attempts. This has a negligible probability if \p N
* is significantly larger than \p min, which is the case
* for all usual cryptographic applications.
*/
int mbedtls_mpi_mod_raw_random(mbedtls_mpi_uint *X,
mbedtls_mpi_uint min,
const mbedtls_mpi_mod_modulus *N,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng);
/** Convert an MPI into Montgomery form.
*
* \param X The address of the MPI.
* Must have the same number of limbs as \p N.
* \param N The address of the modulus, which gives the size of
* the base `R` = 2^(biL*N->limbs).
*
* \return \c 0 if successful.
*/
int mbedtls_mpi_mod_raw_to_mont_rep(mbedtls_mpi_uint *X,
const mbedtls_mpi_mod_modulus *N);
/** Convert an MPI back from Montgomery representation.
*
* \param X The address of the MPI.
* Must have the same number of limbs as \p N.
* \param N The address of the modulus, which gives the size of
* the base `R`= 2^(biL*N->limbs).
*
* \return \c 0 if successful.
*/
int mbedtls_mpi_mod_raw_from_mont_rep(mbedtls_mpi_uint *X,
const mbedtls_mpi_mod_modulus *N);
/** \brief Perform fixed width modular negation.
*
* The size of the operation is determined by \p N. \p A must have
* the same number of limbs as \p N.
*
* \p X may be aliased to \p A.
*
* \param[out] X The result of the modular negation.
* This must be initialized.
* \param[in] A Little-endian presentation of the input operand. This
* must be less than or equal to \p N.
* \param[in] N The modulus to use.
*/
void mbedtls_mpi_mod_raw_neg(mbedtls_mpi_uint *X,
const mbedtls_mpi_uint *A,
const mbedtls_mpi_mod_modulus *N);
#endif /* MBEDTLS_BIGNUM_MOD_RAW_H */

View File

@@ -0,0 +1,34 @@
/**
* \file bignum_mod_raw_invasive.h
*
* \brief Function declarations for invasive functions of Low-level
* modular bignum.
*/
/**
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef MBEDTLS_BIGNUM_MOD_RAW_INVASIVE_H
#define MBEDTLS_BIGNUM_MOD_RAW_INVASIVE_H
#include "common.h"
#include "mbedtls/bignum.h"
#include "bignum_mod.h"
#if defined(MBEDTLS_TEST_HOOKS)
/** Convert the result of a quasi-reduction to its canonical representative.
*
* \param[in,out] X The address of the MPI to be converted. Must have the
* same number of limbs as \p N. The input value must
* be in range 0 <= X < 2N.
* \param[in] N The address of the modulus.
*/
MBEDTLS_STATIC_TESTABLE
void mbedtls_mpi_mod_raw_fix_quasi_reduction(mbedtls_mpi_uint *X,
const mbedtls_mpi_mod_modulus *N);
#endif /* MBEDTLS_TEST_HOOKS */
#endif /* MBEDTLS_BIGNUM_MOD_RAW_INVASIVE_H */

View File

@@ -0,0 +1,99 @@
/**
* \file block_cipher_internal.h
*
* \brief Lightweight abstraction layer for block ciphers with 128 bit blocks,
* for use by the GCM and CCM modules.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef MBEDTLS_BLOCK_CIPHER_INTERNAL_H
#define MBEDTLS_BLOCK_CIPHER_INTERNAL_H
#include "mbedtls/build_info.h"
#include "mbedtls/cipher.h"
#include "mbedtls/block_cipher.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Initialize the context.
* This must be the first API call before using the context.
*
* \param ctx The context to initialize.
*/
static inline void mbedtls_block_cipher_init(mbedtls_block_cipher_context_t *ctx)
{
memset(ctx, 0, sizeof(*ctx));
}
/**
* \brief Set the block cipher to use with this context.
* This must be called after mbedtls_block_cipher_init().
*
* \param ctx The context to set up.
* \param cipher_id The identifier of the cipher to use.
* This must be either AES, ARIA or Camellia.
* Warning: this is a ::mbedtls_cipher_id_t,
* not a ::mbedtls_block_cipher_id_t!
*
* \retval \c 0 on success.
* \retval #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if \p cipher_id was
* invalid.
*/
int mbedtls_block_cipher_setup(mbedtls_block_cipher_context_t *ctx,
mbedtls_cipher_id_t cipher_id);
/**
* \brief Set the key into the context.
*
* \param ctx The context to configure.
* \param key The buffer holding the key material.
* \param key_bitlen The size of the key in bits.
*
* \retval \c 0 on success.
* \retval #MBEDTLS_ERR_CIPHER_INVALID_CONTEXT if the context was not
* properly set up before calling this function.
* \retval One of #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH,
* #MBEDTLS_ERR_ARIA_BAD_INPUT_DATA,
* #MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA if \p key_bitlen is
* invalid.
*/
int mbedtls_block_cipher_setkey(mbedtls_block_cipher_context_t *ctx,
const unsigned char *key,
unsigned key_bitlen);
/**
* \brief Encrypt one block (16 bytes) with the configured key.
*
* \param ctx The context holding the key.
* \param input The buffer holding the input block. Must be 16 bytes.
* \param output The buffer to which the output block will be written.
* Must be writable and 16 bytes long.
* This must either not overlap with \p input, or be equal.
*
* \retval \c 0 on success.
* \retval #MBEDTLS_ERR_CIPHER_INVALID_CONTEXT if the context was not
* properly set up before calling this function.
* \retval Another negative value if encryption failed.
*/
int mbedtls_block_cipher_encrypt(mbedtls_block_cipher_context_t *ctx,
const unsigned char input[16],
unsigned char output[16]);
/**
* \brief Clear the context.
*
* \param ctx The context to clear.
*/
void mbedtls_block_cipher_free(mbedtls_block_cipher_context_t *ctx);
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_BLOCK_CIPHER_INTERNAL_H */

1094
thirdparty/mbedtls/library/bn_mul.h vendored Normal file

File diff suppressed because it is too large Load Diff

1058
thirdparty/mbedtls/library/camellia.c vendored Normal file

File diff suppressed because it is too large Load Diff

764
thirdparty/mbedtls/library/ccm.c vendored Normal file
View File

@@ -0,0 +1,764 @@
/*
* NIST SP800-38C compliant CCM implementation
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
/*
* Definition of CCM:
* http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf
* RFC 3610 "Counter with CBC-MAC (CCM)"
*
* Related:
* RFC 5116 "An Interface and Algorithms for Authenticated Encryption"
*/
#include "common.h"
#if defined(MBEDTLS_CCM_C)
#include "mbedtls/ccm.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#include "mbedtls/constant_time.h"
#if defined(MBEDTLS_BLOCK_CIPHER_C)
#include "block_cipher_internal.h"
#endif
#include <string.h>
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
#endif /* MBEDTLS_PLATFORM_C */
#if !defined(MBEDTLS_CCM_ALT)
/*
* Initialize context
*/
void mbedtls_ccm_init(mbedtls_ccm_context *ctx)
{
memset(ctx, 0, sizeof(mbedtls_ccm_context));
}
int mbedtls_ccm_setkey(mbedtls_ccm_context *ctx,
mbedtls_cipher_id_t cipher,
const unsigned char *key,
unsigned int keybits)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_BLOCK_CIPHER_C)
mbedtls_block_cipher_free(&ctx->block_cipher_ctx);
if ((ret = mbedtls_block_cipher_setup(&ctx->block_cipher_ctx, cipher)) != 0) {
return MBEDTLS_ERR_CCM_BAD_INPUT;
}
if ((ret = mbedtls_block_cipher_setkey(&ctx->block_cipher_ctx, key, keybits)) != 0) {
return MBEDTLS_ERR_CCM_BAD_INPUT;
}
#else
const mbedtls_cipher_info_t *cipher_info;
cipher_info = mbedtls_cipher_info_from_values(cipher, keybits,
MBEDTLS_MODE_ECB);
if (cipher_info == NULL) {
return MBEDTLS_ERR_CCM_BAD_INPUT;
}
if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) {
return MBEDTLS_ERR_CCM_BAD_INPUT;
}
mbedtls_cipher_free(&ctx->cipher_ctx);
if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) {
return ret;
}
if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,
MBEDTLS_ENCRYPT)) != 0) {
return ret;
}
#endif
return ret;
}
/*
* Free context
*/
void mbedtls_ccm_free(mbedtls_ccm_context *ctx)
{
if (ctx == NULL) {
return;
}
#if defined(MBEDTLS_BLOCK_CIPHER_C)
mbedtls_block_cipher_free(&ctx->block_cipher_ctx);
#else
mbedtls_cipher_free(&ctx->cipher_ctx);
#endif
mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ccm_context));
}
#define CCM_STATE__CLEAR 0
#define CCM_STATE__STARTED (1 << 0)
#define CCM_STATE__LENGTHS_SET (1 << 1)
#define CCM_STATE__AUTH_DATA_STARTED (1 << 2)
#define CCM_STATE__AUTH_DATA_FINISHED (1 << 3)
#define CCM_STATE__ERROR (1 << 4)
/*
* Encrypt or decrypt a partial block with CTR
*/
static int mbedtls_ccm_crypt(mbedtls_ccm_context *ctx,
size_t offset, size_t use_len,
const unsigned char *input,
unsigned char *output)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char tmp_buf[16] = { 0 };
#if defined(MBEDTLS_BLOCK_CIPHER_C)
ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->ctr, tmp_buf);
#else
size_t olen = 0;
ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->ctr, 16, tmp_buf, &olen);
#endif
if (ret != 0) {
ctx->state |= CCM_STATE__ERROR;
mbedtls_platform_zeroize(tmp_buf, sizeof(tmp_buf));
return ret;
}
mbedtls_xor(output, input, tmp_buf + offset, use_len);
mbedtls_platform_zeroize(tmp_buf, sizeof(tmp_buf));
return ret;
}
static void mbedtls_ccm_clear_state(mbedtls_ccm_context *ctx)
{
ctx->state = CCM_STATE__CLEAR;
memset(ctx->y, 0, 16);
memset(ctx->ctr, 0, 16);
}
static int ccm_calculate_first_block_if_ready(mbedtls_ccm_context *ctx)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char i;
size_t len_left;
#if !defined(MBEDTLS_BLOCK_CIPHER_C)
size_t olen;
#endif
/* length calculation can be done only after both
* mbedtls_ccm_starts() and mbedtls_ccm_set_lengths() have been executed
*/
if (!(ctx->state & CCM_STATE__STARTED) || !(ctx->state & CCM_STATE__LENGTHS_SET)) {
return 0;
}
/* CCM expects non-empty tag.
* CCM* allows empty tag. For CCM* without tag, the tag calculation is skipped.
*/
if (ctx->tag_len == 0) {
if (ctx->mode == MBEDTLS_CCM_STAR_ENCRYPT || ctx->mode == MBEDTLS_CCM_STAR_DECRYPT) {
ctx->plaintext_len = 0;
return 0;
} else {
return MBEDTLS_ERR_CCM_BAD_INPUT;
}
}
/*
* First block:
* 0 .. 0 flags
* 1 .. iv_len nonce (aka iv) - set by: mbedtls_ccm_starts()
* iv_len+1 .. 15 length
*
* With flags as (bits):
* 7 0
* 6 add present?
* 5 .. 3 (t - 2) / 2
* 2 .. 0 q - 1
*/
ctx->y[0] |= (ctx->add_len > 0) << 6;
ctx->y[0] |= ((ctx->tag_len - 2) / 2) << 3;
ctx->y[0] |= ctx->q - 1;
for (i = 0, len_left = ctx->plaintext_len; i < ctx->q; i++, len_left >>= 8) {
ctx->y[15-i] = MBEDTLS_BYTE_0(len_left);
}
if (len_left > 0) {
ctx->state |= CCM_STATE__ERROR;
return MBEDTLS_ERR_CCM_BAD_INPUT;
}
/* Start CBC-MAC with first block*/
#if defined(MBEDTLS_BLOCK_CIPHER_C)
ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->y);
#else
ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen);
#endif
if (ret != 0) {
ctx->state |= CCM_STATE__ERROR;
return ret;
}
return 0;
}
int mbedtls_ccm_starts(mbedtls_ccm_context *ctx,
int mode,
const unsigned char *iv,
size_t iv_len)
{
/* Also implies q is within bounds */
if (iv_len < 7 || iv_len > 13) {
return MBEDTLS_ERR_CCM_BAD_INPUT;
}
ctx->mode = mode;
ctx->q = 16 - 1 - (unsigned char) iv_len;
/*
* Prepare counter block for encryption:
* 0 .. 0 flags
* 1 .. iv_len nonce (aka iv)
* iv_len+1 .. 15 counter (initially 1)
*
* With flags as (bits):
* 7 .. 3 0
* 2 .. 0 q - 1
*/
memset(ctx->ctr, 0, 16);
ctx->ctr[0] = ctx->q - 1;
memcpy(ctx->ctr + 1, iv, iv_len);
memset(ctx->ctr + 1 + iv_len, 0, ctx->q);
ctx->ctr[15] = 1;
/*
* See ccm_calculate_first_block_if_ready() for block layout description
*/
memcpy(ctx->y + 1, iv, iv_len);
ctx->state |= CCM_STATE__STARTED;
return ccm_calculate_first_block_if_ready(ctx);
}
int mbedtls_ccm_set_lengths(mbedtls_ccm_context *ctx,
size_t total_ad_len,
size_t plaintext_len,
size_t tag_len)
{
/*
* Check length requirements: SP800-38C A.1
* Additional requirement: a < 2^16 - 2^8 to simplify the code.
* 'length' checked later (when writing it to the first block)
*
* Also, loosen the requirements to enable support for CCM* (IEEE 802.15.4).
*/
if (tag_len == 2 || tag_len > 16 || tag_len % 2 != 0) {
return MBEDTLS_ERR_CCM_BAD_INPUT;
}
if (total_ad_len >= 0xFF00) {
return MBEDTLS_ERR_CCM_BAD_INPUT;
}
ctx->plaintext_len = plaintext_len;
ctx->add_len = total_ad_len;
ctx->tag_len = tag_len;
ctx->processed = 0;
ctx->state |= CCM_STATE__LENGTHS_SET;
return ccm_calculate_first_block_if_ready(ctx);
}
int mbedtls_ccm_update_ad(mbedtls_ccm_context *ctx,
const unsigned char *add,
size_t add_len)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t use_len, offset;
#if !defined(MBEDTLS_BLOCK_CIPHER_C)
size_t olen;
#endif
if (ctx->state & CCM_STATE__ERROR) {
return MBEDTLS_ERR_CCM_BAD_INPUT;
}
if (add_len > 0) {
if (ctx->state & CCM_STATE__AUTH_DATA_FINISHED) {
return MBEDTLS_ERR_CCM_BAD_INPUT;
}
if (!(ctx->state & CCM_STATE__AUTH_DATA_STARTED)) {
if (add_len > ctx->add_len) {
return MBEDTLS_ERR_CCM_BAD_INPUT;
}
ctx->y[0] ^= (unsigned char) ((ctx->add_len >> 8) & 0xFF);
ctx->y[1] ^= (unsigned char) ((ctx->add_len) & 0xFF);
ctx->state |= CCM_STATE__AUTH_DATA_STARTED;
} else if (ctx->processed + add_len > ctx->add_len) {
return MBEDTLS_ERR_CCM_BAD_INPUT;
}
while (add_len > 0) {
offset = (ctx->processed + 2) % 16; /* account for y[0] and y[1]
* holding total auth data length */
use_len = 16 - offset;
if (use_len > add_len) {
use_len = add_len;
}
mbedtls_xor(ctx->y + offset, ctx->y + offset, add, use_len);
ctx->processed += use_len;
add_len -= use_len;
add += use_len;
if (use_len + offset == 16 || ctx->processed == ctx->add_len) {
#if defined(MBEDTLS_BLOCK_CIPHER_C)
ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->y);
#else
ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen);
#endif
if (ret != 0) {
ctx->state |= CCM_STATE__ERROR;
return ret;
}
}
}
if (ctx->processed == ctx->add_len) {
ctx->state |= CCM_STATE__AUTH_DATA_FINISHED;
ctx->processed = 0; // prepare for mbedtls_ccm_update()
}
}
return 0;
}
int mbedtls_ccm_update(mbedtls_ccm_context *ctx,
const unsigned char *input, size_t input_len,
unsigned char *output, size_t output_size,
size_t *output_len)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char i;
size_t use_len, offset;
#if !defined(MBEDTLS_BLOCK_CIPHER_C)
size_t olen;
#endif
unsigned char local_output[16];
if (ctx->state & CCM_STATE__ERROR) {
return MBEDTLS_ERR_CCM_BAD_INPUT;
}
/* Check against plaintext length only if performing operation with
* authentication
*/
if (ctx->tag_len != 0 && ctx->processed + input_len > ctx->plaintext_len) {
return MBEDTLS_ERR_CCM_BAD_INPUT;
}
if (output_size < input_len) {
return MBEDTLS_ERR_CCM_BAD_INPUT;
}
*output_len = input_len;
ret = 0;
while (input_len > 0) {
offset = ctx->processed % 16;
use_len = 16 - offset;
if (use_len > input_len) {
use_len = input_len;
}
ctx->processed += use_len;
if (ctx->mode == MBEDTLS_CCM_ENCRYPT || \
ctx->mode == MBEDTLS_CCM_STAR_ENCRYPT) {
mbedtls_xor(ctx->y + offset, ctx->y + offset, input, use_len);
if (use_len + offset == 16 || ctx->processed == ctx->plaintext_len) {
#if defined(MBEDTLS_BLOCK_CIPHER_C)
ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->y);
#else
ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen);
#endif
if (ret != 0) {
ctx->state |= CCM_STATE__ERROR;
goto exit;
}
}
ret = mbedtls_ccm_crypt(ctx, offset, use_len, input, output);
if (ret != 0) {
goto exit;
}
}
if (ctx->mode == MBEDTLS_CCM_DECRYPT || \
ctx->mode == MBEDTLS_CCM_STAR_DECRYPT) {
/* Since output may be in shared memory, we cannot be sure that
* it will contain what we wrote to it. Therefore, we should avoid using
* it as input to any operations.
* Write decrypted data to local_output to avoid using output variable as
* input in the XOR operation for Y.
*/
ret = mbedtls_ccm_crypt(ctx, offset, use_len, input, local_output);
if (ret != 0) {
goto exit;
}
mbedtls_xor(ctx->y + offset, ctx->y + offset, local_output, use_len);
memcpy(output, local_output, use_len);
if (use_len + offset == 16 || ctx->processed == ctx->plaintext_len) {
#if defined(MBEDTLS_BLOCK_CIPHER_C)
ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->y);
#else
ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen);
#endif
if (ret != 0) {
ctx->state |= CCM_STATE__ERROR;
goto exit;
}
}
}
if (use_len + offset == 16 || ctx->processed == ctx->plaintext_len) {
for (i = 0; i < ctx->q; i++) {
if (++(ctx->ctr)[15-i] != 0) {
break;
}
}
}
input_len -= use_len;
input += use_len;
output += use_len;
}
exit:
mbedtls_platform_zeroize(local_output, 16);
return ret;
}
int mbedtls_ccm_finish(mbedtls_ccm_context *ctx,
unsigned char *tag, size_t tag_len)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char i;
if (ctx->state & CCM_STATE__ERROR) {
return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
}
if (ctx->add_len > 0 && !(ctx->state & CCM_STATE__AUTH_DATA_FINISHED)) {
return MBEDTLS_ERR_CCM_BAD_INPUT;
}
if (ctx->plaintext_len > 0 && ctx->processed != ctx->plaintext_len) {
return MBEDTLS_ERR_CCM_BAD_INPUT;
}
/*
* Authentication: reset counter and crypt/mask internal tag
*/
for (i = 0; i < ctx->q; i++) {
ctx->ctr[15-i] = 0;
}
ret = mbedtls_ccm_crypt(ctx, 0, 16, ctx->y, ctx->y);
if (ret != 0) {
return ret;
}
if (tag != NULL) {
memcpy(tag, ctx->y, tag_len);
}
mbedtls_ccm_clear_state(ctx);
return 0;
}
/*
* Authenticated encryption or decryption
*/
static int ccm_auth_crypt(mbedtls_ccm_context *ctx, int mode, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
unsigned char *tag, size_t tag_len)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t olen;
if ((ret = mbedtls_ccm_starts(ctx, mode, iv, iv_len)) != 0) {
return ret;
}
if ((ret = mbedtls_ccm_set_lengths(ctx, add_len, length, tag_len)) != 0) {
return ret;
}
if ((ret = mbedtls_ccm_update_ad(ctx, add, add_len)) != 0) {
return ret;
}
if ((ret = mbedtls_ccm_update(ctx, input, length,
output, length, &olen)) != 0) {
return ret;
}
if ((ret = mbedtls_ccm_finish(ctx, tag, tag_len)) != 0) {
return ret;
}
return 0;
}
/*
* Authenticated encryption
*/
int mbedtls_ccm_star_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
unsigned char *tag, size_t tag_len)
{
return ccm_auth_crypt(ctx, MBEDTLS_CCM_STAR_ENCRYPT, length, iv, iv_len,
add, add_len, input, output, tag, tag_len);
}
int mbedtls_ccm_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
unsigned char *tag, size_t tag_len)
{
return ccm_auth_crypt(ctx, MBEDTLS_CCM_ENCRYPT, length, iv, iv_len,
add, add_len, input, output, tag, tag_len);
}
/*
* Authenticated decryption
*/
static int mbedtls_ccm_compare_tags(const unsigned char *tag1,
const unsigned char *tag2,
size_t tag_len)
{
/* Check tag in "constant-time" */
int diff = mbedtls_ct_memcmp(tag1, tag2, tag_len);
if (diff != 0) {
return MBEDTLS_ERR_CCM_AUTH_FAILED;
}
return 0;
}
static int ccm_auth_decrypt(mbedtls_ccm_context *ctx, int mode, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
const unsigned char *tag, size_t tag_len)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char check_tag[16];
if ((ret = ccm_auth_crypt(ctx, mode, length,
iv, iv_len, add, add_len,
input, output, check_tag, tag_len)) != 0) {
return ret;
}
if ((ret = mbedtls_ccm_compare_tags(tag, check_tag, tag_len)) != 0) {
mbedtls_platform_zeroize(output, length);
return ret;
}
return 0;
}
int mbedtls_ccm_star_auth_decrypt(mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
const unsigned char *tag, size_t tag_len)
{
return ccm_auth_decrypt(ctx, MBEDTLS_CCM_STAR_DECRYPT, length,
iv, iv_len, add, add_len,
input, output, tag, tag_len);
}
int mbedtls_ccm_auth_decrypt(mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
const unsigned char *tag, size_t tag_len)
{
return ccm_auth_decrypt(ctx, MBEDTLS_CCM_DECRYPT, length,
iv, iv_len, add, add_len,
input, output, tag, tag_len);
}
#endif /* !MBEDTLS_CCM_ALT */
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_CCM_GCM_CAN_AES)
/*
* Examples 1 to 3 from SP800-38C Appendix C
*/
#define NB_TESTS 3
#define CCM_SELFTEST_PT_MAX_LEN 24
#define CCM_SELFTEST_CT_MAX_LEN 32
/*
* The data is the same for all tests, only the used length changes
*/
static const unsigned char key_test_data[] = {
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f
};
static const unsigned char iv_test_data[] = {
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b
};
static const unsigned char ad_test_data[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13
};
static const unsigned char msg_test_data[CCM_SELFTEST_PT_MAX_LEN] = {
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
};
static const size_t iv_len_test_data[NB_TESTS] = { 7, 8, 12 };
static const size_t add_len_test_data[NB_TESTS] = { 8, 16, 20 };
static const size_t msg_len_test_data[NB_TESTS] = { 4, 16, 24 };
static const size_t tag_len_test_data[NB_TESTS] = { 4, 6, 8 };
static const unsigned char res_test_data[NB_TESTS][CCM_SELFTEST_CT_MAX_LEN] = {
{ 0x71, 0x62, 0x01, 0x5b, 0x4d, 0xac, 0x25, 0x5d },
{ 0xd2, 0xa1, 0xf0, 0xe0, 0x51, 0xea, 0x5f, 0x62,
0x08, 0x1a, 0x77, 0x92, 0x07, 0x3d, 0x59, 0x3d,
0x1f, 0xc6, 0x4f, 0xbf, 0xac, 0xcd },
{ 0xe3, 0xb2, 0x01, 0xa9, 0xf5, 0xb7, 0x1a, 0x7a,
0x9b, 0x1c, 0xea, 0xec, 0xcd, 0x97, 0xe7, 0x0b,
0x61, 0x76, 0xaa, 0xd9, 0xa4, 0x42, 0x8a, 0xa5,
0x48, 0x43, 0x92, 0xfb, 0xc1, 0xb0, 0x99, 0x51 }
};
int mbedtls_ccm_self_test(int verbose)
{
mbedtls_ccm_context ctx;
/*
* Some hardware accelerators require the input and output buffers
* would be in RAM, because the flash is not accessible.
* Use buffers on the stack to hold the test vectors data.
*/
unsigned char plaintext[CCM_SELFTEST_PT_MAX_LEN];
unsigned char ciphertext[CCM_SELFTEST_CT_MAX_LEN];
size_t i;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ccm_init(&ctx);
if (mbedtls_ccm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, key_test_data,
8 * sizeof(key_test_data)) != 0) {
if (verbose != 0) {
mbedtls_printf(" CCM: setup failed");
}
return 1;
}
for (i = 0; i < NB_TESTS; i++) {
if (verbose != 0) {
mbedtls_printf(" CCM-AES #%u: ", (unsigned int) i + 1);
}
memset(plaintext, 0, CCM_SELFTEST_PT_MAX_LEN);
memset(ciphertext, 0, CCM_SELFTEST_CT_MAX_LEN);
memcpy(plaintext, msg_test_data, msg_len_test_data[i]);
ret = mbedtls_ccm_encrypt_and_tag(&ctx, msg_len_test_data[i],
iv_test_data, iv_len_test_data[i],
ad_test_data, add_len_test_data[i],
plaintext, ciphertext,
ciphertext + msg_len_test_data[i],
tag_len_test_data[i]);
if (ret != 0 ||
memcmp(ciphertext, res_test_data[i],
msg_len_test_data[i] + tag_len_test_data[i]) != 0) {
if (verbose != 0) {
mbedtls_printf("failed\n");
}
return 1;
}
memset(plaintext, 0, CCM_SELFTEST_PT_MAX_LEN);
ret = mbedtls_ccm_auth_decrypt(&ctx, msg_len_test_data[i],
iv_test_data, iv_len_test_data[i],
ad_test_data, add_len_test_data[i],
ciphertext, plaintext,
ciphertext + msg_len_test_data[i],
tag_len_test_data[i]);
if (ret != 0 ||
memcmp(plaintext, msg_test_data, msg_len_test_data[i]) != 0) {
if (verbose != 0) {
mbedtls_printf("failed\n");
}
return 1;
}
if (verbose != 0) {
mbedtls_printf("passed\n");
}
}
mbedtls_ccm_free(&ctx);
if (verbose != 0) {
mbedtls_printf("\n");
}
return 0;
}
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
#endif /* MBEDTLS_CCM_C */

497
thirdparty/mbedtls/library/chacha20.c vendored Normal file
View File

@@ -0,0 +1,497 @@
/**
* \file chacha20.c
*
* \brief ChaCha20 cipher.
*
* \author Daniel King <damaki.gh@gmail.com>
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#if defined(MBEDTLS_CHACHA20_C)
#include "mbedtls/chacha20.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#include <stddef.h>
#include <string.h>
#include "mbedtls/platform.h"
#if !defined(MBEDTLS_CHACHA20_ALT)
#define ROTL32(value, amount) \
((uint32_t) ((value) << (amount)) | ((value) >> (32 - (amount))))
#define CHACHA20_CTR_INDEX (12U)
#define CHACHA20_BLOCK_SIZE_BYTES (4U * 16U)
/**
* \brief ChaCha20 quarter round operation.
*
* The quarter round is defined as follows (from RFC 7539):
* 1. a += b; d ^= a; d <<<= 16;
* 2. c += d; b ^= c; b <<<= 12;
* 3. a += b; d ^= a; d <<<= 8;
* 4. c += d; b ^= c; b <<<= 7;
*
* \param state ChaCha20 state to modify.
* \param a The index of 'a' in the state.
* \param b The index of 'b' in the state.
* \param c The index of 'c' in the state.
* \param d The index of 'd' in the state.
*/
static inline void chacha20_quarter_round(uint32_t state[16],
size_t a,
size_t b,
size_t c,
size_t d)
{
/* a += b; d ^= a; d <<<= 16; */
state[a] += state[b];
state[d] ^= state[a];
state[d] = ROTL32(state[d], 16);
/* c += d; b ^= c; b <<<= 12 */
state[c] += state[d];
state[b] ^= state[c];
state[b] = ROTL32(state[b], 12);
/* a += b; d ^= a; d <<<= 8; */
state[a] += state[b];
state[d] ^= state[a];
state[d] = ROTL32(state[d], 8);
/* c += d; b ^= c; b <<<= 7; */
state[c] += state[d];
state[b] ^= state[c];
state[b] = ROTL32(state[b], 7);
}
/**
* \brief Perform the ChaCha20 inner block operation.
*
* This function performs two rounds: the column round and the
* diagonal round.
*
* \param state The ChaCha20 state to update.
*/
static void chacha20_inner_block(uint32_t state[16])
{
chacha20_quarter_round(state, 0, 4, 8, 12);
chacha20_quarter_round(state, 1, 5, 9, 13);
chacha20_quarter_round(state, 2, 6, 10, 14);
chacha20_quarter_round(state, 3, 7, 11, 15);
chacha20_quarter_round(state, 0, 5, 10, 15);
chacha20_quarter_round(state, 1, 6, 11, 12);
chacha20_quarter_round(state, 2, 7, 8, 13);
chacha20_quarter_round(state, 3, 4, 9, 14);
}
/**
* \brief Generates a keystream block.
*
* \param initial_state The initial ChaCha20 state (key, nonce, counter).
* \param keystream Generated keystream bytes are written to this buffer.
*/
static void chacha20_block(const uint32_t initial_state[16],
unsigned char keystream[64])
{
uint32_t working_state[16];
size_t i;
memcpy(working_state,
initial_state,
CHACHA20_BLOCK_SIZE_BYTES);
for (i = 0U; i < 10U; i++) {
chacha20_inner_block(working_state);
}
working_state[0] += initial_state[0];
working_state[1] += initial_state[1];
working_state[2] += initial_state[2];
working_state[3] += initial_state[3];
working_state[4] += initial_state[4];
working_state[5] += initial_state[5];
working_state[6] += initial_state[6];
working_state[7] += initial_state[7];
working_state[8] += initial_state[8];
working_state[9] += initial_state[9];
working_state[10] += initial_state[10];
working_state[11] += initial_state[11];
working_state[12] += initial_state[12];
working_state[13] += initial_state[13];
working_state[14] += initial_state[14];
working_state[15] += initial_state[15];
for (i = 0U; i < 16; i++) {
size_t offset = i * 4U;
MBEDTLS_PUT_UINT32_LE(working_state[i], keystream, offset);
}
mbedtls_platform_zeroize(working_state, sizeof(working_state));
}
void mbedtls_chacha20_init(mbedtls_chacha20_context *ctx)
{
mbedtls_platform_zeroize(ctx->state, sizeof(ctx->state));
mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8));
/* Initially, there's no keystream bytes available */
ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
}
void mbedtls_chacha20_free(mbedtls_chacha20_context *ctx)
{
if (ctx != NULL) {
mbedtls_platform_zeroize(ctx, sizeof(mbedtls_chacha20_context));
}
}
int mbedtls_chacha20_setkey(mbedtls_chacha20_context *ctx,
const unsigned char key[32])
{
/* ChaCha20 constants - the string "expand 32-byte k" */
ctx->state[0] = 0x61707865;
ctx->state[1] = 0x3320646e;
ctx->state[2] = 0x79622d32;
ctx->state[3] = 0x6b206574;
/* Set key */
ctx->state[4] = MBEDTLS_GET_UINT32_LE(key, 0);
ctx->state[5] = MBEDTLS_GET_UINT32_LE(key, 4);
ctx->state[6] = MBEDTLS_GET_UINT32_LE(key, 8);
ctx->state[7] = MBEDTLS_GET_UINT32_LE(key, 12);
ctx->state[8] = MBEDTLS_GET_UINT32_LE(key, 16);
ctx->state[9] = MBEDTLS_GET_UINT32_LE(key, 20);
ctx->state[10] = MBEDTLS_GET_UINT32_LE(key, 24);
ctx->state[11] = MBEDTLS_GET_UINT32_LE(key, 28);
return 0;
}
int mbedtls_chacha20_starts(mbedtls_chacha20_context *ctx,
const unsigned char nonce[12],
uint32_t counter)
{
/* Counter */
ctx->state[12] = counter;
/* Nonce */
ctx->state[13] = MBEDTLS_GET_UINT32_LE(nonce, 0);
ctx->state[14] = MBEDTLS_GET_UINT32_LE(nonce, 4);
ctx->state[15] = MBEDTLS_GET_UINT32_LE(nonce, 8);
mbedtls_platform_zeroize(ctx->keystream8, sizeof(ctx->keystream8));
/* Initially, there's no keystream bytes available */
ctx->keystream_bytes_used = CHACHA20_BLOCK_SIZE_BYTES;
return 0;
}
int mbedtls_chacha20_update(mbedtls_chacha20_context *ctx,
size_t size,
const unsigned char *input,
unsigned char *output)
{
size_t offset = 0U;
/* Use leftover keystream bytes, if available */
while (size > 0U && ctx->keystream_bytes_used < CHACHA20_BLOCK_SIZE_BYTES) {
output[offset] = input[offset]
^ ctx->keystream8[ctx->keystream_bytes_used];
ctx->keystream_bytes_used++;
offset++;
size--;
}
/* Process full blocks */
while (size >= CHACHA20_BLOCK_SIZE_BYTES) {
/* Generate new keystream block and increment counter */
chacha20_block(ctx->state, ctx->keystream8);
ctx->state[CHACHA20_CTR_INDEX]++;
mbedtls_xor(output + offset, input + offset, ctx->keystream8, 64U);
offset += CHACHA20_BLOCK_SIZE_BYTES;
size -= CHACHA20_BLOCK_SIZE_BYTES;
}
/* Last (partial) block */
if (size > 0U) {
/* Generate new keystream block and increment counter */
chacha20_block(ctx->state, ctx->keystream8);
ctx->state[CHACHA20_CTR_INDEX]++;
mbedtls_xor(output + offset, input + offset, ctx->keystream8, size);
ctx->keystream_bytes_used = size;
}
return 0;
}
int mbedtls_chacha20_crypt(const unsigned char key[32],
const unsigned char nonce[12],
uint32_t counter,
size_t data_len,
const unsigned char *input,
unsigned char *output)
{
mbedtls_chacha20_context ctx;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_chacha20_init(&ctx);
ret = mbedtls_chacha20_setkey(&ctx, key);
if (ret != 0) {
goto cleanup;
}
ret = mbedtls_chacha20_starts(&ctx, nonce, counter);
if (ret != 0) {
goto cleanup;
}
ret = mbedtls_chacha20_update(&ctx, data_len, input, output);
cleanup:
mbedtls_chacha20_free(&ctx);
return ret;
}
#endif /* !MBEDTLS_CHACHA20_ALT */
#if defined(MBEDTLS_SELF_TEST)
static const unsigned char test_keys[2][32] =
{
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
},
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
}
};
static const unsigned char test_nonces[2][12] =
{
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
},
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x02
}
};
static const uint32_t test_counters[2] =
{
0U,
1U
};
static const unsigned char test_input[2][375] =
{
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
},
{
0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,
0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,
0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,
0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,
0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,
0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,
0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,
0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,
0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,
0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,
0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,
0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,
0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,
0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,
0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,
0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,
0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,
0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,
0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f
}
};
static const unsigned char test_output[2][375] =
{
{
0x76, 0xb8, 0xe0, 0xad, 0xa0, 0xf1, 0x3d, 0x90,
0x40, 0x5d, 0x6a, 0xe5, 0x53, 0x86, 0xbd, 0x28,
0xbd, 0xd2, 0x19, 0xb8, 0xa0, 0x8d, 0xed, 0x1a,
0xa8, 0x36, 0xef, 0xcc, 0x8b, 0x77, 0x0d, 0xc7,
0xda, 0x41, 0x59, 0x7c, 0x51, 0x57, 0x48, 0x8d,
0x77, 0x24, 0xe0, 0x3f, 0xb8, 0xd8, 0x4a, 0x37,
0x6a, 0x43, 0xb8, 0xf4, 0x15, 0x18, 0xa1, 0x1c,
0xc3, 0x87, 0xb6, 0x69, 0xb2, 0xee, 0x65, 0x86
},
{
0xa3, 0xfb, 0xf0, 0x7d, 0xf3, 0xfa, 0x2f, 0xde,
0x4f, 0x37, 0x6c, 0xa2, 0x3e, 0x82, 0x73, 0x70,
0x41, 0x60, 0x5d, 0x9f, 0x4f, 0x4f, 0x57, 0xbd,
0x8c, 0xff, 0x2c, 0x1d, 0x4b, 0x79, 0x55, 0xec,
0x2a, 0x97, 0x94, 0x8b, 0xd3, 0x72, 0x29, 0x15,
0xc8, 0xf3, 0xd3, 0x37, 0xf7, 0xd3, 0x70, 0x05,
0x0e, 0x9e, 0x96, 0xd6, 0x47, 0xb7, 0xc3, 0x9f,
0x56, 0xe0, 0x31, 0xca, 0x5e, 0xb6, 0x25, 0x0d,
0x40, 0x42, 0xe0, 0x27, 0x85, 0xec, 0xec, 0xfa,
0x4b, 0x4b, 0xb5, 0xe8, 0xea, 0xd0, 0x44, 0x0e,
0x20, 0xb6, 0xe8, 0xdb, 0x09, 0xd8, 0x81, 0xa7,
0xc6, 0x13, 0x2f, 0x42, 0x0e, 0x52, 0x79, 0x50,
0x42, 0xbd, 0xfa, 0x77, 0x73, 0xd8, 0xa9, 0x05,
0x14, 0x47, 0xb3, 0x29, 0x1c, 0xe1, 0x41, 0x1c,
0x68, 0x04, 0x65, 0x55, 0x2a, 0xa6, 0xc4, 0x05,
0xb7, 0x76, 0x4d, 0x5e, 0x87, 0xbe, 0xa8, 0x5a,
0xd0, 0x0f, 0x84, 0x49, 0xed, 0x8f, 0x72, 0xd0,
0xd6, 0x62, 0xab, 0x05, 0x26, 0x91, 0xca, 0x66,
0x42, 0x4b, 0xc8, 0x6d, 0x2d, 0xf8, 0x0e, 0xa4,
0x1f, 0x43, 0xab, 0xf9, 0x37, 0xd3, 0x25, 0x9d,
0xc4, 0xb2, 0xd0, 0xdf, 0xb4, 0x8a, 0x6c, 0x91,
0x39, 0xdd, 0xd7, 0xf7, 0x69, 0x66, 0xe9, 0x28,
0xe6, 0x35, 0x55, 0x3b, 0xa7, 0x6c, 0x5c, 0x87,
0x9d, 0x7b, 0x35, 0xd4, 0x9e, 0xb2, 0xe6, 0x2b,
0x08, 0x71, 0xcd, 0xac, 0x63, 0x89, 0x39, 0xe2,
0x5e, 0x8a, 0x1e, 0x0e, 0xf9, 0xd5, 0x28, 0x0f,
0xa8, 0xca, 0x32, 0x8b, 0x35, 0x1c, 0x3c, 0x76,
0x59, 0x89, 0xcb, 0xcf, 0x3d, 0xaa, 0x8b, 0x6c,
0xcc, 0x3a, 0xaf, 0x9f, 0x39, 0x79, 0xc9, 0x2b,
0x37, 0x20, 0xfc, 0x88, 0xdc, 0x95, 0xed, 0x84,
0xa1, 0xbe, 0x05, 0x9c, 0x64, 0x99, 0xb9, 0xfd,
0xa2, 0x36, 0xe7, 0xe8, 0x18, 0xb0, 0x4b, 0x0b,
0xc3, 0x9c, 0x1e, 0x87, 0x6b, 0x19, 0x3b, 0xfe,
0x55, 0x69, 0x75, 0x3f, 0x88, 0x12, 0x8c, 0xc0,
0x8a, 0xaa, 0x9b, 0x63, 0xd1, 0xa1, 0x6f, 0x80,
0xef, 0x25, 0x54, 0xd7, 0x18, 0x9c, 0x41, 0x1f,
0x58, 0x69, 0xca, 0x52, 0xc5, 0xb8, 0x3f, 0xa3,
0x6f, 0xf2, 0x16, 0xb9, 0xc1, 0xd3, 0x00, 0x62,
0xbe, 0xbc, 0xfd, 0x2d, 0xc5, 0xbc, 0xe0, 0x91,
0x19, 0x34, 0xfd, 0xa7, 0x9a, 0x86, 0xf6, 0xe6,
0x98, 0xce, 0xd7, 0x59, 0xc3, 0xff, 0x9b, 0x64,
0x77, 0x33, 0x8f, 0x3d, 0xa4, 0xf9, 0xcd, 0x85,
0x14, 0xea, 0x99, 0x82, 0xcc, 0xaf, 0xb3, 0x41,
0xb2, 0x38, 0x4d, 0xd9, 0x02, 0xf3, 0xd1, 0xab,
0x7a, 0xc6, 0x1d, 0xd2, 0x9c, 0x6f, 0x21, 0xba,
0x5b, 0x86, 0x2f, 0x37, 0x30, 0xe3, 0x7c, 0xfd,
0xc4, 0xfd, 0x80, 0x6c, 0x22, 0xf2, 0x21
}
};
static const size_t test_lengths[2] =
{
64U,
375U
};
/* Make sure no other definition is already present. */
#undef ASSERT
#define ASSERT(cond, args) \
do \
{ \
if (!(cond)) \
{ \
if (verbose != 0) \
mbedtls_printf args; \
\
return -1; \
} \
} \
while (0)
int mbedtls_chacha20_self_test(int verbose)
{
unsigned char output[381];
unsigned i;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
for (i = 0U; i < 2U; i++) {
if (verbose != 0) {
mbedtls_printf(" ChaCha20 test %u ", i);
}
ret = mbedtls_chacha20_crypt(test_keys[i],
test_nonces[i],
test_counters[i],
test_lengths[i],
test_input[i],
output);
ASSERT(0 == ret, ("error code: %i\n", ret));
ASSERT(0 == memcmp(output, test_output[i], test_lengths[i]),
("failed (output)\n"));
if (verbose != 0) {
mbedtls_printf("passed\n");
}
}
if (verbose != 0) {
mbedtls_printf("\n");
}
return 0;
}
#endif /* MBEDTLS_SELF_TEST */
#endif /* !MBEDTLS_CHACHA20_C */

478
thirdparty/mbedtls/library/chachapoly.c vendored Normal file
View File

@@ -0,0 +1,478 @@
/**
* \file chachapoly.c
*
* \brief ChaCha20-Poly1305 AEAD construction based on RFC 7539.
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#if defined(MBEDTLS_CHACHAPOLY_C)
#include "mbedtls/chachapoly.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#include "mbedtls/constant_time.h"
#include <string.h>
#include "mbedtls/platform.h"
#if !defined(MBEDTLS_CHACHAPOLY_ALT)
#define CHACHAPOLY_STATE_INIT (0)
#define CHACHAPOLY_STATE_AAD (1)
#define CHACHAPOLY_STATE_CIPHERTEXT (2) /* Encrypting or decrypting */
#define CHACHAPOLY_STATE_FINISHED (3)
/**
* \brief Adds nul bytes to pad the AAD for Poly1305.
*
* \param ctx The ChaCha20-Poly1305 context.
*/
static int chachapoly_pad_aad(mbedtls_chachapoly_context *ctx)
{
uint32_t partial_block_len = (uint32_t) (ctx->aad_len % 16U);
unsigned char zeroes[15];
if (partial_block_len == 0U) {
return 0;
}
memset(zeroes, 0, sizeof(zeroes));
return mbedtls_poly1305_update(&ctx->poly1305_ctx,
zeroes,
16U - partial_block_len);
}
/**
* \brief Adds nul bytes to pad the ciphertext for Poly1305.
*
* \param ctx The ChaCha20-Poly1305 context.
*/
static int chachapoly_pad_ciphertext(mbedtls_chachapoly_context *ctx)
{
uint32_t partial_block_len = (uint32_t) (ctx->ciphertext_len % 16U);
unsigned char zeroes[15];
if (partial_block_len == 0U) {
return 0;
}
memset(zeroes, 0, sizeof(zeroes));
return mbedtls_poly1305_update(&ctx->poly1305_ctx,
zeroes,
16U - partial_block_len);
}
void mbedtls_chachapoly_init(mbedtls_chachapoly_context *ctx)
{
mbedtls_chacha20_init(&ctx->chacha20_ctx);
mbedtls_poly1305_init(&ctx->poly1305_ctx);
ctx->aad_len = 0U;
ctx->ciphertext_len = 0U;
ctx->state = CHACHAPOLY_STATE_INIT;
ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
}
void mbedtls_chachapoly_free(mbedtls_chachapoly_context *ctx)
{
if (ctx == NULL) {
return;
}
mbedtls_chacha20_free(&ctx->chacha20_ctx);
mbedtls_poly1305_free(&ctx->poly1305_ctx);
ctx->aad_len = 0U;
ctx->ciphertext_len = 0U;
ctx->state = CHACHAPOLY_STATE_INIT;
ctx->mode = MBEDTLS_CHACHAPOLY_ENCRYPT;
}
int mbedtls_chachapoly_setkey(mbedtls_chachapoly_context *ctx,
const unsigned char key[32])
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ret = mbedtls_chacha20_setkey(&ctx->chacha20_ctx, key);
return ret;
}
int mbedtls_chachapoly_starts(mbedtls_chachapoly_context *ctx,
const unsigned char nonce[12],
mbedtls_chachapoly_mode_t mode)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char poly1305_key[64];
/* Set counter = 0, will be update to 1 when generating Poly1305 key */
ret = mbedtls_chacha20_starts(&ctx->chacha20_ctx, nonce, 0U);
if (ret != 0) {
goto cleanup;
}
/* Generate the Poly1305 key by getting the ChaCha20 keystream output with
* counter = 0. This is the same as encrypting a buffer of zeroes.
* Only the first 256-bits (32 bytes) of the key is used for Poly1305.
* The other 256 bits are discarded.
*/
memset(poly1305_key, 0, sizeof(poly1305_key));
ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, sizeof(poly1305_key),
poly1305_key, poly1305_key);
if (ret != 0) {
goto cleanup;
}
ret = mbedtls_poly1305_starts(&ctx->poly1305_ctx, poly1305_key);
if (ret == 0) {
ctx->aad_len = 0U;
ctx->ciphertext_len = 0U;
ctx->state = CHACHAPOLY_STATE_AAD;
ctx->mode = mode;
}
cleanup:
mbedtls_platform_zeroize(poly1305_key, 64U);
return ret;
}
int mbedtls_chachapoly_update_aad(mbedtls_chachapoly_context *ctx,
const unsigned char *aad,
size_t aad_len)
{
if (ctx->state != CHACHAPOLY_STATE_AAD) {
return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
}
ctx->aad_len += aad_len;
return mbedtls_poly1305_update(&ctx->poly1305_ctx, aad, aad_len);
}
int mbedtls_chachapoly_update(mbedtls_chachapoly_context *ctx,
size_t len,
const unsigned char *input,
unsigned char *output)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if ((ctx->state != CHACHAPOLY_STATE_AAD) &&
(ctx->state != CHACHAPOLY_STATE_CIPHERTEXT)) {
return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
}
if (ctx->state == CHACHAPOLY_STATE_AAD) {
ctx->state = CHACHAPOLY_STATE_CIPHERTEXT;
ret = chachapoly_pad_aad(ctx);
if (ret != 0) {
return ret;
}
}
ctx->ciphertext_len += len;
if (ctx->mode == MBEDTLS_CHACHAPOLY_ENCRYPT) {
ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output);
if (ret != 0) {
return ret;
}
ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, output, len);
if (ret != 0) {
return ret;
}
} else { /* DECRYPT */
ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, input, len);
if (ret != 0) {
return ret;
}
ret = mbedtls_chacha20_update(&ctx->chacha20_ctx, len, input, output);
if (ret != 0) {
return ret;
}
}
return 0;
}
int mbedtls_chachapoly_finish(mbedtls_chachapoly_context *ctx,
unsigned char mac[16])
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char len_block[16];
if (ctx->state == CHACHAPOLY_STATE_INIT) {
return MBEDTLS_ERR_CHACHAPOLY_BAD_STATE;
}
if (ctx->state == CHACHAPOLY_STATE_AAD) {
ret = chachapoly_pad_aad(ctx);
if (ret != 0) {
return ret;
}
} else if (ctx->state == CHACHAPOLY_STATE_CIPHERTEXT) {
ret = chachapoly_pad_ciphertext(ctx);
if (ret != 0) {
return ret;
}
}
ctx->state = CHACHAPOLY_STATE_FINISHED;
/* The lengths of the AAD and ciphertext are processed by
* Poly1305 as the final 128-bit block, encoded as little-endian integers.
*/
MBEDTLS_PUT_UINT64_LE(ctx->aad_len, len_block, 0);
MBEDTLS_PUT_UINT64_LE(ctx->ciphertext_len, len_block, 8);
ret = mbedtls_poly1305_update(&ctx->poly1305_ctx, len_block, 16U);
if (ret != 0) {
return ret;
}
ret = mbedtls_poly1305_finish(&ctx->poly1305_ctx, mac);
return ret;
}
static int chachapoly_crypt_and_tag(mbedtls_chachapoly_context *ctx,
mbedtls_chachapoly_mode_t mode,
size_t length,
const unsigned char nonce[12],
const unsigned char *aad,
size_t aad_len,
const unsigned char *input,
unsigned char *output,
unsigned char tag[16])
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ret = mbedtls_chachapoly_starts(ctx, nonce, mode);
if (ret != 0) {
goto cleanup;
}
ret = mbedtls_chachapoly_update_aad(ctx, aad, aad_len);
if (ret != 0) {
goto cleanup;
}
ret = mbedtls_chachapoly_update(ctx, length, input, output);
if (ret != 0) {
goto cleanup;
}
ret = mbedtls_chachapoly_finish(ctx, tag);
cleanup:
return ret;
}
int mbedtls_chachapoly_encrypt_and_tag(mbedtls_chachapoly_context *ctx,
size_t length,
const unsigned char nonce[12],
const unsigned char *aad,
size_t aad_len,
const unsigned char *input,
unsigned char *output,
unsigned char tag[16])
{
return chachapoly_crypt_and_tag(ctx, MBEDTLS_CHACHAPOLY_ENCRYPT,
length, nonce, aad, aad_len,
input, output, tag);
}
int mbedtls_chachapoly_auth_decrypt(mbedtls_chachapoly_context *ctx,
size_t length,
const unsigned char nonce[12],
const unsigned char *aad,
size_t aad_len,
const unsigned char tag[16],
const unsigned char *input,
unsigned char *output)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char check_tag[16];
int diff;
if ((ret = chachapoly_crypt_and_tag(ctx,
MBEDTLS_CHACHAPOLY_DECRYPT, length, nonce,
aad, aad_len, input, output, check_tag)) != 0) {
return ret;
}
/* Check tag in "constant-time" */
diff = mbedtls_ct_memcmp(tag, check_tag, sizeof(check_tag));
if (diff != 0) {
mbedtls_platform_zeroize(output, length);
return MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED;
}
return 0;
}
#endif /* MBEDTLS_CHACHAPOLY_ALT */
#if defined(MBEDTLS_SELF_TEST)
static const unsigned char test_key[1][32] =
{
{
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
}
};
static const unsigned char test_nonce[1][12] =
{
{
0x07, 0x00, 0x00, 0x00, /* 32-bit common part */
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47 /* 64-bit IV */
}
};
static const unsigned char test_aad[1][12] =
{
{
0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3,
0xc4, 0xc5, 0xc6, 0xc7
}
};
static const size_t test_aad_len[1] =
{
12U
};
static const unsigned char test_input[1][114] =
{
{
0x4c, 0x61, 0x64, 0x69, 0x65, 0x73, 0x20, 0x61,
0x6e, 0x64, 0x20, 0x47, 0x65, 0x6e, 0x74, 0x6c,
0x65, 0x6d, 0x65, 0x6e, 0x20, 0x6f, 0x66, 0x20,
0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73,
0x73, 0x20, 0x6f, 0x66, 0x20, 0x27, 0x39, 0x39,
0x3a, 0x20, 0x49, 0x66, 0x20, 0x49, 0x20, 0x63,
0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6f, 0x66, 0x66,
0x65, 0x72, 0x20, 0x79, 0x6f, 0x75, 0x20, 0x6f,
0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x6e, 0x65, 0x20,
0x74, 0x69, 0x70, 0x20, 0x66, 0x6f, 0x72, 0x20,
0x74, 0x68, 0x65, 0x20, 0x66, 0x75, 0x74, 0x75,
0x72, 0x65, 0x2c, 0x20, 0x73, 0x75, 0x6e, 0x73,
0x63, 0x72, 0x65, 0x65, 0x6e, 0x20, 0x77, 0x6f,
0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x69,
0x74, 0x2e
}
};
static const unsigned char test_output[1][114] =
{
{
0xd3, 0x1a, 0x8d, 0x34, 0x64, 0x8e, 0x60, 0xdb,
0x7b, 0x86, 0xaf, 0xbc, 0x53, 0xef, 0x7e, 0xc2,
0xa4, 0xad, 0xed, 0x51, 0x29, 0x6e, 0x08, 0xfe,
0xa9, 0xe2, 0xb5, 0xa7, 0x36, 0xee, 0x62, 0xd6,
0x3d, 0xbe, 0xa4, 0x5e, 0x8c, 0xa9, 0x67, 0x12,
0x82, 0xfa, 0xfb, 0x69, 0xda, 0x92, 0x72, 0x8b,
0x1a, 0x71, 0xde, 0x0a, 0x9e, 0x06, 0x0b, 0x29,
0x05, 0xd6, 0xa5, 0xb6, 0x7e, 0xcd, 0x3b, 0x36,
0x92, 0xdd, 0xbd, 0x7f, 0x2d, 0x77, 0x8b, 0x8c,
0x98, 0x03, 0xae, 0xe3, 0x28, 0x09, 0x1b, 0x58,
0xfa, 0xb3, 0x24, 0xe4, 0xfa, 0xd6, 0x75, 0x94,
0x55, 0x85, 0x80, 0x8b, 0x48, 0x31, 0xd7, 0xbc,
0x3f, 0xf4, 0xde, 0xf0, 0x8e, 0x4b, 0x7a, 0x9d,
0xe5, 0x76, 0xd2, 0x65, 0x86, 0xce, 0xc6, 0x4b,
0x61, 0x16
}
};
static const size_t test_input_len[1] =
{
114U
};
static const unsigned char test_mac[1][16] =
{
{
0x1a, 0xe1, 0x0b, 0x59, 0x4f, 0x09, 0xe2, 0x6a,
0x7e, 0x90, 0x2e, 0xcb, 0xd0, 0x60, 0x06, 0x91
}
};
/* Make sure no other definition is already present. */
#undef ASSERT
#define ASSERT(cond, args) \
do \
{ \
if (!(cond)) \
{ \
if (verbose != 0) \
mbedtls_printf args; \
\
return -1; \
} \
} \
while (0)
int mbedtls_chachapoly_self_test(int verbose)
{
mbedtls_chachapoly_context ctx;
unsigned i;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char output[200];
unsigned char mac[16];
for (i = 0U; i < 1U; i++) {
if (verbose != 0) {
mbedtls_printf(" ChaCha20-Poly1305 test %u ", i);
}
mbedtls_chachapoly_init(&ctx);
ret = mbedtls_chachapoly_setkey(&ctx, test_key[i]);
ASSERT(0 == ret, ("setkey() error code: %i\n", ret));
ret = mbedtls_chachapoly_encrypt_and_tag(&ctx,
test_input_len[i],
test_nonce[i],
test_aad[i],
test_aad_len[i],
test_input[i],
output,
mac);
ASSERT(0 == ret, ("crypt_and_tag() error code: %i\n", ret));
ASSERT(0 == memcmp(output, test_output[i], test_input_len[i]),
("failure (wrong output)\n"));
ASSERT(0 == memcmp(mac, test_mac[i], 16U),
("failure (wrong MAC)\n"));
mbedtls_chachapoly_free(&ctx);
if (verbose != 0) {
mbedtls_printf("passed\n");
}
}
if (verbose != 0) {
mbedtls_printf("\n");
}
return 0;
}
#endif /* MBEDTLS_SELF_TEST */
#endif /* MBEDTLS_CHACHAPOLY_C */

View File

@@ -0,0 +1,141 @@
/**
* \file check_crypto_config.h
*
* \brief Consistency checks for PSA configuration options
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
/*
* It is recommended to include this file from your crypto_config.h
* in order to catch dependency issues early.
*/
#ifndef MBEDTLS_CHECK_CRYPTO_CONFIG_H
#define MBEDTLS_CHECK_CRYPTO_CONFIG_H
#if defined(PSA_WANT_ALG_CCM) && \
!(defined(PSA_WANT_KEY_TYPE_AES) || \
defined(PSA_WANT_KEY_TYPE_CAMELLIA))
#error "PSA_WANT_ALG_CCM defined, but not all prerequisites"
#endif
#if defined(PSA_WANT_ALG_CMAC) && \
!(defined(PSA_WANT_KEY_TYPE_AES) || \
defined(PSA_WANT_KEY_TYPE_CAMELLIA) || \
defined(PSA_WANT_KEY_TYPE_DES))
#error "PSA_WANT_ALG_CMAC defined, but not all prerequisites"
#endif
#if defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA) && \
!(defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \
defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY))
#error "PSA_WANT_ALG_DETERMINISTIC_ECDSA defined, but not all prerequisites"
#endif
#if defined(PSA_WANT_ALG_ECDSA) && \
!(defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \
defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY))
#error "PSA_WANT_ALG_ECDSA defined, but not all prerequisites"
#endif
#if defined(PSA_WANT_ALG_GCM) && \
!(defined(PSA_WANT_KEY_TYPE_AES) || \
defined(PSA_WANT_KEY_TYPE_CAMELLIA))
#error "PSA_WANT_ALG_GCM defined, but not all prerequisites"
#endif
#if defined(PSA_WANT_ALG_RSA_PKCS1V15_CRYPT) && \
!(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) || \
defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY))
#error "PSA_WANT_ALG_RSA_PKCS1V15_CRYPT defined, but not all prerequisites"
#endif
#if defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) && \
!(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) || \
defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY))
#error "PSA_WANT_ALG_RSA_PKCS1V15_SIGN defined, but not all prerequisites"
#endif
#if defined(PSA_WANT_ALG_RSA_OAEP) && \
!(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) || \
defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY))
#error "PSA_WANT_ALG_RSA_OAEP defined, but not all prerequisites"
#endif
#if defined(PSA_WANT_ALG_RSA_PSS) && \
!(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) || \
defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY))
#error "PSA_WANT_ALG_RSA_PSS defined, but not all prerequisites"
#endif
#if (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \
defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \
defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \
defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) || \
defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE)) && \
!defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
#error "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_xxx defined, but not all prerequisites"
#endif
#if (defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) || \
defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT) || \
defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \
defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE)) && \
!defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY)
#error "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_xxx defined, but not all prerequisites"
#endif
#if (defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC) || \
defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT) || \
defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \
defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE)) && \
!defined(PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY)
#error "PSA_WANT_KEY_TYPE_DH_KEY_PAIR_xxx defined, but not all prerequisites"
#endif
#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR)
#if defined(MBEDTLS_DEPRECATED_REMOVED)
#error "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR is deprecated and will be removed in a \
future version of Mbed TLS. Please switch to new PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_xxx \
symbols, where xxx can be: USE, IMPORT, EXPORT, GENERATE, DERIVE"
#elif defined(MBEDTLS_DEPRECATED_WARNING)
#warning "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR is deprecated and will be removed in a \
future version of Mbed TLS. Please switch to new PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_xxx \
symbols, where xxx can be: USE, IMPORT, EXPORT, GENERATE, DERIVE"
#endif /* MBEDTLS_DEPRECATED_WARNING */
#endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR */
#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)
#if defined(MBEDTLS_DEPRECATED_REMOVED)
#error "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR is deprecated and will be removed in a \
future version of Mbed TLS. Please switch to new PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_xxx \
symbols, where xxx can be: USE, IMPORT, EXPORT, GENERATE, DERIVE"
#elif defined(MBEDTLS_DEPRECATED_WARNING)
#warning "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR is deprecated and will be removed in a \
future version of Mbed TLS. Please switch to new PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_xxx \
symbols, where xxx can be: USE, IMPORT, EXPORT, GENERATE, DERIVE"
#endif /* MBEDTLS_DEPRECATED_WARNING */
#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR */
#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_DERIVE)
#error "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_DERIVE defined, but feature is not supported"
#endif
#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_DERIVE)
#error "PSA_WANT_KEY_TYPE_DH_KEY_PAIR_DERIVE defined, but feature is not supported"
#endif
#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_USE_PSA_CRYPTO) && \
!(defined(PSA_WANT_ALG_SHA_1) || defined(PSA_WANT_ALG_SHA_256) || defined(PSA_WANT_ALG_SHA_512))
#error "MBEDTLS_SSL_PROTO_TLS1_2 defined, but not all prerequisites"
#endif
#if defined(PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS) && \
!defined(PSA_WANT_ALG_SHA_256)
#error "PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS defined, but not all prerequisites"
#endif
#endif /* MBEDTLS_CHECK_CRYPTO_CONFIG_H */

1689
thirdparty/mbedtls/library/cipher.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,27 @@
/**
* \file cipher_invasive.h
*
* \brief Cipher module: interfaces for invasive testing only.
*
* The interfaces in this file are intended for testing purposes only.
* They SHOULD NOT be made available in library integrations except when
* building the library for testing.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef MBEDTLS_CIPHER_INVASIVE_H
#define MBEDTLS_CIPHER_INVASIVE_H
#include "common.h"
#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_CIPHER_C)
MBEDTLS_STATIC_TESTABLE int mbedtls_get_pkcs_padding(unsigned char *input,
size_t input_len,
size_t *data_len);
#endif
#endif /* MBEDTLS_CIPHER_INVASIVE_H */

2482
thirdparty/mbedtls/library/cipher_wrap.c vendored Normal file

File diff suppressed because it is too large Load Diff

178
thirdparty/mbedtls/library/cipher_wrap.h vendored Normal file
View File

@@ -0,0 +1,178 @@
/**
* \file cipher_wrap.h
*
* \brief Cipher wrappers.
*
* \author Adriaan de Jong <dejong@fox-it.com>
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef MBEDTLS_CIPHER_WRAP_H
#define MBEDTLS_CIPHER_WRAP_H
#include "mbedtls/build_info.h"
#include "mbedtls/cipher.h"
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#include "psa/crypto.h"
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#ifdef __cplusplus
extern "C" {
#endif
/* Support for GCM either through Mbed TLS SW implementation or PSA */
#if defined(MBEDTLS_GCM_C) || \
(defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_GCM))
#define MBEDTLS_CIPHER_HAVE_GCM_VIA_LEGACY_OR_USE_PSA
#endif
#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_AES_C)) || \
(defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_GCM) && defined(PSA_WANT_KEY_TYPE_AES))
#define MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA
#endif
#if defined(MBEDTLS_CCM_C) || \
(defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CCM))
#define MBEDTLS_CIPHER_HAVE_CCM_VIA_LEGACY_OR_USE_PSA
#endif
#if (defined(MBEDTLS_CCM_C) && defined(MBEDTLS_AES_C)) || \
(defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CCM) && defined(PSA_WANT_KEY_TYPE_AES))
#define MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA
#endif
#if defined(MBEDTLS_CCM_C) || \
(defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CCM_STAR_NO_TAG))
#define MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_VIA_LEGACY_OR_USE_PSA
#endif
#if (defined(MBEDTLS_CCM_C) && defined(MBEDTLS_AES_C)) || \
(defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CCM_STAR_NO_TAG) && \
defined(PSA_WANT_KEY_TYPE_AES))
#define MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_AES_VIA_LEGACY_OR_USE_PSA
#endif
#if defined(MBEDTLS_CHACHAPOLY_C) || \
(defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CHACHA20_POLY1305))
#define MBEDTLS_CIPHER_HAVE_CHACHAPOLY_VIA_LEGACY_OR_USE_PSA
#endif
#if defined(MBEDTLS_CIPHER_HAVE_GCM_VIA_LEGACY_OR_USE_PSA) || \
defined(MBEDTLS_CIPHER_HAVE_CCM_VIA_LEGACY_OR_USE_PSA) || \
defined(MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_VIA_LEGACY_OR_USE_PSA) || \
defined(MBEDTLS_CIPHER_HAVE_CHACHAPOLY_VIA_LEGACY_OR_USE_PSA)
#define MBEDTLS_CIPHER_HAVE_SOME_AEAD_VIA_LEGACY_OR_USE_PSA
#endif
/**
* Base cipher information. The non-mode specific functions and values.
*/
struct mbedtls_cipher_base_t {
/** Base Cipher type (e.g. MBEDTLS_CIPHER_ID_AES) */
mbedtls_cipher_id_t cipher;
/** Encrypt using ECB */
int (*ecb_func)(void *ctx, mbedtls_operation_t mode,
const unsigned char *input, unsigned char *output);
#if defined(MBEDTLS_CIPHER_MODE_CBC)
/** Encrypt using CBC */
int (*cbc_func)(void *ctx, mbedtls_operation_t mode, size_t length,
unsigned char *iv, const unsigned char *input,
unsigned char *output);
#endif
#if defined(MBEDTLS_CIPHER_MODE_CFB)
/** Encrypt using CFB (Full length) */
int (*cfb_func)(void *ctx, mbedtls_operation_t mode, size_t length, size_t *iv_off,
unsigned char *iv, const unsigned char *input,
unsigned char *output);
#endif
#if defined(MBEDTLS_CIPHER_MODE_OFB)
/** Encrypt using OFB (Full length) */
int (*ofb_func)(void *ctx, size_t length, size_t *iv_off,
unsigned char *iv,
const unsigned char *input,
unsigned char *output);
#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
/** Encrypt using CTR */
int (*ctr_func)(void *ctx, size_t length, size_t *nc_off,
unsigned char *nonce_counter, unsigned char *stream_block,
const unsigned char *input, unsigned char *output);
#endif
#if defined(MBEDTLS_CIPHER_MODE_XTS)
/** Encrypt or decrypt using XTS. */
int (*xts_func)(void *ctx, mbedtls_operation_t mode, size_t length,
const unsigned char data_unit[16],
const unsigned char *input, unsigned char *output);
#endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM)
/** Encrypt using STREAM */
int (*stream_func)(void *ctx, size_t length,
const unsigned char *input, unsigned char *output);
#endif
/** Set key for encryption purposes */
int (*setkey_enc_func)(void *ctx, const unsigned char *key,
unsigned int key_bitlen);
#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
/** Set key for decryption purposes */
int (*setkey_dec_func)(void *ctx, const unsigned char *key,
unsigned int key_bitlen);
#endif
/** Allocate a new context */
void * (*ctx_alloc_func)(void);
/** Free the given context */
void (*ctx_free_func)(void *ctx);
};
typedef struct {
mbedtls_cipher_type_t type;
const mbedtls_cipher_info_t *info;
} mbedtls_cipher_definition_t;
#if defined(MBEDTLS_USE_PSA_CRYPTO)
typedef enum {
MBEDTLS_CIPHER_PSA_KEY_UNSET = 0,
MBEDTLS_CIPHER_PSA_KEY_OWNED, /* Used for PSA-based cipher contexts which */
/* use raw key material internally imported */
/* as a volatile key, and which hence need */
/* to destroy that key when the context is */
/* freed. */
MBEDTLS_CIPHER_PSA_KEY_NOT_OWNED, /* Used for PSA-based cipher contexts */
/* which use a key provided by the */
/* user, and which hence will not be */
/* destroyed when the context is freed. */
} mbedtls_cipher_psa_key_ownership;
typedef struct {
psa_algorithm_t alg;
mbedtls_svc_key_id_t slot;
mbedtls_cipher_psa_key_ownership slot_state;
} mbedtls_cipher_context_psa;
#endif /* MBEDTLS_USE_PSA_CRYPTO */
extern const mbedtls_cipher_definition_t mbedtls_cipher_definitions[];
extern int mbedtls_cipher_supported[];
extern const mbedtls_cipher_base_t * const mbedtls_cipher_base_lookup_table[];
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_CIPHER_WRAP_H */

1067
thirdparty/mbedtls/library/cmac.c vendored Normal file

File diff suppressed because it is too large Load Diff

453
thirdparty/mbedtls/library/common.h vendored Normal file
View File

@@ -0,0 +1,453 @@
/**
* \file common.h
*
* \brief Utility macros for internal use in the library
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef MBEDTLS_LIBRARY_COMMON_H
#define MBEDTLS_LIBRARY_COMMON_H
#include "mbedtls/build_info.h"
#include "alignment.h"
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <stddef.h>
#if defined(__ARM_NEON)
#include <arm_neon.h>
#define MBEDTLS_HAVE_NEON_INTRINSICS
#elif defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64)
#include <arm64_neon.h>
#define MBEDTLS_HAVE_NEON_INTRINSICS
#endif
/** Helper to define a function as static except when building invasive tests.
*
* If a function is only used inside its own source file and should be
* declared `static` to allow the compiler to optimize for code size,
* but that function has unit tests, define it with
* ```
* MBEDTLS_STATIC_TESTABLE int mbedtls_foo(...) { ... }
* ```
* and declare it in a header in the `library/` directory with
* ```
* #if defined(MBEDTLS_TEST_HOOKS)
* int mbedtls_foo(...);
* #endif
* ```
*/
#if defined(MBEDTLS_TEST_HOOKS)
#define MBEDTLS_STATIC_TESTABLE
#else
#define MBEDTLS_STATIC_TESTABLE static
#endif
#if defined(MBEDTLS_TEST_HOOKS)
extern void (*mbedtls_test_hook_test_fail)(const char *test, int line, const char *file);
#define MBEDTLS_TEST_HOOK_TEST_ASSERT(TEST) \
do { \
if ((!(TEST)) && ((*mbedtls_test_hook_test_fail) != NULL)) \
{ \
(*mbedtls_test_hook_test_fail)( #TEST, __LINE__, __FILE__); \
} \
} while (0)
#else
#define MBEDTLS_TEST_HOOK_TEST_ASSERT(TEST)
#endif /* defined(MBEDTLS_TEST_HOOKS) */
/** \def ARRAY_LENGTH
* Return the number of elements of a static or stack array.
*
* \param array A value of array (not pointer) type.
*
* \return The number of elements of the array.
*/
/* A correct implementation of ARRAY_LENGTH, but which silently gives
* a nonsensical result if called with a pointer rather than an array. */
#define ARRAY_LENGTH_UNSAFE(array) \
(sizeof(array) / sizeof(*(array)))
#if defined(__GNUC__)
/* Test if arg and &(arg)[0] have the same type. This is true if arg is
* an array but not if it's a pointer. */
#define IS_ARRAY_NOT_POINTER(arg) \
(!__builtin_types_compatible_p(__typeof__(arg), \
__typeof__(&(arg)[0])))
/* A compile-time constant with the value 0. If `const_expr` is not a
* compile-time constant with a nonzero value, cause a compile-time error. */
#define STATIC_ASSERT_EXPR(const_expr) \
(0 && sizeof(struct { unsigned int STATIC_ASSERT : 1 - 2 * !(const_expr); }))
/* Return the scalar value `value` (possibly promoted). This is a compile-time
* constant if `value` is. `condition` must be a compile-time constant.
* If `condition` is false, arrange to cause a compile-time error. */
#define STATIC_ASSERT_THEN_RETURN(condition, value) \
(STATIC_ASSERT_EXPR(condition) ? 0 : (value))
#define ARRAY_LENGTH(array) \
(STATIC_ASSERT_THEN_RETURN(IS_ARRAY_NOT_POINTER(array), \
ARRAY_LENGTH_UNSAFE(array)))
#else
/* If we aren't sure the compiler supports our non-standard tricks,
* fall back to the unsafe implementation. */
#define ARRAY_LENGTH(array) ARRAY_LENGTH_UNSAFE(array)
#endif
/** Allow library to access its structs' private members.
*
* Although structs defined in header files are publicly available,
* their members are private and should not be accessed by the user.
*/
#define MBEDTLS_ALLOW_PRIVATE_ACCESS
/**
* \brief Securely zeroize a buffer then free it.
*
* Similar to making consecutive calls to
* \c mbedtls_platform_zeroize() and \c mbedtls_free(), but has
* code size savings, and potential for optimisation in the future.
*
* Guaranteed to be a no-op if \p buf is \c NULL and \p len is 0.
*
* \param buf Buffer to be zeroized then freed.
* \param len Length of the buffer in bytes
*/
void mbedtls_zeroize_and_free(void *buf, size_t len);
/** Return an offset into a buffer.
*
* This is just the addition of an offset to a pointer, except that this
* function also accepts an offset of 0 into a buffer whose pointer is null.
* (`p + n` has undefined behavior when `p` is null, even when `n == 0`.
* A null pointer is a valid buffer pointer when the size is 0, for example
* as the result of `malloc(0)` on some platforms.)
*
* \param p Pointer to a buffer of at least n bytes.
* This may be \p NULL if \p n is zero.
* \param n An offset in bytes.
* \return Pointer to offset \p n in the buffer \p p.
* Note that this is only a valid pointer if the size of the
* buffer is at least \p n + 1.
*/
static inline unsigned char *mbedtls_buffer_offset(
unsigned char *p, size_t n)
{
return p == NULL ? NULL : p + n;
}
/** Return an offset into a read-only buffer.
*
* Similar to mbedtls_buffer_offset(), but for const pointers.
*
* \param p Pointer to a buffer of at least n bytes.
* This may be \p NULL if \p n is zero.
* \param n An offset in bytes.
* \return Pointer to offset \p n in the buffer \p p.
* Note that this is only a valid pointer if the size of the
* buffer is at least \p n + 1.
*/
static inline const unsigned char *mbedtls_buffer_offset_const(
const unsigned char *p, size_t n)
{
return p == NULL ? NULL : p + n;
}
/* Always inline mbedtls_xor() for similar reasons as mbedtls_xor_no_simd(). */
#if defined(__IAR_SYSTEMS_ICC__)
#pragma inline = forced
#elif defined(__GNUC__)
__attribute__((always_inline))
#endif
/**
* Perform a fast block XOR operation, such that
* r[i] = a[i] ^ b[i] where 0 <= i < n
*
* \param r Pointer to result (buffer of at least \p n bytes). \p r
* may be equal to either \p a or \p b, but behaviour when
* it overlaps in other ways is undefined.
* \param a Pointer to input (buffer of at least \p n bytes)
* \param b Pointer to input (buffer of at least \p n bytes)
* \param n Number of bytes to process.
*
* \note Depending on the situation, it may be faster to use either mbedtls_xor() or
* mbedtls_xor_no_simd() (these are functionally equivalent).
* If the result is used immediately after the xor operation in non-SIMD code (e.g, in
* AES-CBC), there may be additional latency to transfer the data from SIMD to scalar
* registers, and in this case, mbedtls_xor_no_simd() may be faster. In other cases where
* the result is not used immediately (e.g., in AES-CTR), mbedtls_xor() may be faster.
* For targets without SIMD support, they will behave the same.
*/
static inline void mbedtls_xor(unsigned char *r,
const unsigned char *a,
const unsigned char *b,
size_t n)
{
size_t i = 0;
#if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS)
#if defined(MBEDTLS_HAVE_NEON_INTRINSICS) && \
(!(defined(MBEDTLS_COMPILER_IS_GCC) && MBEDTLS_GCC_VERSION < 70300))
/* Old GCC versions generate a warning here, so disable the NEON path for these compilers */
for (; (i + 16) <= n; i += 16) {
uint8x16_t v1 = vld1q_u8(a + i);
uint8x16_t v2 = vld1q_u8(b + i);
uint8x16_t x = veorq_u8(v1, v2);
vst1q_u8(r + i, x);
}
#if defined(__IAR_SYSTEMS_ICC__)
/* This if statement helps some compilers (e.g., IAR) optimise out the byte-by-byte tail case
* where n is a constant multiple of 16.
* For other compilers (e.g. recent gcc and clang) it makes no difference if n is a compile-time
* constant, and is a very small perf regression if n is not a compile-time constant. */
if (n % 16 == 0) {
return;
}
#endif
#elif defined(MBEDTLS_ARCH_IS_X64) || defined(MBEDTLS_ARCH_IS_ARM64)
/* This codepath probably only makes sense on architectures with 64-bit registers */
for (; (i + 8) <= n; i += 8) {
uint64_t x = mbedtls_get_unaligned_uint64(a + i) ^ mbedtls_get_unaligned_uint64(b + i);
mbedtls_put_unaligned_uint64(r + i, x);
}
#if defined(__IAR_SYSTEMS_ICC__)
if (n % 8 == 0) {
return;
}
#endif
#else
for (; (i + 4) <= n; i += 4) {
uint32_t x = mbedtls_get_unaligned_uint32(a + i) ^ mbedtls_get_unaligned_uint32(b + i);
mbedtls_put_unaligned_uint32(r + i, x);
}
#if defined(__IAR_SYSTEMS_ICC__)
if (n % 4 == 0) {
return;
}
#endif
#endif
#endif
for (; i < n; i++) {
r[i] = a[i] ^ b[i];
}
}
/* Always inline mbedtls_xor_no_simd() as we see significant perf regressions when it does not get
* inlined (e.g., observed about 3x perf difference in gcm_mult_largetable with gcc 7 - 12) */
#if defined(__IAR_SYSTEMS_ICC__)
#pragma inline = forced
#elif defined(__GNUC__)
__attribute__((always_inline))
#endif
/**
* Perform a fast block XOR operation, such that
* r[i] = a[i] ^ b[i] where 0 <= i < n
*
* In some situations, this can perform better than mbedtls_xor() (e.g., it's about 5%
* better in AES-CBC).
*
* \param r Pointer to result (buffer of at least \p n bytes). \p r
* may be equal to either \p a or \p b, but behaviour when
* it overlaps in other ways is undefined.
* \param a Pointer to input (buffer of at least \p n bytes)
* \param b Pointer to input (buffer of at least \p n bytes)
* \param n Number of bytes to process.
*
* \note Depending on the situation, it may be faster to use either mbedtls_xor() or
* mbedtls_xor_no_simd() (these are functionally equivalent).
* If the result is used immediately after the xor operation in non-SIMD code (e.g, in
* AES-CBC), there may be additional latency to transfer the data from SIMD to scalar
* registers, and in this case, mbedtls_xor_no_simd() may be faster. In other cases where
* the result is not used immediately (e.g., in AES-CTR), mbedtls_xor() may be faster.
* For targets without SIMD support, they will behave the same.
*/
static inline void mbedtls_xor_no_simd(unsigned char *r,
const unsigned char *a,
const unsigned char *b,
size_t n)
{
size_t i = 0;
#if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS)
#if defined(MBEDTLS_ARCH_IS_X64) || defined(MBEDTLS_ARCH_IS_ARM64)
/* This codepath probably only makes sense on architectures with 64-bit registers */
for (; (i + 8) <= n; i += 8) {
uint64_t x = mbedtls_get_unaligned_uint64(a + i) ^ mbedtls_get_unaligned_uint64(b + i);
mbedtls_put_unaligned_uint64(r + i, x);
}
#if defined(__IAR_SYSTEMS_ICC__)
/* This if statement helps some compilers (e.g., IAR) optimise out the byte-by-byte tail case
* where n is a constant multiple of 8.
* For other compilers (e.g. recent gcc and clang) it makes no difference if n is a compile-time
* constant, and is a very small perf regression if n is not a compile-time constant. */
if (n % 8 == 0) {
return;
}
#endif
#else
for (; (i + 4) <= n; i += 4) {
uint32_t x = mbedtls_get_unaligned_uint32(a + i) ^ mbedtls_get_unaligned_uint32(b + i);
mbedtls_put_unaligned_uint32(r + i, x);
}
#if defined(__IAR_SYSTEMS_ICC__)
if (n % 4 == 0) {
return;
}
#endif
#endif
#endif
for (; i < n; i++) {
r[i] = a[i] ^ b[i];
}
}
/* Fix MSVC C99 compatible issue
* MSVC support __func__ from visual studio 2015( 1900 )
* Use MSVC predefine macro to avoid name check fail.
*/
#if (defined(_MSC_VER) && (_MSC_VER <= 1900))
#define /*no-check-names*/ __func__ __FUNCTION__
#endif
/* Define `asm` for compilers which don't define it. */
/* *INDENT-OFF* */
#ifndef asm
#if defined(__IAR_SYSTEMS_ICC__)
#define asm __asm
#else
#define asm __asm__
#endif
#endif
/* *INDENT-ON* */
/*
* Define the constraint used for read-only pointer operands to aarch64 asm.
*
* This is normally the usual "r", but for aarch64_32 (aka ILP32,
* as found in watchos), "p" is required to avoid warnings from clang.
*
* Note that clang does not recognise '+p' or '=p', and armclang
* does not recognise 'p' at all. Therefore, to update a pointer from
* aarch64 assembly, it is necessary to use something like:
*
* uintptr_t uptr = (uintptr_t) ptr;
* asm( "ldr x4, [%x0], #8" ... : "+r" (uptr) : : )
* ptr = (void*) uptr;
*
* Note that the "x" in "%x0" is neccessary; writing "%0" will cause warnings.
*/
#if defined(__aarch64__) && defined(MBEDTLS_HAVE_ASM)
#if UINTPTR_MAX == 0xfffffffful
/* ILP32: Specify the pointer operand slightly differently, as per #7787. */
#define MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT "p"
#elif UINTPTR_MAX == 0xfffffffffffffffful
/* Normal case (64-bit pointers): use "r" as the constraint for pointer operands to asm */
#define MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT "r"
#else
#error "Unrecognised pointer size for aarch64"
#endif
#endif
/* Always provide a static assert macro, so it can be used unconditionally.
* It does nothing on systems where we don't know how to define a static assert.
*/
/* Can't use the C11-style `defined(static_assert)` on FreeBSD, since it
* defines static_assert even with -std=c99, but then complains about it.
*/
#if defined(static_assert) && !defined(__FreeBSD__)
#define MBEDTLS_STATIC_ASSERT(expr, msg) static_assert(expr, msg)
#else
/* Make sure `MBEDTLS_STATIC_ASSERT(expr, msg);` is valid both inside and
* outside a function. We choose a struct declaration, which can be repeated
* any number of times and does not need a matching definition. */
#define MBEDTLS_STATIC_ASSERT(expr, msg) \
struct ISO_C_does_not_allow_extra_semicolon_outside_of_a_function
#endif
#if defined(__has_builtin)
#define MBEDTLS_HAS_BUILTIN(x) __has_builtin(x)
#else
#define MBEDTLS_HAS_BUILTIN(x) 0
#endif
/* Define compiler branch hints */
#if MBEDTLS_HAS_BUILTIN(__builtin_expect)
#define MBEDTLS_LIKELY(x) __builtin_expect(!!(x), 1)
#define MBEDTLS_UNLIKELY(x) __builtin_expect(!!(x), 0)
#else
#define MBEDTLS_LIKELY(x) x
#define MBEDTLS_UNLIKELY(x) x
#endif
/* MBEDTLS_ASSUME may be used to provide additional information to the compiler
* which can result in smaller code-size. */
#if MBEDTLS_HAS_BUILTIN(__builtin_assume)
/* clang provides __builtin_assume */
#define MBEDTLS_ASSUME(x) __builtin_assume(x)
#elif MBEDTLS_HAS_BUILTIN(__builtin_unreachable)
/* gcc and IAR can use __builtin_unreachable */
#define MBEDTLS_ASSUME(x) do { if (!(x)) __builtin_unreachable(); } while (0)
#elif defined(_MSC_VER)
/* Supported by MSVC since VS 2005 */
#define MBEDTLS_ASSUME(x) __assume(x)
#else
#define MBEDTLS_ASSUME(x) do { } while (0)
#endif
/* For gcc -Os, override with -O2 for a given function.
*
* This will not affect behaviour for other optimisation settings, e.g. -O0.
*/
#if defined(MBEDTLS_COMPILER_IS_GCC) && defined(__OPTIMIZE_SIZE__)
#define MBEDTLS_OPTIMIZE_FOR_PERFORMANCE __attribute__((optimize("-O2")))
#else
#define MBEDTLS_OPTIMIZE_FOR_PERFORMANCE
#endif
/* Suppress compiler warnings for unused functions and variables. */
#if !defined(MBEDTLS_MAYBE_UNUSED) && defined(__has_attribute)
# if __has_attribute(unused)
# define MBEDTLS_MAYBE_UNUSED __attribute__((unused))
# endif
#endif
#if !defined(MBEDTLS_MAYBE_UNUSED) && defined(__GNUC__)
# define MBEDTLS_MAYBE_UNUSED __attribute__((unused))
#endif
#if !defined(MBEDTLS_MAYBE_UNUSED) && defined(__IAR_SYSTEMS_ICC__) && defined(__VER__)
/* IAR does support __attribute__((unused)), but only if the -e flag (extended language support)
* is given; the pragma always works.
* Unfortunately the pragma affects the rest of the file where it is used, but this is harmless.
* Check for version 5.2 or later - this pragma may be supported by earlier versions, but I wasn't
* able to find documentation).
*/
# if (__VER__ >= 5020000)
# define MBEDTLS_MAYBE_UNUSED _Pragma("diag_suppress=Pe177")
# endif
#endif
#if !defined(MBEDTLS_MAYBE_UNUSED) && defined(_MSC_VER)
# define MBEDTLS_MAYBE_UNUSED __pragma(warning(suppress:4189))
#endif
#if !defined(MBEDTLS_MAYBE_UNUSED)
# define MBEDTLS_MAYBE_UNUSED
#endif
/* GCC >= 15 has a warning 'unterminated-string-initialization' which complains if you initialize
* a string into an array without space for a terminating NULL character. In some places in the
* codebase this behaviour is intended, so we add the macro MBEDTLS_ATTRIBUTE_UNTERMINATED_STRING
* to suppress the warning in these places.
*/
#if defined(__has_attribute)
#if __has_attribute(nonstring)
#define MBEDTLS_HAS_ATTRIBUTE_NONSTRING
#endif /* __has_attribute(nonstring) */
#endif /* __has_attribute */
#if defined(MBEDTLS_HAS_ATTRIBUTE_NONSTRING)
#define MBEDTLS_ATTRIBUTE_UNTERMINATED_STRING __attribute__((nonstring))
#else
#define MBEDTLS_ATTRIBUTE_UNTERMINATED_STRING
#endif /* MBEDTLS_HAS_ATTRIBUTE_NONSTRING */
#endif /* MBEDTLS_LIBRARY_COMMON_H */

View File

@@ -0,0 +1,248 @@
/**
* Constant-time functions
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
/*
* The following functions are implemented without using comparison operators, as those
* might be translated to branches by some compilers on some platforms.
*/
#include <stdint.h>
#include <limits.h>
#include "common.h"
#include "constant_time_internal.h"
#include "mbedtls/constant_time.h"
#include "mbedtls/error.h"
#include "mbedtls/platform_util.h"
#include <string.h>
#if !defined(MBEDTLS_CT_ASM)
/*
* Define an object with the value zero, such that the compiler cannot prove that it
* has the value zero (because it is volatile, it "may be modified in ways unknown to
* the implementation").
*/
volatile mbedtls_ct_uint_t mbedtls_ct_zero = 0;
#endif
/*
* Define MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS where assembly is present to
* perform fast unaligned access to volatile data.
*
* This is needed because mbedtls_get_unaligned_uintXX etc don't support volatile
* memory accesses.
*
* Some of these definitions could be moved into alignment.h but for now they are
* only used here.
*/
#if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) && \
((defined(MBEDTLS_CT_ARM_ASM) && (UINTPTR_MAX == 0xfffffffful)) || \
defined(MBEDTLS_CT_AARCH64_ASM))
/* We check pointer sizes to avoid issues with them not matching register size requirements */
#define MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS
static inline uint32_t mbedtls_get_unaligned_volatile_uint32(volatile const unsigned char *p)
{
/* This is UB, even where it's safe:
* return *((volatile uint32_t*)p);
* so instead the same thing is expressed in assembly below.
*/
uint32_t r;
#if defined(MBEDTLS_CT_ARM_ASM)
asm volatile ("ldr %0, [%1]" : "=r" (r) : "r" (p) :);
#elif defined(MBEDTLS_CT_AARCH64_ASM)
asm volatile ("ldr %w0, [%1]" : "=r" (r) : MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT(p) :);
#else
#error "No assembly defined for mbedtls_get_unaligned_volatile_uint32"
#endif
return r;
}
#endif /* defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) &&
(defined(MBEDTLS_CT_ARM_ASM) || defined(MBEDTLS_CT_AARCH64_ASM)) */
int mbedtls_ct_memcmp(const void *a,
const void *b,
size_t n)
{
size_t i = 0;
/*
* `A` and `B` are cast to volatile to ensure that the compiler
* generates code that always fully reads both buffers.
* Otherwise it could generate a test to exit early if `diff` has all
* bits set early in the loop.
*/
volatile const unsigned char *A = (volatile const unsigned char *) a;
volatile const unsigned char *B = (volatile const unsigned char *) b;
uint32_t diff = 0;
#if defined(MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS)
for (; (i + 4) <= n; i += 4) {
uint32_t x = mbedtls_get_unaligned_volatile_uint32(A + i);
uint32_t y = mbedtls_get_unaligned_volatile_uint32(B + i);
diff |= x ^ y;
}
#endif
for (; i < n; i++) {
/* Read volatile data in order before computing diff.
* This avoids IAR compiler warning:
* 'the order of volatile accesses is undefined ..' */
unsigned char x = A[i], y = B[i];
diff |= x ^ y;
}
#if (INT_MAX < INT32_MAX)
/* We don't support int smaller than 32-bits, but if someone tried to build
* with this configuration, there is a risk that, for differing data, the
* only bits set in diff are in the top 16-bits, and would be lost by a
* simple cast from uint32 to int.
* This would have significant security implications, so protect against it. */
#error "mbedtls_ct_memcmp() requires minimum 32-bit ints"
#else
/* The bit-twiddling ensures that when we cast uint32_t to int, we are casting
* a value that is in the range 0..INT_MAX - a value larger than this would
* result in implementation defined behaviour.
*
* This ensures that the value returned by the function is non-zero iff
* diff is non-zero.
*/
return (int) ((diff & 0xffff) | (diff >> 16));
#endif
}
#if defined(MBEDTLS_NIST_KW_C)
int mbedtls_ct_memcmp_partial(const void *a,
const void *b,
size_t n,
size_t skip_head,
size_t skip_tail)
{
unsigned int diff = 0;
volatile const unsigned char *A = (volatile const unsigned char *) a;
volatile const unsigned char *B = (volatile const unsigned char *) b;
size_t valid_end = n - skip_tail;
for (size_t i = 0; i < n; i++) {
unsigned char x = A[i], y = B[i];
unsigned int d = x ^ y;
mbedtls_ct_condition_t valid = mbedtls_ct_bool_and(mbedtls_ct_uint_ge(i, skip_head),
mbedtls_ct_uint_lt(i, valid_end));
diff |= mbedtls_ct_uint_if_else_0(valid, d);
}
/* Since we go byte-by-byte, the only bits set will be in the bottom 8 bits, so the
* cast from uint to int is safe. */
return (int) diff;
}
#endif
#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)
void mbedtls_ct_memmove_left(void *start, size_t total, size_t offset)
{
volatile unsigned char *buf = start;
for (size_t i = 0; i < total; i++) {
mbedtls_ct_condition_t no_op = mbedtls_ct_uint_gt(total - offset, i);
/* The first `total - offset` passes are a no-op. The last
* `offset` passes shift the data one byte to the left and
* zero out the last byte. */
for (size_t n = 0; n < total - 1; n++) {
unsigned char current = buf[n];
unsigned char next = buf[n+1];
buf[n] = mbedtls_ct_uint_if(no_op, current, next);
}
buf[total-1] = mbedtls_ct_uint_if_else_0(no_op, buf[total-1]);
}
}
#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */
void mbedtls_ct_memcpy_if(mbedtls_ct_condition_t condition,
unsigned char *dest,
const unsigned char *src1,
const unsigned char *src2,
size_t len)
{
#if defined(MBEDTLS_CT_SIZE_64)
const uint64_t mask = (uint64_t) condition;
const uint64_t not_mask = (uint64_t) ~mbedtls_ct_compiler_opaque(condition);
#else
const uint32_t mask = (uint32_t) condition;
const uint32_t not_mask = (uint32_t) ~mbedtls_ct_compiler_opaque(condition);
#endif
/* If src2 is NULL, setup src2 so that we read from the destination address.
*
* This means that if src2 == NULL && condition is false, the result will be a
* no-op because we read from dest and write the same data back into dest.
*/
if (src2 == NULL) {
src2 = dest;
}
/* dest[i] = c1 == c2 ? src[i] : dest[i] */
size_t i = 0;
#if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS)
#if defined(MBEDTLS_CT_SIZE_64)
for (; (i + 8) <= len; i += 8) {
uint64_t a = mbedtls_get_unaligned_uint64(src1 + i) & mask;
uint64_t b = mbedtls_get_unaligned_uint64(src2 + i) & not_mask;
mbedtls_put_unaligned_uint64(dest + i, a | b);
}
#else
for (; (i + 4) <= len; i += 4) {
uint32_t a = mbedtls_get_unaligned_uint32(src1 + i) & mask;
uint32_t b = mbedtls_get_unaligned_uint32(src2 + i) & not_mask;
mbedtls_put_unaligned_uint32(dest + i, a | b);
}
#endif /* defined(MBEDTLS_CT_SIZE_64) */
#endif /* MBEDTLS_EFFICIENT_UNALIGNED_ACCESS */
for (; i < len; i++) {
dest[i] = (src1[i] & mask) | (src2[i] & not_mask);
}
}
void mbedtls_ct_memcpy_offset(unsigned char *dest,
const unsigned char *src,
size_t offset,
size_t offset_min,
size_t offset_max,
size_t len)
{
size_t offsetval;
for (offsetval = offset_min; offsetval <= offset_max; offsetval++) {
mbedtls_ct_memcpy_if(mbedtls_ct_uint_eq(offsetval, offset), dest, src + offsetval, NULL,
len);
}
}
#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)
void mbedtls_ct_zeroize_if(mbedtls_ct_condition_t condition, void *buf, size_t len)
{
uint32_t mask = (uint32_t) ~condition;
uint8_t *p = (uint8_t *) buf;
size_t i = 0;
#if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS)
for (; (i + 4) <= len; i += 4) {
mbedtls_put_unaligned_uint32((void *) (p + i),
mbedtls_get_unaligned_uint32((void *) (p + i)) & mask);
}
#endif
for (; i < len; i++) {
p[i] = p[i] & mask;
}
}
#endif /* defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) */

View File

@@ -0,0 +1,541 @@
/**
* Constant-time functions
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef MBEDTLS_CONSTANT_TIME_IMPL_H
#define MBEDTLS_CONSTANT_TIME_IMPL_H
#include <stddef.h>
#include "common.h"
#if defined(MBEDTLS_BIGNUM_C)
#include "mbedtls/bignum.h"
#endif
/*
* To improve readability of constant_time_internal.h, the static inline
* definitions are here, and constant_time_internal.h has only the declarations.
*
* This results in duplicate declarations of the form:
* static inline void f(); // from constant_time_internal.h
* static inline void f() { ... } // from constant_time_impl.h
* when constant_time_internal.h is included.
*
* This appears to behave as if the declaration-without-definition was not present
* (except for warnings if gcc -Wredundant-decls or similar is used).
*
* Disable -Wredundant-decls so that gcc does not warn about this. This is re-enabled
* at the bottom of this file.
*/
#if defined(MBEDTLS_COMPILER_IS_GCC) && (__GNUC__ > 4)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wredundant-decls"
#endif
/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */
#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && (!defined(__ARMCC_VERSION) || \
__ARMCC_VERSION >= 6000000)
#define MBEDTLS_CT_ASM
#if (defined(__arm__) || defined(__thumb__) || defined(__thumb2__))
#define MBEDTLS_CT_ARM_ASM
#elif defined(__aarch64__)
#define MBEDTLS_CT_AARCH64_ASM
#elif defined(__amd64__) || defined(__x86_64__)
#define MBEDTLS_CT_X86_64_ASM
#elif defined(__i386__)
#define MBEDTLS_CT_X86_ASM
#endif
#endif
#define MBEDTLS_CT_SIZE (sizeof(mbedtls_ct_uint_t) * 8)
/* ============================================================================
* Core const-time primitives
*/
/* Ensure that the compiler cannot know the value of x (i.e., cannot optimise
* based on its value) after this function is called.
*
* If we are not using assembly, this will be fairly inefficient, so its use
* should be minimised.
*/
#if !defined(MBEDTLS_CT_ASM)
extern volatile mbedtls_ct_uint_t mbedtls_ct_zero;
#endif
/**
* \brief Ensure that a value cannot be known at compile time.
*
* \param x The value to hide from the compiler.
* \return The same value that was passed in, such that the compiler
* cannot prove its value (even for calls of the form
* x = mbedtls_ct_compiler_opaque(1), x will be unknown).
*
* \note This is mainly used in constructing mbedtls_ct_condition_t
* values and performing operations over them, to ensure that
* there is no way for the compiler to ever know anything about
* the value of an mbedtls_ct_condition_t.
*/
static inline mbedtls_ct_uint_t mbedtls_ct_compiler_opaque(mbedtls_ct_uint_t x)
{
#if defined(MBEDTLS_CT_ASM)
asm volatile ("" : [x] "+r" (x) :);
return x;
#else
return x ^ mbedtls_ct_zero;
#endif
}
/*
* Selecting unified syntax is needed for gcc, and harmless on clang.
*
* This is needed because on Thumb 1, condition flags are always set, so
* e.g. "negs" is supported but "neg" is not (on Thumb 2, both exist).
*
* Under Thumb 1 unified syntax, only the "negs" form is accepted, and
* under divided syntax, only the "neg" form is accepted. clang only
* supports unified syntax.
*
* On Thumb 2 and Arm, both compilers are happy with the "s" suffix,
* although we don't actually care about setting the flags.
*
* For old versions of gcc (see #8516 for details), restore divided
* syntax afterwards - otherwise old versions of gcc seem to apply
* unified syntax globally, which breaks other asm code.
*/
#if defined(MBEDTLS_COMPILER_IS_GCC) && defined(__thumb__) && !defined(__thumb2__) && \
(__GNUC__ < 11) && !defined(__ARM_ARCH_2__)
#define RESTORE_ASM_SYNTAX ".syntax divided \n\t"
#else
#define RESTORE_ASM_SYNTAX
#endif
/* Convert a number into a condition in constant time. */
static inline mbedtls_ct_condition_t mbedtls_ct_bool(mbedtls_ct_uint_t x)
{
/*
* Define mask-generation code that, as far as possible, will not use branches or conditional instructions.
*
* For some platforms / type sizes, we define assembly to assure this.
*
* Otherwise, we define a plain C fallback which (in May 2023) does not get optimised into
* conditional instructions or branches by trunk clang, gcc, or MSVC v19.
*/
#if defined(MBEDTLS_CT_AARCH64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64))
mbedtls_ct_uint_t s;
asm volatile ("neg %x[s], %x[x] \n\t"
"orr %x[x], %x[s], %x[x] \n\t"
"asr %x[x], %x[x], 63 \n\t"
:
[s] "=&r" (s),
[x] "+&r" (x)
:
:
);
return (mbedtls_ct_condition_t) x;
#elif defined(MBEDTLS_CT_ARM_ASM) && defined(MBEDTLS_CT_SIZE_32)
uint32_t s;
asm volatile (".syntax unified \n\t"
"negs %[s], %[x] \n\t"
"orrs %[x], %[x], %[s] \n\t"
"asrs %[x], %[x], #31 \n\t"
RESTORE_ASM_SYNTAX
:
[s] "=&l" (s),
[x] "+&l" (x)
:
:
"cc" /* clobbers flag bits */
);
return (mbedtls_ct_condition_t) x;
#elif defined(MBEDTLS_CT_X86_64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64))
uint64_t s;
asm volatile ("mov %[x], %[s] \n\t"
"neg %[s] \n\t"
"or %[x], %[s] \n\t"
"sar $63, %[s] \n\t"
:
[s] "=&a" (s)
:
[x] "D" (x)
:
);
return (mbedtls_ct_condition_t) s;
#elif defined(MBEDTLS_CT_X86_ASM) && defined(MBEDTLS_CT_SIZE_32)
uint32_t s;
asm volatile ("mov %[x], %[s] \n\t"
"neg %[s] \n\t"
"or %[s], %[x] \n\t"
"sar $31, %[x] \n\t"
:
[s] "=&c" (s),
[x] "+&a" (x)
:
:
);
return (mbedtls_ct_condition_t) x;
#else
const mbedtls_ct_uint_t xo = mbedtls_ct_compiler_opaque(x);
#if defined(_MSC_VER)
/* MSVC has a warning about unary minus on unsigned, but this is
* well-defined and precisely what we want to do here */
#pragma warning( push )
#pragma warning( disable : 4146 )
#endif
// y is negative (i.e., top bit set) iff x is non-zero
mbedtls_ct_int_t y = (-xo) | -(xo >> 1);
// extract only the sign bit of y so that y == 1 (if x is non-zero) or 0 (if x is zero)
y = (((mbedtls_ct_uint_t) y) >> (MBEDTLS_CT_SIZE - 1));
// -y has all bits set (if x is non-zero), or all bits clear (if x is zero)
return (mbedtls_ct_condition_t) (-y);
#if defined(_MSC_VER)
#pragma warning( pop )
#endif
#endif
}
static inline mbedtls_ct_uint_t mbedtls_ct_if(mbedtls_ct_condition_t condition,
mbedtls_ct_uint_t if1,
mbedtls_ct_uint_t if0)
{
#if defined(MBEDTLS_CT_AARCH64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64))
asm volatile ("and %x[if1], %x[if1], %x[condition] \n\t"
"mvn %x[condition], %x[condition] \n\t"
"and %x[condition], %x[condition], %x[if0] \n\t"
"orr %x[condition], %x[if1], %x[condition]"
:
[condition] "+&r" (condition),
[if1] "+&r" (if1)
:
[if0] "r" (if0)
:
);
return (mbedtls_ct_uint_t) condition;
#elif defined(MBEDTLS_CT_ARM_ASM) && defined(MBEDTLS_CT_SIZE_32)
asm volatile (".syntax unified \n\t"
"ands %[if1], %[if1], %[condition] \n\t"
"mvns %[condition], %[condition] \n\t"
"ands %[condition], %[condition], %[if0] \n\t"
"orrs %[condition], %[if1], %[condition] \n\t"
RESTORE_ASM_SYNTAX
:
[condition] "+&l" (condition),
[if1] "+&l" (if1)
:
[if0] "l" (if0)
:
"cc"
);
return (mbedtls_ct_uint_t) condition;
#elif defined(MBEDTLS_CT_X86_64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64))
asm volatile ("and %[condition], %[if1] \n\t"
"not %[condition] \n\t"
"and %[condition], %[if0] \n\t"
"or %[if1], %[if0] \n\t"
:
[condition] "+&D" (condition),
[if1] "+&S" (if1),
[if0] "+&a" (if0)
:
:
);
return if0;
#elif defined(MBEDTLS_CT_X86_ASM) && defined(MBEDTLS_CT_SIZE_32)
asm volatile ("and %[condition], %[if1] \n\t"
"not %[condition] \n\t"
"and %[if0], %[condition] \n\t"
"or %[condition], %[if1] \n\t"
:
[condition] "+&c" (condition),
[if1] "+&a" (if1)
:
[if0] "b" (if0)
:
);
return if1;
#else
mbedtls_ct_condition_t not_cond =
(mbedtls_ct_condition_t) (~mbedtls_ct_compiler_opaque(condition));
return (mbedtls_ct_uint_t) ((condition & if1) | (not_cond & if0));
#endif
}
static inline mbedtls_ct_condition_t mbedtls_ct_uint_lt(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y)
{
#if defined(MBEDTLS_CT_AARCH64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64))
uint64_t s1;
asm volatile ("eor %x[s1], %x[y], %x[x] \n\t"
"sub %x[x], %x[x], %x[y] \n\t"
"bic %x[x], %x[x], %x[s1] \n\t"
"and %x[s1], %x[s1], %x[y] \n\t"
"orr %x[s1], %x[x], %x[s1] \n\t"
"asr %x[x], %x[s1], 63"
:
[s1] "=&r" (s1),
[x] "+&r" (x)
:
[y] "r" (y)
:
);
return (mbedtls_ct_condition_t) x;
#elif defined(MBEDTLS_CT_ARM_ASM) && defined(MBEDTLS_CT_SIZE_32)
uint32_t s1;
asm volatile (
".syntax unified \n\t"
#if defined(__thumb__) && !defined(__thumb2__)
"movs %[s1], %[x] \n\t"
"eors %[s1], %[s1], %[y] \n\t"
#else
"eors %[s1], %[x], %[y] \n\t"
#endif
"subs %[x], %[x], %[y] \n\t"
"bics %[x], %[x], %[s1] \n\t"
"ands %[y], %[s1], %[y] \n\t"
"orrs %[x], %[x], %[y] \n\t"
"asrs %[x], %[x], #31 \n\t"
RESTORE_ASM_SYNTAX
:
[s1] "=&l" (s1),
[x] "+&l" (x),
[y] "+&l" (y)
:
:
"cc"
);
return (mbedtls_ct_condition_t) x;
#elif defined(MBEDTLS_CT_X86_64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64))
uint64_t s;
asm volatile ("mov %[x], %[s] \n\t"
"xor %[y], %[s] \n\t"
"sub %[y], %[x] \n\t"
"and %[s], %[y] \n\t"
"not %[s] \n\t"
"and %[s], %[x] \n\t"
"or %[y], %[x] \n\t"
"sar $63, %[x] \n\t"
:
[s] "=&a" (s),
[x] "+&D" (x),
[y] "+&S" (y)
:
:
);
return (mbedtls_ct_condition_t) x;
#elif defined(MBEDTLS_CT_X86_ASM) && defined(MBEDTLS_CT_SIZE_32)
uint32_t s;
asm volatile ("mov %[x], %[s] \n\t"
"xor %[y], %[s] \n\t"
"sub %[y], %[x] \n\t"
"and %[s], %[y] \n\t"
"not %[s] \n\t"
"and %[s], %[x] \n\t"
"or %[y], %[x] \n\t"
"sar $31, %[x] \n\t"
:
[s] "=&b" (s),
[x] "+&a" (x),
[y] "+&c" (y)
:
:
);
return (mbedtls_ct_condition_t) x;
#else
/* Ensure that the compiler cannot optimise the following operations over x and y,
* even if it knows the value of x and y.
*/
const mbedtls_ct_uint_t xo = mbedtls_ct_compiler_opaque(x);
const mbedtls_ct_uint_t yo = mbedtls_ct_compiler_opaque(y);
/*
* Check if the most significant bits (MSB) of the operands are different.
* cond is true iff the MSBs differ.
*/
mbedtls_ct_condition_t cond = mbedtls_ct_bool((xo ^ yo) >> (MBEDTLS_CT_SIZE - 1));
/*
* If the MSB are the same then the difference x-y will be negative (and
* have its MSB set to 1 during conversion to unsigned) if and only if x<y.
*
* If the MSB are different, then the operand with the MSB of 1 is the
* bigger. (That is if y has MSB of 1, then x<y is true and it is false if
* the MSB of y is 0.)
*/
// Select either y, or x - y
mbedtls_ct_uint_t ret = mbedtls_ct_if(cond, yo, (mbedtls_ct_uint_t) (xo - yo));
// Extract only the MSB of ret
ret = ret >> (MBEDTLS_CT_SIZE - 1);
// Convert to a condition (i.e., all bits set iff non-zero)
return mbedtls_ct_bool(ret);
#endif
}
static inline mbedtls_ct_condition_t mbedtls_ct_uint_ne(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y)
{
/* diff = 0 if x == y, non-zero otherwise */
const mbedtls_ct_uint_t diff = mbedtls_ct_compiler_opaque(x) ^ mbedtls_ct_compiler_opaque(y);
/* all ones if x != y, 0 otherwise */
return mbedtls_ct_bool(diff);
}
static inline unsigned char mbedtls_ct_uchar_in_range_if(unsigned char low,
unsigned char high,
unsigned char c,
unsigned char t)
{
const unsigned char co = (unsigned char) mbedtls_ct_compiler_opaque(c);
const unsigned char to = (unsigned char) mbedtls_ct_compiler_opaque(t);
/* low_mask is: 0 if low <= c, 0x...ff if low > c */
unsigned low_mask = ((unsigned) co - low) >> 8;
/* high_mask is: 0 if c <= high, 0x...ff if c > high */
unsigned high_mask = ((unsigned) high - co) >> 8;
return (unsigned char) (~(low_mask | high_mask)) & to;
}
/* ============================================================================
* Everything below here is trivial wrapper functions
*/
static inline size_t mbedtls_ct_size_if(mbedtls_ct_condition_t condition,
size_t if1,
size_t if0)
{
return (size_t) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) if1, (mbedtls_ct_uint_t) if0);
}
static inline unsigned mbedtls_ct_uint_if(mbedtls_ct_condition_t condition,
unsigned if1,
unsigned if0)
{
return (unsigned) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) if1, (mbedtls_ct_uint_t) if0);
}
static inline mbedtls_ct_condition_t mbedtls_ct_bool_if(mbedtls_ct_condition_t condition,
mbedtls_ct_condition_t if1,
mbedtls_ct_condition_t if0)
{
return (mbedtls_ct_condition_t) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) if1,
(mbedtls_ct_uint_t) if0);
}
#if defined(MBEDTLS_BIGNUM_C)
static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if(mbedtls_ct_condition_t condition,
mbedtls_mpi_uint if1,
mbedtls_mpi_uint if0)
{
return (mbedtls_mpi_uint) mbedtls_ct_if(condition,
(mbedtls_ct_uint_t) if1,
(mbedtls_ct_uint_t) if0);
}
#endif
static inline size_t mbedtls_ct_size_if_else_0(mbedtls_ct_condition_t condition, size_t if1)
{
return (size_t) (condition & if1);
}
static inline unsigned mbedtls_ct_uint_if_else_0(mbedtls_ct_condition_t condition, unsigned if1)
{
return (unsigned) (condition & if1);
}
static inline mbedtls_ct_condition_t mbedtls_ct_bool_if_else_0(mbedtls_ct_condition_t condition,
mbedtls_ct_condition_t if1)
{
return (mbedtls_ct_condition_t) (condition & if1);
}
#if defined(MBEDTLS_BIGNUM_C)
static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if_else_0(mbedtls_ct_condition_t condition,
mbedtls_mpi_uint if1)
{
return (mbedtls_mpi_uint) (condition & if1);
}
#endif /* MBEDTLS_BIGNUM_C */
static inline int mbedtls_ct_error_if(mbedtls_ct_condition_t condition, int if1, int if0)
{
/* Coverting int -> uint -> int here is safe, because we require if1 and if0 to be
* in the range -32767..0, and we require 32-bit int and uint types.
*
* This means that (0 <= -if0 < INT_MAX), so negating if0 is safe, and similarly for
* converting back to int.
*/
return -((int) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) (-if1),
(mbedtls_ct_uint_t) (-if0)));
}
static inline int mbedtls_ct_error_if_else_0(mbedtls_ct_condition_t condition, int if1)
{
return -((int) (condition & (-if1)));
}
static inline mbedtls_ct_condition_t mbedtls_ct_uint_eq(mbedtls_ct_uint_t x,
mbedtls_ct_uint_t y)
{
return ~mbedtls_ct_uint_ne(x, y);
}
static inline mbedtls_ct_condition_t mbedtls_ct_uint_gt(mbedtls_ct_uint_t x,
mbedtls_ct_uint_t y)
{
return mbedtls_ct_uint_lt(y, x);
}
static inline mbedtls_ct_condition_t mbedtls_ct_uint_ge(mbedtls_ct_uint_t x,
mbedtls_ct_uint_t y)
{
return ~mbedtls_ct_uint_lt(x, y);
}
static inline mbedtls_ct_condition_t mbedtls_ct_uint_le(mbedtls_ct_uint_t x,
mbedtls_ct_uint_t y)
{
return ~mbedtls_ct_uint_gt(x, y);
}
static inline mbedtls_ct_condition_t mbedtls_ct_bool_ne(mbedtls_ct_condition_t x,
mbedtls_ct_condition_t y)
{
return (mbedtls_ct_condition_t) (x ^ y);
}
static inline mbedtls_ct_condition_t mbedtls_ct_bool_and(mbedtls_ct_condition_t x,
mbedtls_ct_condition_t y)
{
return (mbedtls_ct_condition_t) (x & y);
}
static inline mbedtls_ct_condition_t mbedtls_ct_bool_or(mbedtls_ct_condition_t x,
mbedtls_ct_condition_t y)
{
return (mbedtls_ct_condition_t) (x | y);
}
static inline mbedtls_ct_condition_t mbedtls_ct_bool_not(mbedtls_ct_condition_t x)
{
return (mbedtls_ct_condition_t) (~x);
}
#if defined(MBEDTLS_COMPILER_IS_GCC) && (__GNUC__ > 4)
/* Restore warnings for -Wredundant-decls on gcc */
#pragma GCC diagnostic pop
#endif
#endif /* MBEDTLS_CONSTANT_TIME_IMPL_H */

View File

@@ -0,0 +1,579 @@
/**
* Constant-time functions
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef MBEDTLS_CONSTANT_TIME_INTERNAL_H
#define MBEDTLS_CONSTANT_TIME_INTERNAL_H
#include <stdint.h>
#include <stddef.h>
#include "common.h"
#if defined(MBEDTLS_BIGNUM_C)
#include "mbedtls/bignum.h"
#endif
/* The constant-time interface provides various operations that are likely
* to result in constant-time code that does not branch or use conditional
* instructions for secret data (for secret pointers, this also applies to
* the data pointed to).
*
* It has three main parts:
*
* - boolean operations
* These are all named mbedtls_ct_<type>_<operation>.
* They operate over <type> and return mbedtls_ct_condition_t.
* All arguments are considered secret.
* example: bool x = y | z => x = mbedtls_ct_bool_or(y, z)
* example: bool x = y == z => x = mbedtls_ct_uint_eq(y, z)
*
* - conditional data selection
* These are all named mbedtls_ct_<type>_if and mbedtls_ct_<type>_if_else_0
* All arguments are considered secret.
* example: size_t a = x ? b : c => a = mbedtls_ct_size_if(x, b, c)
* example: unsigned a = x ? b : 0 => a = mbedtls_ct_uint_if_else_0(x, b)
*
* - block memory operations
* Only some arguments are considered secret, as documented for each
* function.
* example: if (x) memcpy(...) => mbedtls_ct_memcpy_if(x, ...)
*
* mbedtls_ct_condition_t must be treated as opaque and only created and
* manipulated via the functions in this header. The compiler should never
* be able to prove anything about its value at compile-time.
*
* mbedtls_ct_uint_t is an unsigned integer type over which constant time
* operations may be performed via the functions in this header. It is as big
* as the larger of size_t and mbedtls_mpi_uint, i.e. it is safe to cast
* to/from "unsigned int", "size_t", and "mbedtls_mpi_uint" (and any other
* not-larger integer types).
*
* For Arm (32-bit, 64-bit and Thumb), x86 and x86-64, assembly implementations
* are used to ensure that the generated code is constant time. For other
* architectures, it uses a plain C fallback designed to yield constant-time code
* (this has been observed to be constant-time on latest gcc, clang and MSVC
* as of May 2023).
*
* For readability, the static inline definitions are separated out into
* constant_time_impl.h.
*/
#if (SIZE_MAX > 0xffffffffffffffffULL)
/* Pointer size > 64-bit */
typedef size_t mbedtls_ct_condition_t;
typedef size_t mbedtls_ct_uint_t;
typedef ptrdiff_t mbedtls_ct_int_t;
#define MBEDTLS_CT_TRUE ((mbedtls_ct_condition_t) mbedtls_ct_compiler_opaque(SIZE_MAX))
#elif (SIZE_MAX > 0xffffffff) || defined(MBEDTLS_HAVE_INT64)
/* 32-bit < pointer size <= 64-bit, or 64-bit MPI */
typedef uint64_t mbedtls_ct_condition_t;
typedef uint64_t mbedtls_ct_uint_t;
typedef int64_t mbedtls_ct_int_t;
#define MBEDTLS_CT_SIZE_64
#define MBEDTLS_CT_TRUE ((mbedtls_ct_condition_t) mbedtls_ct_compiler_opaque(UINT64_MAX))
#else
/* Pointer size <= 32-bit, and no 64-bit MPIs */
typedef uint32_t mbedtls_ct_condition_t;
typedef uint32_t mbedtls_ct_uint_t;
typedef int32_t mbedtls_ct_int_t;
#define MBEDTLS_CT_SIZE_32
#define MBEDTLS_CT_TRUE ((mbedtls_ct_condition_t) mbedtls_ct_compiler_opaque(UINT32_MAX))
#endif
#define MBEDTLS_CT_FALSE ((mbedtls_ct_condition_t) mbedtls_ct_compiler_opaque(0))
/* ============================================================================
* Boolean operations
*/
/** Convert a number into a mbedtls_ct_condition_t.
*
* \param x Number to convert.
*
* \return MBEDTLS_CT_TRUE if \p x != 0, or MBEDTLS_CT_FALSE if \p x == 0
*
*/
static inline mbedtls_ct_condition_t mbedtls_ct_bool(mbedtls_ct_uint_t x);
/** Boolean "not equal" operation.
*
* Functionally equivalent to:
*
* \p x != \p y
*
* \param x The first value to analyze.
* \param y The second value to analyze.
*
* \return MBEDTLS_CT_TRUE if \p x != \p y, otherwise MBEDTLS_CT_FALSE.
*/
static inline mbedtls_ct_condition_t mbedtls_ct_uint_ne(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y);
/** Boolean "equals" operation.
*
* Functionally equivalent to:
*
* \p x == \p y
*
* \param x The first value to analyze.
* \param y The second value to analyze.
*
* \return MBEDTLS_CT_TRUE if \p x == \p y, otherwise MBEDTLS_CT_FALSE.
*/
static inline mbedtls_ct_condition_t mbedtls_ct_uint_eq(mbedtls_ct_uint_t x,
mbedtls_ct_uint_t y);
/** Boolean "less than" operation.
*
* Functionally equivalent to:
*
* \p x < \p y
*
* \param x The first value to analyze.
* \param y The second value to analyze.
*
* \return MBEDTLS_CT_TRUE if \p x < \p y, otherwise MBEDTLS_CT_FALSE.
*/
static inline mbedtls_ct_condition_t mbedtls_ct_uint_lt(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y);
/** Boolean "greater than" operation.
*
* Functionally equivalent to:
*
* \p x > \p y
*
* \param x The first value to analyze.
* \param y The second value to analyze.
*
* \return MBEDTLS_CT_TRUE if \p x > \p y, otherwise MBEDTLS_CT_FALSE.
*/
static inline mbedtls_ct_condition_t mbedtls_ct_uint_gt(mbedtls_ct_uint_t x,
mbedtls_ct_uint_t y);
/** Boolean "greater or equal" operation.
*
* Functionally equivalent to:
*
* \p x >= \p y
*
* \param x The first value to analyze.
* \param y The second value to analyze.
*
* \return MBEDTLS_CT_TRUE if \p x >= \p y,
* otherwise MBEDTLS_CT_FALSE.
*/
static inline mbedtls_ct_condition_t mbedtls_ct_uint_ge(mbedtls_ct_uint_t x,
mbedtls_ct_uint_t y);
/** Boolean "less than or equal" operation.
*
* Functionally equivalent to:
*
* \p x <= \p y
*
* \param x The first value to analyze.
* \param y The second value to analyze.
*
* \return MBEDTLS_CT_TRUE if \p x <= \p y,
* otherwise MBEDTLS_CT_FALSE.
*/
static inline mbedtls_ct_condition_t mbedtls_ct_uint_le(mbedtls_ct_uint_t x,
mbedtls_ct_uint_t y);
/** Boolean not-equals operation.
*
* Functionally equivalent to:
*
* \p x != \p y
*
* \param x The first value to analyze.
* \param y The second value to analyze.
*
* \note This is more efficient than mbedtls_ct_uint_ne if both arguments are
* mbedtls_ct_condition_t.
*
* \return MBEDTLS_CT_TRUE if \p x != \p y,
* otherwise MBEDTLS_CT_FALSE.
*/
static inline mbedtls_ct_condition_t mbedtls_ct_bool_ne(mbedtls_ct_condition_t x,
mbedtls_ct_condition_t y);
/** Boolean "and" operation.
*
* Functionally equivalent to:
*
* \p x && \p y
*
* \param x The first value to analyze.
* \param y The second value to analyze.
*
* \return MBEDTLS_CT_TRUE if \p x && \p y,
* otherwise MBEDTLS_CT_FALSE.
*/
static inline mbedtls_ct_condition_t mbedtls_ct_bool_and(mbedtls_ct_condition_t x,
mbedtls_ct_condition_t y);
/** Boolean "or" operation.
*
* Functionally equivalent to:
*
* \p x || \p y
*
* \param x The first value to analyze.
* \param y The second value to analyze.
*
* \return MBEDTLS_CT_TRUE if \p x || \p y,
* otherwise MBEDTLS_CT_FALSE.
*/
static inline mbedtls_ct_condition_t mbedtls_ct_bool_or(mbedtls_ct_condition_t x,
mbedtls_ct_condition_t y);
/** Boolean "not" operation.
*
* Functionally equivalent to:
*
* ! \p x
*
* \param x The value to invert
*
* \return MBEDTLS_CT_FALSE if \p x, otherwise MBEDTLS_CT_TRUE.
*/
static inline mbedtls_ct_condition_t mbedtls_ct_bool_not(mbedtls_ct_condition_t x);
/* ============================================================================
* Data selection operations
*/
/** Choose between two size_t values.
*
* Functionally equivalent to:
*
* condition ? if1 : if0.
*
* \param condition Condition to test.
* \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE.
* \param if0 Value to use if \p condition == MBEDTLS_CT_FALSE.
*
* \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0.
*/
static inline size_t mbedtls_ct_size_if(mbedtls_ct_condition_t condition,
size_t if1,
size_t if0);
/** Choose between two unsigned values.
*
* Functionally equivalent to:
*
* condition ? if1 : if0.
*
* \param condition Condition to test.
* \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE.
* \param if0 Value to use if \p condition == MBEDTLS_CT_FALSE.
*
* \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0.
*/
static inline unsigned mbedtls_ct_uint_if(mbedtls_ct_condition_t condition,
unsigned if1,
unsigned if0);
/** Choose between two mbedtls_ct_condition_t values.
*
* Functionally equivalent to:
*
* condition ? if1 : if0.
*
* \param condition Condition to test.
* \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE.
* \param if0 Value to use if \p condition == MBEDTLS_CT_FALSE.
*
* \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0.
*/
static inline mbedtls_ct_condition_t mbedtls_ct_bool_if(mbedtls_ct_condition_t condition,
mbedtls_ct_condition_t if1,
mbedtls_ct_condition_t if0);
#if defined(MBEDTLS_BIGNUM_C)
/** Choose between two mbedtls_mpi_uint values.
*
* Functionally equivalent to:
*
* condition ? if1 : if0.
*
* \param condition Condition to test.
* \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE.
* \param if0 Value to use if \p condition == MBEDTLS_CT_FALSE.
*
* \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0.
*/
static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if(mbedtls_ct_condition_t condition, \
mbedtls_mpi_uint if1, \
mbedtls_mpi_uint if0);
#endif
/** Choose between an unsigned value and 0.
*
* Functionally equivalent to:
*
* condition ? if1 : 0.
*
* Functionally equivalent to mbedtls_ct_uint_if(condition, if1, 0) but
* results in smaller code size.
*
* \param condition Condition to test.
* \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE.
*
* \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0.
*/
static inline unsigned mbedtls_ct_uint_if_else_0(mbedtls_ct_condition_t condition, unsigned if1);
/** Choose between an mbedtls_ct_condition_t and 0.
*
* Functionally equivalent to:
*
* condition ? if1 : 0.
*
* Functionally equivalent to mbedtls_ct_bool_if(condition, if1, 0) but
* results in smaller code size.
*
* \param condition Condition to test.
* \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE.
*
* \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0.
*/
static inline mbedtls_ct_condition_t mbedtls_ct_bool_if_else_0(mbedtls_ct_condition_t condition,
mbedtls_ct_condition_t if1);
/** Choose between a size_t value and 0.
*
* Functionally equivalent to:
*
* condition ? if1 : 0.
*
* Functionally equivalent to mbedtls_ct_size_if(condition, if1, 0) but
* results in smaller code size.
*
* \param condition Condition to test.
* \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE.
*
* \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0.
*/
static inline size_t mbedtls_ct_size_if_else_0(mbedtls_ct_condition_t condition, size_t if1);
#if defined(MBEDTLS_BIGNUM_C)
/** Choose between an mbedtls_mpi_uint value and 0.
*
* Functionally equivalent to:
*
* condition ? if1 : 0.
*
* Functionally equivalent to mbedtls_ct_mpi_uint_if(condition, if1, 0) but
* results in smaller code size.
*
* \param condition Condition to test.
* \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE.
*
* \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0.
*/
static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if_else_0(mbedtls_ct_condition_t condition,
mbedtls_mpi_uint if1);
#endif
/** Constant-flow char selection
*
* \param low Secret. Bottom of range
* \param high Secret. Top of range
* \param c Secret. Value to compare to range
* \param t Secret. Value to return, if in range
*
* \return \p t if \p low <= \p c <= \p high, 0 otherwise.
*/
static inline unsigned char mbedtls_ct_uchar_in_range_if(unsigned char low,
unsigned char high,
unsigned char c,
unsigned char t);
/** Choose between two error values. The values must be in the range [-32767..0].
*
* Functionally equivalent to:
*
* condition ? if1 : if0.
*
* \param condition Condition to test.
* \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE.
* \param if0 Value to use if \p condition == MBEDTLS_CT_FALSE.
*
* \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0.
*/
static inline int mbedtls_ct_error_if(mbedtls_ct_condition_t condition, int if1, int if0);
/** Choose between an error value and 0. The error value must be in the range [-32767..0].
*
* Functionally equivalent to:
*
* condition ? if1 : 0.
*
* Functionally equivalent to mbedtls_ct_error_if(condition, if1, 0) but
* results in smaller code size.
*
* \param condition Condition to test.
* \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE.
*
* \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0.
*/
static inline int mbedtls_ct_error_if_else_0(mbedtls_ct_condition_t condition, int if1);
/* ============================================================================
* Block memory operations
*/
#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)
/** Conditionally set a block of memory to zero.
*
* Regardless of the condition, every byte will be read once and written to
* once.
*
* \param condition Secret. Condition to test.
* \param buf Secret. Pointer to the start of the buffer.
* \param len Number of bytes to set to zero.
*
* \warning Unlike mbedtls_platform_zeroize, this does not have the same guarantees
* about not being optimised away if the memory is never read again.
*/
void mbedtls_ct_zeroize_if(mbedtls_ct_condition_t condition, void *buf, size_t len);
/** Shift some data towards the left inside a buffer.
*
* Functionally equivalent to:
*
* memmove(start, start + offset, total - offset);
* memset(start + (total - offset), 0, offset);
*
* Timing independence comes at the expense of performance.
*
* \param start Secret. Pointer to the start of the buffer.
* \param total Total size of the buffer.
* \param offset Secret. Offset from which to copy \p total - \p offset bytes.
*/
void mbedtls_ct_memmove_left(void *start,
size_t total,
size_t offset);
#endif /* defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) */
/** Conditional memcpy.
*
* Functionally equivalent to:
*
* if (condition) {
* memcpy(dest, src1, len);
* } else {
* if (src2 != NULL)
* memcpy(dest, src2, len);
* }
*
* It will always read len bytes from src1.
* If src2 != NULL, it will always read len bytes from src2.
* If src2 == NULL, it will instead read len bytes from dest (as if src2 == dest).
*
* \param condition The condition
* \param dest Secret. Destination pointer.
* \param src1 Secret. Pointer to copy from (if \p condition == MBEDTLS_CT_TRUE).
* This may be equal to \p dest, but may not overlap in other ways.
* \param src2 Secret (contents only - may branch to determine if this parameter is NULL).
* Pointer to copy from (if \p condition == MBEDTLS_CT_FALSE and \p src2 is not NULL). May be NULL.
* This may be equal to \p dest, but may not overlap it in other ways. It may overlap with \p src1.
* \param len Number of bytes to copy.
*/
void mbedtls_ct_memcpy_if(mbedtls_ct_condition_t condition,
unsigned char *dest,
const unsigned char *src1,
const unsigned char *src2,
size_t len
);
/** Copy data from a secret position.
*
* Functionally equivalent to:
*
* memcpy(dst, src + offset, len)
*
* This function copies \p len bytes from \p src + \p offset to
* \p dst, with a code flow and memory access pattern that does not depend on
* \p offset, but only on \p offset_min, \p offset_max and \p len.
*
* \note This function reads from \p dest, but the value that
* is read does not influence the result and this
* function's behavior is well-defined regardless of the
* contents of the buffers. This may result in false
* positives from static or dynamic analyzers, especially
* if \p dest is not initialized.
*
* \param dest Secret. The destination buffer. This must point to a writable
* buffer of at least \p len bytes.
* \param src Secret. The base of the source buffer. This must point to a
* readable buffer of at least \p offset_max + \p len
* bytes. Shouldn't overlap with \p dest
* \param offset Secret. The offset in the source buffer from which to copy.
* This must be no less than \p offset_min and no greater
* than \p offset_max.
* \param offset_min The minimal value of \p offset.
* \param offset_max The maximal value of \p offset.
* \param len The number of bytes to copy.
*/
void mbedtls_ct_memcpy_offset(unsigned char *dest,
const unsigned char *src,
size_t offset,
size_t offset_min,
size_t offset_max,
size_t len);
/* Documented in include/mbedtls/constant_time.h. a and b are secret.
int mbedtls_ct_memcmp(const void *a,
const void *b,
size_t n);
*/
#if defined(MBEDTLS_NIST_KW_C)
/** Constant-time buffer comparison without branches.
*
* Similar to mbedtls_ct_memcmp, except that the result only depends on part of
* the input data - differences in the head or tail are ignored. Functionally equivalent to:
*
* memcmp(a + skip_head, b + skip_head, size - skip_head - skip_tail)
*
* Time taken depends on \p n, but not on \p skip_head or \p skip_tail .
*
* Behaviour is undefined if ( \p skip_head + \p skip_tail) > \p n.
*
* \param a Secret. Pointer to the first buffer, containing at least \p n bytes. May not be NULL.
* \param b Secret. Pointer to the second buffer, containing at least \p n bytes. May not be NULL.
* \param n The number of bytes to examine (total size of the buffers).
* \param skip_head Secret. The number of bytes to treat as non-significant at the start of the buffer.
* These bytes will still be read.
* \param skip_tail Secret. The number of bytes to treat as non-significant at the end of the buffer.
* These bytes will still be read.
*
* \return Zero if the contents of the two buffers are the same, otherwise non-zero.
*/
int mbedtls_ct_memcmp_partial(const void *a,
const void *b,
size_t n,
size_t skip_head,
size_t skip_tail);
#endif
/* Include the implementation of static inline functions above. */
#include "constant_time_impl.h"
#endif /* MBEDTLS_CONSTANT_TIME_INTERNAL_H */

35
thirdparty/mbedtls/library/ctr.h vendored Normal file
View File

@@ -0,0 +1,35 @@
/**
* \file ctr.h
*
* \brief This file contains common functionality for counter algorithms.
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef MBEDTLS_CTR_H
#define MBEDTLS_CTR_H
#include "common.h"
/**
* \brief Increment a big-endian 16-byte value.
* This is quite performance-sensitive for AES-CTR and CTR-DRBG.
*
* \param n A 16-byte value to be incremented.
*/
static inline void mbedtls_ctr_increment_counter(uint8_t n[16])
{
// The 32-bit version seems to perform about the same as a 64-bit version
// on 64-bit architectures, so no need to define a 64-bit version.
for (int i = 3;; i--) {
uint32_t x = MBEDTLS_GET_UINT32_BE(n, i << 2);
x += 1;
MBEDTLS_PUT_UINT32_BE(x, n, i << 2);
if (x != 0 || i == 0) {
break;
}
}
}
#endif /* MBEDTLS_CTR_H */

1016
thirdparty/mbedtls/library/ctr_drbg.c vendored Normal file

File diff suppressed because it is too large Load Diff

465
thirdparty/mbedtls/library/debug.c vendored Normal file
View File

@@ -0,0 +1,465 @@
/*
* Debugging routines
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#if defined(MBEDTLS_DEBUG_C)
#include "mbedtls/platform.h"
#include "debug_internal.h"
#include "mbedtls/error.h"
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
/* DEBUG_BUF_SIZE must be at least 2 */
#define DEBUG_BUF_SIZE 512
static int debug_threshold = 0;
void mbedtls_debug_set_threshold(int threshold)
{
debug_threshold = threshold;
}
/*
* All calls to f_dbg must be made via this function
*/
static inline void debug_send_line(const mbedtls_ssl_context *ssl, int level,
const char *file, int line,
const char *str)
{
/*
* If in a threaded environment, we need a thread identifier.
* Since there is no portable way to get one, use the address of the ssl
* context instead, as it shouldn't be shared between threads.
*/
#if defined(MBEDTLS_THREADING_C)
char idstr[20 + DEBUG_BUF_SIZE]; /* 0x + 16 nibbles + ': ' */
mbedtls_snprintf(idstr, sizeof(idstr), "%p: %s", (void *) ssl, str);
ssl->conf->f_dbg(ssl->conf->p_dbg, level, file, line, idstr);
#else
ssl->conf->f_dbg(ssl->conf->p_dbg, level, file, line, str);
#endif
}
MBEDTLS_PRINTF_ATTRIBUTE(5, 6)
void mbedtls_debug_print_msg(const mbedtls_ssl_context *ssl, int level,
const char *file, int line,
const char *format, ...)
{
va_list argp;
char str[DEBUG_BUF_SIZE];
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
MBEDTLS_STATIC_ASSERT(DEBUG_BUF_SIZE >= 2, "DEBUG_BUF_SIZE too small");
if (NULL == ssl ||
NULL == ssl->conf ||
NULL == ssl->conf->f_dbg ||
level > debug_threshold) {
return;
}
va_start(argp, format);
ret = mbedtls_vsnprintf(str, DEBUG_BUF_SIZE, format, argp);
va_end(argp);
if (ret < 0) {
ret = 0;
} else {
if (ret >= DEBUG_BUF_SIZE - 1) {
ret = DEBUG_BUF_SIZE - 2;
}
}
str[ret] = '\n';
str[ret + 1] = '\0';
debug_send_line(ssl, level, file, line, str);
}
void mbedtls_debug_print_ret(const mbedtls_ssl_context *ssl, int level,
const char *file, int line,
const char *text, int ret)
{
char str[DEBUG_BUF_SIZE];
if (NULL == ssl ||
NULL == ssl->conf ||
NULL == ssl->conf->f_dbg ||
level > debug_threshold) {
return;
}
/*
* With non-blocking I/O and examples that just retry immediately,
* the logs would be quickly flooded with WANT_READ, so ignore that.
* Don't ignore WANT_WRITE however, since it is usually rare.
*/
if (ret == MBEDTLS_ERR_SSL_WANT_READ) {
return;
}
mbedtls_snprintf(str, sizeof(str), "%s() returned %d (-0x%04x)\n",
text, ret, (unsigned int) -ret);
debug_send_line(ssl, level, file, line, str);
}
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)
{
char str[DEBUG_BUF_SIZE];
char txt[17];
size_t i, idx = 0;
if (NULL == ssl ||
NULL == ssl->conf ||
NULL == ssl->conf->f_dbg ||
level > debug_threshold) {
return;
}
mbedtls_snprintf(str + idx, sizeof(str) - idx, "dumping '%s' (%u bytes)\n",
text, (unsigned int) len);
debug_send_line(ssl, level, file, line, str);
memset(txt, 0, sizeof(txt));
for (i = 0; i < len; i++) {
if (i >= 4096) {
break;
}
if (i % 16 == 0) {
if (i > 0) {
mbedtls_snprintf(str + idx, sizeof(str) - idx, " %s\n", txt);
debug_send_line(ssl, level, file, line, str);
idx = 0;
memset(txt, 0, sizeof(txt));
}
idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, "%04x: ",
(unsigned int) i);
}
idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, " %02x",
(unsigned int) buf[i]);
txt[i % 16] = (buf[i] > 31 && buf[i] < 127) ? buf[i] : '.';
}
if (len > 0) {
for (/* i = i */; i % 16 != 0; i++) {
idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, " ");
}
mbedtls_snprintf(str + idx, sizeof(str) - idx, " %s\n", txt);
debug_send_line(ssl, level, file, line, str);
}
}
#if defined(MBEDTLS_ECP_LIGHT)
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)
{
char str[DEBUG_BUF_SIZE];
if (NULL == ssl ||
NULL == ssl->conf ||
NULL == ssl->conf->f_dbg ||
level > debug_threshold) {
return;
}
mbedtls_snprintf(str, sizeof(str), "%s(X)", text);
mbedtls_debug_print_mpi(ssl, level, file, line, str, &X->X);
mbedtls_snprintf(str, sizeof(str), "%s(Y)", text);
mbedtls_debug_print_mpi(ssl, level, file, line, str, &X->Y);
}
#endif /* MBEDTLS_ECP_LIGHT */
#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
static void mbedtls_debug_print_ec_coord(const mbedtls_ssl_context *ssl, int level,
const char *file, int line, const char *text,
const unsigned char *buf, size_t len)
{
char str[DEBUG_BUF_SIZE];
size_t i, idx = 0;
mbedtls_snprintf(str + idx, sizeof(str) - idx, "value of '%s' (%u bits) is:\n",
text, (unsigned int) len * 8);
debug_send_line(ssl, level, file, line, str);
for (i = 0; i < len; i++) {
if (i >= 4096) {
break;
}
if (i % 16 == 0) {
if (i > 0) {
mbedtls_snprintf(str + idx, sizeof(str) - idx, "\n");
debug_send_line(ssl, level, file, line, str);
idx = 0;
}
}
idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, " %02x",
(unsigned int) buf[i]);
}
if (len > 0) {
for (/* i = i */; i % 16 != 0; i++) {
idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, " ");
}
mbedtls_snprintf(str + idx, sizeof(str) - idx, "\n");
debug_send_line(ssl, level, file, line, str);
}
}
void mbedtls_debug_print_psa_ec(const mbedtls_ssl_context *ssl, int level,
const char *file, int line,
const char *text, const mbedtls_pk_context *pk)
{
char str[DEBUG_BUF_SIZE];
const uint8_t *coord_start;
size_t coord_len;
if (NULL == ssl ||
NULL == ssl->conf ||
NULL == ssl->conf->f_dbg ||
level > debug_threshold) {
return;
}
/* For the description of pk->pk_raw content please refer to the description
* psa_export_public_key() function. */
coord_len = (pk->pub_raw_len - 1)/2;
/* X coordinate */
coord_start = pk->pub_raw + 1;
mbedtls_snprintf(str, sizeof(str), "%s(X)", text);
mbedtls_debug_print_ec_coord(ssl, level, file, line, str, coord_start, coord_len);
/* Y coordinate */
coord_start = coord_start + coord_len;
mbedtls_snprintf(str, sizeof(str), "%s(Y)", text);
mbedtls_debug_print_ec_coord(ssl, level, file, line, str, coord_start, coord_len);
}
#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
#if defined(MBEDTLS_BIGNUM_C)
void mbedtls_debug_print_mpi(const mbedtls_ssl_context *ssl, int level,
const char *file, int line,
const char *text, const mbedtls_mpi *X)
{
char str[DEBUG_BUF_SIZE];
size_t bitlen;
size_t idx = 0;
if (NULL == ssl ||
NULL == ssl->conf ||
NULL == ssl->conf->f_dbg ||
NULL == X ||
level > debug_threshold) {
return;
}
bitlen = mbedtls_mpi_bitlen(X);
mbedtls_snprintf(str, sizeof(str), "value of '%s' (%u bits) is:\n",
text, (unsigned) bitlen);
debug_send_line(ssl, level, file, line, str);
if (bitlen == 0) {
str[0] = ' '; str[1] = '0'; str[2] = '0';
idx = 3;
} else {
int n;
for (n = (int) ((bitlen - 1) / 8); n >= 0; n--) {
size_t limb_offset = n / sizeof(mbedtls_mpi_uint);
size_t offset_in_limb = n % sizeof(mbedtls_mpi_uint);
unsigned char octet =
(X->p[limb_offset] >> (offset_in_limb * 8)) & 0xff;
mbedtls_snprintf(str + idx, sizeof(str) - idx, " %02x", octet);
idx += 3;
/* Wrap lines after 16 octets that each take 3 columns */
if (idx >= 3 * 16) {
mbedtls_snprintf(str + idx, sizeof(str) - idx, "\n");
debug_send_line(ssl, level, file, line, str);
idx = 0;
}
}
}
if (idx != 0) {
mbedtls_snprintf(str + idx, sizeof(str) - idx, "\n");
debug_send_line(ssl, level, file, line, str);
}
}
#endif /* MBEDTLS_BIGNUM_C */
#if defined(MBEDTLS_X509_CRT_PARSE_C) && !defined(MBEDTLS_X509_REMOVE_INFO)
static void debug_print_pk(const mbedtls_ssl_context *ssl, int level,
const char *file, int line,
const char *text, const mbedtls_pk_context *pk)
{
size_t i;
mbedtls_pk_debug_item items[MBEDTLS_PK_DEBUG_MAX_ITEMS];
char name[16];
memset(items, 0, sizeof(items));
if (mbedtls_pk_debug(pk, items) != 0) {
debug_send_line(ssl, level, file, line,
"invalid PK context\n");
return;
}
for (i = 0; i < MBEDTLS_PK_DEBUG_MAX_ITEMS; i++) {
if (items[i].type == MBEDTLS_PK_DEBUG_NONE) {
return;
}
mbedtls_snprintf(name, sizeof(name), "%s%s", text, items[i].name);
name[sizeof(name) - 1] = '\0';
#if defined(MBEDTLS_RSA_C)
if (items[i].type == MBEDTLS_PK_DEBUG_MPI) {
mbedtls_debug_print_mpi(ssl, level, file, line, name, items[i].value);
} else
#endif /* MBEDTLS_RSA_C */
#if defined(MBEDTLS_ECP_LIGHT)
if (items[i].type == MBEDTLS_PK_DEBUG_ECP) {
mbedtls_debug_print_ecp(ssl, level, file, line, name, items[i].value);
} else
#endif /* MBEDTLS_ECP_LIGHT */
#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
if (items[i].type == MBEDTLS_PK_DEBUG_PSA_EC) {
mbedtls_debug_print_psa_ec(ssl, level, file, line, name, items[i].value);
} else
#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
{ debug_send_line(ssl, level, file, line,
"should not happen\n"); }
}
}
static void debug_print_line_by_line(const mbedtls_ssl_context *ssl, int level,
const char *file, int line, const char *text)
{
char str[DEBUG_BUF_SIZE];
const char *start, *cur;
start = text;
for (cur = text; *cur != '\0'; cur++) {
if (*cur == '\n') {
size_t len = (size_t) (cur - start) + 1;
if (len > DEBUG_BUF_SIZE - 1) {
len = DEBUG_BUF_SIZE - 1;
}
memcpy(str, start, len);
str[len] = '\0';
debug_send_line(ssl, level, file, line, str);
start = cur + 1;
}
}
}
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)
{
char str[DEBUG_BUF_SIZE];
int i = 0;
if (NULL == ssl ||
NULL == ssl->conf ||
NULL == ssl->conf->f_dbg ||
NULL == crt ||
level > debug_threshold) {
return;
}
while (crt != NULL) {
char buf[1024];
mbedtls_snprintf(str, sizeof(str), "%s #%d:\n", text, ++i);
debug_send_line(ssl, level, file, line, str);
mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt);
debug_print_line_by_line(ssl, level, file, line, buf);
debug_print_pk(ssl, level, file, line, "crt->", &crt->pk);
crt = crt->next;
}
}
#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_X509_REMOVE_INFO */
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED) && \
defined(MBEDTLS_ECDH_C)
static void mbedtls_debug_printf_ecdh_internal(const mbedtls_ssl_context *ssl,
int level, const char *file,
int line,
const mbedtls_ecdh_context *ecdh,
mbedtls_debug_ecdh_attr attr)
{
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
const mbedtls_ecdh_context *ctx = ecdh;
#else
const mbedtls_ecdh_context_mbed *ctx = &ecdh->ctx.mbed_ecdh;
#endif
switch (attr) {
case MBEDTLS_DEBUG_ECDH_Q:
mbedtls_debug_print_ecp(ssl, level, file, line, "ECDH: Q",
&ctx->Q);
break;
case MBEDTLS_DEBUG_ECDH_QP:
mbedtls_debug_print_ecp(ssl, level, file, line, "ECDH: Qp",
&ctx->Qp);
break;
case MBEDTLS_DEBUG_ECDH_Z:
mbedtls_debug_print_mpi(ssl, level, file, line, "ECDH: z",
&ctx->z);
break;
default:
break;
}
}
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)
{
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
mbedtls_debug_printf_ecdh_internal(ssl, level, file, line, ecdh, attr);
#else
switch (ecdh->var) {
default:
mbedtls_debug_printf_ecdh_internal(ssl, level, file, line, ecdh,
attr);
}
#endif
}
#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED &&
MBEDTLS_ECDH_C */
#endif /* MBEDTLS_DEBUG_C */

View File

@@ -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 */

1042
thirdparty/mbedtls/library/des.c vendored Normal file

File diff suppressed because it is too large Load Diff

712
thirdparty/mbedtls/library/dhm.c vendored Normal file
View File

@@ -0,0 +1,712 @@
/*
* Diffie-Hellman-Merkle key exchange
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
/*
* The following sources were referenced in the design of this implementation
* of the Diffie-Hellman-Merkle algorithm:
*
* [1] Handbook of Applied Cryptography - 1997, Chapter 12
* Menezes, van Oorschot and Vanstone
*
*/
#include "common.h"
#if defined(MBEDTLS_DHM_C)
#include "mbedtls/dhm.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#include <string.h>
#if defined(MBEDTLS_PEM_PARSE_C)
#include "mbedtls/pem.h"
#endif
#if defined(MBEDTLS_ASN1_PARSE_C)
#include "mbedtls/asn1.h"
#endif
#include "mbedtls/platform.h"
#if !defined(MBEDTLS_DHM_ALT)
/*
* helper to validate the mbedtls_mpi size and import it
*/
static int dhm_read_bignum(mbedtls_mpi *X,
unsigned char **p,
const unsigned char *end)
{
int ret, n;
if (end - *p < 2) {
return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
}
n = MBEDTLS_GET_UINT16_BE(*p, 0);
(*p) += 2;
if ((size_t) (end - *p) < (size_t) n) {
return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
}
if ((ret = mbedtls_mpi_read_binary(X, *p, n)) != 0) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED, ret);
}
(*p) += n;
return 0;
}
/*
* Verify sanity of parameter with regards to P
*
* Parameter should be: 2 <= public_param <= P - 2
*
* This means that we need to return an error if
* public_param < 2 or public_param > P-2
*
* For more information on the attack, see:
* http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf
* http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643
*/
static int dhm_check_range(const mbedtls_mpi *param, const mbedtls_mpi *P)
{
mbedtls_mpi U;
int ret = 0;
mbedtls_mpi_init(&U);
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&U, P, 2));
if (mbedtls_mpi_cmp_int(param, 2) < 0 ||
mbedtls_mpi_cmp_mpi(param, &U) > 0) {
ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
}
cleanup:
mbedtls_mpi_free(&U);
return ret;
}
void mbedtls_dhm_init(mbedtls_dhm_context *ctx)
{
memset(ctx, 0, sizeof(mbedtls_dhm_context));
}
size_t mbedtls_dhm_get_bitlen(const mbedtls_dhm_context *ctx)
{
return mbedtls_mpi_bitlen(&ctx->P);
}
size_t mbedtls_dhm_get_len(const mbedtls_dhm_context *ctx)
{
return mbedtls_mpi_size(&ctx->P);
}
int mbedtls_dhm_get_value(const mbedtls_dhm_context *ctx,
mbedtls_dhm_parameter param,
mbedtls_mpi *dest)
{
const mbedtls_mpi *src = NULL;
switch (param) {
case MBEDTLS_DHM_PARAM_P:
src = &ctx->P;
break;
case MBEDTLS_DHM_PARAM_G:
src = &ctx->G;
break;
case MBEDTLS_DHM_PARAM_X:
src = &ctx->X;
break;
case MBEDTLS_DHM_PARAM_GX:
src = &ctx->GX;
break;
case MBEDTLS_DHM_PARAM_GY:
src = &ctx->GY;
break;
case MBEDTLS_DHM_PARAM_K:
src = &ctx->K;
break;
default:
return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
}
return mbedtls_mpi_copy(dest, src);
}
/*
* Parse the ServerKeyExchange parameters
*/
int mbedtls_dhm_read_params(mbedtls_dhm_context *ctx,
unsigned char **p,
const unsigned char *end)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if ((ret = dhm_read_bignum(&ctx->P, p, end)) != 0 ||
(ret = dhm_read_bignum(&ctx->G, p, end)) != 0 ||
(ret = dhm_read_bignum(&ctx->GY, p, end)) != 0) {
return ret;
}
if ((ret = dhm_check_range(&ctx->GY, &ctx->P)) != 0) {
return ret;
}
return 0;
}
/*
* Pick a random R in the range [2, M-2] for blinding or key generation.
*/
static int dhm_random_below(mbedtls_mpi *R, const mbedtls_mpi *M,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
{
int ret;
MBEDTLS_MPI_CHK(mbedtls_mpi_random(R, 3, M, f_rng, p_rng));
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(R, R, 1));
cleanup:
return ret;
}
static int dhm_make_common(mbedtls_dhm_context *ctx, int x_size,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng)
{
int ret = 0;
if (mbedtls_mpi_cmp_int(&ctx->P, 0) == 0) {
return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
}
if (x_size < 0) {
return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
}
if ((unsigned) x_size < mbedtls_mpi_size(&ctx->P)) {
MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&ctx->X, x_size, f_rng, p_rng));
} else {
/* Generate X as large as possible ( <= P - 2 ) */
ret = dhm_random_below(&ctx->X, &ctx->P, f_rng, p_rng);
if (ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
return MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED;
}
if (ret != 0) {
return ret;
}
}
/*
* Calculate GX = G^X mod P
*/
MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->GX, &ctx->G, &ctx->X,
&ctx->P, &ctx->RP));
if ((ret = dhm_check_range(&ctx->GX, &ctx->P)) != 0) {
return ret;
}
cleanup:
return ret;
}
/*
* Setup and write the ServerKeyExchange parameters
*/
int mbedtls_dhm_make_params(mbedtls_dhm_context *ctx, int x_size,
unsigned char *output, size_t *olen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng)
{
int ret;
size_t n1, n2, n3;
unsigned char *p;
ret = dhm_make_common(ctx, x_size, f_rng, p_rng);
if (ret != 0) {
goto cleanup;
}
/*
* Export P, G, GX. RFC 5246 §4.4 states that "leading zero octets are
* not required". We omit leading zeros for compactness.
*/
#define DHM_MPI_EXPORT(X, n) \
do { \
MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary((X), \
p + 2, \
(n))); \
*p++ = MBEDTLS_BYTE_1(n); \
*p++ = MBEDTLS_BYTE_0(n); \
p += (n); \
} while (0)
n1 = mbedtls_mpi_size(&ctx->P);
n2 = mbedtls_mpi_size(&ctx->G);
n3 = mbedtls_mpi_size(&ctx->GX);
p = output;
DHM_MPI_EXPORT(&ctx->P, n1);
DHM_MPI_EXPORT(&ctx->G, n2);
DHM_MPI_EXPORT(&ctx->GX, n3);
*olen = (size_t) (p - output);
cleanup:
if (ret != 0 && ret > -128) {
ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED, ret);
}
return ret;
}
/*
* Set prime modulus and generator
*/
int mbedtls_dhm_set_group(mbedtls_dhm_context *ctx,
const mbedtls_mpi *P,
const mbedtls_mpi *G)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if ((ret = mbedtls_mpi_copy(&ctx->P, P)) != 0 ||
(ret = mbedtls_mpi_copy(&ctx->G, G)) != 0) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_SET_GROUP_FAILED, ret);
}
return 0;
}
/*
* Import the peer's public value G^Y
*/
int mbedtls_dhm_read_public(mbedtls_dhm_context *ctx,
const unsigned char *input, size_t ilen)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if (ilen < 1 || ilen > mbedtls_dhm_get_len(ctx)) {
return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
}
if ((ret = mbedtls_mpi_read_binary(&ctx->GY, input, ilen)) != 0) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED, ret);
}
return 0;
}
/*
* Create own private value X and export G^X
*/
int mbedtls_dhm_make_public(mbedtls_dhm_context *ctx, int x_size,
unsigned char *output, size_t olen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng)
{
int ret;
if (olen < 1 || olen > mbedtls_dhm_get_len(ctx)) {
return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
}
ret = dhm_make_common(ctx, x_size, f_rng, p_rng);
if (ret == MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED) {
return MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED;
}
if (ret != 0) {
goto cleanup;
}
MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->GX, output, olen));
cleanup:
if (ret != 0 && ret > -128) {
ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED, ret);
}
return ret;
}
/*
* Use the blinding method and optimisation suggested in section 10 of:
* KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
* DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
* Berlin Heidelberg, 1996. p. 104-113.
*/
static int dhm_update_blinding(mbedtls_dhm_context *ctx,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
{
int ret;
mbedtls_mpi R;
mbedtls_mpi_init(&R);
/*
* Don't use any blinding the first time a particular X is used,
* but remember it to use blinding next time.
*/
if (mbedtls_mpi_cmp_mpi(&ctx->X, &ctx->pX) != 0) {
MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&ctx->pX, &ctx->X));
MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ctx->Vi, 1));
MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ctx->Vf, 1));
return 0;
}
/*
* Ok, we need blinding. Can we re-use existing values?
* If yes, just update them by squaring them.
*/
if (mbedtls_mpi_cmp_int(&ctx->Vi, 1) != 0) {
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vi, &ctx->Vi, &ctx->Vi));
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vi, &ctx->Vi, &ctx->P));
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vf, &ctx->Vf));
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->P));
return 0;
}
/*
* We need to generate blinding values from scratch
*/
/* Vi = random( 2, P-2 ) */
MBEDTLS_MPI_CHK(dhm_random_below(&ctx->Vi, &ctx->P, f_rng, p_rng));
/* Vf = Vi^-X mod P
* First compute Vi^-1 = R * (R Vi)^-1, (avoiding leaks from inv_mod),
* then elevate to the Xth power. */
MBEDTLS_MPI_CHK(dhm_random_below(&R, &ctx->P, f_rng, p_rng));
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vi, &R));
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->P));
MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&ctx->Vf, &ctx->Vf, &ctx->P));
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vf, &R));
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->P));
MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP));
cleanup:
mbedtls_mpi_free(&R);
return ret;
}
/*
* Derive and export the shared secret (G^Y)^X mod P
*/
int mbedtls_dhm_calc_secret(mbedtls_dhm_context *ctx,
unsigned char *output, size_t output_size, size_t *olen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi GYb;
if (f_rng == NULL) {
return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
}
if (output_size < mbedtls_dhm_get_len(ctx)) {
return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
}
if ((ret = dhm_check_range(&ctx->GY, &ctx->P)) != 0) {
return ret;
}
mbedtls_mpi_init(&GYb);
/* Blind peer's value */
MBEDTLS_MPI_CHK(dhm_update_blinding(ctx, f_rng, p_rng));
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&GYb, &ctx->GY, &ctx->Vi));
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&GYb, &GYb, &ctx->P));
/* Do modular exponentiation */
MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->K, &GYb, &ctx->X,
&ctx->P, &ctx->RP));
/* Unblind secret value */
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->K, &ctx->K, &ctx->Vf));
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->K, &ctx->K, &ctx->P));
/* Output the secret without any leading zero byte. This is mandatory
* for TLS per RFC 5246 §8.1.2. */
*olen = mbedtls_mpi_size(&ctx->K);
MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->K, output, *olen));
cleanup:
mbedtls_mpi_free(&GYb);
if (ret != 0) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED, ret);
}
return 0;
}
/*
* Free the components of a DHM key
*/
void mbedtls_dhm_free(mbedtls_dhm_context *ctx)
{
if (ctx == NULL) {
return;
}
mbedtls_mpi_free(&ctx->pX);
mbedtls_mpi_free(&ctx->Vf);
mbedtls_mpi_free(&ctx->Vi);
mbedtls_mpi_free(&ctx->RP);
mbedtls_mpi_free(&ctx->K);
mbedtls_mpi_free(&ctx->GY);
mbedtls_mpi_free(&ctx->GX);
mbedtls_mpi_free(&ctx->X);
mbedtls_mpi_free(&ctx->G);
mbedtls_mpi_free(&ctx->P);
mbedtls_platform_zeroize(ctx, sizeof(mbedtls_dhm_context));
}
#if defined(MBEDTLS_ASN1_PARSE_C)
/*
* Parse DHM parameters
*/
int mbedtls_dhm_parse_dhm(mbedtls_dhm_context *dhm, const unsigned char *dhmin,
size_t dhminlen)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len;
unsigned char *p, *end;
#if defined(MBEDTLS_PEM_PARSE_C)
mbedtls_pem_context pem;
#endif /* MBEDTLS_PEM_PARSE_C */
#if defined(MBEDTLS_PEM_PARSE_C)
mbedtls_pem_init(&pem);
/* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
if (dhminlen == 0 || dhmin[dhminlen - 1] != '\0') {
ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
} else {
ret = mbedtls_pem_read_buffer(&pem,
"-----BEGIN DH PARAMETERS-----",
"-----END DH PARAMETERS-----",
dhmin, NULL, 0, &dhminlen);
}
if (ret == 0) {
/*
* Was PEM encoded
*/
dhminlen = pem.buflen;
} else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
goto exit;
}
p = (ret == 0) ? pem.buf : (unsigned char *) dhmin;
#else
p = (unsigned char *) dhmin;
#endif /* MBEDTLS_PEM_PARSE_C */
end = p + dhminlen;
/*
* DHParams ::= SEQUENCE {
* prime INTEGER, -- P
* generator INTEGER, -- g
* privateValueLength INTEGER OPTIONAL
* }
*/
if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);
goto exit;
}
end = p + len;
if ((ret = mbedtls_asn1_get_mpi(&p, end, &dhm->P)) != 0 ||
(ret = mbedtls_asn1_get_mpi(&p, end, &dhm->G)) != 0) {
ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);
goto exit;
}
if (p != end) {
/* This might be the optional privateValueLength.
* If so, we can cleanly discard it */
mbedtls_mpi rec;
mbedtls_mpi_init(&rec);
ret = mbedtls_asn1_get_mpi(&p, end, &rec);
mbedtls_mpi_free(&rec);
if (ret != 0) {
ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);
goto exit;
}
if (p != end) {
ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT,
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
goto exit;
}
}
ret = 0;
exit:
#if defined(MBEDTLS_PEM_PARSE_C)
mbedtls_pem_free(&pem);
#endif
if (ret != 0) {
mbedtls_dhm_free(dhm);
}
return ret;
}
#if defined(MBEDTLS_FS_IO)
/*
* Load all data from a file into a given buffer.
*
* The file is expected to contain either PEM or DER encoded data.
* A terminating null byte is always appended. It is included in the announced
* length only if the data looks like it is PEM encoded.
*/
static int load_file(const char *path, unsigned char **buf, size_t *n)
{
FILE *f;
long size;
if ((f = fopen(path, "rb")) == NULL) {
return MBEDTLS_ERR_DHM_FILE_IO_ERROR;
}
/* The data loaded here is public, so don't bother disabling buffering. */
fseek(f, 0, SEEK_END);
if ((size = ftell(f)) == -1) {
fclose(f);
return MBEDTLS_ERR_DHM_FILE_IO_ERROR;
}
fseek(f, 0, SEEK_SET);
*n = (size_t) size;
if (*n + 1 == 0 ||
(*buf = mbedtls_calloc(1, *n + 1)) == NULL) {
fclose(f);
return MBEDTLS_ERR_DHM_ALLOC_FAILED;
}
if (fread(*buf, 1, *n, f) != *n) {
fclose(f);
mbedtls_zeroize_and_free(*buf, *n + 1);
return MBEDTLS_ERR_DHM_FILE_IO_ERROR;
}
fclose(f);
(*buf)[*n] = '\0';
if (strstr((const char *) *buf, "-----BEGIN ") != NULL) {
++*n;
}
return 0;
}
/*
* Load and parse DHM parameters
*/
int mbedtls_dhm_parse_dhmfile(mbedtls_dhm_context *dhm, const char *path)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n;
unsigned char *buf;
if ((ret = load_file(path, &buf, &n)) != 0) {
return ret;
}
ret = mbedtls_dhm_parse_dhm(dhm, buf, n);
mbedtls_zeroize_and_free(buf, n);
return ret;
}
#endif /* MBEDTLS_FS_IO */
#endif /* MBEDTLS_ASN1_PARSE_C */
#endif /* MBEDTLS_DHM_ALT */
#if defined(MBEDTLS_SELF_TEST)
#if defined(MBEDTLS_PEM_PARSE_C)
static const char mbedtls_test_dhm_params[] =
"-----BEGIN DH PARAMETERS-----\r\n"
"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
"-----END DH PARAMETERS-----\r\n";
#else /* MBEDTLS_PEM_PARSE_C */
static const char mbedtls_test_dhm_params[] = {
0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44,
0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d,
0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3,
0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1,
0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18,
0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a,
0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1,
0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6,
0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64,
0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8,
0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f,
0x49, 0x75, 0xb3, 0x02, 0x01, 0x02
};
#endif /* MBEDTLS_PEM_PARSE_C */
static const size_t mbedtls_test_dhm_params_len = sizeof(mbedtls_test_dhm_params);
/*
* Checkup routine
*/
int mbedtls_dhm_self_test(int verbose)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_dhm_context dhm;
mbedtls_dhm_init(&dhm);
if (verbose != 0) {
mbedtls_printf(" DHM parameter load: ");
}
if ((ret = mbedtls_dhm_parse_dhm(&dhm,
(const unsigned char *) mbedtls_test_dhm_params,
mbedtls_test_dhm_params_len)) != 0) {
if (verbose != 0) {
mbedtls_printf("failed\n");
}
ret = 1;
goto exit;
}
if (verbose != 0) {
mbedtls_printf("passed\n\n");
}
exit:
mbedtls_dhm_free(&dhm);
return ret;
}
#endif /* MBEDTLS_SELF_TEST */
#endif /* MBEDTLS_DHM_C */

694
thirdparty/mbedtls/library/ecdh.c vendored Normal file
View File

@@ -0,0 +1,694 @@
/*
* Elliptic curve Diffie-Hellman
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
/*
* References:
*
* SEC1 https://www.secg.org/sec1-v2.pdf
* RFC 4492
*/
#include "common.h"
#if defined(MBEDTLS_ECDH_C)
#include "mbedtls/ecdh.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#include <string.h>
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed;
#endif
static mbedtls_ecp_group_id mbedtls_ecdh_grp_id(
const mbedtls_ecdh_context *ctx)
{
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
return ctx->grp.id;
#else
return ctx->grp_id;
#endif
}
int mbedtls_ecdh_can_do(mbedtls_ecp_group_id gid)
{
/* At this time, all groups support ECDH. */
(void) gid;
return 1;
}
#if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
/*
* Generate public key (restartable version)
*
* Note: this internal function relies on its caller preserving the value of
* the output parameter 'd' across continuation calls. This would not be
* acceptable for a public function but is OK here as we control call sites.
*/
static int ecdh_gen_public_restartable(mbedtls_ecp_group *grp,
mbedtls_mpi *d, mbedtls_ecp_point *Q,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
mbedtls_ecp_restart_ctx *rs_ctx)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
int restarting = 0;
#if defined(MBEDTLS_ECP_RESTARTABLE)
restarting = (rs_ctx != NULL && rs_ctx->rsm != NULL);
#endif
/* If multiplication is in progress, we already generated a privkey */
if (!restarting) {
MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, d, f_rng, p_rng));
}
MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, Q, d, &grp->G,
f_rng, p_rng, rs_ctx));
cleanup:
return ret;
}
/*
* Generate public key
*/
int mbedtls_ecdh_gen_public(mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng)
{
return ecdh_gen_public_restartable(grp, d, Q, f_rng, p_rng, NULL);
}
#endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */
#if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT)
/*
* Compute shared secret (SEC1 3.3.1)
*/
static int ecdh_compute_shared_restartable(mbedtls_ecp_group *grp,
mbedtls_mpi *z,
const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
mbedtls_ecp_restart_ctx *rs_ctx)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_point P;
mbedtls_ecp_point_init(&P);
MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, &P, d, Q,
f_rng, p_rng, rs_ctx));
if (mbedtls_ecp_is_zero(&P)) {
ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
goto cleanup;
}
MBEDTLS_MPI_CHK(mbedtls_mpi_copy(z, &P.X));
cleanup:
mbedtls_ecp_point_free(&P);
return ret;
}
/*
* Compute shared secret (SEC1 3.3.1)
*/
int mbedtls_ecdh_compute_shared(mbedtls_ecp_group *grp, mbedtls_mpi *z,
const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng)
{
return ecdh_compute_shared_restartable(grp, z, Q, d,
f_rng, p_rng, NULL);
}
#endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
static void ecdh_init_internal(mbedtls_ecdh_context_mbed *ctx)
{
mbedtls_ecp_group_init(&ctx->grp);
mbedtls_mpi_init(&ctx->d);
mbedtls_ecp_point_init(&ctx->Q);
mbedtls_ecp_point_init(&ctx->Qp);
mbedtls_mpi_init(&ctx->z);
#if defined(MBEDTLS_ECP_RESTARTABLE)
mbedtls_ecp_restart_init(&ctx->rs);
#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
*/
void mbedtls_ecdh_init(mbedtls_ecdh_context *ctx)
{
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
ecdh_init_internal(ctx);
mbedtls_ecp_point_init(&ctx->Vi);
mbedtls_ecp_point_init(&ctx->Vf);
mbedtls_mpi_init(&ctx->_d);
#else
memset(ctx, 0, sizeof(mbedtls_ecdh_context));
ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
#endif
ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
#if defined(MBEDTLS_ECP_RESTARTABLE)
ctx->restart_enabled = 0;
#endif
}
static int ecdh_setup_internal(mbedtls_ecdh_context_mbed *ctx,
mbedtls_ecp_group_id grp_id)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ret = mbedtls_ecp_group_load(&ctx->grp, grp_id);
if (ret != 0) {
return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
}
return 0;
}
/*
* Setup context
*/
int mbedtls_ecdh_setup(mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id)
{
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
return ecdh_setup_internal(ctx, grp_id);
#else
switch (grp_id) {
#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
case MBEDTLS_ECP_DP_CURVE25519:
ctx->point_format = MBEDTLS_ECP_PF_COMPRESSED;
ctx->var = MBEDTLS_ECDH_VARIANT_EVEREST;
ctx->grp_id = grp_id;
return mbedtls_everest_setup(&ctx->ctx.everest_ecdh, grp_id);
#endif
default:
ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0;
ctx->grp_id = grp_id;
ecdh_init_internal(&ctx->ctx.mbed_ecdh);
return ecdh_setup_internal(&ctx->ctx.mbed_ecdh, grp_id);
}
#endif
}
static void ecdh_free_internal(mbedtls_ecdh_context_mbed *ctx)
{
mbedtls_ecp_group_free(&ctx->grp);
mbedtls_mpi_free(&ctx->d);
mbedtls_ecp_point_free(&ctx->Q);
mbedtls_ecp_point_free(&ctx->Qp);
mbedtls_mpi_free(&ctx->z);
#if defined(MBEDTLS_ECP_RESTARTABLE)
mbedtls_ecp_restart_free(&ctx->rs);
#endif
}
#if defined(MBEDTLS_ECP_RESTARTABLE)
/*
* Enable restartable operations for context
*/
void mbedtls_ecdh_enable_restart(mbedtls_ecdh_context *ctx)
{
ctx->restart_enabled = 1;
}
#endif
/*
* Free context
*/
void mbedtls_ecdh_free(mbedtls_ecdh_context *ctx)
{
if (ctx == NULL) {
return;
}
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
mbedtls_ecp_point_free(&ctx->Vi);
mbedtls_ecp_point_free(&ctx->Vf);
mbedtls_mpi_free(&ctx->_d);
ecdh_free_internal(ctx);
#else
switch (ctx->var) {
#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
case MBEDTLS_ECDH_VARIANT_EVEREST:
mbedtls_everest_free(&ctx->ctx.everest_ecdh);
break;
#endif
case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
ecdh_free_internal(&ctx->ctx.mbed_ecdh);
break;
default:
break;
}
ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
ctx->grp_id = MBEDTLS_ECP_DP_NONE;
#endif
}
static int ecdh_make_params_internal(mbedtls_ecdh_context_mbed *ctx,
size_t *olen, int point_format,
unsigned char *buf, size_t blen,
int (*f_rng)(void *,
unsigned char *,
size_t),
void *p_rng,
int restart_enabled)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t grp_len, pt_len;
#if defined(MBEDTLS_ECP_RESTARTABLE)
mbedtls_ecp_restart_ctx *rs_ctx = NULL;
#endif
if (ctx->grp.pbits == 0) {
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
#if defined(MBEDTLS_ECP_RESTARTABLE)
if (restart_enabled) {
rs_ctx = &ctx->rs;
}
#else
(void) restart_enabled;
#endif
#if defined(MBEDTLS_ECP_RESTARTABLE)
if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q,
f_rng, p_rng, rs_ctx)) != 0) {
return ret;
}
#else
if ((ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q,
f_rng, p_rng)) != 0) {
return ret;
}
#endif /* MBEDTLS_ECP_RESTARTABLE */
if ((ret = mbedtls_ecp_tls_write_group(&ctx->grp, &grp_len, buf,
blen)) != 0) {
return ret;
}
buf += grp_len;
blen -= grp_len;
if ((ret = mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format,
&pt_len, buf, blen)) != 0) {
return ret;
}
*olen = grp_len + pt_len;
return 0;
}
/*
* Setup and write the ServerKeyExchange parameters (RFC 4492)
* struct {
* ECParameters curve_params;
* ECPoint public;
* } ServerECDHParams;
*/
int mbedtls_ecdh_make_params(mbedtls_ecdh_context *ctx, size_t *olen,
unsigned char *buf, size_t blen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng)
{
int restart_enabled = 0;
#if defined(MBEDTLS_ECP_RESTARTABLE)
restart_enabled = ctx->restart_enabled;
#else
(void) restart_enabled;
#endif
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
return ecdh_make_params_internal(ctx, olen, ctx->point_format, buf, blen,
f_rng, p_rng, restart_enabled);
#else
switch (ctx->var) {
#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
case MBEDTLS_ECDH_VARIANT_EVEREST:
return mbedtls_everest_make_params(&ctx->ctx.everest_ecdh, olen,
buf, blen, f_rng, p_rng);
#endif
case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
return ecdh_make_params_internal(&ctx->ctx.mbed_ecdh, olen,
ctx->point_format, buf, blen,
f_rng, p_rng,
restart_enabled);
default:
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
#endif
}
static int ecdh_read_params_internal(mbedtls_ecdh_context_mbed *ctx,
const unsigned char **buf,
const unsigned char *end)
{
return mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, buf,
(size_t) (end - *buf));
}
/*
* Read the ServerKeyExchange parameters (RFC 4492)
* struct {
* ECParameters curve_params;
* ECPoint public;
* } ServerECDHParams;
*/
int mbedtls_ecdh_read_params(mbedtls_ecdh_context *ctx,
const unsigned char **buf,
const unsigned char *end)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_group_id grp_id;
if ((ret = mbedtls_ecp_tls_read_group_id(&grp_id, buf, (size_t) (end - *buf)))
!= 0) {
return ret;
}
if ((ret = mbedtls_ecdh_setup(ctx, grp_id)) != 0) {
return ret;
}
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
return ecdh_read_params_internal(ctx, buf, end);
#else
switch (ctx->var) {
#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
case MBEDTLS_ECDH_VARIANT_EVEREST:
return mbedtls_everest_read_params(&ctx->ctx.everest_ecdh,
buf, end);
#endif
case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
return ecdh_read_params_internal(&ctx->ctx.mbed_ecdh,
buf, end);
default:
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
#endif
}
static int ecdh_get_params_internal(mbedtls_ecdh_context_mbed *ctx,
const mbedtls_ecp_keypair *key,
mbedtls_ecdh_side side)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* If it's not our key, just import the public part as Qp */
if (side == MBEDTLS_ECDH_THEIRS) {
return mbedtls_ecp_copy(&ctx->Qp, &key->Q);
}
/* Our key: import public (as Q) and private parts */
if (side != MBEDTLS_ECDH_OURS) {
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
if ((ret = mbedtls_ecp_copy(&ctx->Q, &key->Q)) != 0 ||
(ret = mbedtls_mpi_copy(&ctx->d, &key->d)) != 0) {
return ret;
}
return 0;
}
/*
* Get parameters from a keypair
*/
int mbedtls_ecdh_get_params(mbedtls_ecdh_context *ctx,
const mbedtls_ecp_keypair *key,
mbedtls_ecdh_side side)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if (side != MBEDTLS_ECDH_OURS && side != MBEDTLS_ECDH_THEIRS) {
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
if (mbedtls_ecdh_grp_id(ctx) == MBEDTLS_ECP_DP_NONE) {
/* This is the first call to get_params(). Set up the context
* for use with the group. */
if ((ret = mbedtls_ecdh_setup(ctx, key->grp.id)) != 0) {
return ret;
}
} else {
/* This is not the first call to get_params(). Check that the
* current key's group is the same as the context's, which was set
* from the first key's group. */
if (mbedtls_ecdh_grp_id(ctx) != key->grp.id) {
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
}
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
return ecdh_get_params_internal(ctx, key, side);
#else
switch (ctx->var) {
#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
case MBEDTLS_ECDH_VARIANT_EVEREST:
{
mbedtls_everest_ecdh_side s = side == MBEDTLS_ECDH_OURS ?
MBEDTLS_EVEREST_ECDH_OURS :
MBEDTLS_EVEREST_ECDH_THEIRS;
return mbedtls_everest_get_params(&ctx->ctx.everest_ecdh,
key, s);
}
#endif
case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
return ecdh_get_params_internal(&ctx->ctx.mbed_ecdh,
key, side);
default:
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
#endif
}
static int ecdh_make_public_internal(mbedtls_ecdh_context_mbed *ctx,
size_t *olen, int point_format,
unsigned char *buf, size_t blen,
int (*f_rng)(void *,
unsigned char *,
size_t),
void *p_rng,
int restart_enabled)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_ECP_RESTARTABLE)
mbedtls_ecp_restart_ctx *rs_ctx = NULL;
#endif
if (ctx->grp.pbits == 0) {
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
#if defined(MBEDTLS_ECP_RESTARTABLE)
if (restart_enabled) {
rs_ctx = &ctx->rs;
}
#else
(void) restart_enabled;
#endif
#if defined(MBEDTLS_ECP_RESTARTABLE)
if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q,
f_rng, p_rng, rs_ctx)) != 0) {
return ret;
}
#else
if ((ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q,
f_rng, p_rng)) != 0) {
return ret;
}
#endif /* MBEDTLS_ECP_RESTARTABLE */
return mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format, olen,
buf, blen);
}
/*
* Setup and export the client public value
*/
int mbedtls_ecdh_make_public(mbedtls_ecdh_context *ctx, size_t *olen,
unsigned char *buf, size_t blen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng)
{
int restart_enabled = 0;
#if defined(MBEDTLS_ECP_RESTARTABLE)
restart_enabled = ctx->restart_enabled;
#endif
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
return ecdh_make_public_internal(ctx, olen, ctx->point_format, buf, blen,
f_rng, p_rng, restart_enabled);
#else
switch (ctx->var) {
#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
case MBEDTLS_ECDH_VARIANT_EVEREST:
return mbedtls_everest_make_public(&ctx->ctx.everest_ecdh, olen,
buf, blen, f_rng, p_rng);
#endif
case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
return ecdh_make_public_internal(&ctx->ctx.mbed_ecdh, olen,
ctx->point_format, buf, blen,
f_rng, p_rng,
restart_enabled);
default:
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
#endif
}
static int ecdh_read_public_internal(mbedtls_ecdh_context_mbed *ctx,
const unsigned char *buf, size_t blen)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const unsigned char *p = buf;
if ((ret = mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, &p,
blen)) != 0) {
return ret;
}
if ((size_t) (p - buf) != blen) {
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
return 0;
}
/*
* Parse and import the client's public value
*/
int mbedtls_ecdh_read_public(mbedtls_ecdh_context *ctx,
const unsigned char *buf, size_t blen)
{
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
return ecdh_read_public_internal(ctx, buf, blen);
#else
switch (ctx->var) {
#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
case MBEDTLS_ECDH_VARIANT_EVEREST:
return mbedtls_everest_read_public(&ctx->ctx.everest_ecdh,
buf, blen);
#endif
case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
return ecdh_read_public_internal(&ctx->ctx.mbed_ecdh,
buf, blen);
default:
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
#endif
}
static int ecdh_calc_secret_internal(mbedtls_ecdh_context_mbed *ctx,
size_t *olen, unsigned char *buf,
size_t blen,
int (*f_rng)(void *,
unsigned char *,
size_t),
void *p_rng,
int restart_enabled)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_ECP_RESTARTABLE)
mbedtls_ecp_restart_ctx *rs_ctx = NULL;
#endif
if (ctx == NULL || ctx->grp.pbits == 0) {
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
#if defined(MBEDTLS_ECP_RESTARTABLE)
if (restart_enabled) {
rs_ctx = &ctx->rs;
}
#else
(void) restart_enabled;
#endif
#if defined(MBEDTLS_ECP_RESTARTABLE)
if ((ret = ecdh_compute_shared_restartable(&ctx->grp, &ctx->z, &ctx->Qp,
&ctx->d, f_rng, p_rng,
rs_ctx)) != 0) {
return ret;
}
#else
if ((ret = mbedtls_ecdh_compute_shared(&ctx->grp, &ctx->z, &ctx->Qp,
&ctx->d, f_rng, p_rng)) != 0) {
return ret;
}
#endif /* MBEDTLS_ECP_RESTARTABLE */
if (mbedtls_mpi_size(&ctx->z) > blen) {
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
*olen = ctx->grp.pbits / 8 + ((ctx->grp.pbits % 8) != 0);
if (mbedtls_ecp_get_type(&ctx->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {
return mbedtls_mpi_write_binary_le(&ctx->z, buf, *olen);
}
return mbedtls_mpi_write_binary(&ctx->z, buf, *olen);
}
/*
* Derive and export the shared secret
*/
int mbedtls_ecdh_calc_secret(mbedtls_ecdh_context *ctx, size_t *olen,
unsigned char *buf, size_t blen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng)
{
int restart_enabled = 0;
#if defined(MBEDTLS_ECP_RESTARTABLE)
restart_enabled = ctx->restart_enabled;
#endif
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
return ecdh_calc_secret_internal(ctx, olen, buf, blen, f_rng, p_rng,
restart_enabled);
#else
switch (ctx->var) {
#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
case MBEDTLS_ECDH_VARIANT_EVEREST:
return mbedtls_everest_calc_secret(&ctx->ctx.everest_ecdh, olen,
buf, blen, f_rng, p_rng);
#endif
case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
return ecdh_calc_secret_internal(&ctx->ctx.mbed_ecdh, olen, buf,
blen, f_rng, p_rng,
restart_enabled);
default:
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
#endif
}
#endif /* MBEDTLS_ECDH_C */

867
thirdparty/mbedtls/library/ecdsa.c vendored Normal file
View File

@@ -0,0 +1,867 @@
/*
* Elliptic curve DSA
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
/*
* References:
*
* SEC1 https://www.secg.org/sec1-v2.pdf
*/
#include "common.h"
#if defined(MBEDTLS_ECDSA_C)
#include "mbedtls/ecdsa.h"
#include "mbedtls/asn1write.h"
#include <string.h>
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
#include "mbedtls/hmac_drbg.h"
#endif
#include "mbedtls/platform.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#if defined(MBEDTLS_ECP_RESTARTABLE)
/*
* Sub-context for ecdsa_verify()
*/
struct mbedtls_ecdsa_restart_ver {
mbedtls_mpi u1, u2; /* intermediate values */
enum { /* what to do next? */
ecdsa_ver_init = 0, /* getting started */
ecdsa_ver_muladd, /* muladd step */
} state;
};
/*
* Init verify restart sub-context
*/
static void ecdsa_restart_ver_init(mbedtls_ecdsa_restart_ver_ctx *ctx)
{
mbedtls_mpi_init(&ctx->u1);
mbedtls_mpi_init(&ctx->u2);
ctx->state = ecdsa_ver_init;
}
/*
* Free the components of a verify restart sub-context
*/
static void ecdsa_restart_ver_free(mbedtls_ecdsa_restart_ver_ctx *ctx)
{
if (ctx == NULL) {
return;
}
mbedtls_mpi_free(&ctx->u1);
mbedtls_mpi_free(&ctx->u2);
ecdsa_restart_ver_init(ctx);
}
/*
* Sub-context for ecdsa_sign()
*/
struct mbedtls_ecdsa_restart_sig {
int sign_tries;
int key_tries;
mbedtls_mpi k; /* per-signature random */
mbedtls_mpi r; /* r value */
enum { /* what to do next? */
ecdsa_sig_init = 0, /* getting started */
ecdsa_sig_mul, /* doing ecp_mul() */
ecdsa_sig_modn, /* mod N computations */
} state;
};
/*
* Init verify sign sub-context
*/
static void ecdsa_restart_sig_init(mbedtls_ecdsa_restart_sig_ctx *ctx)
{
ctx->sign_tries = 0;
ctx->key_tries = 0;
mbedtls_mpi_init(&ctx->k);
mbedtls_mpi_init(&ctx->r);
ctx->state = ecdsa_sig_init;
}
/*
* Free the components of a sign restart sub-context
*/
static void ecdsa_restart_sig_free(mbedtls_ecdsa_restart_sig_ctx *ctx)
{
if (ctx == NULL) {
return;
}
mbedtls_mpi_free(&ctx->k);
mbedtls_mpi_free(&ctx->r);
}
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
/*
* Sub-context for ecdsa_sign_det()
*/
struct mbedtls_ecdsa_restart_det {
mbedtls_hmac_drbg_context rng_ctx; /* DRBG state */
enum { /* what to do next? */
ecdsa_det_init = 0, /* getting started */
ecdsa_det_sign, /* make signature */
} state;
};
/*
* Init verify sign_det sub-context
*/
static void ecdsa_restart_det_init(mbedtls_ecdsa_restart_det_ctx *ctx)
{
mbedtls_hmac_drbg_init(&ctx->rng_ctx);
ctx->state = ecdsa_det_init;
}
/*
* Free the components of a sign_det restart sub-context
*/
static void ecdsa_restart_det_free(mbedtls_ecdsa_restart_det_ctx *ctx)
{
if (ctx == NULL) {
return;
}
mbedtls_hmac_drbg_free(&ctx->rng_ctx);
ecdsa_restart_det_init(ctx);
}
#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
#define ECDSA_RS_ECP (rs_ctx == NULL ? NULL : &rs_ctx->ecp)
/* Utility macro for checking and updating ops budget */
#define ECDSA_BUDGET(ops) \
MBEDTLS_MPI_CHK(mbedtls_ecp_check_budget(grp, ECDSA_RS_ECP, ops));
/* Call this when entering a function that needs its own sub-context */
#define ECDSA_RS_ENTER(SUB) do { \
/* reset ops count for this call if top-level */ \
if (rs_ctx != NULL && rs_ctx->ecp.depth++ == 0) \
rs_ctx->ecp.ops_done = 0; \
\
/* set up our own sub-context if needed */ \
if (mbedtls_ecp_restart_is_enabled() && \
rs_ctx != NULL && rs_ctx->SUB == NULL) \
{ \
rs_ctx->SUB = mbedtls_calloc(1, sizeof(*rs_ctx->SUB)); \
if (rs_ctx->SUB == NULL) \
return MBEDTLS_ERR_ECP_ALLOC_FAILED; \
\
ecdsa_restart_## SUB ##_init(rs_ctx->SUB); \
} \
} while (0)
/* Call this when leaving a function that needs its own sub-context */
#define ECDSA_RS_LEAVE(SUB) do { \
/* clear our sub-context when not in progress (done or error) */ \
if (rs_ctx != NULL && rs_ctx->SUB != NULL && \
ret != MBEDTLS_ERR_ECP_IN_PROGRESS) \
{ \
ecdsa_restart_## SUB ##_free(rs_ctx->SUB); \
mbedtls_free(rs_ctx->SUB); \
rs_ctx->SUB = NULL; \
} \
\
if (rs_ctx != NULL) \
rs_ctx->ecp.depth--; \
} while (0)
#else /* MBEDTLS_ECP_RESTARTABLE */
#define ECDSA_RS_ECP NULL
#define ECDSA_BUDGET(ops) /* no-op; for compatibility */
#define ECDSA_RS_ENTER(SUB) (void) rs_ctx
#define ECDSA_RS_LEAVE(SUB) (void) rs_ctx
#endif /* MBEDTLS_ECP_RESTARTABLE */
#if defined(MBEDTLS_ECDSA_DETERMINISTIC) || \
!defined(MBEDTLS_ECDSA_SIGN_ALT) || \
!defined(MBEDTLS_ECDSA_VERIFY_ALT)
/*
* Derive a suitable integer for group grp from a buffer of length len
* SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3
*/
static int derive_mpi(const mbedtls_ecp_group *grp, mbedtls_mpi *x,
const unsigned char *buf, size_t blen)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t n_size = (grp->nbits + 7) / 8;
size_t use_size = blen > n_size ? n_size : blen;
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(x, buf, use_size));
if (use_size * 8 > grp->nbits) {
MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(x, use_size * 8 - grp->nbits));
}
/* While at it, reduce modulo N */
if (mbedtls_mpi_cmp_mpi(x, &grp->N) >= 0) {
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(x, x, &grp->N));
}
cleanup:
return ret;
}
#endif /* ECDSA_DETERMINISTIC || !ECDSA_SIGN_ALT || !ECDSA_VERIFY_ALT */
int mbedtls_ecdsa_can_do(mbedtls_ecp_group_id gid)
{
switch (gid) {
#ifdef MBEDTLS_ECP_DP_CURVE25519_ENABLED
case MBEDTLS_ECP_DP_CURVE25519: return 0;
#endif
#ifdef MBEDTLS_ECP_DP_CURVE448_ENABLED
case MBEDTLS_ECP_DP_CURVE448: return 0;
#endif
default: return 1;
}
}
#if !defined(MBEDTLS_ECDSA_SIGN_ALT)
/*
* Compute ECDSA signature of a hashed message (SEC1 4.1.3)
* Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message)
*/
int mbedtls_ecdsa_sign_restartable(mbedtls_ecp_group *grp,
mbedtls_mpi *r, mbedtls_mpi *s,
const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
int (*f_rng_blind)(void *, unsigned char *, size_t),
void *p_rng_blind,
mbedtls_ecdsa_restart_ctx *rs_ctx)
{
int ret, key_tries, sign_tries;
int *p_sign_tries = &sign_tries, *p_key_tries = &key_tries;
mbedtls_ecp_point R;
mbedtls_mpi k, e, t;
mbedtls_mpi *pk = &k, *pr = r;
/* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
if (!mbedtls_ecdsa_can_do(grp->id) || grp->N.p == NULL) {
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
/* Make sure d is in range 1..n-1 */
if (mbedtls_mpi_cmp_int(d, 1) < 0 || mbedtls_mpi_cmp_mpi(d, &grp->N) >= 0) {
return MBEDTLS_ERR_ECP_INVALID_KEY;
}
mbedtls_ecp_point_init(&R);
mbedtls_mpi_init(&k); mbedtls_mpi_init(&e); mbedtls_mpi_init(&t);
ECDSA_RS_ENTER(sig);
#if defined(MBEDTLS_ECP_RESTARTABLE)
if (rs_ctx != NULL && rs_ctx->sig != NULL) {
/* redirect to our context */
p_sign_tries = &rs_ctx->sig->sign_tries;
p_key_tries = &rs_ctx->sig->key_tries;
pk = &rs_ctx->sig->k;
pr = &rs_ctx->sig->r;
/* jump to current step */
if (rs_ctx->sig->state == ecdsa_sig_mul) {
goto mul;
}
if (rs_ctx->sig->state == ecdsa_sig_modn) {
goto modn;
}
}
#endif /* MBEDTLS_ECP_RESTARTABLE */
*p_sign_tries = 0;
do {
if ((*p_sign_tries)++ > 10) {
ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
goto cleanup;
}
/*
* Steps 1-3: generate a suitable ephemeral keypair
* and set r = xR mod n
*/
*p_key_tries = 0;
do {
if ((*p_key_tries)++ > 10) {
ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
goto cleanup;
}
MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, pk, f_rng, p_rng));
#if defined(MBEDTLS_ECP_RESTARTABLE)
if (rs_ctx != NULL && rs_ctx->sig != NULL) {
rs_ctx->sig->state = ecdsa_sig_mul;
}
mul:
#endif
MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, &R, pk, &grp->G,
f_rng_blind,
p_rng_blind,
ECDSA_RS_ECP));
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pr, &R.X, &grp->N));
} while (mbedtls_mpi_cmp_int(pr, 0) == 0);
#if defined(MBEDTLS_ECP_RESTARTABLE)
if (rs_ctx != NULL && rs_ctx->sig != NULL) {
rs_ctx->sig->state = ecdsa_sig_modn;
}
modn:
#endif
/*
* Accounting for everything up to the end of the loop
* (step 6, but checking now avoids saving e and t)
*/
ECDSA_BUDGET(MBEDTLS_ECP_OPS_INV + 4);
/*
* Step 5: derive MPI from hashed message
*/
MBEDTLS_MPI_CHK(derive_mpi(grp, &e, buf, blen));
/*
* Generate a random value to blind inv_mod in next step,
* avoiding a potential timing leak.
*/
MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, &t, f_rng_blind,
p_rng_blind));
/*
* Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n
*/
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(s, pr, d));
MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&e, &e, s));
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&e, &e, &t));
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(pk, pk, &t));
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pk, pk, &grp->N));
MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(s, pk, &grp->N));
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(s, s, &e));
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(s, s, &grp->N));
} while (mbedtls_mpi_cmp_int(s, 0) == 0);
#if defined(MBEDTLS_ECP_RESTARTABLE)
if (rs_ctx != NULL && rs_ctx->sig != NULL) {
MBEDTLS_MPI_CHK(mbedtls_mpi_copy(r, pr));
}
#endif
cleanup:
mbedtls_ecp_point_free(&R);
mbedtls_mpi_free(&k); mbedtls_mpi_free(&e); mbedtls_mpi_free(&t);
ECDSA_RS_LEAVE(sig);
return ret;
}
/*
* Compute ECDSA signature of a hashed message
*/
int mbedtls_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
{
/* Use the same RNG for both blinding and ephemeral key generation */
return mbedtls_ecdsa_sign_restartable(grp, r, s, d, buf, blen,
f_rng, p_rng, f_rng, p_rng, NULL);
}
#endif /* !MBEDTLS_ECDSA_SIGN_ALT */
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
/*
* Deterministic signature wrapper
*
* note: The f_rng_blind parameter must not be NULL.
*
*/
int mbedtls_ecdsa_sign_det_restartable(mbedtls_ecp_group *grp,
mbedtls_mpi *r, mbedtls_mpi *s,
const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
mbedtls_md_type_t md_alg,
int (*f_rng_blind)(void *, unsigned char *, size_t),
void *p_rng_blind,
mbedtls_ecdsa_restart_ctx *rs_ctx)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_hmac_drbg_context rng_ctx;
mbedtls_hmac_drbg_context *p_rng = &rng_ctx;
unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES];
size_t grp_len = (grp->nbits + 7) / 8;
const mbedtls_md_info_t *md_info;
mbedtls_mpi h;
if ((md_info = mbedtls_md_info_from_type(md_alg)) == NULL) {
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
mbedtls_mpi_init(&h);
mbedtls_hmac_drbg_init(&rng_ctx);
ECDSA_RS_ENTER(det);
#if defined(MBEDTLS_ECP_RESTARTABLE)
if (rs_ctx != NULL && rs_ctx->det != NULL) {
/* redirect to our context */
p_rng = &rs_ctx->det->rng_ctx;
/* jump to current step */
if (rs_ctx->det->state == ecdsa_det_sign) {
goto sign;
}
}
#endif /* MBEDTLS_ECP_RESTARTABLE */
/* Use private key and message hash (reduced) to initialize HMAC_DRBG */
MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(d, data, grp_len));
MBEDTLS_MPI_CHK(derive_mpi(grp, &h, buf, blen));
MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&h, data + grp_len, grp_len));
MBEDTLS_MPI_CHK(mbedtls_hmac_drbg_seed_buf(p_rng, md_info, data, 2 * grp_len));
#if defined(MBEDTLS_ECP_RESTARTABLE)
if (rs_ctx != NULL && rs_ctx->det != NULL) {
rs_ctx->det->state = ecdsa_det_sign;
}
sign:
#endif
#if defined(MBEDTLS_ECDSA_SIGN_ALT)
(void) f_rng_blind;
(void) p_rng_blind;
ret = mbedtls_ecdsa_sign(grp, r, s, d, buf, blen,
mbedtls_hmac_drbg_random, p_rng);
#else
ret = mbedtls_ecdsa_sign_restartable(grp, r, s, d, buf, blen,
mbedtls_hmac_drbg_random, p_rng,
f_rng_blind, p_rng_blind, rs_ctx);
#endif /* MBEDTLS_ECDSA_SIGN_ALT */
cleanup:
mbedtls_hmac_drbg_free(&rng_ctx);
mbedtls_mpi_free(&h);
ECDSA_RS_LEAVE(det);
return ret;
}
/*
* Deterministic signature wrapper
*/
int mbedtls_ecdsa_sign_det_ext(mbedtls_ecp_group *grp, mbedtls_mpi *r,
mbedtls_mpi *s, const mbedtls_mpi *d,
const unsigned char *buf, size_t blen,
mbedtls_md_type_t md_alg,
int (*f_rng_blind)(void *, unsigned char *,
size_t),
void *p_rng_blind)
{
return mbedtls_ecdsa_sign_det_restartable(grp, r, s, d, buf, blen, md_alg,
f_rng_blind, p_rng_blind, NULL);
}
#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
#if !defined(MBEDTLS_ECDSA_VERIFY_ALT)
/*
* Verify ECDSA signature of hashed message (SEC1 4.1.4)
* Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message)
*/
int mbedtls_ecdsa_verify_restartable(mbedtls_ecp_group *grp,
const unsigned char *buf, size_t blen,
const mbedtls_ecp_point *Q,
const mbedtls_mpi *r,
const mbedtls_mpi *s,
mbedtls_ecdsa_restart_ctx *rs_ctx)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi e, s_inv, u1, u2;
mbedtls_ecp_point R;
mbedtls_mpi *pu1 = &u1, *pu2 = &u2;
mbedtls_ecp_point_init(&R);
mbedtls_mpi_init(&e); mbedtls_mpi_init(&s_inv);
mbedtls_mpi_init(&u1); mbedtls_mpi_init(&u2);
/* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
if (!mbedtls_ecdsa_can_do(grp->id) || grp->N.p == NULL) {
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
ECDSA_RS_ENTER(ver);
#if defined(MBEDTLS_ECP_RESTARTABLE)
if (rs_ctx != NULL && rs_ctx->ver != NULL) {
/* redirect to our context */
pu1 = &rs_ctx->ver->u1;
pu2 = &rs_ctx->ver->u2;
/* jump to current step */
if (rs_ctx->ver->state == ecdsa_ver_muladd) {
goto muladd;
}
}
#endif /* MBEDTLS_ECP_RESTARTABLE */
/*
* Step 1: make sure r and s are in range 1..n-1
*/
if (mbedtls_mpi_cmp_int(r, 1) < 0 || mbedtls_mpi_cmp_mpi(r, &grp->N) >= 0 ||
mbedtls_mpi_cmp_int(s, 1) < 0 || mbedtls_mpi_cmp_mpi(s, &grp->N) >= 0) {
ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
goto cleanup;
}
/*
* Step 3: derive MPI from hashed message
*/
MBEDTLS_MPI_CHK(derive_mpi(grp, &e, buf, blen));
/*
* Step 4: u1 = e / s mod n, u2 = r / s mod n
*/
ECDSA_BUDGET(MBEDTLS_ECP_OPS_CHK + MBEDTLS_ECP_OPS_INV + 2);
MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&s_inv, s, &grp->N));
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(pu1, &e, &s_inv));
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pu1, pu1, &grp->N));
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(pu2, r, &s_inv));
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pu2, pu2, &grp->N));
#if defined(MBEDTLS_ECP_RESTARTABLE)
if (rs_ctx != NULL && rs_ctx->ver != NULL) {
rs_ctx->ver->state = ecdsa_ver_muladd;
}
muladd:
#endif
/*
* Step 5: R = u1 G + u2 Q
*/
MBEDTLS_MPI_CHK(mbedtls_ecp_muladd_restartable(grp,
&R, pu1, &grp->G, pu2, Q, ECDSA_RS_ECP));
if (mbedtls_ecp_is_zero(&R)) {
ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
goto cleanup;
}
/*
* Step 6: convert xR to an integer (no-op)
* Step 7: reduce xR mod n (gives v)
*/
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&R.X, &R.X, &grp->N));
/*
* Step 8: check if v (that is, R.X) is equal to r
*/
if (mbedtls_mpi_cmp_mpi(&R.X, r) != 0) {
ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
goto cleanup;
}
cleanup:
mbedtls_ecp_point_free(&R);
mbedtls_mpi_free(&e); mbedtls_mpi_free(&s_inv);
mbedtls_mpi_free(&u1); mbedtls_mpi_free(&u2);
ECDSA_RS_LEAVE(ver);
return ret;
}
/*
* Verify ECDSA signature of hashed message
*/
int mbedtls_ecdsa_verify(mbedtls_ecp_group *grp,
const unsigned char *buf, size_t blen,
const mbedtls_ecp_point *Q,
const mbedtls_mpi *r,
const mbedtls_mpi *s)
{
return mbedtls_ecdsa_verify_restartable(grp, buf, blen, Q, r, s, NULL);
}
#endif /* !MBEDTLS_ECDSA_VERIFY_ALT */
/*
* Convert a signature (given by context) to ASN.1
*/
static int ecdsa_signature_to_asn1(const mbedtls_mpi *r, const mbedtls_mpi *s,
unsigned char *sig, size_t sig_size,
size_t *slen)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char buf[MBEDTLS_ECDSA_MAX_LEN] = { 0 };
unsigned char *p = buf + sizeof(buf);
size_t len = 0;
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_mpi(&p, buf, s));
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_mpi(&p, buf, r));
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));
if (len > sig_size) {
return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
}
memcpy(sig, p, len);
*slen = len;
return 0;
}
/*
* Compute and write signature
*/
int mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context *ctx,
mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hlen,
unsigned char *sig, size_t sig_size, size_t *slen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
mbedtls_ecdsa_restart_ctx *rs_ctx)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_mpi r, s;
if (f_rng == NULL) {
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
}
mbedtls_mpi_init(&r);
mbedtls_mpi_init(&s);
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_det_restartable(&ctx->grp, &r, &s, &ctx->d,
hash, hlen, md_alg, f_rng,
p_rng, rs_ctx));
#else
(void) md_alg;
#if defined(MBEDTLS_ECDSA_SIGN_ALT)
(void) rs_ctx;
MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign(&ctx->grp, &r, &s, &ctx->d,
hash, hlen, f_rng, p_rng));
#else
/* Use the same RNG for both blinding and ephemeral key generation */
MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_restartable(&ctx->grp, &r, &s, &ctx->d,
hash, hlen, f_rng, p_rng, f_rng,
p_rng, rs_ctx));
#endif /* MBEDTLS_ECDSA_SIGN_ALT */
#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
MBEDTLS_MPI_CHK(ecdsa_signature_to_asn1(&r, &s, sig, sig_size, slen));
cleanup:
mbedtls_mpi_free(&r);
mbedtls_mpi_free(&s);
return ret;
}
/*
* Compute and write signature
*/
int mbedtls_ecdsa_write_signature(mbedtls_ecdsa_context *ctx,
mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hlen,
unsigned char *sig, size_t sig_size, size_t *slen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng)
{
return mbedtls_ecdsa_write_signature_restartable(
ctx, md_alg, hash, hlen, sig, sig_size, slen,
f_rng, p_rng, NULL);
}
/*
* Read and check signature
*/
int mbedtls_ecdsa_read_signature(mbedtls_ecdsa_context *ctx,
const unsigned char *hash, size_t hlen,
const unsigned char *sig, size_t slen)
{
return mbedtls_ecdsa_read_signature_restartable(
ctx, hash, hlen, sig, slen, NULL);
}
/*
* Restartable read and check signature
*/
int mbedtls_ecdsa_read_signature_restartable(mbedtls_ecdsa_context *ctx,
const unsigned char *hash, size_t hlen,
const unsigned char *sig, size_t slen,
mbedtls_ecdsa_restart_ctx *rs_ctx)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *p = (unsigned char *) sig;
const unsigned char *end = sig + slen;
size_t len;
mbedtls_mpi r, s;
mbedtls_mpi_init(&r);
mbedtls_mpi_init(&s);
if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
goto cleanup;
}
if (p + len != end) {
ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
goto cleanup;
}
if ((ret = mbedtls_asn1_get_mpi(&p, end, &r)) != 0 ||
(ret = mbedtls_asn1_get_mpi(&p, end, &s)) != 0) {
ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
goto cleanup;
}
#if defined(MBEDTLS_ECDSA_VERIFY_ALT)
(void) rs_ctx;
if ((ret = mbedtls_ecdsa_verify(&ctx->grp, hash, hlen,
&ctx->Q, &r, &s)) != 0) {
goto cleanup;
}
#else
if ((ret = mbedtls_ecdsa_verify_restartable(&ctx->grp, hash, hlen,
&ctx->Q, &r, &s, rs_ctx)) != 0) {
goto cleanup;
}
#endif /* MBEDTLS_ECDSA_VERIFY_ALT */
/* At this point we know that the buffer starts with a valid signature.
* Return 0 if the buffer just contains the signature, and a specific
* error code if the valid signature is followed by more data. */
if (p != end) {
ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH;
}
cleanup:
mbedtls_mpi_free(&r);
mbedtls_mpi_free(&s);
return ret;
}
#if !defined(MBEDTLS_ECDSA_GENKEY_ALT)
/*
* Generate key pair
*/
int mbedtls_ecdsa_genkey(mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
{
int ret = 0;
ret = mbedtls_ecp_group_load(&ctx->grp, gid);
if (ret != 0) {
return ret;
}
return mbedtls_ecp_gen_keypair(&ctx->grp, &ctx->d,
&ctx->Q, f_rng, p_rng);
}
#endif /* !MBEDTLS_ECDSA_GENKEY_ALT */
/*
* Set context from an mbedtls_ecp_keypair
*/
int mbedtls_ecdsa_from_keypair(mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if ((ret = mbedtls_ecp_group_copy(&ctx->grp, &key->grp)) != 0 ||
(ret = mbedtls_mpi_copy(&ctx->d, &key->d)) != 0 ||
(ret = mbedtls_ecp_copy(&ctx->Q, &key->Q)) != 0) {
mbedtls_ecdsa_free(ctx);
}
return ret;
}
/*
* Initialize context
*/
void mbedtls_ecdsa_init(mbedtls_ecdsa_context *ctx)
{
mbedtls_ecp_keypair_init(ctx);
}
/*
* Free context
*/
void mbedtls_ecdsa_free(mbedtls_ecdsa_context *ctx)
{
if (ctx == NULL) {
return;
}
mbedtls_ecp_keypair_free(ctx);
}
#if defined(MBEDTLS_ECP_RESTARTABLE)
/*
* Initialize a restart context
*/
void mbedtls_ecdsa_restart_init(mbedtls_ecdsa_restart_ctx *ctx)
{
mbedtls_ecp_restart_init(&ctx->ecp);
ctx->ver = NULL;
ctx->sig = NULL;
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
ctx->det = NULL;
#endif
}
/*
* Free the components of a restart context
*/
void mbedtls_ecdsa_restart_free(mbedtls_ecdsa_restart_ctx *ctx)
{
if (ctx == NULL) {
return;
}
mbedtls_ecp_restart_free(&ctx->ecp);
ecdsa_restart_ver_free(ctx->ver);
mbedtls_free(ctx->ver);
ctx->ver = NULL;
ecdsa_restart_sig_free(ctx->sig);
mbedtls_free(ctx->sig);
ctx->sig = NULL;
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
ecdsa_restart_det_free(ctx->det);
mbedtls_free(ctx->det);
ctx->det = NULL;
#endif
}
#endif /* MBEDTLS_ECP_RESTARTABLE */
#endif /* MBEDTLS_ECDSA_C */

1216
thirdparty/mbedtls/library/ecjpake.c vendored Normal file

File diff suppressed because it is too large Load Diff

3703
thirdparty/mbedtls/library/ecp.c vendored Normal file

File diff suppressed because it is too large Load Diff

5460
thirdparty/mbedtls/library/ecp_curves.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,287 @@
/**
* \file ecp_internal_alt.h
*
* \brief Function declarations for alternative implementation of elliptic curve
* point arithmetic.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
/*
* References:
*
* [1] BERNSTEIN, Daniel J. Curve25519: new Diffie-Hellman speed records.
* <http://cr.yp.to/ecdh/curve25519-20060209.pdf>
*
* [2] CORON, Jean-S'ebastien. Resistance against differential power analysis
* for elliptic curve cryptosystems. In : Cryptographic Hardware and
* Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302.
* <http://link.springer.com/chapter/10.1007/3-540-48059-5_25>
*
* [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to
* render ECC resistant against Side Channel Attacks. IACR Cryptology
* ePrint Archive, 2004, vol. 2004, p. 342.
* <http://eprint.iacr.org/2004/342.pdf>
*
* [4] Certicom Research. SEC 2: Recommended Elliptic Curve Domain Parameters.
* <http://www.secg.org/sec2-v2.pdf>
*
* [5] HANKERSON, Darrel, MENEZES, Alfred J., VANSTONE, Scott. Guide to Elliptic
* Curve Cryptography.
*
* [6] Digital Signature Standard (DSS), FIPS 186-4.
* <http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf>
*
* [7] Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer
* Security (TLS), RFC 4492.
* <https://tools.ietf.org/search/rfc4492>
*
* [8] <http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html>
*
* [9] COHEN, Henri. A Course in Computational Algebraic Number Theory.
* Springer Science & Business Media, 1 Aug 2000
*/
#ifndef MBEDTLS_ECP_INTERNAL_H
#define MBEDTLS_ECP_INTERNAL_H
#include "mbedtls/build_info.h"
#if defined(MBEDTLS_ECP_INTERNAL_ALT)
/**
* \brief Indicate if the Elliptic Curve Point module extension can
* handle the group.
*
* \param grp The pointer to the elliptic curve group that will be the
* basis of the cryptographic computations.
*
* \return Non-zero if successful.
*/
unsigned char mbedtls_internal_ecp_grp_capable(const mbedtls_ecp_group *grp);
/**
* \brief Initialise the Elliptic Curve Point module extension.
*
* If mbedtls_internal_ecp_grp_capable returns true for a
* group, this function has to be able to initialise the
* module for it.
*
* This module can be a driver to a crypto hardware
* accelerator, for which this could be an initialise function.
*
* \param grp The pointer to the group the module needs to be
* initialised for.
*
* \return 0 if successful.
*/
int mbedtls_internal_ecp_init(const mbedtls_ecp_group *grp);
/**
* \brief Frees and deallocates the Elliptic Curve Point module
* extension.
*
* \param grp The pointer to the group the module was initialised for.
*/
void mbedtls_internal_ecp_free(const mbedtls_ecp_group *grp);
#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
/**
* \brief Randomize jacobian coordinates:
* (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l.
*
* \param grp Pointer to the group representing the curve.
*
* \param pt The point on the curve to be randomised, given with Jacobian
* coordinates.
*
* \param f_rng A function pointer to the random number generator.
*
* \param p_rng A pointer to the random number generator state.
*
* \return 0 if successful.
*/
int mbedtls_internal_ecp_randomize_jac(const mbedtls_ecp_group *grp,
mbedtls_ecp_point *pt, int (*f_rng)(void *,
unsigned char *,
size_t),
void *p_rng);
#endif
#if defined(MBEDTLS_ECP_ADD_MIXED_ALT)
/**
* \brief Addition: R = P + Q, mixed affine-Jacobian coordinates.
*
* The coordinates of Q must be normalized (= affine),
* but those of P don't need to. R is not normalized.
*
* This function is used only as a subrutine of
* ecp_mul_comb().
*
* Special cases: (1) P or Q is zero, (2) R is zero,
* (3) P == Q.
* None of these cases can happen as intermediate step in
* ecp_mul_comb():
* - at each step, P, Q and R are multiples of the base
* point, the factor being less than its order, so none of
* them is zero;
* - Q is an odd multiple of the base point, P an even
* multiple, due to the choice of precomputed points in the
* modified comb method.
* So branches for these cases do not leak secret information.
*
* We accept Q->Z being unset (saving memory in tables) as
* meaning 1.
*
* Cost in field operations if done by [5] 3.22:
* 1A := 8M + 3S
*
* \param grp Pointer to the group representing the curve.
*
* \param R Pointer to a point structure to hold the result.
*
* \param P Pointer to the first summand, given with Jacobian
* coordinates
*
* \param Q Pointer to the second summand, given with affine
* coordinates.
*
* \return 0 if successful.
*/
int mbedtls_internal_ecp_add_mixed(const mbedtls_ecp_group *grp,
mbedtls_ecp_point *R, const mbedtls_ecp_point *P,
const mbedtls_ecp_point *Q);
#endif
/**
* \brief Point doubling R = 2 P, Jacobian coordinates.
*
* Cost: 1D := 3M + 4S (A == 0)
* 4M + 4S (A == -3)
* 3M + 6S + 1a otherwise
* when the implementation is based on the "dbl-1998-cmo-2"
* doubling formulas in [8] and standard optimizations are
* applied when curve parameter A is one of { 0, -3 }.
*
* \param grp Pointer to the group representing the curve.
*
* \param R Pointer to a point structure to hold the result.
*
* \param P Pointer to the point that has to be doubled, given with
* Jacobian coordinates.
*
* \return 0 if successful.
*/
#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)
int mbedtls_internal_ecp_double_jac(const mbedtls_ecp_group *grp,
mbedtls_ecp_point *R, const mbedtls_ecp_point *P);
#endif
/**
* \brief Normalize jacobian coordinates of an array of (pointers to)
* points.
*
* Using Montgomery's trick to perform only one inversion mod P
* the cost is:
* 1N(t) := 1I + (6t - 3)M + 1S
* (See for example Algorithm 10.3.4. in [9])
*
* This function is used only as a subrutine of
* ecp_mul_comb().
*
* Warning: fails (returning an error) if one of the points is
* zero!
* This should never happen, see choice of w in ecp_mul_comb().
*
* \param grp Pointer to the group representing the curve.
*
* \param T Array of pointers to the points to normalise.
*
* \param t_len Number of elements in the array.
*
* \return 0 if successful,
* an error if one of the points is zero.
*/
#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)
int mbedtls_internal_ecp_normalize_jac_many(const mbedtls_ecp_group *grp,
mbedtls_ecp_point *T[], size_t t_len);
#endif
/**
* \brief Normalize jacobian coordinates so that Z == 0 || Z == 1.
*
* Cost in field operations if done by [5] 3.2.1:
* 1N := 1I + 3M + 1S
*
* \param grp Pointer to the group representing the curve.
*
* \param pt pointer to the point to be normalised. This is an
* input/output parameter.
*
* \return 0 if successful.
*/
#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)
int mbedtls_internal_ecp_normalize_jac(const mbedtls_ecp_group *grp,
mbedtls_ecp_point *pt);
#endif
#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */
#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
int mbedtls_internal_ecp_double_add_mxz(const mbedtls_ecp_group *grp,
mbedtls_ecp_point *R,
mbedtls_ecp_point *S,
const mbedtls_ecp_point *P,
const mbedtls_ecp_point *Q,
const mbedtls_mpi *d);
#endif
/**
* \brief Randomize projective x/z coordinates:
* (X, Z) -> (l X, l Z) for random l
*
* \param grp pointer to the group representing the curve
*
* \param P the point on the curve to be randomised given with
* projective coordinates. This is an input/output parameter.
*
* \param f_rng a function pointer to the random number generator
*
* \param p_rng a pointer to the random number generator state
*
* \return 0 if successful
*/
#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)
int mbedtls_internal_ecp_randomize_mxz(const mbedtls_ecp_group *grp,
mbedtls_ecp_point *P, int (*f_rng)(void *,
unsigned char *,
size_t),
void *p_rng);
#endif
/**
* \brief Normalize Montgomery x/z coordinates: X = X/Z, Z = 1.
*
* \param grp pointer to the group representing the curve
*
* \param P pointer to the point to be normalised. This is an
* input/output parameter.
*
* \return 0 if successful
*/
#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
int mbedtls_internal_ecp_normalize_mxz(const mbedtls_ecp_group *grp,
mbedtls_ecp_point *P);
#endif
#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */
#endif /* MBEDTLS_ECP_INTERNAL_ALT */
#endif /* ecp_internal_alt.h */

View File

@@ -0,0 +1,325 @@
/**
* \file ecp_invasive.h
*
* \brief ECP module: interfaces for invasive testing only.
*
* The interfaces in this file are intended for testing purposes only.
* They SHOULD NOT be made available in library integrations except when
* building the library for testing.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef MBEDTLS_ECP_INVASIVE_H
#define MBEDTLS_ECP_INVASIVE_H
#include "common.h"
#include "mbedtls/bignum.h"
#include "bignum_mod.h"
#include "mbedtls/ecp.h"
/*
* Curve modulus types
*/
typedef enum {
MBEDTLS_ECP_MOD_NONE = 0,
MBEDTLS_ECP_MOD_COORDINATE,
MBEDTLS_ECP_MOD_SCALAR
} mbedtls_ecp_modulus_type;
typedef enum {
MBEDTLS_ECP_VARIANT_NONE = 0,
MBEDTLS_ECP_VARIANT_WITH_MPI_STRUCT,
MBEDTLS_ECP_VARIANT_WITH_MPI_UINT
} mbedtls_ecp_variant;
#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_ECP_LIGHT)
/** Queries the ecp variant.
*
* \return The id of the ecp variant.
*/
MBEDTLS_STATIC_TESTABLE
mbedtls_ecp_variant mbedtls_ecp_get_variant(void);
#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
/** Generate a private key on a Montgomery curve (Curve25519 or Curve448).
*
* This function implements key generation for the set of secret keys
* specified in [Curve25519] p. 5 and in [Curve448]. The resulting value
* has the lower bits masked but is not necessarily canonical.
*
* \note - [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf
* - [RFC7748] https://tools.ietf.org/html/rfc7748
*
* \p high_bit The position of the high-order bit of the key to generate.
* This is the bit-size of the key minus 1:
* 254 for Curve25519 or 447 for Curve448.
* \param d The randomly generated key. This is a number of size
* exactly \p high_bit + 1 bits, with the least significant bits
* masked as specified in [Curve25519] and in [RFC7748] §5.
* \param f_rng The RNG function.
* \param p_rng The RNG context to be passed to \p f_rng.
*
* \return \c 0 on success.
* \return \c MBEDTLS_ERR_ECP_xxx or MBEDTLS_ERR_MPI_xxx on failure.
*/
int mbedtls_ecp_gen_privkey_mx(size_t high_bit,
mbedtls_mpi *d,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng);
#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */
#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
/** Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1)
*
* This operation expects a 384 bit MPI and the result of the reduction
* is a 192 bit MPI.
*
* \param[in,out] Np The address of the MPI to be converted.
* Must have twice as many limbs as the modulus.
* Upon return this holds the reduced value. The bitlength
* of the reduced value is the same as that of the modulus
* (192 bits).
* \param[in] Nn The length of \p Np in limbs.
*/
MBEDTLS_STATIC_TESTABLE
int mbedtls_ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn);
#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */
#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
/** Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2)
*
* \param[in,out] X The address of the MPI to be converted.
* Must have exact limb size that stores a 448-bit MPI
* (double the bitlength of the modulus).
* Upon return holds the reduced value which is
* in range `0 <= X < 2 * N` (where N is the modulus).
* The bitlength of the reduced value is the same as
* that of the modulus (224 bits).
* \param[in] X_limbs The length of \p X in limbs.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X_limbs is not the
* limb size that sores a 448-bit MPI.
*/
MBEDTLS_STATIC_TESTABLE
int mbedtls_ecp_mod_p224_raw(mbedtls_mpi_uint *X, size_t X_limbs);
#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */
#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
/** Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3)
*
* \param[in,out] X The address of the MPI to be converted.
* Must have exact limb size that stores a 512-bit MPI
* (double the bitlength of the modulus).
* Upon return holds the reduced value which is
* in range `0 <= X < 2 * N` (where N is the modulus).
* The bitlength of the reduced value is the same as
* that of the modulus (256 bits).
* \param[in] X_limbs The length of \p X in limbs.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X_limbs is not the
* limb size that sores a 512-bit MPI.
*/
MBEDTLS_STATIC_TESTABLE
int mbedtls_ecp_mod_p256_raw(mbedtls_mpi_uint *X, size_t X_limbs);
#endif
#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
/** Fast quasi-reduction modulo p521 = 2^521 - 1 (FIPS 186-3 D.2.5)
*
* \param[in,out] X The address of the MPI to be converted.
* Must have twice as many limbs as the modulus
* (the modulus is 521 bits long). Upon return this
* holds the reduced value. The reduced value is
* in range `0 <= X < 2 * N` (where N is the modulus).
* and its the bitlength is one plus the bitlength
* of the modulus.
* \param[in] X_limbs The length of \p X in limbs.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X_limbs does not have
* twice as many limbs as the modulus.
*/
MBEDTLS_STATIC_TESTABLE
int mbedtls_ecp_mod_p521_raw(mbedtls_mpi_uint *X, size_t X_limbs);
#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */
#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
/** Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4)
*
* \param[in,out] X The address of the MPI to be converted.
* Must have exact limb size that stores a 768-bit MPI
* (double the bitlength of the modulus).
* Upon return holds the reduced value which is
* in range `0 <= X < 2 * N` (where N is the modulus).
* The bitlength of the reduced value is the same as
* that of the modulus (384 bits).
* \param[in] X_limbs The length of \p N in limbs.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p N_n does not have
* twice as many limbs as the modulus.
*/
MBEDTLS_STATIC_TESTABLE
int mbedtls_ecp_mod_p384_raw(mbedtls_mpi_uint *X, size_t X_limbs);
#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */
#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
/** Fast quasi-reduction modulo p192k1 = 2^192 - R,
* with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x01000011C9
*
* \param[in,out] X The address of the MPI to be converted.
* Must have exact limb size that stores a 384-bit MPI
* (double the bitlength of the modulus).
* Upon return holds the reduced value which is
* in range `0 <= X < 2 * N` (where N is the modulus).
* The bitlength of the reduced value is the same as
* that of the modulus (192 bits).
* \param[in] X_limbs The length of \p X in limbs.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X does not have
* twice as many limbs as the modulus.
* \return #MBEDTLS_ERR_ECP_ALLOC_FAILED if memory allocation failed.
*/
MBEDTLS_STATIC_TESTABLE
int mbedtls_ecp_mod_p192k1_raw(mbedtls_mpi_uint *X, size_t X_limbs);
#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */
#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
/** Fast quasi-reduction modulo p224k1 = 2^224 - R,
* with R = 2^32 + 2^12 + 2^11 + 2^9 + 2^7 + 2^4 + 2 + 1 = 0x0100001A93
*
* \param[in,out] X The address of the MPI to be converted.
* Must have exact limb size that stores a 448-bit MPI
* (double the bitlength of the modulus).
* Upon return holds the reduced value which is
* in range `0 <= X < 2 * N` (where N is the modulus).
* The bitlength of the reduced value is the same as
* that of the modulus (224 bits).
* \param[in] X_limbs The length of \p X in limbs.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X does not have
* twice as many limbs as the modulus.
* \return #MBEDTLS_ERR_ECP_ALLOC_FAILED if memory allocation failed.
*/
MBEDTLS_STATIC_TESTABLE
int mbedtls_ecp_mod_p224k1_raw(mbedtls_mpi_uint *X, size_t X_limbs);
#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */
#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
/** Fast quasi-reduction modulo p256k1 = 2^256 - R,
* with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 0x01000003D1
*
* \param[in,out] X The address of the MPI to be converted.
* Must have exact limb size that stores a 512-bit MPI
* (double the bitlength of the modulus).
* Upon return holds the reduced value which is
* in range `0 <= X < 2 * N` (where N is the modulus).
* The bitlength of the reduced value is the same as
* that of the modulus (256 bits).
* \param[in] X_limbs The length of \p X in limbs.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X does not have
* twice as many limbs as the modulus.
* \return #MBEDTLS_ERR_ECP_ALLOC_FAILED if memory allocation failed.
*/
MBEDTLS_STATIC_TESTABLE
int mbedtls_ecp_mod_p256k1_raw(mbedtls_mpi_uint *X, size_t X_limbs);
#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */
#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
/** Fast quasi-reduction modulo p255 = 2^255 - 19
*
* \param[in,out] X The address of the MPI to be converted.
* Must have exact limb size that stores a 510-bit MPI
* (double the bitlength of the modulus).
* Upon return holds the reduced value which is
* in range `0 <= X < 2 * N` (where N is the modulus).
* \param[in] X_limbs The length of \p X in limbs.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X does not have
* twice as many limbs as the modulus.
* \return #MBEDTLS_ERR_ECP_ALLOC_FAILED if memory allocation failed.
*/
MBEDTLS_STATIC_TESTABLE
int mbedtls_ecp_mod_p255_raw(mbedtls_mpi_uint *X, size_t X_limbs);
#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */
#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
/** Fast quasi-reduction modulo p448 = 2^448 - 2^224 - 1
* Write X as A0 + 2^448 A1 and A1 as B0 + 2^224 B1, and return A0 + A1 + B1 +
* (B0 + B1) * 2^224.
*
* \param[in,out] X The address of the MPI to be converted.
* Must have exact limb size that stores a 896-bit MPI
* (double the bitlength of the modulus). Upon return
* holds the reduced value which is in range `0 <= X <
* N` (where N is the modulus). The bitlength of the
* reduced value is the same as that of the modulus
* (448 bits).
* \param[in] X_limbs The length of \p X in limbs.
*
* \return \c 0 on Success.
* \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X does not have
* twice as many limbs as the modulus.
* \return #MBEDTLS_ERR_ECP_ALLOC_FAILED if memory allocation
* failed.
*/
MBEDTLS_STATIC_TESTABLE
int mbedtls_ecp_mod_p448_raw(mbedtls_mpi_uint *X, size_t X_limbs);
#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */
/** Initialise a modulus with hard-coded const curve data.
*
* \note The caller is responsible for the \p N modulus' memory.
* mbedtls_mpi_mod_modulus_free(&N) should be invoked at the
* end of its lifecycle.
*
* \param[in,out] N The address of the modulus structure to populate.
* Must be initialized.
* \param[in] id The mbedtls_ecp_group_id for which to initialise the modulus.
* \param[in] ctype The mbedtls_ecp_modulus_type identifier for a coordinate modulus (P)
* or a scalar modulus (N).
*
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the given MPIs do not
* have the correct number of limbs.
*
*/
MBEDTLS_STATIC_TESTABLE
int mbedtls_ecp_modulus_setup(mbedtls_mpi_mod_modulus *N,
const mbedtls_ecp_group_id id,
const mbedtls_ecp_modulus_type ctype);
#endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_ECP_C */
#endif /* MBEDTLS_ECP_INVASIVE_H */

680
thirdparty/mbedtls/library/entropy.c vendored Normal file
View File

@@ -0,0 +1,680 @@
/*
* Entropy accumulator implementation
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#if defined(MBEDTLS_ENTROPY_C)
#include "mbedtls/entropy.h"
#include "entropy_poll.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#include <string.h>
#if defined(MBEDTLS_FS_IO)
#include <stdio.h>
#endif
#include "mbedtls/platform.h"
#define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */
void mbedtls_entropy_init(mbedtls_entropy_context *ctx)
{
ctx->source_count = 0;
memset(ctx->source, 0, sizeof(ctx->source));
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_init(&ctx->mutex);
#endif
ctx->accumulator_started = 0;
mbedtls_md_init(&ctx->accumulator);
/* Reminder: Update ENTROPY_HAVE_STRONG in the test files
* when adding more strong entropy sources here. */
#if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES)
#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
mbedtls_entropy_add_source(ctx, mbedtls_platform_entropy_poll, NULL,
MBEDTLS_ENTROPY_MIN_PLATFORM,
MBEDTLS_ENTROPY_SOURCE_STRONG);
#endif
#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
mbedtls_entropy_add_source(ctx, mbedtls_hardware_poll, NULL,
MBEDTLS_ENTROPY_MIN_HARDWARE,
MBEDTLS_ENTROPY_SOURCE_STRONG);
#endif
#if defined(MBEDTLS_ENTROPY_NV_SEED)
mbedtls_entropy_add_source(ctx, mbedtls_nv_seed_poll, NULL,
MBEDTLS_ENTROPY_BLOCK_SIZE,
MBEDTLS_ENTROPY_SOURCE_STRONG);
ctx->initial_entropy_run = 0;
#endif
#endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */
}
void mbedtls_entropy_free(mbedtls_entropy_context *ctx)
{
if (ctx == NULL) {
return;
}
/* If the context was already free, don't call free() again.
* This is important for mutexes which don't allow double-free. */
if (ctx->accumulator_started == -1) {
return;
}
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_free(&ctx->mutex);
#endif
mbedtls_md_free(&ctx->accumulator);
#if defined(MBEDTLS_ENTROPY_NV_SEED)
ctx->initial_entropy_run = 0;
#endif
ctx->source_count = 0;
mbedtls_platform_zeroize(ctx->source, sizeof(ctx->source));
ctx->accumulator_started = -1;
}
int mbedtls_entropy_add_source(mbedtls_entropy_context *ctx,
mbedtls_entropy_f_source_ptr f_source, void *p_source,
size_t threshold, int strong)
{
int idx, ret = 0;
#if defined(MBEDTLS_THREADING_C)
if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
return ret;
}
#endif
idx = ctx->source_count;
if (idx >= MBEDTLS_ENTROPY_MAX_SOURCES) {
ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES;
goto exit;
}
ctx->source[idx].f_source = f_source;
ctx->source[idx].p_source = p_source;
ctx->source[idx].threshold = threshold;
ctx->source[idx].strong = strong;
ctx->source_count++;
exit:
#if defined(MBEDTLS_THREADING_C)
if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
}
#endif
return ret;
}
/*
* Entropy accumulator update
*/
static int entropy_update(mbedtls_entropy_context *ctx, unsigned char source_id,
const unsigned char *data, size_t len)
{
unsigned char header[2];
unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE];
size_t use_len = len;
const unsigned char *p = data;
int ret = 0;
if (use_len > MBEDTLS_ENTROPY_BLOCK_SIZE) {
if ((ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD),
data, len, tmp)) != 0) {
goto cleanup;
}
p = tmp;
use_len = MBEDTLS_ENTROPY_BLOCK_SIZE;
}
header[0] = source_id;
header[1] = use_len & 0xFF;
/*
* Start the accumulator if this has not already happened. Note that
* it is sufficient to start the accumulator here only because all calls to
* gather entropy eventually execute this code.
*/
if (ctx->accumulator_started == 0) {
ret = mbedtls_md_setup(&ctx->accumulator,
mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD), 0);
if (ret != 0) {
goto cleanup;
}
ret = mbedtls_md_starts(&ctx->accumulator);
if (ret != 0) {
goto cleanup;
}
ctx->accumulator_started = 1;
}
if ((ret = mbedtls_md_update(&ctx->accumulator, header, 2)) != 0) {
goto cleanup;
}
ret = mbedtls_md_update(&ctx->accumulator, p, use_len);
cleanup:
mbedtls_platform_zeroize(tmp, sizeof(tmp));
return ret;
}
int mbedtls_entropy_update_manual(mbedtls_entropy_context *ctx,
const unsigned char *data, size_t len)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_THREADING_C)
if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
return ret;
}
#endif
ret = entropy_update(ctx, MBEDTLS_ENTROPY_SOURCE_MANUAL, data, len);
#if defined(MBEDTLS_THREADING_C)
if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
}
#endif
return ret;
}
/*
* Run through the different sources to add entropy to our accumulator
*/
static int entropy_gather_internal(mbedtls_entropy_context *ctx)
{
int ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
int i;
int have_one_strong = 0;
unsigned char buf[MBEDTLS_ENTROPY_MAX_GATHER];
size_t olen;
if (ctx->source_count == 0) {
return MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED;
}
/*
* Run through our entropy sources
*/
for (i = 0; i < ctx->source_count; i++) {
if (ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG) {
have_one_strong = 1;
}
olen = 0;
if ((ret = ctx->source[i].f_source(ctx->source[i].p_source,
buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen)) != 0) {
goto cleanup;
}
/*
* Add if we actually gathered something
*/
if (olen > 0) {
if ((ret = entropy_update(ctx, (unsigned char) i,
buf, olen)) != 0) {
return ret;
}
ctx->source[i].size += olen;
}
}
if (have_one_strong == 0) {
ret = MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE;
}
cleanup:
mbedtls_platform_zeroize(buf, sizeof(buf));
return ret;
}
/*
* Thread-safe wrapper for entropy_gather_internal()
*/
int mbedtls_entropy_gather(mbedtls_entropy_context *ctx)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_THREADING_C)
if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
return ret;
}
#endif
ret = entropy_gather_internal(ctx);
#if defined(MBEDTLS_THREADING_C)
if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
}
#endif
return ret;
}
int mbedtls_entropy_func(void *data, unsigned char *output, size_t len)
{
int ret, count = 0, i, thresholds_reached;
size_t strong_size;
mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data;
unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
if (len > MBEDTLS_ENTROPY_BLOCK_SIZE) {
return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
}
#if defined(MBEDTLS_ENTROPY_NV_SEED)
/* Update the NV entropy seed before generating any entropy for outside
* use.
*/
if (ctx->initial_entropy_run == 0) {
ctx->initial_entropy_run = 1;
if ((ret = mbedtls_entropy_update_nv_seed(ctx)) != 0) {
return ret;
}
}
#endif
#if defined(MBEDTLS_THREADING_C)
if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
return ret;
}
#endif
/*
* Always gather extra entropy before a call
*/
do {
if (count++ > ENTROPY_MAX_LOOP) {
ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
goto exit;
}
if ((ret = entropy_gather_internal(ctx)) != 0) {
goto exit;
}
thresholds_reached = 1;
strong_size = 0;
for (i = 0; i < ctx->source_count; i++) {
if (ctx->source[i].size < ctx->source[i].threshold) {
thresholds_reached = 0;
}
if (ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG) {
strong_size += ctx->source[i].size;
}
}
} while (!thresholds_reached || strong_size < MBEDTLS_ENTROPY_BLOCK_SIZE);
memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE);
/*
* Note that at this stage it is assumed that the accumulator was started
* in a previous call to entropy_update(). If this is not guaranteed, the
* code below will fail.
*/
if ((ret = mbedtls_md_finish(&ctx->accumulator, buf)) != 0) {
goto exit;
}
/*
* Reset accumulator and counters and recycle existing entropy
*/
mbedtls_md_free(&ctx->accumulator);
mbedtls_md_init(&ctx->accumulator);
ret = mbedtls_md_setup(&ctx->accumulator,
mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD), 0);
if (ret != 0) {
goto exit;
}
ret = mbedtls_md_starts(&ctx->accumulator);
if (ret != 0) {
goto exit;
}
if ((ret = mbedtls_md_update(&ctx->accumulator, buf,
MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) {
goto exit;
}
/*
* Perform second hashing on entropy
*/
if ((ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD),
buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf)) != 0) {
goto exit;
}
for (i = 0; i < ctx->source_count; i++) {
ctx->source[i].size = 0;
}
memcpy(output, buf, len);
ret = 0;
exit:
mbedtls_platform_zeroize(buf, sizeof(buf));
#if defined(MBEDTLS_THREADING_C)
if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
}
#endif
return ret;
}
#if defined(MBEDTLS_ENTROPY_NV_SEED)
int mbedtls_entropy_update_nv_seed(mbedtls_entropy_context *ctx)
{
int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
/* Read new seed and write it to NV */
if ((ret = mbedtls_entropy_func(ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) {
return ret;
}
if (mbedtls_nv_seed_write(buf, MBEDTLS_ENTROPY_BLOCK_SIZE) < 0) {
return MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
}
/* Manually update the remaining stream with a separator value to diverge */
memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE);
ret = mbedtls_entropy_update_manual(ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE);
return ret;
}
#endif /* MBEDTLS_ENTROPY_NV_SEED */
#if defined(MBEDTLS_FS_IO)
int mbedtls_entropy_write_seed_file(mbedtls_entropy_context *ctx, const char *path)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
FILE *f = NULL;
unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
if ((ret = mbedtls_entropy_func(ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) {
ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
goto exit;
}
if ((f = fopen(path, "wb")) == NULL) {
ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
goto exit;
}
/* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
mbedtls_setbuf(f, NULL);
if (fwrite(buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f) != MBEDTLS_ENTROPY_BLOCK_SIZE) {
ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
goto exit;
}
ret = 0;
exit:
mbedtls_platform_zeroize(buf, sizeof(buf));
if (f != NULL) {
fclose(f);
}
return ret;
}
int mbedtls_entropy_update_seed_file(mbedtls_entropy_context *ctx, const char *path)
{
int ret = 0;
FILE *f;
size_t n;
unsigned char buf[MBEDTLS_ENTROPY_MAX_SEED_SIZE];
if ((f = fopen(path, "rb")) == NULL) {
return MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
}
/* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
mbedtls_setbuf(f, NULL);
fseek(f, 0, SEEK_END);
n = (size_t) ftell(f);
fseek(f, 0, SEEK_SET);
if (n > MBEDTLS_ENTROPY_MAX_SEED_SIZE) {
n = MBEDTLS_ENTROPY_MAX_SEED_SIZE;
}
if (fread(buf, 1, n, f) != n) {
ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
} else {
ret = mbedtls_entropy_update_manual(ctx, buf, n);
}
fclose(f);
mbedtls_platform_zeroize(buf, sizeof(buf));
if (ret != 0) {
return ret;
}
return mbedtls_entropy_write_seed_file(ctx, path);
}
#endif /* MBEDTLS_FS_IO */
#if defined(MBEDTLS_SELF_TEST)
/*
* Dummy source function
*/
static int entropy_dummy_source(void *data, unsigned char *output,
size_t len, size_t *olen)
{
((void) data);
memset(output, 0x2a, len);
*olen = len;
return 0;
}
#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
static int mbedtls_entropy_source_self_test_gather(unsigned char *buf, size_t buf_len)
{
int ret = 0;
size_t entropy_len = 0;
size_t olen = 0;
size_t attempts = buf_len;
while (attempts > 0 && entropy_len < buf_len) {
if ((ret = mbedtls_hardware_poll(NULL, buf + entropy_len,
buf_len - entropy_len, &olen)) != 0) {
return ret;
}
entropy_len += olen;
attempts--;
}
if (entropy_len < buf_len) {
ret = 1;
}
return ret;
}
static int mbedtls_entropy_source_self_test_check_bits(const unsigned char *buf,
size_t buf_len)
{
unsigned char set = 0xFF;
unsigned char unset = 0x00;
size_t i;
for (i = 0; i < buf_len; i++) {
set &= buf[i];
unset |= buf[i];
}
return set == 0xFF || unset == 0x00;
}
/*
* A test to ensure that the entropy sources are functioning correctly
* and there is no obvious failure. The test performs the following checks:
* - The entropy source is not providing only 0s (all bits unset) or 1s (all
* bits set).
* - The entropy source is not providing values in a pattern. Because the
* hardware could be providing data in an arbitrary length, this check polls
* the hardware entropy source twice and compares the result to ensure they
* are not equal.
* - The error code returned by the entropy source is not an error.
*/
int mbedtls_entropy_source_self_test(int verbose)
{
int ret = 0;
unsigned char buf0[2 * sizeof(unsigned long long int)];
unsigned char buf1[2 * sizeof(unsigned long long int)];
if (verbose != 0) {
mbedtls_printf(" ENTROPY_BIAS test: ");
}
memset(buf0, 0x00, sizeof(buf0));
memset(buf1, 0x00, sizeof(buf1));
if ((ret = mbedtls_entropy_source_self_test_gather(buf0, sizeof(buf0))) != 0) {
goto cleanup;
}
if ((ret = mbedtls_entropy_source_self_test_gather(buf1, sizeof(buf1))) != 0) {
goto cleanup;
}
/* Make sure that the returned values are not all 0 or 1 */
if ((ret = mbedtls_entropy_source_self_test_check_bits(buf0, sizeof(buf0))) != 0) {
goto cleanup;
}
if ((ret = mbedtls_entropy_source_self_test_check_bits(buf1, sizeof(buf1))) != 0) {
goto cleanup;
}
/* Make sure that the entropy source is not returning values in a
* pattern */
ret = memcmp(buf0, buf1, sizeof(buf0)) == 0;
cleanup:
if (verbose != 0) {
if (ret != 0) {
mbedtls_printf("failed\n");
} else {
mbedtls_printf("passed\n");
}
mbedtls_printf("\n");
}
return ret != 0;
}
#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */
/*
* The actual entropy quality is hard to test, but we can at least
* test that the functions don't cause errors and write the correct
* amount of data to buffers.
*/
int mbedtls_entropy_self_test(int verbose)
{
int ret = 1;
mbedtls_entropy_context ctx;
unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
size_t i, j;
if (verbose != 0) {
mbedtls_printf(" ENTROPY test: ");
}
mbedtls_entropy_init(&ctx);
/* First do a gather to make sure we have default sources */
if ((ret = mbedtls_entropy_gather(&ctx)) != 0) {
goto cleanup;
}
ret = mbedtls_entropy_add_source(&ctx, entropy_dummy_source, NULL, 16,
MBEDTLS_ENTROPY_SOURCE_WEAK);
if (ret != 0) {
goto cleanup;
}
if ((ret = mbedtls_entropy_update_manual(&ctx, buf, sizeof(buf))) != 0) {
goto cleanup;
}
/*
* To test that mbedtls_entropy_func writes correct number of bytes:
* - use the whole buffer and rely on ASan to detect overruns
* - collect entropy 8 times and OR the result in an accumulator:
* any byte should then be 0 with probably 2^(-64), so requiring
* each of the 32 or 64 bytes to be non-zero has a false failure rate
* of at most 2^(-58) which is acceptable.
*/
for (i = 0; i < 8; i++) {
if ((ret = mbedtls_entropy_func(&ctx, buf, sizeof(buf))) != 0) {
goto cleanup;
}
for (j = 0; j < sizeof(buf); j++) {
acc[j] |= buf[j];
}
}
for (j = 0; j < sizeof(buf); j++) {
if (acc[j] == 0) {
ret = 1;
goto cleanup;
}
}
#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
if ((ret = mbedtls_entropy_source_self_test(0)) != 0) {
goto cleanup;
}
#endif
cleanup:
mbedtls_entropy_free(&ctx);
if (verbose != 0) {
if (ret != 0) {
mbedtls_printf("failed\n");
} else {
mbedtls_printf("passed\n");
}
mbedtls_printf("\n");
}
return ret != 0;
}
#endif /* MBEDTLS_SELF_TEST */
#endif /* MBEDTLS_ENTROPY_C */

View File

@@ -0,0 +1,231 @@
/*
* Platform-specific and custom entropy polling functions
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#if defined(__linux__) || defined(__midipix__)
/* Ensure that syscall() is available even when compiling with -std=c99 */
#if !defined(_GNU_SOURCE)
#define _GNU_SOURCE
#endif
#endif
#include "common.h"
#include <string.h>
#if defined(MBEDTLS_ENTROPY_C)
#include "mbedtls/entropy.h"
#include "entropy_poll.h"
#include "mbedtls/error.h"
#if defined(MBEDTLS_TIMING_C)
#include "mbedtls/timing.h"
#endif
#include "mbedtls/platform.h"
#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
!defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \
!defined(__HAIKU__) && !defined(__midipix__) && !defined(__MVS__)
#error \
"Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in mbedtls_config.h"
#endif
#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
#include <windows.h>
#include <bcrypt.h>
#include <intsafe.h>
int mbedtls_platform_entropy_poll(void *data, unsigned char *output, size_t len,
size_t *olen)
{
((void) data);
*olen = 0;
/*
* BCryptGenRandom takes ULONG for size, which is smaller than size_t on
* 64-bit Windows platforms. Extract entropy in chunks of len (dependent
* on ULONG_MAX) size.
*/
while (len != 0) {
unsigned long ulong_bytes =
(len > ULONG_MAX) ? ULONG_MAX : (unsigned long) len;
if (!BCRYPT_SUCCESS(BCryptGenRandom(NULL, output, ulong_bytes,
BCRYPT_USE_SYSTEM_PREFERRED_RNG))) {
return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
}
*olen += ulong_bytes;
len -= ulong_bytes;
}
return 0;
}
#else /* _WIN32 && !EFIX64 && !EFI32 */
/*
* Test for Linux getrandom() support.
* Since there is no wrapper in the libc yet, use the generic syscall wrapper
* available in GNU libc and compatible libc's (eg uClibc).
*/
#if ((defined(__linux__) && defined(__GLIBC__)) || defined(__midipix__))
#include <unistd.h>
#include <sys/syscall.h>
#if defined(SYS_getrandom)
#define HAVE_GETRANDOM
#include <errno.h>
static int getrandom_wrapper(void *buf, size_t buflen, unsigned int flags)
{
/* MemSan cannot understand that the syscall writes to the buffer */
#if defined(__has_feature)
#if __has_feature(memory_sanitizer)
memset(buf, 0, buflen);
#endif
#endif
return (int) syscall(SYS_getrandom, buf, buflen, flags);
}
#endif /* SYS_getrandom */
#endif /* __linux__ || __midipix__ */
#if defined(__FreeBSD__) || defined(__DragonFly__)
#include <sys/param.h>
#if (defined(__FreeBSD__) && __FreeBSD_version >= 1200000) || \
(defined(__DragonFly__) && __DragonFly_version >= 500700)
#include <errno.h>
#include <sys/random.h>
#define HAVE_GETRANDOM
static int getrandom_wrapper(void *buf, size_t buflen, unsigned int flags)
{
return (int) getrandom(buf, buflen, flags);
}
#endif /* (__FreeBSD__ && __FreeBSD_version >= 1200000) ||
(__DragonFly__ && __DragonFly_version >= 500700) */
#endif /* __FreeBSD__ || __DragonFly__ */
/*
* Some BSD systems provide KERN_ARND.
* This is equivalent to reading from /dev/urandom, only it doesn't require an
* open file descriptor, and provides up to 256 bytes per call (basically the
* same as getentropy(), but with a longer history).
*
* Documentation: https://netbsd.gw.com/cgi-bin/man-cgi?sysctl+7
*/
#if (defined(__FreeBSD__) || defined(__NetBSD__)) && !defined(HAVE_GETRANDOM)
#include <sys/param.h>
#include <sys/sysctl.h>
#if defined(KERN_ARND)
#define HAVE_SYSCTL_ARND
static int sysctl_arnd_wrapper(unsigned char *buf, size_t buflen)
{
int name[2];
size_t len;
name[0] = CTL_KERN;
name[1] = KERN_ARND;
while (buflen > 0) {
len = buflen > 256 ? 256 : buflen;
if (sysctl(name, 2, buf, &len, NULL, 0) == -1) {
return -1;
}
buflen -= len;
buf += len;
}
return 0;
}
#endif /* KERN_ARND */
#endif /* __FreeBSD__ || __NetBSD__ */
#include <stdio.h>
int mbedtls_platform_entropy_poll(void *data,
unsigned char *output, size_t len, size_t *olen)
{
FILE *file;
size_t read_len;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
((void) data);
#if defined(HAVE_GETRANDOM)
ret = getrandom_wrapper(output, len, 0);
if (ret >= 0) {
*olen = (size_t) ret;
return 0;
} else if (errno != ENOSYS) {
return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
}
/* Fall through if the system call isn't known. */
#else
((void) ret);
#endif /* HAVE_GETRANDOM */
#if defined(HAVE_SYSCTL_ARND)
((void) file);
((void) read_len);
if (sysctl_arnd_wrapper(output, len) == -1) {
return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
}
*olen = len;
return 0;
#else
*olen = 0;
file = fopen("/dev/urandom", "rb");
if (file == NULL) {
return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
}
/* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
mbedtls_setbuf(file, NULL);
read_len = fread(output, 1, len, file);
if (read_len != len) {
fclose(file);
return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
}
fclose(file);
*olen = len;
return 0;
#endif /* HAVE_SYSCTL_ARND */
}
#endif /* _WIN32 && !EFIX64 && !EFI32 */
#endif /* !MBEDTLS_NO_PLATFORM_ENTROPY */
#if defined(MBEDTLS_ENTROPY_NV_SEED)
int mbedtls_nv_seed_poll(void *data,
unsigned char *output, size_t len, size_t *olen)
{
unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
size_t use_len = MBEDTLS_ENTROPY_BLOCK_SIZE;
((void) data);
memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE);
if (mbedtls_nv_seed_read(buf, MBEDTLS_ENTROPY_BLOCK_SIZE) < 0) {
return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
}
if (len < use_len) {
use_len = len;
}
memcpy(output, buf, use_len);
*olen = use_len;
return 0;
}
#endif /* MBEDTLS_ENTROPY_NV_SEED */
#endif /* MBEDTLS_ENTROPY_C */

View File

@@ -0,0 +1,64 @@
/**
* \file entropy_poll.h
*
* \brief Platform-specific and custom entropy polling functions
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef MBEDTLS_ENTROPY_POLL_H
#define MBEDTLS_ENTROPY_POLL_H
#include "mbedtls/build_info.h"
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Default thresholds for built-in sources, in bytes
*/
#define MBEDTLS_ENTROPY_MIN_PLATFORM 32 /**< Minimum for platform source */
#if !defined(MBEDTLS_ENTROPY_MIN_HARDWARE)
#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Minimum for the hardware source */
#endif
#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
/**
* \brief Platform-specific entropy poll callback
*/
int mbedtls_platform_entropy_poll(void *data,
unsigned char *output, size_t len, size_t *olen);
#endif
#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
/**
* \brief Entropy poll callback for a hardware source
*
* \warning This is not provided by Mbed TLS!
* See \c MBEDTLS_ENTROPY_HARDWARE_ALT in mbedtls_config.h.
*
* \note This must accept NULL as its first argument.
*/
int mbedtls_hardware_poll(void *data,
unsigned char *output, size_t len, size_t *olen);
#endif
#if defined(MBEDTLS_ENTROPY_NV_SEED)
/**
* \brief Entropy poll callback for a non-volatile seed file
*
* \note This must accept NULL as its first argument.
*/
int mbedtls_nv_seed_poll(void *data,
unsigned char *output, size_t len, size_t *olen);
#endif
#ifdef __cplusplus
}
#endif
#endif /* entropy_poll.h */

878
thirdparty/mbedtls/library/error.c vendored Normal file
View File

@@ -0,0 +1,878 @@
/*
* Error message information
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#include "mbedtls/error.h"
#if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY)
#if defined(MBEDTLS_ERROR_C)
#include "mbedtls/platform.h"
#include <stdio.h>
#include <string.h>
#if defined(MBEDTLS_AES_C)
#include "mbedtls/aes.h"
#endif
#if defined(MBEDTLS_ARIA_C)
#include "mbedtls/aria.h"
#endif
#if defined(MBEDTLS_ASN1_PARSE_C)
#include "mbedtls/asn1.h"
#endif
#if defined(MBEDTLS_BASE64_C)
#include "mbedtls/base64.h"
#endif
#if defined(MBEDTLS_BIGNUM_C)
#include "mbedtls/bignum.h"
#endif
#if defined(MBEDTLS_CAMELLIA_C)
#include "mbedtls/camellia.h"
#endif
#if defined(MBEDTLS_CCM_C)
#include "mbedtls/ccm.h"
#endif
#if defined(MBEDTLS_CHACHA20_C)
#include "mbedtls/chacha20.h"
#endif
#if defined(MBEDTLS_CHACHAPOLY_C)
#include "mbedtls/chachapoly.h"
#endif
#if defined(MBEDTLS_CIPHER_C)
#include "mbedtls/cipher.h"
#endif
#if defined(MBEDTLS_CTR_DRBG_C)
#include "mbedtls/ctr_drbg.h"
#endif
#if defined(MBEDTLS_DES_C)
#include "mbedtls/des.h"
#endif
#if defined(MBEDTLS_DHM_C)
#include "mbedtls/dhm.h"
#endif
#if defined(MBEDTLS_ECP_C)
#include "mbedtls/ecp.h"
#endif
#if defined(MBEDTLS_ENTROPY_C)
#include "mbedtls/entropy.h"
#endif
#if defined(MBEDTLS_ERROR_C)
#include "mbedtls/error.h"
#endif
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#endif
#if defined(MBEDTLS_GCM_C)
#include "mbedtls/gcm.h"
#endif
#if defined(MBEDTLS_HKDF_C)
#include "mbedtls/hkdf.h"
#endif
#if defined(MBEDTLS_HMAC_DRBG_C)
#include "mbedtls/hmac_drbg.h"
#endif
#if defined(MBEDTLS_LMS_C)
#include "mbedtls/lms.h"
#endif
#if defined(MBEDTLS_MD_C)
#include "mbedtls/md.h"
#endif
#if defined(MBEDTLS_NET_C)
#include "mbedtls/net_sockets.h"
#endif
#if defined(MBEDTLS_OID_C)
#include "mbedtls/oid.h"
#endif
#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C)
#include "mbedtls/pem.h"
#endif
#if defined(MBEDTLS_PK_C)
#include "mbedtls/pk.h"
#endif
#if defined(MBEDTLS_PKCS12_C)
#include "mbedtls/pkcs12.h"
#endif
#if defined(MBEDTLS_PKCS5_C)
#include "mbedtls/pkcs5.h"
#endif
#if defined(MBEDTLS_PKCS7_C)
#include "mbedtls/pkcs7.h"
#endif
#if defined(MBEDTLS_POLY1305_C)
#include "mbedtls/poly1305.h"
#endif
#if defined(MBEDTLS_RSA_C)
#include "mbedtls/rsa.h"
#endif
#if defined(MBEDTLS_SHA1_C)
#include "mbedtls/sha1.h"
#endif
#if defined(MBEDTLS_SHA256_C)
#include "mbedtls/sha256.h"
#endif
#if defined(MBEDTLS_SHA3_C)
#include "mbedtls/sha3.h"
#endif
#if defined(MBEDTLS_SHA512_C)
#include "mbedtls/sha512.h"
#endif
#if defined(MBEDTLS_SSL_TLS_C)
#include "mbedtls/ssl.h"
#endif
#if defined(MBEDTLS_THREADING_C)
#include "mbedtls/threading.h"
#endif
#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
#include "mbedtls/x509.h"
#endif
const char *mbedtls_high_level_strerr(int error_code)
{
int high_level_error_code;
if (error_code < 0) {
error_code = -error_code;
}
/* Extract the high-level part from the error code. */
high_level_error_code = error_code & 0xFF80;
switch (high_level_error_code) {
/* Begin Auto-Generated Code. */
#if defined(MBEDTLS_CIPHER_C)
case -(MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE):
return( "CIPHER - The selected feature is not available" );
case -(MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA):
return( "CIPHER - Bad input parameters" );
case -(MBEDTLS_ERR_CIPHER_ALLOC_FAILED):
return( "CIPHER - Failed to allocate memory" );
case -(MBEDTLS_ERR_CIPHER_INVALID_PADDING):
return( "CIPHER - Input data contains invalid padding and is rejected" );
case -(MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED):
return( "CIPHER - Decryption of block requires a full block" );
case -(MBEDTLS_ERR_CIPHER_AUTH_FAILED):
return( "CIPHER - Authentication failed (for AEAD modes)" );
case -(MBEDTLS_ERR_CIPHER_INVALID_CONTEXT):
return( "CIPHER - The context is invalid. For example, because it was freed" );
#endif /* MBEDTLS_CIPHER_C */
#if defined(MBEDTLS_DHM_C)
case -(MBEDTLS_ERR_DHM_BAD_INPUT_DATA):
return( "DHM - Bad input parameters" );
case -(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED):
return( "DHM - Reading of the DHM parameters failed" );
case -(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED):
return( "DHM - Making of the DHM parameters failed" );
case -(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED):
return( "DHM - Reading of the public values failed" );
case -(MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED):
return( "DHM - Making of the public value failed" );
case -(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED):
return( "DHM - Calculation of the DHM secret failed" );
case -(MBEDTLS_ERR_DHM_INVALID_FORMAT):
return( "DHM - The ASN.1 data is not formatted correctly" );
case -(MBEDTLS_ERR_DHM_ALLOC_FAILED):
return( "DHM - Allocation of memory failed" );
case -(MBEDTLS_ERR_DHM_FILE_IO_ERROR):
return( "DHM - Read or write of file failed" );
case -(MBEDTLS_ERR_DHM_SET_GROUP_FAILED):
return( "DHM - Setting the modulus and generator failed" );
#endif /* MBEDTLS_DHM_C */
#if defined(MBEDTLS_ECP_C)
case -(MBEDTLS_ERR_ECP_BAD_INPUT_DATA):
return( "ECP - Bad input parameters to function" );
case -(MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL):
return( "ECP - The buffer is too small to write to" );
case -(MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE):
return( "ECP - The requested feature is not available, for example, the requested curve is not supported" );
case -(MBEDTLS_ERR_ECP_VERIFY_FAILED):
return( "ECP - The signature is not valid" );
case -(MBEDTLS_ERR_ECP_ALLOC_FAILED):
return( "ECP - Memory allocation failed" );
case -(MBEDTLS_ERR_ECP_RANDOM_FAILED):
return( "ECP - Generation of random value, such as ephemeral key, failed" );
case -(MBEDTLS_ERR_ECP_INVALID_KEY):
return( "ECP - Invalid private or public key" );
case -(MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH):
return( "ECP - The buffer contains a valid signature followed by more data" );
case -(MBEDTLS_ERR_ECP_IN_PROGRESS):
return( "ECP - Operation in progress, call again with the same parameters to continue" );
#endif /* MBEDTLS_ECP_C */
#if defined(MBEDTLS_MD_C)
case -(MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE):
return( "MD - The selected feature is not available" );
case -(MBEDTLS_ERR_MD_BAD_INPUT_DATA):
return( "MD - Bad input parameters to function" );
case -(MBEDTLS_ERR_MD_ALLOC_FAILED):
return( "MD - Failed to allocate memory" );
case -(MBEDTLS_ERR_MD_FILE_IO_ERROR):
return( "MD - Opening or reading of file failed" );
#endif /* MBEDTLS_MD_C */
#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C)
case -(MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT):
return( "PEM - No PEM header or footer found" );
case -(MBEDTLS_ERR_PEM_INVALID_DATA):
return( "PEM - PEM string is not as expected" );
case -(MBEDTLS_ERR_PEM_ALLOC_FAILED):
return( "PEM - Failed to allocate memory" );
case -(MBEDTLS_ERR_PEM_INVALID_ENC_IV):
return( "PEM - RSA IV is not in hex-format" );
case -(MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG):
return( "PEM - Unsupported key encryption algorithm" );
case -(MBEDTLS_ERR_PEM_PASSWORD_REQUIRED):
return( "PEM - Private key password can't be empty" );
case -(MBEDTLS_ERR_PEM_PASSWORD_MISMATCH):
return( "PEM - Given private key password does not allow for correct decryption" );
case -(MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE):
return( "PEM - Unavailable feature, e.g. hashing/encryption combination" );
case -(MBEDTLS_ERR_PEM_BAD_INPUT_DATA):
return( "PEM - Bad input parameters to function" );
#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */
#if defined(MBEDTLS_PK_C)
case -(MBEDTLS_ERR_PK_ALLOC_FAILED):
return( "PK - Memory allocation failed" );
case -(MBEDTLS_ERR_PK_TYPE_MISMATCH):
return( "PK - Type mismatch, eg attempt to encrypt with an ECDSA key" );
case -(MBEDTLS_ERR_PK_BAD_INPUT_DATA):
return( "PK - Bad input parameters to function" );
case -(MBEDTLS_ERR_PK_FILE_IO_ERROR):
return( "PK - Read/write of file failed" );
case -(MBEDTLS_ERR_PK_KEY_INVALID_VERSION):
return( "PK - Unsupported key version" );
case -(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT):
return( "PK - Invalid key tag or value" );
case -(MBEDTLS_ERR_PK_UNKNOWN_PK_ALG):
return( "PK - Key algorithm is unsupported (only RSA and EC are supported)" );
case -(MBEDTLS_ERR_PK_PASSWORD_REQUIRED):
return( "PK - Private key password can't be empty" );
case -(MBEDTLS_ERR_PK_PASSWORD_MISMATCH):
return( "PK - Given private key password does not allow for correct decryption" );
case -(MBEDTLS_ERR_PK_INVALID_PUBKEY):
return( "PK - The pubkey tag or value is invalid (only RSA and EC are supported)" );
case -(MBEDTLS_ERR_PK_INVALID_ALG):
return( "PK - The algorithm tag or value is invalid" );
case -(MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE):
return( "PK - Elliptic curve is unsupported (only NIST curves are supported)" );
case -(MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE):
return( "PK - Unavailable feature, e.g. RSA disabled for RSA key" );
case -(MBEDTLS_ERR_PK_SIG_LEN_MISMATCH):
return( "PK - The buffer contains a valid signature followed by more data" );
case -(MBEDTLS_ERR_PK_BUFFER_TOO_SMALL):
return( "PK - The output buffer is too small" );
#endif /* MBEDTLS_PK_C */
#if defined(MBEDTLS_PKCS12_C)
case -(MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA):
return( "PKCS12 - Bad input parameters to function" );
case -(MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE):
return( "PKCS12 - Feature not available, e.g. unsupported encryption scheme" );
case -(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT):
return( "PKCS12 - PBE ASN.1 data not as expected" );
case -(MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH):
return( "PKCS12 - Given private key password does not allow for correct decryption" );
#endif /* MBEDTLS_PKCS12_C */
#if defined(MBEDTLS_PKCS5_C)
case -(MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA):
return( "PKCS5 - Bad input parameters to function" );
case -(MBEDTLS_ERR_PKCS5_INVALID_FORMAT):
return( "PKCS5 - Unexpected ASN.1 data" );
case -(MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE):
return( "PKCS5 - Requested encryption or digest alg not available" );
case -(MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH):
return( "PKCS5 - Given private key password does not allow for correct decryption" );
#endif /* MBEDTLS_PKCS5_C */
#if defined(MBEDTLS_PKCS7_C)
case -(MBEDTLS_ERR_PKCS7_INVALID_FORMAT):
return( "PKCS7 - The format is invalid, e.g. different type expected" );
case -(MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE):
return( "PKCS7 - Unavailable feature, e.g. anything other than signed data" );
case -(MBEDTLS_ERR_PKCS7_INVALID_VERSION):
return( "PKCS7 - The PKCS #7 version element is invalid or cannot be parsed" );
case -(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO):
return( "PKCS7 - The PKCS #7 content info is invalid or cannot be parsed" );
case -(MBEDTLS_ERR_PKCS7_INVALID_ALG):
return( "PKCS7 - The algorithm tag or value is invalid or cannot be parsed" );
case -(MBEDTLS_ERR_PKCS7_INVALID_CERT):
return( "PKCS7 - The certificate tag or value is invalid or cannot be parsed" );
case -(MBEDTLS_ERR_PKCS7_INVALID_SIGNATURE):
return( "PKCS7 - Error parsing the signature" );
case -(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO):
return( "PKCS7 - Error parsing the signer's info" );
case -(MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA):
return( "PKCS7 - Input invalid" );
case -(MBEDTLS_ERR_PKCS7_ALLOC_FAILED):
return( "PKCS7 - Allocation of memory failed" );
case -(MBEDTLS_ERR_PKCS7_VERIFY_FAIL):
return( "PKCS7 - Verification Failed" );
case -(MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID):
return( "PKCS7 - The PKCS #7 date issued/expired dates are invalid" );
#endif /* MBEDTLS_PKCS7_C */
#if defined(MBEDTLS_RSA_C)
case -(MBEDTLS_ERR_RSA_BAD_INPUT_DATA):
return( "RSA - Bad input parameters to function" );
case -(MBEDTLS_ERR_RSA_INVALID_PADDING):
return( "RSA - Input data contains invalid padding and is rejected" );
case -(MBEDTLS_ERR_RSA_KEY_GEN_FAILED):
return( "RSA - Something failed during generation of a key" );
case -(MBEDTLS_ERR_RSA_KEY_CHECK_FAILED):
return( "RSA - Key failed to pass the validity check of the library" );
case -(MBEDTLS_ERR_RSA_PUBLIC_FAILED):
return( "RSA - The public key operation failed" );
case -(MBEDTLS_ERR_RSA_PRIVATE_FAILED):
return( "RSA - The private key operation failed" );
case -(MBEDTLS_ERR_RSA_VERIFY_FAILED):
return( "RSA - The PKCS#1 verification failed" );
case -(MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE):
return( "RSA - The output buffer for decryption is not large enough" );
case -(MBEDTLS_ERR_RSA_RNG_FAILED):
return( "RSA - The random generator failed to generate non-zeros" );
#endif /* MBEDTLS_RSA_C */
#if defined(MBEDTLS_SSL_TLS_C)
case -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS):
return( "SSL - A cryptographic operation is in progress. Try again later" );
case -(MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE):
return( "SSL - The requested feature is not available" );
case -(MBEDTLS_ERR_SSL_BAD_INPUT_DATA):
return( "SSL - Bad input parameters to function" );
case -(MBEDTLS_ERR_SSL_INVALID_MAC):
return( "SSL - Verification of the message MAC failed" );
case -(MBEDTLS_ERR_SSL_INVALID_RECORD):
return( "SSL - An invalid SSL record was received" );
case -(MBEDTLS_ERR_SSL_CONN_EOF):
return( "SSL - The connection indicated an EOF" );
case -(MBEDTLS_ERR_SSL_DECODE_ERROR):
return( "SSL - A message could not be parsed due to a syntactic error" );
case -(MBEDTLS_ERR_SSL_NO_RNG):
return( "SSL - No RNG was provided to the SSL module" );
case -(MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE):
return( "SSL - No client certification received from the client, but required by the authentication mode" );
case -(MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION):
return( "SSL - Client received an extended server hello containing an unsupported extension" );
case -(MBEDTLS_ERR_SSL_NO_APPLICATION_PROTOCOL):
return( "SSL - No ALPN protocols supported that the client advertises" );
case -(MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED):
return( "SSL - The own private key or pre-shared key is not set, but needed" );
case -(MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED):
return( "SSL - No CA Chain is set, but required to operate" );
case -(MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE):
return( "SSL - An unexpected message was received from our peer" );
case -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE):
return( "SSL - A fatal alert message was received from our peer" );
case -(MBEDTLS_ERR_SSL_UNRECOGNIZED_NAME):
return( "SSL - No server could be identified matching the client's SNI" );
case -(MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY):
return( "SSL - The peer notified us that the connection is going to be closed" );
case -(MBEDTLS_ERR_SSL_BAD_CERTIFICATE):
return( "SSL - Processing of the Certificate handshake message failed" );
case -(MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET):
return( "SSL - A TLS 1.3 NewSessionTicket message has been received" );
case -(MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA):
return( "SSL - Not possible to read early data" );
case -(MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA):
return( "SSL - * Early data has been received as part of an on-going handshake. This error code can be returned only on server side if and only if early data has been enabled by means of the mbedtls_ssl_conf_early_data() API. This error code can then be returned by mbedtls_ssl_handshake(), mbedtls_ssl_handshake_step(), mbedtls_ssl_read() or mbedtls_ssl_write() if early data has been received as part of the handshake sequence they triggered. To read the early data, call mbedtls_ssl_read_early_data()" );
case -(MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA):
return( "SSL - Not possible to write early data" );
case -(MBEDTLS_ERR_SSL_CACHE_ENTRY_NOT_FOUND):
return( "SSL - Cache entry not found" );
case -(MBEDTLS_ERR_SSL_ALLOC_FAILED):
return( "SSL - Memory allocation failed" );
case -(MBEDTLS_ERR_SSL_HW_ACCEL_FAILED):
return( "SSL - Hardware acceleration function returned with error" );
case -(MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH):
return( "SSL - Hardware acceleration function skipped / left alone data" );
case -(MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION):
return( "SSL - Handshake protocol not within min/max boundaries" );
case -(MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE):
return( "SSL - The handshake negotiation failed" );
case -(MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED):
return( "SSL - Session ticket has expired" );
case -(MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH):
return( "SSL - Public key type mismatch (eg, asked for RSA key exchange and presented EC key)" );
case -(MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY):
return( "SSL - Unknown identity received (eg, PSK identity)" );
case -(MBEDTLS_ERR_SSL_INTERNAL_ERROR):
return( "SSL - Internal error (eg, unexpected failure in lower-level module)" );
case -(MBEDTLS_ERR_SSL_COUNTER_WRAPPING):
return( "SSL - A counter would wrap (eg, too many messages exchanged)" );
case -(MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO):
return( "SSL - Unexpected message at ServerHello in renegotiation" );
case -(MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED):
return( "SSL - DTLS client must retry for hello verification" );
case -(MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL):
return( "SSL - A buffer is too small to receive or write a message" );
case -(MBEDTLS_ERR_SSL_WANT_READ):
return( "SSL - No data of requested type currently available on underlying transport" );
case -(MBEDTLS_ERR_SSL_WANT_WRITE):
return( "SSL - Connection requires a write call" );
case -(MBEDTLS_ERR_SSL_TIMEOUT):
return( "SSL - The operation timed out" );
case -(MBEDTLS_ERR_SSL_CLIENT_RECONNECT):
return( "SSL - The client initiated a reconnect from the same port" );
case -(MBEDTLS_ERR_SSL_UNEXPECTED_RECORD):
return( "SSL - Record header looks valid but is not expected" );
case -(MBEDTLS_ERR_SSL_NON_FATAL):
return( "SSL - The alert message received indicates a non-fatal error" );
case -(MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER):
return( "SSL - A field in a message was incorrect or inconsistent with other fields" );
case -(MBEDTLS_ERR_SSL_CONTINUE_PROCESSING):
return( "SSL - Internal-only message signaling that further message-processing should be done" );
case -(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS):
return( "SSL - The asynchronous operation is not completed yet" );
case -(MBEDTLS_ERR_SSL_EARLY_MESSAGE):
return( "SSL - Internal-only message signaling that a message arrived early" );
case -(MBEDTLS_ERR_SSL_UNEXPECTED_CID):
return( "SSL - An encrypted DTLS-frame with an unexpected CID was received" );
case -(MBEDTLS_ERR_SSL_VERSION_MISMATCH):
return( "SSL - An operation failed due to an unexpected version or configuration" );
case -(MBEDTLS_ERR_SSL_BAD_CONFIG):
return( "SSL - Invalid value in SSL config" );
case -(MBEDTLS_ERR_SSL_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME):
return( "SSL - Attempt to verify a certificate without an expected hostname. This is usually insecure. In TLS clients, when a client authenticates a server through its certificate, the client normally checks three things: - the certificate chain must be valid; - the chain must start from a trusted CA; - the certificate must cover the server name that is expected by the client. Omitting any of these checks is generally insecure, and can allow a malicious server to impersonate a legitimate server. The third check may be safely skipped in some unusual scenarios, such as networks where eavesdropping is a risk but not active attacks, or a private PKI where the client equally trusts all servers that are accredited by the root CA. You should call mbedtls_ssl_set_hostname() with the expected server name before starting a TLS handshake on a client (unless the client is set up to only use PSK-based authentication, which does not rely on the host name). If you have determined that server name verification is not required for security in your scenario, call mbedtls_ssl_set_hostname() with \\p NULL as the server name. This error is raised if all of the following conditions are met: - A TLS client is configured with the authentication mode #MBEDTLS_SSL_VERIFY_REQUIRED (default). - Certificate authentication is enabled. - The client does not call mbedtls_ssl_set_hostname(). - The configuration option #MBEDTLS_SSL_CLI_ALLOW_WEAK_CERTIFICATE_VERIFICATION_WITHOUT_HOSTNAME is not enabled" );
#endif /* MBEDTLS_SSL_TLS_C */
#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
case -(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE):
return( "X509 - Unavailable feature, e.g. RSA hashing/encryption combination" );
case -(MBEDTLS_ERR_X509_UNKNOWN_OID):
return( "X509 - Requested OID is unknown" );
case -(MBEDTLS_ERR_X509_INVALID_FORMAT):
return( "X509 - The CRT/CRL/CSR format is invalid, e.g. different type expected" );
case -(MBEDTLS_ERR_X509_INVALID_VERSION):
return( "X509 - The CRT/CRL/CSR version element is invalid" );
case -(MBEDTLS_ERR_X509_INVALID_SERIAL):
return( "X509 - The serial tag or value is invalid" );
case -(MBEDTLS_ERR_X509_INVALID_ALG):
return( "X509 - The algorithm tag or value is invalid" );
case -(MBEDTLS_ERR_X509_INVALID_NAME):
return( "X509 - The name tag or value is invalid" );
case -(MBEDTLS_ERR_X509_INVALID_DATE):
return( "X509 - The date tag or value is invalid" );
case -(MBEDTLS_ERR_X509_INVALID_SIGNATURE):
return( "X509 - The signature tag or value invalid" );
case -(MBEDTLS_ERR_X509_INVALID_EXTENSIONS):
return( "X509 - The extension tag or value is invalid" );
case -(MBEDTLS_ERR_X509_UNKNOWN_VERSION):
return( "X509 - CRT/CRL/CSR has an unsupported version number" );
case -(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG):
return( "X509 - Signature algorithm (oid) is unsupported" );
case -(MBEDTLS_ERR_X509_SIG_MISMATCH):
return( "X509 - Signature algorithms do not match. (see \\c ::mbedtls_x509_crt sig_oid)" );
case -(MBEDTLS_ERR_X509_CERT_VERIFY_FAILED):
return( "X509 - Certificate verification failed, e.g. CRL, CA or signature check failed" );
case -(MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT):
return( "X509 - Format not recognized as DER or PEM" );
case -(MBEDTLS_ERR_X509_BAD_INPUT_DATA):
return( "X509 - Input invalid" );
case -(MBEDTLS_ERR_X509_ALLOC_FAILED):
return( "X509 - Allocation of memory failed" );
case -(MBEDTLS_ERR_X509_FILE_IO_ERROR):
return( "X509 - Read/write of file failed" );
case -(MBEDTLS_ERR_X509_BUFFER_TOO_SMALL):
return( "X509 - Destination buffer is too small" );
case -(MBEDTLS_ERR_X509_FATAL_ERROR):
return( "X509 - A fatal error occurred, eg the chain is too long or the vrfy callback failed" );
#endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */
/* End Auto-Generated Code. */
default:
break;
}
return NULL;
}
const char *mbedtls_low_level_strerr(int error_code)
{
int low_level_error_code;
if (error_code < 0) {
error_code = -error_code;
}
/* Extract the low-level part from the error code. */
low_level_error_code = error_code & ~0xFF80;
switch (low_level_error_code) {
/* Begin Auto-Generated Code. */
#if defined(MBEDTLS_AES_C)
case -(MBEDTLS_ERR_AES_INVALID_KEY_LENGTH):
return( "AES - Invalid key length" );
case -(MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH):
return( "AES - Invalid data input length" );
case -(MBEDTLS_ERR_AES_BAD_INPUT_DATA):
return( "AES - Invalid input data" );
#endif /* MBEDTLS_AES_C */
#if defined(MBEDTLS_ARIA_C)
case -(MBEDTLS_ERR_ARIA_BAD_INPUT_DATA):
return( "ARIA - Bad input data" );
case -(MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH):
return( "ARIA - Invalid data input length" );
#endif /* MBEDTLS_ARIA_C */
#if defined(MBEDTLS_ASN1_PARSE_C)
case -(MBEDTLS_ERR_ASN1_OUT_OF_DATA):
return( "ASN1 - Out of data when parsing an ASN1 data structure" );
case -(MBEDTLS_ERR_ASN1_UNEXPECTED_TAG):
return( "ASN1 - ASN1 tag was of an unexpected value" );
case -(MBEDTLS_ERR_ASN1_INVALID_LENGTH):
return( "ASN1 - Error when trying to determine the length or invalid length" );
case -(MBEDTLS_ERR_ASN1_LENGTH_MISMATCH):
return( "ASN1 - Actual length differs from expected length" );
case -(MBEDTLS_ERR_ASN1_INVALID_DATA):
return( "ASN1 - Data is invalid" );
case -(MBEDTLS_ERR_ASN1_ALLOC_FAILED):
return( "ASN1 - Memory allocation failed" );
case -(MBEDTLS_ERR_ASN1_BUF_TOO_SMALL):
return( "ASN1 - Buffer too small when writing ASN.1 data structure" );
#endif /* MBEDTLS_ASN1_PARSE_C */
#if defined(MBEDTLS_BASE64_C)
case -(MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL):
return( "BASE64 - Output buffer too small" );
case -(MBEDTLS_ERR_BASE64_INVALID_CHARACTER):
return( "BASE64 - Invalid character in input" );
#endif /* MBEDTLS_BASE64_C */
#if defined(MBEDTLS_BIGNUM_C)
case -(MBEDTLS_ERR_MPI_FILE_IO_ERROR):
return( "BIGNUM - An error occurred while reading from or writing to a file" );
case -(MBEDTLS_ERR_MPI_BAD_INPUT_DATA):
return( "BIGNUM - Bad input parameters to function" );
case -(MBEDTLS_ERR_MPI_INVALID_CHARACTER):
return( "BIGNUM - There is an invalid character in the digit string" );
case -(MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL):
return( "BIGNUM - The buffer is too small to write to" );
case -(MBEDTLS_ERR_MPI_NEGATIVE_VALUE):
return( "BIGNUM - The input arguments are negative or result in illegal output" );
case -(MBEDTLS_ERR_MPI_DIVISION_BY_ZERO):
return( "BIGNUM - The input argument for division is zero, which is not allowed" );
case -(MBEDTLS_ERR_MPI_NOT_ACCEPTABLE):
return( "BIGNUM - The input arguments are not acceptable" );
case -(MBEDTLS_ERR_MPI_ALLOC_FAILED):
return( "BIGNUM - Memory allocation failed" );
#endif /* MBEDTLS_BIGNUM_C */
#if defined(MBEDTLS_CAMELLIA_C)
case -(MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA):
return( "CAMELLIA - Bad input data" );
case -(MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH):
return( "CAMELLIA - Invalid data input length" );
#endif /* MBEDTLS_CAMELLIA_C */
#if defined(MBEDTLS_CCM_C)
case -(MBEDTLS_ERR_CCM_BAD_INPUT):
return( "CCM - Bad input parameters to the function" );
case -(MBEDTLS_ERR_CCM_AUTH_FAILED):
return( "CCM - Authenticated decryption failed" );
#endif /* MBEDTLS_CCM_C */
#if defined(MBEDTLS_CHACHA20_C)
case -(MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA):
return( "CHACHA20 - Invalid input parameter(s)" );
#endif /* MBEDTLS_CHACHA20_C */
#if defined(MBEDTLS_CHACHAPOLY_C)
case -(MBEDTLS_ERR_CHACHAPOLY_BAD_STATE):
return( "CHACHAPOLY - The requested operation is not permitted in the current state" );
case -(MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED):
return( "CHACHAPOLY - Authenticated decryption failed: data was not authentic" );
#endif /* MBEDTLS_CHACHAPOLY_C */
#if defined(MBEDTLS_CTR_DRBG_C)
case -(MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED):
return( "CTR_DRBG - The entropy source failed" );
case -(MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG):
return( "CTR_DRBG - The requested random buffer length is too big" );
case -(MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG):
return( "CTR_DRBG - The input (entropy + additional data) is too large" );
case -(MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR):
return( "CTR_DRBG - Read or write error in file" );
#endif /* MBEDTLS_CTR_DRBG_C */
#if defined(MBEDTLS_DES_C)
case -(MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH):
return( "DES - The data input has an invalid length" );
#endif /* MBEDTLS_DES_C */
#if defined(MBEDTLS_ENTROPY_C)
case -(MBEDTLS_ERR_ENTROPY_SOURCE_FAILED):
return( "ENTROPY - Critical entropy source failure" );
case -(MBEDTLS_ERR_ENTROPY_MAX_SOURCES):
return( "ENTROPY - No more sources can be added" );
case -(MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED):
return( "ENTROPY - No sources have been added to poll" );
case -(MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE):
return( "ENTROPY - No strong sources have been added to poll" );
case -(MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR):
return( "ENTROPY - Read/write error in file" );
#endif /* MBEDTLS_ENTROPY_C */
#if defined(MBEDTLS_ERROR_C)
case -(MBEDTLS_ERR_ERROR_GENERIC_ERROR):
return( "ERROR - Generic error" );
case -(MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED):
return( "ERROR - This is a bug in the library" );
#endif /* MBEDTLS_ERROR_C */
#if defined(MBEDTLS_PLATFORM_C)
case -(MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED):
return( "PLATFORM - Hardware accelerator failed" );
case -(MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED):
return( "PLATFORM - The requested feature is not supported by the platform" );
#endif /* MBEDTLS_PLATFORM_C */
#if defined(MBEDTLS_GCM_C)
case -(MBEDTLS_ERR_GCM_AUTH_FAILED):
return( "GCM - Authenticated decryption failed" );
case -(MBEDTLS_ERR_GCM_BAD_INPUT):
return( "GCM - Bad input parameters to function" );
case -(MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL):
return( "GCM - An output buffer is too small" );
#endif /* MBEDTLS_GCM_C */
#if defined(MBEDTLS_HKDF_C)
case -(MBEDTLS_ERR_HKDF_BAD_INPUT_DATA):
return( "HKDF - Bad input parameters to function" );
#endif /* MBEDTLS_HKDF_C */
#if defined(MBEDTLS_HMAC_DRBG_C)
case -(MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG):
return( "HMAC_DRBG - Too many random requested in single call" );
case -(MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG):
return( "HMAC_DRBG - Input too large (Entropy + additional)" );
case -(MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR):
return( "HMAC_DRBG - Read/write error in file" );
case -(MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED):
return( "HMAC_DRBG - The entropy source failed" );
#endif /* MBEDTLS_HMAC_DRBG_C */
#if defined(MBEDTLS_LMS_C)
case -(MBEDTLS_ERR_LMS_BAD_INPUT_DATA):
return( "LMS - Bad data has been input to an LMS function" );
case -(MBEDTLS_ERR_LMS_OUT_OF_PRIVATE_KEYS):
return( "LMS - Specified LMS key has utilised all of its private keys" );
case -(MBEDTLS_ERR_LMS_VERIFY_FAILED):
return( "LMS - LMS signature verification failed" );
case -(MBEDTLS_ERR_LMS_ALLOC_FAILED):
return( "LMS - LMS failed to allocate space for a private key" );
case -(MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL):
return( "LMS - Input/output buffer is too small to contain requited data" );
#endif /* MBEDTLS_LMS_C */
#if defined(MBEDTLS_NET_C)
case -(MBEDTLS_ERR_NET_SOCKET_FAILED):
return( "NET - Failed to open a socket" );
case -(MBEDTLS_ERR_NET_CONNECT_FAILED):
return( "NET - The connection to the given server / port failed" );
case -(MBEDTLS_ERR_NET_BIND_FAILED):
return( "NET - Binding of the socket failed" );
case -(MBEDTLS_ERR_NET_LISTEN_FAILED):
return( "NET - Could not listen on the socket" );
case -(MBEDTLS_ERR_NET_ACCEPT_FAILED):
return( "NET - Could not accept the incoming connection" );
case -(MBEDTLS_ERR_NET_RECV_FAILED):
return( "NET - Reading information from the socket failed" );
case -(MBEDTLS_ERR_NET_SEND_FAILED):
return( "NET - Sending information through the socket failed" );
case -(MBEDTLS_ERR_NET_CONN_RESET):
return( "NET - Connection was reset by peer" );
case -(MBEDTLS_ERR_NET_UNKNOWN_HOST):
return( "NET - Failed to get an IP address for the given hostname" );
case -(MBEDTLS_ERR_NET_BUFFER_TOO_SMALL):
return( "NET - Buffer is too small to hold the data" );
case -(MBEDTLS_ERR_NET_INVALID_CONTEXT):
return( "NET - The context is invalid, eg because it was free()ed" );
case -(MBEDTLS_ERR_NET_POLL_FAILED):
return( "NET - Polling the net context failed" );
case -(MBEDTLS_ERR_NET_BAD_INPUT_DATA):
return( "NET - Input invalid" );
#endif /* MBEDTLS_NET_C */
#if defined(MBEDTLS_OID_C)
case -(MBEDTLS_ERR_OID_NOT_FOUND):
return( "OID - OID is not found" );
case -(MBEDTLS_ERR_OID_BUF_TOO_SMALL):
return( "OID - output buffer is too small" );
#endif /* MBEDTLS_OID_C */
#if defined(MBEDTLS_POLY1305_C)
case -(MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA):
return( "POLY1305 - Invalid input parameter(s)" );
#endif /* MBEDTLS_POLY1305_C */
#if defined(MBEDTLS_SHA1_C)
case -(MBEDTLS_ERR_SHA1_BAD_INPUT_DATA):
return( "SHA1 - SHA-1 input data was malformed" );
#endif /* MBEDTLS_SHA1_C */
#if defined(MBEDTLS_SHA256_C)
case -(MBEDTLS_ERR_SHA256_BAD_INPUT_DATA):
return( "SHA256 - SHA-256 input data was malformed" );
#endif /* MBEDTLS_SHA256_C */
#if defined(MBEDTLS_SHA3_C)
case -(MBEDTLS_ERR_SHA3_BAD_INPUT_DATA):
return( "SHA3 - SHA-3 input data was malformed" );
#endif /* MBEDTLS_SHA3_C */
#if defined(MBEDTLS_SHA512_C)
case -(MBEDTLS_ERR_SHA512_BAD_INPUT_DATA):
return( "SHA512 - SHA-512 input data was malformed" );
#endif /* MBEDTLS_SHA512_C */
#if defined(MBEDTLS_THREADING_C)
case -(MBEDTLS_ERR_THREADING_BAD_INPUT_DATA):
return( "THREADING - Bad input parameters to function" );
case -(MBEDTLS_ERR_THREADING_MUTEX_ERROR):
return( "THREADING - Locking / unlocking / free failed with error code" );
#endif /* MBEDTLS_THREADING_C */
/* End Auto-Generated Code. */
default:
break;
}
return NULL;
}
void mbedtls_strerror(int ret, char *buf, size_t buflen)
{
size_t len;
int use_ret;
const char *high_level_error_description = NULL;
const char *low_level_error_description = NULL;
if (buflen == 0) {
return;
}
memset(buf, 0x00, buflen);
if (ret < 0) {
ret = -ret;
}
if (ret & 0xFF80) {
use_ret = ret & 0xFF80;
// Translate high level error code.
high_level_error_description = mbedtls_high_level_strerr(ret);
if (high_level_error_description == NULL) {
mbedtls_snprintf(buf, buflen, "UNKNOWN ERROR CODE (%04X)", (unsigned int) use_ret);
} else {
mbedtls_snprintf(buf, buflen, "%s", high_level_error_description);
}
#if defined(MBEDTLS_SSL_TLS_C)
// Early return in case of a fatal error - do not try to translate low
// level code.
if (use_ret == -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE)) {
return;
}
#endif /* MBEDTLS_SSL_TLS_C */
}
use_ret = ret & ~0xFF80;
if (use_ret == 0) {
return;
}
// If high level code is present, make a concatenation between both
// error strings.
//
len = strlen(buf);
if (len > 0) {
if (buflen - len < 5) {
return;
}
mbedtls_snprintf(buf + len, buflen - len, " : ");
buf += len + 3;
buflen -= len + 3;
}
// Translate low level error code.
low_level_error_description = mbedtls_low_level_strerr(ret);
if (low_level_error_description == NULL) {
mbedtls_snprintf(buf, buflen, "UNKNOWN ERROR CODE (%04X)", (unsigned int) use_ret);
} else {
mbedtls_snprintf(buf, buflen, "%s", low_level_error_description);
}
}
#else /* MBEDTLS_ERROR_C */
/*
* Provide a dummy implementation when MBEDTLS_ERROR_C is not defined
*/
void mbedtls_strerror(int ret, char *buf, size_t buflen)
{
((void) ret);
if (buflen > 0) {
buf[0] = '\0';
}
}
#endif /* MBEDTLS_ERROR_C */
#endif /* MBEDTLS_ERROR_C || MBEDTLS_ERROR_STRERROR_DUMMY */

1330
thirdparty/mbedtls/library/gcm.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,17 @@
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include <stdio.h>
#include <string.h>
#include <stddef.h>
#ifdef MBEDTLS_PLATFORM_ZEROIZE_ALT
static void *(*const volatile memset_func)(void *, int, size_t) = memset;
void mbedtls_platform_zeroize(void *buf, size_t len) {
memset_func( buf, 0, len );
}
#endif

161
thirdparty/mbedtls/library/hkdf.c vendored Normal file
View File

@@ -0,0 +1,161 @@
/*
* HKDF implementation -- RFC 5869
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#if defined(MBEDTLS_HKDF_C)
#include <string.h>
#include "mbedtls/hkdf.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
int mbedtls_hkdf(const mbedtls_md_info_t *md, const unsigned char *salt,
size_t salt_len, const unsigned char *ikm, size_t ikm_len,
const unsigned char *info, size_t info_len,
unsigned char *okm, size_t okm_len)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char prk[MBEDTLS_MD_MAX_SIZE];
ret = mbedtls_hkdf_extract(md, salt, salt_len, ikm, ikm_len, prk);
if (ret == 0) {
ret = mbedtls_hkdf_expand(md, prk, mbedtls_md_get_size(md),
info, info_len, okm, okm_len);
}
mbedtls_platform_zeroize(prk, sizeof(prk));
return ret;
}
int mbedtls_hkdf_extract(const mbedtls_md_info_t *md,
const unsigned char *salt, size_t salt_len,
const unsigned char *ikm, size_t ikm_len,
unsigned char *prk)
{
unsigned char null_salt[MBEDTLS_MD_MAX_SIZE] = { '\0' };
if (salt == NULL) {
size_t hash_len;
if (salt_len != 0) {
return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA;
}
hash_len = mbedtls_md_get_size(md);
if (hash_len == 0) {
return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA;
}
salt = null_salt;
salt_len = hash_len;
}
return mbedtls_md_hmac(md, salt, salt_len, ikm, ikm_len, prk);
}
int mbedtls_hkdf_expand(const mbedtls_md_info_t *md, const unsigned char *prk,
size_t prk_len, const unsigned char *info,
size_t info_len, unsigned char *okm, size_t okm_len)
{
size_t hash_len;
size_t where = 0;
size_t n;
size_t t_len = 0;
size_t i;
int ret = 0;
mbedtls_md_context_t ctx;
unsigned char t[MBEDTLS_MD_MAX_SIZE];
if (okm == NULL) {
return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA;
}
hash_len = mbedtls_md_get_size(md);
if (prk_len < hash_len || hash_len == 0) {
return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA;
}
if (info == NULL) {
info = (const unsigned char *) "";
info_len = 0;
}
n = okm_len / hash_len;
if (okm_len % hash_len != 0) {
n++;
}
/*
* Per RFC 5869 Section 2.3, okm_len must not exceed
* 255 times the hash length
*/
if (n > 255) {
return MBEDTLS_ERR_HKDF_BAD_INPUT_DATA;
}
mbedtls_md_init(&ctx);
if ((ret = mbedtls_md_setup(&ctx, md, 1)) != 0) {
goto exit;
}
memset(t, 0, hash_len);
/*
* Compute T = T(1) | T(2) | T(3) | ... | T(N)
* Where T(N) is defined in RFC 5869 Section 2.3
*/
for (i = 1; i <= n; i++) {
size_t num_to_copy;
unsigned char c = i & 0xff;
ret = mbedtls_md_hmac_starts(&ctx, prk, prk_len);
if (ret != 0) {
goto exit;
}
ret = mbedtls_md_hmac_update(&ctx, t, t_len);
if (ret != 0) {
goto exit;
}
ret = mbedtls_md_hmac_update(&ctx, info, info_len);
if (ret != 0) {
goto exit;
}
/* The constant concatenated to the end of each T(n) is a single octet.
* */
ret = mbedtls_md_hmac_update(&ctx, &c, 1);
if (ret != 0) {
goto exit;
}
ret = mbedtls_md_hmac_finish(&ctx, t);
if (ret != 0) {
goto exit;
}
num_to_copy = i != n ? hash_len : okm_len - where;
memcpy(okm + where, t, num_to_copy);
where += hash_len;
t_len = hash_len;
}
exit:
mbedtls_md_free(&ctx);
mbedtls_platform_zeroize(t, sizeof(t));
return ret;
}
#endif /* MBEDTLS_HKDF_C */

633
thirdparty/mbedtls/library/hmac_drbg.c vendored Normal file
View File

@@ -0,0 +1,633 @@
/*
* HMAC_DRBG implementation (NIST SP 800-90)
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
/*
* The NIST SP 800-90A DRBGs are described in the following publication.
* http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
* References below are based on rev. 1 (January 2012).
*/
#include "common.h"
#if defined(MBEDTLS_HMAC_DRBG_C)
#include "mbedtls/hmac_drbg.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#include <string.h>
#if defined(MBEDTLS_FS_IO)
#include <stdio.h>
#endif
#include "mbedtls/platform.h"
/*
* HMAC_DRBG context initialization
*/
void mbedtls_hmac_drbg_init(mbedtls_hmac_drbg_context *ctx)
{
memset(ctx, 0, sizeof(mbedtls_hmac_drbg_context));
ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
}
/*
* HMAC_DRBG update, using optional additional data (10.1.2.2)
*/
int mbedtls_hmac_drbg_update(mbedtls_hmac_drbg_context *ctx,
const unsigned char *additional,
size_t add_len)
{
size_t md_len = mbedtls_md_get_size(ctx->md_ctx.md_info);
unsigned char rounds = (additional != NULL && add_len != 0) ? 2 : 1;
unsigned char sep[1];
unsigned char K[MBEDTLS_MD_MAX_SIZE];
int ret = MBEDTLS_ERR_MD_BAD_INPUT_DATA;
for (sep[0] = 0; sep[0] < rounds; sep[0]++) {
/* Step 1 or 4 */
if ((ret = mbedtls_md_hmac_reset(&ctx->md_ctx)) != 0) {
goto exit;
}
if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,
ctx->V, md_len)) != 0) {
goto exit;
}
if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,
sep, 1)) != 0) {
goto exit;
}
if (rounds == 2) {
if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,
additional, add_len)) != 0) {
goto exit;
}
}
if ((ret = mbedtls_md_hmac_finish(&ctx->md_ctx, K)) != 0) {
goto exit;
}
/* Step 2 or 5 */
if ((ret = mbedtls_md_hmac_starts(&ctx->md_ctx, K, md_len)) != 0) {
goto exit;
}
if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,
ctx->V, md_len)) != 0) {
goto exit;
}
if ((ret = mbedtls_md_hmac_finish(&ctx->md_ctx, ctx->V)) != 0) {
goto exit;
}
}
exit:
mbedtls_platform_zeroize(K, sizeof(K));
return ret;
}
/*
* Simplified HMAC_DRBG initialisation (for use with deterministic ECDSA)
*/
int mbedtls_hmac_drbg_seed_buf(mbedtls_hmac_drbg_context *ctx,
const mbedtls_md_info_t *md_info,
const unsigned char *data, size_t data_len)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if ((ret = mbedtls_md_setup(&ctx->md_ctx, md_info, 1)) != 0) {
return ret;
}
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_init(&ctx->mutex);
#endif
/*
* Set initial working state.
* Use the V memory location, which is currently all 0, to initialize the
* MD context with an all-zero key. Then set V to its initial value.
*/
if ((ret = mbedtls_md_hmac_starts(&ctx->md_ctx, ctx->V,
mbedtls_md_get_size(md_info))) != 0) {
return ret;
}
memset(ctx->V, 0x01, mbedtls_md_get_size(md_info));
if ((ret = mbedtls_hmac_drbg_update(ctx, data, data_len)) != 0) {
return ret;
}
return 0;
}
/*
* Internal function used both for seeding and reseeding the DRBG.
* Comments starting with arabic numbers refer to section 10.1.2.4
* of SP800-90A, while roman numbers refer to section 9.2.
*/
static int hmac_drbg_reseed_core(mbedtls_hmac_drbg_context *ctx,
const unsigned char *additional, size_t len,
int use_nonce)
{
unsigned char seed[MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT];
size_t seedlen = 0;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
{
size_t total_entropy_len;
if (use_nonce == 0) {
total_entropy_len = ctx->entropy_len;
} else {
total_entropy_len = ctx->entropy_len * 3 / 2;
}
/* III. Check input length */
if (len > MBEDTLS_HMAC_DRBG_MAX_INPUT ||
total_entropy_len + len > MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT) {
return MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
}
}
memset(seed, 0, MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT);
/* IV. Gather entropy_len bytes of entropy for the seed */
if ((ret = ctx->f_entropy(ctx->p_entropy,
seed, ctx->entropy_len)) != 0) {
return MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED;
}
seedlen += ctx->entropy_len;
/* For initial seeding, allow adding of nonce generated
* from the entropy source. See Sect 8.6.7 in SP800-90A. */
if (use_nonce) {
/* Note: We don't merge the two calls to f_entropy() in order
* to avoid requesting too much entropy from f_entropy()
* at once. Specifically, if the underlying digest is not
* SHA-1, 3 / 2 * entropy_len is at least 36 Bytes, which
* is larger than the maximum of 32 Bytes that our own
* entropy source implementation can emit in a single
* call in configurations disabling SHA-512. */
if ((ret = ctx->f_entropy(ctx->p_entropy,
seed + seedlen,
ctx->entropy_len / 2)) != 0) {
return MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED;
}
seedlen += ctx->entropy_len / 2;
}
/* 1. Concatenate entropy and additional data if any */
if (additional != NULL && len != 0) {
memcpy(seed + seedlen, additional, len);
seedlen += len;
}
/* 2. Update state */
if ((ret = mbedtls_hmac_drbg_update(ctx, seed, seedlen)) != 0) {
goto exit;
}
/* 3. Reset reseed_counter */
ctx->reseed_counter = 1;
exit:
/* 4. Done */
mbedtls_platform_zeroize(seed, seedlen);
return ret;
}
/*
* HMAC_DRBG reseeding: 10.1.2.4 + 9.2
*/
int mbedtls_hmac_drbg_reseed(mbedtls_hmac_drbg_context *ctx,
const unsigned char *additional, size_t len)
{
return hmac_drbg_reseed_core(ctx, additional, len, 0);
}
/*
* HMAC_DRBG initialisation (10.1.2.3 + 9.1)
*
* The nonce is not passed as a separate parameter but extracted
* from the entropy source as suggested in 8.6.7.
*/
int mbedtls_hmac_drbg_seed(mbedtls_hmac_drbg_context *ctx,
const mbedtls_md_info_t *md_info,
int (*f_entropy)(void *, unsigned char *, size_t),
void *p_entropy,
const unsigned char *custom,
size_t len)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t md_size;
if ((ret = mbedtls_md_setup(&ctx->md_ctx, md_info, 1)) != 0) {
return ret;
}
/* The mutex is initialized iff the md context is set up. */
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_init(&ctx->mutex);
#endif
md_size = mbedtls_md_get_size(md_info);
/*
* Set initial working state.
* Use the V memory location, which is currently all 0, to initialize the
* MD context with an all-zero key. Then set V to its initial value.
*/
if ((ret = mbedtls_md_hmac_starts(&ctx->md_ctx, ctx->V, md_size)) != 0) {
return ret;
}
memset(ctx->V, 0x01, md_size);
ctx->f_entropy = f_entropy;
ctx->p_entropy = p_entropy;
if (ctx->entropy_len == 0) {
/*
* See SP800-57 5.6.1 (p. 65-66) for the security strength provided by
* each hash function, then according to SP800-90A rev1 10.1 table 2,
* min_entropy_len (in bits) is security_strength.
*
* (This also matches the sizes used in the NIST test vectors.)
*/
ctx->entropy_len = md_size <= 20 ? 16 : /* 160-bits hash -> 128 bits */
md_size <= 28 ? 24 : /* 224-bits hash -> 192 bits */
32; /* better (256+) -> 256 bits */
}
if ((ret = hmac_drbg_reseed_core(ctx, custom, len,
1 /* add nonce */)) != 0) {
return ret;
}
return 0;
}
/*
* Set prediction resistance
*/
void mbedtls_hmac_drbg_set_prediction_resistance(mbedtls_hmac_drbg_context *ctx,
int resistance)
{
ctx->prediction_resistance = resistance;
}
/*
* Set entropy length grabbed for seeding
*/
void mbedtls_hmac_drbg_set_entropy_len(mbedtls_hmac_drbg_context *ctx, size_t len)
{
ctx->entropy_len = len;
}
/*
* Set reseed interval
*/
void mbedtls_hmac_drbg_set_reseed_interval(mbedtls_hmac_drbg_context *ctx, int interval)
{
ctx->reseed_interval = interval;
}
/*
* HMAC_DRBG random function with optional additional data:
* 10.1.2.5 (arabic) + 9.3 (Roman)
*/
int mbedtls_hmac_drbg_random_with_add(void *p_rng,
unsigned char *output, size_t out_len,
const unsigned char *additional, size_t add_len)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
size_t md_len = mbedtls_md_get_size(ctx->md_ctx.md_info);
size_t left = out_len;
unsigned char *out = output;
/* II. Check request length */
if (out_len > MBEDTLS_HMAC_DRBG_MAX_REQUEST) {
return MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG;
}
/* III. Check input length */
if (add_len > MBEDTLS_HMAC_DRBG_MAX_INPUT) {
return MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
}
/* 1. (aka VII and IX) Check reseed counter and PR */
if (ctx->f_entropy != NULL && /* For no-reseeding instances */
(ctx->prediction_resistance == MBEDTLS_HMAC_DRBG_PR_ON ||
ctx->reseed_counter > ctx->reseed_interval)) {
if ((ret = mbedtls_hmac_drbg_reseed(ctx, additional, add_len)) != 0) {
return ret;
}
add_len = 0; /* VII.4 */
}
/* 2. Use additional data if any */
if (additional != NULL && add_len != 0) {
if ((ret = mbedtls_hmac_drbg_update(ctx,
additional, add_len)) != 0) {
goto exit;
}
}
/* 3, 4, 5. Generate bytes */
while (left != 0) {
size_t use_len = left > md_len ? md_len : left;
if ((ret = mbedtls_md_hmac_reset(&ctx->md_ctx)) != 0) {
goto exit;
}
if ((ret = mbedtls_md_hmac_update(&ctx->md_ctx,
ctx->V, md_len)) != 0) {
goto exit;
}
if ((ret = mbedtls_md_hmac_finish(&ctx->md_ctx, ctx->V)) != 0) {
goto exit;
}
memcpy(out, ctx->V, use_len);
out += use_len;
left -= use_len;
}
/* 6. Update */
if ((ret = mbedtls_hmac_drbg_update(ctx,
additional, add_len)) != 0) {
goto exit;
}
/* 7. Update reseed counter */
ctx->reseed_counter++;
exit:
/* 8. Done */
return ret;
}
/*
* HMAC_DRBG random function
*/
int mbedtls_hmac_drbg_random(void *p_rng, unsigned char *output, size_t out_len)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_hmac_drbg_context *ctx = (mbedtls_hmac_drbg_context *) p_rng;
#if defined(MBEDTLS_THREADING_C)
if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
return ret;
}
#endif
ret = mbedtls_hmac_drbg_random_with_add(ctx, output, out_len, NULL, 0);
#if defined(MBEDTLS_THREADING_C)
if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
}
#endif
return ret;
}
/*
* This function resets HMAC_DRBG context to the state immediately
* after initial call of mbedtls_hmac_drbg_init().
*/
void mbedtls_hmac_drbg_free(mbedtls_hmac_drbg_context *ctx)
{
if (ctx == NULL) {
return;
}
#if defined(MBEDTLS_THREADING_C)
/* The mutex is initialized iff the md context is set up. */
if (ctx->md_ctx.md_info != NULL) {
mbedtls_mutex_free(&ctx->mutex);
}
#endif
mbedtls_md_free(&ctx->md_ctx);
mbedtls_platform_zeroize(ctx, sizeof(mbedtls_hmac_drbg_context));
ctx->reseed_interval = MBEDTLS_HMAC_DRBG_RESEED_INTERVAL;
}
#if defined(MBEDTLS_FS_IO)
int mbedtls_hmac_drbg_write_seed_file(mbedtls_hmac_drbg_context *ctx, const char *path)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
FILE *f;
unsigned char buf[MBEDTLS_HMAC_DRBG_MAX_INPUT];
if ((f = fopen(path, "wb")) == NULL) {
return MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
}
/* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
mbedtls_setbuf(f, NULL);
if ((ret = mbedtls_hmac_drbg_random(ctx, buf, sizeof(buf))) != 0) {
goto exit;
}
if (fwrite(buf, 1, sizeof(buf), f) != sizeof(buf)) {
ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
goto exit;
}
ret = 0;
exit:
fclose(f);
mbedtls_platform_zeroize(buf, sizeof(buf));
return ret;
}
int mbedtls_hmac_drbg_update_seed_file(mbedtls_hmac_drbg_context *ctx, const char *path)
{
int ret = 0;
FILE *f = NULL;
size_t n;
unsigned char buf[MBEDTLS_HMAC_DRBG_MAX_INPUT];
unsigned char c;
if ((f = fopen(path, "rb")) == NULL) {
return MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
}
/* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
mbedtls_setbuf(f, NULL);
n = fread(buf, 1, sizeof(buf), f);
if (fread(&c, 1, 1, f) != 0) {
ret = MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG;
goto exit;
}
if (n == 0 || ferror(f)) {
ret = MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR;
goto exit;
}
fclose(f);
f = NULL;
ret = mbedtls_hmac_drbg_update(ctx, buf, n);
exit:
mbedtls_platform_zeroize(buf, sizeof(buf));
if (f != NULL) {
fclose(f);
}
if (ret != 0) {
return ret;
}
return mbedtls_hmac_drbg_write_seed_file(ctx, path);
}
#endif /* MBEDTLS_FS_IO */
#if defined(MBEDTLS_SELF_TEST)
#if !defined(MBEDTLS_MD_CAN_SHA1)
/* Dummy checkup routine */
int mbedtls_hmac_drbg_self_test(int verbose)
{
(void) verbose;
return 0;
}
#else
#define OUTPUT_LEN 80
/* From a NIST PR=true test vector */
static const unsigned char entropy_pr[] = {
0xa0, 0xc9, 0xab, 0x58, 0xf1, 0xe2, 0xe5, 0xa4, 0xde, 0x3e, 0xbd, 0x4f,
0xf7, 0x3e, 0x9c, 0x5b, 0x64, 0xef, 0xd8, 0xca, 0x02, 0x8c, 0xf8, 0x11,
0x48, 0xa5, 0x84, 0xfe, 0x69, 0xab, 0x5a, 0xee, 0x42, 0xaa, 0x4d, 0x42,
0x17, 0x60, 0x99, 0xd4, 0x5e, 0x13, 0x97, 0xdc, 0x40, 0x4d, 0x86, 0xa3,
0x7b, 0xf5, 0x59, 0x54, 0x75, 0x69, 0x51, 0xe4
};
static const unsigned char result_pr[OUTPUT_LEN] = {
0x9a, 0x00, 0xa2, 0xd0, 0x0e, 0xd5, 0x9b, 0xfe, 0x31, 0xec, 0xb1, 0x39,
0x9b, 0x60, 0x81, 0x48, 0xd1, 0x96, 0x9d, 0x25, 0x0d, 0x3c, 0x1e, 0x94,
0x10, 0x10, 0x98, 0x12, 0x93, 0x25, 0xca, 0xb8, 0xfc, 0xcc, 0x2d, 0x54,
0x73, 0x19, 0x70, 0xc0, 0x10, 0x7a, 0xa4, 0x89, 0x25, 0x19, 0x95, 0x5e,
0x4b, 0xc6, 0x00, 0x1d, 0x7f, 0x4e, 0x6a, 0x2b, 0xf8, 0xa3, 0x01, 0xab,
0x46, 0x05, 0x5c, 0x09, 0xa6, 0x71, 0x88, 0xf1, 0xa7, 0x40, 0xee, 0xf3,
0xe1, 0x5c, 0x02, 0x9b, 0x44, 0xaf, 0x03, 0x44
};
/* From a NIST PR=false test vector */
static const unsigned char entropy_nopr[] = {
0x79, 0x34, 0x9b, 0xbf, 0x7c, 0xdd, 0xa5, 0x79, 0x95, 0x57, 0x86, 0x66,
0x21, 0xc9, 0x13, 0x83, 0x11, 0x46, 0x73, 0x3a, 0xbf, 0x8c, 0x35, 0xc8,
0xc7, 0x21, 0x5b, 0x5b, 0x96, 0xc4, 0x8e, 0x9b, 0x33, 0x8c, 0x74, 0xe3,
0xe9, 0x9d, 0xfe, 0xdf
};
static const unsigned char result_nopr[OUTPUT_LEN] = {
0xc6, 0xa1, 0x6a, 0xb8, 0xd4, 0x20, 0x70, 0x6f, 0x0f, 0x34, 0xab, 0x7f,
0xec, 0x5a, 0xdc, 0xa9, 0xd8, 0xca, 0x3a, 0x13, 0x3e, 0x15, 0x9c, 0xa6,
0xac, 0x43, 0xc6, 0xf8, 0xa2, 0xbe, 0x22, 0x83, 0x4a, 0x4c, 0x0a, 0x0a,
0xff, 0xb1, 0x0d, 0x71, 0x94, 0xf1, 0xc1, 0xa5, 0xcf, 0x73, 0x22, 0xec,
0x1a, 0xe0, 0x96, 0x4e, 0xd4, 0xbf, 0x12, 0x27, 0x46, 0xe0, 0x87, 0xfd,
0xb5, 0xb3, 0xe9, 0x1b, 0x34, 0x93, 0xd5, 0xbb, 0x98, 0xfa, 0xed, 0x49,
0xe8, 0x5f, 0x13, 0x0f, 0xc8, 0xa4, 0x59, 0xb7
};
/* "Entropy" from buffer */
static size_t test_offset;
static int hmac_drbg_self_test_entropy(void *data,
unsigned char *buf, size_t len)
{
const unsigned char *p = data;
memcpy(buf, p + test_offset, len);
test_offset += len;
return 0;
}
#define CHK(c) if ((c) != 0) \
{ \
if (verbose != 0) \
mbedtls_printf("failed\n"); \
return 1; \
}
/*
* Checkup routine for HMAC_DRBG with SHA-1
*/
int mbedtls_hmac_drbg_self_test(int verbose)
{
mbedtls_hmac_drbg_context ctx;
unsigned char buf[OUTPUT_LEN];
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
mbedtls_hmac_drbg_init(&ctx);
/*
* PR = True
*/
if (verbose != 0) {
mbedtls_printf(" HMAC_DRBG (PR = True) : ");
}
test_offset = 0;
CHK(mbedtls_hmac_drbg_seed(&ctx, md_info,
hmac_drbg_self_test_entropy, (void *) entropy_pr,
NULL, 0));
mbedtls_hmac_drbg_set_prediction_resistance(&ctx, MBEDTLS_HMAC_DRBG_PR_ON);
CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));
CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));
CHK(memcmp(buf, result_pr, OUTPUT_LEN));
mbedtls_hmac_drbg_free(&ctx);
mbedtls_hmac_drbg_free(&ctx);
if (verbose != 0) {
mbedtls_printf("passed\n");
}
/*
* PR = False
*/
if (verbose != 0) {
mbedtls_printf(" HMAC_DRBG (PR = False) : ");
}
mbedtls_hmac_drbg_init(&ctx);
test_offset = 0;
CHK(mbedtls_hmac_drbg_seed(&ctx, md_info,
hmac_drbg_self_test_entropy, (void *) entropy_nopr,
NULL, 0));
CHK(mbedtls_hmac_drbg_reseed(&ctx, NULL, 0));
CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));
CHK(mbedtls_hmac_drbg_random(&ctx, buf, OUTPUT_LEN));
CHK(memcmp(buf, result_nopr, OUTPUT_LEN));
mbedtls_hmac_drbg_free(&ctx);
mbedtls_hmac_drbg_free(&ctx);
if (verbose != 0) {
mbedtls_printf("passed\n");
}
if (verbose != 0) {
mbedtls_printf("\n");
}
return 0;
}
#endif /* MBEDTLS_MD_CAN_SHA1 */
#endif /* MBEDTLS_SELF_TEST */
#endif /* MBEDTLS_HMAC_DRBG_C */

288
thirdparty/mbedtls/library/lmots.h vendored Normal file
View File

@@ -0,0 +1,288 @@
/**
* \file lmots.h
*
* \brief This file provides an API for the LM-OTS post-quantum-safe one-time
* public-key signature scheme as defined in RFC8554 and NIST.SP.200-208.
* This implementation currently only supports a single parameter set
* MBEDTLS_LMOTS_SHA256_N32_W8 in order to reduce complexity.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef MBEDTLS_LMOTS_H
#define MBEDTLS_LMOTS_H
#include "mbedtls/build_info.h"
#include "psa/crypto.h"
#include "mbedtls/lms.h"
#include <stdint.h>
#include <stddef.h>
#define MBEDTLS_LMOTS_PUBLIC_KEY_LEN(type) (MBEDTLS_LMOTS_TYPE_LEN + \
MBEDTLS_LMOTS_I_KEY_ID_LEN + \
MBEDTLS_LMOTS_Q_LEAF_ID_LEN + \
MBEDTLS_LMOTS_N_HASH_LEN(type))
#define MBEDTLS_LMOTS_SIG_TYPE_OFFSET (0)
#define MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET (MBEDTLS_LMOTS_SIG_TYPE_OFFSET + \
MBEDTLS_LMOTS_TYPE_LEN)
#define MBEDTLS_LMOTS_SIG_SIGNATURE_OFFSET(type) (MBEDTLS_LMOTS_SIG_C_RANDOM_OFFSET + \
MBEDTLS_LMOTS_C_RANDOM_VALUE_LEN(type))
#ifdef __cplusplus
extern "C" {
#endif
#if defined(MBEDTLS_TEST_HOOKS)
extern int (*mbedtls_lmots_sign_private_key_invalidated_hook)(unsigned char *);
#endif /* defined(MBEDTLS_TEST_HOOKS) */
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
/**
* \brief This function converts a \ref psa_status_t to a
* low-level LMS error code.
*
* \param status The psa_status_t to convert
*
* \return The corresponding LMS error code.
*/
int MBEDTLS_DEPRECATED mbedtls_lms_error_from_psa(psa_status_t status);
#endif
/**
* \brief This function initializes a public LMOTS context
*
* \param ctx The uninitialized LMOTS context that will then be
* initialized.
*/
void mbedtls_lmots_public_init(mbedtls_lmots_public_t *ctx);
/**
* \brief This function uninitializes a public LMOTS context
*
* \param ctx The initialized LMOTS context that will then be
* uninitialized.
*/
void mbedtls_lmots_public_free(mbedtls_lmots_public_t *ctx);
/**
* \brief This function imports an LMOTS public key into a
* LMOTS context.
*
* \note Before this function is called, the context must
* have been initialized.
*
* \note See IETF RFC8554 for details of the encoding of
* this public key.
*
* \param ctx The initialized LMOTS context store the key in.
* \param key The buffer from which the key will be read.
* #MBEDTLS_LMOTS_PUBLIC_KEY_LEN bytes will be read
* from this.
*
* \return \c 0 on success.
* \return A non-zero error code on failure.
*/
int mbedtls_lmots_import_public_key(mbedtls_lmots_public_t *ctx,
const unsigned char *key, size_t key_size);
/**
* \brief This function exports an LMOTS public key from a
* LMOTS context that already contains a public key.
*
* \note Before this function is called, the context must
* have been initialized and the context must contain
* a public key.
*
* \note See IETF RFC8554 for details of the encoding of
* this public key.
*
* \param ctx The initialized LMOTS context that contains the
* public key.
* \param key The buffer into which the key will be output. Must
* be at least #MBEDTLS_LMOTS_PUBLIC_KEY_LEN in size.
*
* \return \c 0 on success.
* \return A non-zero error code on failure.
*/
int mbedtls_lmots_export_public_key(const mbedtls_lmots_public_t *ctx,
unsigned char *key, size_t key_size,
size_t *key_len);
/**
* \brief This function creates a candidate public key from
* an LMOTS signature. This can then be compared to
* the real public key to determine the validity of
* the signature.
*
* \note This function is exposed publicly to be used in LMS
* signature verification, it is expected that
* mbedtls_lmots_verify will be used for LMOTS
* signature verification.
*
* \param params The LMOTS parameter set, q and I values as an
* mbedtls_lmots_parameters_t struct.
* \param msg The buffer from which the message will be read.
* \param msg_size The size of the message that will be read.
* \param sig The buffer from which the signature will be read.
* #MBEDTLS_LMOTS_SIG_LEN bytes will be read from
* this.
* \param out The buffer where the candidate public key will be
* stored. Must be at least #MBEDTLS_LMOTS_N_HASH_LEN
* bytes in size.
*
* \return \c 0 on success.
* \return A non-zero error code on failure.
*/
int mbedtls_lmots_calculate_public_key_candidate(const mbedtls_lmots_parameters_t *params,
const unsigned char *msg,
size_t msg_size,
const unsigned char *sig,
size_t sig_size,
unsigned char *out,
size_t out_size,
size_t *out_len);
/**
* \brief This function verifies a LMOTS signature, using a
* LMOTS context that contains a public key.
*
* \warning This function is **not intended for use in
* production**, due to as-yet unsolved problems with
* handling stateful keys. The API for this function
* may change considerably in future versions.
*
* \note Before this function is called, the context must
* have been initialized and must contain a public key
* (either by import or calculation from a private
* key).
*
* \param ctx The initialized LMOTS context from which the public
* key will be read.
* \param msg The buffer from which the message will be read.
* \param msg_size The size of the message that will be read.
* \param sig The buf from which the signature will be read.
* #MBEDTLS_LMOTS_SIG_LEN bytes will be read from
* this.
*
* \return \c 0 on successful verification.
* \return A non-zero error code on failure.
*/
int mbedtls_lmots_verify(const mbedtls_lmots_public_t *ctx,
const unsigned char *msg,
size_t msg_size, const unsigned char *sig,
size_t sig_size);
#if defined(MBEDTLS_LMS_PRIVATE)
/**
* \brief This function initializes a private LMOTS context
*
* \param ctx The uninitialized LMOTS context that will then be
* initialized.
*/
void mbedtls_lmots_private_init(mbedtls_lmots_private_t *ctx);
/**
* \brief This function uninitializes a private LMOTS context
*
* \param ctx The initialized LMOTS context that will then be
* uninitialized.
*/
void mbedtls_lmots_private_free(mbedtls_lmots_private_t *ctx);
/**
* \brief This function calculates an LMOTS private key, and
* stores in into an LMOTS context.
*
* \warning This function is **not intended for use in
* production**, due to as-yet unsolved problems with
* handling stateful keys. The API for this function
* may change considerably in future versions.
*
* \note The seed must have at least 256 bits of entropy.
*
* \param ctx The initialized LMOTS context to generate the key
* into.
* \param I_key_identifier The key identifier of the key, as a 16-byte string.
* \param q_leaf_identifier The leaf identifier of key. If this LMOTS key is
* not being used as part of an LMS key, this should
* be set to 0.
* \param seed The seed used to deterministically generate the
* key.
* \param seed_size The length of the seed.
*
* \return \c 0 on success.
* \return A non-zero error code on failure.
*/
int mbedtls_lmots_generate_private_key(mbedtls_lmots_private_t *ctx,
mbedtls_lmots_algorithm_type_t type,
const unsigned char I_key_identifier[MBEDTLS_LMOTS_I_KEY_ID_LEN],
uint32_t q_leaf_identifier,
const unsigned char *seed,
size_t seed_size);
/**
* \brief This function generates an LMOTS public key from a
* LMOTS context that already contains a private key.
*
* \note Before this function is called, the context must
* have been initialized and the context must contain
* a private key.
*
* \param ctx The initialized LMOTS context to generate the key
* from and store it into.
*
* \return \c 0 on success.
* \return A non-zero error code on failure.
*/
int mbedtls_lmots_calculate_public_key(mbedtls_lmots_public_t *ctx,
const mbedtls_lmots_private_t *priv_ctx);
/**
* \brief This function creates a LMOTS signature, using a
* LMOTS context that contains a private key.
*
* \note Before this function is called, the context must
* have been initialized and must contain a private
* key.
*
* \note LMOTS private keys can only be used once, otherwise
* attackers may be able to create forged signatures.
* If the signing operation is successful, the private
* key in the context will be erased, and no further
* signing will be possible until another private key
* is loaded
*
* \param ctx The initialized LMOTS context from which the
* private key will be read.
* \param f_rng The RNG function to be used for signature
* generation.
* \param p_rng The RNG context to be passed to f_rng
* \param msg The buffer from which the message will be read.
* \param msg_size The size of the message that will be read.
* \param sig The buf into which the signature will be stored.
* Must be at least #MBEDTLS_LMOTS_SIG_LEN in size.
*
* \return \c 0 on success.
* \return A non-zero error code on failure.
*/
int mbedtls_lmots_sign(mbedtls_lmots_private_t *ctx,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng, const unsigned char *msg, size_t msg_size,
unsigned char *sig, size_t sig_size, size_t *sig_len);
#endif /* defined(MBEDTLS_LMS_PRIVATE) */
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_LMOTS_H */

1108
thirdparty/mbedtls/library/md.c vendored Normal file

File diff suppressed because it is too large Load Diff

426
thirdparty/mbedtls/library/md5.c vendored Normal file
View File

@@ -0,0 +1,426 @@
/*
* RFC 1321 compliant MD5 implementation
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
/*
* The MD5 algorithm was designed by Ron Rivest in 1991.
*
* http://www.ietf.org/rfc/rfc1321.txt
*/
#include "common.h"
#if defined(MBEDTLS_MD5_C)
#include "mbedtls/md5.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#include <string.h>
#include "mbedtls/platform.h"
#if !defined(MBEDTLS_MD5_ALT)
void mbedtls_md5_init(mbedtls_md5_context *ctx)
{
memset(ctx, 0, sizeof(mbedtls_md5_context));
}
void mbedtls_md5_free(mbedtls_md5_context *ctx)
{
if (ctx == NULL) {
return;
}
mbedtls_platform_zeroize(ctx, sizeof(mbedtls_md5_context));
}
void mbedtls_md5_clone(mbedtls_md5_context *dst,
const mbedtls_md5_context *src)
{
*dst = *src;
}
/*
* MD5 context setup
*/
int mbedtls_md5_starts(mbedtls_md5_context *ctx)
{
ctx->total[0] = 0;
ctx->total[1] = 0;
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476;
return 0;
}
#if !defined(MBEDTLS_MD5_PROCESS_ALT)
int mbedtls_internal_md5_process(mbedtls_md5_context *ctx,
const unsigned char data[64])
{
struct {
uint32_t X[16], A, B, C, D;
} local;
local.X[0] = MBEDTLS_GET_UINT32_LE(data, 0);
local.X[1] = MBEDTLS_GET_UINT32_LE(data, 4);
local.X[2] = MBEDTLS_GET_UINT32_LE(data, 8);
local.X[3] = MBEDTLS_GET_UINT32_LE(data, 12);
local.X[4] = MBEDTLS_GET_UINT32_LE(data, 16);
local.X[5] = MBEDTLS_GET_UINT32_LE(data, 20);
local.X[6] = MBEDTLS_GET_UINT32_LE(data, 24);
local.X[7] = MBEDTLS_GET_UINT32_LE(data, 28);
local.X[8] = MBEDTLS_GET_UINT32_LE(data, 32);
local.X[9] = MBEDTLS_GET_UINT32_LE(data, 36);
local.X[10] = MBEDTLS_GET_UINT32_LE(data, 40);
local.X[11] = MBEDTLS_GET_UINT32_LE(data, 44);
local.X[12] = MBEDTLS_GET_UINT32_LE(data, 48);
local.X[13] = MBEDTLS_GET_UINT32_LE(data, 52);
local.X[14] = MBEDTLS_GET_UINT32_LE(data, 56);
local.X[15] = MBEDTLS_GET_UINT32_LE(data, 60);
#define S(x, n) \
(((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n))))
#define P(a, b, c, d, k, s, t) \
do \
{ \
(a) += F((b), (c), (d)) + local.X[(k)] + (t); \
(a) = S((a), (s)) + (b); \
} while (0)
local.A = ctx->state[0];
local.B = ctx->state[1];
local.C = ctx->state[2];
local.D = ctx->state[3];
#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
P(local.A, local.B, local.C, local.D, 0, 7, 0xD76AA478);
P(local.D, local.A, local.B, local.C, 1, 12, 0xE8C7B756);
P(local.C, local.D, local.A, local.B, 2, 17, 0x242070DB);
P(local.B, local.C, local.D, local.A, 3, 22, 0xC1BDCEEE);
P(local.A, local.B, local.C, local.D, 4, 7, 0xF57C0FAF);
P(local.D, local.A, local.B, local.C, 5, 12, 0x4787C62A);
P(local.C, local.D, local.A, local.B, 6, 17, 0xA8304613);
P(local.B, local.C, local.D, local.A, 7, 22, 0xFD469501);
P(local.A, local.B, local.C, local.D, 8, 7, 0x698098D8);
P(local.D, local.A, local.B, local.C, 9, 12, 0x8B44F7AF);
P(local.C, local.D, local.A, local.B, 10, 17, 0xFFFF5BB1);
P(local.B, local.C, local.D, local.A, 11, 22, 0x895CD7BE);
P(local.A, local.B, local.C, local.D, 12, 7, 0x6B901122);
P(local.D, local.A, local.B, local.C, 13, 12, 0xFD987193);
P(local.C, local.D, local.A, local.B, 14, 17, 0xA679438E);
P(local.B, local.C, local.D, local.A, 15, 22, 0x49B40821);
#undef F
#define F(x, y, z) ((y) ^ ((z) & ((x) ^ (y))))
P(local.A, local.B, local.C, local.D, 1, 5, 0xF61E2562);
P(local.D, local.A, local.B, local.C, 6, 9, 0xC040B340);
P(local.C, local.D, local.A, local.B, 11, 14, 0x265E5A51);
P(local.B, local.C, local.D, local.A, 0, 20, 0xE9B6C7AA);
P(local.A, local.B, local.C, local.D, 5, 5, 0xD62F105D);
P(local.D, local.A, local.B, local.C, 10, 9, 0x02441453);
P(local.C, local.D, local.A, local.B, 15, 14, 0xD8A1E681);
P(local.B, local.C, local.D, local.A, 4, 20, 0xE7D3FBC8);
P(local.A, local.B, local.C, local.D, 9, 5, 0x21E1CDE6);
P(local.D, local.A, local.B, local.C, 14, 9, 0xC33707D6);
P(local.C, local.D, local.A, local.B, 3, 14, 0xF4D50D87);
P(local.B, local.C, local.D, local.A, 8, 20, 0x455A14ED);
P(local.A, local.B, local.C, local.D, 13, 5, 0xA9E3E905);
P(local.D, local.A, local.B, local.C, 2, 9, 0xFCEFA3F8);
P(local.C, local.D, local.A, local.B, 7, 14, 0x676F02D9);
P(local.B, local.C, local.D, local.A, 12, 20, 0x8D2A4C8A);
#undef F
#define F(x, y, z) ((x) ^ (y) ^ (z))
P(local.A, local.B, local.C, local.D, 5, 4, 0xFFFA3942);
P(local.D, local.A, local.B, local.C, 8, 11, 0x8771F681);
P(local.C, local.D, local.A, local.B, 11, 16, 0x6D9D6122);
P(local.B, local.C, local.D, local.A, 14, 23, 0xFDE5380C);
P(local.A, local.B, local.C, local.D, 1, 4, 0xA4BEEA44);
P(local.D, local.A, local.B, local.C, 4, 11, 0x4BDECFA9);
P(local.C, local.D, local.A, local.B, 7, 16, 0xF6BB4B60);
P(local.B, local.C, local.D, local.A, 10, 23, 0xBEBFBC70);
P(local.A, local.B, local.C, local.D, 13, 4, 0x289B7EC6);
P(local.D, local.A, local.B, local.C, 0, 11, 0xEAA127FA);
P(local.C, local.D, local.A, local.B, 3, 16, 0xD4EF3085);
P(local.B, local.C, local.D, local.A, 6, 23, 0x04881D05);
P(local.A, local.B, local.C, local.D, 9, 4, 0xD9D4D039);
P(local.D, local.A, local.B, local.C, 12, 11, 0xE6DB99E5);
P(local.C, local.D, local.A, local.B, 15, 16, 0x1FA27CF8);
P(local.B, local.C, local.D, local.A, 2, 23, 0xC4AC5665);
#undef F
#define F(x, y, z) ((y) ^ ((x) | ~(z)))
P(local.A, local.B, local.C, local.D, 0, 6, 0xF4292244);
P(local.D, local.A, local.B, local.C, 7, 10, 0x432AFF97);
P(local.C, local.D, local.A, local.B, 14, 15, 0xAB9423A7);
P(local.B, local.C, local.D, local.A, 5, 21, 0xFC93A039);
P(local.A, local.B, local.C, local.D, 12, 6, 0x655B59C3);
P(local.D, local.A, local.B, local.C, 3, 10, 0x8F0CCC92);
P(local.C, local.D, local.A, local.B, 10, 15, 0xFFEFF47D);
P(local.B, local.C, local.D, local.A, 1, 21, 0x85845DD1);
P(local.A, local.B, local.C, local.D, 8, 6, 0x6FA87E4F);
P(local.D, local.A, local.B, local.C, 15, 10, 0xFE2CE6E0);
P(local.C, local.D, local.A, local.B, 6, 15, 0xA3014314);
P(local.B, local.C, local.D, local.A, 13, 21, 0x4E0811A1);
P(local.A, local.B, local.C, local.D, 4, 6, 0xF7537E82);
P(local.D, local.A, local.B, local.C, 11, 10, 0xBD3AF235);
P(local.C, local.D, local.A, local.B, 2, 15, 0x2AD7D2BB);
P(local.B, local.C, local.D, local.A, 9, 21, 0xEB86D391);
#undef F
ctx->state[0] += local.A;
ctx->state[1] += local.B;
ctx->state[2] += local.C;
ctx->state[3] += local.D;
/* Zeroise variables to clear sensitive data from memory. */
mbedtls_platform_zeroize(&local, sizeof(local));
return 0;
}
#endif /* !MBEDTLS_MD5_PROCESS_ALT */
/*
* MD5 process buffer
*/
int mbedtls_md5_update(mbedtls_md5_context *ctx,
const unsigned char *input,
size_t ilen)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t fill;
uint32_t left;
if (ilen == 0) {
return 0;
}
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += (uint32_t) ilen;
ctx->total[0] &= 0xFFFFFFFF;
if (ctx->total[0] < (uint32_t) ilen) {
ctx->total[1]++;
}
if (left && ilen >= fill) {
memcpy((void *) (ctx->buffer + left), input, fill);
if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0) {
return ret;
}
input += fill;
ilen -= fill;
left = 0;
}
while (ilen >= 64) {
if ((ret = mbedtls_internal_md5_process(ctx, input)) != 0) {
return ret;
}
input += 64;
ilen -= 64;
}
if (ilen > 0) {
memcpy((void *) (ctx->buffer + left), input, ilen);
}
return 0;
}
/*
* MD5 final digest
*/
int mbedtls_md5_finish(mbedtls_md5_context *ctx,
unsigned char output[16])
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
uint32_t used;
uint32_t high, low;
/*
* Add padding: 0x80 then 0x00 until 8 bytes remain for the length
*/
used = ctx->total[0] & 0x3F;
ctx->buffer[used++] = 0x80;
if (used <= 56) {
/* Enough room for padding + length in current block */
memset(ctx->buffer + used, 0, 56 - used);
} else {
/* We'll need an extra block */
memset(ctx->buffer + used, 0, 64 - used);
if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0) {
goto exit;
}
memset(ctx->buffer, 0, 56);
}
/*
* Add message length
*/
high = (ctx->total[0] >> 29)
| (ctx->total[1] << 3);
low = (ctx->total[0] << 3);
MBEDTLS_PUT_UINT32_LE(low, ctx->buffer, 56);
MBEDTLS_PUT_UINT32_LE(high, ctx->buffer, 60);
if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0) {
goto exit;
}
/*
* Output final state
*/
MBEDTLS_PUT_UINT32_LE(ctx->state[0], output, 0);
MBEDTLS_PUT_UINT32_LE(ctx->state[1], output, 4);
MBEDTLS_PUT_UINT32_LE(ctx->state[2], output, 8);
MBEDTLS_PUT_UINT32_LE(ctx->state[3], output, 12);
ret = 0;
exit:
mbedtls_md5_free(ctx);
return ret;
}
#endif /* !MBEDTLS_MD5_ALT */
/*
* output = MD5( input buffer )
*/
int mbedtls_md5(const unsigned char *input,
size_t ilen,
unsigned char output[16])
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_md5_context ctx;
mbedtls_md5_init(&ctx);
if ((ret = mbedtls_md5_starts(&ctx)) != 0) {
goto exit;
}
if ((ret = mbedtls_md5_update(&ctx, input, ilen)) != 0) {
goto exit;
}
if ((ret = mbedtls_md5_finish(&ctx, output)) != 0) {
goto exit;
}
exit:
mbedtls_md5_free(&ctx);
return ret;
}
#if defined(MBEDTLS_SELF_TEST)
/*
* RFC 1321 test vectors
*/
static const unsigned char md5_test_buf[7][81] =
{
{ "" },
{ "a" },
{ "abc" },
{ "message digest" },
{ "abcdefghijklmnopqrstuvwxyz" },
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
{ "12345678901234567890123456789012345678901234567890123456789012345678901234567890" }
};
static const size_t md5_test_buflen[7] =
{
0, 1, 3, 14, 26, 62, 80
};
static const unsigned char md5_test_sum[7][16] =
{
{ 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,
0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E },
{ 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8,
0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 },
{ 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0,
0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 },
{ 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D,
0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 },
{ 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00,
0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B },
{ 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5,
0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F },
{ 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55,
0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A }
};
/*
* Checkup routine
*/
int mbedtls_md5_self_test(int verbose)
{
int i, ret = 0;
unsigned char md5sum[16];
for (i = 0; i < 7; i++) {
if (verbose != 0) {
mbedtls_printf(" MD5 test #%d: ", i + 1);
}
ret = mbedtls_md5(md5_test_buf[i], md5_test_buflen[i], md5sum);
if (ret != 0) {
goto fail;
}
if (memcmp(md5sum, md5_test_sum[i], 16) != 0) {
ret = 1;
goto fail;
}
if (verbose != 0) {
mbedtls_printf("passed\n");
}
}
if (verbose != 0) {
mbedtls_printf("\n");
}
return 0;
fail:
if (verbose != 0) {
mbedtls_printf("failed\n");
}
return ret;
}
#endif /* MBEDTLS_SELF_TEST */
#endif /* MBEDTLS_MD5_C */

26
thirdparty/mbedtls/library/md_psa.h vendored Normal file
View File

@@ -0,0 +1,26 @@
/**
* Translation between MD and PSA identifiers (algorithms, errors).
*
* Note: this internal module will go away when everything becomes based on
* PSA Crypto; it is a helper for the transition period.
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef MBEDTLS_MD_PSA_H
#define MBEDTLS_MD_PSA_H
#include "common.h"
#include "mbedtls/md.h"
#include "psa/crypto.h"
/** Convert PSA status to MD error code.
*
* \param status PSA status.
*
* \return The corresponding MD error code,
*/
int mbedtls_md_error_from_psa(psa_status_t status);
#endif /* MBEDTLS_MD_PSA_H */

46
thirdparty/mbedtls/library/md_wrap.h vendored Normal file
View File

@@ -0,0 +1,46 @@
/**
* \file md_wrap.h
*
* \brief Message digest wrappers.
*
* \warning This in an internal header. Do not include directly.
*
* \author Adriaan de Jong <dejong@fox-it.com>
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef MBEDTLS_MD_WRAP_H
#define MBEDTLS_MD_WRAP_H
#include "mbedtls/build_info.h"
#include "mbedtls/md.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Message digest information.
* Allows message digest functions to be called in a generic way.
*/
struct mbedtls_md_info_t {
/** Digest identifier */
mbedtls_md_type_t type;
/** Output length of the digest function in bytes */
unsigned char size;
#if defined(MBEDTLS_MD_C)
/** Block length of the digest function in bytes */
unsigned char block_size;
#endif
};
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_MD_WRAP_H */

View File

@@ -0,0 +1,745 @@
/*
* Buffer-based memory allocator
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
#include "mbedtls/memory_buffer_alloc.h"
/* No need for the header guard as MBEDTLS_MEMORY_BUFFER_ALLOC_C
is dependent upon MBEDTLS_PLATFORM_C */
#include "mbedtls/platform.h"
#include "mbedtls/platform_util.h"
#include <string.h>
#if defined(MBEDTLS_MEMORY_BACKTRACE)
#include <execinfo.h>
#endif
#if defined(MBEDTLS_THREADING_C)
#include "mbedtls/threading.h"
#endif
#define MAGIC1 0xFF00AA55
#define MAGIC2 0xEE119966
#define MAX_BT 20
typedef struct _memory_header memory_header;
struct _memory_header {
size_t magic1;
size_t size;
size_t alloc;
memory_header *prev;
memory_header *next;
memory_header *prev_free;
memory_header *next_free;
#if defined(MBEDTLS_MEMORY_BACKTRACE)
char **trace;
size_t trace_count;
#endif
size_t magic2;
};
typedef struct {
unsigned char *buf;
size_t len;
memory_header *first;
memory_header *first_free;
int verify;
#if defined(MBEDTLS_MEMORY_DEBUG)
size_t alloc_count;
size_t free_count;
size_t total_used;
size_t maximum_used;
size_t header_count;
size_t maximum_header_count;
#endif
#if defined(MBEDTLS_THREADING_C)
mbedtls_threading_mutex_t mutex;
#endif
}
buffer_alloc_ctx;
static buffer_alloc_ctx heap;
#if defined(MBEDTLS_MEMORY_DEBUG)
static void debug_header(memory_header *hdr)
{
#if defined(MBEDTLS_MEMORY_BACKTRACE)
size_t i;
#endif
mbedtls_fprintf(stderr, "HDR: PTR(%10zu), PREV(%10zu), NEXT(%10zu), "
"ALLOC(%zu), SIZE(%10zu)\n",
(size_t) hdr, (size_t) hdr->prev, (size_t) hdr->next,
hdr->alloc, hdr->size);
mbedtls_fprintf(stderr, " FPREV(%10zu), FNEXT(%10zu)\n",
(size_t) hdr->prev_free, (size_t) hdr->next_free);
#if defined(MBEDTLS_MEMORY_BACKTRACE)
mbedtls_fprintf(stderr, "TRACE: \n");
for (i = 0; i < hdr->trace_count; i++) {
mbedtls_fprintf(stderr, "%s\n", hdr->trace[i]);
}
mbedtls_fprintf(stderr, "\n");
#endif
}
static void debug_chain(void)
{
memory_header *cur = heap.first;
mbedtls_fprintf(stderr, "\nBlock list\n");
while (cur != NULL) {
debug_header(cur);
cur = cur->next;
}
mbedtls_fprintf(stderr, "Free list\n");
cur = heap.first_free;
while (cur != NULL) {
debug_header(cur);
cur = cur->next_free;
}
}
#endif /* MBEDTLS_MEMORY_DEBUG */
static int verify_header(memory_header *hdr)
{
if (hdr->magic1 != MAGIC1) {
#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_fprintf(stderr, "FATAL: MAGIC1 mismatch\n");
#endif
return 1;
}
if (hdr->magic2 != MAGIC2) {
#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_fprintf(stderr, "FATAL: MAGIC2 mismatch\n");
#endif
return 1;
}
if (hdr->alloc > 1) {
#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_fprintf(stderr, "FATAL: alloc has illegal value\n");
#endif
return 1;
}
if (hdr->prev != NULL && hdr->prev == hdr->next) {
#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_fprintf(stderr, "FATAL: prev == next\n");
#endif
return 1;
}
if (hdr->prev_free != NULL && hdr->prev_free == hdr->next_free) {
#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_fprintf(stderr, "FATAL: prev_free == next_free\n");
#endif
return 1;
}
return 0;
}
static int verify_chain(void)
{
memory_header *prv = heap.first, *cur;
if (prv == NULL || verify_header(prv) != 0) {
#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_fprintf(stderr, "FATAL: verification of first header "
"failed\n");
#endif
return 1;
}
if (heap.first->prev != NULL) {
#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_fprintf(stderr, "FATAL: verification failed: "
"first->prev != NULL\n");
#endif
return 1;
}
cur = heap.first->next;
while (cur != NULL) {
if (verify_header(cur) != 0) {
#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_fprintf(stderr, "FATAL: verification of header "
"failed\n");
#endif
return 1;
}
if (cur->prev != prv) {
#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_fprintf(stderr, "FATAL: verification failed: "
"cur->prev != prv\n");
#endif
return 1;
}
prv = cur;
cur = cur->next;
}
return 0;
}
static void *buffer_alloc_calloc(size_t n, size_t size)
{
memory_header *new, *cur = heap.first_free;
unsigned char *p;
void *ret;
size_t original_len, len;
#if defined(MBEDTLS_MEMORY_BACKTRACE)
void *trace_buffer[MAX_BT];
size_t trace_cnt;
#endif
if (heap.buf == NULL || heap.first == NULL) {
return NULL;
}
original_len = len = n * size;
if (n == 0 || size == 0 || len / n != size) {
return NULL;
} else if (len > (size_t) -MBEDTLS_MEMORY_ALIGN_MULTIPLE) {
return NULL;
}
if (len % MBEDTLS_MEMORY_ALIGN_MULTIPLE) {
len -= len % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
len += MBEDTLS_MEMORY_ALIGN_MULTIPLE;
}
// Find block that fits
//
while (cur != NULL) {
if (cur->size >= len) {
break;
}
cur = cur->next_free;
}
if (cur == NULL) {
return NULL;
}
if (cur->alloc != 0) {
#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_fprintf(stderr, "FATAL: block in free_list but allocated "
"data\n");
#endif
mbedtls_exit(1);
}
#if defined(MBEDTLS_MEMORY_DEBUG)
heap.alloc_count++;
#endif
// Found location, split block if > memory_header + 4 room left
//
if (cur->size - len < sizeof(memory_header) +
MBEDTLS_MEMORY_ALIGN_MULTIPLE) {
cur->alloc = 1;
// Remove from free_list
//
if (cur->prev_free != NULL) {
cur->prev_free->next_free = cur->next_free;
} else {
heap.first_free = cur->next_free;
}
if (cur->next_free != NULL) {
cur->next_free->prev_free = cur->prev_free;
}
cur->prev_free = NULL;
cur->next_free = NULL;
#if defined(MBEDTLS_MEMORY_DEBUG)
heap.total_used += cur->size;
if (heap.total_used > heap.maximum_used) {
heap.maximum_used = heap.total_used;
}
#endif
#if defined(MBEDTLS_MEMORY_BACKTRACE)
trace_cnt = backtrace(trace_buffer, MAX_BT);
cur->trace = backtrace_symbols(trace_buffer, trace_cnt);
cur->trace_count = trace_cnt;
#endif
if ((heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC) && verify_chain() != 0) {
mbedtls_exit(1);
}
ret = (unsigned char *) cur + sizeof(memory_header);
memset(ret, 0, original_len);
return ret;
}
p = ((unsigned char *) cur) + sizeof(memory_header) + len;
new = (memory_header *) p;
new->size = cur->size - len - sizeof(memory_header);
new->alloc = 0;
new->prev = cur;
new->next = cur->next;
#if defined(MBEDTLS_MEMORY_BACKTRACE)
new->trace = NULL;
new->trace_count = 0;
#endif
new->magic1 = MAGIC1;
new->magic2 = MAGIC2;
if (new->next != NULL) {
new->next->prev = new;
}
// Replace cur with new in free_list
//
new->prev_free = cur->prev_free;
new->next_free = cur->next_free;
if (new->prev_free != NULL) {
new->prev_free->next_free = new;
} else {
heap.first_free = new;
}
if (new->next_free != NULL) {
new->next_free->prev_free = new;
}
cur->alloc = 1;
cur->size = len;
cur->next = new;
cur->prev_free = NULL;
cur->next_free = NULL;
#if defined(MBEDTLS_MEMORY_DEBUG)
heap.header_count++;
if (heap.header_count > heap.maximum_header_count) {
heap.maximum_header_count = heap.header_count;
}
heap.total_used += cur->size;
if (heap.total_used > heap.maximum_used) {
heap.maximum_used = heap.total_used;
}
#endif
#if defined(MBEDTLS_MEMORY_BACKTRACE)
trace_cnt = backtrace(trace_buffer, MAX_BT);
cur->trace = backtrace_symbols(trace_buffer, trace_cnt);
cur->trace_count = trace_cnt;
#endif
if ((heap.verify & MBEDTLS_MEMORY_VERIFY_ALLOC) && verify_chain() != 0) {
mbedtls_exit(1);
}
ret = (unsigned char *) cur + sizeof(memory_header);
memset(ret, 0, original_len);
return ret;
}
static void buffer_alloc_free(void *ptr)
{
memory_header *hdr, *old = NULL;
unsigned char *p = (unsigned char *) ptr;
if (ptr == NULL || heap.buf == NULL || heap.first == NULL) {
return;
}
if (p < heap.buf || p >= heap.buf + heap.len) {
#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_fprintf(stderr, "FATAL: mbedtls_free() outside of managed "
"space\n");
#endif
mbedtls_exit(1);
}
p -= sizeof(memory_header);
hdr = (memory_header *) p;
if (verify_header(hdr) != 0) {
mbedtls_exit(1);
}
if (hdr->alloc != 1) {
#if defined(MBEDTLS_MEMORY_DEBUG)
mbedtls_fprintf(stderr, "FATAL: mbedtls_free() on unallocated "
"data\n");
#endif
mbedtls_exit(1);
}
hdr->alloc = 0;
#if defined(MBEDTLS_MEMORY_DEBUG)
heap.free_count++;
heap.total_used -= hdr->size;
#endif
#if defined(MBEDTLS_MEMORY_BACKTRACE)
free(hdr->trace);
hdr->trace = NULL;
hdr->trace_count = 0;
#endif
// Regroup with block before
//
if (hdr->prev != NULL && hdr->prev->alloc == 0) {
#if defined(MBEDTLS_MEMORY_DEBUG)
heap.header_count--;
#endif
hdr->prev->size += sizeof(memory_header) + hdr->size;
hdr->prev->next = hdr->next;
old = hdr;
hdr = hdr->prev;
if (hdr->next != NULL) {
hdr->next->prev = hdr;
}
memset(old, 0, sizeof(memory_header));
}
// Regroup with block after
//
if (hdr->next != NULL && hdr->next->alloc == 0) {
#if defined(MBEDTLS_MEMORY_DEBUG)
heap.header_count--;
#endif
hdr->size += sizeof(memory_header) + hdr->next->size;
old = hdr->next;
hdr->next = hdr->next->next;
if (hdr->prev_free != NULL || hdr->next_free != NULL) {
if (hdr->prev_free != NULL) {
hdr->prev_free->next_free = hdr->next_free;
} else {
heap.first_free = hdr->next_free;
}
if (hdr->next_free != NULL) {
hdr->next_free->prev_free = hdr->prev_free;
}
}
hdr->prev_free = old->prev_free;
hdr->next_free = old->next_free;
if (hdr->prev_free != NULL) {
hdr->prev_free->next_free = hdr;
} else {
heap.first_free = hdr;
}
if (hdr->next_free != NULL) {
hdr->next_free->prev_free = hdr;
}
if (hdr->next != NULL) {
hdr->next->prev = hdr;
}
memset(old, 0, sizeof(memory_header));
}
// Prepend to free_list if we have not merged
// (Does not have to stay in same order as prev / next list)
//
if (old == NULL) {
hdr->next_free = heap.first_free;
if (heap.first_free != NULL) {
heap.first_free->prev_free = hdr;
}
heap.first_free = hdr;
}
if ((heap.verify & MBEDTLS_MEMORY_VERIFY_FREE) && verify_chain() != 0) {
mbedtls_exit(1);
}
}
void mbedtls_memory_buffer_set_verify(int verify)
{
heap.verify = verify;
}
int mbedtls_memory_buffer_alloc_verify(void)
{
return verify_chain();
}
#if defined(MBEDTLS_MEMORY_DEBUG)
void mbedtls_memory_buffer_alloc_status(void)
{
mbedtls_fprintf(stderr,
"Current use: %zu blocks / %zu bytes, max: %zu blocks / "
"%zu bytes (total %zu bytes), alloc / free: %zu / %zu\n",
heap.header_count, heap.total_used,
heap.maximum_header_count, heap.maximum_used,
heap.maximum_header_count * sizeof(memory_header)
+ heap.maximum_used,
heap.alloc_count, heap.free_count);
if (heap.first->next == NULL) {
mbedtls_fprintf(stderr, "All memory de-allocated in stack buffer\n");
} else {
mbedtls_fprintf(stderr, "Memory currently allocated:\n");
debug_chain();
}
}
void mbedtls_memory_buffer_alloc_count_get(size_t *alloc_count, size_t *free_count)
{
*alloc_count = heap.alloc_count;
*free_count = heap.free_count;
}
void mbedtls_memory_buffer_alloc_max_get(size_t *max_used, size_t *max_blocks)
{
*max_used = heap.maximum_used;
*max_blocks = heap.maximum_header_count;
}
void mbedtls_memory_buffer_alloc_max_reset(void)
{
heap.maximum_used = 0;
heap.maximum_header_count = 0;
}
void mbedtls_memory_buffer_alloc_cur_get(size_t *cur_used, size_t *cur_blocks)
{
*cur_used = heap.total_used;
*cur_blocks = heap.header_count;
}
#endif /* MBEDTLS_MEMORY_DEBUG */
#if defined(MBEDTLS_THREADING_C)
static void *buffer_alloc_calloc_mutexed(size_t n, size_t size)
{
void *buf;
if (mbedtls_mutex_lock(&heap.mutex) != 0) {
return NULL;
}
buf = buffer_alloc_calloc(n, size);
if (mbedtls_mutex_unlock(&heap.mutex)) {
return NULL;
}
return buf;
}
static void buffer_alloc_free_mutexed(void *ptr)
{
/* We have no good option here, but corrupting the heap seems
* worse than losing memory. */
if (mbedtls_mutex_lock(&heap.mutex)) {
return;
}
buffer_alloc_free(ptr);
(void) mbedtls_mutex_unlock(&heap.mutex);
}
#endif /* MBEDTLS_THREADING_C */
void mbedtls_memory_buffer_alloc_init(unsigned char *buf, size_t len)
{
memset(&heap, 0, sizeof(buffer_alloc_ctx));
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_init(&heap.mutex);
mbedtls_platform_set_calloc_free(buffer_alloc_calloc_mutexed,
buffer_alloc_free_mutexed);
#else
mbedtls_platform_set_calloc_free(buffer_alloc_calloc, buffer_alloc_free);
#endif
if (len < sizeof(memory_header) + MBEDTLS_MEMORY_ALIGN_MULTIPLE) {
return;
} else if ((size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE) {
/* Adjust len first since buf is used in the computation */
len -= MBEDTLS_MEMORY_ALIGN_MULTIPLE
- (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
buf += MBEDTLS_MEMORY_ALIGN_MULTIPLE
- (size_t) buf % MBEDTLS_MEMORY_ALIGN_MULTIPLE;
}
memset(buf, 0, len);
heap.buf = buf;
heap.len = len;
heap.first = (memory_header *) buf;
heap.first->size = len - sizeof(memory_header);
heap.first->magic1 = MAGIC1;
heap.first->magic2 = MAGIC2;
heap.first_free = heap.first;
}
void mbedtls_memory_buffer_alloc_free(void)
{
#if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_free(&heap.mutex);
#endif
mbedtls_platform_zeroize(&heap, sizeof(buffer_alloc_ctx));
}
#if defined(MBEDTLS_SELF_TEST)
static int check_pointer(void *p)
{
if (p == NULL) {
return -1;
}
if ((size_t) p % MBEDTLS_MEMORY_ALIGN_MULTIPLE != 0) {
return -1;
}
return 0;
}
static int check_all_free(void)
{
if (
#if defined(MBEDTLS_MEMORY_DEBUG)
heap.total_used != 0 ||
#endif
heap.first != heap.first_free ||
(void *) heap.first != (void *) heap.buf) {
return -1;
}
return 0;
}
#define TEST_ASSERT(condition) \
if (!(condition)) \
{ \
if (verbose != 0) \
mbedtls_printf("failed\n"); \
\
ret = 1; \
goto cleanup; \
}
int mbedtls_memory_buffer_alloc_self_test(int verbose)
{
unsigned char buf[1024];
unsigned char *p, *q, *r, *end;
int ret = 0;
if (verbose != 0) {
mbedtls_printf(" MBA test #1 (basic alloc-free cycle): ");
}
mbedtls_memory_buffer_alloc_init(buf, sizeof(buf));
p = mbedtls_calloc(1, 1);
q = mbedtls_calloc(1, 128);
r = mbedtls_calloc(1, 16);
TEST_ASSERT(check_pointer(p) == 0 &&
check_pointer(q) == 0 &&
check_pointer(r) == 0);
mbedtls_free(r);
mbedtls_free(q);
mbedtls_free(p);
TEST_ASSERT(check_all_free() == 0);
/* Memorize end to compare with the next test */
end = heap.buf + heap.len;
mbedtls_memory_buffer_alloc_free();
if (verbose != 0) {
mbedtls_printf("passed\n");
}
if (verbose != 0) {
mbedtls_printf(" MBA test #2 (buf not aligned): ");
}
mbedtls_memory_buffer_alloc_init(buf + 1, sizeof(buf) - 1);
TEST_ASSERT(heap.buf + heap.len == end);
p = mbedtls_calloc(1, 1);
q = mbedtls_calloc(1, 128);
r = mbedtls_calloc(1, 16);
TEST_ASSERT(check_pointer(p) == 0 &&
check_pointer(q) == 0 &&
check_pointer(r) == 0);
mbedtls_free(r);
mbedtls_free(q);
mbedtls_free(p);
TEST_ASSERT(check_all_free() == 0);
mbedtls_memory_buffer_alloc_free();
if (verbose != 0) {
mbedtls_printf("passed\n");
}
if (verbose != 0) {
mbedtls_printf(" MBA test #3 (full): ");
}
mbedtls_memory_buffer_alloc_init(buf, sizeof(buf));
p = mbedtls_calloc(1, sizeof(buf) - sizeof(memory_header));
TEST_ASSERT(check_pointer(p) == 0);
TEST_ASSERT(mbedtls_calloc(1, 1) == NULL);
mbedtls_free(p);
p = mbedtls_calloc(1, sizeof(buf) - 2 * sizeof(memory_header) - 16);
q = mbedtls_calloc(1, 16);
TEST_ASSERT(check_pointer(p) == 0 && check_pointer(q) == 0);
TEST_ASSERT(mbedtls_calloc(1, 1) == NULL);
mbedtls_free(q);
TEST_ASSERT(mbedtls_calloc(1, 17) == NULL);
mbedtls_free(p);
TEST_ASSERT(check_all_free() == 0);
mbedtls_memory_buffer_alloc_free();
if (verbose != 0) {
mbedtls_printf("passed\n");
}
cleanup:
mbedtls_memory_buffer_alloc_free();
return ret;
}
#endif /* MBEDTLS_SELF_TEST */
#endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */

181
thirdparty/mbedtls/library/mps_common.h vendored Normal file
View File

@@ -0,0 +1,181 @@
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
/**
* \file mps_common.h
*
* \brief Common functions and macros used by MPS
*/
#ifndef MBEDTLS_MPS_COMMON_H
#define MBEDTLS_MPS_COMMON_H
#include "mps_error.h"
#include <stdio.h>
/**
* \name SECTION: MPS Configuration
*
* \{
*/
/*! This flag controls whether the MPS-internal components
* (reader, writer, Layer 1-3) perform validation of the
* expected abstract state at the entry of API calls.
*
* Context: All MPS API functions impose assumptions/preconditions on the
* context on which they operate. For example, every structure has a notion of
* state integrity which is established by `xxx_init()` and preserved by any
* calls to the MPS API which satisfy their preconditions and either succeed,
* or fail with an error code which is explicitly documented to not corrupt
* structure integrity (such as WANT_READ and WANT_WRITE);
* apart from `xxx_init()` any function assumes state integrity as a
* precondition (but usually more). If any of the preconditions is violated,
* the function's behavior is entirely undefined.
* In addition to state integrity, all MPS structures have a more refined
* notion of abstract state that the API operates on. For example, all layers
* have a notion of 'abstract read state' which indicates if incoming data has
* been passed to the user, e.g. through mps_l2_read_start() for Layer 2
* or mps_l3_read() in Layer 3. After such a call, it doesn't make sense to
* call these reading functions again until the incoming data has been
* explicitly 'consumed', e.g. through mps_l2_read_consume() for Layer 2 or
* mps_l3_read_consume() on Layer 3. However, even if it doesn't make sense,
* it's a design choice whether the API should fail gracefully on such
* non-sensical calls or not, and that's what this option is about:
*
* This option determines whether the expected abstract state
* is part of the API preconditions or not: If the option is set,
* then the abstract state is not part of the precondition and is
* thus required to be validated by the implementation. If an unexpected
* abstract state is encountered, the implementation must fail gracefully
* with error #MBEDTLS_ERR_MPS_OPERATION_UNEXPECTED.
* Conversely, if this option is not set, then the expected abstract state
* is included in the preconditions of the respective API calls, and
* an implementation's behaviour is undefined if the abstract state is
* not as expected.
*
* For example: Enabling this makes mps_l2_read_done() fail if
* no incoming record is currently open; disabling this would
* lead to undefined behavior in this case.
*
* Comment this to remove state validation.
*/
#define MBEDTLS_MPS_STATE_VALIDATION
/*! This flag enables/disables assertions on the internal state of MPS.
*
* Assertions are sanity checks that should never trigger when MPS
* is used within the bounds of its API and preconditions.
*
* Enabling this increases security by limiting the scope of
* potential bugs, but comes at the cost of increased code size.
*
* Note: So far, there is no guiding principle as to what
* expected conditions merit an assertion, and which don't.
*
* Comment this to disable assertions.
*/
#define MBEDTLS_MPS_ENABLE_ASSERTIONS
/*! This flag controls whether tracing for MPS should be enabled. */
//#define MBEDTLS_MPS_ENABLE_TRACE
#if defined(MBEDTLS_MPS_STATE_VALIDATION)
#define MBEDTLS_MPS_STATE_VALIDATE_RAW(cond, string) \
do \
{ \
if (!(cond)) \
{ \
MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_ERROR, string); \
MBEDTLS_MPS_TRACE_RETURN(MBEDTLS_ERR_MPS_OPERATION_UNEXPECTED); \
} \
} while (0)
#else /* MBEDTLS_MPS_STATE_VALIDATION */
#define MBEDTLS_MPS_STATE_VALIDATE_RAW(cond, string) \
do \
{ \
(cond); \
} while (0)
#endif /* MBEDTLS_MPS_STATE_VALIDATION */
#if defined(MBEDTLS_MPS_ENABLE_ASSERTIONS)
#define MBEDTLS_MPS_ASSERT_RAW(cond, string) \
do \
{ \
if (!(cond)) \
{ \
MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_ERROR, string); \
MBEDTLS_MPS_TRACE_RETURN(MBEDTLS_ERR_MPS_INTERNAL_ERROR); \
} \
} while (0)
#else /* MBEDTLS_MPS_ENABLE_ASSERTIONS */
#define MBEDTLS_MPS_ASSERT_RAW(cond, string) do {} while (0)
#endif /* MBEDTLS_MPS_ENABLE_ASSERTIONS */
/* \} name SECTION: MPS Configuration */
/**
* \name SECTION: Common types
*
* Various common types used throughout MPS.
* \{
*/
/** \brief The type of buffer sizes and offsets used in MPS structures.
*
* This is an unsigned integer type that should be large enough to
* hold the length of any buffer or message processed by MPS.
*
* The reason to pick a value as small as possible here is
* to reduce the size of MPS structures.
*
* \warning Care has to be taken when using a narrower type
* than ::mbedtls_mps_size_t here because of
* potential truncation during conversion.
*
* \warning Handshake messages in TLS may be up to 2^24 ~ 16Mb in size.
* If mbedtls_mps_[opt_]stored_size_t is smaller than that, the
* maximum handshake message is restricted accordingly.
*
* For now, we use the default type of size_t throughout, and the use of
* smaller types or different types for ::mbedtls_mps_size_t and
* ::mbedtls_mps_stored_size_t is not yet supported.
*
*/
typedef size_t mbedtls_mps_stored_size_t;
#define MBEDTLS_MPS_STORED_SIZE_MAX (SIZE_MAX)
/** \brief The type of buffer sizes and offsets used in the MPS API
* and implementation.
*
* This must be at least as wide as ::mbedtls_stored_size_t but
* may be chosen to be strictly larger if more suitable for the
* target architecture.
*
* For example, in a test build for ARM Thumb, using uint_fast16_t
* instead of uint16_t reduced the code size from 1060 Byte to 962 Byte,
* so almost 10%.
*/
typedef size_t mbedtls_mps_size_t;
#define MBEDTLS_MPS_SIZE_MAX (SIZE_MAX)
#if MBEDTLS_MPS_STORED_SIZE_MAX > MBEDTLS_MPS_SIZE_MAX
#error "Misconfiguration of mbedtls_mps_size_t and mbedtls_mps_stored_size_t."
#endif
/* \} SECTION: Common types */
#endif /* MBEDTLS_MPS_COMMON_H */

89
thirdparty/mbedtls/library/mps_error.h vendored Normal file
View File

@@ -0,0 +1,89 @@
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
/**
* \file mps_error.h
*
* \brief Error codes used by MPS
*/
#ifndef MBEDTLS_MPS_ERROR_H
#define MBEDTLS_MPS_ERROR_H
/* TODO: The error code allocation needs to be revisited:
*
* - Should we make (some of) the MPS Reader error codes public?
* If so, we need to adjust MBEDTLS_MPS_READER_MAKE_ERROR() to hit
* a gap in the Mbed TLS public error space.
* If not, we have to make sure we don't forward those errors
* at the level of the public API -- no risk at the moment as
* long as MPS is an experimental component not accessible from
* public API.
*/
/**
* \name SECTION: MPS general error codes
*
* \{
*/
#ifndef MBEDTLS_MPS_ERR_BASE
#define MBEDTLS_MPS_ERR_BASE (0)
#endif
#define MBEDTLS_MPS_MAKE_ERROR(code) \
(-(MBEDTLS_MPS_ERR_BASE | (code)))
#define MBEDTLS_ERR_MPS_OPERATION_UNEXPECTED MBEDTLS_MPS_MAKE_ERROR(0x1)
#define MBEDTLS_ERR_MPS_INTERNAL_ERROR MBEDTLS_MPS_MAKE_ERROR(0x2)
/* \} name SECTION: MPS general error codes */
/**
* \name SECTION: MPS Reader error codes
*
* \{
*/
#ifndef MBEDTLS_MPS_READER_ERR_BASE
#define MBEDTLS_MPS_READER_ERR_BASE (1 << 8)
#endif
#define MBEDTLS_MPS_READER_MAKE_ERROR(code) \
(-(MBEDTLS_MPS_READER_ERR_BASE | (code)))
/*! An attempt to reclaim the data buffer from a reader failed because
* the user hasn't yet read and committed all of it. */
#define MBEDTLS_ERR_MPS_READER_DATA_LEFT MBEDTLS_MPS_READER_MAKE_ERROR(0x1)
/*! An invalid argument was passed to the reader. */
#define MBEDTLS_ERR_MPS_READER_INVALID_ARG MBEDTLS_MPS_READER_MAKE_ERROR(0x2)
/*! An attempt to move a reader to consuming mode through mbedtls_mps_reader_feed()
* after pausing failed because the provided data is not sufficient to serve the
* read requests that led to the pausing. */
#define MBEDTLS_ERR_MPS_READER_NEED_MORE MBEDTLS_MPS_READER_MAKE_ERROR(0x3)
/*! A get request failed because not enough data is available in the reader. */
#define MBEDTLS_ERR_MPS_READER_OUT_OF_DATA MBEDTLS_MPS_READER_MAKE_ERROR(0x4)
/*!< A get request after pausing and reactivating the reader failed because
* the request is not in line with the request made prior to pausing. The user
* must not change it's 'strategy' after pausing and reactivating a reader. */
#define MBEDTLS_ERR_MPS_READER_INCONSISTENT_REQUESTS MBEDTLS_MPS_READER_MAKE_ERROR(0x5)
/*! An attempt to reclaim the data buffer from a reader failed because the reader
* has no accumulator it can use to backup the data that hasn't been processed. */
#define MBEDTLS_ERR_MPS_READER_NEED_ACCUMULATOR MBEDTLS_MPS_READER_MAKE_ERROR(0x6)
/*! An attempt to reclaim the data buffer from a reader failed because the
* accumulator passed to the reader is not large enough to hold both the
* data that hasn't been processed and the excess of the last read-request. */
#define MBEDTLS_ERR_MPS_READER_ACCUMULATOR_TOO_SMALL MBEDTLS_MPS_READER_MAKE_ERROR(0x7)
/* \} name SECTION: MPS Reader error codes */
#endif /* MBEDTLS_MPS_ERROR_H */

538
thirdparty/mbedtls/library/mps_reader.c vendored Normal file
View File

@@ -0,0 +1,538 @@
/*
* Message Processing Stack, Reader implementation
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
#include "mps_reader.h"
#include "mps_common.h"
#include "mps_trace.h"
#include <string.h>
#if defined(MBEDTLS_MPS_ENABLE_TRACE)
static int mbedtls_mps_trace_id = MBEDTLS_MPS_TRACE_BIT_READER;
#endif /* MBEDTLS_MPS_ENABLE_TRACE */
/*
* GENERAL NOTE ON CODING STYLE
*
* The following code intentionally separates memory loads
* and stores from other operations (arithmetic or branches).
* This leads to the introduction of many local variables
* and significantly increases the C-code line count, but
* should not increase the size of generated assembly.
*
* The reason for this is twofold:
* (1) It will ease verification efforts using the VST
* (Verified Software Toolchain)
* whose program logic cannot directly reason
* about instructions containing a load or store in
* addition to other operations (e.g. *p = *q or
* tmp = *p + 42).
* (2) Operating on local variables and writing the results
* back to the target contexts on success only
* allows to maintain structure invariants even
* on failure - this in turn has two benefits:
* (2.a) If for some reason an error code is not caught
* and operation continues, functions are nonetheless
* called with sane contexts, reducing the risk
* of dangerous behavior.
* (2.b) Randomized testing is easier if structures
* remain intact even in the face of failing
* and/or non-sensical calls.
* Moreover, it might even reduce code-size because
* the compiler need not write back temporary results
* to memory in case of failure.
*
*/
static inline int mps_reader_is_accumulating(
mbedtls_mps_reader const *rd)
{
mbedtls_mps_size_t acc_remaining;
if (rd->acc == NULL) {
return 0;
}
acc_remaining = rd->acc_share.acc_remaining;
return acc_remaining > 0;
}
static inline int mps_reader_is_producing(
mbedtls_mps_reader const *rd)
{
unsigned char *frag = rd->frag;
return frag == NULL;
}
static inline int mps_reader_is_consuming(
mbedtls_mps_reader const *rd)
{
return !mps_reader_is_producing(rd);
}
static inline mbedtls_mps_size_t mps_reader_get_fragment_offset(
mbedtls_mps_reader const *rd)
{
unsigned char *acc = rd->acc;
mbedtls_mps_size_t frag_offset;
if (acc == NULL) {
return 0;
}
frag_offset = rd->acc_share.frag_offset;
return frag_offset;
}
static inline mbedtls_mps_size_t mps_reader_serving_from_accumulator(
mbedtls_mps_reader const *rd)
{
mbedtls_mps_size_t frag_offset, end;
frag_offset = mps_reader_get_fragment_offset(rd);
end = rd->end;
return end < frag_offset;
}
static inline void mps_reader_zero(mbedtls_mps_reader *rd)
{
/* A plain memset() would likely be more efficient,
* but the current way of zeroing makes it harder
* to overlook fields which should not be zero-initialized.
* It's also more suitable for FV efforts since it
* doesn't require reasoning about structs being
* interpreted as unstructured binary blobs. */
static mbedtls_mps_reader const zero =
{ .frag = NULL,
.frag_len = 0,
.commit = 0,
.end = 0,
.pending = 0,
.acc = NULL,
.acc_len = 0,
.acc_available = 0,
.acc_share = { .acc_remaining = 0 } };
*rd = zero;
}
int mbedtls_mps_reader_init(mbedtls_mps_reader *rd,
unsigned char *acc,
mbedtls_mps_size_t acc_len)
{
MBEDTLS_MPS_TRACE_INIT("mbedtls_mps_reader_init");
MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"* Accumulator size: %u bytes", (unsigned) acc_len);
mps_reader_zero(rd);
rd->acc = acc;
rd->acc_len = acc_len;
MBEDTLS_MPS_TRACE_RETURN(0);
}
int mbedtls_mps_reader_free(mbedtls_mps_reader *rd)
{
MBEDTLS_MPS_TRACE_INIT("mbedtls_mps_reader_free");
mps_reader_zero(rd);
MBEDTLS_MPS_TRACE_RETURN(0);
}
int mbedtls_mps_reader_feed(mbedtls_mps_reader *rd,
unsigned char *new_frag,
mbedtls_mps_size_t new_frag_len)
{
mbedtls_mps_size_t copy_to_acc;
MBEDTLS_MPS_TRACE_INIT("mbedtls_mps_reader_feed");
MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"* Fragment length: %u bytes", (unsigned) new_frag_len);
if (new_frag == NULL) {
MBEDTLS_MPS_TRACE_RETURN(MBEDTLS_ERR_MPS_READER_INVALID_ARG);
}
MBEDTLS_MPS_STATE_VALIDATE_RAW(mps_reader_is_producing(
rd),
"mbedtls_mps_reader_feed() requires reader to be in producing mode");
if (mps_reader_is_accumulating(rd)) {
unsigned char *acc = rd->acc;
mbedtls_mps_size_t acc_remaining = rd->acc_share.acc_remaining;
mbedtls_mps_size_t acc_available = rd->acc_available;
/* Skip over parts of the accumulator that have already been filled. */
acc += acc_available;
copy_to_acc = acc_remaining;
if (copy_to_acc > new_frag_len) {
copy_to_acc = new_frag_len;
}
/* Copy new contents to accumulator. */
memcpy(acc, new_frag, copy_to_acc);
MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"Copy new data of size %u of %u into accumulator at offset %u",
(unsigned) copy_to_acc, (unsigned) new_frag_len,
(unsigned) acc_available);
/* Check if, with the new fragment, we have enough data. */
acc_remaining -= copy_to_acc;
if (acc_remaining > 0) {
/* We need to accumulate more data. Stay in producing mode. */
acc_available += copy_to_acc;
rd->acc_share.acc_remaining = acc_remaining;
rd->acc_available = acc_available;
MBEDTLS_MPS_TRACE_RETURN(MBEDTLS_ERR_MPS_READER_NEED_MORE);
}
/* We have filled the accumulator: Move to consuming mode. */
MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"Enough data available to serve user request");
/* Remember overlap of accumulator and fragment. */
rd->acc_share.frag_offset = acc_available;
acc_available += copy_to_acc;
rd->acc_available = acc_available;
} else { /* Not accumulating */
rd->acc_share.frag_offset = 0;
}
rd->frag = new_frag;
rd->frag_len = new_frag_len;
rd->commit = 0;
rd->end = 0;
MBEDTLS_MPS_TRACE_RETURN(0);
}
int mbedtls_mps_reader_get(mbedtls_mps_reader *rd,
mbedtls_mps_size_t desired,
unsigned char **buffer,
mbedtls_mps_size_t *buflen)
{
unsigned char *frag;
mbedtls_mps_size_t frag_len, frag_offset, end, frag_fetched, frag_remaining;
MBEDTLS_MPS_TRACE_INIT("mbedtls_mps_reader_get");
MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"* Bytes requested: %u", (unsigned) desired);
MBEDTLS_MPS_STATE_VALIDATE_RAW(mps_reader_is_consuming(
rd),
"mbedtls_mps_reader_get() requires reader to be in consuming mode");
end = rd->end;
frag_offset = mps_reader_get_fragment_offset(rd);
/* Check if we're still serving from the accumulator. */
if (mps_reader_serving_from_accumulator(rd)) {
/* Illustration of supported and unsupported cases:
*
* - Allowed #1
*
* +-----------------------------------+
* | frag |
* +-----------------------------------+
*
* end end+desired
* | |
* +-----v-------v-------------+
* | acc |
* +---------------------------+
* | |
* frag_offset acc_available
*
* - Allowed #2
*
* +-----------------------------------+
* | frag |
* +-----------------------------------+
*
* end end+desired
* | |
* +----------v----------------v
* | acc |
* +---------------------------+
* | |
* frag_offset acc_available
*
* - Not allowed #1 (could be served, but we don't actually use it):
*
* +-----------------------------------+
* | frag |
* +-----------------------------------+
*
* end end+desired
* | |
* +------v-------------v------+
* | acc |
* +---------------------------+
* | |
* frag_offset acc_available
*
*
* - Not allowed #2 (can't be served with a contiguous buffer):
*
* +-----------------------------------+
* | frag |
* +-----------------------------------+
*
* end end + desired
* | |
* +------v--------------------+ v
* | acc |
* +---------------------------+
* | |
* frag_offset acc_available
*
* In case of Allowed #2 we're switching to serve from
* `frag` starting from the next call to mbedtls_mps_reader_get().
*/
unsigned char *acc;
MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"Serve the request from the accumulator");
if (frag_offset - end < desired) {
mbedtls_mps_size_t acc_available;
acc_available = rd->acc_available;
if (acc_available - end != desired) {
/* It might be possible to serve some of these situations by
* making additional space in the accumulator, removing those
* parts that have already been committed.
* On the other hand, this brings additional complexity and
* enlarges the code size, while there doesn't seem to be a use
* case where we don't attempt exactly the same `get` calls when
* resuming on a reader than what we tried before pausing it.
* If we believe we adhere to this restricted usage throughout
* the library, this check is a good opportunity to
* validate this. */
MBEDTLS_MPS_TRACE_RETURN(
MBEDTLS_ERR_MPS_READER_INCONSISTENT_REQUESTS);
}
}
acc = rd->acc;
acc += end;
*buffer = acc;
if (buflen != NULL) {
*buflen = desired;
}
end += desired;
rd->end = end;
rd->pending = 0;
MBEDTLS_MPS_TRACE_RETURN(0);
}
/* Attempt to serve the request from the current fragment */
MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"Serve the request from the current fragment.");
frag_len = rd->frag_len;
frag_fetched = end - frag_offset; /* The amount of data from the current
* fragment that has already been passed
* to the user. */
frag_remaining = frag_len - frag_fetched; /* Remaining data in fragment */
/* Check if we can serve the read request from the fragment. */
if (frag_remaining < desired) {
MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"There's not enough data in the current fragment "
"to serve the request.");
/* There's not enough data in the current fragment,
* so either just RETURN what we have or fail. */
if (buflen == NULL) {
if (frag_remaining > 0) {
rd->pending = desired - frag_remaining;
MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"Remember to collect %u bytes before re-opening",
(unsigned) rd->pending);
}
MBEDTLS_MPS_TRACE_RETURN(MBEDTLS_ERR_MPS_READER_OUT_OF_DATA);
}
desired = frag_remaining;
}
/* There's enough data in the current fragment to serve the
* (potentially modified) read request. */
frag = rd->frag;
frag += frag_fetched;
*buffer = frag;
if (buflen != NULL) {
*buflen = desired;
}
end += desired;
rd->end = end;
rd->pending = 0;
MBEDTLS_MPS_TRACE_RETURN(0);
}
int mbedtls_mps_reader_commit(mbedtls_mps_reader *rd)
{
mbedtls_mps_size_t end;
MBEDTLS_MPS_TRACE_INIT("mbedtls_mps_reader_commit");
MBEDTLS_MPS_STATE_VALIDATE_RAW(mps_reader_is_consuming(
rd),
"mbedtls_mps_reader_commit() requires reader to be in consuming mode");
end = rd->end;
rd->commit = end;
MBEDTLS_MPS_TRACE_RETURN(0);
}
int mbedtls_mps_reader_reclaim(mbedtls_mps_reader *rd,
int *paused)
{
unsigned char *frag, *acc;
mbedtls_mps_size_t pending, commit;
mbedtls_mps_size_t acc_len, frag_offset, frag_len;
MBEDTLS_MPS_TRACE_INIT("mbedtls_mps_reader_reclaim");
if (paused != NULL) {
*paused = 0;
}
MBEDTLS_MPS_STATE_VALIDATE_RAW(mps_reader_is_consuming(
rd),
"mbedtls_mps_reader_reclaim() requires reader to be in consuming mode");
frag = rd->frag;
acc = rd->acc;
pending = rd->pending;
commit = rd->commit;
frag_len = rd->frag_len;
frag_offset = mps_reader_get_fragment_offset(rd);
if (pending == 0) {
MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"No unsatisfied read-request has been logged.");
/* Check if there's data left to be consumed. */
if (commit < frag_offset || commit - frag_offset < frag_len) {
MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"There is data left to be consumed.");
rd->end = commit;
MBEDTLS_MPS_TRACE_RETURN(MBEDTLS_ERR_MPS_READER_DATA_LEFT);
}
rd->acc_available = 0;
rd->acc_share.acc_remaining = 0;
MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"Fragment has been fully processed and committed.");
} else {
int overflow;
mbedtls_mps_size_t acc_backup_offset;
mbedtls_mps_size_t acc_backup_len;
mbedtls_mps_size_t frag_backup_offset;
mbedtls_mps_size_t frag_backup_len;
mbedtls_mps_size_t backup_len;
mbedtls_mps_size_t acc_len_needed;
MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"There has been an unsatisfied read with %u bytes overhead.",
(unsigned) pending);
if (acc == NULL) {
MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"No accumulator present");
MBEDTLS_MPS_TRACE_RETURN(
MBEDTLS_ERR_MPS_READER_NEED_ACCUMULATOR);
}
acc_len = rd->acc_len;
/* Check if the upper layer has already fetched
* and committed the contents of the accumulator. */
if (commit < frag_offset) {
/* No, accumulator is still being processed. */
frag_backup_offset = 0;
frag_backup_len = frag_len;
acc_backup_offset = commit;
acc_backup_len = frag_offset - commit;
} else {
/* Yes, the accumulator is already processed. */
frag_backup_offset = commit - frag_offset;
frag_backup_len = frag_len - frag_backup_offset;
acc_backup_offset = 0;
acc_backup_len = 0;
}
backup_len = acc_backup_len + frag_backup_len;
acc_len_needed = backup_len + pending;
overflow = 0;
overflow |= (backup_len < acc_backup_len);
overflow |= (acc_len_needed < backup_len);
if (overflow || acc_len < acc_len_needed) {
/* Except for the different return code, we behave as if
* there hadn't been a call to mbedtls_mps_reader_get()
* since the last commit. */
rd->end = commit;
rd->pending = 0;
MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_ERROR,
"The accumulator is too small to handle the backup.");
MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_ERROR,
"* Size: %u", (unsigned) acc_len);
MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_ERROR,
"* Needed: %u (%u + %u)",
(unsigned) acc_len_needed,
(unsigned) backup_len, (unsigned) pending);
MBEDTLS_MPS_TRACE_RETURN(
MBEDTLS_ERR_MPS_READER_ACCUMULATOR_TOO_SMALL);
}
MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"Fragment backup: %u", (unsigned) frag_backup_len);
MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"Accumulator backup: %u", (unsigned) acc_backup_len);
/* Move uncommitted parts from the accumulator to the front
* of the accumulator. */
memmove(acc, acc + acc_backup_offset, acc_backup_len);
/* Copy uncommitted parts of the current fragment to the
* accumulator. */
memcpy(acc + acc_backup_len,
frag + frag_backup_offset, frag_backup_len);
rd->acc_available = backup_len;
rd->acc_share.acc_remaining = pending;
if (paused != NULL) {
*paused = 1;
}
}
rd->frag = NULL;
rd->frag_len = 0;
rd->commit = 0;
rd->end = 0;
rd->pending = 0;
MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_COMMENT,
"Final state: aa %u, al %u, ar %u",
(unsigned) rd->acc_available, (unsigned) rd->acc_len,
(unsigned) rd->acc_share.acc_remaining);
MBEDTLS_MPS_TRACE_RETURN(0);
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */

366
thirdparty/mbedtls/library/mps_reader.h vendored Normal file
View File

@@ -0,0 +1,366 @@
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
/**
* \file mps_reader.h
*
* \brief This file defines reader objects, which together with their
* sibling writer objects form the basis for the communication
* between the various layers of the Mbed TLS messaging stack,
* as well as the communication between the messaging stack and
* the (D)TLS handshake protocol implementation.
*
* Readers provide a means of transferring incoming data from
* a 'producer' providing it in chunks of arbitrary size, to
* a 'consumer' which fetches and processes it in chunks of
* again arbitrary, and potentially different, size.
*
* Readers can thus be seen as datagram-to-stream converters,
* and they abstract away the following two tasks from the user:
* 1. The pointer arithmetic of stepping through a producer-
* provided chunk in smaller chunks.
* 2. The merging of incoming data chunks in case the
* consumer requests data in larger chunks than what the
* producer provides.
*
* The basic abstract flow of operation is the following:
* - Initially, the reader is in 'producing mode'.
* - The producer hands an incoming data buffer to the reader,
* moving it from 'producing' to 'consuming' mode.
* - The consumer subsequently fetches and processes the buffer
* content. Once that's done -- or partially done and a consumer's
* request can't be fulfilled -- the producer revokes the reader's
* access to the incoming data buffer, putting the reader back to
* producing mode.
* - The producer subsequently gathers more incoming data and hands
* it to the reader until it switches back to consuming mode
* if enough data is available for the last consumer request to
* be satisfiable.
* - Repeat the above.
*
* The abstract states of the reader from the producer's and
* consumer's perspective are as follows:
*
* - From the perspective of the consumer, the state of the
* reader consists of the following:
* - A byte stream representing (concatenation of) the data
* received through calls to mbedtls_mps_reader_get(),
* - A marker within that byte stream indicating which data
* can be considered processed, and hence need not be retained,
* when the reader is passed back to the producer via
* mbedtls_mps_reader_reclaim().
* The marker is set via mbedtls_mps_reader_commit()
* which places it at the end of the current byte stream.
* The consumer need not be aware of the distinction between consumer
* and producer mode, because it only interfaces with the reader
* when the latter is in consuming mode.
*
* - From the perspective of the producer, the reader's state is one of:
* - Attached: The reader is in consuming mode.
* - Unset: No incoming data buffer is currently managed by the reader,
* and all previously handed incoming data buffers have been
* fully processed. More data needs to be fed into the reader
* via mbedtls_mps_reader_feed().
*
* - Accumulating: No incoming data buffer is currently managed by the
* reader, but some data from the previous incoming data
* buffer hasn't been processed yet and is internally
* held back.
* The Attached state belongs to consuming mode, while the Unset and
* Accumulating states belong to producing mode.
*
* Transitioning from the Unset or Accumulating state to Attached is
* done via successful calls to mbedtls_mps_reader_feed(), while
* transitioning from Attached to either Unset or Accumulating (depending
* on what has been processed) is done via mbedtls_mps_reader_reclaim().
*
* The following diagram depicts the producer-state progression:
*
* +------------------+ reclaim
* | Unset +<-------------------------------------+ get
* +--------|---------+ | +------+
* | | | |
* | | | |
* | feed +---------+---+--+ |
* +--------------------------------------> <---+
* | Attached |
* +--------------------------------------> <---+
* | feed, enough data available +---------+---+--+ |
* | to serve previous consumer request | | |
* | | | |
* +--------+---------+ | +------+
* +----> Accumulating |<-------------------------------------+ commit
* | +---+--------------+ reclaim, previous read request
* | | couldn't be fulfilled
* | |
* +--------+
* feed, need more data to serve
* previous consumer request
* |
* |
* producing mode | consuming mode
* |
*
*/
#ifndef MBEDTLS_READER_H
#define MBEDTLS_READER_H
#include <stdio.h>
#include "mps_common.h"
#include "mps_error.h"
struct mbedtls_mps_reader;
typedef struct mbedtls_mps_reader mbedtls_mps_reader;
/*
* Structure definitions
*/
struct mbedtls_mps_reader {
unsigned char *frag; /*!< The fragment of incoming data managed by
* the reader; it is provided to the reader
* through mbedtls_mps_reader_feed(). The reader
* does not own the fragment and does not
* perform any allocation operations on it,
* but does have read and write access to it.
*
* The reader is in consuming mode if
* and only if \c frag is not \c NULL. */
mbedtls_mps_stored_size_t frag_len;
/*!< The length of the current fragment.
* Must be 0 if \c frag == \c NULL. */
mbedtls_mps_stored_size_t commit;
/*!< The offset of the last commit, relative
* to the first byte in the fragment, if
* no accumulator is present. If an accumulator
* is present, it is viewed as a prefix to the
* current fragment, and this variable contains
* an offset from the beginning of the accumulator.
*
* This is only used when the reader is in
* consuming mode, i.e. \c frag != \c NULL;
* otherwise, its value is \c 0. */
mbedtls_mps_stored_size_t end;
/*!< The offset of the end of the last chunk
* passed to the user through a call to
* mbedtls_mps_reader_get(), relative to the first
* byte in the fragment, if no accumulator is
* present. If an accumulator is present, it is
* viewed as a prefix to the current fragment, and
* this variable contains an offset from the
* beginning of the accumulator.
*
* This is only used when the reader is in
* consuming mode, i.e. \c frag != \c NULL;
* otherwise, its value is \c 0. */
mbedtls_mps_stored_size_t pending;
/*!< The amount of incoming data missing on the
* last call to mbedtls_mps_reader_get().
* In particular, it is \c 0 if the last call
* was successful.
* If a reader is reclaimed after an
* unsuccessful call to mbedtls_mps_reader_get(),
* this variable is used to have the reader
* remember how much data should be accumulated
* so that the call to mbedtls_mps_reader_get()
* succeeds next time.
* This is only used when the reader is in
* consuming mode, i.e. \c frag != \c NULL;
* otherwise, its value is \c 0. */
/* The accumulator is only needed if we need to be able to pause
* the reader. A few bytes could be saved by moving this to a
* separate struct and using a pointer here. */
unsigned char *acc; /*!< The accumulator is used to gather incoming
* data if a read-request via mbedtls_mps_reader_get()
* cannot be served from the current fragment. */
mbedtls_mps_stored_size_t acc_len;
/*!< The total size of the accumulator. */
mbedtls_mps_stored_size_t acc_available;
/*!< The number of bytes currently gathered in
* the accumulator. This is both used in
* producing and in consuming mode:
* While producing, it is increased until
* it reaches the value of \c acc_remaining below.
* While consuming, it is used to judge if a
* get request can be served from the
* accumulator or not.
* Must not be larger than \c acc_len. */
union {
mbedtls_mps_stored_size_t acc_remaining;
/*!< This indicates the amount of data still
* to be gathered in the accumulator. It is
* only used in producing mode.
* Must be at most acc_len - acc_available. */
mbedtls_mps_stored_size_t frag_offset;
/*!< If an accumulator is present and in use, this
* field indicates the offset of the current
* fragment from the beginning of the
* accumulator. If no accumulator is present
* or the accumulator is not in use, this is \c 0.
* It is only used in consuming mode.
* Must not be larger than \c acc_available. */
} acc_share;
};
/*
* API organization:
* A reader object is usually prepared and maintained
* by some lower layer and passed for usage to an upper
* layer, and the API naturally splits according to which
* layer is supposed to use the respective functions.
*/
/*
* Maintenance API (Lower layer)
*/
/**
* \brief Initialize a reader object
*
* \param reader The reader to be initialized.
* \param acc The buffer to be used as a temporary accumulator
* in case get requests through mbedtls_mps_reader_get()
* exceed the buffer provided by mbedtls_mps_reader_feed().
* This buffer is owned by the caller and exclusive use
* for reading and writing is given to the reader for the
* duration of the reader's lifetime. It is thus the caller's
* responsibility to maintain (and not touch) the buffer for
* the lifetime of the reader, and to properly zeroize and
* free the memory after the reader has been destroyed.
* \param acc_len The size in Bytes of \p acc.
*
* \return \c 0 on success.
* \return A negative \c MBEDTLS_ERR_READER_XXX error code on failure.
*/
int mbedtls_mps_reader_init(mbedtls_mps_reader *reader,
unsigned char *acc,
mbedtls_mps_size_t acc_len);
/**
* \brief Free a reader object
*
* \param reader The reader to be freed.
*
* \return \c 0 on success.
* \return A negative \c MBEDTLS_ERR_READER_XXX error code on failure.
*/
int mbedtls_mps_reader_free(mbedtls_mps_reader *reader);
/**
* \brief Pass chunk of data for the reader to manage.
*
* \param reader The reader context to use. The reader must be
* in producing mode.
* \param buf The buffer to be managed by the reader.
* \param buflen The size in Bytes of \p buffer.
*
* \return \c 0 on success. In this case, the reader will be
* moved to consuming mode and obtains read access
* of \p buf until mbedtls_mps_reader_reclaim()
* is called. It is the responsibility of the caller
* to ensure that the \p buf persists and is not changed
* between successful calls to mbedtls_mps_reader_feed()
* and mbedtls_mps_reader_reclaim().
* \return \c MBEDTLS_ERR_MPS_READER_NEED_MORE if more input data is
* required to fulfill a previous request to mbedtls_mps_reader_get().
* In this case, the reader remains in producing mode and
* takes no ownership of the provided buffer (an internal copy
* is made instead).
* \return Another negative \c MBEDTLS_ERR_READER_XXX error code on
* different kinds of failures.
*/
int mbedtls_mps_reader_feed(mbedtls_mps_reader *reader,
unsigned char *buf,
mbedtls_mps_size_t buflen);
/**
* \brief Reclaim reader's access to the current input buffer.
*
* \param reader The reader context to use. The reader must be
* in consuming mode.
* \param paused If not \c NULL, the integer at address \p paused will be
* modified to indicate whether the reader has been paused
* (value \c 1) or not (value \c 0). Pausing happens if there
* is uncommitted data and a previous request to
* mbedtls_mps_reader_get() has exceeded the bounds of the
* input buffer.
*
* \return \c 0 on success.
* \return A negative \c MBEDTLS_ERR_READER_XXX error code on failure.
*/
int mbedtls_mps_reader_reclaim(mbedtls_mps_reader *reader,
int *paused);
/*
* Usage API (Upper layer)
*/
/**
* \brief Request data from the reader.
*
* \param reader The reader context to use. The reader must
* be in consuming mode.
* \param desired The desired amount of data to be read, in Bytes.
* \param buffer The address to store the buffer pointer in.
* This must not be \c NULL.
* \param buflen The address to store the actual buffer
* length in, or \c NULL.
*
* \return \c 0 on success. In this case, \c *buf holds the
* address of a buffer of size \c *buflen
* (if \c buflen != \c NULL) or \c desired
* (if \c buflen == \c NULL). The user has read access
* to the buffer and guarantee of stability of the data
* until the next call to mbedtls_mps_reader_reclaim().
* \return #MBEDTLS_ERR_MPS_READER_OUT_OF_DATA if there is not enough
* data available to serve the get request. In this case, the
* reader remains intact and in consuming mode, and the consumer
* should retry the call after a successful cycle of
* mbedtls_mps_reader_reclaim() and mbedtls_mps_reader_feed().
* If, after such a cycle, the consumer requests a different
* amount of data, the result is implementation-defined;
* progress is guaranteed only if the same amount of data
* is requested after a mbedtls_mps_reader_reclaim() and
* mbedtls_mps_reader_feed() cycle.
* \return Another negative \c MBEDTLS_ERR_READER_XXX error
* code for different kinds of failure.
*
* \note Passing \c NULL as \p buflen is a convenient way to
* indicate that fragmentation is not tolerated.
* It's functionally equivalent to passing a valid
* address as buflen and checking \c *buflen == \c desired
* afterwards.
*/
int mbedtls_mps_reader_get(mbedtls_mps_reader *reader,
mbedtls_mps_size_t desired,
unsigned char **buffer,
mbedtls_mps_size_t *buflen);
/**
* \brief Mark data obtained from mbedtls_mps_reader_get() as processed.
*
* This call indicates that all data received from prior calls to
* mbedtls_mps_reader_get() has been or will have been
* processed when mbedtls_mps_reader_reclaim() is called,
* and thus need not be backed up.
*
* This function has no user observable effect until
* mbedtls_mps_reader_reclaim() is called. In particular,
* buffers received from mbedtls_mps_reader_get() remain
* valid until mbedtls_mps_reader_reclaim() is called.
*
* \param reader The reader context to use.
*
* \return \c 0 on success.
* \return A negative \c MBEDTLS_ERR_READER_XXX error code on failure.
*
*/
int mbedtls_mps_reader_commit(mbedtls_mps_reader *reader);
#endif /* MBEDTLS_READER_H */

112
thirdparty/mbedtls/library/mps_trace.c vendored Normal file
View File

@@ -0,0 +1,112 @@
/*
* Message Processing Stack, Trace module
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
#include "mps_common.h"
#if defined(MBEDTLS_MPS_ENABLE_TRACE)
#include "mps_trace.h"
#include <stdarg.h>
static int trace_depth = 0;
#define color_default "\x1B[0m"
#define color_red "\x1B[1;31m"
#define color_green "\x1B[1;32m"
#define color_yellow "\x1B[1;33m"
#define color_blue "\x1B[1;34m"
#define color_magenta "\x1B[1;35m"
#define color_cyan "\x1B[1;36m"
#define color_white "\x1B[1;37m"
static char const *colors[] =
{
color_default,
color_green,
color_yellow,
color_magenta,
color_cyan,
color_blue,
color_white
};
#define MPS_TRACE_BUF_SIZE 100
void mbedtls_mps_trace_print_msg(int id, int line, const char *format, ...)
{
int ret;
char str[MPS_TRACE_BUF_SIZE];
va_list argp;
va_start(argp, format);
ret = mbedtls_vsnprintf(str, MPS_TRACE_BUF_SIZE, format, argp);
va_end(argp);
if (ret >= 0 && ret < MPS_TRACE_BUF_SIZE) {
str[ret] = '\0';
mbedtls_printf("[%d|L%d]: %s\n", id, line, str);
}
}
int mbedtls_mps_trace_get_depth()
{
return trace_depth;
}
void mbedtls_mps_trace_dec_depth()
{
trace_depth--;
}
void mbedtls_mps_trace_inc_depth()
{
trace_depth++;
}
void mbedtls_mps_trace_color(int id)
{
if (id > (int) (sizeof(colors) / sizeof(*colors))) {
return;
}
printf("%s", colors[id]);
}
void mbedtls_mps_trace_indent(int level, mbedtls_mps_trace_type ty)
{
if (level > 0) {
while (--level) {
printf("| ");
}
printf("| ");
}
switch (ty) {
case MBEDTLS_MPS_TRACE_TYPE_COMMENT:
mbedtls_printf("@ ");
break;
case MBEDTLS_MPS_TRACE_TYPE_CALL:
mbedtls_printf("+--> ");
break;
case MBEDTLS_MPS_TRACE_TYPE_ERROR:
mbedtls_printf("E ");
break;
case MBEDTLS_MPS_TRACE_TYPE_RETURN:
mbedtls_printf("< ");
break;
default:
break;
}
}
#endif /* MBEDTLS_MPS_ENABLE_TRACE */
#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */

154
thirdparty/mbedtls/library/mps_trace.h vendored Normal file
View File

@@ -0,0 +1,154 @@
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
/**
* \file mps_trace.h
*
* \brief Tracing module for MPS
*/
#ifndef MBEDTLS_MPS_MBEDTLS_MPS_TRACE_H
#define MBEDTLS_MPS_MBEDTLS_MPS_TRACE_H
#include "common.h"
#include "mps_common.h"
#include "mps_trace.h"
#include "mbedtls/platform.h"
#if defined(MBEDTLS_MPS_ENABLE_TRACE)
/*
* Adapt this to enable/disable tracing output
* from the various layers of the MPS.
*/
#define MBEDTLS_MPS_TRACE_ENABLE_LAYER_1
#define MBEDTLS_MPS_TRACE_ENABLE_LAYER_2
#define MBEDTLS_MPS_TRACE_ENABLE_LAYER_3
#define MBEDTLS_MPS_TRACE_ENABLE_LAYER_4
#define MBEDTLS_MPS_TRACE_ENABLE_READER
#define MBEDTLS_MPS_TRACE_ENABLE_WRITER
/*
* To use the existing trace module, only change
* MBEDTLS_MPS_TRACE_ENABLE_XXX above, but don't modify the
* rest of this file.
*/
typedef enum {
MBEDTLS_MPS_TRACE_TYPE_COMMENT,
MBEDTLS_MPS_TRACE_TYPE_CALL,
MBEDTLS_MPS_TRACE_TYPE_ERROR,
MBEDTLS_MPS_TRACE_TYPE_RETURN
} mbedtls_mps_trace_type;
#define MBEDTLS_MPS_TRACE_BIT_LAYER_1 1
#define MBEDTLS_MPS_TRACE_BIT_LAYER_2 2
#define MBEDTLS_MPS_TRACE_BIT_LAYER_3 3
#define MBEDTLS_MPS_TRACE_BIT_LAYER_4 4
#define MBEDTLS_MPS_TRACE_BIT_WRITER 5
#define MBEDTLS_MPS_TRACE_BIT_READER 6
#if defined(MBEDTLS_MPS_TRACE_ENABLE_LAYER_1)
#define MBEDTLS_MPS_TRACE_MASK_LAYER_1 (1u << MBEDTLS_MPS_TRACE_BIT_LAYER_1)
#else
#define MBEDTLS_MPS_TRACE_MASK_LAYER_1 0
#endif
#if defined(MBEDTLS_MPS_TRACE_ENABLE_LAYER_2)
#define MBEDTLS_MPS_TRACE_MASK_LAYER_2 (1u << MBEDTLS_MPS_TRACE_BIT_LAYER_2)
#else
#define MBEDTLS_MPS_TRACE_MASK_LAYER_2 0
#endif
#if defined(MBEDTLS_MPS_TRACE_ENABLE_LAYER_3)
#define MBEDTLS_MPS_TRACE_MASK_LAYER_3 (1u << MBEDTLS_MPS_TRACE_BIT_LAYER_3)
#else
#define MBEDTLS_MPS_TRACE_MASK_LAYER_3 0
#endif
#if defined(MBEDTLS_MPS_TRACE_ENABLE_LAYER_4)
#define MBEDTLS_MPS_TRACE_MASK_LAYER_4 (1u << MBEDTLS_MPS_TRACE_BIT_LAYER_4)
#else
#define MBEDTLS_MPS_TRACE_MASK_LAYER_4 0
#endif
#if defined(MBEDTLS_MPS_TRACE_ENABLE_READER)
#define MBEDTLS_MPS_TRACE_MASK_READER (1u << MBEDTLS_MPS_TRACE_BIT_READER)
#else
#define MBEDTLS_MPS_TRACE_MASK_READER 0
#endif
#if defined(MBEDTLS_MPS_TRACE_ENABLE_WRITER)
#define MBEDTLS_MPS_TRACE_MASK_WRITER (1u << MBEDTLS_MPS_TRACE_BIT_WRITER)
#else
#define MBEDTLS_MPS_TRACE_MASK_WRITER 0
#endif
#define MBEDTLS_MPS_TRACE_MASK (MBEDTLS_MPS_TRACE_MASK_LAYER_1 | \
MBEDTLS_MPS_TRACE_MASK_LAYER_2 | \
MBEDTLS_MPS_TRACE_MASK_LAYER_3 | \
MBEDTLS_MPS_TRACE_MASK_LAYER_4 | \
MBEDTLS_MPS_TRACE_MASK_READER | \
MBEDTLS_MPS_TRACE_MASK_WRITER)
/* We have to avoid globals because E-ACSL chokes on them...
* Wrap everything in stub functions. */
int mbedtls_mps_trace_get_depth(void);
void mbedtls_mps_trace_inc_depth(void);
void mbedtls_mps_trace_dec_depth(void);
void mbedtls_mps_trace_color(int id);
void mbedtls_mps_trace_indent(int level, mbedtls_mps_trace_type ty);
void mbedtls_mps_trace_print_msg(int id, int line, const char *format, ...);
#define MBEDTLS_MPS_TRACE(type, ...) \
do { \
if (!(MBEDTLS_MPS_TRACE_MASK & (1u << mbedtls_mps_trace_id))) \
break; \
mbedtls_mps_trace_indent(mbedtls_mps_trace_get_depth(), type); \
mbedtls_mps_trace_color(mbedtls_mps_trace_id); \
mbedtls_mps_trace_print_msg(mbedtls_mps_trace_id, __LINE__, __VA_ARGS__); \
mbedtls_mps_trace_color(0); \
} while (0)
#define MBEDTLS_MPS_TRACE_INIT(...) \
do { \
if (!(MBEDTLS_MPS_TRACE_MASK & (1u << mbedtls_mps_trace_id))) \
break; \
MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_CALL, __VA_ARGS__); \
mbedtls_mps_trace_inc_depth(); \
} while (0)
#define MBEDTLS_MPS_TRACE_END(val) \
do { \
if (!(MBEDTLS_MPS_TRACE_MASK & (1u << mbedtls_mps_trace_id))) \
break; \
MBEDTLS_MPS_TRACE(MBEDTLS_MPS_TRACE_TYPE_RETURN, "%d (-%#04x)", \
(int) (val), -((unsigned) (val))); \
mbedtls_mps_trace_dec_depth(); \
} while (0)
#define MBEDTLS_MPS_TRACE_RETURN(val) \
do { \
/* Breaks tail recursion. */ \
int ret__ = val; \
MBEDTLS_MPS_TRACE_END(ret__); \
return ret__; \
} while (0)
#else /* MBEDTLS_MPS_TRACE */
#define MBEDTLS_MPS_TRACE(type, ...) do { } while (0)
#define MBEDTLS_MPS_TRACE_INIT(...) do { } while (0)
#define MBEDTLS_MPS_TRACE_END do { } while (0)
#define MBEDTLS_MPS_TRACE_RETURN(val) return val;
#endif /* MBEDTLS_MPS_TRACE */
#endif /* MBEDTLS_MPS_MBEDTLS_MPS_TRACE_H */

696
thirdparty/mbedtls/library/net_sockets.c vendored Normal file
View File

@@ -0,0 +1,696 @@
/*
* TCP/IP or UDP/IP networking functions
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
/* Enable definition of getaddrinfo() even when compiling with -std=c99. Must
* be set before mbedtls_config.h, which pulls in glibc's features.h indirectly.
* Harmless on other platforms. */
#ifndef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200112L
#endif
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 600 /* sockaddr_storage */
#endif
#include "common.h"
#if defined(MBEDTLS_NET_C)
#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
!defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \
!defined(__HAIKU__) && !defined(__midipix__)
#error "This module only works on Unix and Windows, see MBEDTLS_NET_C in mbedtls_config.h"
#endif
#include "mbedtls/platform.h"
#include "mbedtls/net_sockets.h"
#include "mbedtls/error.h"
#include <string.h>
#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
!defined(EFI32)
#define IS_EINTR(ret) ((ret) == WSAEINTR)
#include <ws2tcpip.h>
#include <winsock2.h>
#include <windows.h>
#if (_WIN32_WINNT < 0x0501)
#include <wspiapi.h>
#endif
#if defined(_MSC_VER)
#if defined(_WIN32_WCE)
#pragma comment( lib, "ws2.lib" )
#else
#pragma comment( lib, "ws2_32.lib" )
#endif
#endif /* _MSC_VER */
#define read(fd, buf, len) recv(fd, (char *) (buf), (int) (len), 0)
#define write(fd, buf, len) send(fd, (char *) (buf), (int) (len), 0)
#define close(fd) closesocket(fd)
static int wsa_init_done = 0;
#else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <netdb.h>
#include <errno.h>
#define IS_EINTR(ret) ((ret) == EINTR)
#define SOCKET int
#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
/* Some MS functions want int and MSVC warns if we pass size_t,
* but the standard functions use socklen_t, so cast only for MSVC */
#if defined(_MSC_VER)
#define MSVC_INT_CAST (int)
#else
#define MSVC_INT_CAST
#endif
#include <stdio.h>
#if defined(MBEDTLS_HAVE_TIME)
#include <time.h>
#endif
#include <stdint.h>
/*
* Prepare for using the sockets interface
*/
static int net_prepare(void)
{
#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
!defined(EFI32)
WSADATA wsaData;
if (wsa_init_done == 0) {
if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {
return MBEDTLS_ERR_NET_SOCKET_FAILED;
}
wsa_init_done = 1;
}
#else
#if !defined(EFIX64) && !defined(EFI32)
signal(SIGPIPE, SIG_IGN);
#endif
#endif
return 0;
}
/*
* Return 0 if the file descriptor is valid, an error otherwise.
* If for_select != 0, check whether the file descriptor is within the range
* allowed for fd_set used for the FD_xxx macros and the select() function.
*/
static int check_fd(int fd, int for_select)
{
if (fd < 0) {
return MBEDTLS_ERR_NET_INVALID_CONTEXT;
}
#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
!defined(EFI32)
(void) for_select;
#else
/* A limitation of select() is that it only works with file descriptors
* that are strictly less than FD_SETSIZE. This is a limitation of the
* fd_set type. Error out early, because attempting to call FD_SET on a
* large file descriptor is a buffer overflow on typical platforms. */
if (for_select && fd >= FD_SETSIZE) {
return MBEDTLS_ERR_NET_POLL_FAILED;
}
#endif
return 0;
}
/*
* Initialize a context
*/
void mbedtls_net_init(mbedtls_net_context *ctx)
{
ctx->fd = -1;
}
/*
* Initiate a TCP connection with host:port and the given protocol
*/
int mbedtls_net_connect(mbedtls_net_context *ctx, const char *host,
const char *port, int proto)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
struct addrinfo hints, *addr_list, *cur;
if ((ret = net_prepare()) != 0) {
return ret;
}
/* Do name resolution with both IPv6 and IPv4 */
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
if (getaddrinfo(host, port, &hints, &addr_list) != 0) {
return MBEDTLS_ERR_NET_UNKNOWN_HOST;
}
/* Try the sockaddrs until a connection succeeds */
ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
for (cur = addr_list; cur != NULL; cur = cur->ai_next) {
ctx->fd = (int) socket(cur->ai_family, cur->ai_socktype,
cur->ai_protocol);
if (ctx->fd < 0) {
ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
continue;
}
if (connect(ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen) == 0) {
ret = 0;
break;
}
mbedtls_net_close(ctx);
ret = MBEDTLS_ERR_NET_CONNECT_FAILED;
}
freeaddrinfo(addr_list);
return ret;
}
/*
* Create a listening socket on bind_ip:port
*/
int mbedtls_net_bind(mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto)
{
int n, ret;
struct addrinfo hints, *addr_list, *cur;
if ((ret = net_prepare()) != 0) {
return ret;
}
/* Bind to IPv6 and/or IPv4, but only in the desired protocol */
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = proto == MBEDTLS_NET_PROTO_UDP ? SOCK_DGRAM : SOCK_STREAM;
hints.ai_protocol = proto == MBEDTLS_NET_PROTO_UDP ? IPPROTO_UDP : IPPROTO_TCP;
if (bind_ip == NULL) {
hints.ai_flags = AI_PASSIVE;
}
if (getaddrinfo(bind_ip, port, &hints, &addr_list) != 0) {
return MBEDTLS_ERR_NET_UNKNOWN_HOST;
}
/* Try the sockaddrs until a binding succeeds */
ret = MBEDTLS_ERR_NET_UNKNOWN_HOST;
for (cur = addr_list; cur != NULL; cur = cur->ai_next) {
ctx->fd = (int) socket(cur->ai_family, cur->ai_socktype,
cur->ai_protocol);
if (ctx->fd < 0) {
ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
continue;
}
n = 1;
if (setsockopt(ctx->fd, SOL_SOCKET, SO_REUSEADDR,
(const char *) &n, sizeof(n)) != 0) {
mbedtls_net_close(ctx);
ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
continue;
}
if (bind(ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen) != 0) {
mbedtls_net_close(ctx);
ret = MBEDTLS_ERR_NET_BIND_FAILED;
continue;
}
/* Listen only makes sense for TCP */
if (proto == MBEDTLS_NET_PROTO_TCP) {
if (listen(ctx->fd, MBEDTLS_NET_LISTEN_BACKLOG) != 0) {
mbedtls_net_close(ctx);
ret = MBEDTLS_ERR_NET_LISTEN_FAILED;
continue;
}
}
/* Bind was successful */
ret = 0;
break;
}
freeaddrinfo(addr_list);
return ret;
}
#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
!defined(EFI32)
/*
* Check if the requested operation would be blocking on a non-blocking socket
* and thus 'failed' with a negative return value.
*/
static int net_would_block(const mbedtls_net_context *ctx)
{
((void) ctx);
return WSAGetLastError() == WSAEWOULDBLOCK;
}
#else
/*
* Check if the requested operation would be blocking on a non-blocking socket
* and thus 'failed' with a negative return value.
*
* Note: on a blocking socket this function always returns 0!
*/
static int net_would_block(const mbedtls_net_context *ctx)
{
int err = errno;
/*
* Never return 'WOULD BLOCK' on a blocking socket
*/
if ((fcntl(ctx->fd, F_GETFL) & O_NONBLOCK) != O_NONBLOCK) {
errno = err;
return 0;
}
switch (errno = err) {
#if defined EAGAIN
case EAGAIN:
#endif
#if defined EWOULDBLOCK && EWOULDBLOCK != EAGAIN
case EWOULDBLOCK:
#endif
return 1;
}
return 0;
}
#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
/*
* Accept a connection from a remote client
*/
int mbedtls_net_accept(mbedtls_net_context *bind_ctx,
mbedtls_net_context *client_ctx,
void *client_ip, size_t buf_size, size_t *cip_len)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
int type;
struct sockaddr_storage client_addr;
#if defined(__socklen_t_defined) || defined(_SOCKLEN_T) || \
defined(_SOCKLEN_T_DECLARED) || defined(__DEFINED_socklen_t) || \
defined(socklen_t) || (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L)
socklen_t n = (socklen_t) sizeof(client_addr);
socklen_t type_len = (socklen_t) sizeof(type);
#else
int n = (int) sizeof(client_addr);
int type_len = (int) sizeof(type);
#endif
/* Is this a TCP or UDP socket? */
if (getsockopt(bind_ctx->fd, SOL_SOCKET, SO_TYPE,
(void *) &type, &type_len) != 0 ||
(type != SOCK_STREAM && type != SOCK_DGRAM)) {
return MBEDTLS_ERR_NET_ACCEPT_FAILED;
}
if (type == SOCK_STREAM) {
/* TCP: actual accept() */
ret = client_ctx->fd = (int) accept(bind_ctx->fd,
(struct sockaddr *) &client_addr, &n);
} else {
/* UDP: wait for a message, but keep it in the queue */
char buf[1] = { 0 };
ret = (int) recvfrom(bind_ctx->fd, buf, sizeof(buf), MSG_PEEK,
(struct sockaddr *) &client_addr, &n);
#if defined(_WIN32)
if (ret == SOCKET_ERROR &&
WSAGetLastError() == WSAEMSGSIZE) {
/* We know buf is too small, thanks, just peeking here */
ret = 0;
}
#endif
}
if (ret < 0) {
if (net_would_block(bind_ctx) != 0) {
return MBEDTLS_ERR_SSL_WANT_READ;
}
return MBEDTLS_ERR_NET_ACCEPT_FAILED;
}
/* UDP: hijack the listening socket to communicate with the client,
* then bind a new socket to accept new connections */
if (type != SOCK_STREAM) {
struct sockaddr_storage local_addr;
int one = 1;
if (connect(bind_ctx->fd, (struct sockaddr *) &client_addr, n) != 0) {
return MBEDTLS_ERR_NET_ACCEPT_FAILED;
}
client_ctx->fd = bind_ctx->fd;
bind_ctx->fd = -1; /* In case we exit early */
n = sizeof(struct sockaddr_storage);
if (getsockname(client_ctx->fd,
(struct sockaddr *) &local_addr, &n) != 0 ||
(bind_ctx->fd = (int) socket(local_addr.ss_family,
SOCK_DGRAM, IPPROTO_UDP)) < 0 ||
setsockopt(bind_ctx->fd, SOL_SOCKET, SO_REUSEADDR,
(const char *) &one, sizeof(one)) != 0) {
return MBEDTLS_ERR_NET_SOCKET_FAILED;
}
if (bind(bind_ctx->fd, (struct sockaddr *) &local_addr, n) != 0) {
return MBEDTLS_ERR_NET_BIND_FAILED;
}
}
if (client_ip != NULL) {
if (client_addr.ss_family == AF_INET) {
struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr;
*cip_len = sizeof(addr4->sin_addr.s_addr);
if (buf_size < *cip_len) {
return MBEDTLS_ERR_NET_BUFFER_TOO_SMALL;
}
memcpy(client_ip, &addr4->sin_addr.s_addr, *cip_len);
} else {
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr;
*cip_len = sizeof(addr6->sin6_addr.s6_addr);
if (buf_size < *cip_len) {
return MBEDTLS_ERR_NET_BUFFER_TOO_SMALL;
}
memcpy(client_ip, &addr6->sin6_addr.s6_addr, *cip_len);
}
}
return 0;
}
/*
* Set the socket blocking or non-blocking
*/
int mbedtls_net_set_block(mbedtls_net_context *ctx)
{
#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
!defined(EFI32)
u_long n = 0;
return ioctlsocket(ctx->fd, FIONBIO, &n);
#else
return fcntl(ctx->fd, F_SETFL, fcntl(ctx->fd, F_GETFL) & ~O_NONBLOCK);
#endif
}
int mbedtls_net_set_nonblock(mbedtls_net_context *ctx)
{
#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
!defined(EFI32)
u_long n = 1;
return ioctlsocket(ctx->fd, FIONBIO, &n);
#else
return fcntl(ctx->fd, F_SETFL, fcntl(ctx->fd, F_GETFL) | O_NONBLOCK);
#endif
}
/*
* Check if data is available on the socket
*/
int mbedtls_net_poll(mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
struct timeval tv;
fd_set read_fds;
fd_set write_fds;
int fd = ctx->fd;
ret = check_fd(fd, 1);
if (ret != 0) {
return ret;
}
#if defined(__has_feature)
#if __has_feature(memory_sanitizer)
/* Ensure that memory sanitizers consider read_fds and write_fds as
* initialized even on platforms such as Glibc/x86_64 where FD_ZERO
* is implemented in assembly. */
memset(&read_fds, 0, sizeof(read_fds));
memset(&write_fds, 0, sizeof(write_fds));
#endif
#endif
FD_ZERO(&read_fds);
if (rw & MBEDTLS_NET_POLL_READ) {
rw &= ~MBEDTLS_NET_POLL_READ;
FD_SET((SOCKET) fd, &read_fds);
}
FD_ZERO(&write_fds);
if (rw & MBEDTLS_NET_POLL_WRITE) {
rw &= ~MBEDTLS_NET_POLL_WRITE;
FD_SET((SOCKET) fd, &write_fds);
}
if (rw != 0) {
return MBEDTLS_ERR_NET_BAD_INPUT_DATA;
}
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
do {
ret = select(fd + 1, &read_fds, &write_fds, NULL,
timeout == (uint32_t) -1 ? NULL : &tv);
} while (IS_EINTR(ret));
if (ret < 0) {
return MBEDTLS_ERR_NET_POLL_FAILED;
}
ret = 0;
if (FD_ISSET(fd, &read_fds)) {
ret |= MBEDTLS_NET_POLL_READ;
}
if (FD_ISSET(fd, &write_fds)) {
ret |= MBEDTLS_NET_POLL_WRITE;
}
return ret;
}
/*
* Portable usleep helper
*/
void mbedtls_net_usleep(unsigned long usec)
{
#if defined(_WIN32)
Sleep((usec + 999) / 1000);
#else
struct timeval tv;
tv.tv_sec = usec / 1000000;
#if (defined(__unix__) || defined(__unix) || \
(defined(__APPLE__) && defined(__MACH__))) && !defined(__DJGPP__)
tv.tv_usec = (suseconds_t) usec % 1000000;
#else
tv.tv_usec = usec % 1000000;
#endif
select(0, NULL, NULL, NULL, &tv);
#endif
}
/*
* Read at most 'len' characters
*/
int mbedtls_net_recv(void *ctx, unsigned char *buf, size_t len)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
int fd = ((mbedtls_net_context *) ctx)->fd;
ret = check_fd(fd, 0);
if (ret != 0) {
return ret;
}
ret = (int) read(fd, buf, len);
if (ret < 0) {
if (net_would_block(ctx) != 0) {
return MBEDTLS_ERR_SSL_WANT_READ;
}
#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
!defined(EFI32)
if (WSAGetLastError() == WSAECONNRESET) {
return MBEDTLS_ERR_NET_CONN_RESET;
}
#else
if (errno == EPIPE || errno == ECONNRESET) {
return MBEDTLS_ERR_NET_CONN_RESET;
}
if (errno == EINTR) {
return MBEDTLS_ERR_SSL_WANT_READ;
}
#endif
return MBEDTLS_ERR_NET_RECV_FAILED;
}
return ret;
}
/*
* Read at most 'len' characters, blocking for at most 'timeout' ms
*/
int mbedtls_net_recv_timeout(void *ctx, unsigned char *buf,
size_t len, uint32_t timeout)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
struct timeval tv;
fd_set read_fds;
int fd = ((mbedtls_net_context *) ctx)->fd;
ret = check_fd(fd, 1);
if (ret != 0) {
return ret;
}
FD_ZERO(&read_fds);
FD_SET((SOCKET) fd, &read_fds);
tv.tv_sec = timeout / 1000;
tv.tv_usec = (timeout % 1000) * 1000;
ret = select(fd + 1, &read_fds, NULL, NULL, timeout == 0 ? NULL : &tv);
/* Zero fds ready means we timed out */
if (ret == 0) {
return MBEDTLS_ERR_SSL_TIMEOUT;
}
if (ret < 0) {
#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
!defined(EFI32)
if (WSAGetLastError() == WSAEINTR) {
return MBEDTLS_ERR_SSL_WANT_READ;
}
#else
if (errno == EINTR) {
return MBEDTLS_ERR_SSL_WANT_READ;
}
#endif
return MBEDTLS_ERR_NET_RECV_FAILED;
}
/* This call will not block */
return mbedtls_net_recv(ctx, buf, len);
}
/*
* Write at most 'len' characters
*/
int mbedtls_net_send(void *ctx, const unsigned char *buf, size_t len)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
int fd = ((mbedtls_net_context *) ctx)->fd;
ret = check_fd(fd, 0);
if (ret != 0) {
return ret;
}
ret = (int) write(fd, buf, len);
if (ret < 0) {
if (net_would_block(ctx) != 0) {
return MBEDTLS_ERR_SSL_WANT_WRITE;
}
#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \
!defined(EFI32)
if (WSAGetLastError() == WSAECONNRESET) {
return MBEDTLS_ERR_NET_CONN_RESET;
}
#else
if (errno == EPIPE || errno == ECONNRESET) {
return MBEDTLS_ERR_NET_CONN_RESET;
}
if (errno == EINTR) {
return MBEDTLS_ERR_SSL_WANT_WRITE;
}
#endif
return MBEDTLS_ERR_NET_SEND_FAILED;
}
return ret;
}
/*
* Close the connection
*/
void mbedtls_net_close(mbedtls_net_context *ctx)
{
if (ctx->fd == -1) {
return;
}
close(ctx->fd);
ctx->fd = -1;
}
/*
* Gracefully close the connection
*/
void mbedtls_net_free(mbedtls_net_context *ctx)
{
if (ctx == NULL || ctx->fd == -1) {
return;
}
shutdown(ctx->fd, 2);
close(ctx->fd);
ctx->fd = -1;
}
#endif /* MBEDTLS_NET_C */

729
thirdparty/mbedtls/library/nist_kw.c vendored Normal file
View File

@@ -0,0 +1,729 @@
/*
* Implementation of NIST SP 800-38F key wrapping, supporting KW and KWP modes
* only
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
/*
* Definition of Key Wrapping:
* https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf
* RFC 3394 "Advanced Encryption Standard (AES) Key Wrap Algorithm"
* RFC 5649 "Advanced Encryption Standard (AES) Key Wrap with Padding Algorithm"
*
* Note: RFC 3394 defines different methodology for intermediate operations for
* the wrapping and unwrapping operation than the definition in NIST SP 800-38F.
*/
#include "common.h"
#if defined(MBEDTLS_NIST_KW_C)
#include "mbedtls/nist_kw.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#include "mbedtls/constant_time.h"
#include "constant_time_internal.h"
#include <stdint.h>
#include <string.h>
#include "mbedtls/platform.h"
#if !defined(MBEDTLS_NIST_KW_ALT)
#define KW_SEMIBLOCK_LENGTH 8
#define MIN_SEMIBLOCKS_COUNT 3
/*! The 64-bit default integrity check value (ICV) for KW mode. */
static const unsigned char NIST_KW_ICV1[] = { 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6 };
/*! The 32-bit default integrity check value (ICV) for KWP mode. */
static const unsigned char NIST_KW_ICV2[] = { 0xA6, 0x59, 0x59, 0xA6 };
/*
* Initialize context
*/
void mbedtls_nist_kw_init(mbedtls_nist_kw_context *ctx)
{
memset(ctx, 0, sizeof(mbedtls_nist_kw_context));
}
int mbedtls_nist_kw_setkey(mbedtls_nist_kw_context *ctx,
mbedtls_cipher_id_t cipher,
const unsigned char *key,
unsigned int keybits,
const int is_wrap)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const mbedtls_cipher_info_t *cipher_info;
cipher_info = mbedtls_cipher_info_from_values(cipher,
keybits,
MBEDTLS_MODE_ECB);
if (cipher_info == NULL) {
return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
}
if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) {
return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
}
/*
* SP 800-38F currently defines AES cipher as the only block cipher allowed:
* "For KW and KWP, the underlying block cipher shall be approved, and the
* block size shall be 128 bits. Currently, the AES block cipher, with key
* lengths of 128, 192, or 256 bits, is the only block cipher that fits
* this profile."
* Currently we don't support other 128 bit block ciphers for key wrapping,
* such as Camellia and Aria.
*/
if (cipher != MBEDTLS_CIPHER_ID_AES) {
return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
}
mbedtls_cipher_free(&ctx->cipher_ctx);
if ((ret = mbedtls_cipher_setup(&ctx->cipher_ctx, cipher_info)) != 0) {
return ret;
}
if ((ret = mbedtls_cipher_setkey(&ctx->cipher_ctx, key, keybits,
is_wrap ? MBEDTLS_ENCRYPT :
MBEDTLS_DECRYPT)
) != 0) {
return ret;
}
return 0;
}
/*
* Free context
*/
void mbedtls_nist_kw_free(mbedtls_nist_kw_context *ctx)
{
if (ctx == NULL) {
return;
}
mbedtls_cipher_free(&ctx->cipher_ctx);
mbedtls_platform_zeroize(ctx, sizeof(mbedtls_nist_kw_context));
}
/*
* Helper function for Xoring the uint64_t "t" with the encrypted A.
* Defined in NIST SP 800-38F section 6.1
*/
static void calc_a_xor_t(unsigned char A[KW_SEMIBLOCK_LENGTH], uint64_t t)
{
size_t i = 0;
for (i = 0; i < sizeof(t); i++) {
A[i] ^= (t >> ((sizeof(t) - 1 - i) * 8)) & 0xff;
}
}
/*
* KW-AE as defined in SP 800-38F section 6.2
* KWP-AE as defined in SP 800-38F section 6.3
*/
int mbedtls_nist_kw_wrap(mbedtls_nist_kw_context *ctx,
mbedtls_nist_kw_mode_t mode,
const unsigned char *input, size_t in_len,
unsigned char *output, size_t *out_len, size_t out_size)
{
int ret = 0;
size_t semiblocks = 0;
size_t s;
size_t olen, padlen = 0;
uint64_t t = 0;
unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
*out_len = 0;
/*
* Generate the String to work on
*/
if (mode == MBEDTLS_KW_MODE_KW) {
if (out_size < in_len + KW_SEMIBLOCK_LENGTH) {
return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
}
/*
* According to SP 800-38F Table 1, the plaintext length for KW
* must be between 2 to 2^54-1 semiblocks inclusive.
*/
if (in_len < 16 ||
#if SIZE_MAX > 0x1FFFFFFFFFFFFF8
in_len > 0x1FFFFFFFFFFFFF8 ||
#endif
in_len % KW_SEMIBLOCK_LENGTH != 0) {
return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
}
memcpy(output, NIST_KW_ICV1, KW_SEMIBLOCK_LENGTH);
memmove(output + KW_SEMIBLOCK_LENGTH, input, in_len);
} else {
if (in_len % 8 != 0) {
padlen = (8 - (in_len % 8));
}
if (out_size < in_len + KW_SEMIBLOCK_LENGTH + padlen) {
return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
}
/*
* According to SP 800-38F Table 1, the plaintext length for KWP
* must be between 1 and 2^32-1 octets inclusive.
*/
if (in_len < 1
#if SIZE_MAX > 0xFFFFFFFF
|| in_len > 0xFFFFFFFF
#endif
) {
return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
}
memcpy(output, NIST_KW_ICV2, KW_SEMIBLOCK_LENGTH / 2);
MBEDTLS_PUT_UINT32_BE((in_len & 0xffffffff), output,
KW_SEMIBLOCK_LENGTH / 2);
memcpy(output + KW_SEMIBLOCK_LENGTH, input, in_len);
memset(output + KW_SEMIBLOCK_LENGTH + in_len, 0, padlen);
}
semiblocks = ((in_len + padlen) / KW_SEMIBLOCK_LENGTH) + 1;
s = 6 * (semiblocks - 1);
if (mode == MBEDTLS_KW_MODE_KWP
&& in_len <= KW_SEMIBLOCK_LENGTH) {
memcpy(inbuff, output, 16);
ret = mbedtls_cipher_update(&ctx->cipher_ctx,
inbuff, 16, output, &olen);
if (ret != 0) {
goto cleanup;
}
} else {
unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH;
unsigned char *A = output;
/*
* Do the wrapping function W, as defined in RFC 3394 section 2.2.1
*/
if (semiblocks < MIN_SEMIBLOCKS_COUNT) {
ret = MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
goto cleanup;
}
/* Calculate intermediate values */
for (t = 1; t <= s; t++) {
memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH);
memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R2, KW_SEMIBLOCK_LENGTH);
ret = mbedtls_cipher_update(&ctx->cipher_ctx,
inbuff, 16, outbuff, &olen);
if (ret != 0) {
goto cleanup;
}
memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
calc_a_xor_t(A, t);
memcpy(R2, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
R2 += KW_SEMIBLOCK_LENGTH;
if (R2 >= output + (semiblocks * KW_SEMIBLOCK_LENGTH)) {
R2 = output + KW_SEMIBLOCK_LENGTH;
}
}
}
*out_len = semiblocks * KW_SEMIBLOCK_LENGTH;
cleanup:
if (ret != 0) {
memset(output, 0, semiblocks * KW_SEMIBLOCK_LENGTH);
}
mbedtls_platform_zeroize(inbuff, KW_SEMIBLOCK_LENGTH * 2);
mbedtls_platform_zeroize(outbuff, KW_SEMIBLOCK_LENGTH * 2);
return ret;
}
/*
* W-1 function as defined in RFC 3394 section 2.2.2
* This function assumes the following:
* 1. Output buffer is at least of size ( semiblocks - 1 ) * KW_SEMIBLOCK_LENGTH.
* 2. The input buffer is of size semiblocks * KW_SEMIBLOCK_LENGTH.
* 3. Minimal number of semiblocks is 3.
* 4. A is a buffer to hold the first semiblock of the input buffer.
*/
static int unwrap(mbedtls_nist_kw_context *ctx,
const unsigned char *input, size_t semiblocks,
unsigned char A[KW_SEMIBLOCK_LENGTH],
unsigned char *output, size_t *out_len)
{
int ret = 0;
const size_t s = 6 * (semiblocks - 1);
size_t olen;
uint64_t t = 0;
unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];
unsigned char *R = NULL;
*out_len = 0;
if (semiblocks < MIN_SEMIBLOCKS_COUNT) {
return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
}
memcpy(A, input, KW_SEMIBLOCK_LENGTH);
memmove(output, input + KW_SEMIBLOCK_LENGTH, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH);
R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH;
/* Calculate intermediate values */
for (t = s; t >= 1; t--) {
calc_a_xor_t(A, t);
memcpy(inbuff, A, KW_SEMIBLOCK_LENGTH);
memcpy(inbuff + KW_SEMIBLOCK_LENGTH, R, KW_SEMIBLOCK_LENGTH);
ret = mbedtls_cipher_update(&ctx->cipher_ctx,
inbuff, 16, outbuff, &olen);
if (ret != 0) {
goto cleanup;
}
memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
/* Set R as LSB64 of outbuff */
memcpy(R, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
if (R == output) {
R = output + (semiblocks - 2) * KW_SEMIBLOCK_LENGTH;
} else {
R -= KW_SEMIBLOCK_LENGTH;
}
}
*out_len = (semiblocks - 1) * KW_SEMIBLOCK_LENGTH;
cleanup:
if (ret != 0) {
memset(output, 0, (semiblocks - 1) * KW_SEMIBLOCK_LENGTH);
}
mbedtls_platform_zeroize(inbuff, sizeof(inbuff));
mbedtls_platform_zeroize(outbuff, sizeof(outbuff));
return ret;
}
/*
* KW-AD as defined in SP 800-38F section 6.2
* KWP-AD as defined in SP 800-38F section 6.3
*/
int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx,
mbedtls_nist_kw_mode_t mode,
const unsigned char *input, size_t in_len,
unsigned char *output, size_t *out_len, size_t out_size)
{
int ret = 0;
size_t olen;
unsigned char A[KW_SEMIBLOCK_LENGTH];
int diff;
*out_len = 0;
if (out_size < in_len - KW_SEMIBLOCK_LENGTH) {
return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
}
if (mode == MBEDTLS_KW_MODE_KW) {
/*
* According to SP 800-38F Table 1, the ciphertext length for KW
* must be between 3 to 2^54 semiblocks inclusive.
*/
if (in_len < 24 ||
#if SIZE_MAX > 0x200000000000000
in_len > 0x200000000000000 ||
#endif
in_len % KW_SEMIBLOCK_LENGTH != 0) {
return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
}
ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
A, output, out_len);
if (ret != 0) {
goto cleanup;
}
/* Check ICV in "constant-time" */
diff = mbedtls_ct_memcmp(NIST_KW_ICV1, A, KW_SEMIBLOCK_LENGTH);
if (diff != 0) {
ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
goto cleanup;
}
} else if (mode == MBEDTLS_KW_MODE_KWP) {
size_t padlen = 0;
uint32_t Plen;
/*
* According to SP 800-38F Table 1, the ciphertext length for KWP
* must be between 2 to 2^29 semiblocks inclusive.
*/
if (in_len < KW_SEMIBLOCK_LENGTH * 2 ||
#if SIZE_MAX > 0x100000000
in_len > 0x100000000 ||
#endif
in_len % KW_SEMIBLOCK_LENGTH != 0) {
return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
}
if (in_len == KW_SEMIBLOCK_LENGTH * 2) {
unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
ret = mbedtls_cipher_update(&ctx->cipher_ctx,
input, 16, outbuff, &olen);
if (ret != 0) {
goto cleanup;
}
memcpy(A, outbuff, KW_SEMIBLOCK_LENGTH);
memcpy(output, outbuff + KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH);
mbedtls_platform_zeroize(outbuff, sizeof(outbuff));
*out_len = KW_SEMIBLOCK_LENGTH;
} else {
/* in_len >= KW_SEMIBLOCK_LENGTH * 3 */
ret = unwrap(ctx, input, in_len / KW_SEMIBLOCK_LENGTH,
A, output, out_len);
if (ret != 0) {
goto cleanup;
}
}
/* Check ICV in "constant-time" */
diff = mbedtls_ct_memcmp(NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2);
if (diff != 0) {
ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
}
Plen = MBEDTLS_GET_UINT32_BE(A, KW_SEMIBLOCK_LENGTH / 2);
/*
* Plen is the length of the plaintext, when the input is valid.
* If Plen is larger than the plaintext and padding, padlen will be
* larger than 8, because of the type wrap around.
*/
padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen;
ret = mbedtls_ct_error_if(mbedtls_ct_uint_gt(padlen, 7),
MBEDTLS_ERR_CIPHER_AUTH_FAILED, ret);
padlen &= 7;
/* Check padding in "constant-time" */
const uint8_t zero[KW_SEMIBLOCK_LENGTH] = { 0 };
diff = mbedtls_ct_memcmp_partial(
&output[*out_len - KW_SEMIBLOCK_LENGTH], zero,
KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH - padlen, 0);
if (diff != 0) {
ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
}
if (ret != 0) {
goto cleanup;
}
memset(output + Plen, 0, padlen);
*out_len = Plen;
} else {
ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
goto cleanup;
}
cleanup:
if (ret != 0) {
memset(output, 0, *out_len);
*out_len = 0;
}
mbedtls_platform_zeroize(&diff, sizeof(diff));
mbedtls_platform_zeroize(A, sizeof(A));
return ret;
}
#endif /* !MBEDTLS_NIST_KW_ALT */
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
/*
* Test vectors taken from NIST
* https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW
*/
static const unsigned int key_len[] = {
16,
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
24,
32
#endif
};
static const unsigned char kw_key[][32] = {
{ 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2,
0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 },
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
{ 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b,
0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d,
0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 },
{ 0x11, 0x2a, 0xd4, 0x1b, 0x48, 0x56, 0xc7, 0x25,
0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33,
0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d,
0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 }
#endif
};
static const unsigned char kw_msg[][40] = {
{ 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea,
0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f },
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
{ 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb,
0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d,
0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45,
0xc0, 0x9d, 0x15, 0x8f, 0x51, 0xce, 0x62, 0x9d,
0xe2, 0xaf, 0x26, 0xe3, 0x25, 0x0e, 0x6b, 0x4c },
{ 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7,
0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8,
0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 }
#endif
};
static const size_t kw_msg_len[] = {
16,
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
40,
24
#endif
};
static const size_t kw_out_len[] = {
24,
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
48,
32
#endif
};
static const unsigned char kw_res[][48] = {
{ 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d,
0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3,
0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb },
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
{ 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91,
0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec,
0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d,
0x6c, 0x42, 0x6f, 0xc6, 0x97, 0x15, 0x63, 0xe8,
0xa1, 0x4a, 0x55, 0x8e, 0x09, 0x64, 0x16, 0x19,
0xbf, 0x03, 0xfc, 0xaf, 0x90, 0xb1, 0xfc, 0x2d },
{ 0xba, 0x8a, 0x25, 0x9a, 0x47, 0x1b, 0x78, 0x7d,
0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87,
0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9,
0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 }
#endif
};
static const unsigned char kwp_key[][32] = {
{ 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a,
0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 },
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
{ 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98,
0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7,
0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 },
{ 0x95, 0xda, 0x27, 0x00, 0xca, 0x6f, 0xd9, 0xa5,
0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f,
0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae,
0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a }
#endif
};
static const unsigned char kwp_msg[][31] = {
{ 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8,
0x96 },
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
{ 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb,
0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19,
0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66,
0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f },
{ 0xd1 }
#endif
};
static const size_t kwp_msg_len[] = {
9,
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
31,
1
#endif
};
static const unsigned char kwp_res[][48] = {
{ 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e,
0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7,
0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 },
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
{ 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13,
0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88,
0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63,
0x8b, 0xcc, 0x81, 0x66, 0x84, 0x68, 0x17, 0x90,
0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 },
{ 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd,
0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4 }
#endif
};
static const size_t kwp_out_len[] = {
24,
#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
40,
16
#endif
};
int mbedtls_nist_kw_self_test(int verbose)
{
mbedtls_nist_kw_context ctx;
unsigned char out[48];
size_t olen;
int i;
int ret = 0;
mbedtls_nist_kw_init(&ctx);
/*
* KW mode
*/
{
static const int num_tests = sizeof(kw_key) / sizeof(*kw_key);
for (i = 0; i < num_tests; i++) {
if (verbose != 0) {
mbedtls_printf(" KW-AES-%u ", (unsigned int) key_len[i] * 8);
}
ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
kw_key[i], key_len[i] * 8, 1);
if (ret != 0) {
if (verbose != 0) {
mbedtls_printf(" KW: setup failed ");
}
goto end;
}
ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KW, kw_msg[i],
kw_msg_len[i], out, &olen, sizeof(out));
if (ret != 0 || kw_out_len[i] != olen ||
memcmp(out, kw_res[i], kw_out_len[i]) != 0) {
if (verbose != 0) {
mbedtls_printf("failed. ");
}
ret = 1;
goto end;
}
if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
kw_key[i], key_len[i] * 8, 0))
!= 0) {
if (verbose != 0) {
mbedtls_printf(" KW: setup failed ");
}
goto end;
}
ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KW,
out, olen, out, &olen, sizeof(out));
if (ret != 0 || olen != kw_msg_len[i] ||
memcmp(out, kw_msg[i], kw_msg_len[i]) != 0) {
if (verbose != 0) {
mbedtls_printf("failed\n");
}
ret = 1;
goto end;
}
if (verbose != 0) {
mbedtls_printf(" passed\n");
}
}
}
/*
* KWP mode
*/
{
static const int num_tests = sizeof(kwp_key) / sizeof(*kwp_key);
for (i = 0; i < num_tests; i++) {
olen = sizeof(out);
if (verbose != 0) {
mbedtls_printf(" KWP-AES-%u ", (unsigned int) key_len[i] * 8);
}
ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i],
key_len[i] * 8, 1);
if (ret != 0) {
if (verbose != 0) {
mbedtls_printf(" KWP: setup failed ");
}
goto end;
}
ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i],
kwp_msg_len[i], out, &olen, sizeof(out));
if (ret != 0 || kwp_out_len[i] != olen ||
memcmp(out, kwp_res[i], kwp_out_len[i]) != 0) {
if (verbose != 0) {
mbedtls_printf("failed. ");
}
ret = 1;
goto end;
}
if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
kwp_key[i], key_len[i] * 8, 0))
!= 0) {
if (verbose != 0) {
mbedtls_printf(" KWP: setup failed ");
}
goto end;
}
ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KWP, out,
olen, out, &olen, sizeof(out));
if (ret != 0 || olen != kwp_msg_len[i] ||
memcmp(out, kwp_msg[i], kwp_msg_len[i]) != 0) {
if (verbose != 0) {
mbedtls_printf("failed. ");
}
ret = 1;
goto end;
}
if (verbose != 0) {
mbedtls_printf(" passed\n");
}
}
}
end:
mbedtls_nist_kw_free(&ctx);
if (verbose != 0) {
mbedtls_printf("\n");
}
return ret;
}
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
#endif /* MBEDTLS_NIST_KW_C */

1166
thirdparty/mbedtls/library/oid.c vendored Normal file

File diff suppressed because it is too large Load Diff

157
thirdparty/mbedtls/library/padlock.c vendored Normal file
View File

@@ -0,0 +1,157 @@
/*
* VIA PadLock support functions
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
/*
* This implementation is based on the VIA PadLock Programming Guide:
*
* http://www.via.com.tw/en/downloads/whitepapers/initiatives/padlock/
* programming_guide.pdf
*/
#include "common.h"
#if defined(MBEDTLS_PADLOCK_C)
#include "padlock.h"
#include <string.h>
#if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)
/*
* PadLock detection routine
*/
int mbedtls_padlock_has_support(int feature)
{
static int flags = -1;
int ebx = 0, edx = 0;
if (flags == -1) {
asm ("movl %%ebx, %0 \n\t"
"movl $0xC0000000, %%eax \n\t"
"cpuid \n\t"
"cmpl $0xC0000001, %%eax \n\t"
"movl $0, %%edx \n\t"
"jb 1f \n\t"
"movl $0xC0000001, %%eax \n\t"
"cpuid \n\t"
"1: \n\t"
"movl %%edx, %1 \n\t"
"movl %2, %%ebx \n\t"
: "=m" (ebx), "=m" (edx)
: "m" (ebx)
: "eax", "ecx", "edx");
flags = edx;
}
return flags & feature;
}
/*
* PadLock AES-ECB block en(de)cryption
*/
int mbedtls_padlock_xcryptecb(mbedtls_aes_context *ctx,
int mode,
const unsigned char input[16],
unsigned char output[16])
{
int ebx = 0;
uint32_t *rk;
uint32_t *blk;
uint32_t *ctrl;
unsigned char buf[256];
rk = ctx->buf + ctx->rk_offset;
if (((long) rk & 15) != 0) {
return MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED;
}
blk = MBEDTLS_PADLOCK_ALIGN16(buf);
memcpy(blk, input, 16);
ctrl = blk + 4;
*ctrl = 0x80 | ctx->nr | ((ctx->nr + (mode^1) - 10) << 9);
asm ("pushfl \n\t"
"popfl \n\t"
"movl %%ebx, %0 \n\t"
"movl $1, %%ecx \n\t"
"movl %2, %%edx \n\t"
"movl %3, %%ebx \n\t"
"movl %4, %%esi \n\t"
"movl %4, %%edi \n\t"
".byte 0xf3,0x0f,0xa7,0xc8 \n\t"
"movl %1, %%ebx \n\t"
: "=m" (ebx)
: "m" (ebx), "m" (ctrl), "m" (rk), "m" (blk)
: "memory", "ecx", "edx", "esi", "edi");
memcpy(output, blk, 16);
return 0;
}
#if defined(MBEDTLS_CIPHER_MODE_CBC)
/*
* PadLock AES-CBC buffer en(de)cryption
*/
int mbedtls_padlock_xcryptcbc(mbedtls_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output)
{
int ebx = 0;
size_t count;
uint32_t *rk;
uint32_t *iw;
uint32_t *ctrl;
unsigned char buf[256];
rk = ctx->buf + ctx->rk_offset;
if (((long) input & 15) != 0 ||
((long) output & 15) != 0 ||
((long) rk & 15) != 0) {
return MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED;
}
iw = MBEDTLS_PADLOCK_ALIGN16(buf);
memcpy(iw, iv, 16);
ctrl = iw + 4;
*ctrl = 0x80 | ctx->nr | ((ctx->nr + (mode ^ 1) - 10) << 9);
count = (length + 15) >> 4;
asm ("pushfl \n\t"
"popfl \n\t"
"movl %%ebx, %0 \n\t"
"movl %2, %%ecx \n\t"
"movl %3, %%edx \n\t"
"movl %4, %%ebx \n\t"
"movl %5, %%esi \n\t"
"movl %6, %%edi \n\t"
"movl %7, %%eax \n\t"
".byte 0xf3,0x0f,0xa7,0xd0 \n\t"
"movl %1, %%ebx \n\t"
: "=m" (ebx)
: "m" (ebx), "m" (count), "m" (ctrl),
"m" (rk), "m" (input), "m" (output), "m" (iw)
: "memory", "eax", "ecx", "edx", "esi", "edi");
memcpy(iv, iw, 16);
return 0;
}
#endif /* MBEDTLS_CIPHER_MODE_CBC */
#endif /* MBEDTLS_VIA_PADLOCK_HAVE_CODE */
#endif /* MBEDTLS_PADLOCK_C */

111
thirdparty/mbedtls/library/padlock.h vendored Normal file
View File

@@ -0,0 +1,111 @@
/**
* \file padlock.h
*
* \brief VIA PadLock ACE for HW encryption/decryption supported by some
* processors
*
* \warning These functions are only for internal use by other library
* functions; you must not call them directly.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef MBEDTLS_PADLOCK_H
#define MBEDTLS_PADLOCK_H
#include "mbedtls/build_info.h"
#include "mbedtls/aes.h"
#define MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED -0x0030 /**< Input data should be aligned. */
#if defined(__has_feature)
#if __has_feature(address_sanitizer)
#define MBEDTLS_HAVE_ASAN
#endif
#endif
/*
* - `padlock` is implements with GNUC assembly for x86 target.
* - Some versions of ASan result in errors about not enough registers.
*/
#if defined(MBEDTLS_PADLOCK_C) && \
defined(__GNUC__) && defined(MBEDTLS_ARCH_IS_X86) && \
defined(MBEDTLS_HAVE_ASM) && \
!defined(MBEDTLS_HAVE_ASAN)
#define MBEDTLS_VIA_PADLOCK_HAVE_CODE
#include <stdint.h>
#define MBEDTLS_PADLOCK_RNG 0x000C
#define MBEDTLS_PADLOCK_ACE 0x00C0
#define MBEDTLS_PADLOCK_PHE 0x0C00
#define MBEDTLS_PADLOCK_PMM 0x3000
#define MBEDTLS_PADLOCK_ALIGN16(x) (uint32_t *) (16 + ((int32_t) (x) & ~15))
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Internal PadLock detection routine
*
* \note This function is only for internal use by other library
* functions; you must not call it directly.
*
* \param feature The feature to detect
*
* \return non-zero if CPU has support for the feature, 0 otherwise
*/
int mbedtls_padlock_has_support(int feature);
/**
* \brief Internal PadLock AES-ECB block en(de)cryption
*
* \note This function is only for internal use by other library
* functions; you must not call it directly.
*
* \param ctx AES context
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
* \param input 16-byte input block
* \param output 16-byte output block
*
* \return 0 if success, 1 if operation failed
*/
int mbedtls_padlock_xcryptecb(mbedtls_aes_context *ctx,
int mode,
const unsigned char input[16],
unsigned char output[16]);
/**
* \brief Internal PadLock AES-CBC buffer en(de)cryption
*
* \note This function is only for internal use by other library
* functions; you must not call it directly.
*
* \param ctx AES context
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if success, 1 if operation failed
*/
int mbedtls_padlock_xcryptcbc(mbedtls_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output);
#ifdef __cplusplus
}
#endif
#endif /* HAVE_X86 */
#endif /* padlock.h */

554
thirdparty/mbedtls/library/pem.c vendored Normal file
View File

@@ -0,0 +1,554 @@
/*
* Privacy Enhanced Mail (PEM) decoding
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C)
#include "mbedtls/pem.h"
#include "mbedtls/base64.h"
#include "mbedtls/des.h"
#include "mbedtls/aes.h"
#include "mbedtls/md.h"
#include "mbedtls/cipher.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#include <string.h>
#include "mbedtls/platform.h"
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#include "psa/crypto.h"
#endif
#if defined(MBEDTLS_MD_CAN_MD5) && \
defined(MBEDTLS_CIPHER_MODE_CBC) && \
(defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C))
#define PEM_RFC1421
#endif /* MBEDTLS_MD_CAN_MD5 &&
MBEDTLS_CIPHER_MODE_CBC &&
( MBEDTLS_AES_C || MBEDTLS_DES_C ) */
#if defined(MBEDTLS_PEM_PARSE_C)
void mbedtls_pem_init(mbedtls_pem_context *ctx)
{
memset(ctx, 0, sizeof(mbedtls_pem_context));
}
#if defined(PEM_RFC1421)
/*
* Read a 16-byte hex string and convert it to binary
*/
static int pem_get_iv(const unsigned char *s, unsigned char *iv,
size_t iv_len)
{
size_t i, j, k;
memset(iv, 0, iv_len);
for (i = 0; i < iv_len * 2; i++, s++) {
if (*s >= '0' && *s <= '9') {
j = *s - '0';
} else
if (*s >= 'A' && *s <= 'F') {
j = *s - '7';
} else
if (*s >= 'a' && *s <= 'f') {
j = *s - 'W';
} else {
return MBEDTLS_ERR_PEM_INVALID_ENC_IV;
}
k = ((i & 1) != 0) ? j : j << 4;
iv[i >> 1] = (unsigned char) (iv[i >> 1] | k);
}
return 0;
}
static int pem_pbkdf1(unsigned char *key, size_t keylen,
unsigned char *iv,
const unsigned char *pwd, size_t pwdlen)
{
mbedtls_md_context_t md5_ctx;
const mbedtls_md_info_t *md5_info;
unsigned char md5sum[16];
size_t use_len;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_md_init(&md5_ctx);
/* Prepare the context. (setup() errors gracefully on NULL info.) */
md5_info = mbedtls_md_info_from_type(MBEDTLS_MD_MD5);
if ((ret = mbedtls_md_setup(&md5_ctx, md5_info, 0)) != 0) {
goto exit;
}
/*
* key[ 0..15] = MD5(pwd || IV)
*/
if ((ret = mbedtls_md_starts(&md5_ctx)) != 0) {
goto exit;
}
if ((ret = mbedtls_md_update(&md5_ctx, pwd, pwdlen)) != 0) {
goto exit;
}
if ((ret = mbedtls_md_update(&md5_ctx, iv, 8)) != 0) {
goto exit;
}
if ((ret = mbedtls_md_finish(&md5_ctx, md5sum)) != 0) {
goto exit;
}
if (keylen <= 16) {
memcpy(key, md5sum, keylen);
goto exit;
}
memcpy(key, md5sum, 16);
/*
* key[16..23] = MD5(key[ 0..15] || pwd || IV])
*/
if ((ret = mbedtls_md_starts(&md5_ctx)) != 0) {
goto exit;
}
if ((ret = mbedtls_md_update(&md5_ctx, md5sum, 16)) != 0) {
goto exit;
}
if ((ret = mbedtls_md_update(&md5_ctx, pwd, pwdlen)) != 0) {
goto exit;
}
if ((ret = mbedtls_md_update(&md5_ctx, iv, 8)) != 0) {
goto exit;
}
if ((ret = mbedtls_md_finish(&md5_ctx, md5sum)) != 0) {
goto exit;
}
use_len = 16;
if (keylen < 32) {
use_len = keylen - 16;
}
memcpy(key + 16, md5sum, use_len);
exit:
mbedtls_md_free(&md5_ctx);
mbedtls_platform_zeroize(md5sum, 16);
return ret;
}
#if defined(MBEDTLS_DES_C)
/*
* Decrypt with DES-CBC, using PBKDF1 for key derivation
*/
static int pem_des_decrypt(unsigned char des_iv[8],
unsigned char *buf, size_t buflen,
const unsigned char *pwd, size_t pwdlen)
{
mbedtls_des_context des_ctx;
unsigned char des_key[8];
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_des_init(&des_ctx);
if ((ret = pem_pbkdf1(des_key, 8, des_iv, pwd, pwdlen)) != 0) {
goto exit;
}
if ((ret = mbedtls_des_setkey_dec(&des_ctx, des_key)) != 0) {
goto exit;
}
ret = mbedtls_des_crypt_cbc(&des_ctx, MBEDTLS_DES_DECRYPT, buflen,
des_iv, buf, buf);
exit:
mbedtls_des_free(&des_ctx);
mbedtls_platform_zeroize(des_key, 8);
return ret;
}
/*
* Decrypt with 3DES-CBC, using PBKDF1 for key derivation
*/
static int pem_des3_decrypt(unsigned char des3_iv[8],
unsigned char *buf, size_t buflen,
const unsigned char *pwd, size_t pwdlen)
{
mbedtls_des3_context des3_ctx;
unsigned char des3_key[24];
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_des3_init(&des3_ctx);
if ((ret = pem_pbkdf1(des3_key, 24, des3_iv, pwd, pwdlen)) != 0) {
goto exit;
}
if ((ret = mbedtls_des3_set3key_dec(&des3_ctx, des3_key)) != 0) {
goto exit;
}
ret = mbedtls_des3_crypt_cbc(&des3_ctx, MBEDTLS_DES_DECRYPT, buflen,
des3_iv, buf, buf);
exit:
mbedtls_des3_free(&des3_ctx);
mbedtls_platform_zeroize(des3_key, 24);
return ret;
}
#endif /* MBEDTLS_DES_C */
#if defined(MBEDTLS_AES_C)
/*
* Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation
*/
static int pem_aes_decrypt(unsigned char aes_iv[16], unsigned int keylen,
unsigned char *buf, size_t buflen,
const unsigned char *pwd, size_t pwdlen)
{
mbedtls_aes_context aes_ctx;
unsigned char aes_key[32];
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_aes_init(&aes_ctx);
if ((ret = pem_pbkdf1(aes_key, keylen, aes_iv, pwd, pwdlen)) != 0) {
goto exit;
}
if ((ret = mbedtls_aes_setkey_dec(&aes_ctx, aes_key, keylen * 8)) != 0) {
goto exit;
}
ret = mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_DECRYPT, buflen,
aes_iv, buf, buf);
exit:
mbedtls_aes_free(&aes_ctx);
mbedtls_platform_zeroize(aes_key, keylen);
return ret;
}
#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 not guaranteed by mbedtls_pem_read_buffer(). */
if (input_len < 1) {
return MBEDTLS_ERR_PEM_INVALID_DATA;
}
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,
const unsigned char *data, const unsigned char *pwd,
size_t pwdlen, size_t *use_len)
{
int ret, enc;
size_t len;
unsigned char *buf;
const unsigned char *s1, *s2, *end;
#if defined(PEM_RFC1421)
unsigned char pem_iv[16];
mbedtls_cipher_type_t enc_alg = MBEDTLS_CIPHER_NONE;
#else
((void) pwd);
((void) pwdlen);
#endif /* PEM_RFC1421 */
if (ctx == NULL) {
return MBEDTLS_ERR_PEM_BAD_INPUT_DATA;
}
s1 = (unsigned char *) strstr((const char *) data, header);
if (s1 == NULL) {
return MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
}
s2 = (unsigned char *) strstr((const char *) data, footer);
if (s2 == NULL || s2 <= s1) {
return MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
}
s1 += strlen(header);
if (*s1 == ' ') {
s1++;
}
if (*s1 == '\r') {
s1++;
}
if (*s1 == '\n') {
s1++;
} else {
return MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
}
end = s2;
end += strlen(footer);
if (*end == ' ') {
end++;
}
if (*end == '\r') {
end++;
}
if (*end == '\n') {
end++;
}
*use_len = (size_t) (end - data);
enc = 0;
if (s2 - s1 >= 22 && memcmp(s1, "Proc-Type: 4,ENCRYPTED", 22) == 0) {
#if defined(PEM_RFC1421)
enc++;
s1 += 22;
if (*s1 == '\r') {
s1++;
}
if (*s1 == '\n') {
s1++;
} else {
return MBEDTLS_ERR_PEM_INVALID_DATA;
}
#if defined(MBEDTLS_DES_C)
if (s2 - s1 >= 23 && memcmp(s1, "DEK-Info: DES-EDE3-CBC,", 23) == 0) {
enc_alg = MBEDTLS_CIPHER_DES_EDE3_CBC;
s1 += 23;
if (s2 - s1 < 16 || pem_get_iv(s1, pem_iv, 8) != 0) {
return MBEDTLS_ERR_PEM_INVALID_ENC_IV;
}
s1 += 16;
} else if (s2 - s1 >= 18 && memcmp(s1, "DEK-Info: DES-CBC,", 18) == 0) {
enc_alg = MBEDTLS_CIPHER_DES_CBC;
s1 += 18;
if (s2 - s1 < 16 || pem_get_iv(s1, pem_iv, 8) != 0) {
return MBEDTLS_ERR_PEM_INVALID_ENC_IV;
}
s1 += 16;
}
#endif /* MBEDTLS_DES_C */
#if defined(MBEDTLS_AES_C)
if (s2 - s1 >= 14 && memcmp(s1, "DEK-Info: AES-", 14) == 0) {
if (s2 - s1 < 22) {
return MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG;
} else if (memcmp(s1, "DEK-Info: AES-128-CBC,", 22) == 0) {
enc_alg = MBEDTLS_CIPHER_AES_128_CBC;
} else if (memcmp(s1, "DEK-Info: AES-192-CBC,", 22) == 0) {
enc_alg = MBEDTLS_CIPHER_AES_192_CBC;
} else if (memcmp(s1, "DEK-Info: AES-256-CBC,", 22) == 0) {
enc_alg = MBEDTLS_CIPHER_AES_256_CBC;
} else {
return MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG;
}
s1 += 22;
if (s2 - s1 < 32 || pem_get_iv(s1, pem_iv, 16) != 0) {
return MBEDTLS_ERR_PEM_INVALID_ENC_IV;
}
s1 += 32;
}
#endif /* MBEDTLS_AES_C */
if (enc_alg == MBEDTLS_CIPHER_NONE) {
return MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG;
}
if (*s1 == '\r') {
s1++;
}
if (*s1 == '\n') {
s1++;
} else {
return MBEDTLS_ERR_PEM_INVALID_DATA;
}
#else
return MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE;
#endif /* PEM_RFC1421 */
}
if (s1 >= s2) {
return MBEDTLS_ERR_PEM_INVALID_DATA;
}
ret = mbedtls_base64_decode(NULL, 0, &len, s1, (size_t) (s2 - s1));
if (ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER) {
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;
}
if ((ret = mbedtls_base64_decode(buf, len, &len, s1, (size_t) (s2 - s1))) != 0) {
mbedtls_zeroize_and_free(buf, len);
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PEM_INVALID_DATA, ret);
}
if (enc != 0) {
#if defined(PEM_RFC1421)
if (pwd == NULL) {
mbedtls_zeroize_and_free(buf, len);
return MBEDTLS_ERR_PEM_PASSWORD_REQUIRED;
}
ret = 0;
#if defined(MBEDTLS_DES_C)
if (enc_alg == MBEDTLS_CIPHER_DES_EDE3_CBC) {
ret = pem_des3_decrypt(pem_iv, buf, len, pwd, pwdlen);
} else if (enc_alg == MBEDTLS_CIPHER_DES_CBC) {
ret = pem_des_decrypt(pem_iv, buf, len, pwd, pwdlen);
}
#endif /* MBEDTLS_DES_C */
#if defined(MBEDTLS_AES_C)
if (enc_alg == MBEDTLS_CIPHER_AES_128_CBC) {
ret = pem_aes_decrypt(pem_iv, 16, buf, len, pwd, pwdlen);
} else if (enc_alg == MBEDTLS_CIPHER_AES_192_CBC) {
ret = pem_aes_decrypt(pem_iv, 24, buf, len, pwd, pwdlen);
} else if (enc_alg == MBEDTLS_CIPHER_AES_256_CBC) {
ret = pem_aes_decrypt(pem_iv, 32, buf, len, pwd, pwdlen);
}
#endif /* MBEDTLS_AES_C */
if (ret != 0) {
mbedtls_zeroize_and_free(buf, len);
return ret;
}
/* 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 ret;
}
len = unpadded_len;
#else
mbedtls_zeroize_and_free(buf, len);
return MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE;
#endif /* PEM_RFC1421 */
}
ctx->buf = buf;
ctx->buflen = len;
return 0;
}
void mbedtls_pem_free(mbedtls_pem_context *ctx)
{
if (ctx == NULL) {
return;
}
if (ctx->buf != NULL) {
mbedtls_zeroize_and_free(ctx->buf, ctx->buflen);
}
mbedtls_free(ctx->info);
mbedtls_platform_zeroize(ctx, sizeof(mbedtls_pem_context));
}
#endif /* MBEDTLS_PEM_PARSE_C */
#if defined(MBEDTLS_PEM_WRITE_C)
int mbedtls_pem_write_buffer(const char *header, const char *footer,
const unsigned char *der_data, size_t der_len,
unsigned char *buf, size_t buf_len, size_t *olen)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *encode_buf = NULL, *c, *p = buf;
size_t len = 0, use_len, add_len = 0;
mbedtls_base64_encode(NULL, 0, &use_len, der_data, der_len);
add_len = strlen(header) + strlen(footer) + (((use_len > 2) ? (use_len - 2) : 0) / 64) + 1;
if (use_len + add_len > buf_len) {
*olen = use_len + add_len;
return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL;
}
if (use_len != 0 &&
((encode_buf = mbedtls_calloc(1, use_len)) == NULL)) {
return MBEDTLS_ERR_PEM_ALLOC_FAILED;
}
if ((ret = mbedtls_base64_encode(encode_buf, use_len, &use_len, der_data,
der_len)) != 0) {
mbedtls_free(encode_buf);
return ret;
}
memcpy(p, header, strlen(header));
p += strlen(header);
c = encode_buf;
while (use_len) {
len = (use_len > 64) ? 64 : use_len;
memcpy(p, c, len);
use_len -= len;
p += len;
c += len;
*p++ = '\n';
}
memcpy(p, footer, strlen(footer));
p += strlen(footer);
*p++ = '\0';
*olen = (size_t) (p - buf);
/* Clean any remaining data previously written to the buffer */
memset(buf + *olen, 0, buf_len - *olen);
mbedtls_free(encode_buf);
return 0;
}
#endif /* MBEDTLS_PEM_WRITE_C */
#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */

1503
thirdparty/mbedtls/library/pk.c vendored Normal file

File diff suppressed because it is too large Load Diff

255
thirdparty/mbedtls/library/pk_ecc.c vendored Normal file
View File

@@ -0,0 +1,255 @@
/*
* ECC setters for PK.
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#include "mbedtls/pk.h"
#include "mbedtls/error.h"
#include "mbedtls/ecp.h"
#include "pk_internal.h"
#if defined(MBEDTLS_PK_C) && defined(MBEDTLS_PK_HAVE_ECC_KEYS)
int mbedtls_pk_ecc_set_group(mbedtls_pk_context *pk, mbedtls_ecp_group_id grp_id)
{
#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
size_t ec_bits;
psa_ecc_family_t ec_family = mbedtls_ecc_group_to_psa(grp_id, &ec_bits);
/* group may already be initialized; if so, make sure IDs match */
if ((pk->ec_family != 0 && pk->ec_family != ec_family) ||
(pk->ec_bits != 0 && pk->ec_bits != ec_bits)) {
return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
}
/* set group */
pk->ec_family = ec_family;
pk->ec_bits = ec_bits;
return 0;
#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
mbedtls_ecp_keypair *ecp = mbedtls_pk_ec_rw(*pk);
/* grp may already be initialized; if so, make sure IDs match */
if (mbedtls_pk_ec_ro(*pk)->grp.id != MBEDTLS_ECP_DP_NONE &&
mbedtls_pk_ec_ro(*pk)->grp.id != grp_id) {
return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
}
/* set group */
return mbedtls_ecp_group_load(&(ecp->grp), grp_id);
#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
}
int mbedtls_pk_ecc_set_key(mbedtls_pk_context *pk, unsigned char *key, size_t key_len)
{
#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_usage_t flags;
psa_status_t status;
psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(pk->ec_family));
if (pk->ec_family == PSA_ECC_FAMILY_MONTGOMERY) {
/* Do not set algorithm here because Montgomery keys cannot do ECDSA and
* the PK module cannot do ECDH. When the key will be used in TLS for
* ECDH, it will be exported and then re-imported with proper flags
* and algorithm. */
flags = PSA_KEY_USAGE_EXPORT;
} else {
psa_set_key_algorithm(&attributes,
MBEDTLS_PK_PSA_ALG_ECDSA_MAYBE_DET(PSA_ALG_ANY_HASH));
flags = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE |
PSA_KEY_USAGE_EXPORT;
}
psa_set_key_usage_flags(&attributes, flags);
status = psa_import_key(&attributes, key, key_len, &pk->priv_id);
return psa_pk_status_to_mbedtls(status);
#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
mbedtls_ecp_keypair *eck = mbedtls_pk_ec_rw(*pk);
int ret = mbedtls_ecp_read_key(eck->grp.id, eck, key, key_len);
if (ret != 0) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
}
return 0;
#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
}
int mbedtls_pk_ecc_set_pubkey_from_prv(mbedtls_pk_context *pk,
const unsigned char *prv, size_t prv_len,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
{
#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
(void) f_rng;
(void) p_rng;
(void) prv;
(void) prv_len;
psa_status_t status;
status = psa_export_public_key(pk->priv_id, pk->pub_raw, sizeof(pk->pub_raw),
&pk->pub_raw_len);
return psa_pk_status_to_mbedtls(status);
#elif defined(MBEDTLS_USE_PSA_CRYPTO) /* && !MBEDTLS_PK_USE_PSA_EC_DATA */
(void) f_rng;
(void) p_rng;
psa_status_t status;
mbedtls_ecp_keypair *eck = (mbedtls_ecp_keypair *) pk->pk_ctx;
size_t curve_bits;
psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(eck->grp.id, &curve_bits);
/* Import private key into PSA, from serialized input */
mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(curve));
psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT);
status = psa_import_key(&key_attr, prv, prv_len, &key_id);
if (status != PSA_SUCCESS) {
return psa_pk_status_to_mbedtls(status);
}
/* Export public key from PSA */
unsigned char pub[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH];
size_t pub_len;
status = psa_export_public_key(key_id, pub, sizeof(pub), &pub_len);
psa_status_t destruction_status = psa_destroy_key(key_id);
if (status != PSA_SUCCESS) {
return psa_pk_status_to_mbedtls(status);
} else if (destruction_status != PSA_SUCCESS) {
return psa_pk_status_to_mbedtls(destruction_status);
}
/* Load serialized public key into ecp_keypair structure */
return mbedtls_ecp_point_read_binary(&eck->grp, &eck->Q, pub, pub_len);
#else /* MBEDTLS_USE_PSA_CRYPTO */
(void) prv;
(void) prv_len;
mbedtls_ecp_keypair *eck = (mbedtls_ecp_keypair *) pk->pk_ctx;
return mbedtls_ecp_mul(&eck->grp, &eck->Q, &eck->d, &eck->grp.G, f_rng, p_rng);
#endif /* MBEDTLS_USE_PSA_CRYPTO */
}
#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
/*
* Set the public key: fallback using ECP_LIGHT in the USE_PSA_EC_DATA case.
*
* Normally, when MBEDTLS_PK_USE_PSA_EC_DATA is enabled, we only use PSA
* functions to handle keys. However, currently psa_import_key() does not
* support compressed points. In case that support was explicitly requested,
* this fallback uses ECP functions to get the job done. This is the reason
* why MBEDTLS_PK_PARSE_EC_COMPRESSED auto-enables MBEDTLS_ECP_LIGHT.
*
* [in/out] pk: in: must have the group set, see mbedtls_pk_ecc_set_group().
* out: will have the public key set.
* [in] pub, pub_len: the public key as an ECPoint,
* in any format supported by ECP.
*
* Return:
* - 0 on success;
* - MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the format is potentially valid
* but not supported;
* - another error code otherwise.
*/
static int pk_ecc_set_pubkey_psa_ecp_fallback(mbedtls_pk_context *pk,
const unsigned char *pub,
size_t pub_len)
{
#if !defined(MBEDTLS_PK_PARSE_EC_COMPRESSED)
(void) pk;
(void) pub;
(void) pub_len;
return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
#else /* MBEDTLS_PK_PARSE_EC_COMPRESSED */
mbedtls_ecp_keypair ecp_key;
mbedtls_ecp_group_id ecp_group_id;
int ret;
ecp_group_id = mbedtls_ecc_group_from_psa(pk->ec_family, pk->ec_bits);
mbedtls_ecp_keypair_init(&ecp_key);
ret = mbedtls_ecp_group_load(&(ecp_key.grp), ecp_group_id);
if (ret != 0) {
goto exit;
}
ret = mbedtls_ecp_point_read_binary(&(ecp_key.grp), &ecp_key.Q,
pub, pub_len);
if (ret != 0) {
goto exit;
}
ret = mbedtls_ecp_point_write_binary(&(ecp_key.grp), &ecp_key.Q,
MBEDTLS_ECP_PF_UNCOMPRESSED,
&pk->pub_raw_len, pk->pub_raw,
sizeof(pk->pub_raw));
exit:
mbedtls_ecp_keypair_free(&ecp_key);
return ret;
#endif /* MBEDTLS_PK_PARSE_EC_COMPRESSED */
}
#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
int mbedtls_pk_ecc_set_pubkey(mbedtls_pk_context *pk, const unsigned char *pub, size_t pub_len)
{
#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
/* Load the key */
if (!PSA_ECC_FAMILY_IS_WEIERSTRASS(pk->ec_family) || *pub == 0x04) {
/* Format directly supported by PSA:
* - non-Weierstrass curves that only have one format;
* - uncompressed format for Weierstrass curves. */
if (pub_len > sizeof(pk->pub_raw)) {
return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;
}
memcpy(pk->pub_raw, pub, pub_len);
pk->pub_raw_len = pub_len;
} else {
/* Other format, try the fallback */
int ret = pk_ecc_set_pubkey_psa_ecp_fallback(pk, pub, pub_len);
if (ret != 0) {
return ret;
}
}
/* Validate the key by trying to import it */
mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
psa_key_attributes_t key_attrs = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_usage_flags(&key_attrs, 0);
psa_set_key_type(&key_attrs, PSA_KEY_TYPE_ECC_PUBLIC_KEY(pk->ec_family));
psa_set_key_bits(&key_attrs, pk->ec_bits);
if ((psa_import_key(&key_attrs, pk->pub_raw, pk->pub_raw_len,
&key_id) != PSA_SUCCESS) ||
(psa_destroy_key(key_id) != PSA_SUCCESS)) {
return MBEDTLS_ERR_PK_INVALID_PUBKEY;
}
return 0;
#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
int ret;
mbedtls_ecp_keypair *ec_key = (mbedtls_ecp_keypair *) pk->pk_ctx;
ret = mbedtls_ecp_point_read_binary(&ec_key->grp, &ec_key->Q, pub, pub_len);
if (ret != 0) {
return ret;
}
return mbedtls_ecp_check_pubkey(&ec_key->grp, &ec_key->Q);
#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
}
#endif /* MBEDTLS_PK_C && MBEDTLS_PK_HAVE_ECC_KEYS */

207
thirdparty/mbedtls/library/pk_internal.h vendored Normal file
View File

@@ -0,0 +1,207 @@
/**
* \file pk_internal.h
*
* \brief Public Key abstraction layer: internal (i.e. library only) functions
* and definitions.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef MBEDTLS_PK_INTERNAL_H
#define MBEDTLS_PK_INTERNAL_H
#include "mbedtls/pk.h"
#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
#include "mbedtls/ecp.h"
#endif
#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
#include "psa/crypto.h"
#include "psa_util_internal.h"
#define PSA_PK_TO_MBEDTLS_ERR(status) psa_pk_status_to_mbedtls(status)
#define PSA_PK_RSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \
psa_to_pk_rsa_errors, \
psa_pk_status_to_mbedtls)
#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_PSA_CRYPTO_CLIENT */
/* Headers/footers for PEM files */
#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----"
#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----"
#define PEM_BEGIN_PRIVATE_KEY_RSA "-----BEGIN RSA PRIVATE KEY-----"
#define PEM_END_PRIVATE_KEY_RSA "-----END RSA PRIVATE KEY-----"
#define PEM_BEGIN_PUBLIC_KEY_RSA "-----BEGIN RSA PUBLIC KEY-----"
#define PEM_END_PUBLIC_KEY_RSA "-----END RSA PUBLIC KEY-----"
#define PEM_BEGIN_PRIVATE_KEY_EC "-----BEGIN EC PRIVATE KEY-----"
#define PEM_END_PRIVATE_KEY_EC "-----END EC PRIVATE KEY-----"
#define PEM_BEGIN_PRIVATE_KEY_PKCS8 "-----BEGIN PRIVATE KEY-----"
#define PEM_END_PRIVATE_KEY_PKCS8 "-----END PRIVATE KEY-----"
#define PEM_BEGIN_ENCRYPTED_PRIVATE_KEY_PKCS8 "-----BEGIN ENCRYPTED PRIVATE KEY-----"
#define PEM_END_ENCRYPTED_PRIVATE_KEY_PKCS8 "-----END ENCRYPTED PRIVATE KEY-----"
#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) && !defined(MBEDTLS_PK_USE_PSA_EC_DATA)
/**
* Public function mbedtls_pk_ec() can be used to get direct access to the
* wrapped ecp_keypair structure pointed to the pk_ctx. However this is not
* ideal because it bypasses the PK module on the control of its internal
* structure (pk_context) fields.
* For backward compatibility we keep mbedtls_pk_ec() when ECP_C is defined, but
* we provide 2 very similar functions when only ECP_LIGHT is enabled and not
* ECP_C.
* These variants embed the "ro" or "rw" keywords in their name to make the
* usage of the returned pointer explicit. Of course the returned value is
* const or non-const accordingly.
*/
static inline const mbedtls_ecp_keypair *mbedtls_pk_ec_ro(const mbedtls_pk_context pk)
{
switch (mbedtls_pk_get_type(&pk)) {
case MBEDTLS_PK_ECKEY:
case MBEDTLS_PK_ECKEY_DH:
case MBEDTLS_PK_ECDSA:
return (const mbedtls_ecp_keypair *) (pk).MBEDTLS_PRIVATE(pk_ctx);
default:
return NULL;
}
}
static inline mbedtls_ecp_keypair *mbedtls_pk_ec_rw(const mbedtls_pk_context pk)
{
switch (mbedtls_pk_get_type(&pk)) {
case MBEDTLS_PK_ECKEY:
case MBEDTLS_PK_ECKEY_DH:
case MBEDTLS_PK_ECDSA:
return (mbedtls_ecp_keypair *) (pk).MBEDTLS_PRIVATE(pk_ctx);
default:
return NULL;
}
}
#endif /* MBEDTLS_PK_HAVE_ECC_KEYS && !MBEDTLS_PK_USE_PSA_EC_DATA */
#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
static inline mbedtls_ecp_group_id mbedtls_pk_get_ec_group_id(const mbedtls_pk_context *pk)
{
mbedtls_ecp_group_id id;
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
psa_key_attributes_t opaque_attrs = PSA_KEY_ATTRIBUTES_INIT;
psa_key_type_t opaque_key_type;
psa_ecc_family_t curve;
if (psa_get_key_attributes(pk->priv_id, &opaque_attrs) != PSA_SUCCESS) {
return MBEDTLS_ECP_DP_NONE;
}
opaque_key_type = psa_get_key_type(&opaque_attrs);
curve = PSA_KEY_TYPE_ECC_GET_FAMILY(opaque_key_type);
id = mbedtls_ecc_group_from_psa(curve, psa_get_key_bits(&opaque_attrs));
psa_reset_key_attributes(&opaque_attrs);
} else
#endif /* MBEDTLS_USE_PSA_CRYPTO */
{
#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
id = mbedtls_ecc_group_from_psa(pk->ec_family, pk->ec_bits);
#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
id = mbedtls_pk_ec_ro(*pk)->grp.id;
#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
}
return id;
}
/* Helper for Montgomery curves */
#if defined(MBEDTLS_ECP_HAVE_CURVE25519) || defined(MBEDTLS_ECP_HAVE_CURVE448)
#define MBEDTLS_PK_HAVE_RFC8410_CURVES
#endif /* MBEDTLS_ECP_HAVE_CURVE25519 || MBEDTLS_ECP_DP_CURVE448 */
#define MBEDTLS_PK_IS_RFC8410_GROUP_ID(id) \
((id == MBEDTLS_ECP_DP_CURVE25519) || (id == MBEDTLS_ECP_DP_CURVE448))
static inline int mbedtls_pk_is_rfc8410(const mbedtls_pk_context *pk)
{
mbedtls_ecp_group_id id = mbedtls_pk_get_ec_group_id(pk);
return MBEDTLS_PK_IS_RFC8410_GROUP_ID(id);
}
/*
* Set the group used by this key.
*
* [in/out] pk: in: must have been pk_setup() to an ECC type
* out: will have group (curve) information set
* [in] grp_in: a supported group ID (not NONE)
*/
int mbedtls_pk_ecc_set_group(mbedtls_pk_context *pk, mbedtls_ecp_group_id grp_id);
/*
* Set the private key material
*
* [in/out] pk: in: must have the group set already, see mbedtls_pk_ecc_set_group().
* out: will have the private key set.
* [in] key, key_len: the raw private key (no ASN.1 wrapping).
*/
int mbedtls_pk_ecc_set_key(mbedtls_pk_context *pk, unsigned char *key, size_t key_len);
/*
* Set the public key.
*
* [in/out] pk: in: must have its group set, see mbedtls_pk_ecc_set_group().
* out: will have the public key set.
* [in] pub, pub_len: the raw public key (an ECPoint).
*
* Return:
* - 0 on success;
* - MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the format is potentially valid
* but not supported;
* - another error code otherwise.
*/
int mbedtls_pk_ecc_set_pubkey(mbedtls_pk_context *pk, const unsigned char *pub, size_t pub_len);
/*
* Derive a public key from its private counterpart.
* Computationally intensive, only use when public key is not available.
*
* [in/out] pk: in: must have the private key set, see mbedtls_pk_ecc_set_key().
* out: will have the public key set.
* [in] prv, prv_len: the raw private key (see note below).
* [in] f_rng, p_rng: RNG function and context.
*
* Note: the private key information is always available from pk,
* however for convenience the serialized version is also passed,
* as it's available at each calling site, and useful in some configs
* (as otherwise we would have to re-serialize it from the pk context).
*
* There are three implementations of this function:
* 1. MBEDTLS_PK_USE_PSA_EC_DATA,
* 2. MBEDTLS_USE_PSA_CRYPTO but not MBEDTLS_PK_USE_PSA_EC_DATA,
* 3. not MBEDTLS_USE_PSA_CRYPTO.
*/
int mbedtls_pk_ecc_set_pubkey_from_prv(mbedtls_pk_context *pk,
const unsigned char *prv, size_t prv_len,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng);
#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
/* Helper for (deterministic) ECDSA */
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
#define MBEDTLS_PK_PSA_ALG_ECDSA_MAYBE_DET PSA_ALG_DETERMINISTIC_ECDSA
#else
#define MBEDTLS_PK_PSA_ALG_ECDSA_MAYBE_DET PSA_ALG_ECDSA
#endif
#if defined(MBEDTLS_TEST_HOOKS)
MBEDTLS_STATIC_TESTABLE int mbedtls_pk_parse_key_pkcs8_encrypted_der(
mbedtls_pk_context *pk,
unsigned char *key, size_t keylen,
const unsigned char *pwd, size_t pwdlen,
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 */

1584
thirdparty/mbedtls/library/pk_wrap.c vendored Normal file

File diff suppressed because it is too large Load Diff

138
thirdparty/mbedtls/library/pk_wrap.h vendored Normal file
View File

@@ -0,0 +1,138 @@
/**
* \file pk_wrap.h
*
* \brief Public Key abstraction layer: wrapper functions
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef MBEDTLS_PK_WRAP_H
#define MBEDTLS_PK_WRAP_H
#include "mbedtls/build_info.h"
#include "mbedtls/pk.h"
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#include "psa/crypto.h"
#endif
struct mbedtls_pk_info_t {
/** Public key type */
mbedtls_pk_type_t type;
/** Type name */
const char *name;
/** Get key size in bits */
size_t (*get_bitlen)(mbedtls_pk_context *pk);
/** Tell if the context implements this type (e.g. ECKEY can do ECDSA) */
int (*can_do)(mbedtls_pk_type_t type);
/** Verify signature */
int (*verify_func)(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len);
/** Make signature */
int (*sign_func)(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
unsigned char *sig, size_t sig_size, size_t *sig_len,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng);
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
/** Verify signature (restartable) */
int (*verify_rs_func)(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len,
void *rs_ctx);
/** Make signature (restartable) */
int (*sign_rs_func)(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
unsigned char *sig, size_t sig_size, size_t *sig_len,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng, void *rs_ctx);
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
/** Decrypt message */
int (*decrypt_func)(mbedtls_pk_context *pk, const unsigned char *input, size_t ilen,
unsigned char *output, size_t *olen, size_t osize,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng);
/** Encrypt message */
int (*encrypt_func)(mbedtls_pk_context *pk, const unsigned char *input, size_t ilen,
unsigned char *output, size_t *olen, size_t osize,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng);
/** Check public-private key pair */
int (*check_pair_func)(mbedtls_pk_context *pub, mbedtls_pk_context *prv,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng);
/** Allocate a new context */
void * (*ctx_alloc_func)(void);
/** Free the given context */
void (*ctx_free_func)(void *ctx);
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
/** Allocate the restart context */
void *(*rs_alloc_func)(void);
/** Free the restart context */
void (*rs_free_func)(void *rs_ctx);
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
/** Interface with the debug module */
void (*debug_func)(mbedtls_pk_context *pk, mbedtls_pk_debug_item *items);
};
#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
/* Container for RSA-alt */
typedef struct {
void *key;
mbedtls_pk_rsa_alt_decrypt_func decrypt_func;
mbedtls_pk_rsa_alt_sign_func sign_func;
mbedtls_pk_rsa_alt_key_len_func key_len_func;
} mbedtls_rsa_alt_context;
#endif
#if defined(MBEDTLS_RSA_C)
extern const mbedtls_pk_info_t mbedtls_rsa_info;
#endif
#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
extern const mbedtls_pk_info_t mbedtls_eckey_info;
extern const mbedtls_pk_info_t mbedtls_eckeydh_info;
#endif
#if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
extern const mbedtls_pk_info_t mbedtls_ecdsa_info;
#endif
#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
extern const mbedtls_pk_info_t mbedtls_rsa_alt_info;
#endif
#if defined(MBEDTLS_USE_PSA_CRYPTO)
extern const mbedtls_pk_info_t mbedtls_ecdsa_opaque_info;
extern const mbedtls_pk_info_t mbedtls_rsa_opaque_info;
#if defined(MBEDTLS_RSA_C)
int mbedtls_pk_psa_rsa_sign_ext(psa_algorithm_t psa_alg_md,
mbedtls_rsa_context *rsa_ctx,
const unsigned char *hash, size_t hash_len,
unsigned char *sig, size_t sig_size,
size_t *sig_len);
#endif /* MBEDTLS_RSA_C */
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#endif /* MBEDTLS_PK_WRAP_H */

437
thirdparty/mbedtls/library/pkcs12.c vendored Normal file
View File

@@ -0,0 +1,437 @@
/*
* PKCS#12 Personal Information Exchange Syntax
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
/*
* The PKCS #12 Personal Information Exchange Syntax Standard v1.1
*
* http://www.rsa.com/rsalabs/pkcs/files/h11301-wp-pkcs-12v1-1-personal-information-exchange-syntax.pdf
* ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1-1.asn
*/
#include "common.h"
#if defined(MBEDTLS_PKCS12_C)
#include "mbedtls/pkcs12.h"
#include "mbedtls/asn1.h"
#if defined(MBEDTLS_CIPHER_C)
#include "mbedtls/cipher.h"
#endif /* MBEDTLS_CIPHER_C */
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#include <string.h>
#if defined(MBEDTLS_DES_C)
#include "mbedtls/des.h"
#endif
#include "psa_util_internal.h"
#if defined(MBEDTLS_ASN1_PARSE_C) && defined(MBEDTLS_CIPHER_C)
static int pkcs12_parse_pbe_params(mbedtls_asn1_buf *params,
mbedtls_asn1_buf *salt, int *iterations)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char **p = &params->p;
const unsigned char *end = params->p + params->len;
/*
* pkcs-12PbeParams ::= SEQUENCE {
* salt OCTET STRING,
* iterations INTEGER
* }
*
*/
if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT,
MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
}
if ((ret = mbedtls_asn1_get_tag(p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT, ret);
}
salt->p = *p;
*p += salt->len;
if ((ret = mbedtls_asn1_get_int(p, end, iterations)) != 0) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT, ret);
}
if (*p != end) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT,
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
}
return 0;
}
#define PKCS12_MAX_PWDLEN 128
static int pkcs12_pbe_derive_key_iv(mbedtls_asn1_buf *pbe_params, mbedtls_md_type_t md_type,
const unsigned char *pwd, size_t pwdlen,
unsigned char *key, size_t keylen,
unsigned char *iv, size_t ivlen)
{
int ret, iterations = 0;
mbedtls_asn1_buf salt;
size_t i;
unsigned char unipwd[PKCS12_MAX_PWDLEN * 2 + 2];
if (pwdlen > PKCS12_MAX_PWDLEN) {
return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA;
}
memset(&salt, 0, sizeof(mbedtls_asn1_buf));
memset(&unipwd, 0, sizeof(unipwd));
if ((ret = pkcs12_parse_pbe_params(pbe_params, &salt,
&iterations)) != 0) {
return ret;
}
for (i = 0; i < pwdlen; i++) {
unipwd[i * 2 + 1] = pwd[i];
}
if ((ret = mbedtls_pkcs12_derivation(key, keylen, unipwd, pwdlen * 2 + 2,
salt.p, salt.len, md_type,
MBEDTLS_PKCS12_DERIVE_KEY, iterations)) != 0) {
return ret;
}
if (iv == NULL || ivlen == 0) {
return 0;
}
if ((ret = mbedtls_pkcs12_derivation(iv, ivlen, unipwd, pwdlen * 2 + 2,
salt.p, salt.len, md_type,
MBEDTLS_PKCS12_DERIVE_IV, iterations)) != 0) {
return ret;
}
return 0;
}
#undef PKCS12_MAX_PWDLEN
#if !defined(MBEDTLS_CIPHER_PADDING_PKCS7)
int mbedtls_pkcs12_pbe_ext(mbedtls_asn1_buf *pbe_params, int mode,
mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type,
const unsigned char *pwd, size_t pwdlen,
const unsigned char *data, size_t len,
unsigned char *output, size_t output_size,
size_t *output_len);
#endif
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
int mbedtls_pkcs12_pbe(mbedtls_asn1_buf *pbe_params, int mode,
mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type,
const unsigned char *pwd, size_t pwdlen,
const unsigned char *data, size_t len,
unsigned char *output)
{
size_t output_len = 0;
/* We assume caller of the function is providing a big enough output buffer
* so we pass output_size as SIZE_MAX to pass checks, However, no guarantees
* for the output size actually being correct.
*/
return mbedtls_pkcs12_pbe_ext(pbe_params, mode, cipher_type, md_type,
pwd, pwdlen, data, len, output, SIZE_MAX,
&output_len);
}
#endif
int mbedtls_pkcs12_pbe_ext(mbedtls_asn1_buf *pbe_params, int mode,
mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type,
const unsigned char *pwd, size_t pwdlen,
const unsigned char *data, size_t len,
unsigned char *output, size_t output_size,
size_t *output_len)
{
int ret, keylen = 0;
unsigned char key[32];
unsigned char iv[16];
const mbedtls_cipher_info_t *cipher_info;
mbedtls_cipher_context_t cipher_ctx;
size_t iv_len = 0;
size_t finish_olen = 0;
unsigned int padlen = 0;
if (pwd == NULL && pwdlen != 0) {
return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA;
}
cipher_info = mbedtls_cipher_info_from_type(cipher_type);
if (cipher_info == NULL) {
return MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE;
}
keylen = (int) mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8;
if (mode == MBEDTLS_PKCS12_PBE_DECRYPT) {
if (output_size < len) {
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
}
}
if (mode == MBEDTLS_PKCS12_PBE_ENCRYPT) {
padlen = cipher_info->block_size - (len % cipher_info->block_size);
if (output_size < (len + padlen)) {
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
}
}
iv_len = mbedtls_cipher_info_get_iv_size(cipher_info);
if ((ret = pkcs12_pbe_derive_key_iv(pbe_params, md_type, pwd, pwdlen,
key, keylen,
iv, iv_len)) != 0) {
return ret;
}
mbedtls_cipher_init(&cipher_ctx);
if ((ret = mbedtls_cipher_setup(&cipher_ctx, cipher_info)) != 0) {
goto exit;
}
if ((ret = mbedtls_cipher_setkey(&cipher_ctx, key, 8 * keylen,
(mbedtls_operation_t) mode)) != 0) {
goto exit;
}
#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
{
/* PKCS12 uses CBC with PKCS7 padding */
mbedtls_cipher_padding_t padding = MBEDTLS_PADDING_PKCS7;
#if !defined(MBEDTLS_CIPHER_PADDING_PKCS7)
/* For historical reasons, when decrypting, this function works when
* decrypting even when support for PKCS7 padding is disabled. In this
* case, it ignores the padding, and so will never report a
* password mismatch.
*/
if (mode == MBEDTLS_PKCS12_PBE_DECRYPT) {
padding = MBEDTLS_PADDING_NONE;
}
#endif
if ((ret = mbedtls_cipher_set_padding_mode(&cipher_ctx, padding)) != 0) {
goto exit;
}
}
#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
ret = mbedtls_cipher_crypt(&cipher_ctx, iv, iv_len, data, len, output, &finish_olen);
if (ret == MBEDTLS_ERR_CIPHER_INVALID_PADDING) {
ret = MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH;
}
*output_len += finish_olen;
exit:
mbedtls_platform_zeroize(key, sizeof(key));
mbedtls_platform_zeroize(iv, sizeof(iv));
mbedtls_cipher_free(&cipher_ctx);
return ret;
}
#endif /* MBEDTLS_ASN1_PARSE_C && MBEDTLS_CIPHER_C */
static void pkcs12_fill_buffer(unsigned char *data, size_t data_len,
const unsigned char *filler, size_t fill_len)
{
unsigned char *p = data;
size_t use_len;
if (filler != NULL && fill_len != 0) {
while (data_len > 0) {
use_len = (data_len > fill_len) ? fill_len : data_len;
memcpy(p, filler, use_len);
p += use_len;
data_len -= use_len;
}
} else {
/* If either of the above are not true then clearly there is nothing
* that this function can do. The function should *not* be called
* under either of those circumstances, as you could end up with an
* incorrect output but for safety's sake, leaving the check in as
* otherwise we could end up with memory corruption.*/
}
}
static int calculate_hashes(mbedtls_md_type_t md_type, int iterations,
unsigned char *diversifier, unsigned char *salt_block,
unsigned char *pwd_block, unsigned char *hash_output, int use_salt,
int use_password, size_t hlen, size_t v)
{
int ret = -1;
size_t i;
const mbedtls_md_info_t *md_info;
mbedtls_md_context_t md_ctx;
md_info = mbedtls_md_info_from_type(md_type);
if (md_info == NULL) {
return MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE;
}
mbedtls_md_init(&md_ctx);
if ((ret = mbedtls_md_setup(&md_ctx, md_info, 0)) != 0) {
return ret;
}
// Calculate hash( diversifier || salt_block || pwd_block )
if ((ret = mbedtls_md_starts(&md_ctx)) != 0) {
goto exit;
}
if ((ret = mbedtls_md_update(&md_ctx, diversifier, v)) != 0) {
goto exit;
}
if (use_salt != 0) {
if ((ret = mbedtls_md_update(&md_ctx, salt_block, v)) != 0) {
goto exit;
}
}
if (use_password != 0) {
if ((ret = mbedtls_md_update(&md_ctx, pwd_block, v)) != 0) {
goto exit;
}
}
if ((ret = mbedtls_md_finish(&md_ctx, hash_output)) != 0) {
goto exit;
}
// Perform remaining ( iterations - 1 ) recursive hash calculations
for (i = 1; i < (size_t) iterations; i++) {
if ((ret = mbedtls_md(md_info, hash_output, hlen, hash_output))
!= 0) {
goto exit;
}
}
exit:
mbedtls_md_free(&md_ctx);
return ret;
}
int mbedtls_pkcs12_derivation(unsigned char *data, size_t datalen,
const unsigned char *pwd, size_t pwdlen,
const unsigned char *salt, size_t saltlen,
mbedtls_md_type_t md_type, int id, int iterations)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned int j;
unsigned char diversifier[128];
unsigned char salt_block[128], pwd_block[128], hash_block[128] = { 0 };
unsigned char hash_output[MBEDTLS_MD_MAX_SIZE];
unsigned char *p;
unsigned char c;
int use_password = 0;
int use_salt = 0;
size_t hlen, use_len, v, i;
// This version only allows max of 64 bytes of password or salt
if (datalen > 128 || pwdlen > 64 || saltlen > 64) {
return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA;
}
if (pwd == NULL && pwdlen != 0) {
return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA;
}
if (salt == NULL && saltlen != 0) {
return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA;
}
use_password = (pwd && pwdlen != 0);
use_salt = (salt && saltlen != 0);
hlen = mbedtls_md_get_size_from_type(md_type);
if (hlen <= 32) {
v = 64;
} else {
v = 128;
}
memset(diversifier, (unsigned char) id, v);
if (use_salt != 0) {
pkcs12_fill_buffer(salt_block, v, salt, saltlen);
}
if (use_password != 0) {
pkcs12_fill_buffer(pwd_block, v, pwd, pwdlen);
}
p = data;
while (datalen > 0) {
if (calculate_hashes(md_type, iterations, diversifier, salt_block,
pwd_block, hash_output, use_salt, use_password, hlen,
v) != 0) {
goto exit;
}
use_len = (datalen > hlen) ? hlen : datalen;
memcpy(p, hash_output, use_len);
datalen -= use_len;
p += use_len;
if (datalen == 0) {
break;
}
// Concatenating copies of hash_output into hash_block (B)
pkcs12_fill_buffer(hash_block, v, hash_output, hlen);
// B += 1
for (i = v; i > 0; i--) {
if (++hash_block[i - 1] != 0) {
break;
}
}
if (use_salt != 0) {
// salt_block += B
c = 0;
for (i = v; i > 0; i--) {
j = salt_block[i - 1] + hash_block[i - 1] + c;
c = MBEDTLS_BYTE_1(j);
salt_block[i - 1] = MBEDTLS_BYTE_0(j);
}
}
if (use_password != 0) {
// pwd_block += B
c = 0;
for (i = v; i > 0; i--) {
j = pwd_block[i - 1] + hash_block[i - 1] + c;
c = MBEDTLS_BYTE_1(j);
pwd_block[i - 1] = MBEDTLS_BYTE_0(j);
}
}
}
ret = 0;
exit:
mbedtls_platform_zeroize(salt_block, sizeof(salt_block));
mbedtls_platform_zeroize(pwd_block, sizeof(pwd_block));
mbedtls_platform_zeroize(hash_block, sizeof(hash_block));
mbedtls_platform_zeroize(hash_output, sizeof(hash_output));
return ret;
}
#endif /* MBEDTLS_PKCS12_C */

500
thirdparty/mbedtls/library/pkcs5.c vendored Normal file
View File

@@ -0,0 +1,500 @@
/**
* \file pkcs5.c
*
* \brief PKCS#5 functions
*
* \author Mathias Olsson <mathias@kompetensum.com>
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
/*
* PKCS#5 includes PBKDF2 and more
*
* http://tools.ietf.org/html/rfc2898 (Specification)
* http://tools.ietf.org/html/rfc6070 (Test vectors)
*/
#include "common.h"
#if defined(MBEDTLS_PKCS5_C)
#include "mbedtls/pkcs5.h"
#include "mbedtls/error.h"
#if defined(MBEDTLS_ASN1_PARSE_C)
#include "mbedtls/asn1.h"
#if defined(MBEDTLS_CIPHER_C)
#include "mbedtls/cipher.h"
#endif /* MBEDTLS_CIPHER_C */
#include "mbedtls/oid.h"
#endif /* MBEDTLS_ASN1_PARSE_C */
#include <string.h>
#include "mbedtls/platform.h"
#include "psa_util_internal.h"
#if defined(MBEDTLS_ASN1_PARSE_C) && defined(MBEDTLS_CIPHER_C)
static int pkcs5_parse_pbkdf2_params(const mbedtls_asn1_buf *params,
mbedtls_asn1_buf *salt, int *iterations,
int *keylen, mbedtls_md_type_t *md_type)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_asn1_buf prf_alg_oid;
unsigned char *p = params->p;
const unsigned char *end = params->p + params->len;
if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT,
MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
}
/*
* PBKDF2-params ::= SEQUENCE {
* salt OCTET STRING,
* iterationCount INTEGER,
* keyLength INTEGER OPTIONAL
* prf AlgorithmIdentifier DEFAULT algid-hmacWithSHA1
* }
*
*/
if ((ret = mbedtls_asn1_get_tag(&p, end, &salt->len,
MBEDTLS_ASN1_OCTET_STRING)) != 0) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
}
salt->p = p;
p += salt->len;
if ((ret = mbedtls_asn1_get_int(&p, end, iterations)) != 0) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
}
if (p == end) {
return 0;
}
if ((ret = mbedtls_asn1_get_int(&p, end, keylen)) != 0) {
if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
}
}
if (p == end) {
return 0;
}
if ((ret = mbedtls_asn1_get_alg_null(&p, end, &prf_alg_oid)) != 0) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
}
if (mbedtls_oid_get_md_hmac(&prf_alg_oid, md_type) != 0) {
return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;
}
if (p != end) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT,
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
}
return 0;
}
#if !defined(MBEDTLS_CIPHER_PADDING_PKCS7)
int mbedtls_pkcs5_pbes2_ext(const mbedtls_asn1_buf *pbe_params, int mode,
const unsigned char *pwd, size_t pwdlen,
const unsigned char *data, size_t datalen,
unsigned char *output, size_t output_size,
size_t *output_len);
#endif
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
int mbedtls_pkcs5_pbes2(const mbedtls_asn1_buf *pbe_params, int mode,
const unsigned char *pwd, size_t pwdlen,
const unsigned char *data, size_t datalen,
unsigned char *output)
{
size_t output_len = 0;
/* We assume caller of the function is providing a big enough output buffer
* so we pass output_size as SIZE_MAX to pass checks, However, no guarantees
* for the output size actually being correct.
*/
return mbedtls_pkcs5_pbes2_ext(pbe_params, mode, pwd, pwdlen, data,
datalen, output, SIZE_MAX, &output_len);
}
#endif
int mbedtls_pkcs5_pbes2_ext(const mbedtls_asn1_buf *pbe_params, int mode,
const unsigned char *pwd, size_t pwdlen,
const unsigned char *data, size_t datalen,
unsigned char *output, size_t output_size,
size_t *output_len)
{
int ret, iterations = 0, keylen = 0;
unsigned char *p, *end;
mbedtls_asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params;
mbedtls_asn1_buf salt;
mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1;
unsigned char key[32], iv[32];
const mbedtls_cipher_info_t *cipher_info;
mbedtls_cipher_type_t cipher_alg;
mbedtls_cipher_context_t cipher_ctx;
unsigned int padlen = 0;
p = pbe_params->p;
end = p + pbe_params->len;
/*
* PBES2-params ::= SEQUENCE {
* keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}},
* encryptionScheme AlgorithmIdentifier {{PBES2-Encs}}
* }
*/
if (pbe_params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT,
MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
}
if ((ret = mbedtls_asn1_get_alg(&p, end, &kdf_alg_oid,
&kdf_alg_params)) != 0) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
}
// Only PBKDF2 supported at the moment
//
if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS5_PBKDF2, &kdf_alg_oid) != 0) {
return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;
}
if ((ret = pkcs5_parse_pbkdf2_params(&kdf_alg_params,
&salt, &iterations, &keylen,
&md_type)) != 0) {
return ret;
}
if ((ret = mbedtls_asn1_get_alg(&p, end, &enc_scheme_oid,
&enc_scheme_params)) != 0) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
}
if (mbedtls_oid_get_cipher_alg(&enc_scheme_oid, &cipher_alg) != 0) {
return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;
}
cipher_info = mbedtls_cipher_info_from_type(cipher_alg);
if (cipher_info == NULL) {
return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;
}
/*
* The value of keylen from pkcs5_parse_pbkdf2_params() is ignored
* since it is optional and we don't know if it was set or not
*/
keylen = (int) mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8;
if (enc_scheme_params.tag != MBEDTLS_ASN1_OCTET_STRING ||
enc_scheme_params.len != mbedtls_cipher_info_get_iv_size(cipher_info)) {
return MBEDTLS_ERR_PKCS5_INVALID_FORMAT;
}
if (mode == MBEDTLS_PKCS5_DECRYPT) {
if (output_size < datalen) {
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
}
}
if (mode == MBEDTLS_PKCS5_ENCRYPT) {
padlen = cipher_info->block_size - (datalen % cipher_info->block_size);
if (output_size < (datalen + padlen)) {
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
}
}
mbedtls_cipher_init(&cipher_ctx);
memcpy(iv, enc_scheme_params.p, enc_scheme_params.len);
if ((ret = mbedtls_pkcs5_pbkdf2_hmac_ext(md_type, pwd, pwdlen, salt.p,
salt.len, iterations, keylen,
key)) != 0) {
goto exit;
}
if ((ret = mbedtls_cipher_setup(&cipher_ctx, cipher_info)) != 0) {
goto exit;
}
if ((ret = mbedtls_cipher_setkey(&cipher_ctx, key, 8 * keylen,
(mbedtls_operation_t) mode)) != 0) {
goto exit;
}
#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
{
/* PKCS5 uses CBC with PKCS7 padding (which is the same as
* "PKCS5 padding" except that it's typically only called PKCS5
* with 64-bit-block ciphers).
*/
mbedtls_cipher_padding_t padding = MBEDTLS_PADDING_PKCS7;
#if !defined(MBEDTLS_CIPHER_PADDING_PKCS7)
/* For historical reasons, when decrypting, this function works when
* decrypting even when support for PKCS7 padding is disabled. In this
* case, it ignores the padding, and so will never report a
* password mismatch.
*/
if (mode == MBEDTLS_DECRYPT) {
padding = MBEDTLS_PADDING_NONE;
}
#endif
if ((ret = mbedtls_cipher_set_padding_mode(&cipher_ctx, padding)) != 0) {
goto exit;
}
}
#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
if ((ret = mbedtls_cipher_crypt(&cipher_ctx, iv, enc_scheme_params.len,
data, datalen, output, output_len)) != 0) {
ret = MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH;
}
exit:
mbedtls_cipher_free(&cipher_ctx);
return ret;
}
#endif /* MBEDTLS_ASN1_PARSE_C && MBEDTLS_CIPHER_C */
static int pkcs5_pbkdf2_hmac(mbedtls_md_context_t *ctx,
const unsigned char *password,
size_t plen, const unsigned char *salt, size_t slen,
unsigned int iteration_count,
uint32_t key_length, unsigned char *output)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned int i;
unsigned char md1[MBEDTLS_MD_MAX_SIZE];
unsigned char work[MBEDTLS_MD_MAX_SIZE];
unsigned char md_size = mbedtls_md_get_size(ctx->md_info);
size_t use_len;
unsigned char *out_p = output;
unsigned char counter[4];
memset(counter, 0, 4);
counter[3] = 1;
#if UINT_MAX > 0xFFFFFFFF
if (iteration_count > 0xFFFFFFFF) {
return MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA;
}
#endif
if ((ret = mbedtls_md_hmac_starts(ctx, password, plen)) != 0) {
return ret;
}
while (key_length) {
// U1 ends up in work
//
if ((ret = mbedtls_md_hmac_update(ctx, salt, slen)) != 0) {
goto cleanup;
}
if ((ret = mbedtls_md_hmac_update(ctx, counter, 4)) != 0) {
goto cleanup;
}
if ((ret = mbedtls_md_hmac_finish(ctx, work)) != 0) {
goto cleanup;
}
if ((ret = mbedtls_md_hmac_reset(ctx)) != 0) {
goto cleanup;
}
memcpy(md1, work, md_size);
for (i = 1; i < iteration_count; i++) {
// U2 ends up in md1
//
if ((ret = mbedtls_md_hmac_update(ctx, md1, md_size)) != 0) {
goto cleanup;
}
if ((ret = mbedtls_md_hmac_finish(ctx, md1)) != 0) {
goto cleanup;
}
if ((ret = mbedtls_md_hmac_reset(ctx)) != 0) {
goto cleanup;
}
// U1 xor U2
//
mbedtls_xor(work, work, md1, md_size);
}
use_len = (key_length < md_size) ? key_length : md_size;
memcpy(out_p, work, use_len);
key_length -= (uint32_t) use_len;
out_p += use_len;
for (i = 4; i > 0; i--) {
if (++counter[i - 1] != 0) {
break;
}
}
}
cleanup:
/* Zeroise buffers to clear sensitive data from memory. */
mbedtls_platform_zeroize(work, MBEDTLS_MD_MAX_SIZE);
mbedtls_platform_zeroize(md1, MBEDTLS_MD_MAX_SIZE);
return ret;
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
int mbedtls_pkcs5_pbkdf2_hmac(mbedtls_md_context_t *ctx,
const unsigned char *password,
size_t plen, const unsigned char *salt, size_t slen,
unsigned int iteration_count,
uint32_t key_length, unsigned char *output)
{
return pkcs5_pbkdf2_hmac(ctx, password, plen, salt, slen, iteration_count,
key_length, output);
}
#endif
int mbedtls_pkcs5_pbkdf2_hmac_ext(mbedtls_md_type_t md_alg,
const unsigned char *password,
size_t plen, const unsigned char *salt, size_t slen,
unsigned int iteration_count,
uint32_t key_length, unsigned char *output)
{
mbedtls_md_context_t md_ctx;
const mbedtls_md_info_t *md_info = NULL;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
md_info = mbedtls_md_info_from_type(md_alg);
if (md_info == NULL) {
return MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE;
}
mbedtls_md_init(&md_ctx);
if ((ret = mbedtls_md_setup(&md_ctx, md_info, 1)) != 0) {
goto exit;
}
ret = pkcs5_pbkdf2_hmac(&md_ctx, password, plen, salt, slen,
iteration_count, key_length, output);
exit:
mbedtls_md_free(&md_ctx);
return ret;
}
#if defined(MBEDTLS_SELF_TEST)
#if !defined(MBEDTLS_MD_CAN_SHA1)
int mbedtls_pkcs5_self_test(int verbose)
{
if (verbose != 0) {
mbedtls_printf(" PBKDF2 (SHA1): skipped\n\n");
}
return 0;
}
#else
#define MAX_TESTS 6
static const size_t plen_test_data[MAX_TESTS] =
{ 8, 8, 8, 24, 9 };
static const unsigned char password_test_data[MAX_TESTS][32] =
{
"password",
"password",
"password",
"passwordPASSWORDpassword",
"pass\0word",
};
static const size_t slen_test_data[MAX_TESTS] =
{ 4, 4, 4, 36, 5 };
static const unsigned char salt_test_data[MAX_TESTS][40] =
{
"salt",
"salt",
"salt",
"saltSALTsaltSALTsaltSALTsaltSALTsalt",
"sa\0lt",
};
static const uint32_t it_cnt_test_data[MAX_TESTS] =
{ 1, 2, 4096, 4096, 4096 };
static const uint32_t key_len_test_data[MAX_TESTS] =
{ 20, 20, 20, 25, 16 };
static const unsigned char result_key_test_data[MAX_TESTS][32] =
{
{ 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71,
0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06,
0x2f, 0xe0, 0x37, 0xa6 },
{ 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c,
0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0,
0xd8, 0xde, 0x89, 0x57 },
{ 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a,
0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0,
0x65, 0xa4, 0x29, 0xc1 },
{ 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b,
0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a,
0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70,
0x38 },
{ 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d,
0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 },
};
int mbedtls_pkcs5_self_test(int verbose)
{
int ret, i;
unsigned char key[64];
for (i = 0; i < MAX_TESTS; i++) {
if (verbose != 0) {
mbedtls_printf(" PBKDF2 (SHA1) #%d: ", i);
}
ret = mbedtls_pkcs5_pbkdf2_hmac_ext(MBEDTLS_MD_SHA1, password_test_data[i],
plen_test_data[i], salt_test_data[i],
slen_test_data[i], it_cnt_test_data[i],
key_len_test_data[i], key);
if (ret != 0 ||
memcmp(result_key_test_data[i], key, key_len_test_data[i]) != 0) {
if (verbose != 0) {
mbedtls_printf("failed\n");
}
ret = 1;
goto exit;
}
if (verbose != 0) {
mbedtls_printf("passed\n");
}
}
if (verbose != 0) {
mbedtls_printf("\n");
}
exit:
return ret;
}
#endif /* MBEDTLS_MD_CAN_SHA1 */
#endif /* MBEDTLS_SELF_TEST */
#endif /* MBEDTLS_PKCS5_C */

773
thirdparty/mbedtls/library/pkcs7.c vendored Normal file
View File

@@ -0,0 +1,773 @@
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#include "mbedtls/build_info.h"
#if defined(MBEDTLS_PKCS7_C)
#include "mbedtls/pkcs7.h"
#include "x509_internal.h"
#include "mbedtls/asn1.h"
#include "mbedtls/x509_crt.h"
#include "mbedtls/x509_crl.h"
#include "mbedtls/oid.h"
#include "mbedtls/error.h"
#if defined(MBEDTLS_FS_IO)
#include <sys/types.h>
#include <sys/stat.h>
#endif
#include "mbedtls/platform.h"
#include "mbedtls/platform_util.h"
#if defined(MBEDTLS_HAVE_TIME)
#include "mbedtls/platform_time.h"
#endif
#if defined(MBEDTLS_HAVE_TIME_DATE)
#include <time.h>
#endif
/**
* Initializes the mbedtls_pkcs7 structure.
*/
void mbedtls_pkcs7_init(mbedtls_pkcs7 *pkcs7)
{
memset(pkcs7, 0, sizeof(*pkcs7));
}
static int pkcs7_get_next_content_len(unsigned char **p, unsigned char *end,
size_t *len)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ret = mbedtls_asn1_get_tag(p, end, len, MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_CONTEXT_SPECIFIC);
if (ret != 0) {
ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret);
} else if ((size_t) (end - *p) != *len) {
ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO,
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
}
return ret;
}
/**
* version Version
* Version ::= INTEGER
**/
static int pkcs7_get_version(unsigned char **p, unsigned char *end, int *ver)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ret = mbedtls_asn1_get_int(p, end, ver);
if (ret != 0) {
ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_VERSION, ret);
}
/* If version != 1, return invalid version */
if (*ver != MBEDTLS_PKCS7_SUPPORTED_VERSION) {
ret = MBEDTLS_ERR_PKCS7_INVALID_VERSION;
}
return ret;
}
/**
* ContentInfo ::= SEQUENCE {
* contentType ContentType,
* content
* [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
**/
static int pkcs7_get_content_info_type(unsigned char **p, unsigned char *end,
unsigned char **seq_end,
mbedtls_pkcs7_buf *pkcs7)
{
size_t len = 0;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *start = *p;
ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE);
if (ret != 0) {
*p = start;
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret);
}
*seq_end = *p + len;
ret = mbedtls_asn1_get_tag(p, *seq_end, &len, MBEDTLS_ASN1_OID);
if (ret != 0) {
*p = start;
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret);
}
pkcs7->tag = MBEDTLS_ASN1_OID;
pkcs7->len = len;
pkcs7->p = *p;
*p += len;
return ret;
}
/**
* DigestAlgorithmIdentifier ::= AlgorithmIdentifier
*
* This is from x509.h
**/
static int pkcs7_get_digest_algorithm(unsigned char **p, unsigned char *end,
mbedtls_x509_buf *alg)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if ((ret = mbedtls_asn1_get_alg_null(p, end, alg)) != 0) {
ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret);
}
return ret;
}
/**
* DigestAlgorithmIdentifiers :: SET of DigestAlgorithmIdentifier
**/
static int pkcs7_get_digest_algorithm_set(unsigned char **p,
unsigned char *end,
mbedtls_x509_buf *alg)
{
size_t len = 0;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SET);
if (ret != 0) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret);
}
end = *p + len;
ret = mbedtls_asn1_get_alg_null(p, end, alg);
if (ret != 0) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret);
}
/** For now, it assumes there is only one digest algorithm specified **/
if (*p != end) {
return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
}
return 0;
}
/**
* certificates :: SET OF ExtendedCertificateOrCertificate,
* ExtendedCertificateOrCertificate ::= CHOICE {
* certificate Certificate -- x509,
* extendedCertificate[0] IMPLICIT ExtendedCertificate }
* Return number of certificates added to the signed data,
* 0 or higher is valid.
* Return negative error code for failure.
**/
static int pkcs7_get_certificates(unsigned char **p, unsigned char *end,
mbedtls_x509_crt *certs)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len1 = 0;
size_t len2 = 0;
unsigned char *end_set, *end_cert, *start;
ret = mbedtls_asn1_get_tag(p, end, &len1, MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_CONTEXT_SPECIFIC);
if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
return 0;
}
if (ret != 0) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret);
}
start = *p;
end_set = *p + len1;
ret = mbedtls_asn1_get_tag(p, end_set, &len2, MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE);
if (ret != 0) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CERT, ret);
}
end_cert = *p + len2;
/*
* This is to verify that there is only one signer certificate. It seems it is
* not easy to differentiate between the chain vs different signer's certificate.
* So, we support only the root certificate and the single signer.
* The behaviour would be improved with addition of multiple signer support.
*/
if (end_cert != end_set) {
return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
}
if ((ret = mbedtls_x509_crt_parse_der(certs, start, len1)) < 0) {
return MBEDTLS_ERR_PKCS7_INVALID_CERT;
}
*p = end_cert;
/*
* Since in this version we strictly support single certificate, and reaching
* here implies we have parsed successfully, we return 1.
*/
return 1;
}
/**
* EncryptedDigest ::= OCTET STRING
**/
static int pkcs7_get_signature(unsigned char **p, unsigned char *end,
mbedtls_pkcs7_buf *signature)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
if (ret != 0) {
return ret;
}
signature->tag = MBEDTLS_ASN1_OCTET_STRING;
signature->len = len;
signature->p = *p;
*p = *p + len;
return 0;
}
static void pkcs7_free_signer_info(mbedtls_pkcs7_signer_info *signer)
{
mbedtls_x509_name *name_cur;
mbedtls_x509_name *name_prv;
if (signer == NULL) {
return;
}
name_cur = signer->issuer.next;
while (name_cur != NULL) {
name_prv = name_cur;
name_cur = name_cur->next;
mbedtls_free(name_prv);
}
signer->issuer.next = NULL;
}
/**
* SignerInfo ::= SEQUENCE {
* version Version;
* issuerAndSerialNumber IssuerAndSerialNumber,
* digestAlgorithm DigestAlgorithmIdentifier,
* authenticatedAttributes
* [0] IMPLICIT Attributes OPTIONAL,
* digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
* encryptedDigest EncryptedDigest,
* unauthenticatedAttributes
* [1] IMPLICIT Attributes OPTIONAL,
* Returns 0 if the signerInfo is valid.
* Return negative error code for failure.
* Structure must not contain vales for authenticatedAttributes
* and unauthenticatedAttributes.
**/
static int pkcs7_get_signer_info(unsigned char **p, unsigned char *end,
mbedtls_pkcs7_signer_info *signer,
mbedtls_x509_buf *alg)
{
unsigned char *end_signer, *end_issuer_and_sn;
int asn1_ret = 0, ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
asn1_ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE);
if (asn1_ret != 0) {
goto out;
}
end_signer = *p + len;
ret = pkcs7_get_version(p, end_signer, &signer->version);
if (ret != 0) {
goto out;
}
asn1_ret = mbedtls_asn1_get_tag(p, end_signer, &len,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
if (asn1_ret != 0) {
goto out;
}
end_issuer_and_sn = *p + len;
/* Parsing IssuerAndSerialNumber */
signer->issuer_raw.p = *p;
asn1_ret = mbedtls_asn1_get_tag(p, end_issuer_and_sn, &len,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
if (asn1_ret != 0) {
goto out;
}
ret = mbedtls_x509_get_name(p, *p + len, &signer->issuer);
if (ret != 0) {
goto out;
}
signer->issuer_raw.len = (size_t) (*p - signer->issuer_raw.p);
ret = mbedtls_x509_get_serial(p, end_issuer_and_sn, &signer->serial);
if (ret != 0) {
goto out;
}
/* ensure no extra or missing bytes */
if (*p != end_issuer_and_sn) {
ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;
goto out;
}
ret = pkcs7_get_digest_algorithm(p, end_signer, &signer->alg_identifier);
if (ret != 0) {
goto out;
}
/* Check that the digest algorithm used matches the one provided earlier */
if (signer->alg_identifier.tag != alg->tag ||
signer->alg_identifier.len != alg->len ||
memcmp(signer->alg_identifier.p, alg->p, alg->len) != 0) {
ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;
goto out;
}
/* Assume authenticatedAttributes is nonexistent */
ret = pkcs7_get_digest_algorithm(p, end_signer, &signer->sig_alg_identifier);
if (ret != 0) {
goto out;
}
ret = pkcs7_get_signature(p, end_signer, &signer->sig);
if (ret != 0) {
goto out;
}
/* Do not permit any unauthenticated attributes */
if (*p != end_signer) {
ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;
}
out:
if (asn1_ret != 0 || ret != 0) {
pkcs7_free_signer_info(signer);
ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO,
asn1_ret);
}
return ret;
}
/**
* SignerInfos ::= SET of SignerInfo
* Return number of signers added to the signed data,
* 0 or higher is valid.
* Return negative error code for failure.
**/
static int pkcs7_get_signers_info_set(unsigned char **p, unsigned char *end,
mbedtls_pkcs7_signer_info *signers_set,
mbedtls_x509_buf *digest_alg)
{
unsigned char *end_set;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
int count = 0;
size_t len = 0;
ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SET);
if (ret != 0) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO, ret);
}
/* Detect zero signers */
if (len == 0) {
return 0;
}
end_set = *p + len;
ret = pkcs7_get_signer_info(p, end_set, signers_set, digest_alg);
if (ret != 0) {
return ret;
}
count++;
mbedtls_pkcs7_signer_info *prev = signers_set;
while (*p != end_set) {
mbedtls_pkcs7_signer_info *signer =
mbedtls_calloc(1, sizeof(mbedtls_pkcs7_signer_info));
if (!signer) {
ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
goto cleanup;
}
ret = pkcs7_get_signer_info(p, end_set, signer, digest_alg);
if (ret != 0) {
mbedtls_free(signer);
goto cleanup;
}
prev->next = signer;
prev = signer;
count++;
}
return count;
cleanup:
pkcs7_free_signer_info(signers_set);
mbedtls_pkcs7_signer_info *signer = signers_set->next;
while (signer != NULL) {
prev = signer;
signer = signer->next;
pkcs7_free_signer_info(prev);
mbedtls_free(prev);
}
signers_set->next = NULL;
return ret;
}
/**
* SignedData ::= SEQUENCE {
* version Version,
* digestAlgorithms DigestAlgorithmIdentifiers,
* contentInfo ContentInfo,
* certificates
* [0] IMPLICIT ExtendedCertificatesAndCertificates
* OPTIONAL,
* crls
* [0] IMPLICIT CertificateRevocationLists OPTIONAL,
* signerInfos SignerInfos }
*/
static int pkcs7_get_signed_data(unsigned char *buf, size_t buflen,
mbedtls_pkcs7_signed_data *signed_data)
{
unsigned char *p = buf;
unsigned char *end = buf + buflen;
unsigned char *end_content_info = NULL;
size_t len = 0;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_md_type_t md_alg;
ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE);
if (ret != 0) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret);
}
if (p + len != end) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT,
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
}
/* Get version of signed data */
ret = pkcs7_get_version(&p, end, &signed_data->version);
if (ret != 0) {
return ret;
}
/* Get digest algorithm */
ret = pkcs7_get_digest_algorithm_set(&p, end,
&signed_data->digest_alg_identifiers);
if (ret != 0) {
return ret;
}
ret = mbedtls_oid_get_md_alg(&signed_data->digest_alg_identifiers, &md_alg);
if (ret != 0) {
return MBEDTLS_ERR_PKCS7_INVALID_ALG;
}
mbedtls_pkcs7_buf content_type;
memset(&content_type, 0, sizeof(content_type));
ret = pkcs7_get_content_info_type(&p, end, &end_content_info, &content_type);
if (ret != 0) {
return ret;
}
if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS7_DATA, &content_type)) {
return MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO;
}
if (p != end_content_info) {
/* Determine if valid content is present */
ret = mbedtls_asn1_get_tag(&p,
end_content_info,
&len,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC);
if (ret != 0) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret);
}
p += len;
if (p != end_content_info) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret);
}
/* Valid content is present - this is not supported */
return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
}
/* Look for certificates, there may or may not be any */
mbedtls_x509_crt_init(&signed_data->certs);
ret = pkcs7_get_certificates(&p, end, &signed_data->certs);
if (ret < 0) {
return ret;
}
signed_data->no_of_certs = ret;
/*
* Currently CRLs are not supported. If CRL exist, the parsing will fail
* at next step of getting signers info and return error as invalid
* signer info.
*/
signed_data->no_of_crls = 0;
/* Get signers info */
ret = pkcs7_get_signers_info_set(&p,
end,
&signed_data->signers,
&signed_data->digest_alg_identifiers);
if (ret < 0) {
return ret;
}
signed_data->no_of_signers = ret;
/* Don't permit trailing data */
if (p != end) {
return MBEDTLS_ERR_PKCS7_INVALID_FORMAT;
}
return 0;
}
int mbedtls_pkcs7_parse_der(mbedtls_pkcs7 *pkcs7, const unsigned char *buf,
const size_t buflen)
{
unsigned char *p;
unsigned char *end;
size_t len = 0;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if (pkcs7 == NULL) {
return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
}
/* make an internal copy of the buffer for parsing */
pkcs7->raw.p = p = mbedtls_calloc(1, buflen);
if (pkcs7->raw.p == NULL) {
ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
goto out;
}
memcpy(p, buf, buflen);
pkcs7->raw.len = buflen;
end = p + buflen;
ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE);
if (ret != 0) {
ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret);
goto out;
}
if ((size_t) (end - p) != len) {
ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT,
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
goto out;
}
if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) {
if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
goto out;
}
p = pkcs7->raw.p;
len = buflen;
goto try_data;
}
if (MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_SIGNED_DATA, p, len)) {
/* OID is not MBEDTLS_OID_PKCS7_SIGNED_DATA, which is the only supported feature */
if (!MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_DATA, p, len)
|| !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, p, len)
|| !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_ENVELOPED_DATA, p, len)
|| !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA, p, len)
|| !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_DIGESTED_DATA, p, len)) {
/* OID is valid according to the spec, but unsupported */
ret = MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
} else {
/* OID is invalid according to the spec */
ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
}
goto out;
}
p += len;
ret = pkcs7_get_next_content_len(&p, end, &len);
if (ret != 0) {
goto out;
}
/* ensure no extra/missing data */
if (p + len != end) {
ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
goto out;
}
try_data:
ret = pkcs7_get_signed_data(p, len, &pkcs7->signed_data);
if (ret != 0) {
goto out;
}
ret = MBEDTLS_PKCS7_SIGNED_DATA;
out:
if (ret < 0) {
mbedtls_pkcs7_free(pkcs7);
}
return ret;
}
static int mbedtls_pkcs7_data_or_hash_verify(mbedtls_pkcs7 *pkcs7,
const mbedtls_x509_crt *cert,
const unsigned char *data,
size_t datalen,
const int is_data_hash)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *hash;
mbedtls_pk_context pk_cxt = cert->pk;
const mbedtls_md_info_t *md_info;
mbedtls_md_type_t md_alg;
mbedtls_pkcs7_signer_info *signer;
if (pkcs7->signed_data.no_of_signers == 0) {
return MBEDTLS_ERR_PKCS7_INVALID_CERT;
}
if (mbedtls_x509_time_is_past(&cert->valid_to) ||
mbedtls_x509_time_is_future(&cert->valid_from)) {
return MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID;
}
ret = mbedtls_oid_get_md_alg(&pkcs7->signed_data.digest_alg_identifiers, &md_alg);
if (ret != 0) {
return ret;
}
md_info = mbedtls_md_info_from_type(md_alg);
if (md_info == NULL) {
return MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
}
hash = mbedtls_calloc(mbedtls_md_get_size(md_info), 1);
if (hash == NULL) {
return MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
}
/* BEGIN must free hash before jumping out */
if (is_data_hash) {
if (datalen != mbedtls_md_get_size(md_info)) {
ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
} else {
memcpy(hash, data, datalen);
}
} else {
ret = mbedtls_md(md_info, data, datalen, hash);
}
if (ret != 0) {
mbedtls_free(hash);
return MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
}
/* assume failure */
ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
/*
* Potential TODOs
* Currently we iterate over all signers and return success if any of them
* verify.
*
* However, we could make this better by checking against the certificate's
* identification and SignerIdentifier fields first. That would also allow
* us to distinguish between 'no signature for key' and 'signature for key
* failed to validate'.
*/
for (signer = &pkcs7->signed_data.signers; signer; signer = signer->next) {
ret = mbedtls_pk_verify(&pk_cxt, md_alg, hash,
mbedtls_md_get_size(md_info),
signer->sig.p, signer->sig.len);
if (ret == 0) {
break;
}
}
mbedtls_free(hash);
/* END must free hash before jumping out */
return ret;
}
int mbedtls_pkcs7_signed_data_verify(mbedtls_pkcs7 *pkcs7,
const mbedtls_x509_crt *cert,
const unsigned char *data,
size_t datalen)
{
if (data == NULL) {
return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
}
return mbedtls_pkcs7_data_or_hash_verify(pkcs7, cert, data, datalen, 0);
}
int mbedtls_pkcs7_signed_hash_verify(mbedtls_pkcs7 *pkcs7,
const mbedtls_x509_crt *cert,
const unsigned char *hash,
size_t hashlen)
{
if (hash == NULL) {
return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
}
return mbedtls_pkcs7_data_or_hash_verify(pkcs7, cert, hash, hashlen, 1);
}
/*
* Unallocate all pkcs7 data
*/
void mbedtls_pkcs7_free(mbedtls_pkcs7 *pkcs7)
{
mbedtls_pkcs7_signer_info *signer_cur;
mbedtls_pkcs7_signer_info *signer_prev;
if (pkcs7 == NULL || pkcs7->raw.p == NULL) {
return;
}
mbedtls_free(pkcs7->raw.p);
mbedtls_x509_crt_free(&pkcs7->signed_data.certs);
mbedtls_x509_crl_free(&pkcs7->signed_data.crl);
signer_cur = pkcs7->signed_data.signers.next;
pkcs7_free_signer_info(&pkcs7->signed_data.signers);
while (signer_cur != NULL) {
signer_prev = signer_cur;
signer_cur = signer_prev->next;
pkcs7_free_signer_info(signer_prev);
mbedtls_free(signer_prev);
}
pkcs7->raw.p = NULL;
}
#endif

1392
thirdparty/mbedtls/library/pkparse.c vendored Normal file

File diff suppressed because it is too large Load Diff

629
thirdparty/mbedtls/library/pkwrite.c vendored Normal file
View File

@@ -0,0 +1,629 @@
/*
* Public Key layer for writing key files and structures
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#if defined(MBEDTLS_PK_WRITE_C)
#include "mbedtls/pk.h"
#include "mbedtls/asn1write.h"
#include "mbedtls/oid.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#include "pk_internal.h"
#include <string.h>
#if defined(MBEDTLS_ECP_C)
#include "mbedtls/bignum.h"
#include "mbedtls/ecp.h"
#include "mbedtls/platform_util.h"
#endif
#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
#include "pk_internal.h"
#endif
#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_HAVE_ECC_KEYS)
#include "pkwrite.h"
#endif
#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"
#include "psa_util_internal.h"
#endif
#include "mbedtls/platform.h"
/* Helpers for properly sizing buffers aimed at holding public keys or
* key-pairs based on build symbols. */
#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
#define PK_MAX_EC_PUBLIC_KEY_SIZE PSA_EXPORT_PUBLIC_KEY_MAX_SIZE
#define PK_MAX_EC_KEY_PAIR_SIZE MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH
#elif defined(MBEDTLS_USE_PSA_CRYPTO)
#define PK_MAX_EC_PUBLIC_KEY_SIZE PSA_EXPORT_PUBLIC_KEY_MAX_SIZE
#define PK_MAX_EC_KEY_PAIR_SIZE MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH
#else
#define PK_MAX_EC_PUBLIC_KEY_SIZE MBEDTLS_ECP_MAX_PT_LEN
#define PK_MAX_EC_KEY_PAIR_SIZE MBEDTLS_ECP_MAX_BYTES
#endif
/******************************************************************************
* Internal functions for RSA keys.
******************************************************************************/
#if defined(MBEDTLS_RSA_C)
static int pk_write_rsa_der(unsigned char **p, unsigned char *buf,
const mbedtls_pk_context *pk)
{
#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;
if (psa_export_key(pk->priv_id, tmp, sizeof(tmp), &tmp_len) != PSA_SUCCESS) {
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
}
/* Ensure there's enough space in the provided buffer before copying data into it. */
if (tmp_len > (size_t) (*p - buf)) {
mbedtls_platform_zeroize(tmp, sizeof(tmp));
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
}
*p -= tmp_len;
memcpy(*p, tmp, tmp_len);
mbedtls_platform_zeroize(tmp, sizeof(tmp));
return (int) tmp_len;
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
return mbedtls_rsa_write_key(mbedtls_pk_rsa(*pk), buf, p);
}
#endif /* MBEDTLS_RSA_C */
/******************************************************************************
* Internal functions for EC keys.
******************************************************************************/
#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start,
const mbedtls_pk_context *pk)
{
size_t len = 0;
uint8_t buf[PK_MAX_EC_PUBLIC_KEY_SIZE];
if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) {
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
}
} else {
len = pk->pub_raw_len;
memcpy(buf, pk->pub_raw, len);
}
if (*p < start || (size_t) (*p - start) < len) {
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
}
*p -= len;
memcpy(*p, buf, len);
return (int) len;
}
#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start,
const mbedtls_pk_context *pk)
{
size_t len = 0;
unsigned char buf[PK_MAX_EC_PUBLIC_KEY_SIZE];
mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*pk);
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) {
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
}
/* Ensure there's enough space in the provided buffer before copying data into it. */
if (len > (size_t) (*p - start)) {
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
}
*p -= len;
memcpy(*p, buf, len);
return (int) len;
} else
#endif /* MBEDTLS_USE_PSA_CRYPTO */
{
if ((ret = mbedtls_ecp_point_write_binary(&ec->grp, &ec->Q,
MBEDTLS_ECP_PF_UNCOMPRESSED,
&len, buf, sizeof(buf))) != 0) {
return ret;
}
}
if (*p < start || (size_t) (*p - start) < len) {
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
}
*p -= len;
memcpy(*p, buf, len);
return (int) len;
}
#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
/*
* privateKey OCTET STRING -- always of length ceil(log2(n)/8)
*/
#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
static int pk_write_ec_private(unsigned char **p, unsigned char *start,
const mbedtls_pk_context *pk)
{
size_t byte_length;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char tmp[PK_MAX_EC_KEY_PAIR_SIZE];
psa_status_t status;
if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length);
if (status != PSA_SUCCESS) {
ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
return ret;
}
} else {
status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length);
if (status != PSA_SUCCESS) {
ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
goto exit;
}
}
ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length);
exit:
mbedtls_platform_zeroize(tmp, sizeof(tmp));
return ret;
}
#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
static int pk_write_ec_private(unsigned char **p, unsigned char *start,
const mbedtls_pk_context *pk)
{
size_t byte_length;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char tmp[PK_MAX_EC_KEY_PAIR_SIZE];
#if defined(MBEDTLS_USE_PSA_CRYPTO)
psa_status_t status;
if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length);
if (status != PSA_SUCCESS) {
ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
return ret;
}
} else
#endif /* MBEDTLS_USE_PSA_CRYPTO */
{
mbedtls_ecp_keypair *ec = mbedtls_pk_ec_rw(*pk);
byte_length = (ec->grp.pbits + 7) / 8;
ret = mbedtls_ecp_write_key_ext(ec, &byte_length, tmp, sizeof(tmp));
if (ret != 0) {
goto exit;
}
}
ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length);
exit:
mbedtls_platform_zeroize(tmp, sizeof(tmp));
return ret;
}
#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
/*
* ECParameters ::= CHOICE {
* namedCurve OBJECT IDENTIFIER
* }
*/
static int pk_write_ec_param(unsigned char **p, unsigned char *start,
mbedtls_ecp_group_id grp_id)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
const char *oid;
size_t oid_len;
if ((ret = mbedtls_oid_get_oid_by_ec_grp(grp_id, &oid, &oid_len)) != 0) {
return ret;
}
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len));
return (int) len;
}
#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
/*
* RFC8410 section 7
*
* OneAsymmetricKey ::= SEQUENCE {
* version Version,
* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
* privateKey PrivateKey,
* attributes [0] IMPLICIT Attributes OPTIONAL,
* ...,
* [[2: publicKey [1] IMPLICIT PublicKey OPTIONAL ]],
* ...
* }
* ...
* CurvePrivateKey ::= OCTET STRING
*/
static int pk_write_ec_rfc8410_der(unsigned char **p, unsigned char *buf,
const mbedtls_pk_context *pk)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
size_t oid_len = 0;
const char *oid;
mbedtls_ecp_group_id grp_id;
/* privateKey */
MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(p, buf, pk));
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_OCTET_STRING));
grp_id = mbedtls_pk_get_ec_group_id(pk);
/* privateKeyAlgorithm */
if ((ret = mbedtls_oid_get_oid_by_ec_grp_algid(grp_id, &oid, &oid_len)) != 0) {
return ret;
}
MBEDTLS_ASN1_CHK_ADD(len,
mbedtls_asn1_write_algorithm_identifier_ext(p, buf, oid, oid_len, 0, 0));
/* version */
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;
}
#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
/*
* RFC 5915, or SEC1 Appendix C.4
*
* ECPrivateKey ::= SEQUENCE {
* version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
* privateKey OCTET STRING,
* parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
* publicKey [1] BIT STRING OPTIONAL
* }
*/
static int pk_write_ec_der(unsigned char **p, unsigned char *buf,
const mbedtls_pk_context *pk)
{
size_t len = 0;
int ret;
size_t pub_len = 0, par_len = 0;
mbedtls_ecp_group_id grp_id;
/* publicKey */
MBEDTLS_ASN1_CHK_ADD(pub_len, pk_write_ec_pubkey(p, buf, pk));
if (*p - buf < 1) {
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
}
(*p)--;
**p = 0;
pub_len += 1;
MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(p, buf, pub_len));
MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_BIT_STRING));
MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(p, buf, pub_len));
MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(p, buf,
MBEDTLS_ASN1_CONTEXT_SPECIFIC |
MBEDTLS_ASN1_CONSTRUCTED | 1));
len += pub_len;
/* parameters */
grp_id = mbedtls_pk_get_ec_group_id(pk);
MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(p, buf, grp_id));
MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_len(p, buf, par_len));
MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_tag(p, buf,
MBEDTLS_ASN1_CONTEXT_SPECIFIC |
MBEDTLS_ASN1_CONSTRUCTED | 0));
len += par_len;
/* privateKey */
MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(p, buf, pk));
/* version */
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 1));
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;
}
#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
/******************************************************************************
* Internal functions for Opaque keys.
******************************************************************************/
#if defined(MBEDTLS_USE_PSA_CRYPTO)
static int pk_write_opaque_pubkey(unsigned char **p, unsigned char *start,
const mbedtls_pk_context *pk)
{
size_t buffer_size;
size_t len = 0;
if (*p < start) {
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
}
buffer_size = (size_t) (*p - start);
if (psa_export_public_key(pk->priv_id, start, buffer_size,
&len) != PSA_SUCCESS) {
return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
}
*p -= len;
memmove(*p, start, len);
return (int) len;
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
/******************************************************************************
* Generic helpers
******************************************************************************/
/* Extend the public mbedtls_pk_get_type() by getting key type also in case of
* opaque keys. */
static mbedtls_pk_type_t pk_get_type_ext(const mbedtls_pk_context *pk)
{
mbedtls_pk_type_t pk_type = mbedtls_pk_get_type(pk);
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if (pk_type == MBEDTLS_PK_OPAQUE) {
psa_key_attributes_t opaque_attrs = PSA_KEY_ATTRIBUTES_INIT;
psa_key_type_t opaque_key_type;
if (psa_get_key_attributes(pk->priv_id, &opaque_attrs) != PSA_SUCCESS) {
return MBEDTLS_PK_NONE;
}
opaque_key_type = psa_get_key_type(&opaque_attrs);
psa_reset_key_attributes(&opaque_attrs);
if (PSA_KEY_TYPE_IS_ECC(opaque_key_type)) {
return MBEDTLS_PK_ECKEY;
} else if (PSA_KEY_TYPE_IS_RSA(opaque_key_type)) {
return MBEDTLS_PK_RSA;
} else {
return MBEDTLS_PK_NONE;
}
} else
#endif
return pk_type;
}
/******************************************************************************
* Public functions for writing private/public DER keys.
******************************************************************************/
int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start,
const mbedtls_pk_context *key)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0;
#if defined(MBEDTLS_RSA_C)
if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) {
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_rsa_write_pubkey(mbedtls_pk_rsa(*key), start, p));
} else
#endif
#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) {
MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_pubkey(p, start, key));
} else
#endif
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if (mbedtls_pk_get_type(key) == MBEDTLS_PK_OPAQUE) {
MBEDTLS_ASN1_CHK_ADD(len, pk_write_opaque_pubkey(p, start, key));
} else
#endif /* MBEDTLS_USE_PSA_CRYPTO */
return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
return (int) len;
}
int mbedtls_pk_write_pubkey_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *c;
int has_par = 1;
size_t len = 0, par_len = 0, oid_len = 0;
mbedtls_pk_type_t pk_type;
const char *oid = NULL;
if (size == 0) {
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
}
c = buf + size;
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_pk_write_pubkey(&c, buf, key));
if (c - buf < 1) {
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
}
/*
* SubjectPublicKeyInfo ::= SEQUENCE {
* algorithm AlgorithmIdentifier,
* subjectPublicKey BIT STRING }
*/
*--c = 0;
len += 1;
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING));
pk_type = pk_get_type_ext(key);
#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) {
mbedtls_ecp_group_id ec_grp_id = mbedtls_pk_get_ec_group_id(key);
if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) {
ret = mbedtls_oid_get_oid_by_ec_grp_algid(ec_grp_id, &oid, &oid_len);
if (ret != 0) {
return ret;
}
has_par = 0;
} else {
MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, ec_grp_id));
}
}
#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
/* At this point oid_len is not null only for EC Montgomery keys. */
if (oid_len == 0) {
ret = mbedtls_oid_get_oid_by_pk_alg(pk_type, &oid, &oid_len);
if (ret != 0) {
return ret;
}
}
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier_ext(&c, buf, oid, oid_len,
par_len, has_par));
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SEQUENCE));
return (int) len;
}
int mbedtls_pk_write_key_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
{
unsigned char *c;
if (size == 0) {
return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
}
c = buf + size;
#if defined(MBEDTLS_RSA_C)
if (pk_get_type_ext(key) == MBEDTLS_PK_RSA) {
return pk_write_rsa_der(&c, buf, key);
} else
#endif /* MBEDTLS_RSA_C */
#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) {
#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
if (mbedtls_pk_is_rfc8410(key)) {
return pk_write_ec_rfc8410_der(&c, buf, key);
}
#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
return pk_write_ec_der(&c, buf, key);
} else
#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
}
/******************************************************************************
* Public functions for wrinting private/public PEM keys.
******************************************************************************/
#if defined(MBEDTLS_PEM_WRITE_C)
#define PUB_DER_MAX_BYTES \
(MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES > MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES ? \
MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES : MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES)
#define PRV_DER_MAX_BYTES \
(MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES > MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES ? \
MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES : MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES)
int mbedtls_pk_write_pubkey_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *output_buf = NULL;
output_buf = mbedtls_calloc(1, PUB_DER_MAX_BYTES);
if (output_buf == NULL) {
return MBEDTLS_ERR_PK_ALLOC_FAILED;
}
size_t olen = 0;
if ((ret = mbedtls_pk_write_pubkey_der(key, output_buf,
PUB_DER_MAX_BYTES)) < 0) {
goto cleanup;
}
if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_PUBLIC_KEY "\n", PEM_END_PUBLIC_KEY "\n",
output_buf + PUB_DER_MAX_BYTES - ret,
ret, buf, size, &olen)) != 0) {
goto cleanup;
}
ret = 0;
cleanup:
mbedtls_free(output_buf);
return ret;
}
int mbedtls_pk_write_key_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *output_buf = NULL;
output_buf = mbedtls_calloc(1, PRV_DER_MAX_BYTES);
if (output_buf == NULL) {
return MBEDTLS_ERR_PK_ALLOC_FAILED;
}
const char *begin, *end;
size_t olen = 0;
if ((ret = mbedtls_pk_write_key_der(key, output_buf, PRV_DER_MAX_BYTES)) < 0) {
goto cleanup;
}
#if defined(MBEDTLS_RSA_C)
if (pk_get_type_ext(key) == MBEDTLS_PK_RSA) {
begin = PEM_BEGIN_PRIVATE_KEY_RSA "\n";
end = PEM_END_PRIVATE_KEY_RSA "\n";
} else
#endif
#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) {
if (mbedtls_pk_is_rfc8410(key)) {
begin = PEM_BEGIN_PRIVATE_KEY_PKCS8 "\n";
end = PEM_END_PRIVATE_KEY_PKCS8 "\n";
} else {
begin = PEM_BEGIN_PRIVATE_KEY_EC "\n";
end = PEM_END_PRIVATE_KEY_EC "\n";
}
} else
#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
{
ret = MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
goto cleanup;
}
if ((ret = mbedtls_pem_write_buffer(begin, end,
output_buf + PRV_DER_MAX_BYTES - ret,
ret, buf, size, &olen)) != 0) {
goto cleanup;
}
ret = 0;
cleanup:
mbedtls_zeroize_and_free(output_buf, PRV_DER_MAX_BYTES);
return ret;
}
#endif /* MBEDTLS_PEM_WRITE_C */
#endif /* MBEDTLS_PK_WRITE_C */

121
thirdparty/mbedtls/library/pkwrite.h vendored Normal file
View File

@@ -0,0 +1,121 @@
/**
* \file pkwrite.h
*
* \brief Internal defines shared by the PK write module
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef MBEDTLS_PK_WRITE_H
#define MBEDTLS_PK_WRITE_H
#include "mbedtls/build_info.h"
#include "mbedtls/pk.h"
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#include "psa/crypto.h"
#endif /* MBEDTLS_USE_PSA_CRYPTO */
/*
* Max sizes of key per types. Shown as tag + len (+ content).
*/
#if defined(MBEDTLS_RSA_C)
/*
* RSA public keys:
* SubjectPublicKeyInfo ::= SEQUENCE { 1 + 3
* algorithm AlgorithmIdentifier, 1 + 1 (sequence)
* + 1 + 1 + 9 (rsa oid)
* + 1 + 1 (params null)
* subjectPublicKey BIT STRING } 1 + 3 + (1 + below)
* RSAPublicKey ::= SEQUENCE { 1 + 3
* modulus INTEGER, -- n 1 + 3 + MPI_MAX + 1
* publicExponent INTEGER -- e 1 + 3 + MPI_MAX + 1
* }
*/
#define MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES (38 + 2 * MBEDTLS_MPI_MAX_SIZE)
/*
* RSA private keys:
* RSAPrivateKey ::= SEQUENCE { 1 + 3
* version Version, 1 + 1 + 1
* modulus INTEGER, 1 + 3 + MPI_MAX + 1
* publicExponent INTEGER, 1 + 3 + MPI_MAX + 1
* privateExponent INTEGER, 1 + 3 + MPI_MAX + 1
* prime1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1
* prime2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1
* exponent1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1
* exponent2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1
* coefficient INTEGER, 1 + 3 + MPI_MAX / 2 + 1
* otherPrimeInfos OtherPrimeInfos OPTIONAL 0 (not supported)
* }
*/
#define MBEDTLS_MPI_MAX_SIZE_2 (MBEDTLS_MPI_MAX_SIZE / 2 + \
MBEDTLS_MPI_MAX_SIZE % 2)
#define MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES (47 + 3 * MBEDTLS_MPI_MAX_SIZE \
+ 5 * MBEDTLS_MPI_MAX_SIZE_2)
#else /* MBEDTLS_RSA_C */
#define MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES 0
#define MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES 0
#endif /* MBEDTLS_RSA_C */
#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
/* Find the maximum number of bytes necessary to store an EC point. When USE_PSA
* is defined this means looking for the maximum between PSA and built-in
* supported curves. */
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#define MBEDTLS_PK_MAX_ECC_BYTES (PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS) > \
MBEDTLS_ECP_MAX_BYTES ? \
PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS) : \
MBEDTLS_ECP_MAX_BYTES)
#else /* MBEDTLS_USE_PSA_CRYPTO */
#define MBEDTLS_PK_MAX_ECC_BYTES MBEDTLS_ECP_MAX_BYTES
#endif /* MBEDTLS_USE_PSA_CRYPTO */
/*
* EC public keys:
* SubjectPublicKeyInfo ::= SEQUENCE { 1 + 2
* algorithm AlgorithmIdentifier, 1 + 1 (sequence)
* + 1 + 1 + 7 (ec oid)
* + 1 + 1 + 9 (namedCurve oid)
* subjectPublicKey BIT STRING 1 + 2 + 1 [1]
* + 1 (point format) [1]
* + 2 * ECP_MAX (coords) [1]
* }
*/
#define MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES (30 + 2 * MBEDTLS_PK_MAX_ECC_BYTES)
/*
* EC private keys:
* ECPrivateKey ::= SEQUENCE { 1 + 2
* version INTEGER , 1 + 1 + 1
* privateKey OCTET STRING, 1 + 1 + ECP_MAX
* parameters [0] ECParameters OPTIONAL, 1 + 1 + (1 + 1 + 9)
* publicKey [1] BIT STRING OPTIONAL 1 + 2 + [1] above
* }
*/
#define MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES (29 + 3 * MBEDTLS_PK_MAX_ECC_BYTES)
#else /* MBEDTLS_PK_HAVE_ECC_KEYS */
#define MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES 0
#define MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES 0
#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
/* Define the maximum available public key DER length based on the supported
* key types (EC and/or RSA). */
#if (MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES > MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES)
#define MBEDTLS_PK_WRITE_PUBKEY_MAX_SIZE MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES
#else
#define MBEDTLS_PK_WRITE_PUBKEY_MAX_SIZE MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES
#endif
#endif /* MBEDTLS_PK_WRITE_H */

402
thirdparty/mbedtls/library/platform.c vendored Normal file
View File

@@ -0,0 +1,402 @@
/*
* Platform abstraction layer
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
/* The compile time configuration of memory allocation via the macros
* MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO takes precedence over the runtime
* configuration via mbedtls_platform_set_calloc_free(). So, omit everything
* related to the latter if MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO are defined. */
#if defined(MBEDTLS_PLATFORM_MEMORY) && \
!(defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && \
defined(MBEDTLS_PLATFORM_FREE_MACRO))
#if !defined(MBEDTLS_PLATFORM_STD_CALLOC)
static void *platform_calloc_uninit(size_t n, size_t size)
{
((void) n);
((void) size);
return NULL;
}
#define MBEDTLS_PLATFORM_STD_CALLOC platform_calloc_uninit
#endif /* !MBEDTLS_PLATFORM_STD_CALLOC */
#if !defined(MBEDTLS_PLATFORM_STD_FREE)
static void platform_free_uninit(void *ptr)
{
((void) ptr);
}
#define MBEDTLS_PLATFORM_STD_FREE platform_free_uninit
#endif /* !MBEDTLS_PLATFORM_STD_FREE */
static void * (*mbedtls_calloc_func)(size_t, size_t) = MBEDTLS_PLATFORM_STD_CALLOC;
static void (*mbedtls_free_func)(void *) = MBEDTLS_PLATFORM_STD_FREE;
void *mbedtls_calloc(size_t nmemb, size_t size)
{
return (*mbedtls_calloc_func)(nmemb, size);
}
void mbedtls_free(void *ptr)
{
(*mbedtls_free_func)(ptr);
}
int mbedtls_platform_set_calloc_free(void *(*calloc_func)(size_t, size_t),
void (*free_func)(void *))
{
mbedtls_calloc_func = calloc_func;
mbedtls_free_func = free_func;
return 0;
}
#endif /* MBEDTLS_PLATFORM_MEMORY &&
!( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&
defined(MBEDTLS_PLATFORM_FREE_MACRO) ) */
#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF)
#include <stdarg.h>
int mbedtls_platform_win32_snprintf(char *s, size_t n, const char *fmt, ...)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
va_list argp;
va_start(argp, fmt);
ret = mbedtls_vsnprintf(s, n, fmt, argp);
va_end(argp);
return ret;
}
#endif
#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT)
#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF)
/*
* Make dummy function to prevent NULL pointer dereferences
*/
static int platform_snprintf_uninit(char *s, size_t n,
const char *format, ...)
{
((void) s);
((void) n);
((void) format);
return 0;
}
#define MBEDTLS_PLATFORM_STD_SNPRINTF platform_snprintf_uninit
#endif /* !MBEDTLS_PLATFORM_STD_SNPRINTF */
int (*mbedtls_snprintf)(char *s, size_t n,
const char *format,
...) = MBEDTLS_PLATFORM_STD_SNPRINTF;
int mbedtls_platform_set_snprintf(int (*snprintf_func)(char *s, size_t n,
const char *format,
...))
{
mbedtls_snprintf = snprintf_func;
return 0;
}
#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */
#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF)
#include <stdarg.h>
int mbedtls_platform_win32_vsnprintf(char *s, size_t n, const char *fmt, va_list arg)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* Avoid calling the invalid parameter handler by checking ourselves */
if (s == NULL || n == 0 || fmt == NULL) {
return -1;
}
#if defined(_TRUNCATE)
ret = vsnprintf_s(s, n, _TRUNCATE, fmt, arg);
#else
ret = vsnprintf(s, n, fmt, arg);
if (ret < 0 || (size_t) ret == n) {
s[n-1] = '\0';
ret = -1;
}
#endif
return ret;
}
#endif
#if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT)
#if !defined(MBEDTLS_PLATFORM_STD_VSNPRINTF)
/*
* Make dummy function to prevent NULL pointer dereferences
*/
static int platform_vsnprintf_uninit(char *s, size_t n,
const char *format, va_list arg)
{
((void) s);
((void) n);
((void) format);
((void) arg);
return -1;
}
#define MBEDTLS_PLATFORM_STD_VSNPRINTF platform_vsnprintf_uninit
#endif /* !MBEDTLS_PLATFORM_STD_VSNPRINTF */
int (*mbedtls_vsnprintf)(char *s, size_t n,
const char *format,
va_list arg) = MBEDTLS_PLATFORM_STD_VSNPRINTF;
int mbedtls_platform_set_vsnprintf(int (*vsnprintf_func)(char *s, size_t n,
const char *format,
va_list arg))
{
mbedtls_vsnprintf = vsnprintf_func;
return 0;
}
#endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */
#if defined(MBEDTLS_PLATFORM_PRINTF_ALT)
#if !defined(MBEDTLS_PLATFORM_STD_PRINTF)
/*
* Make dummy function to prevent NULL pointer dereferences
*/
static int platform_printf_uninit(const char *format, ...)
{
((void) format);
return 0;
}
#define MBEDTLS_PLATFORM_STD_PRINTF platform_printf_uninit
#endif /* !MBEDTLS_PLATFORM_STD_PRINTF */
int (*mbedtls_printf)(const char *, ...) = MBEDTLS_PLATFORM_STD_PRINTF;
int mbedtls_platform_set_printf(int (*printf_func)(const char *, ...))
{
mbedtls_printf = printf_func;
return 0;
}
#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */
#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT)
#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF)
/*
* Make dummy function to prevent NULL pointer dereferences
*/
static int platform_fprintf_uninit(FILE *stream, const char *format, ...)
{
((void) stream);
((void) format);
return 0;
}
#define MBEDTLS_PLATFORM_STD_FPRINTF platform_fprintf_uninit
#endif /* !MBEDTLS_PLATFORM_STD_FPRINTF */
int (*mbedtls_fprintf)(FILE *, const char *, ...) =
MBEDTLS_PLATFORM_STD_FPRINTF;
int mbedtls_platform_set_fprintf(int (*fprintf_func)(FILE *, const char *, ...))
{
mbedtls_fprintf = fprintf_func;
return 0;
}
#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */
#if defined(MBEDTLS_PLATFORM_SETBUF_ALT)
#if !defined(MBEDTLS_PLATFORM_STD_SETBUF)
/*
* Make dummy function to prevent NULL pointer dereferences
*/
static void platform_setbuf_uninit(FILE *stream, char *buf)
{
((void) stream);
((void) buf);
}
#define MBEDTLS_PLATFORM_STD_SETBUF platform_setbuf_uninit
#endif /* !MBEDTLS_PLATFORM_STD_SETBUF */
void (*mbedtls_setbuf)(FILE *stream, char *buf) = MBEDTLS_PLATFORM_STD_SETBUF;
int mbedtls_platform_set_setbuf(void (*setbuf_func)(FILE *stream, char *buf))
{
mbedtls_setbuf = setbuf_func;
return 0;
}
#endif /* MBEDTLS_PLATFORM_SETBUF_ALT */
#if defined(MBEDTLS_PLATFORM_EXIT_ALT)
#if !defined(MBEDTLS_PLATFORM_STD_EXIT)
/*
* Make dummy function to prevent NULL pointer dereferences
*/
static void platform_exit_uninit(int status)
{
((void) status);
}
#define MBEDTLS_PLATFORM_STD_EXIT platform_exit_uninit
#endif /* !MBEDTLS_PLATFORM_STD_EXIT */
void (*mbedtls_exit)(int status) = MBEDTLS_PLATFORM_STD_EXIT;
int mbedtls_platform_set_exit(void (*exit_func)(int status))
{
mbedtls_exit = exit_func;
return 0;
}
#endif /* MBEDTLS_PLATFORM_EXIT_ALT */
#if defined(MBEDTLS_HAVE_TIME)
#if defined(MBEDTLS_PLATFORM_TIME_ALT)
#if !defined(MBEDTLS_PLATFORM_STD_TIME)
/*
* Make dummy function to prevent NULL pointer dereferences
*/
static mbedtls_time_t platform_time_uninit(mbedtls_time_t *timer)
{
((void) timer);
return 0;
}
#define MBEDTLS_PLATFORM_STD_TIME platform_time_uninit
#endif /* !MBEDTLS_PLATFORM_STD_TIME */
mbedtls_time_t (*mbedtls_time)(mbedtls_time_t *timer) = MBEDTLS_PLATFORM_STD_TIME;
int mbedtls_platform_set_time(mbedtls_time_t (*time_func)(mbedtls_time_t *timer))
{
mbedtls_time = time_func;
return 0;
}
#endif /* MBEDTLS_PLATFORM_TIME_ALT */
#endif /* MBEDTLS_HAVE_TIME */
#if defined(MBEDTLS_ENTROPY_NV_SEED)
#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO)
/* Default implementations for the platform independent seed functions use
* standard libc file functions to read from and write to a pre-defined filename
*/
int mbedtls_platform_std_nv_seed_read(unsigned char *buf, size_t buf_len)
{
FILE *file;
size_t n;
if ((file = fopen(MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "rb")) == NULL) {
return -1;
}
/* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
mbedtls_setbuf(file, NULL);
if ((n = fread(buf, 1, buf_len, file)) != buf_len) {
fclose(file);
mbedtls_platform_zeroize(buf, buf_len);
return -1;
}
fclose(file);
return (int) n;
}
int mbedtls_platform_std_nv_seed_write(unsigned char *buf, size_t buf_len)
{
FILE *file;
size_t n;
if ((file = fopen(MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "w")) == NULL) {
return -1;
}
/* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
mbedtls_setbuf(file, NULL);
if ((n = fwrite(buf, 1, buf_len, file)) != buf_len) {
fclose(file);
return -1;
}
fclose(file);
return (int) n;
}
#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */
#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT)
#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ)
/*
* Make dummy function to prevent NULL pointer dereferences
*/
static int platform_nv_seed_read_uninit(unsigned char *buf, size_t buf_len)
{
((void) buf);
((void) buf_len);
return -1;
}
#define MBEDTLS_PLATFORM_STD_NV_SEED_READ platform_nv_seed_read_uninit
#endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_READ */
#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE)
/*
* Make dummy function to prevent NULL pointer dereferences
*/
static int platform_nv_seed_write_uninit(unsigned char *buf, size_t buf_len)
{
((void) buf);
((void) buf_len);
return -1;
}
#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE platform_nv_seed_write_uninit
#endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_WRITE */
int (*mbedtls_nv_seed_read)(unsigned char *buf, size_t buf_len) =
MBEDTLS_PLATFORM_STD_NV_SEED_READ;
int (*mbedtls_nv_seed_write)(unsigned char *buf, size_t buf_len) =
MBEDTLS_PLATFORM_STD_NV_SEED_WRITE;
int mbedtls_platform_set_nv_seed(
int (*nv_seed_read_func)(unsigned char *buf, size_t buf_len),
int (*nv_seed_write_func)(unsigned char *buf, size_t buf_len))
{
mbedtls_nv_seed_read = nv_seed_read_func;
mbedtls_nv_seed_write = nv_seed_write_func;
return 0;
}
#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */
#endif /* MBEDTLS_ENTROPY_NV_SEED */
#if !defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT)
/*
* Placeholder platform setup that does nothing by default
*/
int mbedtls_platform_setup(mbedtls_platform_context *ctx)
{
(void) ctx;
return 0;
}
/*
* Placeholder platform teardown that does nothing by default
*/
void mbedtls_platform_teardown(mbedtls_platform_context *ctx)
{
(void) ctx;
}
#endif /* MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */
#endif /* MBEDTLS_PLATFORM_C */

View File

@@ -0,0 +1,263 @@
/*
* Common and shared functions used by multiple modules in the Mbed TLS
* library.
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
/*
* Ensure gmtime_r is available even with -std=c99; must be defined before
* mbedtls_config.h, which pulls in glibc's features.h. Harmless on other platforms
* except OpenBSD, where it stops us accessing explicit_bzero.
*/
#if !defined(_POSIX_C_SOURCE) && !defined(__OpenBSD__)
#define _POSIX_C_SOURCE 200112L
#endif
#if !defined(_GNU_SOURCE)
/* Clang requires this to get support for explicit_bzero */
#define _GNU_SOURCE
#endif
#include "common.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/platform.h"
#include "mbedtls/threading.h"
#include <stddef.h>
#ifndef __STDC_WANT_LIB_EXT1__
#define __STDC_WANT_LIB_EXT1__ 1 /* Ask for the C11 gmtime_s() and memset_s() if available */
#endif
#include <string.h>
#if defined(_WIN32)
#include <windows.h>
#endif
// Detect platforms known to support explicit_bzero()
#if defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 25)
#define MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO 1
#elif (defined(__FreeBSD__) && (__FreeBSD_version >= 1100037)) || defined(__OpenBSD__)
#define MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO 1
#endif
#if !defined(MBEDTLS_PLATFORM_ZEROIZE_ALT)
#undef HAVE_MEMORY_SANITIZER
#if defined(__has_feature)
#if __has_feature(memory_sanitizer)
#include <sanitizer/msan_interface.h>
#define HAVE_MEMORY_SANITIZER
#endif
#endif
/*
* Where possible, we try to detect the presence of a platform-provided
* secure memset, such as explicit_bzero(), that is safe against being optimized
* out, and use that.
*
* For other platforms, we provide an implementation that aims not to be
* optimized out by the compiler.
*
* This implementation for mbedtls_platform_zeroize() was inspired from Colin
* Percival's blog article at:
*
* http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html
*
* It uses a volatile function pointer to the standard memset(). Because the
* pointer is volatile the compiler expects it to change at
* any time and will not optimize out the call that could potentially perform
* other operations on the input buffer instead of just setting it to 0.
* Nevertheless, as pointed out by davidtgoldblatt on Hacker News
* (refer to http://www.daemonology.net/blog/2014-09-05-erratum.html for
* details), optimizations of the following form are still possible:
*
* if (memset_func != memset)
* memset_func(buf, 0, len);
*
* Note that it is extremely difficult to guarantee that
* the memset() call will not be optimized out by aggressive compilers
* in a portable way. For this reason, Mbed TLS also provides the configuration
* option MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure
* mbedtls_platform_zeroize() to use a suitable implementation for their
* platform and needs.
*/
#if !defined(MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO) && !(defined(__STDC_LIB_EXT1__) && \
!defined(__IAR_SYSTEMS_ICC__)) \
&& !defined(_WIN32)
static void *(*const volatile memset_func)(void *, int, size_t) = memset;
#endif
void mbedtls_platform_zeroize(void *buf, size_t len)
{
if (len > 0) {
#if defined(MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO)
explicit_bzero(buf, len);
#if defined(HAVE_MEMORY_SANITIZER)
/* You'd think that Msan would recognize explicit_bzero() as
* equivalent to bzero(), but it actually doesn't on several
* platforms, including Linux (Ubuntu 20.04).
* https://github.com/google/sanitizers/issues/1507
* https://github.com/openssh/openssh-portable/commit/74433a19bb6f4cef607680fa4d1d7d81ca3826aa
*/
__msan_unpoison(buf, len);
#endif
#elif defined(__STDC_LIB_EXT1__) && !defined(__IAR_SYSTEMS_ICC__)
memset_s(buf, len, 0, len);
#elif defined(_WIN32)
SecureZeroMemory(buf, len);
#else
memset_func(buf, 0, len);
#endif
#if defined(__GNUC__)
/* For clang and recent gcc, pretend that we have some assembly that reads the
* zero'd memory as an additional protection against being optimised away. */
#if defined(__clang__) || (__GNUC__ >= 10)
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wvla"
#elif defined(MBEDTLS_COMPILER_IS_GCC)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wvla"
#endif
asm volatile ("" : : "m" (*(char (*)[len]) buf) :);
#if defined(__clang__)
#pragma clang diagnostic pop
#elif defined(MBEDTLS_COMPILER_IS_GCC)
#pragma GCC diagnostic pop
#endif
#endif
#endif
}
}
#endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */
void mbedtls_zeroize_and_free(void *buf, size_t len)
{
if (buf != NULL) {
mbedtls_platform_zeroize(buf, len);
}
mbedtls_free(buf);
}
#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT)
#include <time.h>
#if !defined(_WIN32) && (defined(unix) || \
defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \
defined(__MACH__)) || defined(__midipix__))
#include <unistd.h>
#endif /* !_WIN32 && (unix || __unix || __unix__ ||
* (__APPLE__ && __MACH__) || __midipix__) */
#if !((defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L) || \
(defined(_POSIX_THREAD_SAFE_FUNCTIONS) && \
_POSIX_THREAD_SAFE_FUNCTIONS >= 200112L))
/*
* This is a convenience shorthand macro to avoid checking the long
* preprocessor conditions above. Ideally, we could expose this macro in
* platform_util.h and simply use it in platform_util.c, threading.c and
* threading.h. However, this macro is not part of the Mbed TLS public API, so
* we keep it private by only defining it in this file
*/
#if !(defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)) || \
(defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
#define PLATFORM_UTIL_USE_GMTIME
#endif
#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \
( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \
_POSIX_THREAD_SAFE_FUNCTIONS >= 200112L ) ) */
struct tm *mbedtls_platform_gmtime_r(const mbedtls_time_t *tt,
struct tm *tm_buf)
{
#if defined(_WIN32) && !defined(PLATFORM_UTIL_USE_GMTIME)
#if defined(__STDC_LIB_EXT1__)
return (gmtime_s(tt, tm_buf) == 0) ? NULL : tm_buf;
#else
/* MSVC and mingw64 argument order and return value are inconsistent with the C11 standard */
return (gmtime_s(tm_buf, tt) == 0) ? tm_buf : NULL;
#endif
#elif !defined(PLATFORM_UTIL_USE_GMTIME)
return gmtime_r(tt, tm_buf);
#else
struct tm *lt;
#if defined(MBEDTLS_THREADING_C)
if (mbedtls_mutex_lock(&mbedtls_threading_gmtime_mutex) != 0) {
return NULL;
}
#endif /* MBEDTLS_THREADING_C */
lt = gmtime(tt);
if (lt != NULL) {
memcpy(tm_buf, lt, sizeof(struct tm));
}
#if defined(MBEDTLS_THREADING_C)
if (mbedtls_mutex_unlock(&mbedtls_threading_gmtime_mutex) != 0) {
return NULL;
}
#endif /* MBEDTLS_THREADING_C */
return (lt == NULL) ? NULL : tm_buf;
#endif /* _WIN32 && !EFIX64 && !EFI32 */
}
#endif /* MBEDTLS_HAVE_TIME_DATE && MBEDTLS_PLATFORM_GMTIME_R_ALT */
#if defined(MBEDTLS_TEST_HOOKS)
void (*mbedtls_test_hook_test_fail)(const char *, int, const char *);
#endif /* MBEDTLS_TEST_HOOKS */
#if defined(MBEDTLS_HAVE_TIME) && !defined(MBEDTLS_PLATFORM_MS_TIME_ALT)
#include <time.h>
#if !defined(_WIN32) && \
(defined(unix) || defined(__unix) || defined(__unix__) || \
(defined(__APPLE__) && defined(__MACH__)) || defined(__HAIKU__) || defined(__midipix__))
#include <unistd.h>
#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)
{
int ret;
struct timespec tv;
mbedtls_ms_time_t current_ms;
#if defined(__linux__) && defined(CLOCK_BOOTTIME) || defined(__midipix__)
ret = clock_gettime(CLOCK_BOOTTIME, &tv);
#else
ret = clock_gettime(CLOCK_MONOTONIC, &tv);
#endif
if (ret) {
return time(NULL) * 1000;
}
current_ms = tv.tv_sec;
return current_ms*1000 + tv.tv_nsec / 1000000;
}
#elif defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \
defined(__MINGW32__) || defined(_WIN64)
#include <windows.h>
mbedtls_ms_time_t mbedtls_ms_time(void)
{
FILETIME ct;
mbedtls_ms_time_t current_ms;
GetSystemTimeAsFileTime(&ct);
current_ms = ((mbedtls_ms_time_t) ct.dwLowDateTime +
((mbedtls_ms_time_t) (ct.dwHighDateTime) << 32LL))/10000;
return current_ms;
}
#else
#error "No mbedtls_ms_time available"
#endif
#endif /* MBEDTLS_HAVE_TIME && !MBEDTLS_PLATFORM_MS_TIME_ALT */

492
thirdparty/mbedtls/library/poly1305.c vendored Normal file
View File

@@ -0,0 +1,492 @@
/**
* \file poly1305.c
*
* \brief Poly1305 authentication algorithm.
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#if defined(MBEDTLS_POLY1305_C)
#include "mbedtls/poly1305.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#include <string.h>
#include "mbedtls/platform.h"
#if !defined(MBEDTLS_POLY1305_ALT)
#define POLY1305_BLOCK_SIZE_BYTES (16U)
/*
* Our implementation is tuned for 32-bit platforms with a 64-bit multiplier.
* However we provided an alternative for platforms without such a multiplier.
*/
#if defined(MBEDTLS_NO_64BIT_MULTIPLICATION)
static uint64_t mul64(uint32_t a, uint32_t b)
{
/* a = al + 2**16 ah, b = bl + 2**16 bh */
const uint16_t al = (uint16_t) a;
const uint16_t bl = (uint16_t) b;
const uint16_t ah = a >> 16;
const uint16_t bh = b >> 16;
/* ab = al*bl + 2**16 (ah*bl + bl*bh) + 2**32 ah*bh */
const uint32_t lo = (uint32_t) al * bl;
const uint64_t me = (uint64_t) ((uint32_t) ah * bl) + (uint32_t) al * bh;
const uint32_t hi = (uint32_t) ah * bh;
return lo + (me << 16) + ((uint64_t) hi << 32);
}
#else
static inline uint64_t mul64(uint32_t a, uint32_t b)
{
return (uint64_t) a * b;
}
#endif
/**
* \brief Process blocks with Poly1305.
*
* \param ctx The Poly1305 context.
* \param nblocks Number of blocks to process. Note that this
* function only processes full blocks.
* \param input Buffer containing the input block(s).
* \param needs_padding Set to 0 if the padding bit has already been
* applied to the input data before calling this
* function. Otherwise, set this parameter to 1.
*/
static void poly1305_process(mbedtls_poly1305_context *ctx,
size_t nblocks,
const unsigned char *input,
uint32_t needs_padding)
{
uint64_t d0, d1, d2, d3;
uint32_t acc0, acc1, acc2, acc3, acc4;
uint32_t r0, r1, r2, r3;
uint32_t rs1, rs2, rs3;
size_t offset = 0U;
size_t i;
r0 = ctx->r[0];
r1 = ctx->r[1];
r2 = ctx->r[2];
r3 = ctx->r[3];
rs1 = r1 + (r1 >> 2U);
rs2 = r2 + (r2 >> 2U);
rs3 = r3 + (r3 >> 2U);
acc0 = ctx->acc[0];
acc1 = ctx->acc[1];
acc2 = ctx->acc[2];
acc3 = ctx->acc[3];
acc4 = ctx->acc[4];
/* Process full blocks */
for (i = 0U; i < nblocks; i++) {
/* The input block is treated as a 128-bit little-endian integer */
d0 = MBEDTLS_GET_UINT32_LE(input, offset + 0);
d1 = MBEDTLS_GET_UINT32_LE(input, offset + 4);
d2 = MBEDTLS_GET_UINT32_LE(input, offset + 8);
d3 = MBEDTLS_GET_UINT32_LE(input, offset + 12);
/* Compute: acc += (padded) block as a 130-bit integer */
d0 += (uint64_t) acc0;
d1 += (uint64_t) acc1 + (d0 >> 32U);
d2 += (uint64_t) acc2 + (d1 >> 32U);
d3 += (uint64_t) acc3 + (d2 >> 32U);
acc0 = (uint32_t) d0;
acc1 = (uint32_t) d1;
acc2 = (uint32_t) d2;
acc3 = (uint32_t) d3;
acc4 += (uint32_t) (d3 >> 32U) + needs_padding;
/* Compute: acc *= r */
d0 = mul64(acc0, r0) +
mul64(acc1, rs3) +
mul64(acc2, rs2) +
mul64(acc3, rs1);
d1 = mul64(acc0, r1) +
mul64(acc1, r0) +
mul64(acc2, rs3) +
mul64(acc3, rs2) +
mul64(acc4, rs1);
d2 = mul64(acc0, r2) +
mul64(acc1, r1) +
mul64(acc2, r0) +
mul64(acc3, rs3) +
mul64(acc4, rs2);
d3 = mul64(acc0, r3) +
mul64(acc1, r2) +
mul64(acc2, r1) +
mul64(acc3, r0) +
mul64(acc4, rs3);
acc4 *= r0;
/* Compute: acc %= (2^130 - 5) (partial remainder) */
d1 += (d0 >> 32);
d2 += (d1 >> 32);
d3 += (d2 >> 32);
acc0 = (uint32_t) d0;
acc1 = (uint32_t) d1;
acc2 = (uint32_t) d2;
acc3 = (uint32_t) d3;
acc4 = (uint32_t) (d3 >> 32) + acc4;
d0 = (uint64_t) acc0 + (acc4 >> 2) + (acc4 & 0xFFFFFFFCU);
acc4 &= 3U;
acc0 = (uint32_t) d0;
d0 = (uint64_t) acc1 + (d0 >> 32U);
acc1 = (uint32_t) d0;
d0 = (uint64_t) acc2 + (d0 >> 32U);
acc2 = (uint32_t) d0;
d0 = (uint64_t) acc3 + (d0 >> 32U);
acc3 = (uint32_t) d0;
d0 = (uint64_t) acc4 + (d0 >> 32U);
acc4 = (uint32_t) d0;
offset += POLY1305_BLOCK_SIZE_BYTES;
}
ctx->acc[0] = acc0;
ctx->acc[1] = acc1;
ctx->acc[2] = acc2;
ctx->acc[3] = acc3;
ctx->acc[4] = acc4;
}
/**
* \brief Compute the Poly1305 MAC
*
* \param ctx The Poly1305 context.
* \param mac The buffer to where the MAC is written. Must be
* big enough to contain the 16-byte MAC.
*/
static void poly1305_compute_mac(const mbedtls_poly1305_context *ctx,
unsigned char mac[16])
{
uint64_t d;
uint32_t g0, g1, g2, g3, g4;
uint32_t acc0, acc1, acc2, acc3, acc4;
uint32_t mask;
uint32_t mask_inv;
acc0 = ctx->acc[0];
acc1 = ctx->acc[1];
acc2 = ctx->acc[2];
acc3 = ctx->acc[3];
acc4 = ctx->acc[4];
/* Before adding 's' we ensure that the accumulator is mod 2^130 - 5.
* We do this by calculating acc - (2^130 - 5), then checking if
* the 131st bit is set. If it is, then reduce: acc -= (2^130 - 5)
*/
/* Calculate acc + -(2^130 - 5) */
d = ((uint64_t) acc0 + 5U);
g0 = (uint32_t) d;
d = ((uint64_t) acc1 + (d >> 32));
g1 = (uint32_t) d;
d = ((uint64_t) acc2 + (d >> 32));
g2 = (uint32_t) d;
d = ((uint64_t) acc3 + (d >> 32));
g3 = (uint32_t) d;
g4 = acc4 + (uint32_t) (d >> 32U);
/* mask == 0xFFFFFFFF if 131st bit is set, otherwise mask == 0 */
mask = (uint32_t) 0U - (g4 >> 2U);
mask_inv = ~mask;
/* If 131st bit is set then acc=g, otherwise, acc is unmodified */
acc0 = (acc0 & mask_inv) | (g0 & mask);
acc1 = (acc1 & mask_inv) | (g1 & mask);
acc2 = (acc2 & mask_inv) | (g2 & mask);
acc3 = (acc3 & mask_inv) | (g3 & mask);
/* Add 's' */
d = (uint64_t) acc0 + ctx->s[0];
acc0 = (uint32_t) d;
d = (uint64_t) acc1 + ctx->s[1] + (d >> 32U);
acc1 = (uint32_t) d;
d = (uint64_t) acc2 + ctx->s[2] + (d >> 32U);
acc2 = (uint32_t) d;
acc3 += ctx->s[3] + (uint32_t) (d >> 32U);
/* Compute MAC (128 least significant bits of the accumulator) */
MBEDTLS_PUT_UINT32_LE(acc0, mac, 0);
MBEDTLS_PUT_UINT32_LE(acc1, mac, 4);
MBEDTLS_PUT_UINT32_LE(acc2, mac, 8);
MBEDTLS_PUT_UINT32_LE(acc3, mac, 12);
}
void mbedtls_poly1305_init(mbedtls_poly1305_context *ctx)
{
mbedtls_platform_zeroize(ctx, sizeof(mbedtls_poly1305_context));
}
void mbedtls_poly1305_free(mbedtls_poly1305_context *ctx)
{
if (ctx == NULL) {
return;
}
mbedtls_platform_zeroize(ctx, sizeof(mbedtls_poly1305_context));
}
int mbedtls_poly1305_starts(mbedtls_poly1305_context *ctx,
const unsigned char key[32])
{
/* r &= 0x0ffffffc0ffffffc0ffffffc0fffffff */
ctx->r[0] = MBEDTLS_GET_UINT32_LE(key, 0) & 0x0FFFFFFFU;
ctx->r[1] = MBEDTLS_GET_UINT32_LE(key, 4) & 0x0FFFFFFCU;
ctx->r[2] = MBEDTLS_GET_UINT32_LE(key, 8) & 0x0FFFFFFCU;
ctx->r[3] = MBEDTLS_GET_UINT32_LE(key, 12) & 0x0FFFFFFCU;
ctx->s[0] = MBEDTLS_GET_UINT32_LE(key, 16);
ctx->s[1] = MBEDTLS_GET_UINT32_LE(key, 20);
ctx->s[2] = MBEDTLS_GET_UINT32_LE(key, 24);
ctx->s[3] = MBEDTLS_GET_UINT32_LE(key, 28);
/* Initial accumulator state */
ctx->acc[0] = 0U;
ctx->acc[1] = 0U;
ctx->acc[2] = 0U;
ctx->acc[3] = 0U;
ctx->acc[4] = 0U;
/* Queue initially empty */
mbedtls_platform_zeroize(ctx->queue, sizeof(ctx->queue));
ctx->queue_len = 0U;
return 0;
}
int mbedtls_poly1305_update(mbedtls_poly1305_context *ctx,
const unsigned char *input,
size_t ilen)
{
size_t offset = 0U;
size_t remaining = ilen;
size_t queue_free_len;
size_t nblocks;
if ((remaining > 0U) && (ctx->queue_len > 0U)) {
queue_free_len = (POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len);
if (ilen < queue_free_len) {
/* Not enough data to complete the block.
* Store this data with the other leftovers.
*/
memcpy(&ctx->queue[ctx->queue_len],
input,
ilen);
ctx->queue_len += ilen;
remaining = 0U;
} else {
/* Enough data to produce a complete block */
memcpy(&ctx->queue[ctx->queue_len],
input,
queue_free_len);
ctx->queue_len = 0U;
poly1305_process(ctx, 1U, ctx->queue, 1U); /* add padding bit */
offset += queue_free_len;
remaining -= queue_free_len;
}
}
if (remaining >= POLY1305_BLOCK_SIZE_BYTES) {
nblocks = remaining / POLY1305_BLOCK_SIZE_BYTES;
poly1305_process(ctx, nblocks, &input[offset], 1U);
offset += nblocks * POLY1305_BLOCK_SIZE_BYTES;
remaining %= POLY1305_BLOCK_SIZE_BYTES;
}
if (remaining > 0U) {
/* Store partial block */
ctx->queue_len = remaining;
memcpy(ctx->queue, &input[offset], remaining);
}
return 0;
}
int mbedtls_poly1305_finish(mbedtls_poly1305_context *ctx,
unsigned char mac[16])
{
/* Process any leftover data */
if (ctx->queue_len > 0U) {
/* Add padding bit */
ctx->queue[ctx->queue_len] = 1U;
ctx->queue_len++;
/* Pad with zeroes */
memset(&ctx->queue[ctx->queue_len],
0,
POLY1305_BLOCK_SIZE_BYTES - ctx->queue_len);
poly1305_process(ctx, 1U, /* Process 1 block */
ctx->queue, 0U); /* Already padded above */
}
poly1305_compute_mac(ctx, mac);
return 0;
}
int mbedtls_poly1305_mac(const unsigned char key[32],
const unsigned char *input,
size_t ilen,
unsigned char mac[16])
{
mbedtls_poly1305_context ctx;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_poly1305_init(&ctx);
ret = mbedtls_poly1305_starts(&ctx, key);
if (ret != 0) {
goto cleanup;
}
ret = mbedtls_poly1305_update(&ctx, input, ilen);
if (ret != 0) {
goto cleanup;
}
ret = mbedtls_poly1305_finish(&ctx, mac);
cleanup:
mbedtls_poly1305_free(&ctx);
return ret;
}
#endif /* MBEDTLS_POLY1305_ALT */
#if defined(MBEDTLS_SELF_TEST)
static const unsigned char test_keys[2][32] =
{
{
0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33,
0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5, 0x06, 0xa8,
0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd,
0x4a, 0xbf, 0xf6, 0xaf, 0x41, 0x49, 0xf5, 0x1b
},
{
0x1c, 0x92, 0x40, 0xa5, 0xeb, 0x55, 0xd3, 0x8a,
0xf3, 0x33, 0x88, 0x86, 0x04, 0xf6, 0xb5, 0xf0,
0x47, 0x39, 0x17, 0xc1, 0x40, 0x2b, 0x80, 0x09,
0x9d, 0xca, 0x5c, 0xbc, 0x20, 0x70, 0x75, 0xc0
}
};
static const unsigned char test_data[2][127] =
{
{
0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x67, 0x72,
0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x46, 0x6f,
0x72, 0x75, 0x6d, 0x20, 0x52, 0x65, 0x73, 0x65,
0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6f,
0x75, 0x70
},
{
0x27, 0x54, 0x77, 0x61, 0x73, 0x20, 0x62, 0x72,
0x69, 0x6c, 0x6c, 0x69, 0x67, 0x2c, 0x20, 0x61,
0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
0x6c, 0x69, 0x74, 0x68, 0x79, 0x20, 0x74, 0x6f,
0x76, 0x65, 0x73, 0x0a, 0x44, 0x69, 0x64, 0x20,
0x67, 0x79, 0x72, 0x65, 0x20, 0x61, 0x6e, 0x64,
0x20, 0x67, 0x69, 0x6d, 0x62, 0x6c, 0x65, 0x20,
0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
0x61, 0x62, 0x65, 0x3a, 0x0a, 0x41, 0x6c, 0x6c,
0x20, 0x6d, 0x69, 0x6d, 0x73, 0x79, 0x20, 0x77,
0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
0x62, 0x6f, 0x72, 0x6f, 0x67, 0x6f, 0x76, 0x65,
0x73, 0x2c, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
0x68, 0x65, 0x20, 0x6d, 0x6f, 0x6d, 0x65, 0x20,
0x72, 0x61, 0x74, 0x68, 0x73, 0x20, 0x6f, 0x75,
0x74, 0x67, 0x72, 0x61, 0x62, 0x65, 0x2e
}
};
static const size_t test_data_len[2] =
{
34U,
127U
};
static const unsigned char test_mac[2][16] =
{
{
0xa8, 0x06, 0x1d, 0xc1, 0x30, 0x51, 0x36, 0xc6,
0xc2, 0x2b, 0x8b, 0xaf, 0x0c, 0x01, 0x27, 0xa9
},
{
0x45, 0x41, 0x66, 0x9a, 0x7e, 0xaa, 0xee, 0x61,
0xe7, 0x08, 0xdc, 0x7c, 0xbc, 0xc5, 0xeb, 0x62
}
};
/* Make sure no other definition is already present. */
#undef ASSERT
#define ASSERT(cond, args) \
do \
{ \
if (!(cond)) \
{ \
if (verbose != 0) \
mbedtls_printf args; \
\
return -1; \
} \
} \
while (0)
int mbedtls_poly1305_self_test(int verbose)
{
unsigned char mac[16];
unsigned i;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
for (i = 0U; i < 2U; i++) {
if (verbose != 0) {
mbedtls_printf(" Poly1305 test %u ", i);
}
ret = mbedtls_poly1305_mac(test_keys[i],
test_data[i],
test_data_len[i],
mac);
ASSERT(0 == ret, ("error code: %i\n", ret));
ASSERT(0 == memcmp(mac, test_mac[i], 16U), ("failed (mac)\n"));
if (verbose != 0) {
mbedtls_printf("passed\n");
}
}
if (verbose != 0) {
mbedtls_printf("\n");
}
return 0;
}
#endif /* MBEDTLS_SELF_TEST */
#endif /* MBEDTLS_POLY1305_C */

9459
thirdparty/mbedtls/library/psa_crypto.c vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,649 @@
/*
* PSA AEAD entry points
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#if defined(MBEDTLS_PSA_CRYPTO_C)
#include "psa_crypto_aead.h"
#include "psa_crypto_core.h"
#include "psa_crypto_cipher.h"
#include <string.h>
#include "mbedtls/platform.h"
#include "mbedtls/ccm.h"
#include "mbedtls/chachapoly.h"
#include "mbedtls/cipher.h"
#include "mbedtls/gcm.h"
#include "mbedtls/error.h"
static psa_status_t psa_aead_setup(
mbedtls_psa_aead_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_cipher_id_t cipher_id;
mbedtls_cipher_mode_t mode;
size_t key_bits = attributes->bits;
(void) key_buffer_size;
status = mbedtls_cipher_values_from_psa(alg, attributes->type,
&key_bits, &mode, &cipher_id);
if (status != PSA_SUCCESS) {
return status;
}
switch (PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0)) {
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0):
operation->alg = PSA_ALG_CCM;
/* 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->type) != 16) {
return PSA_ERROR_INVALID_ARGUMENT;
}
mbedtls_ccm_init(&operation->ctx.ccm);
status = mbedtls_to_psa_error(
mbedtls_ccm_setkey(&operation->ctx.ccm, cipher_id,
key_buffer, (unsigned int) key_bits));
if (status != PSA_SUCCESS) {
return status;
}
break;
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0):
operation->alg = PSA_ALG_GCM;
/* 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->type) != 16) {
return PSA_ERROR_INVALID_ARGUMENT;
}
mbedtls_gcm_init(&operation->ctx.gcm);
status = mbedtls_to_psa_error(
mbedtls_gcm_setkey(&operation->ctx.gcm, cipher_id,
key_buffer, (unsigned int) key_bits));
if (status != PSA_SUCCESS) {
return status;
}
break;
#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0):
operation->alg = PSA_ALG_CHACHA20_POLY1305;
/* We only support the default tag length. */
if (alg != PSA_ALG_CHACHA20_POLY1305) {
return PSA_ERROR_NOT_SUPPORTED;
}
mbedtls_chachapoly_init(&operation->ctx.chachapoly);
status = mbedtls_to_psa_error(
mbedtls_chachapoly_setkey(&operation->ctx.chachapoly,
key_buffer));
if (status != PSA_SUCCESS) {
return status;
}
break;
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
default:
(void) status;
(void) key_buffer;
return PSA_ERROR_NOT_SUPPORTED;
}
operation->key_type = psa_get_key_type(attributes);
operation->tag_length = PSA_ALG_AEAD_GET_TAG_LENGTH(alg);
return PSA_SUCCESS;
}
psa_status_t mbedtls_psa_aead_encrypt(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *nonce, size_t nonce_length,
const uint8_t *additional_data, size_t additional_data_length,
const uint8_t *plaintext, size_t plaintext_length,
uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_psa_aead_operation_t operation = MBEDTLS_PSA_AEAD_OPERATION_INIT;
uint8_t *tag;
status = psa_aead_setup(&operation, attributes, key_buffer,
key_buffer_size, alg);
if (status != PSA_SUCCESS) {
goto exit;
}
/* For all currently supported modes, the tag is at the end of the
* ciphertext. */
if (ciphertext_size < (plaintext_length + operation.tag_length)) {
status = PSA_ERROR_BUFFER_TOO_SMALL;
goto exit;
}
tag = ciphertext + plaintext_length;
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
if (operation.alg == PSA_ALG_CCM) {
status = mbedtls_to_psa_error(
mbedtls_ccm_encrypt_and_tag(&operation.ctx.ccm,
plaintext_length,
nonce, nonce_length,
additional_data,
additional_data_length,
plaintext, ciphertext,
tag, operation.tag_length));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
if (operation.alg == PSA_ALG_GCM) {
status = mbedtls_to_psa_error(
mbedtls_gcm_crypt_and_tag(&operation.ctx.gcm,
MBEDTLS_GCM_ENCRYPT,
plaintext_length,
nonce, nonce_length,
additional_data, additional_data_length,
plaintext, ciphertext,
operation.tag_length, tag));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
if (operation.alg == PSA_ALG_CHACHA20_POLY1305) {
if (operation.tag_length != 16) {
status = PSA_ERROR_NOT_SUPPORTED;
goto exit;
}
status = mbedtls_to_psa_error(
mbedtls_chachapoly_encrypt_and_tag(&operation.ctx.chachapoly,
plaintext_length,
nonce,
additional_data,
additional_data_length,
plaintext,
ciphertext,
tag));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
{
(void) tag;
(void) nonce;
(void) nonce_length;
(void) additional_data;
(void) additional_data_length;
(void) plaintext;
return PSA_ERROR_NOT_SUPPORTED;
}
if (status == PSA_SUCCESS) {
*ciphertext_length = plaintext_length + operation.tag_length;
}
exit:
mbedtls_psa_aead_abort(&operation);
return status;
}
/* Locate the tag in a ciphertext buffer containing the encrypted data
* followed by the tag. Return the length of the part preceding the tag in
* *plaintext_length. This is the size of the plaintext in modes where
* the encrypted data has the same size as the plaintext, such as
* CCM and GCM. */
static psa_status_t psa_aead_unpadded_locate_tag(size_t tag_length,
const uint8_t *ciphertext,
size_t ciphertext_length,
size_t plaintext_size,
const uint8_t **p_tag)
{
size_t payload_length;
if (tag_length > ciphertext_length) {
return PSA_ERROR_INVALID_ARGUMENT;
}
payload_length = ciphertext_length - tag_length;
if (payload_length > plaintext_size) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
*p_tag = ciphertext + payload_length;
return PSA_SUCCESS;
}
psa_status_t mbedtls_psa_aead_decrypt(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *nonce, size_t nonce_length,
const uint8_t *additional_data, size_t additional_data_length,
const uint8_t *ciphertext, size_t ciphertext_length,
uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_psa_aead_operation_t operation = MBEDTLS_PSA_AEAD_OPERATION_INIT;
const uint8_t *tag = NULL;
status = psa_aead_setup(&operation, attributes, key_buffer,
key_buffer_size, alg);
if (status != PSA_SUCCESS) {
goto exit;
}
status = psa_aead_unpadded_locate_tag(operation.tag_length,
ciphertext, ciphertext_length,
plaintext_size, &tag);
if (status != PSA_SUCCESS) {
goto exit;
}
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
if (operation.alg == PSA_ALG_CCM) {
status = mbedtls_to_psa_error(
mbedtls_ccm_auth_decrypt(&operation.ctx.ccm,
ciphertext_length - operation.tag_length,
nonce, nonce_length,
additional_data,
additional_data_length,
ciphertext, plaintext,
tag, operation.tag_length));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
if (operation.alg == PSA_ALG_GCM) {
status = mbedtls_to_psa_error(
mbedtls_gcm_auth_decrypt(&operation.ctx.gcm,
ciphertext_length - operation.tag_length,
nonce, nonce_length,
additional_data,
additional_data_length,
tag, operation.tag_length,
ciphertext, plaintext));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
if (operation.alg == PSA_ALG_CHACHA20_POLY1305) {
if (operation.tag_length != 16) {
status = PSA_ERROR_NOT_SUPPORTED;
goto exit;
}
status = mbedtls_to_psa_error(
mbedtls_chachapoly_auth_decrypt(&operation.ctx.chachapoly,
ciphertext_length - operation.tag_length,
nonce,
additional_data,
additional_data_length,
tag,
ciphertext,
plaintext));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
{
(void) nonce;
(void) nonce_length;
(void) additional_data;
(void) additional_data_length;
(void) plaintext;
return PSA_ERROR_NOT_SUPPORTED;
}
if (status == PSA_SUCCESS) {
*plaintext_length = ciphertext_length - operation.tag_length;
}
exit:
mbedtls_psa_aead_abort(&operation);
if (status == PSA_SUCCESS) {
*plaintext_length = ciphertext_length - operation.tag_length;
}
return status;
}
/* Set the key and algorithm for a multipart authenticated encryption
* operation. */
psa_status_t mbedtls_psa_aead_encrypt_setup(
mbedtls_psa_aead_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
status = psa_aead_setup(operation, attributes, key_buffer,
key_buffer_size, alg);
if (status == PSA_SUCCESS) {
operation->is_encrypt = 1;
}
return status;
}
/* Set the key and algorithm for a multipart authenticated decryption
* operation. */
psa_status_t mbedtls_psa_aead_decrypt_setup(
mbedtls_psa_aead_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
status = psa_aead_setup(operation, attributes, key_buffer,
key_buffer_size, alg);
if (status == PSA_SUCCESS) {
operation->is_encrypt = 0;
}
return status;
}
/* Set a nonce for the multipart AEAD operation*/
psa_status_t mbedtls_psa_aead_set_nonce(
mbedtls_psa_aead_operation_t *operation,
const uint8_t *nonce,
size_t nonce_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
if (operation->alg == PSA_ALG_GCM) {
status = mbedtls_to_psa_error(
mbedtls_gcm_starts(&operation->ctx.gcm,
operation->is_encrypt ?
MBEDTLS_GCM_ENCRYPT : MBEDTLS_GCM_DECRYPT,
nonce,
nonce_length));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
if (operation->alg == PSA_ALG_CCM) {
status = mbedtls_to_psa_error(
mbedtls_ccm_starts(&operation->ctx.ccm,
operation->is_encrypt ?
MBEDTLS_CCM_ENCRYPT : MBEDTLS_CCM_DECRYPT,
nonce,
nonce_length));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
if (operation->alg == PSA_ALG_CHACHA20_POLY1305) {
/* Note - ChaChaPoly allows an 8 byte nonce, but we would have to
* allocate a buffer in the operation, copy the nonce to it and pad
* it, so for now check the nonce is 12 bytes, as
* mbedtls_chachapoly_starts() assumes it can read 12 bytes from the
* passed in buffer. */
if (nonce_length != 12) {
return PSA_ERROR_INVALID_ARGUMENT;
}
status = mbedtls_to_psa_error(
mbedtls_chachapoly_starts(&operation->ctx.chachapoly,
nonce,
operation->is_encrypt ?
MBEDTLS_CHACHAPOLY_ENCRYPT :
MBEDTLS_CHACHAPOLY_DECRYPT));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
{
(void) operation;
(void) nonce;
(void) nonce_length;
return PSA_ERROR_NOT_SUPPORTED;
}
return status;
}
/* Declare the lengths of the message and additional data for AEAD. */
psa_status_t mbedtls_psa_aead_set_lengths(
mbedtls_psa_aead_operation_t *operation,
size_t ad_length,
size_t plaintext_length)
{
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
if (operation->alg == PSA_ALG_CCM) {
return mbedtls_to_psa_error(
mbedtls_ccm_set_lengths(&operation->ctx.ccm,
ad_length,
plaintext_length,
operation->tag_length));
}
#else /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
(void) operation;
(void) ad_length;
(void) plaintext_length;
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
return PSA_SUCCESS;
}
/* Pass additional data to an active multipart AEAD operation. */
psa_status_t mbedtls_psa_aead_update_ad(
mbedtls_psa_aead_operation_t *operation,
const uint8_t *input,
size_t input_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
if (operation->alg == PSA_ALG_GCM) {
status = mbedtls_to_psa_error(
mbedtls_gcm_update_ad(&operation->ctx.gcm, input, input_length));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
if (operation->alg == PSA_ALG_CCM) {
status = mbedtls_to_psa_error(
mbedtls_ccm_update_ad(&operation->ctx.ccm, input, input_length));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
if (operation->alg == PSA_ALG_CHACHA20_POLY1305) {
status = mbedtls_to_psa_error(
mbedtls_chachapoly_update_aad(&operation->ctx.chachapoly,
input,
input_length));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
{
(void) operation;
(void) input;
(void) input_length;
return PSA_ERROR_NOT_SUPPORTED;
}
return status;
}
/* Encrypt or decrypt a message fragment in an active multipart AEAD
* operation.*/
psa_status_t mbedtls_psa_aead_update(
mbedtls_psa_aead_operation_t *operation,
const uint8_t *input,
size_t input_length,
uint8_t *output,
size_t output_size,
size_t *output_length)
{
size_t update_output_length;
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
update_output_length = input_length;
#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
if (operation->alg == PSA_ALG_GCM) {
status = mbedtls_to_psa_error(
mbedtls_gcm_update(&operation->ctx.gcm,
input, input_length,
output, output_size,
&update_output_length));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
if (operation->alg == PSA_ALG_CCM) {
if (output_size < input_length) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
status = mbedtls_to_psa_error(
mbedtls_ccm_update(&operation->ctx.ccm,
input, input_length,
output, output_size,
&update_output_length));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
if (operation->alg == PSA_ALG_CHACHA20_POLY1305) {
if (output_size < input_length) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
status = mbedtls_to_psa_error(
mbedtls_chachapoly_update(&operation->ctx.chachapoly,
input_length,
input,
output));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
{
(void) operation;
(void) input;
(void) output;
(void) output_size;
return PSA_ERROR_NOT_SUPPORTED;
}
if (status == PSA_SUCCESS) {
*output_length = update_output_length;
}
return status;
}
/* Finish encrypting a message in a multipart AEAD operation. */
psa_status_t mbedtls_psa_aead_finish(
mbedtls_psa_aead_operation_t *operation,
uint8_t *ciphertext,
size_t ciphertext_size,
size_t *ciphertext_length,
uint8_t *tag,
size_t tag_size,
size_t *tag_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
size_t finish_output_size = 0;
if (tag_size < operation->tag_length) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
if (operation->alg == PSA_ALG_GCM) {
status = mbedtls_to_psa_error(
mbedtls_gcm_finish(&operation->ctx.gcm,
ciphertext, ciphertext_size, ciphertext_length,
tag, operation->tag_length));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
if (operation->alg == PSA_ALG_CCM) {
/* tag must be big enough to store a tag of size passed into set
* lengths. */
if (tag_size < operation->tag_length) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
status = mbedtls_to_psa_error(
mbedtls_ccm_finish(&operation->ctx.ccm,
tag, operation->tag_length));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
if (operation->alg == PSA_ALG_CHACHA20_POLY1305) {
/* Belt and braces. Although the above tag_size check should have
* already done this, if we later start supporting smaller tag sizes
* for chachapoly, then passing a tag buffer smaller than 16 into here
* could cause a buffer overflow, so better safe than sorry. */
if (tag_size < 16) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
status = mbedtls_to_psa_error(
mbedtls_chachapoly_finish(&operation->ctx.chachapoly,
tag));
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
{
(void) ciphertext;
(void) ciphertext_size;
(void) ciphertext_length;
(void) tag;
(void) tag_size;
(void) tag_length;
return PSA_ERROR_NOT_SUPPORTED;
}
if (status == PSA_SUCCESS) {
/* This will be zero for all supported algorithms currently, but left
* here for future support. */
*ciphertext_length = finish_output_size;
*tag_length = operation->tag_length;
}
return status;
}
/* Abort an AEAD operation */
psa_status_t mbedtls_psa_aead_abort(
mbedtls_psa_aead_operation_t *operation)
{
switch (operation->alg) {
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
case PSA_ALG_CCM:
mbedtls_ccm_free(&operation->ctx.ccm);
break;
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
case PSA_ALG_GCM:
mbedtls_gcm_free(&operation->ctx.gcm);
break;
#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
case PSA_ALG_CHACHA20_POLY1305:
mbedtls_chachapoly_free(&operation->ctx.chachapoly);
break;
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
}
operation->is_encrypt = 0;
return PSA_SUCCESS;
}
#endif /* MBEDTLS_PSA_CRYPTO_C */

View File

@@ -0,0 +1,499 @@
/*
* PSA AEAD driver entry points
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef PSA_CRYPTO_AEAD_H
#define PSA_CRYPTO_AEAD_H
#include <psa/crypto.h>
/**
* \brief Process an authenticated encryption operation.
*
* \note The signature of this function is that of a PSA driver
* aead_encrypt entry point. This function behaves as an aead_encrypt
* entry point as defined in the PSA driver interface specification for
* transparent drivers.
*
* \param[in] attributes The attributes of the key to use for the
* operation.
* \param[in] key_buffer The buffer containing the key context.
* \param key_buffer_size Size of the \p key_buffer buffer in bytes.
* \param alg The AEAD algorithm to compute.
* \param[in] nonce Nonce or IV to use.
* \param nonce_length Size of the nonce buffer in bytes. This must
* be appropriate for the selected algorithm.
* The default nonce size is
* PSA_AEAD_NONCE_LENGTH(key_type, alg) where
* key_type is the type of key.
* \param[in] additional_data Additional data that will be authenticated
* but not encrypted.
* \param additional_data_length Size of additional_data in bytes.
* \param[in] plaintext Data that will be authenticated and encrypted.
* \param plaintext_length Size of plaintext in bytes.
* \param[out] ciphertext Output buffer for the authenticated and
* encrypted data. The additional data is not
* part of this output. For algorithms where the
* encrypted data and the authentication tag are
* defined as separate outputs, the
* authentication tag is appended to the
* encrypted data.
* \param ciphertext_size Size of the ciphertext buffer in bytes. This
* must be appropriate for the selected algorithm
* and key:
* - A sufficient output size is
* PSA_AEAD_ENCRYPT_OUTPUT_SIZE(key_type, alg,
* plaintext_length) where key_type is the type
* of key.
* - PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(
* plaintext_length) evaluates to the maximum
* ciphertext size of any supported AEAD
* encryption.
* \param[out] ciphertext_length On success, the size of the output in the
* ciphertext buffer.
*
* \retval #PSA_SUCCESS Success.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \p alg is not supported.
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* ciphertext_size is too small.
* \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
*/
psa_status_t mbedtls_psa_aead_encrypt(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *nonce, size_t nonce_length,
const uint8_t *additional_data, size_t additional_data_length,
const uint8_t *plaintext, size_t plaintext_length,
uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length);
/**
* \brief Process an authenticated decryption operation.
*
* \note The signature of this function is that of a PSA driver
* aead_decrypt entry point. This function behaves as an aead_decrypt
* entry point as defined in the PSA driver interface specification for
* transparent drivers.
*
* \param[in] attributes The attributes of the key to use for the
* operation.
* \param[in] key_buffer The buffer containing the key context.
* \param key_buffer_size Size of the \p key_buffer buffer in bytes.
* \param alg The AEAD algorithm to compute.
* \param[in] nonce Nonce or IV to use.
* \param nonce_length Size of the nonce buffer in bytes. This must
* be appropriate for the selected algorithm.
* The default nonce size is
* PSA_AEAD_NONCE_LENGTH(key_type, alg) where
* key_type is the type of key.
* \param[in] additional_data Additional data that has been authenticated
* but not encrypted.
* \param additional_data_length Size of additional_data in bytes.
* \param[in] ciphertext Data that has been authenticated and
* encrypted. For algorithms where the encrypted
* data and the authentication tag are defined
* as separate inputs, the buffer contains
* encrypted data followed by the authentication
* tag.
* \param ciphertext_length Size of ciphertext in bytes.
* \param[out] plaintext Output buffer for the decrypted data.
* \param plaintext_size Size of the plaintext buffer in bytes. This
* must be appropriate for the selected algorithm
* and key:
* - A sufficient output size is
* PSA_AEAD_DECRYPT_OUTPUT_SIZE(key_type, alg,
* ciphertext_length) where key_type is the
* type of key.
* - PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(
* ciphertext_length) evaluates to the maximum
* plaintext size of any supported AEAD
* decryption.
* \param[out] plaintext_length On success, the size of the output in the
* plaintext buffer.
*
* \retval #PSA_SUCCESS Success.
* \retval #PSA_ERROR_INVALID_SIGNATURE
* The cipher is not authentic.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \p alg is not supported.
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* plaintext_size is too small.
* \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
*/
psa_status_t mbedtls_psa_aead_decrypt(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *nonce, size_t nonce_length,
const uint8_t *additional_data, size_t additional_data_length,
const uint8_t *ciphertext, size_t ciphertext_length,
uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length);
/** Set the key for a multipart authenticated encryption operation.
*
* \note The signature of this function is that of a PSA driver
* aead_encrypt_setup entry point. This function behaves as an
* aead_encrypt_setup entry point as defined in the PSA driver interface
* specification for transparent drivers.
*
* If an error occurs at any step after a call to
* mbedtls_psa_aead_encrypt_setup(), the operation is reset by the PSA core by a
* call to mbedtls_psa_aead_abort(). The PSA core may call
* mbedtls_psa_aead_abort() at any time after the operation has been
* initialized, and is required to when the operation is no longer needed.
*
* \param[in,out] operation The operation object to set up. It must have
* been initialized as per the documentation for
* #mbedtls_psa_aead_operation_t and not yet in
* use.
* \param[in] attributes The attributes of the key to use for the
* operation.
* \param[in] key_buffer The buffer containing the key context.
* \param key_buffer_size Size of the \p key_buffer buffer in bytes.
It must be consistent with the size in bits
recorded in \p attributes.
* \param alg The AEAD algorithm to compute
* (\c PSA_ALG_XXX value such that
* #PSA_ALG_IS_AEAD(\p alg) is true).
*
* \retval #PSA_SUCCESS
* Success.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* An invalid block length was supplied.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \p alg is not supported.
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* Failed to allocate memory for key material
*/
psa_status_t mbedtls_psa_aead_encrypt_setup(
mbedtls_psa_aead_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg);
/** Set the key for a multipart authenticated decryption operation.
*
* \note The signature of this function is that of a PSA driver
* aead_decrypt_setup entry point. This function behaves as an
* aead_decrypt_setup entry point as defined in the PSA driver interface
* specification for transparent drivers.
*
* If an error occurs at any step after a call to
* mbedtls_psa_aead_decrypt_setup(), the PSA core resets the operation by a
* call to mbedtls_psa_aead_abort(). The PSA core may call
* mbedtls_psa_aead_abort() at any time after the operation has been
* initialized, and is required to when the operation is no longer needed.
*
* \param[in,out] operation The operation object to set up. It must have
* been initialized as per the documentation for
* #mbedtls_psa_aead_operation_t and not yet in
* use.
* \param[in] attributes The attributes of the key to use for the
* operation.
* \param[in] key_buffer The buffer containing the key context.
* \param key_buffer_size Size of the \p key_buffer buffer in bytes.
It must be consistent with the size in bits
recorded in \p attributes.
* \param alg The AEAD algorithm to compute
* (\c PSA_ALG_XXX value such that
* #PSA_ALG_IS_AEAD(\p alg) is true).
*
* \retval #PSA_SUCCESS
* Success.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* An invalid block length was supplied.
* \retval #PSA_ERROR_NOT_SUPPORTED
* \p alg is not supported.
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* Failed to allocate memory for key material
*/
psa_status_t mbedtls_psa_aead_decrypt_setup(
mbedtls_psa_aead_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg);
/** Set the nonce for an authenticated encryption or decryption operation.
*
* \note The signature of this function is that of a PSA driver aead_set_nonce
* entry point. This function behaves as an aead_set_nonce entry point as
* defined in the PSA driver interface specification for transparent
* drivers.
*
* This function sets the nonce for the authenticated
* encryption or decryption operation.
*
* The PSA core calls mbedtls_psa_aead_encrypt_setup() or
* mbedtls_psa_aead_decrypt_setup() before calling this function.
*
* If this function returns an error status, the PSA core will call
* mbedtls_psa_aead_abort().
*
* \param[in,out] operation Active AEAD operation.
* \param[in] nonce Buffer containing the nonce to use.
* \param nonce_length Size of the nonce in bytes.
*
* \retval #PSA_SUCCESS
* Success.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* The size of \p nonce is not acceptable for the chosen algorithm.
* \retval #PSA_ERROR_NOT_SUPPORTED
* Algorithm previously set is not supported in this configuration of
* the library.
*/
psa_status_t mbedtls_psa_aead_set_nonce(
mbedtls_psa_aead_operation_t *operation,
const uint8_t *nonce,
size_t nonce_length);
/** Declare the lengths of the message and additional data for AEAD.
*
* \note The signature of this function is that of a PSA driver aead_set_lengths
* entry point. This function behaves as an aead_set_lengths entry point
* as defined in the PSA driver interface specification for transparent
* drivers.
*
* The PSA core calls this function before calling mbedtls_psa_aead_update_ad()
* or mbedtls_psa_aead_update() if the algorithm for the operation requires it.
* If the algorithm does not require it, calling this function is optional, but
* if this function is called then the implementation must enforce the lengths.
*
* The PSA core may call this function before or after setting the nonce with
* mbedtls_psa_aead_set_nonce().
*
* - For #PSA_ALG_CCM, calling this function is required.
* - For the other AEAD algorithms defined in this specification, calling
* this function is not required.
*
* If this function returns an error status, the PSA core calls
* mbedtls_psa_aead_abort().
*
* \param[in,out] operation Active AEAD operation.
* \param ad_length Size of the non-encrypted additional
* authenticated data in bytes.
* \param plaintext_length Size of the plaintext to encrypt in bytes.
*
* \retval #PSA_SUCCESS
* Success.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* At least one of the lengths is not acceptable for the chosen
* algorithm.
* \retval #PSA_ERROR_NOT_SUPPORTED
* Algorithm previously set is not supported in this configuration of
* the library.
*/
psa_status_t mbedtls_psa_aead_set_lengths(
mbedtls_psa_aead_operation_t *operation,
size_t ad_length,
size_t plaintext_length);
/** Pass additional data to an active AEAD operation.
*
* \note The signature of this function is that of a PSA driver
* aead_update_ad entry point. This function behaves as an aead_update_ad
* entry point as defined in the PSA driver interface specification for
* transparent drivers.
*
* Additional data is authenticated, but not encrypted.
*
* The PSA core can call this function multiple times to pass successive
* fragments of the additional data. It will not call this function after
* passing data to encrypt or decrypt with mbedtls_psa_aead_update().
*
* Before calling this function, the PSA core will:
* 1. Call either mbedtls_psa_aead_encrypt_setup() or
* mbedtls_psa_aead_decrypt_setup().
* 2. Set the nonce with mbedtls_psa_aead_set_nonce().
*
* If this function returns an error status, the PSA core will call
* mbedtls_psa_aead_abort().
*
* \param[in,out] operation Active AEAD operation.
* \param[in] input Buffer containing the fragment of
* additional data.
* \param input_length Size of the \p input buffer in bytes.
*
* \retval #PSA_SUCCESS
* Success.
* \retval #PSA_ERROR_NOT_SUPPORTED
* Algorithm previously set is not supported in this configuration of
* the library.
*/
psa_status_t mbedtls_psa_aead_update_ad(
mbedtls_psa_aead_operation_t *operation,
const uint8_t *input,
size_t input_length);
/** Encrypt or decrypt a message fragment in an active AEAD operation.
*
* \note The signature of this function is that of a PSA driver
* aead_update entry point. This function behaves as an aead_update entry
* point as defined in the PSA driver interface specification for
* transparent drivers.
*
* Before calling this function, the PSA core will:
* 1. Call either mbedtls_psa_aead_encrypt_setup() or
* mbedtls_psa_aead_decrypt_setup(). The choice of setup function
* determines whether this function encrypts or decrypts its input.
* 2. Set the nonce with mbedtls_psa_aead_set_nonce().
* 3. Call mbedtls_psa_aead_update_ad() to pass all the additional data.
*
* If this function returns an error status, the PSA core will call
* mbedtls_psa_aead_abort().
*
* This function does not require the input to be aligned to any
* particular block boundary. If the implementation can only process
* a whole block at a time, it must consume all the input provided, but
* it may delay the end of the corresponding output until a subsequent
* call to mbedtls_psa_aead_update(), mbedtls_psa_aead_finish() provides
* sufficient input. The amount of data that can be delayed in this way is
* bounded by #PSA_AEAD_UPDATE_OUTPUT_SIZE.
*
* \param[in,out] operation Active AEAD operation.
* \param[in] input Buffer containing the message fragment to
* encrypt or decrypt.
* \param input_length Size of the \p input buffer in bytes.
* \param[out] output Buffer where the output is to be written.
* \param output_size Size of the \p output buffer in bytes.
* This must be appropriate for the selected
* algorithm and key:
* - A sufficient output size is
* #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c key_type,
* \c alg, \p input_length) where
* \c key_type is the type of key and \c alg is
* the algorithm that were used to set up the
* operation.
* - #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\p
* input_length) evaluates to the maximum
* output size of any supported AEAD
* algorithm.
* \param[out] output_length On success, the number of bytes
* that make up the returned output.
*
* \retval #PSA_SUCCESS
* Success.
*
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* The size of the \p output buffer is too small.
* #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c key_type, \c alg, \p input_length) or
* #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\p input_length) can be used to
* determine the required buffer size.
*/
psa_status_t mbedtls_psa_aead_update(
mbedtls_psa_aead_operation_t *operation,
const uint8_t *input,
size_t input_length,
uint8_t *output,
size_t output_size,
size_t *output_length);
/** Finish encrypting a message in an AEAD operation.
*
* \note The signature of this function is that of a PSA driver
* aead_finish entry point. This function behaves as an aead_finish entry
* point as defined in the PSA driver interface specification for
* transparent drivers.
*
* The operation must have been set up by the PSA core with
* mbedtls_psa_aead_encrypt_setup().
*
* This function finishes the authentication of the additional data
* formed by concatenating the inputs passed to preceding calls to
* mbedtls_psa_aead_update_ad() with the plaintext formed by concatenating the
* inputs passed to preceding calls to mbedtls_psa_aead_update().
*
* This function has two output buffers:
* - \p ciphertext contains trailing ciphertext that was buffered from
* preceding calls to mbedtls_psa_aead_update().
* - \p tag contains the authentication tag.
*
* Whether or not this function returns successfully, the PSA core subsequently
* calls mbedtls_psa_aead_abort() to deactivate the operation.
*
* \param[in,out] operation Active AEAD operation.
* \param[out] ciphertext Buffer where the last part of the ciphertext
* is to be written.
* \param ciphertext_size Size of the \p ciphertext buffer in bytes.
* This must be appropriate for the selected
* algorithm and key:
* - A sufficient output size is
* #PSA_AEAD_FINISH_OUTPUT_SIZE(\c key_type,
* \c alg) where \c key_type is the type of key
* and \c alg is the algorithm that were used to
* set up the operation.
* - #PSA_AEAD_FINISH_OUTPUT_MAX_SIZE evaluates to
* the maximum output size of any supported AEAD
* algorithm.
* \param[out] ciphertext_length On success, the number of bytes of
* returned ciphertext.
* \param[out] tag Buffer where the authentication tag is
* to be written.
* \param tag_size Size of the \p tag buffer in bytes.
* This must be appropriate for the selected
* algorithm and key:
* - The exact tag size is #PSA_AEAD_TAG_LENGTH(\c
* key_type, \c key_bits, \c alg) where
* \c key_type and \c key_bits are the type and
* bit-size of the key, and \c alg are the
* algorithm that were used in the call to
* mbedtls_psa_aead_encrypt_setup().
* - #PSA_AEAD_TAG_MAX_SIZE evaluates to the
* maximum tag size of any supported AEAD
* algorithm.
* \param[out] tag_length On success, the number of bytes
* that make up the returned tag.
*
* \retval #PSA_SUCCESS
* Success.
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* The size of the \p tag buffer is too small.
* #PSA_AEAD_TAG_LENGTH(\c key_type, key_bits, \c alg) or
* #PSA_AEAD_TAG_MAX_SIZE can be used to determine the required \p tag
* buffer size.
*/
psa_status_t mbedtls_psa_aead_finish(
mbedtls_psa_aead_operation_t *operation,
uint8_t *ciphertext,
size_t ciphertext_size,
size_t *ciphertext_length,
uint8_t *tag,
size_t tag_size,
size_t *tag_length);
/** Abort an AEAD operation.
*
* \note The signature of this function is that of a PSA driver
* aead_abort entry point. This function behaves as an aead_abort entry
* point as defined in the PSA driver interface specification for
* transparent drivers.
*
* Aborting an operation frees all associated resources except for the
* \p operation structure itself. Once aborted, the operation object
* can be reused for another operation by the PSA core by it calling
* mbedtls_psa_aead_encrypt_setup() or mbedtls_psa_aead_decrypt_setup() again.
*
* The PSA core may call this function any time after the operation object has
* been initialized as described in #mbedtls_psa_aead_operation_t.
*
* In particular, calling mbedtls_psa_aead_abort() after the operation has been
* terminated by a call to mbedtls_psa_aead_abort() or
* mbedtls_psa_aead_finish() is safe and has no effect.
*
* \param[in,out] operation Initialized AEAD operation.
*
* \retval #PSA_SUCCESS
* Success.
*/
psa_status_t mbedtls_psa_aead_abort(
mbedtls_psa_aead_operation_t *operation);
#endif /* PSA_CRYPTO_AEAD_H */

View File

@@ -0,0 +1,721 @@
/*
* PSA cipher driver entry points
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#if defined(MBEDTLS_PSA_CRYPTO_C)
#include "psa_crypto_cipher.h"
#include "psa_crypto_core.h"
#include "psa_crypto_random_impl.h"
#include "mbedtls/cipher.h"
#include "mbedtls/error.h"
#include <string.h>
/* mbedtls_cipher_values_from_psa() below only checks if the proper build symbols
* are enabled, but it does not provide any compatibility check between them
* (i.e. if the specified key works with the specified algorithm). This helper
* function is meant to provide this support.
* mbedtls_cipher_info_from_psa() might be used for the same purpose, but it
* requires CIPHER_C to be enabled.
*/
static psa_status_t mbedtls_cipher_validate_values(
psa_algorithm_t alg,
psa_key_type_t key_type)
{
/* Reduce code size - hinting to the compiler about what it can assume allows the compiler to
eliminate bits of the logic below. */
#if !defined(PSA_WANT_KEY_TYPE_AES)
MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_AES);
#endif
#if !defined(PSA_WANT_KEY_TYPE_ARIA)
MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_ARIA);
#endif
#if !defined(PSA_WANT_KEY_TYPE_CAMELLIA)
MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_CAMELLIA);
#endif
#if !defined(PSA_WANT_KEY_TYPE_CHACHA20)
MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_CHACHA20);
#endif
#if !defined(PSA_WANT_KEY_TYPE_DES)
MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_DES);
#endif
#if !defined(PSA_WANT_ALG_CCM)
MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0));
#endif
#if !defined(PSA_WANT_ALG_GCM)
MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0));
#endif
#if !defined(PSA_WANT_ALG_STREAM_CIPHER)
MBEDTLS_ASSUME(alg != PSA_ALG_STREAM_CIPHER);
#endif
#if !defined(PSA_WANT_ALG_CHACHA20_POLY1305)
MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0));
#endif
#if !defined(PSA_WANT_ALG_CCM_STAR_NO_TAG)
MBEDTLS_ASSUME(alg != PSA_ALG_CCM_STAR_NO_TAG);
#endif
#if !defined(PSA_WANT_ALG_CTR)
MBEDTLS_ASSUME(alg != PSA_ALG_CTR);
#endif
#if !defined(PSA_WANT_ALG_CFB)
MBEDTLS_ASSUME(alg != PSA_ALG_CFB);
#endif
#if !defined(PSA_WANT_ALG_OFB)
MBEDTLS_ASSUME(alg != PSA_ALG_OFB);
#endif
#if !defined(PSA_WANT_ALG_ECB_NO_PADDING)
MBEDTLS_ASSUME(alg != PSA_ALG_ECB_NO_PADDING);
#endif
#if !defined(PSA_WANT_ALG_CBC_NO_PADDING)
MBEDTLS_ASSUME(alg != PSA_ALG_CBC_NO_PADDING);
#endif
#if !defined(PSA_WANT_ALG_CBC_PKCS7)
MBEDTLS_ASSUME(alg != PSA_ALG_CBC_PKCS7);
#endif
#if !defined(PSA_WANT_ALG_CMAC)
MBEDTLS_ASSUME(alg != PSA_ALG_CMAC);
#endif
if (alg == PSA_ALG_STREAM_CIPHER ||
alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0)) {
if (key_type == PSA_KEY_TYPE_CHACHA20) {
return PSA_SUCCESS;
}
}
if (alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0) ||
alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0) ||
alg == PSA_ALG_CCM_STAR_NO_TAG) {
if (key_type == PSA_KEY_TYPE_AES ||
key_type == PSA_KEY_TYPE_ARIA ||
key_type == PSA_KEY_TYPE_CAMELLIA) {
return PSA_SUCCESS;
}
}
if (alg == PSA_ALG_CTR ||
alg == PSA_ALG_CFB ||
alg == PSA_ALG_OFB ||
alg == PSA_ALG_XTS ||
alg == PSA_ALG_ECB_NO_PADDING ||
alg == PSA_ALG_CBC_NO_PADDING ||
alg == PSA_ALG_CBC_PKCS7 ||
alg == PSA_ALG_CMAC) {
if (key_type == PSA_KEY_TYPE_AES ||
key_type == PSA_KEY_TYPE_ARIA ||
key_type == PSA_KEY_TYPE_DES ||
key_type == PSA_KEY_TYPE_CAMELLIA) {
return PSA_SUCCESS;
}
}
return PSA_ERROR_NOT_SUPPORTED;
}
psa_status_t mbedtls_cipher_values_from_psa(
psa_algorithm_t alg,
psa_key_type_t key_type,
size_t *key_bits,
mbedtls_cipher_mode_t *mode,
mbedtls_cipher_id_t *cipher_id)
{
mbedtls_cipher_id_t cipher_id_tmp;
/* Only DES modifies key_bits */
#if !defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
(void) key_bits;
#endif
if (PSA_ALG_IS_AEAD(alg)) {
alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0);
}
if (PSA_ALG_IS_CIPHER(alg) || PSA_ALG_IS_AEAD(alg)) {
switch (alg) {
#if defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER)
case PSA_ALG_STREAM_CIPHER:
*mode = MBEDTLS_MODE_STREAM;
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CTR)
case PSA_ALG_CTR:
*mode = MBEDTLS_MODE_CTR;
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CFB)
case PSA_ALG_CFB:
*mode = MBEDTLS_MODE_CFB;
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_OFB)
case PSA_ALG_OFB:
*mode = MBEDTLS_MODE_OFB;
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
case PSA_ALG_ECB_NO_PADDING:
*mode = MBEDTLS_MODE_ECB;
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING)
case PSA_ALG_CBC_NO_PADDING:
*mode = MBEDTLS_MODE_CBC;
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
case PSA_ALG_CBC_PKCS7:
*mode = MBEDTLS_MODE_CBC;
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG)
case PSA_ALG_CCM_STAR_NO_TAG:
*mode = MBEDTLS_MODE_CCM_STAR_NO_TAG;
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0):
*mode = MBEDTLS_MODE_CCM;
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0):
*mode = MBEDTLS_MODE_GCM;
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0):
*mode = MBEDTLS_MODE_CHACHAPOLY;
break;
#endif
default:
return PSA_ERROR_NOT_SUPPORTED;
}
} else if (alg == PSA_ALG_CMAC) {
*mode = MBEDTLS_MODE_ECB;
} else {
return PSA_ERROR_NOT_SUPPORTED;
}
switch (key_type) {
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES)
case PSA_KEY_TYPE_AES:
cipher_id_tmp = MBEDTLS_CIPHER_ID_AES;
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA)
case PSA_KEY_TYPE_ARIA:
cipher_id_tmp = MBEDTLS_CIPHER_ID_ARIA;
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
case PSA_KEY_TYPE_DES:
/* key_bits is 64 for Single-DES, 128 for two-key Triple-DES,
* and 192 for three-key Triple-DES. */
if (*key_bits == 64) {
cipher_id_tmp = MBEDTLS_CIPHER_ID_DES;
} else {
cipher_id_tmp = MBEDTLS_CIPHER_ID_3DES;
}
/* mbedtls doesn't recognize two-key Triple-DES as an algorithm,
* but two-key Triple-DES is functionally three-key Triple-DES
* with K1=K3, so that's how we present it to mbedtls. */
if (*key_bits == 128) {
*key_bits = 192;
}
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA)
case PSA_KEY_TYPE_CAMELLIA:
cipher_id_tmp = MBEDTLS_CIPHER_ID_CAMELLIA;
break;
#endif
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20)
case PSA_KEY_TYPE_CHACHA20:
cipher_id_tmp = MBEDTLS_CIPHER_ID_CHACHA20;
break;
#endif
default:
return PSA_ERROR_NOT_SUPPORTED;
}
if (cipher_id != NULL) {
*cipher_id = cipher_id_tmp;
}
return mbedtls_cipher_validate_values(alg, key_type);
}
#if defined(MBEDTLS_CIPHER_C)
const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa(
psa_algorithm_t alg,
psa_key_type_t key_type,
size_t key_bits,
mbedtls_cipher_id_t *cipher_id)
{
mbedtls_cipher_mode_t mode;
psa_status_t status;
mbedtls_cipher_id_t cipher_id_tmp = MBEDTLS_CIPHER_ID_NONE;
status = mbedtls_cipher_values_from_psa(alg, key_type, &key_bits, &mode, &cipher_id_tmp);
if (status != PSA_SUCCESS) {
return NULL;
}
if (cipher_id != NULL) {
*cipher_id = cipher_id_tmp;
}
return mbedtls_cipher_info_from_values(cipher_id_tmp, (int) key_bits, mode);
}
#endif /* MBEDTLS_CIPHER_C */
#if defined(MBEDTLS_PSA_BUILTIN_CIPHER)
static psa_status_t psa_cipher_setup(
mbedtls_psa_cipher_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg,
mbedtls_operation_t cipher_operation)
{
int ret = 0;
size_t key_bits;
const mbedtls_cipher_info_t *cipher_info = NULL;
psa_key_type_t key_type = attributes->type;
(void) key_buffer_size;
mbedtls_cipher_init(&operation->ctx.cipher);
operation->alg = alg;
key_bits = attributes->bits;
cipher_info = mbedtls_cipher_info_from_psa(alg, key_type,
key_bits, NULL);
if (cipher_info == NULL) {
return PSA_ERROR_NOT_SUPPORTED;
}
ret = mbedtls_cipher_setup(&operation->ctx.cipher, cipher_info);
if (ret != 0) {
goto exit;
}
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
if (key_type == PSA_KEY_TYPE_DES && key_bits == 128) {
/* Two-key Triple-DES is 3-key Triple-DES with K1=K3 */
uint8_t keys[24];
memcpy(keys, key_buffer, 16);
memcpy(keys + 16, key_buffer, 8);
ret = mbedtls_cipher_setkey(&operation->ctx.cipher,
keys,
192, cipher_operation);
} else
#endif
{
ret = mbedtls_cipher_setkey(&operation->ctx.cipher, key_buffer,
(int) key_bits, cipher_operation);
}
if (ret != 0) {
goto exit;
}
#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
switch (alg) {
case PSA_ALG_CBC_NO_PADDING:
ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher,
MBEDTLS_PADDING_NONE);
break;
case PSA_ALG_CBC_PKCS7:
ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher,
MBEDTLS_PADDING_PKCS7);
break;
default:
/* The algorithm doesn't involve padding. */
ret = 0;
break;
}
if (ret != 0) {
goto exit;
}
#endif /* MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING ||
MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 */
operation->block_length = (PSA_ALG_IS_STREAM_CIPHER(alg) ? 1 :
PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type));
operation->iv_length = PSA_CIPHER_IV_LENGTH(key_type, alg);
exit:
return mbedtls_to_psa_error(ret);
}
psa_status_t mbedtls_psa_cipher_encrypt_setup(
mbedtls_psa_cipher_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg)
{
return psa_cipher_setup(operation, attributes,
key_buffer, key_buffer_size,
alg, MBEDTLS_ENCRYPT);
}
psa_status_t mbedtls_psa_cipher_decrypt_setup(
mbedtls_psa_cipher_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg)
{
return psa_cipher_setup(operation, attributes,
key_buffer, key_buffer_size,
alg, MBEDTLS_DECRYPT);
}
psa_status_t mbedtls_psa_cipher_set_iv(
mbedtls_psa_cipher_operation_t *operation,
const uint8_t *iv, size_t iv_length)
{
if (iv_length != operation->iv_length) {
return PSA_ERROR_INVALID_ARGUMENT;
}
return mbedtls_to_psa_error(
mbedtls_cipher_set_iv(&operation->ctx.cipher,
iv, iv_length));
}
#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
/** Process input for which the algorithm is set to ECB mode.
*
* This requires manual processing, since the PSA API is defined as being
* able to process arbitrary-length calls to psa_cipher_update() with ECB mode,
* but the underlying mbedtls_cipher_update only takes full blocks.
*
* \param ctx The mbedtls cipher context to use. It must have been
* set up for ECB.
* \param[in] input The input plaintext or ciphertext to process.
* \param input_length The number of bytes to process from \p input.
* This does not need to be aligned to a block boundary.
* If there is a partial block at the end of the input,
* it is stored in \p ctx for future processing.
* \param output The buffer where the output is written. It must be
* at least `BS * floor((p + input_length) / BS)` bytes
* long, where `p` is the number of bytes in the
* unprocessed partial block in \p ctx (with
* `0 <= p <= BS - 1`) and `BS` is the block size.
* \param output_length On success, the number of bytes written to \p output.
* \c 0 on error.
*
* \return #PSA_SUCCESS or an error from a hardware accelerator
*/
static psa_status_t psa_cipher_update_ecb(
mbedtls_cipher_context_t *ctx,
const uint8_t *input,
size_t input_length,
uint8_t *output,
size_t *output_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
size_t block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info);
size_t internal_output_length = 0;
*output_length = 0;
if (input_length == 0) {
status = PSA_SUCCESS;
goto exit;
}
if (ctx->unprocessed_len > 0) {
/* Fill up to block size, and run the block if there's a full one. */
size_t bytes_to_copy = block_size - ctx->unprocessed_len;
if (input_length < bytes_to_copy) {
bytes_to_copy = input_length;
}
memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]),
input, bytes_to_copy);
input_length -= bytes_to_copy;
input += bytes_to_copy;
ctx->unprocessed_len += bytes_to_copy;
if (ctx->unprocessed_len == block_size) {
status = mbedtls_to_psa_error(
mbedtls_cipher_update(ctx,
ctx->unprocessed_data,
block_size,
output, &internal_output_length));
if (status != PSA_SUCCESS) {
goto exit;
}
output += internal_output_length;
*output_length += internal_output_length;
ctx->unprocessed_len = 0;
}
}
while (input_length >= block_size) {
/* Run all full blocks we have, one by one */
status = mbedtls_to_psa_error(
mbedtls_cipher_update(ctx, input,
block_size,
output, &internal_output_length));
if (status != PSA_SUCCESS) {
goto exit;
}
input_length -= block_size;
input += block_size;
output += internal_output_length;
*output_length += internal_output_length;
}
if (input_length > 0) {
/* Save unprocessed bytes for later processing */
memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]),
input, input_length);
ctx->unprocessed_len += input_length;
}
status = PSA_SUCCESS;
exit:
return status;
}
#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */
psa_status_t mbedtls_psa_cipher_update(
mbedtls_psa_cipher_operation_t *operation,
const uint8_t *input, size_t input_length,
uint8_t *output, size_t output_size, size_t *output_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
size_t expected_output_size;
if (!PSA_ALG_IS_STREAM_CIPHER(operation->alg)) {
/* Take the unprocessed partial block left over from previous
* update calls, if any, plus the input to this call. Remove
* the last partial block, if any. You get the data that will be
* output in this call. */
expected_output_size =
(operation->ctx.cipher.unprocessed_len + input_length)
/ operation->block_length * operation->block_length;
} else {
expected_output_size = input_length;
}
if (output_size < expected_output_size) {
return PSA_ERROR_BUFFER_TOO_SMALL;
}
#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
if (operation->alg == PSA_ALG_ECB_NO_PADDING) {
/* mbedtls_cipher_update has an API inconsistency: it will only
* process a single block at a time in ECB mode. Abstract away that
* inconsistency here to match the PSA API behaviour. */
status = psa_cipher_update_ecb(&operation->ctx.cipher,
input,
input_length,
output,
output_length);
} else
#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */
if (input_length == 0) {
/* There is no input, nothing to be done */
*output_length = 0;
status = PSA_SUCCESS;
} else {
status = mbedtls_to_psa_error(
mbedtls_cipher_update(&operation->ctx.cipher, input,
input_length, output, output_length));
if (*output_length > output_size) {
return PSA_ERROR_CORRUPTION_DETECTED;
}
}
return status;
}
psa_status_t mbedtls_psa_cipher_finish(
mbedtls_psa_cipher_operation_t *operation,
uint8_t *output, size_t output_size, size_t *output_length)
{
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH];
if (operation->ctx.cipher.unprocessed_len != 0) {
if (operation->alg == PSA_ALG_ECB_NO_PADDING ||
operation->alg == PSA_ALG_CBC_NO_PADDING) {
status = PSA_ERROR_INVALID_ARGUMENT;
goto exit;
}
}
status = mbedtls_to_psa_error(
mbedtls_cipher_finish(&operation->ctx.cipher,
temp_output_buffer,
output_length));
if (status != PSA_SUCCESS) {
goto exit;
}
if (*output_length == 0) {
; /* Nothing to copy. Note that output may be NULL in this case. */
} else if (output_size >= *output_length) {
memcpy(output, temp_output_buffer, *output_length);
} else {
status = PSA_ERROR_BUFFER_TOO_SMALL;
}
exit:
mbedtls_platform_zeroize(temp_output_buffer,
sizeof(temp_output_buffer));
return status;
}
psa_status_t mbedtls_psa_cipher_abort(
mbedtls_psa_cipher_operation_t *operation)
{
/* Sanity check (shouldn't happen: operation->alg should
* always have been initialized to a valid value). */
if (!PSA_ALG_IS_CIPHER(operation->alg)) {
return PSA_ERROR_BAD_STATE;
}
mbedtls_cipher_free(&operation->ctx.cipher);
return PSA_SUCCESS;
}
psa_status_t mbedtls_psa_cipher_encrypt(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *iv,
size_t iv_length,
const uint8_t *input,
size_t input_length,
uint8_t *output,
size_t output_size,
size_t *output_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT;
size_t update_output_length, finish_output_length;
status = mbedtls_psa_cipher_encrypt_setup(&operation, attributes,
key_buffer, key_buffer_size,
alg);
if (status != PSA_SUCCESS) {
goto exit;
}
if (iv_length > 0) {
status = mbedtls_psa_cipher_set_iv(&operation, iv, iv_length);
if (status != PSA_SUCCESS) {
goto exit;
}
}
status = mbedtls_psa_cipher_update(&operation, input, input_length,
output, output_size,
&update_output_length);
if (status != PSA_SUCCESS) {
goto exit;
}
status = mbedtls_psa_cipher_finish(
&operation,
mbedtls_buffer_offset(output, update_output_length),
output_size - update_output_length, &finish_output_length);
if (status != PSA_SUCCESS) {
goto exit;
}
*output_length = update_output_length + finish_output_length;
exit:
if (status == PSA_SUCCESS) {
status = mbedtls_psa_cipher_abort(&operation);
} else {
mbedtls_psa_cipher_abort(&operation);
}
return status;
}
psa_status_t mbedtls_psa_cipher_decrypt(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *input,
size_t input_length,
uint8_t *output,
size_t output_size,
size_t *output_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT;
size_t olength, accumulated_length;
status = mbedtls_psa_cipher_decrypt_setup(&operation, attributes,
key_buffer, key_buffer_size,
alg);
if (status != PSA_SUCCESS) {
goto exit;
}
if (operation.iv_length > 0) {
status = mbedtls_psa_cipher_set_iv(&operation,
input, operation.iv_length);
if (status != PSA_SUCCESS) {
goto exit;
}
}
status = mbedtls_psa_cipher_update(
&operation,
mbedtls_buffer_offset_const(input, operation.iv_length),
input_length - operation.iv_length,
output, output_size, &olength);
if (status != PSA_SUCCESS) {
goto exit;
}
accumulated_length = olength;
status = mbedtls_psa_cipher_finish(
&operation,
mbedtls_buffer_offset(output, accumulated_length),
output_size - accumulated_length, &olength);
if (status != PSA_SUCCESS) {
goto exit;
}
*output_length = accumulated_length + olength;
exit:
if (status == PSA_SUCCESS) {
status = mbedtls_psa_cipher_abort(&operation);
} else {
mbedtls_psa_cipher_abort(&operation);
}
return status;
}
#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */
#endif /* MBEDTLS_PSA_CRYPTO_C */

View File

@@ -0,0 +1,316 @@
/*
* PSA cipher driver entry points and associated auxiliary functions
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef PSA_CRYPTO_CIPHER_H
#define PSA_CRYPTO_CIPHER_H
#include <mbedtls/cipher.h>
#include <psa/crypto.h>
/** Get Mbed TLS cipher information given the cipher algorithm PSA identifier
* as well as the PSA type and size of the key to be used with the cipher
* algorithm.
*
* \param[in] alg PSA cipher algorithm identifier
* \param[in] key_type PSA key type
* \param[in,out] key_bits Size of the key in bits. The value provided in input
* might be updated if necessary.
* \param[out] mode Mbed TLS cipher mode
* \param[out] cipher_id Mbed TLS cipher algorithm identifier
*
* \return On success \c PSA_SUCCESS is returned and key_bits, mode and cipher_id
* are properly updated.
* \c PSA_ERROR_NOT_SUPPORTED is returned if the cipher algorithm is not
* supported.
*/
psa_status_t mbedtls_cipher_values_from_psa(psa_algorithm_t alg, psa_key_type_t key_type,
size_t *key_bits, mbedtls_cipher_mode_t *mode,
mbedtls_cipher_id_t *cipher_id);
#if defined(MBEDTLS_CIPHER_C)
/** Get Mbed TLS cipher information given the cipher algorithm PSA identifier
* as well as the PSA type and size of the key to be used with the cipher
* algorithm.
*
* \param alg PSA cipher algorithm identifier
* \param key_type PSA key type
* \param key_bits Size of the key in bits
* \param[out] cipher_id Mbed TLS cipher algorithm identifier
*
* \return The Mbed TLS cipher information of the cipher algorithm.
* \c NULL if the PSA cipher algorithm is not supported.
*/
const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa(
psa_algorithm_t alg, psa_key_type_t key_type, size_t key_bits,
mbedtls_cipher_id_t *cipher_id);
#endif /* MBEDTLS_CIPHER_C */
/**
* \brief Set the key for a multipart symmetric encryption operation.
*
* \note The signature of this function is that of a PSA driver
* cipher_encrypt_setup entry point. This function behaves as a
* cipher_encrypt_setup entry point as defined in the PSA driver
* interface specification for transparent drivers.
*
* \param[in,out] operation The operation object to set up. It has been
* initialized as per the documentation for
* #psa_cipher_operation_t and not yet in use.
* \param[in] attributes The attributes of the key to use for the
* operation.
* \param[in] key_buffer The buffer containing the key context.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes.
* \param[in] alg The cipher algorithm to compute
* (\c PSA_ALG_XXX value such that
* #PSA_ALG_IS_CIPHER(\p alg) is true).
*
* \retval #PSA_SUCCESS \emptydescription
* \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
* \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
*/
psa_status_t mbedtls_psa_cipher_encrypt_setup(
mbedtls_psa_cipher_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg);
/**
* \brief Set the key for a multipart symmetric decryption operation.
*
* \note The signature of this function is that of a PSA driver
* cipher_decrypt_setup entry point. This function behaves as a
* cipher_decrypt_setup entry point as defined in the PSA driver
* interface specification for transparent drivers.
*
* \param[in,out] operation The operation object to set up. It has been
* initialized as per the documentation for
* #psa_cipher_operation_t and not yet in use.
* \param[in] attributes The attributes of the key to use for the
* operation.
* \param[in] key_buffer The buffer containing the key context.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes.
* \param[in] alg The cipher algorithm to compute
* (\c PSA_ALG_XXX value such that
* #PSA_ALG_IS_CIPHER(\p alg) is true).
*
* \retval #PSA_SUCCESS \emptydescription
* \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
* \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
*/
psa_status_t mbedtls_psa_cipher_decrypt_setup(
mbedtls_psa_cipher_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg);
/** Set the IV for a symmetric encryption or decryption operation.
*
* This function sets the IV (initialization vector), nonce
* or initial counter value for the encryption or decryption operation.
*
* \note The signature of this function is that of a PSA driver
* cipher_set_iv entry point. This function behaves as a
* cipher_set_iv entry point as defined in the PSA driver
* interface specification for transparent drivers.
*
* \param[in,out] operation Active cipher operation.
* \param[in] iv Buffer containing the IV to use.
* \param[in] iv_length Size of the IV in bytes. It is guaranteed by
* the core to be less or equal to
* PSA_CIPHER_IV_MAX_SIZE.
*
* \retval #PSA_SUCCESS \emptydescription
* \retval #PSA_ERROR_INVALID_ARGUMENT
* The size of \p iv is not acceptable for the chosen algorithm,
* or the chosen algorithm does not use an IV.
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
*/
psa_status_t mbedtls_psa_cipher_set_iv(
mbedtls_psa_cipher_operation_t *operation,
const uint8_t *iv, size_t iv_length);
/** Encrypt or decrypt a message fragment in an active cipher operation.
*
* \note The signature of this function is that of a PSA driver
* cipher_update entry point. This function behaves as a
* cipher_update entry point as defined in the PSA driver
* interface specification for transparent drivers.
*
* \param[in,out] operation Active cipher operation.
* \param[in] input Buffer containing the message fragment to
* encrypt or decrypt.
* \param[in] input_length Size of the \p input buffer in bytes.
* \param[out] output Buffer where the output is to be written.
* \param[in] output_size Size of the \p output buffer in bytes.
* \param[out] output_length On success, the number of bytes
* that make up the returned output.
*
* \retval #PSA_SUCCESS \emptydescription
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* The size of the \p output buffer is too small.
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
*/
psa_status_t mbedtls_psa_cipher_update(
mbedtls_psa_cipher_operation_t *operation,
const uint8_t *input, size_t input_length,
uint8_t *output, size_t output_size, size_t *output_length);
/** Finish encrypting or decrypting a message in a cipher operation.
*
* \note The signature of this function is that of a PSA driver
* cipher_finish entry point. This function behaves as a
* cipher_finish entry point as defined in the PSA driver
* interface specification for transparent drivers.
*
* \param[in,out] operation Active cipher operation.
* \param[out] output Buffer where the output is to be written.
* \param[in] output_size Size of the \p output buffer in bytes.
* \param[out] output_length On success, the number of bytes
* that make up the returned output.
*
* \retval #PSA_SUCCESS \emptydescription
* \retval #PSA_ERROR_INVALID_ARGUMENT
* The total input size passed to this operation is not valid for
* this particular algorithm. For example, the algorithm is a based
* on block cipher and requires a whole number of blocks, but the
* total input size is not a multiple of the block size.
* \retval #PSA_ERROR_INVALID_PADDING
* This is a decryption operation for an algorithm that includes
* padding, and the ciphertext does not contain valid padding.
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* The size of the \p output buffer is too small.
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
*/
psa_status_t mbedtls_psa_cipher_finish(
mbedtls_psa_cipher_operation_t *operation,
uint8_t *output, size_t output_size, size_t *output_length);
/** Abort a cipher operation.
*
* Aborting an operation frees all associated resources except for the
* \p operation structure itself. Once aborted, the operation object
* can be reused for another operation.
*
* \note The signature of this function is that of a PSA driver
* cipher_abort entry point. This function behaves as a
* cipher_abort entry point as defined in the PSA driver
* interface specification for transparent drivers.
*
* \param[in,out] operation Initialized cipher operation.
*
* \retval #PSA_SUCCESS \emptydescription
*/
psa_status_t mbedtls_psa_cipher_abort(mbedtls_psa_cipher_operation_t *operation);
/** Encrypt a message using a symmetric cipher.
*
* \note The signature of this function is that of a PSA driver
* cipher_encrypt entry point. This function behaves as a
* cipher_encrypt entry point as defined in the PSA driver
* interface specification for transparent drivers.
*
* \param[in] attributes The attributes of the key to use for the
* operation.
* \param[in] key_buffer The buffer containing the key context.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes.
* \param[in] alg The cipher algorithm to compute
* (\c PSA_ALG_XXX value such that
* #PSA_ALG_IS_CIPHER(\p alg) is true).
* \param[in] iv Buffer containing the IV for encryption. The
* IV has been generated by the core.
* \param[in] iv_length Size of the \p iv in bytes.
* \param[in] input Buffer containing the message to encrypt.
* \param[in] input_length Size of the \p input buffer in bytes.
* \param[in,out] output Buffer where the output is to be written.
* \param[in] output_size Size of the \p output buffer in bytes.
* \param[out] output_length On success, the number of bytes that make up
* the returned output. Initialized to zero
* by the core.
*
* \retval #PSA_SUCCESS \emptydescription
* \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
* \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* The size of the \p output buffer is too small.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* The size \p iv_length is not acceptable for the chosen algorithm,
* or the chosen algorithm does not use an IV.
* The total input size passed to this operation is not valid for
* this particular algorithm. For example, the algorithm is a based
* on block cipher and requires a whole number of blocks, but the
* total input size is not a multiple of the block size.
* \retval #PSA_ERROR_INVALID_PADDING
* This is a decryption operation for an algorithm that includes
* padding, and the ciphertext does not contain valid padding.
*/
psa_status_t mbedtls_psa_cipher_encrypt(const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *iv,
size_t iv_length,
const uint8_t *input,
size_t input_length,
uint8_t *output,
size_t output_size,
size_t *output_length);
/** Decrypt a message using a symmetric cipher.
*
* \note The signature of this function is that of a PSA driver
* cipher_decrypt entry point. This function behaves as a
* cipher_decrypt entry point as defined in the PSA driver
* interface specification for transparent drivers.
*
* \param[in] attributes The attributes of the key to use for the
* operation.
* \param[in] key_buffer The buffer containing the key context.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes.
* \param[in] alg The cipher algorithm to compute
* (\c PSA_ALG_XXX value such that
* #PSA_ALG_IS_CIPHER(\p alg) is true).
* \param[in] input Buffer containing the iv and the ciphertext.
* \param[in] input_length Size of the \p input buffer in bytes.
* \param[out] output Buffer where the output is to be written.
* \param[in] output_size Size of the \p output buffer in bytes.
* \param[out] output_length On success, the number of bytes that make up
* the returned output. Initialized to zero
* by the core.
*
* \retval #PSA_SUCCESS \emptydescription
* \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
* \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* The size of the \p output buffer is too small.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* The size of \p iv is not acceptable for the chosen algorithm,
* or the chosen algorithm does not use an IV.
* The total input size passed to this operation is not valid for
* this particular algorithm. For example, the algorithm is a based
* on block cipher and requires a whole number of blocks, but the
* total input size is not a multiple of the block size.
* \retval #PSA_ERROR_INVALID_PADDING
* This is a decryption operation for an algorithm that includes
* padding, and the ciphertext does not contain valid padding.
*/
psa_status_t mbedtls_psa_cipher_decrypt(const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *input,
size_t input_length,
uint8_t *output,
size_t output_size,
size_t *output_length);
#endif /* PSA_CRYPTO_CIPHER_H */

View File

@@ -0,0 +1,22 @@
/*
* PSA crypto client code
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#include "psa/crypto.h"
#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
#include <string.h>
#include "mbedtls/platform.h"
void psa_reset_key_attributes(psa_key_attributes_t *attributes)
{
memset(attributes, 0, sizeof(*attributes));
}
#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */

View File

@@ -0,0 +1,995 @@
/*
* PSA crypto core internal interfaces
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef PSA_CRYPTO_CORE_H
#define PSA_CRYPTO_CORE_H
/*
* Include the build-time configuration information header. Here, we do not
* include `"mbedtls/build_info.h"` directly but `"psa/build_info.h"`, which
* is basically just an alias to it. This is to ease the maintenance of the
* TF-PSA-Crypto repository which has a different build system and
* configuration.
*/
#include "psa/build_info.h"
#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 cipher.
*
* \note For now, only checks the state of the driver subsystem,
* not the algorithm. Might do more in the future.
*
* \param cipher_alg The cipher algorithm (ignored for now).
*
* \return 1 if the driver subsytem is ready, 0 otherwise.
*/
int psa_can_do_cipher(psa_key_type_t key_type, psa_algorithm_t cipher_alg);
typedef enum {
PSA_SLOT_EMPTY = 0,
PSA_SLOT_FILLING,
PSA_SLOT_FULL,
PSA_SLOT_PENDING_DELETION,
} psa_key_slot_state_t;
/** The data structure representing a key slot, containing key material
* and metadata for one key.
*/
typedef struct {
/* This field is accessed in a lot of places. Putting it first
* reduces the code size. */
psa_key_attributes_t attr;
/*
* The current state of the key slot, as described in
* docs/architecture/psa-thread-safety/psa-thread-safety.md.
*
* Library functions can modify the state of a key slot by calling
* psa_key_slot_state_transition.
*
* The state variable is used to help determine whether library functions
* which operate on the slot succeed. For example, psa_finish_key_creation,
* which transfers the state of a slot from PSA_SLOT_FILLING to
* PSA_SLOT_FULL, must fail with error code PSA_ERROR_CORRUPTION_DETECTED
* if the state of the slot is not PSA_SLOT_FILLING.
*
* Library functions which traverse the array of key slots only consider
* slots that are in a suitable state for the function.
* For example, psa_get_and_lock_key_slot_in_memory, which finds a slot
* containing a given key ID, will only check slots whose state variable is
* PSA_SLOT_FULL.
*/
psa_key_slot_state_t state;
#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
/* The index of the slice containing this slot.
* This field must be filled if the slot contains a key
* (including keys being created or destroyed), and can be either
* filled or 0 when the slot is free.
*
* In most cases, the slice index can be deduced from the key identifer.
* We keep it in a separate field for robustness (it reduces the chance
* that a coding mistake in the key store will result in accessing the
* wrong slice), and also so that it's available even on code paths
* during creation or destruction where the key identifier might not be
* filled in.
* */
uint8_t slice_index;
#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
union {
struct {
/* The index of the next slot in the free list for this
* slice, relative * to the next array element.
*
* That is, 0 means the next slot, 1 means the next slot
* but one, etc. -1 would mean the slot itself. -2 means
* the previous slot, etc.
*
* If this is beyond the array length, the free list ends with the
* current element.
*
* The reason for this strange encoding is that 0 means the next
* element. This way, when we allocate a slice and initialize it
* to all-zero, the slice is ready for use, with a free list that
* consists of all the slots in order.
*/
int32_t next_free_relative_to_next;
} free;
struct {
/*
* Number of functions registered as reading the material in the key slot.
*
* Library functions must not write directly to registered_readers
*
* 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. 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.
*
* This counter is used to prevent resetting the key slot while
* the library may access it. For example, such control is needed
* in the following scenarios:
* . In case of key slot starvation, all key slots contain the
* description of a key, and the library asks for the
* description of a persistent key not present in the
* key slots, the key slots currently accessed by the
* library cannot be reclaimed to free a key slot to load
* the persistent key.
* . In case of a multi-threaded application where one thread
* asks to close or purge or destroy a key while it is in use
* by the library through another thread. */
size_t registered_readers;
} occupied;
} var;
/* Dynamically allocated key data buffer.
* Format as specified in psa_export_key(). */
struct key_data {
#if defined(MBEDTLS_PSA_STATIC_KEY_SLOTS)
uint8_t data[MBEDTLS_PSA_STATIC_KEY_SLOT_BUFFER_SIZE];
#else
uint8_t *data;
#endif
size_t bytes;
} key;
} psa_key_slot_t;
#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
* global key slot mutex.
*
* \param[in] slot The key slot to test.
*
* \return 1 if the slot has any registered readers, 0 otherwise.
*/
static inline int psa_key_slot_has_readers(const psa_key_slot_t *slot)
{
return slot->var.occupied.registered_readers > 0;
}
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
/** Get the SE slot number of a key from the key slot storing its description.
*
* \param[in] slot The key slot to query. This must be a key slot storing
* the description of a key of a dynamically registered
* secure element, otherwise the behaviour is undefined.
*/
static inline psa_key_slot_number_t psa_key_slot_get_slot_number(
const psa_key_slot_t *slot)
{
return *((psa_key_slot_number_t *) (slot->key.data));
}
#endif
/** Completely wipe a slot in memory, including its policy.
*
* Persistent storage is not affected.
* Sets the slot's state to PSA_SLOT_EMPTY.
* If multi-threading is enabled, the caller must hold the
* global key slot mutex.
*
* \param[in,out] slot The key slot to wipe.
*
* \retval #PSA_SUCCESS
* The slot has been successfully wiped.
* \retval #PSA_ERROR_CORRUPTION_DETECTED
* The slot's state was PSA_SLOT_FULL or PSA_SLOT_PENDING_DELETION, and
* the amount of registered readers was not equal to 1. Or,
* the slot's state was PSA_SLOT_EMPTY. Or,
* the slot's state was PSA_SLOT_FILLING, and the amount
* of registered readers was not equal to 0.
*/
psa_status_t psa_wipe_key_slot(psa_key_slot_t *slot);
/** Try to allocate a buffer to an empty key slot.
*
* \param[in,out] slot Key slot to attach buffer to.
* \param[in] buffer_length Requested size of the buffer.
*
* \retval #PSA_SUCCESS
* The buffer has been successfully allocated.
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* Not enough memory was available for allocation.
* \retval #PSA_ERROR_ALREADY_EXISTS
* Trying to allocate a buffer to a non-empty key slot.
*/
psa_status_t psa_allocate_buffer_to_slot(psa_key_slot_t *slot,
size_t buffer_length);
/** Wipe key data from a slot. Preserves metadata such as the policy. */
psa_status_t psa_remove_key_data_from_memory(psa_key_slot_t *slot);
/** Copy key data (in export format) into an empty key slot.
*
* This function assumes that the slot does not contain
* any key material yet. On failure, the slot content is unchanged.
*
* \param[in,out] slot Key slot to copy the key into.
* \param[in] data Buffer containing the key material.
* \param data_length Size of the key buffer.
*
* \retval #PSA_SUCCESS
* The key has been copied successfully.
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* Not enough memory was available for allocation of the
* copy buffer.
* \retval #PSA_ERROR_ALREADY_EXISTS
* There was other key material already present in the slot.
*/
psa_status_t psa_copy_key_material_into_slot(psa_key_slot_t *slot,
const uint8_t *data,
size_t data_length);
/** Convert an Mbed TLS error code to a PSA error code
*
* \note This function is provided solely for the convenience of
* Mbed TLS and may be removed at any time without notice.
*
* \param ret An Mbed TLS-thrown error code
*
* \return The corresponding PSA error code
*/
psa_status_t mbedtls_to_psa_error(int ret);
/** Import a key in binary format.
*
* \note The signature of this function is that of a PSA driver
* import_key entry point. This function behaves as an import_key
* entry point as defined in the PSA driver interface specification for
* transparent drivers.
*
* \param[in] attributes The attributes for the key to import.
* \param[in] data The buffer containing the key data in import
* format.
* \param[in] data_length Size of the \p data buffer in bytes.
* \param[out] key_buffer The buffer to contain the key data in output
* format upon successful return.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes. This
* size is greater or equal to \p data_length.
* \param[out] key_buffer_length The length of the data written in \p
* key_buffer in bytes.
* \param[out] bits The key size in number of bits.
*
* \retval #PSA_SUCCESS The key was imported successfully.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* The key data is not correctly formatted.
* \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
* \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
*/
psa_status_t psa_import_key_into_slot(
const psa_key_attributes_t *attributes,
const uint8_t *data, size_t data_length,
uint8_t *key_buffer, size_t key_buffer_size,
size_t *key_buffer_length, size_t *bits);
/** Export a key in binary format
*
* \note The signature of this function is that of a PSA driver export_key
* entry point. This function behaves as an export_key entry point as
* defined in the PSA driver interface specification.
*
* \param[in] attributes The attributes for the key to export.
* \param[in] key_buffer Material or context of the key to export.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes.
* \param[out] data Buffer where the key data is to be written.
* \param[in] data_size Size of the \p data buffer in bytes.
* \param[out] data_length On success, the number of bytes written in
* \p data
*
* \retval #PSA_SUCCESS The key was exported successfully.
* \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
* \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
* \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
* \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
* \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
*/
psa_status_t psa_export_key_internal(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length);
/** Export a public key or the public part of a key pair in binary format.
*
* \note The signature of this function is that of a PSA driver
* export_public_key entry point. This function behaves as an
* export_public_key entry point as defined in the PSA driver interface
* specification.
*
* \param[in] attributes The attributes for the key to export.
* \param[in] key_buffer Material or context of the key to export.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes.
* \param[out] data Buffer where the key data is to be written.
* \param[in] data_size Size of the \p data buffer in bytes.
* \param[out] data_length On success, the number of bytes written in
* \p data
*
* \retval #PSA_SUCCESS The public key was exported successfully.
* \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
* \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
* \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
* \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
* \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
*/
psa_status_t psa_export_public_key_internal(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length);
/** Whether a key custom production parameters structure is the default.
*
* Calls to a key generation driver with non-default custom production parameters
* require a driver supporting custom production parameters.
*
* \param[in] custom The key custom production parameters to check.
* \param custom_data_length Size of the associated variable-length data
* in bytes.
*/
int psa_custom_key_parameters_are_default(
const psa_custom_key_parameters_t *custom,
size_t custom_data_length);
/**
* \brief Generate a key.
*
* \note The signature of the function is that of a PSA driver generate_key
* entry point.
*
* \param[in] attributes The attributes for the key to generate.
* \param[in] custom Custom parameters for the key generation.
* \param[in] custom_data Variable-length data associated with \c custom.
* \param custom_data_length Length of `custom_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
* \p key_buffer.
*
* \retval #PSA_SUCCESS
* The key was generated successfully.
* \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
* \retval #PSA_ERROR_NOT_SUPPORTED
* Key size in bits or type not supported.
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* The size of \p key_buffer is too small.
*/
psa_status_t psa_generate_key_internal(const psa_key_attributes_t *attributes,
const psa_custom_key_parameters_t *custom,
const uint8_t *custom_data,
size_t custom_data_length,
uint8_t *key_buffer,
size_t key_buffer_size,
size_t *key_buffer_length);
/** Sign a message with a private key. For hash-and-sign algorithms,
* this includes the hashing step.
*
* \note The signature of this function is that of a PSA driver
* sign_message entry point. This function behaves as a sign_message
* entry point as defined in the PSA driver interface specification for
* transparent drivers.
*
* \note This function will call the driver for psa_sign_hash
* and go through driver dispatch again.
*
* \param[in] attributes The attributes of the key to use for the
* operation.
* \param[in] key_buffer The buffer containing the key context.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes.
* \param[in] alg A signature algorithm that is compatible with
* the type of the key.
* \param[in] input The input message to sign.
* \param[in] input_length Size of the \p input buffer in bytes.
* \param[out] signature Buffer where the signature is to be written.
* \param[in] signature_size Size of the \p signature buffer in bytes.
* \param[out] signature_length On success, the number of bytes
* that make up the returned signature value.
*
* \retval #PSA_SUCCESS \emptydescription
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* The size of the \p signature buffer is too small. You can
* determine a sufficient buffer size by calling
* #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg)
* where \c key_type and \c key_bits are the type and bit-size
* respectively of the key.
* \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
* \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
* \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
* \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
*/
psa_status_t psa_sign_message_builtin(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *input, size_t input_length,
uint8_t *signature, size_t signature_size, size_t *signature_length);
/** Verify the signature of a message with a public key, using
* a hash-and-sign verification algorithm.
*
* \note The signature of this function is that of a PSA driver
* verify_message entry point. This function behaves as a verify_message
* entry point as defined in the PSA driver interface specification for
* transparent drivers.
*
* \note This function will call the driver for psa_verify_hash
* and go through driver dispatch again.
*
* \param[in] attributes The attributes of the key to use for the
* operation.
* \param[in] key_buffer The buffer containing the key context.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes.
* \param[in] alg A signature algorithm that is compatible with
* the type of the key.
* \param[in] input The message whose signature is to be verified.
* \param[in] input_length Size of the \p input buffer in bytes.
* \param[in] signature Buffer containing the signature to verify.
* \param[in] signature_length Size of the \p signature buffer in bytes.
*
* \retval #PSA_SUCCESS
* The signature is valid.
* \retval #PSA_ERROR_INVALID_SIGNATURE
* The calculation was performed successfully, but the passed
* signature is not a valid signature.
* \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
* \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
*/
psa_status_t psa_verify_message_builtin(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *input, size_t input_length,
const uint8_t *signature, size_t signature_length);
/** Sign an already-calculated hash with a private key.
*
* \note The signature of this function is that of a PSA driver
* sign_hash entry point. This function behaves as a sign_hash
* entry point as defined in the PSA driver interface specification for
* transparent drivers.
*
* \param[in] attributes The attributes of the key to use for the
* operation.
* \param[in] key_buffer The buffer containing the key context.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes.
* \param[in] alg A signature algorithm that is compatible with
* the type of the key.
* \param[in] hash The hash or message to sign.
* \param[in] hash_length Size of the \p hash buffer in bytes.
* \param[out] signature Buffer where the signature is to be written.
* \param[in] signature_size Size of the \p signature buffer in bytes.
* \param[out] signature_length On success, the number of bytes
* that make up the returned signature value.
*
* \retval #PSA_SUCCESS \emptydescription
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* The size of the \p signature buffer is too small. You can
* determine a sufficient buffer size by calling
* #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg)
* where \c key_type and \c key_bits are the type and bit-size
* respectively of the key.
* \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
* \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
* \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
* \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
*/
psa_status_t psa_sign_hash_builtin(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
uint8_t *signature, size_t signature_size, size_t *signature_length);
/**
* \brief Verify the signature a hash or short message using a public key.
*
* \note The signature of this function is that of a PSA driver
* verify_hash entry point. This function behaves as a verify_hash
* entry point as defined in the PSA driver interface specification for
* transparent drivers.
*
* \param[in] attributes The attributes of the key to use for the
* operation.
* \param[in] key_buffer The buffer containing the key context.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes.
* \param[in] alg A signature algorithm that is compatible with
* the type of the key.
* \param[in] hash The hash or message whose signature is to be
* verified.
* \param[in] hash_length Size of the \p hash buffer in bytes.
* \param[in] signature Buffer containing the signature to verify.
* \param[in] signature_length Size of the \p signature buffer in bytes.
*
* \retval #PSA_SUCCESS
* The signature is valid.
* \retval #PSA_ERROR_INVALID_SIGNATURE
* The calculation was performed successfully, but the passed
* signature is not a valid signature.
* \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
* \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
*/
psa_status_t psa_verify_hash_builtin(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
const uint8_t *signature, size_t signature_length);
/**
* \brief Validate the key bit size for unstructured keys.
*
* \note Check that the bit size is acceptable for a given key type for
* unstructured keys.
*
* \param[in] type The key type
* \param[in] bits The number of bits of the key
*
* \retval #PSA_SUCCESS
* 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
* The type and/or the size in bits of the key or the combination of
* the two is not supported.
*/
psa_status_t psa_validate_unstructured_key_bit_size(psa_key_type_t type,
size_t bits);
/** Perform a key agreement and return the raw shared secret, using
built-in raw key agreement functions.
*
* \note The signature of this function is that of a PSA driver
* key_agreement entry point. This function behaves as a key_agreement
* entry point as defined in the PSA driver interface specification for
* transparent drivers.
*
* \param[in] attributes The attributes of the key to use for the
* operation.
* \param[in] key_buffer The buffer containing the private key
* context.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in
* bytes.
* \param[in] alg A key agreement algorithm that is
* compatible with the type of the key.
* \param[in] peer_key The buffer containing the key context
* of the peer's public key.
* \param[in] peer_key_length Size of the \p peer_key buffer in
* bytes.
* \param[out] shared_secret The buffer to which the shared secret
* is to be written.
* \param[in] shared_secret_size Size of the \p shared_secret buffer in
* bytes.
* \param[out] shared_secret_length On success, the number of bytes that make
* up the returned shared secret.
* \retval #PSA_SUCCESS
* Success. Shared secret successfully calculated.
* \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
* \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
* \retval #PSA_ERROR_INVALID_ARGUMENT
* \p alg is not a key agreement algorithm, or
* \p private_key is not compatible with \p alg,
* or \p peer_key is not valid for \p alg or not compatible with
* \p private_key.
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* \p shared_secret_size is too small
* \retval #PSA_ERROR_NOT_SUPPORTED
* \p alg is not a supported key agreement algorithm.
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
* \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
* \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
* \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
* \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
* \retval #PSA_ERROR_BAD_STATE \emptydescription
*/
psa_status_t psa_key_agreement_raw_builtin(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer,
size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *peer_key,
size_t peer_key_length,
uint8_t *shared_secret,
size_t shared_secret_size,
size_t *shared_secret_length);
/**
* \brief Set the maximum number of ops allowed to be executed by an
* interruptible function in a single call.
*
* \note The signature of this function is that of a PSA driver
* interruptible_set_max_ops entry point. This function behaves as an
* interruptible_set_max_ops entry point as defined in the PSA driver
* interface specification for transparent drivers.
*
* \param[in] max_ops The maximum number of ops to be executed in a
* single call, this can be a number from 0 to
* #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED, where 0
* is obviously the least amount of work done per
* call.
*/
void mbedtls_psa_interruptible_set_max_ops(uint32_t max_ops);
/**
* \brief Get the maximum number of ops allowed to be executed by an
* interruptible function in a single call.
*
* \note The signature of this function is that of a PSA driver
* interruptible_get_max_ops entry point. This function behaves as an
* interruptible_get_max_ops entry point as defined in the PSA driver
* interface specification for transparent drivers.
*
* \return Maximum number of ops allowed to be executed
* by an interruptible function in a single call.
*/
uint32_t mbedtls_psa_interruptible_get_max_ops(void);
/**
* \brief Get the number of ops that a hash signing operation has taken for the
* previous call. If no call or work has taken place, this will return
* zero.
*
* \note The signature of this function is that of a PSA driver
* sign_hash_get_num_ops entry point. This function behaves as an
* sign_hash_get_num_ops entry point as defined in the PSA driver
* interface specification for transparent drivers.
*
* \param operation The \c
* mbedtls_psa_sign_hash_interruptible_operation_t
* to use. This must be initialized first.
*
* \return Number of ops that were completed
* in the last call to \c
* mbedtls_psa_sign_hash_complete().
*/
uint32_t mbedtls_psa_sign_hash_get_num_ops(
const mbedtls_psa_sign_hash_interruptible_operation_t *operation);
/**
* \brief Get the number of ops that a hash verification operation has taken for
* the previous call. If no call or work has taken place, this will
* return zero.
*
* \note The signature of this function is that of a PSA driver
* verify_hash_get_num_ops entry point. This function behaves as an
* verify_hash_get_num_ops entry point as defined in the PSA driver
* interface specification for transparent drivers.
*
* \param operation The \c
* mbedtls_psa_verify_hash_interruptible_operation_t
* to use. This must be initialized first.
*
* \return Number of ops that were completed
* in the last call to \c
* mbedtls_psa_verify_hash_complete().
*/
uint32_t mbedtls_psa_verify_hash_get_num_ops(
const mbedtls_psa_verify_hash_interruptible_operation_t *operation);
/**
* \brief Start signing a hash or short message with a private key, in an
* interruptible manner.
*
* \note The signature of this function is that of a PSA driver
* sign_hash_start entry point. This function behaves as a
* sign_hash_start entry point as defined in the PSA driver interface
* specification for transparent drivers.
*
* \param[in] operation The \c
* mbedtls_psa_sign_hash_interruptible_operation_t
* to use. This must be initialized first.
* \param[in] attributes The attributes of the key to use for the
* operation.
* \param[in] key_buffer The buffer containing the key context.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes.
* \param[in] alg A signature algorithm that is compatible with
* the type of the key.
* \param[in] hash The hash or message to sign.
* \param hash_length Size of the \p hash buffer in bytes.
*
* \retval #PSA_SUCCESS
* The operation started successfully - call \c psa_sign_hash_complete()
* with the same context to complete the operation
* \retval #PSA_ERROR_INVALID_ARGUMENT
* An unsupported, incorrectly formatted or incorrect type of key was
* used.
* \retval #PSA_ERROR_NOT_SUPPORTED Either no internal interruptible operations
* are currently supported, or the key type is currently unsupported.
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* There was insufficient memory to load the key representation.
*/
psa_status_t mbedtls_psa_sign_hash_start(
mbedtls_psa_sign_hash_interruptible_operation_t *operation,
const psa_key_attributes_t *attributes, const uint8_t *key_buffer,
size_t key_buffer_size, psa_algorithm_t alg,
const uint8_t *hash, size_t hash_length);
/**
* \brief Continue and eventually complete the action of signing a hash or
* short message with a private key, in an interruptible manner.
*
* \note The signature of this function is that of a PSA driver
* sign_hash_complete entry point. This function behaves as a
* sign_hash_complete entry point as defined in the PSA driver interface
* specification for transparent drivers.
*
* \param[in] operation The \c
* mbedtls_psa_sign_hash_interruptible_operation_t
* to use. This must be initialized first.
*
* \param[out] signature Buffer where the signature is to be written.
* \param signature_size Size of the \p signature buffer in bytes. This
* must be appropriate for the selected
* algorithm and key.
* \param[out] signature_length On success, the number of bytes that make up
* the returned signature value.
*
* \retval #PSA_SUCCESS
* Operation completed successfully
*
* \retval #PSA_OPERATION_INCOMPLETE
* Operation was interrupted due to the setting of \c
* psa_interruptible_set_max_ops(), there is still work to be done,
* please call this function again with the same operation object.
*
* \retval #PSA_ERROR_BUFFER_TOO_SMALL
* The size of the \p signature buffer is too small. You can
* determine a sufficient buffer size by calling
* #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg)
* where \c key_type and \c key_bits are the type and bit-size
* respectively of \p key.
*
* \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
* \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
* \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
* \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
*/
psa_status_t mbedtls_psa_sign_hash_complete(
mbedtls_psa_sign_hash_interruptible_operation_t *operation,
uint8_t *signature, size_t signature_size,
size_t *signature_length);
/**
* \brief Abort a sign hash operation.
*
* \note The signature of this function is that of a PSA driver sign_hash_abort
* entry point. This function behaves as a sign_hash_abort entry point as
* defined in the PSA driver interface specification for transparent
* drivers.
*
* \param[in] operation The \c
* mbedtls_psa_sign_hash_interruptible_operation_t
* to abort.
*
* \retval #PSA_SUCCESS
* The operation was aborted successfully.
*/
psa_status_t mbedtls_psa_sign_hash_abort(
mbedtls_psa_sign_hash_interruptible_operation_t *operation);
/**
* \brief Start reading and verifying a hash or short message, in an
* interruptible manner.
*
* \note The signature of this function is that of a PSA driver
* verify_hash_start entry point. This function behaves as a
* verify_hash_start entry point as defined in the PSA driver interface
* specification for transparent drivers.
*
* \param[in] operation The \c
* mbedtls_psa_verify_hash_interruptible_operation_t
* to use. This must be initialized first.
* \param[in] attributes The attributes of the key to use for the
* operation.
* \param[in] key_buffer The buffer containing the key context.
* \param[in] key_buffer_size Size of the \p key_buffer buffer in bytes.
* \param[in] alg A signature algorithm that is compatible with
* the type of the key.
* \param[in] hash The hash whose signature is to be verified.
* \param hash_length Size of the \p hash buffer in bytes.
* \param[in] signature Buffer containing the signature to verify.
* \param signature_length Size of the \p signature buffer in bytes.
*
* \retval #PSA_SUCCESS
* The operation started successfully - call \c psa_sign_hash_complete()
* with the same context to complete the operation
* \retval #PSA_ERROR_INVALID_ARGUMENT
* An unsupported or incorrect type of key was used.
* \retval #PSA_ERROR_NOT_SUPPORTED
* Either no internal interruptible operations are currently supported,
* or the key type is currently unsupported.
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY
* There was insufficient memory either to load the key representation,
* or to prepare the operation.
*/
psa_status_t mbedtls_psa_verify_hash_start(
mbedtls_psa_verify_hash_interruptible_operation_t *operation,
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg,
const uint8_t *hash, size_t hash_length,
const uint8_t *signature, size_t signature_length);
/**
* \brief Continue and eventually complete the action of signing a hash or
* short message with a private key, in an interruptible manner.
*
* \note The signature of this function is that of a PSA driver
* sign_hash_complete entry point. This function behaves as a
* sign_hash_complete entry point as defined in the PSA driver interface
* specification for transparent drivers.
*
* \param[in] operation The \c
* mbedtls_psa_sign_hash_interruptible_operation_t
* to use. This must be initialized first.
*
* \retval #PSA_SUCCESS
* Operation completed successfully, and the passed signature is valid.
*
* \retval #PSA_OPERATION_INCOMPLETE
* Operation was interrupted due to the setting of \c
* psa_interruptible_set_max_ops(), there is still work to be done,
* please call this function again with the same operation object.
*
* \retval #PSA_ERROR_INVALID_SIGNATURE
* The calculation was performed successfully, but the passed
* signature is not a valid signature.
*
* \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
* \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
* \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
*/
psa_status_t mbedtls_psa_verify_hash_complete(
mbedtls_psa_verify_hash_interruptible_operation_t *operation);
/**
* \brief Abort a verify signed hash operation.
*
* \note The signature of this function is that of a PSA driver
* verify_hash_abort entry point. This function behaves as a
* verify_hash_abort entry point as defined in the PSA driver interface
* specification for transparent drivers.
*
* \param[in] operation The \c
* mbedtls_psa_verify_hash_interruptible_operation_t
* to abort.
*
* \retval #PSA_SUCCESS
* The operation was aborted successfully.
*/
psa_status_t mbedtls_psa_verify_hash_abort(
mbedtls_psa_verify_hash_interruptible_operation_t *operation);
typedef struct psa_crypto_local_input_s {
uint8_t *buffer;
size_t length;
} psa_crypto_local_input_t;
#define PSA_CRYPTO_LOCAL_INPUT_INIT ((psa_crypto_local_input_t) { NULL, 0 })
/** Allocate a local copy of an input buffer and copy the contents into it.
*
* \param[in] input Pointer to input buffer.
* \param[in] input_len Length of the input buffer.
* \param[out] local_input Pointer to a psa_crypto_local_input_t struct
* containing a local input copy.
* \return #PSA_SUCCESS, if the buffer was successfully
* copied.
* \return #PSA_ERROR_INSUFFICIENT_MEMORY, if a copy of
* the buffer cannot be allocated.
*/
psa_status_t psa_crypto_local_input_alloc(const uint8_t *input, size_t input_len,
psa_crypto_local_input_t *local_input);
/** Free a local copy of an input buffer.
*
* \param[in] local_input Pointer to a psa_crypto_local_input_t struct
* populated by a previous call to
* psa_crypto_local_input_alloc().
*/
void psa_crypto_local_input_free(psa_crypto_local_input_t *local_input);
typedef struct psa_crypto_local_output_s {
uint8_t *original;
uint8_t *buffer;
size_t length;
} psa_crypto_local_output_t;
#define PSA_CRYPTO_LOCAL_OUTPUT_INIT ((psa_crypto_local_output_t) { NULL, NULL, 0 })
/** Allocate a local copy of an output buffer.
*
* \note This does not copy any data from the original
* output buffer but only allocates a buffer
* whose contents will be copied back to the
* original in a future call to
* psa_crypto_local_output_free().
*
* \param[in] output Pointer to output buffer.
* \param[in] output_len Length of the output buffer.
* \param[out] local_output Pointer to a psa_crypto_local_output_t struct to
* populate with the local output copy.
* \return #PSA_SUCCESS, if the buffer was successfully
* copied.
* \return #PSA_ERROR_INSUFFICIENT_MEMORY, if a copy of
* the buffer cannot be allocated.
*/
psa_status_t psa_crypto_local_output_alloc(uint8_t *output, size_t output_len,
psa_crypto_local_output_t *local_output);
/** Copy from a local copy of an output buffer back to the original, then
* free the local copy.
*
* \param[in] local_output Pointer to a psa_crypto_local_output_t struct
* populated by a previous call to
* psa_crypto_local_output_alloc().
* \return #PSA_SUCCESS, if the local output was
* successfully copied back to the original.
* \return #PSA_ERROR_CORRUPTION_DETECTED, if the output
* could not be copied back to the original.
*/
psa_status_t psa_crypto_local_output_free(psa_crypto_local_output_t *local_output);
#endif /* PSA_CRYPTO_CORE_H */

View File

@@ -0,0 +1,52 @@
/**
* \file psa_crypto_core_common.h
*
* \brief Utility macros for internal use in the PSA cryptography core.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef PSA_CRYPTO_CORE_COMMON_H
#define PSA_CRYPTO_CORE_COMMON_H
/** Return an offset into a buffer.
*
* This is just the addition of an offset to a pointer, except that this
* function also accepts an offset of 0 into a buffer whose pointer is null.
* (`p + n` has undefined behavior when `p` is null, even when `n == 0`.
* A null pointer is a valid buffer pointer when the size is 0, for example
* as the result of `malloc(0)` on some platforms.)
*
* \param p Pointer to a buffer of at least n bytes.
* This may be \p NULL if \p n is zero.
* \param n An offset in bytes.
* \return Pointer to offset \p n in the buffer \p p.
* Note that this is only a valid pointer if the size of the
* buffer is at least \p n + 1.
*/
static inline unsigned char *psa_crypto_buffer_offset(
unsigned char *p, size_t n)
{
return p == NULL ? NULL : p + n;
}
/** Return an offset into a read-only buffer.
*
* Similar to mbedtls_buffer_offset(), but for const pointers.
*
* \param p Pointer to a buffer of at least n bytes.
* This may be \p NULL if \p n is zero.
* \param n An offset in bytes.
* \return Pointer to offset \p n in the buffer \p p.
* Note that this is only a valid pointer if the size of the
* buffer is at least \p n + 1.
*/
static inline const unsigned char *psa_crypto_buffer_offset_const(
const unsigned char *p, size_t n)
{
return p == NULL ? NULL : p + n;
}
#endif /* PSA_CRYPTO_CORE_COMMON_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,256 @@
/*
* Functions to delegate cryptographic operations to an available
* and appropriate accelerator.
* Warning: This file is now auto-generated.
*/
/* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
/* BEGIN-common headers */
#include "common.h"
#include "psa_crypto_aead.h"
#include "psa_crypto_cipher.h"
#include "psa_crypto_core.h"
#include "psa_crypto_driver_wrappers_no_static.h"
#include "psa_crypto_hash.h"
#include "psa_crypto_mac.h"
#include "psa_crypto_pake.h"
#include "psa_crypto_rsa.h"
#include "mbedtls/platform.h"
/* END-common headers */
#if defined(MBEDTLS_PSA_CRYPTO_C)
/* BEGIN-driver headers */
/* Headers for mbedtls_test opaque driver */
#if defined(PSA_CRYPTO_DRIVER_TEST)
#include "test/drivers/test_driver.h"
#endif
/* Headers for mbedtls_test transparent driver */
#if defined(PSA_CRYPTO_DRIVER_TEST)
#include "test/drivers/test_driver.h"
#endif
/* Headers for p256 transparent driver */
#if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED)
#include "../3rdparty/p256-m/p256-m_driver_entrypoints.h"
#endif
/* END-driver headers */
/* Auto-generated values depending on which drivers are registered.
* ID 0 is reserved for unallocated operations.
* ID 1 is reserved for the Mbed TLS software driver. */
/* BEGIN-driver id definition */
#define PSA_CRYPTO_MBED_TLS_DRIVER_ID (1)
#define MBEDTLS_TEST_OPAQUE_DRIVER_ID (2)
#define MBEDTLS_TEST_TRANSPARENT_DRIVER_ID (3)
#define P256_TRANSPARENT_DRIVER_ID (4)
/* END-driver id */
/* BEGIN-Common Macro definitions */
/* END-Common Macro definitions */
/* Support the 'old' SE interface when asked to */
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
/* PSA_CRYPTO_DRIVER_PRESENT is defined when either a new-style or old-style
* SE driver is present, to avoid unused argument errors at compile time. */
#ifndef PSA_CRYPTO_DRIVER_PRESENT
#define PSA_CRYPTO_DRIVER_PRESENT
#endif
#include "psa_crypto_se.h"
#endif
/** Get the key buffer size required to store the key material of a key
* associated with an opaque driver.
*
* \param[in] attributes The key attributes.
* \param[out] key_buffer_size Minimum buffer size to contain the key material
*
* \retval #PSA_SUCCESS
* The minimum size for a buffer to contain the key material has been
* returned successfully.
* \retval #PSA_ERROR_NOT_SUPPORTED
* The type and/or the size in bits of the key or the combination of
* the two is not supported.
* \retval #PSA_ERROR_INVALID_ARGUMENT
* The key is declared with a lifetime not known to us.
*/
psa_status_t psa_driver_wrapper_get_key_buffer_size(
const psa_key_attributes_t *attributes,
size_t *key_buffer_size )
{
psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );
psa_key_type_t key_type = psa_get_key_type(attributes);
size_t key_bits = psa_get_key_bits(attributes);
*key_buffer_size = 0;
switch( location )
{
#if defined(PSA_CRYPTO_DRIVER_TEST)
case PSA_CRYPTO_TEST_DRIVER_LOCATION:
#if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)
/* Emulate property 'builtin_key_size' */
if( psa_key_id_is_builtin(
MBEDTLS_SVC_KEY_ID_GET_KEY_ID(
psa_get_key_id( attributes ) ) ) )
{
*key_buffer_size = sizeof( psa_drv_slot_number_t );
return( PSA_SUCCESS );
}
#endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
*key_buffer_size = mbedtls_test_opaque_size_function( key_type,
key_bits );
return( ( *key_buffer_size != 0 ) ?
PSA_SUCCESS : PSA_ERROR_NOT_SUPPORTED );
#endif /* PSA_CRYPTO_DRIVER_TEST */
default:
(void)key_type;
(void)key_bits;
return( PSA_ERROR_INVALID_ARGUMENT );
}
}
psa_status_t psa_driver_wrapper_export_public_key(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length )
{
psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(
psa_get_key_lifetime( attributes ) );
/* Try dynamically-registered SE interface first */
#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
const psa_drv_se_t *drv;
psa_drv_se_context_t *drv_context;
if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) )
{
if( ( drv->key_management == NULL ) ||
( drv->key_management->p_export_public == NULL ) )
{
return( PSA_ERROR_NOT_SUPPORTED );
}
return( drv->key_management->p_export_public(
drv_context,
*( (psa_key_slot_number_t *)key_buffer ),
data, data_size, data_length ) );
}
#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
switch( location )
{
case PSA_KEY_LOCATION_LOCAL_STORAGE:
/* Key is stored in the slot in export representation, so
* cycle through all known transparent accelerators */
#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
#if (defined(PSA_CRYPTO_DRIVER_TEST) )
status = mbedtls_test_transparent_export_public_key
(attributes,
key_buffer,
key_buffer_size,
data,
data_size,
data_length
);
if( status != PSA_ERROR_NOT_SUPPORTED )
return( status );
#endif
#if (defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) )
status = p256_transparent_export_public_key
(attributes,
key_buffer,
key_buffer_size,
data,
data_size,
data_length
);
if( status != PSA_ERROR_NOT_SUPPORTED )
return( status );
#endif
#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
/* Fell through, meaning no accelerator supports this operation */
return( psa_export_public_key_internal( attributes,
key_buffer,
key_buffer_size,
data,
data_size,
data_length ) );
/* Add cases for opaque driver here */
#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
#if (defined(PSA_CRYPTO_DRIVER_TEST) )
case 0x7fffff:
return( mbedtls_test_opaque_export_public_key
(attributes,
key_buffer,
key_buffer_size,
data,
data_size,
data_length
));
#endif
#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
default:
/* Key is declared with a lifetime not known to us */
return( status );
}
}
psa_status_t psa_driver_wrapper_get_builtin_key(
psa_drv_slot_number_t slot_number,
psa_key_attributes_t *attributes,
uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length )
{
psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );
switch( location )
{
#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
#if (defined(PSA_CRYPTO_DRIVER_TEST) )
case 0x7fffff:
return( mbedtls_test_opaque_get_builtin_key
(slot_number,
attributes,
key_buffer,
key_buffer_size,
key_buffer_length
));
#endif
#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
default:
(void) slot_number;
(void) key_buffer;
(void) key_buffer_size;
(void) key_buffer_length;
return( PSA_ERROR_DOES_NOT_EXIST );
}
}
#endif /* MBEDTLS_PSA_CRYPTO_C */

View File

@@ -0,0 +1,31 @@
/*
* Function signatures for functionality that can be provided by
* cryptographic accelerators.
*/
/* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#ifndef PSA_CRYPTO_DRIVER_WRAPPERS_NO_STATIC_H
#define PSA_CRYPTO_DRIVER_WRAPPERS_NO_STATIC_H
#include "psa/crypto.h"
#include "psa/crypto_driver_common.h"
psa_status_t psa_driver_wrapper_export_public_key(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length);
psa_status_t psa_driver_wrapper_get_key_buffer_size(
const psa_key_attributes_t *attributes,
size_t *key_buffer_size);
psa_status_t psa_driver_wrapper_get_builtin_key(
psa_drv_slot_number_t slot_number,
psa_key_attributes_t *attributes,
uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length);
#endif /* PSA_CRYPTO_DRIVER_WRAPPERS_NO_STATIC_H */
/* End of automatically generated file. */

View File

@@ -0,0 +1,594 @@
/*
* PSA ECP layer on top of Mbed TLS crypto
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
*/
#include "common.h"
#if defined(MBEDTLS_PSA_CRYPTO_C)
#include <psa/crypto.h>
#include "psa_crypto_core.h"
#include "psa_crypto_ecp.h"
#include "psa_crypto_random_impl.h"
#include "mbedtls/psa_util.h"
#include <stdlib.h>
#include <string.h>
#include "mbedtls/platform.h"
#include <mbedtls/ecdsa.h>
#include <mbedtls/ecdh.h>
#include <mbedtls/ecp.h>
#include <mbedtls/error.h>
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)
/* Helper function to verify if the provided EC's family and key bit size are valid.
*
* Note: "bits" parameter is used both as input and output and it might be updated
* in case provided input value is not multiple of 8 ("sloppy" bits).
*/
static int check_ecc_parameters(psa_ecc_family_t family, size_t *bits)
{
switch (family) {
case PSA_ECC_FAMILY_SECP_R1:
switch (*bits) {
case 192:
case 224:
case 256:
case 384:
case 521:
return PSA_SUCCESS;
case 528:
*bits = 521;
return PSA_SUCCESS;
}
break;
case PSA_ECC_FAMILY_BRAINPOOL_P_R1:
switch (*bits) {
case 256:
case 384:
case 512:
return PSA_SUCCESS;
}
break;
case PSA_ECC_FAMILY_MONTGOMERY:
switch (*bits) {
case 448:
case 255:
return PSA_SUCCESS;
case 256:
*bits = 255;
return PSA_SUCCESS;
}
break;
case PSA_ECC_FAMILY_SECP_K1:
switch (*bits) {
case 192:
/* secp224k1 is not and will not be supported in PSA (#3541). */
case 256:
return PSA_SUCCESS;
}
break;
}
return PSA_ERROR_INVALID_ARGUMENT;
}
psa_status_t mbedtls_psa_ecp_load_representation(
psa_key_type_t type, size_t curve_bits,
const uint8_t *data, size_t data_length,
mbedtls_ecp_keypair **p_ecp)
{
mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE;
psa_status_t status;
mbedtls_ecp_keypair *ecp = NULL;
size_t curve_bytes = data_length;
int explicit_bits = (curve_bits != 0);
if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type) &&
PSA_KEY_TYPE_ECC_GET_FAMILY(type) != PSA_ECC_FAMILY_MONTGOMERY) {
/* A Weierstrass public key is represented as:
* - The byte 0x04;
* - `x_P` as a `ceiling(m/8)`-byte string, big-endian;
* - `y_P` as a `ceiling(m/8)`-byte string, big-endian.
* So its data length is 2m+1 where m is the curve size in bits.
*/
if ((data_length & 1) == 0) {
return PSA_ERROR_INVALID_ARGUMENT;
}
curve_bytes = data_length / 2;
/* Montgomery public keys are represented in compressed format, meaning
* their curve_bytes is equal to the amount of input. */
/* Private keys are represented in uncompressed private random integer
* format, meaning their curve_bytes is equal to the amount of input. */
}
if (explicit_bits) {
/* With an explicit bit-size, the data must have the matching length. */
if (curve_bytes != PSA_BITS_TO_BYTES(curve_bits)) {
return PSA_ERROR_INVALID_ARGUMENT;
}
} else {
/* We need to infer the bit-size from the data. Since the only
* information we have is the length in bytes, the value of curve_bits
* at this stage is rounded up to the nearest multiple of 8. */
curve_bits = PSA_BYTES_TO_BITS(curve_bytes);
}
/* Allocate and initialize a key representation. */
ecp = mbedtls_calloc(1, sizeof(mbedtls_ecp_keypair));
if (ecp == NULL) {
return PSA_ERROR_INSUFFICIENT_MEMORY;
}
mbedtls_ecp_keypair_init(ecp);
status = check_ecc_parameters(PSA_KEY_TYPE_ECC_GET_FAMILY(type), &curve_bits);
if (status != PSA_SUCCESS) {
goto exit;
}
/* Load the group. */
grp_id = mbedtls_ecc_group_from_psa(PSA_KEY_TYPE_ECC_GET_FAMILY(type),
curve_bits);
if (grp_id == MBEDTLS_ECP_DP_NONE) {
status = PSA_ERROR_NOT_SUPPORTED;
goto exit;
}
status = mbedtls_to_psa_error(
mbedtls_ecp_group_load(&ecp->grp, grp_id));
if (status != PSA_SUCCESS) {
goto exit;
}
/* Load the key material. */
if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) {
/* Load the public value. */
status = mbedtls_to_psa_error(
mbedtls_ecp_point_read_binary(&ecp->grp, &ecp->Q,
data,
data_length));
if (status != PSA_SUCCESS) {
goto exit;
}
/* Check that the point is on the curve. */
status = mbedtls_to_psa_error(
mbedtls_ecp_check_pubkey(&ecp->grp, &ecp->Q));
if (status != PSA_SUCCESS) {
goto exit;
}
} else {
/* Load and validate the secret value. */
status = mbedtls_to_psa_error(
mbedtls_ecp_read_key(ecp->grp.id,
ecp,
data,
data_length));
if (status != PSA_SUCCESS) {
goto exit;
}
}
*p_ecp = ecp;
exit:
if (status != PSA_SUCCESS) {
mbedtls_ecp_keypair_free(ecp);
mbedtls_free(ecp);
}
return status;
}
#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC) ||
* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) ||
* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) ||
* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) ||
* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) ||
* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) */
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \
defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)
psa_status_t mbedtls_psa_ecp_import_key(
const psa_key_attributes_t *attributes,
const uint8_t *data, size_t data_length,
uint8_t *key_buffer, size_t key_buffer_size,
size_t *key_buffer_length, size_t *bits)
{
psa_status_t status;
mbedtls_ecp_keypair *ecp = NULL;
/* Parse input */
status = mbedtls_psa_ecp_load_representation(attributes->type,
attributes->bits,
data,
data_length,
&ecp);
if (status != PSA_SUCCESS) {
goto exit;
}
if (PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->type) ==
PSA_ECC_FAMILY_MONTGOMERY) {
*bits = ecp->grp.nbits + 1;
} else {
*bits = ecp->grp.nbits;
}
/* 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->type,
ecp,
key_buffer,
key_buffer_size,
key_buffer_length);
exit:
/* Always free the PK object (will also free contained ECP context) */
mbedtls_ecp_keypair_free(ecp);
mbedtls_free(ecp);
return status;
}
psa_status_t mbedtls_psa_ecp_export_key(psa_key_type_t type,
mbedtls_ecp_keypair *ecp,
uint8_t *data,
size_t data_size,
size_t *data_length)
{
psa_status_t status;
if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) {
/* Check whether the public part is loaded */
if (mbedtls_ecp_is_zero(&ecp->Q)) {
/* Calculate the public key */
status = mbedtls_to_psa_error(
mbedtls_ecp_mul(&ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE));
if (status != PSA_SUCCESS) {
return status;
}
}
status = mbedtls_to_psa_error(
mbedtls_ecp_point_write_binary(&ecp->grp, &ecp->Q,
MBEDTLS_ECP_PF_UNCOMPRESSED,
data_length,
data,
data_size));
if (status != PSA_SUCCESS) {
memset(data, 0, data_size);
}
return status;
} else {
status = mbedtls_to_psa_error(
mbedtls_ecp_write_key_ext(ecp, data_length, data, data_size));
return status;
}
}
psa_status_t mbedtls_psa_ecp_export_public_key(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
uint8_t *data, size_t data_size, size_t *data_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_keypair *ecp = NULL;
status = mbedtls_psa_ecp_load_representation(
attributes->type, attributes->bits,
key_buffer, key_buffer_size, &ecp);
if (status != PSA_SUCCESS) {
return status;
}
status = mbedtls_psa_ecp_export_key(
PSA_KEY_TYPE_ECC_PUBLIC_KEY(
PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->type)),
ecp, data, data_size, data_length);
mbedtls_ecp_keypair_free(ecp);
mbedtls_free(ecp);
return status;
}
#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) ||
* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) ||
* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */
#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE)
psa_status_t mbedtls_psa_ecp_generate_key(
const psa_key_attributes_t *attributes,
uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length)
{
psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY(
attributes->type);
mbedtls_ecp_group_id grp_id =
mbedtls_ecc_group_from_psa(curve, attributes->bits);
if (grp_id == MBEDTLS_ECP_DP_NONE) {
return PSA_ERROR_NOT_SUPPORTED;
}
mbedtls_ecp_keypair ecp;
mbedtls_ecp_keypair_init(&ecp);
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
ret = mbedtls_ecp_group_load(&ecp.grp, grp_id);
if (ret != 0) {
goto exit;
}
ret = mbedtls_ecp_gen_privkey(&ecp.grp, &ecp.d,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE);
if (ret != 0) {
goto exit;
}
ret = mbedtls_ecp_write_key_ext(&ecp, key_buffer_length,
key_buffer, key_buffer_size);
exit:
mbedtls_ecp_keypair_free(&ecp);
return mbedtls_to_psa_error(ret);
}
#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE */
/****************************************************************/
/* ECDSA sign/verify */
/****************************************************************/
#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
psa_status_t mbedtls_psa_ecdsa_sign_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
uint8_t *signature, size_t signature_size, size_t *signature_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_keypair *ecp = NULL;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t curve_bytes;
mbedtls_mpi r, s;
status = mbedtls_psa_ecp_load_representation(attributes->type,
attributes->bits,
key_buffer,
key_buffer_size,
&ecp);
if (status != PSA_SUCCESS) {
return status;
}
curve_bytes = PSA_BITS_TO_BYTES(ecp->grp.pbits);
mbedtls_mpi_init(&r);
mbedtls_mpi_init(&s);
if (signature_size < 2 * curve_bytes) {
ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
goto cleanup;
}
if (PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) {
#if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg);
mbedtls_md_type_t md_alg = mbedtls_md_type_from_psa_alg(hash_alg);
MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_det_ext(
&ecp->grp, &r, &s,
&ecp->d, hash,
hash_length, md_alg,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE));
#else
ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
goto cleanup;
#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
} else {
(void) alg;
MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign(&ecp->grp, &r, &s, &ecp->d,
hash, hash_length,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE));
}
MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&r,
signature,
curve_bytes));
MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&s,
signature + curve_bytes,
curve_bytes));
cleanup:
mbedtls_mpi_free(&r);
mbedtls_mpi_free(&s);
if (ret == 0) {
*signature_length = 2 * curve_bytes;
}
mbedtls_ecp_keypair_free(ecp);
mbedtls_free(ecp);
return mbedtls_to_psa_error(ret);
}
psa_status_t mbedtls_psa_ecp_load_public_part(mbedtls_ecp_keypair *ecp)
{
int ret = 0;
/* Check whether the public part is loaded. If not, load it. */
if (mbedtls_ecp_is_zero(&ecp->Q)) {
ret = mbedtls_ecp_mul(&ecp->grp, &ecp->Q,
&ecp->d, &ecp->grp.G,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE);
}
return mbedtls_to_psa_error(ret);
}
psa_status_t mbedtls_psa_ecdsa_verify_hash(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
const uint8_t *signature, size_t signature_length)
{
psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
mbedtls_ecp_keypair *ecp = NULL;
size_t curve_bytes;
mbedtls_mpi r, s;
(void) alg;
status = mbedtls_psa_ecp_load_representation(attributes->type,
attributes->bits,
key_buffer,
key_buffer_size,
&ecp);
if (status != PSA_SUCCESS) {
return status;
}
curve_bytes = PSA_BITS_TO_BYTES(ecp->grp.pbits);
mbedtls_mpi_init(&r);
mbedtls_mpi_init(&s);
if (signature_length != 2 * curve_bytes) {
status = PSA_ERROR_INVALID_SIGNATURE;
goto cleanup;
}
status = mbedtls_to_psa_error(mbedtls_mpi_read_binary(&r,
signature,
curve_bytes));
if (status != PSA_SUCCESS) {
goto cleanup;
}
status = mbedtls_to_psa_error(mbedtls_mpi_read_binary(&s,
signature + curve_bytes,
curve_bytes));
if (status != PSA_SUCCESS) {
goto cleanup;
}
status = mbedtls_psa_ecp_load_public_part(ecp);
if (status != PSA_SUCCESS) {
goto cleanup;
}
status = mbedtls_to_psa_error(mbedtls_ecdsa_verify(&ecp->grp, hash,
hash_length, &ecp->Q,
&r, &s));
cleanup:
mbedtls_mpi_free(&r);
mbedtls_mpi_free(&s);
mbedtls_ecp_keypair_free(ecp);
mbedtls_free(ecp);
return status;
}
#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
/****************************************************************/
/* ECDH Key Agreement */
/****************************************************************/
#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)
psa_status_t mbedtls_psa_key_agreement_ecdh(
const psa_key_attributes_t *attributes,
const uint8_t *key_buffer, size_t key_buffer_size,
psa_algorithm_t alg, const uint8_t *peer_key, size_t peer_key_length,
uint8_t *shared_secret, size_t shared_secret_size,
size_t *shared_secret_length)
{
psa_status_t status;
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->type,
attributes->bits,
key_buffer,
key_buffer_size,
&ecp);
if (status != PSA_SUCCESS) {
return status;
}
mbedtls_ecp_keypair *their_key = NULL;
mbedtls_ecdh_context ecdh;
size_t bits = 0;
psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(ecp->grp.id, &bits);
mbedtls_ecdh_init(&ecdh);
status = mbedtls_psa_ecp_load_representation(
PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve),
bits,
peer_key,
peer_key_length,
&their_key);
if (status != PSA_SUCCESS) {
goto exit;
}
status = mbedtls_to_psa_error(
mbedtls_ecdh_get_params(&ecdh, their_key, MBEDTLS_ECDH_THEIRS));
if (status != PSA_SUCCESS) {
goto exit;
}
status = mbedtls_to_psa_error(
mbedtls_ecdh_get_params(&ecdh, ecp, MBEDTLS_ECDH_OURS));
if (status != PSA_SUCCESS) {
goto exit;
}
status = mbedtls_to_psa_error(
mbedtls_ecdh_calc_secret(&ecdh,
shared_secret_length,
shared_secret, shared_secret_size,
mbedtls_psa_get_random,
MBEDTLS_PSA_RANDOM_STATE));
if (status != PSA_SUCCESS) {
goto exit;
}
if (PSA_BITS_TO_BYTES(bits) != *shared_secret_length) {
status = PSA_ERROR_CORRUPTION_DETECTED;
}
exit:
if (status != PSA_SUCCESS) {
mbedtls_platform_zeroize(shared_secret, shared_secret_size);
}
mbedtls_ecdh_free(&ecdh);
mbedtls_ecp_keypair_free(their_key);
mbedtls_free(their_key);
mbedtls_ecp_keypair_free(ecp);
mbedtls_free(ecp);
return status;
}
#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */
#endif /* MBEDTLS_PSA_CRYPTO_C */

Some files were not shown because too many files have changed in this diff Show More