mirror of
https://github.com/Mbed-TLS/mbedtls.git
synced 2025-08-01 10:06:53 +03:00
Merge branch 'development-restricted' into mbedtls-3.5.0rc0-pr
Signed-off-by: Minos Galanakis <minos.galanakis@arm.com>
This commit is contained in:
@ -83,7 +83,7 @@ int mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi *X,
|
||||
* That is if X is negative (X_is_negative == 1), then X < Y is true and it
|
||||
* is false if X is positive (X_is_negative == 0).
|
||||
*/
|
||||
different_sign = mbedtls_ct_bool_xor(X_is_negative, Y_is_negative); // true if different sign
|
||||
different_sign = mbedtls_ct_bool_ne(X_is_negative, Y_is_negative); // true if different sign
|
||||
result = mbedtls_ct_bool_and(different_sign, X_is_negative);
|
||||
|
||||
/*
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "mbedtls/ccm.h"
|
||||
#include "mbedtls/platform_util.h"
|
||||
#include "mbedtls/error.h"
|
||||
#include "mbedtls/constant_time.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@ -532,13 +533,8 @@ static int mbedtls_ccm_compare_tags(const unsigned char *tag1,
|
||||
const unsigned char *tag2,
|
||||
size_t tag_len)
|
||||
{
|
||||
unsigned char i;
|
||||
int diff;
|
||||
|
||||
/* Check tag in "constant-time" */
|
||||
for (diff = 0, i = 0; i < tag_len; i++) {
|
||||
diff |= tag1[i] ^ tag2[i];
|
||||
}
|
||||
int diff = mbedtls_ct_memcmp(tag1, tag2, tag_len);
|
||||
|
||||
if (diff != 0) {
|
||||
return MBEDTLS_ERR_CCM_AUTH_FAILED;
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "mbedtls/chachapoly.h"
|
||||
#include "mbedtls/platform_util.h"
|
||||
#include "mbedtls/error.h"
|
||||
#include "mbedtls/constant_time.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@ -310,7 +311,6 @@ int mbedtls_chachapoly_auth_decrypt(mbedtls_chachapoly_context *ctx,
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
unsigned char check_tag[16];
|
||||
size_t i;
|
||||
int diff;
|
||||
|
||||
if ((ret = chachapoly_crypt_and_tag(ctx,
|
||||
@ -320,9 +320,7 @@ int mbedtls_chachapoly_auth_decrypt(mbedtls_chachapoly_context *ctx,
|
||||
}
|
||||
|
||||
/* Check tag in "constant-time" */
|
||||
for (diff = 0, i = 0; i < sizeof(check_tag); i++) {
|
||||
diff |= tag[i] ^ check_tag[i];
|
||||
}
|
||||
diff = mbedtls_ct_memcmp(tag, check_tag, sizeof(check_tag));
|
||||
|
||||
if (diff != 0) {
|
||||
mbedtls_platform_zeroize(output, length);
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "mbedtls/platform_util.h"
|
||||
#include "mbedtls/error.h"
|
||||
#include "mbedtls/constant_time.h"
|
||||
#include "constant_time_internal.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -268,17 +269,6 @@ int mbedtls_cipher_setup(mbedtls_cipher_context_t *ctx,
|
||||
|
||||
ctx->cipher_info = cipher_info;
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
|
||||
/*
|
||||
* Ignore possible errors caused by a cipher mode that doesn't use padding
|
||||
*/
|
||||
#if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
|
||||
(void) mbedtls_cipher_set_padding_mode(ctx, MBEDTLS_PADDING_PKCS7);
|
||||
#else
|
||||
(void) mbedtls_cipher_set_padding_mode(ctx, MBEDTLS_PADDING_NONE);
|
||||
#endif
|
||||
#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -848,7 +838,7 @@ static int get_pkcs_padding(unsigned char *input, size_t input_len,
|
||||
size_t *data_len)
|
||||
{
|
||||
size_t i, pad_idx;
|
||||
unsigned char padding_len, bad = 0;
|
||||
unsigned char padding_len;
|
||||
|
||||
if (NULL == input || NULL == data_len) {
|
||||
return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
|
||||
@ -857,18 +847,19 @@ static int get_pkcs_padding(unsigned char *input, size_t input_len,
|
||||
padding_len = input[input_len - 1];
|
||||
*data_len = input_len - padding_len;
|
||||
|
||||
/* Avoid logical || since it results in a branch */
|
||||
bad |= padding_len > input_len;
|
||||
bad |= padding_len == 0;
|
||||
mbedtls_ct_condition_t bad = mbedtls_ct_uint_gt(padding_len, input_len);
|
||||
bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_eq(padding_len, 0));
|
||||
|
||||
/* The number of bytes checked must be independent of padding_len,
|
||||
* so pick input_len, which is usually 8 or 16 (one block) */
|
||||
pad_idx = input_len - padding_len;
|
||||
for (i = 0; i < input_len; i++) {
|
||||
bad |= (input[i] ^ padding_len) * (i >= pad_idx);
|
||||
mbedtls_ct_condition_t in_padding = mbedtls_ct_uint_ge(i, pad_idx);
|
||||
mbedtls_ct_condition_t different = mbedtls_ct_uint_ne(input[i], padding_len);
|
||||
bad = mbedtls_ct_bool_or(bad, mbedtls_ct_bool_and(in_padding, different));
|
||||
}
|
||||
|
||||
return MBEDTLS_ERR_CIPHER_INVALID_PADDING * (bad != 0);
|
||||
return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING);
|
||||
}
|
||||
#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */
|
||||
|
||||
@ -891,24 +882,28 @@ static void add_one_and_zeros_padding(unsigned char *output,
|
||||
static int get_one_and_zeros_padding(unsigned char *input, size_t input_len,
|
||||
size_t *data_len)
|
||||
{
|
||||
size_t i;
|
||||
unsigned char done = 0, prev_done, bad;
|
||||
|
||||
if (NULL == input || NULL == data_len) {
|
||||
return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
|
||||
}
|
||||
|
||||
bad = 0x80;
|
||||
mbedtls_ct_condition_t in_padding = MBEDTLS_CT_TRUE;
|
||||
mbedtls_ct_condition_t bad = MBEDTLS_CT_TRUE;
|
||||
|
||||
*data_len = 0;
|
||||
for (i = input_len; i > 0; i--) {
|
||||
prev_done = done;
|
||||
done |= (input[i - 1] != 0);
|
||||
*data_len |= (i - 1) * (done != prev_done);
|
||||
bad ^= input[i - 1] * (done != prev_done);
|
||||
|
||||
for (ptrdiff_t i = (ptrdiff_t) (input_len) - 1; i >= 0; i--) {
|
||||
mbedtls_ct_condition_t is_nonzero = mbedtls_ct_bool(input[i]);
|
||||
|
||||
mbedtls_ct_condition_t hit_first_nonzero = mbedtls_ct_bool_and(is_nonzero, in_padding);
|
||||
|
||||
*data_len = mbedtls_ct_size_if(hit_first_nonzero, i, *data_len);
|
||||
|
||||
bad = mbedtls_ct_bool_if(hit_first_nonzero, mbedtls_ct_uint_ne(input[i], 0x80), bad);
|
||||
|
||||
in_padding = mbedtls_ct_bool_and(in_padding, mbedtls_ct_bool_not(is_nonzero));
|
||||
}
|
||||
|
||||
return MBEDTLS_ERR_CIPHER_INVALID_PADDING * (bad != 0);
|
||||
|
||||
return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING);
|
||||
}
|
||||
#endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */
|
||||
|
||||
@ -932,7 +927,8 @@ static int get_zeros_and_len_padding(unsigned char *input, size_t input_len,
|
||||
size_t *data_len)
|
||||
{
|
||||
size_t i, pad_idx;
|
||||
unsigned char padding_len, bad = 0;
|
||||
unsigned char padding_len;
|
||||
mbedtls_ct_condition_t bad;
|
||||
|
||||
if (NULL == input || NULL == data_len) {
|
||||
return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
|
||||
@ -942,16 +938,19 @@ static int get_zeros_and_len_padding(unsigned char *input, size_t input_len,
|
||||
*data_len = input_len - padding_len;
|
||||
|
||||
/* Avoid logical || since it results in a branch */
|
||||
bad |= padding_len > input_len;
|
||||
bad |= padding_len == 0;
|
||||
bad = mbedtls_ct_uint_gt(padding_len, input_len);
|
||||
bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_eq(padding_len, 0));
|
||||
|
||||
/* The number of bytes checked must be independent of padding_len */
|
||||
pad_idx = input_len - padding_len;
|
||||
for (i = 0; i < input_len - 1; i++) {
|
||||
bad |= input[i] * (i >= pad_idx);
|
||||
mbedtls_ct_condition_t is_padding = mbedtls_ct_uint_ge(i, pad_idx);
|
||||
mbedtls_ct_condition_t nonzero_pad_byte;
|
||||
nonzero_pad_byte = mbedtls_ct_bool_if_else_0(is_padding, mbedtls_ct_bool(input[i]));
|
||||
bad = mbedtls_ct_bool_or(bad, nonzero_pad_byte);
|
||||
}
|
||||
|
||||
return MBEDTLS_ERR_CIPHER_INVALID_PADDING * (bad != 0);
|
||||
return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING);
|
||||
}
|
||||
#endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */
|
||||
|
||||
@ -962,18 +961,14 @@ static int get_zeros_and_len_padding(unsigned char *input, size_t input_len,
|
||||
static void add_zeros_padding(unsigned char *output,
|
||||
size_t output_len, size_t data_len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = data_len; i < output_len; i++) {
|
||||
output[i] = 0x00;
|
||||
}
|
||||
memset(output + data_len, 0, output_len - data_len);
|
||||
}
|
||||
|
||||
static int get_zeros_padding(unsigned char *input, size_t input_len,
|
||||
size_t *data_len)
|
||||
{
|
||||
size_t i;
|
||||
unsigned char done = 0, prev_done;
|
||||
mbedtls_ct_condition_t done = MBEDTLS_CT_FALSE, prev_done;
|
||||
|
||||
if (NULL == input || NULL == data_len) {
|
||||
return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
|
||||
@ -982,8 +977,8 @@ static int get_zeros_padding(unsigned char *input, size_t input_len,
|
||||
*data_len = 0;
|
||||
for (i = input_len; i > 0; i--) {
|
||||
prev_done = done;
|
||||
done |= (input[i-1] != 0);
|
||||
*data_len |= i * (done != prev_done);
|
||||
done = mbedtls_ct_bool_or(done, mbedtls_ct_uint_ne(input[i-1], 0));
|
||||
*data_len = mbedtls_ct_size_if(mbedtls_ct_bool_ne(done, prev_done), i, *data_len);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1027,6 +1022,16 @@ int mbedtls_cipher_finish(mbedtls_cipher_context_t *ctx,
|
||||
|
||||
*olen = 0;
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
|
||||
/* CBC mode requires padding so we make sure a call to
|
||||
* mbedtls_cipher_set_padding_mode has been done successfully. */
|
||||
if (MBEDTLS_MODE_CBC == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {
|
||||
if (ctx->get_padding == NULL) {
|
||||
return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (MBEDTLS_MODE_CFB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||
|
||||
MBEDTLS_MODE_OFB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||
|
||||
MBEDTLS_MODE_CTR == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||
|
||||
|
@ -114,7 +114,7 @@ static int cmac_generate_subkeys(mbedtls_cipher_context_t *ctx,
|
||||
unsigned char *K1, unsigned char *K2)
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
unsigned char L[MBEDTLS_CIPHER_BLKSIZE_MAX];
|
||||
unsigned char L[MBEDTLS_CMAC_MAX_BLOCK_SIZE];
|
||||
size_t olen, block_size;
|
||||
|
||||
mbedtls_platform_zeroize(L, sizeof(L));
|
||||
@ -152,7 +152,7 @@ exit:
|
||||
* We can't use the padding option from the cipher layer, as it only works for
|
||||
* CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition.
|
||||
*/
|
||||
static void cmac_pad(unsigned char padded_block[MBEDTLS_CIPHER_BLKSIZE_MAX],
|
||||
static void cmac_pad(unsigned char padded_block[MBEDTLS_CMAC_MAX_BLOCK_SIZE],
|
||||
size_t padded_block_len,
|
||||
const unsigned char *last_block,
|
||||
size_t last_block_len)
|
||||
@ -283,9 +283,9 @@ int mbedtls_cipher_cmac_finish(mbedtls_cipher_context_t *ctx,
|
||||
{
|
||||
mbedtls_cmac_context_t *cmac_ctx;
|
||||
unsigned char *state, *last_block;
|
||||
unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX];
|
||||
unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX];
|
||||
unsigned char M_last[MBEDTLS_CIPHER_BLKSIZE_MAX];
|
||||
unsigned char K1[MBEDTLS_CMAC_MAX_BLOCK_SIZE];
|
||||
unsigned char K2[MBEDTLS_CMAC_MAX_BLOCK_SIZE];
|
||||
unsigned char M_last[MBEDTLS_CMAC_MAX_BLOCK_SIZE];
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
size_t olen, block_size;
|
||||
|
||||
@ -332,7 +332,7 @@ exit:
|
||||
mbedtls_platform_zeroize(cmac_ctx->unprocessed_block,
|
||||
sizeof(cmac_ctx->unprocessed_block));
|
||||
|
||||
mbedtls_platform_zeroize(state, MBEDTLS_CIPHER_BLKSIZE_MAX);
|
||||
mbedtls_platform_zeroize(state, MBEDTLS_CMAC_MAX_BLOCK_SIZE);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -750,8 +750,8 @@ static int cmac_test_subkeys(int verbose,
|
||||
int i, ret = 0;
|
||||
mbedtls_cipher_context_t ctx;
|
||||
const mbedtls_cipher_info_t *cipher_info;
|
||||
unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX];
|
||||
unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX];
|
||||
unsigned char K1[MBEDTLS_CMAC_MAX_BLOCK_SIZE];
|
||||
unsigned char K2[MBEDTLS_CMAC_MAX_BLOCK_SIZE];
|
||||
|
||||
cipher_info = mbedtls_cipher_info_from_type(cipher_type);
|
||||
if (cipher_info == NULL) {
|
||||
@ -845,7 +845,7 @@ static int cmac_test_wth_cipher(int verbose,
|
||||
{
|
||||
const mbedtls_cipher_info_t *cipher_info;
|
||||
int i, ret = 0;
|
||||
unsigned char output[MBEDTLS_CIPHER_BLKSIZE_MAX];
|
||||
unsigned char output[MBEDTLS_CMAC_MAX_BLOCK_SIZE];
|
||||
|
||||
cipher_info = mbedtls_cipher_info_from_type(cipher_type);
|
||||
if (cipher_info == NULL) {
|
||||
|
@ -22,6 +22,7 @@
|
||||
* might be translated to branches by some compilers on some platforms.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "common.h"
|
||||
@ -120,9 +121,56 @@ int mbedtls_ct_memcmp(const void *a,
|
||||
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)
|
||||
|
@ -429,7 +429,6 @@ static inline unsigned char mbedtls_ct_uchar_in_range_if(unsigned char low,
|
||||
return (unsigned char) (~(low_mask | high_mask)) & to;
|
||||
}
|
||||
|
||||
|
||||
/* ============================================================================
|
||||
* Everything below here is trivial wrapper functions
|
||||
*/
|
||||
@ -448,6 +447,14 @@ static inline unsigned mbedtls_ct_uint_if(mbedtls_ct_condition_t condition,
|
||||
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,
|
||||
@ -471,6 +478,12 @@ static inline unsigned mbedtls_ct_uint_if_else_0(mbedtls_ct_condition_t conditio
|
||||
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,
|
||||
@ -481,6 +494,23 @@ static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if_else_0(mbedtls_ct_conditio
|
||||
|
||||
#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)
|
||||
{
|
||||
@ -505,8 +535,8 @@ static inline mbedtls_ct_condition_t mbedtls_ct_uint_le(mbedtls_ct_uint_t x,
|
||||
return ~mbedtls_ct_uint_gt(x, y);
|
||||
}
|
||||
|
||||
static inline mbedtls_ct_condition_t mbedtls_ct_bool_xor(mbedtls_ct_condition_t x,
|
||||
mbedtls_ct_condition_t 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);
|
||||
}
|
||||
|
@ -194,11 +194,11 @@ static inline mbedtls_ct_condition_t mbedtls_ct_uint_ge(mbedtls_ct_uint_t x,
|
||||
static inline mbedtls_ct_condition_t mbedtls_ct_uint_le(mbedtls_ct_uint_t x,
|
||||
mbedtls_ct_uint_t y);
|
||||
|
||||
/** Boolean "xor" operation.
|
||||
/** Boolean not-equals operation.
|
||||
*
|
||||
* Functionally equivalent to:
|
||||
*
|
||||
* \p x ^ \p y
|
||||
* \p x != \p y
|
||||
*
|
||||
* \param x The first value to analyze.
|
||||
* \param y The second value to analyze.
|
||||
@ -206,11 +206,11 @@ static inline mbedtls_ct_condition_t mbedtls_ct_uint_le(mbedtls_ct_uint_t x,
|
||||
* \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,
|
||||
* \return MBEDTLS_CT_TRUE if \p x != \p y,
|
||||
* otherwise MBEDTLS_CT_FALSE.
|
||||
*/
|
||||
static inline mbedtls_ct_condition_t mbedtls_ct_bool_xor(mbedtls_ct_condition_t x,
|
||||
mbedtls_ct_condition_t y);
|
||||
static inline mbedtls_ct_condition_t mbedtls_ct_bool_ne(mbedtls_ct_condition_t x,
|
||||
mbedtls_ct_condition_t y);
|
||||
|
||||
/** Boolean "and" operation.
|
||||
*
|
||||
@ -291,6 +291,22 @@ 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.
|
||||
@ -327,6 +343,23 @@ static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if(mbedtls_ct_condition_t con
|
||||
*/
|
||||
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:
|
||||
@ -378,6 +411,35 @@ static inline unsigned char mbedtls_ct_uchar_in_range_if(unsigned char low,
|
||||
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
|
||||
@ -492,6 +554,37 @@ void mbedtls_ct_memcpy_offset(unsigned char *dest,
|
||||
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"
|
||||
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "mbedtls/platform.h"
|
||||
#include "mbedtls/platform_util.h"
|
||||
#include "mbedtls/error.h"
|
||||
#include "mbedtls/constant_time.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@ -601,7 +602,6 @@ int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx,
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
unsigned char check_tag[16];
|
||||
size_t i;
|
||||
int diff;
|
||||
|
||||
if ((ret = mbedtls_gcm_crypt_and_tag(ctx, MBEDTLS_GCM_DECRYPT, length,
|
||||
@ -611,9 +611,7 @@ int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx,
|
||||
}
|
||||
|
||||
/* Check tag in "constant-time" */
|
||||
for (diff = 0, i = 0; i < tag_len; i++) {
|
||||
diff |= tag[i] ^ check_tag[i];
|
||||
}
|
||||
diff = mbedtls_ct_memcmp(tag, check_tag, tag_len);
|
||||
|
||||
if (diff != 0) {
|
||||
mbedtls_platform_zeroize(output, length);
|
||||
|
@ -35,6 +35,7 @@
|
||||
#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>
|
||||
@ -333,9 +334,9 @@ int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx,
|
||||
unsigned char *output, size_t *out_len, size_t out_size)
|
||||
{
|
||||
int ret = 0;
|
||||
size_t i, olen;
|
||||
size_t olen;
|
||||
unsigned char A[KW_SEMIBLOCK_LENGTH];
|
||||
unsigned char diff, bad_padding = 0;
|
||||
int diff;
|
||||
|
||||
*out_len = 0;
|
||||
if (out_size < in_len - KW_SEMIBLOCK_LENGTH) {
|
||||
@ -420,19 +421,15 @@ int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx,
|
||||
* larger than 8, because of the type wrap around.
|
||||
*/
|
||||
padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen;
|
||||
if (padlen > 7) {
|
||||
padlen &= 7;
|
||||
ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
|
||||
}
|
||||
ret = mbedtls_ct_error_if(mbedtls_ct_uint_gt(padlen, 7),
|
||||
MBEDTLS_ERR_CIPHER_AUTH_FAILED, ret);
|
||||
padlen &= 7;
|
||||
|
||||
/* Check padding in "constant-time" */
|
||||
for (diff = 0, i = 0; i < KW_SEMIBLOCK_LENGTH; i++) {
|
||||
if (i >= KW_SEMIBLOCK_LENGTH - padlen) {
|
||||
diff |= output[*out_len - KW_SEMIBLOCK_LENGTH + i];
|
||||
} else {
|
||||
bad_padding |= output[*out_len - KW_SEMIBLOCK_LENGTH + i];
|
||||
}
|
||||
}
|
||||
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;
|
||||
@ -454,7 +451,6 @@ cleanup:
|
||||
*out_len = 0;
|
||||
}
|
||||
|
||||
mbedtls_platform_zeroize(&bad_padding, sizeof(bad_padding));
|
||||
mbedtls_platform_zeroize(&diff, sizeof(diff));
|
||||
mbedtls_platform_zeroize(A, sizeof(A));
|
||||
|
||||
|
@ -117,5 +117,14 @@ static inline mbedtls_ecp_group_id mbedtls_pk_get_group_id(const mbedtls_pk_cont
|
||||
#endif /* MBEDTLS_ECP_HAVE_CURVE25519 || MBEDTLS_ECP_DP_CURVE448 */
|
||||
#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
|
||||
|
||||
#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
|
||||
|
||||
#endif /* MBEDTLS_PK_INTERNAL_H */
|
||||
|
@ -129,18 +129,48 @@ static int pkcs12_pbe_derive_key_iv(mbedtls_asn1_buf *pbe_params, mbedtls_md_typ
|
||||
|
||||
#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 olen = 0;
|
||||
size_t finish_olen = 0;
|
||||
unsigned int padlen = 0;
|
||||
|
||||
if (pwd == NULL && pwdlen != 0) {
|
||||
return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA;
|
||||
@ -153,6 +183,19 @@ int mbedtls_pkcs12_pbe(mbedtls_asn1_buf *pbe_params, int mode,
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if ((ret = pkcs12_pbe_derive_key_iv(pbe_params, md_type, pwd, pwdlen,
|
||||
key, keylen,
|
||||
iv, mbedtls_cipher_info_get_iv_size(cipher_info))) != 0) {
|
||||
@ -171,6 +214,25 @@ int mbedtls_pkcs12_pbe(mbedtls_asn1_buf *pbe_params, int mode,
|
||||
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 */
|
||||
|
||||
if ((ret =
|
||||
mbedtls_cipher_set_iv(&cipher_ctx, iv,
|
||||
mbedtls_cipher_info_get_iv_size(cipher_info))) != 0) {
|
||||
@ -182,14 +244,16 @@ int mbedtls_pkcs12_pbe(mbedtls_asn1_buf *pbe_params, int mode,
|
||||
}
|
||||
|
||||
if ((ret = mbedtls_cipher_update(&cipher_ctx, data, len,
|
||||
output, &olen)) != 0) {
|
||||
output, output_len)) != 0) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if ((ret = mbedtls_cipher_finish(&cipher_ctx, output + olen, &olen)) != 0) {
|
||||
if ((ret = mbedtls_cipher_finish(&cipher_ctx, output + (*output_len), &finish_olen)) != 0) {
|
||||
ret = MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH;
|
||||
}
|
||||
|
||||
*output_len += finish_olen;
|
||||
|
||||
exit:
|
||||
mbedtls_platform_zeroize(key, sizeof(key));
|
||||
mbedtls_platform_zeroize(iv, sizeof(iv));
|
||||
|
@ -111,10 +111,36 @@ static int pkcs5_parse_pbkdf2_params(const mbedtls_asn1_buf *params,
|
||||
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;
|
||||
@ -122,10 +148,10 @@ int mbedtls_pkcs5_pbes2(const mbedtls_asn1_buf *pbe_params, int mode,
|
||||
mbedtls_asn1_buf salt;
|
||||
mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1;
|
||||
unsigned char key[32], iv[32];
|
||||
size_t olen = 0;
|
||||
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;
|
||||
@ -183,6 +209,19 @@ int mbedtls_pkcs5_pbes2(const mbedtls_asn1_buf *pbe_params, int mode,
|
||||
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);
|
||||
@ -202,8 +241,28 @@ int mbedtls_pkcs5_pbes2(const mbedtls_asn1_buf *pbe_params, int mode,
|
||||
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, &olen)) != 0) {
|
||||
data, datalen, output, output_len)) != 0) {
|
||||
ret = MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH;
|
||||
}
|
||||
|
||||
|
@ -1417,6 +1417,12 @@ static int pk_parse_key_pkcs8_unencrypted_der(
|
||||
#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
|
||||
return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
|
||||
|
||||
end = p + len;
|
||||
if (end != (key + keylen)) {
|
||||
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
|
||||
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1430,7 +1436,7 @@ static int pk_parse_key_pkcs8_unencrypted_der(
|
||||
*
|
||||
*/
|
||||
#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
|
||||
static int pk_parse_key_pkcs8_encrypted_der(
|
||||
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,
|
||||
@ -1445,6 +1451,7 @@ static int pk_parse_key_pkcs8_encrypted_der(
|
||||
mbedtls_cipher_type_t cipher_alg;
|
||||
mbedtls_md_type_t md_alg;
|
||||
#endif
|
||||
size_t outlen = 0;
|
||||
|
||||
p = key;
|
||||
end = p + keylen;
|
||||
@ -1490,9 +1497,9 @@ static int pk_parse_key_pkcs8_encrypted_der(
|
||||
*/
|
||||
#if defined(MBEDTLS_PKCS12_C)
|
||||
if (mbedtls_oid_get_pkcs12_pbe_alg(&pbe_alg_oid, &md_alg, &cipher_alg) == 0) {
|
||||
if ((ret = mbedtls_pkcs12_pbe(&pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT,
|
||||
cipher_alg, md_alg,
|
||||
pwd, pwdlen, p, len, buf)) != 0) {
|
||||
if ((ret = mbedtls_pkcs12_pbe_ext(&pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT,
|
||||
cipher_alg, md_alg,
|
||||
pwd, pwdlen, p, len, buf, len, &outlen)) != 0) {
|
||||
if (ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH) {
|
||||
return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
|
||||
}
|
||||
@ -1505,8 +1512,8 @@ static int pk_parse_key_pkcs8_encrypted_der(
|
||||
#endif /* MBEDTLS_PKCS12_C */
|
||||
#if defined(MBEDTLS_PKCS5_C)
|
||||
if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid) == 0) {
|
||||
if ((ret = mbedtls_pkcs5_pbes2(&pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen,
|
||||
p, len, buf)) != 0) {
|
||||
if ((ret = mbedtls_pkcs5_pbes2_ext(&pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen,
|
||||
p, len, buf, len, &outlen)) != 0) {
|
||||
if (ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH) {
|
||||
return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
|
||||
}
|
||||
@ -1524,8 +1531,7 @@ static int pk_parse_key_pkcs8_encrypted_der(
|
||||
if (decrypted == 0) {
|
||||
return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
|
||||
}
|
||||
|
||||
return pk_parse_key_pkcs8_unencrypted_der(pk, buf, len, f_rng, p_rng);
|
||||
return pk_parse_key_pkcs8_unencrypted_der(pk, buf, outlen, f_rng, p_rng);
|
||||
}
|
||||
#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
|
||||
|
||||
@ -1644,8 +1650,8 @@ int mbedtls_pk_parse_key(mbedtls_pk_context *pk,
|
||||
key, NULL, 0, &len);
|
||||
}
|
||||
if (ret == 0) {
|
||||
if ((ret = pk_parse_key_pkcs8_encrypted_der(pk, pem.buf, pem.buflen,
|
||||
pwd, pwdlen, f_rng, p_rng)) != 0) {
|
||||
if ((ret = mbedtls_pk_parse_key_pkcs8_encrypted_der(pk, pem.buf, pem.buflen,
|
||||
pwd, pwdlen, f_rng, p_rng)) != 0) {
|
||||
mbedtls_pk_free(pk);
|
||||
}
|
||||
|
||||
@ -1677,8 +1683,8 @@ int mbedtls_pk_parse_key(mbedtls_pk_context *pk,
|
||||
|
||||
memcpy(key_copy, key, keylen);
|
||||
|
||||
ret = pk_parse_key_pkcs8_encrypted_der(pk, key_copy, keylen,
|
||||
pwd, pwdlen, f_rng, p_rng);
|
||||
ret = mbedtls_pk_parse_key_pkcs8_encrypted_der(pk, key_copy, keylen,
|
||||
pwd, pwdlen, f_rng, p_rng);
|
||||
|
||||
mbedtls_zeroize_and_free(key_copy, keylen);
|
||||
}
|
||||
|
@ -158,12 +158,10 @@ static int mbedtls_ct_rsaes_pkcs1_v15_unpadding(unsigned char *input,
|
||||
* - OUTPUT_TOO_LARGE if the padding is good but the decrypted
|
||||
* plaintext does not fit in the output buffer.
|
||||
* - 0 if the padding is correct. */
|
||||
ret = -(int) mbedtls_ct_uint_if(
|
||||
ret = mbedtls_ct_error_if(
|
||||
bad,
|
||||
(unsigned) (-(MBEDTLS_ERR_RSA_INVALID_PADDING)),
|
||||
mbedtls_ct_uint_if_else_0(
|
||||
output_too_large,
|
||||
(unsigned) (-(MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE)))
|
||||
MBEDTLS_ERR_RSA_INVALID_PADDING,
|
||||
mbedtls_ct_error_if_else_0(output_too_large, MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE)
|
||||
);
|
||||
|
||||
/* If the padding is bad or the plaintext is too large, zero the
|
||||
@ -1541,7 +1539,8 @@ int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx,
|
||||
{
|
||||
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
|
||||
size_t ilen, i, pad_len;
|
||||
unsigned char *p, bad, pad_done;
|
||||
unsigned char *p;
|
||||
mbedtls_ct_condition_t bad, in_padding;
|
||||
unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
|
||||
unsigned char lhash[MBEDTLS_MD_MAX_SIZE];
|
||||
unsigned int hlen;
|
||||
@ -1601,28 +1600,26 @@ int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx,
|
||||
* Check contents, in "constant-time"
|
||||
*/
|
||||
p = buf;
|
||||
bad = 0;
|
||||
|
||||
bad |= *p++; /* First byte must be 0 */
|
||||
bad = mbedtls_ct_bool(*p++); /* First byte must be 0 */
|
||||
|
||||
p += hlen; /* Skip seed */
|
||||
|
||||
/* Check lHash */
|
||||
for (i = 0; i < hlen; i++) {
|
||||
bad |= lhash[i] ^ *p++;
|
||||
}
|
||||
bad = mbedtls_ct_bool_or(bad, mbedtls_ct_bool(mbedtls_ct_memcmp(lhash, p, hlen)));
|
||||
p += hlen;
|
||||
|
||||
/* Get zero-padding len, but always read till end of buffer
|
||||
* (minus one, for the 01 byte) */
|
||||
pad_len = 0;
|
||||
pad_done = 0;
|
||||
in_padding = MBEDTLS_CT_TRUE;
|
||||
for (i = 0; i < ilen - 2 * hlen - 2; i++) {
|
||||
pad_done |= p[i];
|
||||
pad_len += ((pad_done | (unsigned char) -pad_done) >> 7) ^ 1;
|
||||
in_padding = mbedtls_ct_bool_and(in_padding, mbedtls_ct_uint_eq(p[i], 0));
|
||||
pad_len += mbedtls_ct_uint_if_else_0(in_padding, 1);
|
||||
}
|
||||
|
||||
p += pad_len;
|
||||
bad |= *p++ ^ 0x01;
|
||||
bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_ne(*p++, 0x01));
|
||||
|
||||
/*
|
||||
* The only information "leaked" is whether the padding was correct or not
|
||||
@ -1630,7 +1627,7 @@ int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx,
|
||||
* recommendations in PKCS#1 v2.2: an opponent cannot distinguish between
|
||||
* the different error conditions.
|
||||
*/
|
||||
if (bad != 0) {
|
||||
if (bad != MBEDTLS_CT_FALSE) {
|
||||
ret = MBEDTLS_ERR_RSA_INVALID_PADDING;
|
||||
goto cleanup;
|
||||
}
|
||||
|
@ -1547,8 +1547,16 @@ int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl,
|
||||
|
||||
#if defined(MBEDTLS_SSL_SOME_SUITES_USE_STREAM)
|
||||
if (ssl_mode == MBEDTLS_SSL_MODE_STREAM) {
|
||||
if (rec->data_len < transform->maclen) {
|
||||
MBEDTLS_SSL_DEBUG_MSG(1,
|
||||
("Record too short for MAC:"
|
||||
" %" MBEDTLS_PRINTF_SIZET " < %" MBEDTLS_PRINTF_SIZET,
|
||||
rec->data_len, transform->maclen));
|
||||
return MBEDTLS_ERR_SSL_INVALID_MAC;
|
||||
}
|
||||
|
||||
/* The only supported stream cipher is "NULL",
|
||||
* so there's nothing to do here.*/
|
||||
* so there's no encryption to do here.*/
|
||||
} else
|
||||
#endif /* MBEDTLS_SSL_SOME_SUITES_USE_STREAM */
|
||||
#if defined(MBEDTLS_GCM_C) || \
|
||||
@ -2011,7 +2019,7 @@ hmac_failed_etm_enabled:
|
||||
unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD] = { 0 };
|
||||
unsigned char mac_peer[MBEDTLS_SSL_MAC_ADD] = { 0 };
|
||||
|
||||
/* If the initial value of padlen was such that
|
||||
/* For CBC+MAC, If the initial value of padlen was such that
|
||||
* data_len < maclen + padlen + 1, then padlen
|
||||
* got reset to 1, and the initial check
|
||||
* data_len >= minlen + maclen + 1
|
||||
@ -2023,6 +2031,9 @@ hmac_failed_etm_enabled:
|
||||
* subtracted either padlen + 1 (if the padding was correct)
|
||||
* or 0 (if the padding was incorrect) since then,
|
||||
* hence data_len >= maclen in any case.
|
||||
*
|
||||
* For stream ciphers, we checked above that
|
||||
* data_len >= maclen.
|
||||
*/
|
||||
rec->data_len -= transform->maclen;
|
||||
ssl_extract_add_data_from_record(add_data, &add_data_len, rec,
|
||||
|
@ -1727,7 +1727,7 @@ static int ssl_parse_server_ecdh_params(mbedtls_ssl_context *ssl,
|
||||
unsigned char *end)
|
||||
{
|
||||
uint16_t tls_id;
|
||||
uint8_t ecpoint_len;
|
||||
size_t ecpoint_len;
|
||||
mbedtls_ssl_handshake_params *handshake = ssl->handshake;
|
||||
psa_key_type_t key_type = PSA_KEY_TYPE_NONE;
|
||||
size_t ec_bits = 0;
|
||||
@ -1779,7 +1779,7 @@ static int ssl_parse_server_ecdh_params(mbedtls_ssl_context *ssl,
|
||||
return MBEDTLS_ERR_SSL_DECODE_ERROR;
|
||||
}
|
||||
|
||||
if (ecpoint_len > PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)) {
|
||||
if (ecpoint_len > sizeof(handshake->xxdh_psa_peerkey)) {
|
||||
return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
|
||||
}
|
||||
|
||||
@ -2059,7 +2059,7 @@ static int ssl_get_ecdh_params_from_cert(mbedtls_ssl_context *ssl)
|
||||
ret = mbedtls_ecp_point_write_binary(&peer_key->grp, &peer_key->Q,
|
||||
MBEDTLS_ECP_PF_UNCOMPRESSED, &olen,
|
||||
ssl->handshake->xxdh_psa_peerkey,
|
||||
MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH);
|
||||
sizeof(ssl->handshake->xxdh_psa_peerkey));
|
||||
|
||||
if (ret != 0) {
|
||||
MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ecp_point_write_binary"), ret);
|
||||
|
@ -3718,22 +3718,32 @@ static int ssl_parse_client_key_exchange(mbedtls_ssl_context *ssl)
|
||||
psa_status_t status = PSA_ERROR_GENERIC_ERROR;
|
||||
mbedtls_ssl_handshake_params *handshake = ssl->handshake;
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG(1, ("Read the peer's public key."));
|
||||
MBEDTLS_SSL_DEBUG_MSG(3, ("Read the peer's public key."));
|
||||
|
||||
/*
|
||||
* We must have at least two bytes (1 for length, at least 1 for data)
|
||||
*/
|
||||
if (buf_len < 2) {
|
||||
MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid buffer length"));
|
||||
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
|
||||
MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid buffer length: %" MBEDTLS_PRINTF_SIZET,
|
||||
buf_len));
|
||||
return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
|
||||
}
|
||||
|
||||
if (data_len < 1 || data_len > buf_len) {
|
||||
MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid data length"));
|
||||
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
|
||||
MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid data length: %" MBEDTLS_PRINTF_SIZET
|
||||
" > %" MBEDTLS_PRINTF_SIZET,
|
||||
data_len, buf_len));
|
||||
return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
|
||||
}
|
||||
|
||||
/* Store peer's ECDH public key. */
|
||||
if (data_len > sizeof(handshake->xxdh_psa_peerkey)) {
|
||||
MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid public key length: %" MBEDTLS_PRINTF_SIZET
|
||||
" > %" MBEDTLS_PRINTF_SIZET,
|
||||
data_len,
|
||||
sizeof(handshake->xxdh_psa_peerkey)));
|
||||
return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
|
||||
}
|
||||
memcpy(handshake->xxdh_psa_peerkey, p, data_len);
|
||||
handshake->xxdh_psa_peerkey_len = data_len;
|
||||
|
||||
|
@ -1516,7 +1516,13 @@ int mbedtls_ssl_tls13_read_public_xxdhe_share(mbedtls_ssl_context *ssl,
|
||||
/* Check if key size is consistent with given buffer length. */
|
||||
MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, peerkey_len);
|
||||
|
||||
/* Store peer's ECDH public key. */
|
||||
/* Store peer's ECDH/FFDH public key. */
|
||||
if (peerkey_len > sizeof(handshake->xxdh_psa_peerkey)) {
|
||||
MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid public key length: %u > %" MBEDTLS_PRINTF_SIZET,
|
||||
(unsigned) peerkey_len,
|
||||
sizeof(handshake->xxdh_psa_peerkey)));
|
||||
return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
|
||||
}
|
||||
memcpy(handshake->xxdh_psa_peerkey, p, peerkey_len);
|
||||
handshake->xxdh_psa_peerkey_len = peerkey_len;
|
||||
|
||||
|
@ -185,51 +185,107 @@ static int parse_attribute_value_string(const char *s,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_attribute_value_der_encoded(const char *s,
|
||||
int len,
|
||||
unsigned char *data,
|
||||
size_t *data_len,
|
||||
int *tag)
|
||||
/** Parse a hexstring containing a DER-encoded string.
|
||||
*
|
||||
* \param s A string of \p len bytes hexadecimal digits.
|
||||
* \param len Number of bytes to read from \p s.
|
||||
* \param data Output buffer of size \p data_size.
|
||||
* On success, it contains the payload that's DER-encoded
|
||||
* in the input (content without the tag and length).
|
||||
* If the DER tag is a string tag, the payload is guaranteed
|
||||
* not to contain null bytes.
|
||||
* \param data_size Length of the \p data buffer.
|
||||
* \param data_len On success, the length of the parsed string.
|
||||
* It is guaranteed to be less than
|
||||
* #MBEDTLS_X509_MAX_DN_NAME_SIZE.
|
||||
* \param tag The ASN.1 tag that the payload in \p data is encoded in.
|
||||
*
|
||||
* \retval 0 on success.
|
||||
* \retval #MBEDTLS_ERR_X509_INVALID_NAME if \p s does not contain
|
||||
* a valid hexstring,
|
||||
* or if the decoded hexstring is not valid DER,
|
||||
* or if the payload does not fit in \p data,
|
||||
* or if the payload is more than
|
||||
* #MBEDTLS_X509_MAX_DN_NAME_SIZE bytes,
|
||||
* of if \p *tag is an ASN.1 string tag and the payload
|
||||
* contains a null byte.
|
||||
* \retval #MBEDTLS_ERR_X509_ALLOC_FAILED on low memory.
|
||||
*/
|
||||
static int parse_attribute_value_hex_der_encoded(const char *s,
|
||||
size_t len,
|
||||
unsigned char *data,
|
||||
size_t data_size,
|
||||
size_t *data_len,
|
||||
int *tag)
|
||||
{
|
||||
const char *c = s;
|
||||
const char *end = c + len;
|
||||
unsigned char asn1_der_buf[MBEDTLS_X509_MAX_DN_NAME_SIZE];
|
||||
unsigned char *asn1_der_end;
|
||||
unsigned char *p;
|
||||
unsigned char *d = data;
|
||||
int n;
|
||||
/* Step 1: preliminary length checks. */
|
||||
/* Each byte is encoded by exactly two hexadecimal digits. */
|
||||
if (len % 2 != 0) {
|
||||
/* Odd number of hex digits */
|
||||
return MBEDTLS_ERR_X509_INVALID_NAME;
|
||||
}
|
||||
size_t const der_length = len / 2;
|
||||
if (der_length > MBEDTLS_X509_MAX_DN_NAME_SIZE + 4) {
|
||||
/* The payload would be more than MBEDTLS_X509_MAX_DN_NAME_SIZE
|
||||
* (after subtracting the ASN.1 tag and length). Reject this early
|
||||
* to avoid allocating a large intermediate buffer. */
|
||||
return MBEDTLS_ERR_X509_INVALID_NAME;
|
||||
}
|
||||
if (der_length < 1) {
|
||||
/* Avoid empty-buffer shenanigans. A valid DER encoding is never
|
||||
* empty. */
|
||||
return MBEDTLS_ERR_X509_INVALID_NAME;
|
||||
}
|
||||
|
||||
/* Converting from hexstring to raw binary so we can use asn1parse.c */
|
||||
if ((len < 5) || (*c != '#')) {
|
||||
return MBEDTLS_ERR_X509_INVALID_NAME;
|
||||
/* Step 2: Decode the hex string into an intermediate buffer. */
|
||||
unsigned char *der = mbedtls_calloc(1, der_length);
|
||||
if (der == NULL) {
|
||||
return MBEDTLS_ERR_X509_ALLOC_FAILED;
|
||||
}
|
||||
c++;
|
||||
if ((*tag = hexpair_to_int(c)) == -1) {
|
||||
return MBEDTLS_ERR_X509_INVALID_NAME;
|
||||
}
|
||||
c += 2;
|
||||
p = asn1_der_buf;
|
||||
for (p = asn1_der_buf; c < end; c += 2) {
|
||||
if ((c + 1 >= end) || (n = hexpair_to_int(c)) == -1) {
|
||||
return MBEDTLS_ERR_X509_INVALID_NAME;
|
||||
/* Beyond this point, der needs to be freed on exit. */
|
||||
for (size_t i = 0; i < der_length; i++) {
|
||||
int c = hexpair_to_int(s + 2 * i);
|
||||
if (c < 0) {
|
||||
goto error;
|
||||
}
|
||||
if (MBEDTLS_ASN1_IS_STRING_TAG(*tag) && n == 0) {
|
||||
return MBEDTLS_ERR_X509_INVALID_NAME;
|
||||
der[i] = c;
|
||||
}
|
||||
|
||||
/* Step 3: decode the DER. */
|
||||
/* We've checked that der_length >= 1 above. */
|
||||
*tag = der[0];
|
||||
unsigned char *p = der + 1;
|
||||
if (mbedtls_asn1_get_len(&p, der + der_length, data_len) != 0) {
|
||||
goto error;
|
||||
}
|
||||
/* Now p points to the first byte of the payload inside der,
|
||||
* and *data_len is the length of the payload. */
|
||||
|
||||
/* Step 4: payload validation */
|
||||
if (*data_len > MBEDTLS_X509_MAX_DN_NAME_SIZE) {
|
||||
goto error;
|
||||
}
|
||||
/* Strings must not contain null bytes. */
|
||||
if (MBEDTLS_ASN1_IS_STRING_TAG(*tag)) {
|
||||
for (size_t i = 0; i < *data_len; i++) {
|
||||
if (p[i] == 0) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
*(p++) = n;
|
||||
}
|
||||
asn1_der_end = p;
|
||||
|
||||
p = asn1_der_buf;
|
||||
if (mbedtls_asn1_get_len(&p, asn1_der_end, data_len) != 0) {
|
||||
return MBEDTLS_ERR_X509_INVALID_NAME;
|
||||
}
|
||||
|
||||
while (p < asn1_der_end) {
|
||||
*(d++) = *(p++);
|
||||
/* Step 5: output the payload. */
|
||||
if (*data_len > data_size) {
|
||||
goto error;
|
||||
}
|
||||
memcpy(data, p, *data_len);
|
||||
mbedtls_free(der);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
mbedtls_free(der);
|
||||
return MBEDTLS_ERR_X509_INVALID_NAME;
|
||||
}
|
||||
|
||||
int mbedtls_x509_string_to_names(mbedtls_asn1_named_data **head, const char *name)
|
||||
@ -273,11 +329,14 @@ int mbedtls_x509_string_to_names(mbedtls_asn1_named_data **head, const char *nam
|
||||
mbedtls_free(oid.p);
|
||||
return MBEDTLS_ERR_X509_INVALID_NAME;
|
||||
} else if (*s == '#') {
|
||||
if ((parse_ret =
|
||||
parse_attribute_value_der_encoded(s, (int) (c - s), data, &data_len,
|
||||
&tag)) != 0) {
|
||||
/* We know that c >= s (loop invariant) and c != s (in this
|
||||
* else branch), hence c - s - 1 >= 0. */
|
||||
parse_ret = parse_attribute_value_hex_der_encoded(
|
||||
s + 1, c - s - 1,
|
||||
data, sizeof(data), &data_len, &tag);
|
||||
if (parse_ret != 0) {
|
||||
mbedtls_free(oid.p);
|
||||
return MBEDTLS_ERR_X509_INVALID_NAME;
|
||||
return parse_ret;
|
||||
}
|
||||
} else {
|
||||
if (numericoid) {
|
||||
|
Reference in New Issue
Block a user