mbedtls 2.26.0

This commit is contained in:
Philippe Teuwen
2021-05-14 09:53:00 +02:00
parent 37e0ed59f2
commit 6324e2e746
187 changed files with 106114 additions and 19438 deletions

View File

@@ -20,7 +20,6 @@ add_library(pm3rrg_rdv4_mbedtls STATIC
../../common/mbedtls/des.c ../../common/mbedtls/des.c
../../common/mbedtls/ecdsa.c ../../common/mbedtls/ecdsa.c
../../common/mbedtls/md.c ../../common/mbedtls/md.c
../../common/mbedtls/md_wrap.c
../../common/mbedtls/md5.c ../../common/mbedtls/md5.c
../../common/mbedtls/oid.c ../../common/mbedtls/oid.c
../../common/mbedtls/pem.c ../../common/mbedtls/pem.c

View File

@@ -24,7 +24,6 @@ MYSRCS = \
des.c \ des.c \
ecdsa.c \ ecdsa.c \
md.c \ md.c \
md_wrap.c \
md5.c \ md5.c \
oid.c \ oid.c \
pem.c \ pem.c \

File diff suppressed because it is too large Load Diff

View File

@@ -20,31 +20,28 @@
* <https://ieeexplore.ieee.org/servlet/opac?punumber=4375278>. * <https://ieeexplore.ieee.org/servlet/opac?punumber=4375278>.
*/ */
/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. /*
* SPDX-License-Identifier: GPL-2.0 * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of Mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
#ifndef MBEDTLS_AES_H #ifndef MBEDTLS_AES_H
#define MBEDTLS_AES_H #define MBEDTLS_AES_H
#if !defined(MBEDTLS_CONFIG_FILE) #if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h" #include "mbedtls/config.h"
#else #else
#include MBEDTLS_CONFIG_FILE #include MBEDTLS_CONFIG_FILE
#endif #endif
@@ -62,7 +59,11 @@
/* Error codes in range 0x0021-0x0025 */ /* Error codes in range 0x0021-0x0025 */
#define MBEDTLS_ERR_AES_BAD_INPUT_DATA -0x0021 /**< Invalid input data. */ #define MBEDTLS_ERR_AES_BAD_INPUT_DATA -0x0021 /**< Invalid input data. */
/* MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE is deprecated and should not be used. */
#define MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE -0x0023 /**< Feature not available. For example, an unsupported AES key size. */ #define MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE -0x0023 /**< Feature not available. For example, an unsupported AES key size. */
/* MBEDTLS_ERR_AES_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_AES_HW_ACCEL_FAILED -0x0025 /**< AES hardware accelerator failed. */ #define MBEDTLS_ERR_AES_HW_ACCEL_FAILED -0x0025 /**< AES hardware accelerator failed. */
#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ #if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
@@ -81,7 +82,8 @@ extern "C" {
/** /**
* \brief The AES context-type definition. * \brief The AES context-type definition.
*/ */
typedef struct mbedtls_aes_context { typedef struct mbedtls_aes_context
{
int nr; /*!< The number of rounds. */ int nr; /*!< The number of rounds. */
uint32_t *rk; /*!< AES round keys. */ uint32_t *rk; /*!< AES round keys. */
uint32_t buf[68]; /*!< Unaligned data buffer. This buffer can uint32_t buf[68]; /*!< Unaligned data buffer. This buffer can
@@ -99,7 +101,8 @@ mbedtls_aes_context;
/** /**
* \brief The AES XTS context-type definition. * \brief The AES XTS context-type definition.
*/ */
typedef struct mbedtls_aes_xts_context { typedef struct mbedtls_aes_xts_context
{
mbedtls_aes_context crypt; /*!< The AES context to use for AES block mbedtls_aes_context crypt; /*!< The AES context to use for AES block
encryption or decryption. */ encryption or decryption. */
mbedtls_aes_context tweak; /*!< The AES context used for tweak mbedtls_aes_context tweak; /*!< The AES context used for tweak
@@ -117,16 +120,18 @@ typedef struct mbedtls_aes_xts_context {
* It must be the first API called before using * It must be the first API called before using
* the context. * the context.
* *
* \param ctx The AES context to initialize. * \param ctx The AES context to initialize. This must not be \c NULL.
*/ */
void mbedtls_aes_init(mbedtls_aes_context *ctx); void mbedtls_aes_init( mbedtls_aes_context *ctx );
/** /**
* \brief This function releases and clears the specified AES context. * \brief This function releases and clears the specified AES context.
* *
* \param ctx The AES context to clear. * \param ctx The AES context to clear.
* If this is \c NULL, this function does nothing.
* Otherwise, the context must have been at least initialized.
*/ */
void mbedtls_aes_free(mbedtls_aes_context *ctx); void mbedtls_aes_free( mbedtls_aes_context *ctx );
#if defined(MBEDTLS_CIPHER_MODE_XTS) #if defined(MBEDTLS_CIPHER_MODE_XTS)
/** /**
@@ -135,23 +140,27 @@ void mbedtls_aes_free(mbedtls_aes_context *ctx);
* It must be the first API called before using * It must be the first API called before using
* the context. * the context.
* *
* \param ctx The AES XTS context to initialize. * \param ctx The AES XTS context to initialize. This must not be \c NULL.
*/ */
void mbedtls_aes_xts_init(mbedtls_aes_xts_context *ctx); void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx );
/** /**
* \brief This function releases and clears the specified AES XTS context. * \brief This function releases and clears the specified AES XTS context.
* *
* \param ctx The AES XTS context to clear. * \param ctx The AES XTS context to clear.
* If this is \c NULL, this function does nothing.
* Otherwise, the context must have been at least initialized.
*/ */
void mbedtls_aes_xts_free(mbedtls_aes_xts_context *ctx); void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx );
#endif /* MBEDTLS_CIPHER_MODE_XTS */ #endif /* MBEDTLS_CIPHER_MODE_XTS */
/** /**
* \brief This function sets the encryption key. * \brief This function sets the encryption key.
* *
* \param ctx The AES context to which the key should be bound. * \param ctx The AES context to which the key should be bound.
* It must be initialized.
* \param key The encryption key. * \param key The encryption key.
* This must be a readable buffer of size \p keybits bits.
* \param keybits The size of data passed in bits. Valid options are: * \param keybits The size of data passed in bits. Valid options are:
* <ul><li>128 bits</li> * <ul><li>128 bits</li>
* <li>192 bits</li> * <li>192 bits</li>
@@ -160,14 +169,16 @@ void mbedtls_aes_xts_free(mbedtls_aes_xts_context *ctx);
* \return \c 0 on success. * \return \c 0 on success.
* \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
*/ */
int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key, int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
unsigned int keybits); unsigned int keybits );
/** /**
* \brief This function sets the decryption key. * \brief This function sets the decryption key.
* *
* \param ctx The AES context to which the key should be bound. * \param ctx The AES context to which the key should be bound.
* It must be initialized.
* \param key The decryption key. * \param key The decryption key.
* This must be a readable buffer of size \p keybits bits.
* \param keybits The size of data passed. Valid options are: * \param keybits The size of data passed. Valid options are:
* <ul><li>128 bits</li> * <ul><li>128 bits</li>
* <li>192 bits</li> * <li>192 bits</li>
@@ -176,8 +187,8 @@ int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key,
* \return \c 0 on success. * \return \c 0 on success.
* \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
*/ */
int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key, int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
unsigned int keybits); unsigned int keybits );
#if defined(MBEDTLS_CIPHER_MODE_XTS) #if defined(MBEDTLS_CIPHER_MODE_XTS)
/** /**
@@ -185,8 +196,10 @@ int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key,
* sets the encryption key. * sets the encryption key.
* *
* \param ctx The AES XTS context to which the key should be bound. * \param ctx The AES XTS context to which the key should be bound.
* It must be initialized.
* \param key The encryption key. This is comprised of the XTS key1 * \param key The encryption key. This is comprised of the XTS key1
* concatenated with the XTS key2. * concatenated with the XTS key2.
* This must be a readable buffer of size \p keybits bits.
* \param keybits The size of \p key passed in bits. Valid options are: * \param keybits The size of \p key passed in bits. Valid options are:
* <ul><li>256 bits (each of key1 and key2 is a 128-bit key)</li> * <ul><li>256 bits (each of key1 and key2 is a 128-bit key)</li>
* <li>512 bits (each of key1 and key2 is a 256-bit key)</li></ul> * <li>512 bits (each of key1 and key2 is a 256-bit key)</li></ul>
@@ -194,17 +207,19 @@ int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key,
* \return \c 0 on success. * \return \c 0 on success.
* \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
*/ */
int mbedtls_aes_xts_setkey_enc(mbedtls_aes_xts_context *ctx, int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx,
const unsigned char *key, const unsigned char *key,
unsigned int keybits); unsigned int keybits );
/** /**
* \brief This function prepares an XTS context for decryption and * \brief This function prepares an XTS context for decryption and
* sets the decryption key. * sets the decryption key.
* *
* \param ctx The AES XTS context to which the key should be bound. * \param ctx The AES XTS context to which the key should be bound.
* It must be initialized.
* \param key The decryption key. This is comprised of the XTS key1 * \param key The decryption key. This is comprised of the XTS key1
* concatenated with the XTS key2. * concatenated with the XTS key2.
* This must be a readable buffer of size \p keybits bits.
* \param keybits The size of \p key passed in bits. Valid options are: * \param keybits The size of \p key passed in bits. Valid options are:
* <ul><li>256 bits (each of key1 and key2 is a 128-bit key)</li> * <ul><li>256 bits (each of key1 and key2 is a 128-bit key)</li>
* <li>512 bits (each of key1 and key2 is a 256-bit key)</li></ul> * <li>512 bits (each of key1 and key2 is a 256-bit key)</li></ul>
@@ -212,9 +227,9 @@ int mbedtls_aes_xts_setkey_enc(mbedtls_aes_xts_context *ctx,
* \return \c 0 on success. * \return \c 0 on success.
* \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
*/ */
int mbedtls_aes_xts_setkey_dec(mbedtls_aes_xts_context *ctx, int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx,
const unsigned char *key, const unsigned char *key,
unsigned int keybits); unsigned int keybits );
#endif /* MBEDTLS_CIPHER_MODE_XTS */ #endif /* MBEDTLS_CIPHER_MODE_XTS */
/** /**
@@ -230,17 +245,20 @@ int mbedtls_aes_xts_setkey_dec(mbedtls_aes_xts_context *ctx,
* call to this API with the same context. * call to this API with the same context.
* *
* \param ctx The AES context to use for encryption or decryption. * \param ctx The AES context to use for encryption or decryption.
* It must be initialized and bound to a key.
* \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or
* #MBEDTLS_AES_DECRYPT. * #MBEDTLS_AES_DECRYPT.
* \param input The 16-Byte buffer holding the input data. * \param input The buffer holding the input data.
* \param output The 16-Byte buffer holding the output data. * It must be readable and at least \c 16 Bytes long.
* \param output The buffer where the output data will be written.
* It must be writeable and at least \c 16 Bytes long.
* \return \c 0 on success. * \return \c 0 on success.
*/ */
int mbedtls_aes_crypt_ecb(mbedtls_aes_context *ctx, int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
int mode, int mode,
const unsigned char input[16], const unsigned char input[16],
unsigned char output[16]); unsigned char output[16] );
#if defined(MBEDTLS_CIPHER_MODE_CBC) #if defined(MBEDTLS_CIPHER_MODE_CBC)
/** /**
@@ -256,8 +274,8 @@ int mbedtls_aes_crypt_ecb(mbedtls_aes_context *ctx,
* mbedtls_aes_setkey_enc() or mbedtls_aes_setkey_dec() must be called * mbedtls_aes_setkey_enc() or mbedtls_aes_setkey_dec() must be called
* before the first call to this API with the same context. * before the first call to this API with the same context.
* *
* \note This function operates on aligned blocks, that is, the input size * \note This function operates on full blocks, that is, the input size
* must be a multiple of the AES block size of 16 Bytes. * must be a multiple of the AES block size of \c 16 Bytes.
* *
* \note Upon exit, the content of the IV is updated so that you can * \note Upon exit, the content of the IV is updated so that you can
* call the same function again on the next * call the same function again on the next
@@ -268,24 +286,28 @@ int mbedtls_aes_crypt_ecb(mbedtls_aes_context *ctx,
* *
* *
* \param ctx The AES context to use for encryption or decryption. * \param ctx The AES context to use for encryption or decryption.
* It must be initialized and bound to a key.
* \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or
* #MBEDTLS_AES_DECRYPT. * #MBEDTLS_AES_DECRYPT.
* \param length The length of the input data in Bytes. This must be a * \param length The length of the input data in Bytes. This must be a
* multiple of the block size (16 Bytes). * multiple of the block size (\c 16 Bytes).
* \param iv Initialization vector (updated after use). * \param iv Initialization vector (updated after use).
* It must be a readable and writeable buffer of \c 16 Bytes.
* \param input The buffer holding the input data. * \param input The buffer holding the input data.
* It must be readable and of size \p length Bytes.
* \param output The buffer holding the output data. * \param output The buffer holding the output data.
* It must be writeable and of size \p length Bytes.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH * \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH
* on failure. * on failure.
*/ */
int mbedtls_aes_crypt_cbc(mbedtls_aes_context *ctx, int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
int mode, int mode,
size_t length, size_t length,
unsigned char iv[16], unsigned char iv[16],
const unsigned char *input, const unsigned char *input,
unsigned char *output); unsigned char *output );
#endif /* MBEDTLS_CIPHER_MODE_CBC */ #endif /* MBEDTLS_CIPHER_MODE_CBC */
#if defined(MBEDTLS_CIPHER_MODE_XTS) #if defined(MBEDTLS_CIPHER_MODE_XTS)
@@ -302,9 +324,10 @@ int mbedtls_aes_crypt_cbc(mbedtls_aes_context *ctx,
* returns #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH. * returns #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH.
* *
* \param ctx The AES XTS context to use for AES XTS operations. * \param ctx The AES XTS context to use for AES XTS operations.
* It must be initialized and bound to a key.
* \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or
* #MBEDTLS_AES_DECRYPT. * #MBEDTLS_AES_DECRYPT.
* \param length The length of a data unit in bytes. This can be any * \param length The length of a data unit in Bytes. This can be any
* length between 16 bytes and 2^24 bytes inclusive * length between 16 bytes and 2^24 bytes inclusive
* (between 1 and 2^20 block cipher blocks). * (between 1 and 2^20 block cipher blocks).
* \param data_unit The address of the data unit encoded as an array of 16 * \param data_unit The address of the data unit encoded as an array of 16
@@ -312,23 +335,23 @@ int mbedtls_aes_crypt_cbc(mbedtls_aes_context *ctx,
* is typically the index of the block device sector that * is typically the index of the block device sector that
* contains the data. * contains the data.
* \param input The buffer holding the input data (which is an entire * \param input The buffer holding the input data (which is an entire
* data unit). This function reads \p length bytes from \p * data unit). This function reads \p length Bytes from \p
* input. * input.
* \param output The buffer holding the output data (which is an entire * \param output The buffer holding the output data (which is an entire
* data unit). This function writes \p length bytes to \p * data unit). This function writes \p length Bytes to \p
* output. * output.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH if \p length is * \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH if \p length is
* smaller than an AES block in size (16 bytes) or if \p * smaller than an AES block in size (16 Bytes) or if \p
* length is larger than 2^20 blocks (16 MiB). * length is larger than 2^20 blocks (16 MiB).
*/ */
int mbedtls_aes_crypt_xts(mbedtls_aes_xts_context *ctx, int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx,
int mode, int mode,
size_t length, size_t length,
const unsigned char data_unit[16], const unsigned char data_unit[16],
const unsigned char *input, const unsigned char *input,
unsigned char *output); unsigned char *output );
#endif /* MBEDTLS_CIPHER_MODE_XTS */ #endif /* MBEDTLS_CIPHER_MODE_XTS */
#if defined(MBEDTLS_CIPHER_MODE_CFB) #if defined(MBEDTLS_CIPHER_MODE_CFB)
@@ -356,23 +379,28 @@ int mbedtls_aes_crypt_xts(mbedtls_aes_xts_context *ctx,
* *
* *
* \param ctx The AES context to use for encryption or decryption. * \param ctx The AES context to use for encryption or decryption.
* It must be initialized and bound to a key.
* \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or
* #MBEDTLS_AES_DECRYPT. * #MBEDTLS_AES_DECRYPT.
* \param length The length of the input data. * \param length The length of the input data in Bytes.
* \param iv_off The offset in IV (updated after use). * \param iv_off The offset in IV (updated after use).
* It must point to a valid \c size_t.
* \param iv The initialization vector (updated after use). * \param iv The initialization vector (updated after use).
* It must be a readable and writeable buffer of \c 16 Bytes.
* \param input The buffer holding the input data. * \param input The buffer holding the input data.
* It must be readable and of size \p length Bytes.
* \param output The buffer holding the output data. * \param output The buffer holding the output data.
* It must be writeable and of size \p length Bytes.
* *
* \return \c 0 on success. * \return \c 0 on success.
*/ */
int mbedtls_aes_crypt_cfb128(mbedtls_aes_context *ctx, int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx,
int mode, int mode,
size_t length, size_t length,
size_t *iv_off, size_t *iv_off,
unsigned char iv[16], unsigned char iv[16],
const unsigned char *input, const unsigned char *input,
unsigned char *output); unsigned char *output );
/** /**
* \brief This function performs an AES-CFB8 encryption or decryption * \brief This function performs an AES-CFB8 encryption or decryption
@@ -397,21 +425,25 @@ int mbedtls_aes_crypt_cfb128(mbedtls_aes_context *ctx,
* *
* *
* \param ctx The AES context to use for encryption or decryption. * \param ctx The AES context to use for encryption or decryption.
* It must be initialized and bound to a key.
* \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or
* #MBEDTLS_AES_DECRYPT * #MBEDTLS_AES_DECRYPT
* \param length The length of the input data. * \param length The length of the input data.
* \param iv The initialization vector (updated after use). * \param iv The initialization vector (updated after use).
* It must be a readable and writeable buffer of \c 16 Bytes.
* \param input The buffer holding the input data. * \param input The buffer holding the input data.
* It must be readable and of size \p length Bytes.
* \param output The buffer holding the output data. * \param output The buffer holding the output data.
* It must be writeable and of size \p length Bytes.
* *
* \return \c 0 on success. * \return \c 0 on success.
*/ */
int mbedtls_aes_crypt_cfb8(mbedtls_aes_context *ctx, int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
int mode, int mode,
size_t length, size_t length,
unsigned char iv[16], unsigned char iv[16],
const unsigned char *input, const unsigned char *input,
unsigned char *output); unsigned char *output );
#endif /*MBEDTLS_CIPHER_MODE_CFB */ #endif /*MBEDTLS_CIPHER_MODE_CFB */
#if defined(MBEDTLS_CIPHER_MODE_OFB) #if defined(MBEDTLS_CIPHER_MODE_OFB)
@@ -447,20 +479,25 @@ int mbedtls_aes_crypt_cfb8(mbedtls_aes_context *ctx,
* will compromise security. * will compromise security.
* *
* \param ctx The AES context to use for encryption or decryption. * \param ctx The AES context to use for encryption or decryption.
* It must be initialized and bound to a key.
* \param length The length of the input data. * \param length The length of the input data.
* \param iv_off The offset in IV (updated after use). * \param iv_off The offset in IV (updated after use).
* It must point to a valid \c size_t.
* \param iv The initialization vector (updated after use). * \param iv The initialization vector (updated after use).
* It must be a readable and writeable buffer of \c 16 Bytes.
* \param input The buffer holding the input data. * \param input The buffer holding the input data.
* It must be readable and of size \p length Bytes.
* \param output The buffer holding the output data. * \param output The buffer holding the output data.
* It must be writeable and of size \p length Bytes.
* *
* \return \c 0 on success. * \return \c 0 on success.
*/ */
int mbedtls_aes_crypt_ofb(mbedtls_aes_context *ctx, int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx,
size_t length, size_t length,
size_t *iv_off, size_t *iv_off,
unsigned char iv[16], unsigned char iv[16],
const unsigned char *input, const unsigned char *input,
unsigned char *output); unsigned char *output );
#endif /* MBEDTLS_CIPHER_MODE_OFB */ #endif /* MBEDTLS_CIPHER_MODE_OFB */
@@ -523,25 +560,31 @@ int mbedtls_aes_crypt_ofb(mbedtls_aes_context *ctx,
* securely discarded as soon as it's no longer needed. * securely discarded as soon as it's no longer needed.
* *
* \param ctx The AES context to use for encryption or decryption. * \param ctx The AES context to use for encryption or decryption.
* It must be initialized and bound to a key.
* \param length The length of the input data. * \param length The length of the input data.
* \param nc_off The offset in the current \p stream_block, for * \param nc_off The offset in the current \p stream_block, for
* resuming within the current cipher stream. The * resuming within the current cipher stream. The
* offset pointer should be 0 at the start of a stream. * offset pointer should be 0 at the start of a stream.
* It must point to a valid \c size_t.
* \param nonce_counter The 128-bit nonce and counter. * \param nonce_counter The 128-bit nonce and counter.
* It must be a readable-writeable buffer of \c 16 Bytes.
* \param stream_block The saved stream block for resuming. This is * \param stream_block The saved stream block for resuming. This is
* overwritten by the function. * overwritten by the function.
* It must be a readable-writeable buffer of \c 16 Bytes.
* \param input The buffer holding the input data. * \param input The buffer holding the input data.
* It must be readable and of size \p length Bytes.
* \param output The buffer holding the output data. * \param output The buffer holding the output data.
* It must be writeable and of size \p length Bytes.
* *
* \return \c 0 on success. * \return \c 0 on success.
*/ */
int mbedtls_aes_crypt_ctr(mbedtls_aes_context *ctx, int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx,
size_t length, size_t length,
size_t *nc_off, size_t *nc_off,
unsigned char nonce_counter[16], unsigned char nonce_counter[16],
unsigned char stream_block[16], unsigned char stream_block[16],
const unsigned char *input, const unsigned char *input,
unsigned char *output); unsigned char *output );
#endif /* MBEDTLS_CIPHER_MODE_CTR */ #endif /* MBEDTLS_CIPHER_MODE_CTR */
/** /**
@@ -555,9 +598,9 @@ int mbedtls_aes_crypt_ctr(mbedtls_aes_context *ctx,
* *
* \return \c 0 on success. * \return \c 0 on success.
*/ */
int mbedtls_internal_aes_encrypt(mbedtls_aes_context *ctx, int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx,
const unsigned char input[16], const unsigned char input[16],
unsigned char output[16]); unsigned char output[16] );
/** /**
* \brief Internal AES block decryption function. This is only * \brief Internal AES block decryption function. This is only
@@ -570,9 +613,9 @@ int mbedtls_internal_aes_encrypt(mbedtls_aes_context *ctx,
* *
* \return \c 0 on success. * \return \c 0 on success.
*/ */
int mbedtls_internal_aes_decrypt(mbedtls_aes_context *ctx, int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx,
const unsigned char input[16], const unsigned char input[16],
unsigned char output[16]); unsigned char output[16] );
#if !defined(MBEDTLS_DEPRECATED_REMOVED) #if !defined(MBEDTLS_DEPRECATED_REMOVED)
#if defined(MBEDTLS_DEPRECATED_WARNING) #if defined(MBEDTLS_DEPRECATED_WARNING)
@@ -584,40 +627,44 @@ int mbedtls_internal_aes_decrypt(mbedtls_aes_context *ctx,
* \brief Deprecated internal AES block encryption function * \brief Deprecated internal AES block encryption function
* without return value. * without return value.
* *
* \deprecated Superseded by mbedtls_aes_encrypt_ext() in 2.5.0. * \deprecated Superseded by mbedtls_internal_aes_encrypt()
* *
* \param ctx The AES context to use for encryption. * \param ctx The AES context to use for encryption.
* \param input Plaintext block. * \param input Plaintext block.
* \param output Output (ciphertext) block. * \param output Output (ciphertext) block.
*/ */
MBEDTLS_DEPRECATED void mbedtls_aes_encrypt(mbedtls_aes_context *ctx, MBEDTLS_DEPRECATED void mbedtls_aes_encrypt( mbedtls_aes_context *ctx,
const unsigned char input[16], const unsigned char input[16],
unsigned char output[16]); unsigned char output[16] );
/** /**
* \brief Deprecated internal AES block decryption function * \brief Deprecated internal AES block decryption function
* without return value. * without return value.
* *
* \deprecated Superseded by mbedtls_aes_decrypt_ext() in 2.5.0. * \deprecated Superseded by mbedtls_internal_aes_decrypt()
* *
* \param ctx The AES context to use for decryption. * \param ctx The AES context to use for decryption.
* \param input Ciphertext block. * \param input Ciphertext block.
* \param output Output (plaintext) block. * \param output Output (plaintext) block.
*/ */
MBEDTLS_DEPRECATED void mbedtls_aes_decrypt(mbedtls_aes_context *ctx, MBEDTLS_DEPRECATED void mbedtls_aes_decrypt( mbedtls_aes_context *ctx,
const unsigned char input[16], const unsigned char input[16],
unsigned char output[16]); unsigned char output[16] );
#undef MBEDTLS_DEPRECATED #undef MBEDTLS_DEPRECATED
#endif /* !MBEDTLS_DEPRECATED_REMOVED */ #endif /* !MBEDTLS_DEPRECATED_REMOVED */
#if defined(MBEDTLS_SELF_TEST)
/** /**
* \brief Checkup routine. * \brief Checkup routine.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return \c 1 on failure. * \return \c 1 on failure.
*/ */
int mbedtls_aes_self_test(int verbose); int mbedtls_aes_self_test( int verbose );
#endif /* MBEDTLS_SELF_TEST */
#ifdef __cplusplus #ifdef __cplusplus
} }

464
common/mbedtls/aesni.c Normal file
View File

@@ -0,0 +1,464 @@
/*
* AES-NI support functions
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* [AES-WP] http://software.intel.com/en-us/articles/intel-advanced-encryption-standard-aes-instructions-set
* [CLMUL-WP] http://software.intel.com/en-us/articles/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode/
*/
#include "common.h"
#if defined(MBEDTLS_AESNI_C)
#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
#include "mbedtls/aesni.h"
#include <string.h>
#ifndef asm
#define asm __asm
#endif
#if defined(MBEDTLS_HAVE_X86_64)
/*
* AES-NI support detection routine
*/
int mbedtls_aesni_has_support( unsigned int what )
{
static int done = 0;
static unsigned int c = 0;
if( ! done )
{
asm( "movl $1, %%eax \n\t"
"cpuid \n\t"
: "=c" (c)
:
: "eax", "ebx", "edx" );
done = 1;
}
return( ( c & what ) != 0 );
}
/*
* 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 ".byte 0x66,0x0F,0x38,0xDE,"
#define AESDECLAST ".byte 0x66,0x0F,0x38,0xDF,"
#define AESENC ".byte 0x66,0x0F,0x38,0xDC,"
#define AESENCLAST ".byte 0x66,0x0F,0x38,0xDD,"
#define AESIMC ".byte 0x66,0x0F,0x38,0xDB,"
#define AESKEYGENA ".byte 0x66,0x0F,0x3A,0xDF,"
#define PCLMULQDQ ".byte 0x66,0x0F,0x3A,0x44,"
#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 "\n\t" // 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 "\n\t" // last round
"jmp 3f \n\t"
"2: \n\t" // decryption loop
"movdqu (%1), %%xmm1 \n\t"
AESDEC xmm1_xmm0 "\n\t" // 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 "\n\t" // last round
"3: \n\t"
"movdqu %%xmm0, (%4) \n\t" // export output
:
: "r" (ctx->nr), "r" (ctx->rk), "r" (mode), "r" (input), "r" (output)
: "memory", "cc", "xmm0", "xmm1" );
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. 13).
*/
"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 \n\t" // a0*b0 = c1:c0
PCLMULQDQ xmm0_xmm2 ",0x11 \n\t" // a1*b1 = d1:d0
PCLMULQDQ xmm0_xmm3 ",0x10 \n\t" // a0*b1 = e1:e0
PCLMULQDQ xmm0_xmm4 ",0x01 \n\t" // 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. 20)
*/
"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. 20).
* 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
*/
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 "\n\t"
"movdqu %%xmm0, (%1) \n\t"
:
: "r" (fk), "r" (ik)
: "memory", "xmm0" );
memcpy( ik, fk, 16 );
}
/*
* 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 \n\tcall 1b \n\t"
AESKEYGENA xmm0_xmm1 ",0x02 \n\tcall 1b \n\t"
AESKEYGENA xmm0_xmm1 ",0x04 \n\tcall 1b \n\t"
AESKEYGENA xmm0_xmm1 ",0x08 \n\tcall 1b \n\t"
AESKEYGENA xmm0_xmm1 ",0x10 \n\tcall 1b \n\t"
AESKEYGENA xmm0_xmm1 ",0x20 \n\tcall 1b \n\t"
AESKEYGENA xmm0_xmm1 ",0x40 \n\tcall 1b \n\t"
AESKEYGENA xmm0_xmm1 ",0x80 \n\tcall 1b \n\t"
AESKEYGENA xmm0_xmm1 ",0x1B \n\tcall 1b \n\t"
AESKEYGENA xmm0_xmm1 ",0x36 \n\tcall 1b \n\t"
:
: "r" (rk), "r" (key)
: "memory", "cc", "0" );
}
/*
* Key expansion, 192-bit case
*/
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 \n\tcall 1b \n\t"
AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t"
AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t"
AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t"
AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t"
AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t"
AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t"
AESKEYGENA xmm1_xmm2 ",0x80 \n\tcall 1b \n\t"
:
: "r" (rk), "r" (key)
: "memory", "cc", "0" );
}
/*
* Key expansion, 256-bit case
*/
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 \n\t"
"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 \n\tcall 1b \n\t"
AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t"
AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t"
AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t"
AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t"
AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t"
AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t"
:
: "r" (rk), "r" (key)
: "memory", "cc", "0" );
}
/*
* 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;
case 192: aesni_setkey_enc_192( rk, key ); break;
case 256: aesni_setkey_enc_256( rk, key ); break;
default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
}
return( 0 );
}
#endif /* MBEDTLS_HAVE_X86_64 */
#endif /* MBEDTLS_AESNI_C */

136
common/mbedtls/aesni.h Normal file
View File

@@ -0,0 +1,136 @@
/**
* \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
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBEDTLS_AESNI_H
#define MBEDTLS_AESNI_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include "mbedtls/aes.h"
#define MBEDTLS_AESNI_AES 0x02000000u
#define MBEDTLS_AESNI_CLMUL 0x00000002u
#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && \
( defined(__amd64__) || defined(__x86_64__) ) && \
! defined(MBEDTLS_HAVE_X86_64)
#define MBEDTLS_HAVE_X86_64
#endif
#if defined(MBEDTLS_HAVE_X86_64)
#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
*/
int mbedtls_aesni_has_support( unsigned int what );
/**
* \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] );
/**
* \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 );
/**
* \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_HAVE_X86_64 */
#endif /* MBEDTLS_AESNI_H */

View File

@@ -1,24 +1,20 @@
/* /*
* An implementation of the ARCFOUR algorithm * An implementation of the ARCFOUR algorithm
* *
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
/* /*
* The ARCFOUR algorithm was publicly disclosed on 94/09. * The ARCFOUR algorithm was publicly disclosed on 94/09.
@@ -26,11 +22,7 @@
* http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0 * http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0
*/ */
#if !defined(MBEDTLS_CONFIG_FILE) #include "common.h"
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_ARC4_C) #if defined(MBEDTLS_ARC4_C)
@@ -50,22 +42,25 @@
#if !defined(MBEDTLS_ARC4_ALT) #if !defined(MBEDTLS_ARC4_ALT)
void mbedtls_arc4_init(mbedtls_arc4_context *ctx) { void mbedtls_arc4_init( mbedtls_arc4_context *ctx )
memset(ctx, 0, sizeof(mbedtls_arc4_context)); {
memset( ctx, 0, sizeof( mbedtls_arc4_context ) );
} }
void mbedtls_arc4_free(mbedtls_arc4_context *ctx) { void mbedtls_arc4_free( mbedtls_arc4_context *ctx )
if (ctx == NULL) {
if( ctx == NULL )
return; return;
mbedtls_platform_zeroize(ctx, sizeof(mbedtls_arc4_context)); mbedtls_platform_zeroize( ctx, sizeof( mbedtls_arc4_context ) );
} }
/* /*
* ARC4 key schedule * ARC4 key schedule
*/ */
void mbedtls_arc4_setup(mbedtls_arc4_context *ctx, const unsigned char *key, void mbedtls_arc4_setup( mbedtls_arc4_context *ctx, const unsigned char *key,
unsigned int keylen) { unsigned int keylen )
{
int i, j, a; int i, j, a;
unsigned int k; unsigned int k;
unsigned char *m; unsigned char *m;
@@ -74,16 +69,17 @@ void mbedtls_arc4_setup(mbedtls_arc4_context *ctx, const unsigned char *key,
ctx->y = 0; ctx->y = 0;
m = ctx->m; m = ctx->m;
for (i = 0; i < 256; i++) for( i = 0; i < 256; i++ )
m[i] = (unsigned char) i; m[i] = (unsigned char) i;
j = k = 0; j = k = 0;
for (i = 0; i < 256; i++, k++) { for( i = 0; i < 256; i++, k++ )
if (k >= keylen) k = 0; {
if( k >= keylen ) k = 0;
a = m[i]; a = m[i];
j = (j + a + key[k]) & 0xFF; j = ( j + a + key[k] ) & 0xFF;
m[i] = m[j]; m[i] = m[j];
m[j] = (unsigned char) a; m[j] = (unsigned char) a;
} }
@@ -92,8 +88,9 @@ void mbedtls_arc4_setup(mbedtls_arc4_context *ctx, const unsigned char *key,
/* /*
* ARC4 cipher function * ARC4 cipher function
*/ */
int mbedtls_arc4_crypt(mbedtls_arc4_context *ctx, size_t length, const unsigned char *input, int mbedtls_arc4_crypt( mbedtls_arc4_context *ctx, size_t length, const unsigned char *input,
unsigned char *output) { unsigned char *output )
{
int x, y, a, b; int x, y, a, b;
size_t i; size_t i;
unsigned char *m; unsigned char *m;
@@ -102,23 +99,22 @@ int mbedtls_arc4_crypt(mbedtls_arc4_context *ctx, size_t length, const unsigned
y = ctx->y; y = ctx->y;
m = ctx->m; m = ctx->m;
for (i = 0; i < length; i++) { for( i = 0; i < length; i++ )
x = (x + 1) & 0xFF; {
a = m[x]; x = ( x + 1 ) & 0xFF; a = m[x];
y = (y + a) & 0xFF; y = ( y + a ) & 0xFF; b = m[y];
b = m[y];
m[x] = (unsigned char) b; m[x] = (unsigned char) b;
m[y] = (unsigned char) a; m[y] = (unsigned char) a;
output[i] = (unsigned char) output[i] = (unsigned char)
(input[i] ^ m[(unsigned char)(a + b)]); ( input[i] ^ m[(unsigned char)( a + b )] );
} }
ctx->x = x; ctx->x = x;
ctx->y = y; ctx->y = y;
return (0); return( 0 );
} }
#endif /* !MBEDTLS_ARC4_ALT */ #endif /* !MBEDTLS_ARC4_ALT */
@@ -129,19 +125,22 @@ int mbedtls_arc4_crypt(mbedtls_arc4_context *ctx, size_t length, const unsigned
* *
* http://groups.google.com/group/comp.security.misc/msg/10a300c9d21afca0 * http://groups.google.com/group/comp.security.misc/msg/10a300c9d21afca0
*/ */
static const unsigned char arc4_test_key[3][8] = { static const unsigned char arc4_test_key[3][8] =
{
{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
}; };
static const unsigned char arc4_test_pt[3][8] = { static const unsigned char arc4_test_pt[3][8] =
{
{ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
{ 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 }
}; };
static const unsigned char arc4_test_ct[3][8] = { static const unsigned char arc4_test_ct[3][8] =
{
{ 0x75, 0xB7, 0x87, 0x80, 0x99, 0xE0, 0xC5, 0x96 }, { 0x75, 0xB7, 0x87, 0x80, 0x99, 0xE0, 0xC5, 0x96 },
{ 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79 }, { 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79 },
{ 0xDE, 0x18, 0x89, 0x41, 0xA3, 0x37, 0x5D, 0x3A } { 0xDE, 0x18, 0x89, 0x41, 0xA3, 0x37, 0x5D, 0x3A }
@@ -150,42 +149,45 @@ static const unsigned char arc4_test_ct[3][8] = {
/* /*
* Checkup routine * Checkup routine
*/ */
int mbedtls_arc4_self_test(int verbose) { int mbedtls_arc4_self_test( int verbose )
{
int i, ret = 0; int i, ret = 0;
unsigned char ibuf[8]; unsigned char ibuf[8];
unsigned char obuf[8]; unsigned char obuf[8];
mbedtls_arc4_context ctx; mbedtls_arc4_context ctx;
mbedtls_arc4_init(&ctx); mbedtls_arc4_init( &ctx );
for (i = 0; i < 3; i++) { for( i = 0; i < 3; i++ )
if (verbose != 0) {
mbedtls_printf(" ARC4 test #%d: ", i + 1); if( verbose != 0 )
mbedtls_printf( " ARC4 test #%d: ", i + 1 );
memcpy(ibuf, arc4_test_pt[i], 8); memcpy( ibuf, arc4_test_pt[i], 8 );
mbedtls_arc4_setup(&ctx, arc4_test_key[i], 8); mbedtls_arc4_setup( &ctx, arc4_test_key[i], 8 );
mbedtls_arc4_crypt(&ctx, 8, ibuf, obuf); mbedtls_arc4_crypt( &ctx, 8, ibuf, obuf );
if (memcmp(obuf, arc4_test_ct[i], 8) != 0) { if( memcmp( obuf, arc4_test_ct[i], 8 ) != 0 )
if (verbose != 0) {
mbedtls_printf("failed\n"); if( verbose != 0 )
mbedtls_printf( "failed\n" );
ret = 1; ret = 1;
goto exit; goto exit;
} }
if (verbose != 0) if( verbose != 0 )
mbedtls_printf("passed\n"); mbedtls_printf( "passed\n" );
} }
if (verbose != 0) if( verbose != 0 )
mbedtls_printf("\n"); mbedtls_printf( "\n" );
exit: exit:
mbedtls_arc4_free(&ctx); mbedtls_arc4_free( &ctx );
return (ret); return( ret );
} }
#endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_SELF_TEST */

View File

@@ -7,37 +7,34 @@
* security risk. We recommend considering stronger ciphers instead. * security risk. We recommend considering stronger ciphers instead.
*/ */
/* /*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of mbed TLS (https://tls.mbed.org) * limitations under the License.
* *
*/ */
#ifndef MBEDTLS_ARC4_H #ifndef MBEDTLS_ARC4_H
#define MBEDTLS_ARC4_H #define MBEDTLS_ARC4_H
#if !defined(MBEDTLS_CONFIG_FILE) #if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h" #include "mbedtls/config.h"
#else #else
#include MBEDTLS_CONFIG_FILE #include MBEDTLS_CONFIG_FILE
#endif #endif
#include <stddef.h> #include <stddef.h>
/* MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED -0x0019 /**< ARC4 hardware accelerator failed. */ #define MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED -0x0019 /**< ARC4 hardware accelerator failed. */
#ifdef __cplusplus #ifdef __cplusplus
@@ -55,7 +52,8 @@ extern "C" {
* security risk. We recommend considering stronger ciphers instead. * security risk. We recommend considering stronger ciphers instead.
* *
*/ */
typedef struct mbedtls_arc4_context { typedef struct mbedtls_arc4_context
{
int x; /*!< permutation index */ int x; /*!< permutation index */
int y; /*!< permutation index */ int y; /*!< permutation index */
unsigned char m[256]; /*!< permutation table */ unsigned char m[256]; /*!< permutation table */
@@ -76,7 +74,7 @@ mbedtls_arc4_context;
* instead. * instead.
* *
*/ */
void mbedtls_arc4_init(mbedtls_arc4_context *ctx); void mbedtls_arc4_init( mbedtls_arc4_context *ctx );
/** /**
* \brief Clear ARC4 context * \brief Clear ARC4 context
@@ -88,7 +86,7 @@ void mbedtls_arc4_init(mbedtls_arc4_context *ctx);
* instead. * instead.
* *
*/ */
void mbedtls_arc4_free(mbedtls_arc4_context *ctx); void mbedtls_arc4_free( mbedtls_arc4_context *ctx );
/** /**
* \brief ARC4 key schedule * \brief ARC4 key schedule
@@ -102,8 +100,8 @@ void mbedtls_arc4_free(mbedtls_arc4_context *ctx);
* instead. * instead.
* *
*/ */
void mbedtls_arc4_setup(mbedtls_arc4_context *ctx, const unsigned char *key, void mbedtls_arc4_setup( mbedtls_arc4_context *ctx, const unsigned char *key,
unsigned int keylen); unsigned int keylen );
/** /**
* \brief ARC4 cipher function * \brief ARC4 cipher function
@@ -120,8 +118,10 @@ void mbedtls_arc4_setup(mbedtls_arc4_context *ctx, const unsigned char *key,
* instead. * instead.
* *
*/ */
int mbedtls_arc4_crypt(mbedtls_arc4_context *ctx, size_t length, const unsigned char *input, int mbedtls_arc4_crypt( mbedtls_arc4_context *ctx, size_t length, const unsigned char *input,
unsigned char *output); unsigned char *output );
#if defined(MBEDTLS_SELF_TEST)
/** /**
* \brief Checkup routine * \brief Checkup routine
@@ -133,7 +133,9 @@ int mbedtls_arc4_crypt(mbedtls_arc4_context *ctx, size_t length, const unsigned
* instead. * instead.
* *
*/ */
int mbedtls_arc4_self_test(int verbose); int mbedtls_arc4_self_test( int verbose );
#endif /* MBEDTLS_SELF_TEST */
#ifdef __cplusplus #ifdef __cplusplus
} }

1073
common/mbedtls/aria.c Normal file

File diff suppressed because it is too large Load Diff

369
common/mbedtls/aria.h Normal file
View File

@@ -0,0 +1,369 @@
/**
* \file aria.h
*
* \brief ARIA block cipher
*
* The ARIA algorithm is a symmetric block cipher that can encrypt and
* decrypt information. It is defined by the Korean Agency for
* Technology and Standards (KATS) in <em>KS X 1213:2004</em> (in
* Korean, but see http://210.104.33.10/ARIA/index-e.html in English)
* and also described by the IETF in <em>RFC 5794</em>.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBEDTLS_ARIA_H
#define MBEDTLS_ARIA_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include <stddef.h>
#include <stdint.h>
#include "mbedtls/platform_util.h"
#define MBEDTLS_ARIA_ENCRYPT 1 /**< ARIA encryption. */
#define MBEDTLS_ARIA_DECRYPT 0 /**< ARIA decryption. */
#define MBEDTLS_ARIA_BLOCKSIZE 16 /**< ARIA block size in bytes. */
#define MBEDTLS_ARIA_MAX_ROUNDS 16 /**< Maxiumum number of rounds in ARIA. */
#define MBEDTLS_ARIA_MAX_KEYSIZE 32 /**< Maximum size of an ARIA key in bytes. */
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
#define MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( -0x005C )
#endif /* !MBEDTLS_DEPRECATED_REMOVED */
#define MBEDTLS_ERR_ARIA_BAD_INPUT_DATA -0x005C /**< Bad input data. */
#define MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH -0x005E /**< Invalid data input length. */
/* MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE is deprecated and should not be used.
*/
#define MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE -0x005A /**< Feature not available. For example, an unsupported ARIA key size. */
/* MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED -0x0058 /**< ARIA hardware accelerator failed. */
#if !defined(MBEDTLS_ARIA_ALT)
// Regular implementation
//
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief The ARIA context-type definition.
*/
typedef struct mbedtls_aria_context
{
unsigned char nr; /*!< The number of rounds (12, 14 or 16) */
/*! The ARIA round keys. */
uint32_t rk[MBEDTLS_ARIA_MAX_ROUNDS + 1][MBEDTLS_ARIA_BLOCKSIZE / 4];
}
mbedtls_aria_context;
#else /* MBEDTLS_ARIA_ALT */
#include "aria_alt.h"
#endif /* MBEDTLS_ARIA_ALT */
/**
* \brief This function initializes the specified ARIA context.
*
* It must be the first API called before using
* the context.
*
* \param ctx The ARIA context to initialize. This must not be \c NULL.
*/
void mbedtls_aria_init( mbedtls_aria_context *ctx );
/**
* \brief This function releases and clears the specified ARIA context.
*
* \param ctx The ARIA context to clear. This may be \c NULL, in which
* case this function returns immediately. If it is not \c NULL,
* it must point to an initialized ARIA context.
*/
void mbedtls_aria_free( mbedtls_aria_context *ctx );
/**
* \brief This function sets the encryption key.
*
* \param ctx The ARIA context to which the key should be bound.
* This must be initialized.
* \param key The encryption key. This must be a readable buffer
* of size \p keybits Bits.
* \param keybits The size of \p key in Bits. Valid options are:
* <ul><li>128 bits</li>
* <li>192 bits</li>
* <li>256 bits</li></ul>
*
* \return \c 0 on success.
* \return A negative error code on failure.
*/
int mbedtls_aria_setkey_enc( mbedtls_aria_context *ctx,
const unsigned char *key,
unsigned int keybits );
/**
* \brief This function sets the decryption key.
*
* \param ctx The ARIA context to which the key should be bound.
* This must be initialized.
* \param key The decryption key. This must be a readable buffer
* of size \p keybits Bits.
* \param keybits The size of data passed. Valid options are:
* <ul><li>128 bits</li>
* <li>192 bits</li>
* <li>256 bits</li></ul>
*
* \return \c 0 on success.
* \return A negative error code on failure.
*/
int mbedtls_aria_setkey_dec( mbedtls_aria_context *ctx,
const unsigned char *key,
unsigned int keybits );
/**
* \brief This function performs an ARIA single-block encryption or
* decryption operation.
*
* It performs encryption or decryption (depending on whether
* the key was set for encryption on decryption) on the input
* data buffer defined in the \p input parameter.
*
* mbedtls_aria_init(), and either mbedtls_aria_setkey_enc() or
* mbedtls_aria_setkey_dec() must be called before the first
* call to this API with the same context.
*
* \param ctx The ARIA context to use for encryption or decryption.
* This must be initialized and bound to a key.
* \param input The 16-Byte buffer holding the input data.
* \param output The 16-Byte buffer holding the output data.
* \return \c 0 on success.
* \return A negative error code on failure.
*/
int mbedtls_aria_crypt_ecb( mbedtls_aria_context *ctx,
const unsigned char input[MBEDTLS_ARIA_BLOCKSIZE],
unsigned char output[MBEDTLS_ARIA_BLOCKSIZE] );
#if defined(MBEDTLS_CIPHER_MODE_CBC)
/**
* \brief This function performs an ARIA-CBC encryption or decryption operation
* on full blocks.
*
* It performs the operation defined in the \p mode
* parameter (encrypt/decrypt), on the input data buffer defined in
* the \p input parameter.
*
* It can be called as many times as needed, until all the input
* data is processed. mbedtls_aria_init(), and either
* mbedtls_aria_setkey_enc() or mbedtls_aria_setkey_dec() must be called
* before the first call to this API with the same context.
*
* \note This function operates on aligned blocks, that is, the input size
* must be a multiple of the ARIA block size of 16 Bytes.
*
* \note Upon exit, the content of the IV is updated so that you can
* call the same function again on the next
* block(s) of data and get the same result as if it was
* encrypted in one call. This allows a "streaming" usage.
* If you need to retain the contents of the IV, you should
* either save it manually or use the cipher module instead.
*
*
* \param ctx The ARIA context to use for encryption or decryption.
* This must be initialized and bound to a key.
* \param mode The mode of operation. This must be either
* #MBEDTLS_ARIA_ENCRYPT for encryption, or
* #MBEDTLS_ARIA_DECRYPT for decryption.
* \param length The length of the input data in Bytes. This must be a
* multiple of the block size (16 Bytes).
* \param iv Initialization vector (updated after use).
* This must be a readable buffer of size 16 Bytes.
* \param input The buffer holding the input data. This must
* be a readable buffer of length \p length Bytes.
* \param output The buffer holding the output data. This must
* be a writable buffer of length \p length Bytes.
*
* \return \c 0 on success.
* \return A negative error code on failure.
*/
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 );
#endif /* MBEDTLS_CIPHER_MODE_CBC */
#if defined(MBEDTLS_CIPHER_MODE_CFB)
/**
* \brief This function performs an ARIA-CFB128 encryption or decryption
* operation.
*
* It performs the operation defined in the \p mode
* parameter (encrypt or decrypt), on the input data buffer
* defined in the \p input parameter.
*
* For CFB, you must set up the context with mbedtls_aria_setkey_enc(),
* regardless of whether you are performing an encryption or decryption
* operation, that is, regardless of the \p mode parameter. This is
* because CFB mode uses the same key schedule for encryption and
* decryption.
*
* \note Upon exit, the content of the IV is updated so that you can
* call the same function again on the next
* block(s) of data and get the same result as if it was
* encrypted in one call. This allows a "streaming" usage.
* If you need to retain the contents of the
* IV, you must either save it manually or use the cipher
* module instead.
*
*
* \param ctx The ARIA context to use for encryption or decryption.
* This must be initialized and bound to a key.
* \param mode The mode of operation. This must be either
* #MBEDTLS_ARIA_ENCRYPT for encryption, or
* #MBEDTLS_ARIA_DECRYPT for decryption.
* \param length The length of the input data \p input in Bytes.
* \param iv_off The offset in IV (updated after use).
* This must not be larger than 15.
* \param iv The initialization vector (updated after use).
* This must be a readable buffer of size 16 Bytes.
* \param input The buffer holding the input data. This must
* be a readable buffer of length \p length Bytes.
* \param output The buffer holding the output data. This must
* be a writable buffer of length \p length Bytes.
*
* \return \c 0 on success.
* \return A negative error code on failure.
*/
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 );
#endif /* MBEDTLS_CIPHER_MODE_CFB */
#if defined(MBEDTLS_CIPHER_MODE_CTR)
/**
* \brief This function performs an ARIA-CTR encryption or decryption
* operation.
*
* This function performs the operation defined in the \p mode
* parameter (encrypt/decrypt), on the input data buffer
* defined in the \p input parameter.
*
* Due to the nature of CTR, you must use the same key schedule
* for both encryption and decryption operations. Therefore, you
* must use the context initialized with mbedtls_aria_setkey_enc()
* for both #MBEDTLS_ARIA_ENCRYPT and #MBEDTLS_ARIA_DECRYPT.
*
* \warning You must never reuse a nonce value with the same key. Doing so
* would void the encryption for the two messages encrypted with
* the same nonce and key.
*
* There are two common strategies for managing nonces with CTR:
*
* 1. You can handle everything as a single message processed over
* successive calls to this function. In that case, you want to
* set \p nonce_counter and \p nc_off to 0 for the first call, and
* then preserve the values of \p nonce_counter, \p nc_off and \p
* stream_block across calls to this function as they will be
* updated by this function.
*
* With this strategy, you must not encrypt more than 2**128
* blocks of data with the same key.
*
* 2. You can encrypt separate messages by dividing the \p
* nonce_counter buffer in two areas: the first one used for a
* per-message nonce, handled by yourself, and the second one
* updated by this function internally.
*
* For example, you might reserve the first 12 bytes for the
* per-message nonce, and the last 4 bytes for internal use. In that
* case, before calling this function on a new message you need to
* set the first 12 bytes of \p nonce_counter to your chosen nonce
* value, the last 4 to 0, and \p nc_off to 0 (which will cause \p
* stream_block to be ignored). That way, you can encrypt at most
* 2**96 messages of up to 2**32 blocks each with the same key.
*
* The per-message nonce (or information sufficient to reconstruct
* it) needs to be communicated with the ciphertext and must be unique.
* The recommended way to ensure uniqueness is to use a message
* counter. An alternative is to generate random nonces, but this
* limits the number of messages that can be securely encrypted:
* for example, with 96-bit random nonces, you should not encrypt
* more than 2**32 messages with the same key.
*
* Note that for both stategies, sizes are measured in blocks and
* that an ARIA block is 16 bytes.
*
* \warning Upon return, \p stream_block contains sensitive data. Its
* content must not be written to insecure storage and should be
* securely discarded as soon as it's no longer needed.
*
* \param ctx The ARIA context to use for encryption or decryption.
* This must be initialized and bound to a key.
* \param length The length of the input data \p input in Bytes.
* \param nc_off The offset in Bytes in the current \p stream_block,
* for resuming within the current cipher stream. The
* offset pointer should be \c 0 at the start of a
* stream. This must not be larger than \c 15 Bytes.
* \param nonce_counter The 128-bit nonce and counter. This must point to
* a read/write buffer of length \c 16 bytes.
* \param stream_block The saved stream block for resuming. This must
* point to a read/write buffer of length \c 16 bytes.
* This is overwritten by the function.
* \param input The buffer holding the input data. This must
* be a readable buffer of length \p length Bytes.
* \param output The buffer holding the output data. This must
* be a writable buffer of length \p length Bytes.
*
* \return \c 0 on success.
* \return A negative error code on failure.
*/
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 );
#endif /* MBEDTLS_CIPHER_MODE_CTR */
#if defined(MBEDTLS_SELF_TEST)
/**
* \brief Checkup routine.
*
* \return \c 0 on success, or \c 1 on failure.
*/
int mbedtls_aria_self_test( int verbose );
#endif /* MBEDTLS_SELF_TEST */
#ifdef __cplusplus
}
#endif
#endif /* aria.h */

View File

@@ -4,30 +4,26 @@
* \brief Generic ASN.1 parsing * \brief Generic ASN.1 parsing
*/ */
/* /*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
#ifndef MBEDTLS_ASN1_H #ifndef MBEDTLS_ASN1_H
#define MBEDTLS_ASN1_H #define MBEDTLS_ASN1_H
#if !defined(MBEDTLS_CONFIG_FILE) #if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h" #include "mbedtls/config.h"
#else #else
#include MBEDTLS_CONFIG_FILE #include MBEDTLS_CONFIG_FILE
#endif #endif
@@ -35,7 +31,7 @@
#include <stddef.h> #include <stddef.h>
#if defined(MBEDTLS_BIGNUM_C) #if defined(MBEDTLS_BIGNUM_C)
#include "bignum.h" #include "mbedtls/bignum.h"
#endif #endif
/** /**
@@ -54,7 +50,7 @@
#define MBEDTLS_ERR_ASN1_UNEXPECTED_TAG -0x0062 /**< ASN1 tag was of an unexpected value. */ #define MBEDTLS_ERR_ASN1_UNEXPECTED_TAG -0x0062 /**< ASN1 tag was of an unexpected value. */
#define MBEDTLS_ERR_ASN1_INVALID_LENGTH -0x0064 /**< Error when trying to determine the length or invalid length. */ #define MBEDTLS_ERR_ASN1_INVALID_LENGTH -0x0064 /**< Error when trying to determine the length or invalid length. */
#define MBEDTLS_ERR_ASN1_LENGTH_MISMATCH -0x0066 /**< Actual length differs from expected length. */ #define MBEDTLS_ERR_ASN1_LENGTH_MISMATCH -0x0066 /**< Actual length differs from expected length. */
#define MBEDTLS_ERR_ASN1_INVALID_DATA -0x0068 /**< Data is invalid. (not used) */ #define MBEDTLS_ERR_ASN1_INVALID_DATA -0x0068 /**< Data is invalid. */
#define MBEDTLS_ERR_ASN1_ALLOC_FAILED -0x006A /**< Memory allocation failed */ #define MBEDTLS_ERR_ASN1_ALLOC_FAILED -0x006A /**< Memory allocation failed */
#define MBEDTLS_ERR_ASN1_BUF_TOO_SMALL -0x006C /**< Buffer too small when writing ASN.1 data structure. */ #define MBEDTLS_ERR_ASN1_BUF_TOO_SMALL -0x006C /**< Buffer too small when writing ASN.1 data structure. */
@@ -77,6 +73,7 @@
#define MBEDTLS_ASN1_OCTET_STRING 0x04 #define MBEDTLS_ASN1_OCTET_STRING 0x04
#define MBEDTLS_ASN1_NULL 0x05 #define MBEDTLS_ASN1_NULL 0x05
#define MBEDTLS_ASN1_OID 0x06 #define MBEDTLS_ASN1_OID 0x06
#define MBEDTLS_ASN1_ENUMERATED 0x0A
#define MBEDTLS_ASN1_UTF8_STRING 0x0C #define MBEDTLS_ASN1_UTF8_STRING 0x0C
#define MBEDTLS_ASN1_SEQUENCE 0x10 #define MBEDTLS_ASN1_SEQUENCE 0x10
#define MBEDTLS_ASN1_SET 0x11 #define MBEDTLS_ASN1_SET 0x11
@@ -91,6 +88,18 @@
#define MBEDTLS_ASN1_CONSTRUCTED 0x20 #define MBEDTLS_ASN1_CONSTRUCTED 0x20
#define MBEDTLS_ASN1_CONTEXT_SPECIFIC 0x80 #define MBEDTLS_ASN1_CONTEXT_SPECIFIC 0x80
/* Slightly smaller way to check if tag is a string tag
* compared to canonical implementation. */
#define MBEDTLS_ASN1_IS_STRING_TAG( tag ) \
( ( tag ) < 32u && ( \
( ( 1u << ( tag ) ) & ( ( 1u << MBEDTLS_ASN1_BMP_STRING ) | \
( 1u << MBEDTLS_ASN1_UTF8_STRING ) | \
( 1u << MBEDTLS_ASN1_T61_STRING ) | \
( 1u << MBEDTLS_ASN1_IA5_STRING ) | \
( 1u << MBEDTLS_ASN1_UNIVERSAL_STRING ) | \
( 1u << MBEDTLS_ASN1_PRINTABLE_STRING ) | \
( 1u << MBEDTLS_ASN1_BIT_STRING ) ) ) != 0 ) )
/* /*
* Bit masks for each of the components of an ASN.1 tag as specified in * Bit masks for each of the components of an ASN.1 tag as specified in
* ITU X.690 (08/2015), section 8.1 "General rules for encoding", * ITU X.690 (08/2015), section 8.1 "General rules for encoding",
@@ -118,8 +127,12 @@
* 'unsigned char *oid' here! * 'unsigned char *oid' here!
*/ */
#define MBEDTLS_OID_CMP(oid_str, oid_buf) \ #define MBEDTLS_OID_CMP(oid_str, oid_buf) \
( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf)->len ) || \ ( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf)->len ) || \
memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) != 0 ) memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) != 0 )
#define MBEDTLS_OID_CMP_RAW(oid_str, oid_buf, oid_buf_len) \
( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf_len) ) || \
memcmp( (oid_str), (oid_buf), (oid_buf_len) ) != 0 )
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@@ -133,7 +146,8 @@ extern "C" {
/** /**
* Type-length-value structure that allows for ASN1 using DER. * Type-length-value structure that allows for ASN1 using DER.
*/ */
typedef struct mbedtls_asn1_buf { typedef struct mbedtls_asn1_buf
{
int tag; /**< ASN1 type, e.g. MBEDTLS_ASN1_UTF8_STRING. */ int tag; /**< ASN1 type, e.g. MBEDTLS_ASN1_UTF8_STRING. */
size_t len; /**< ASN1 length, in octets. */ size_t len; /**< ASN1 length, in octets. */
unsigned char *p; /**< ASN1 data, e.g. in ASCII. */ unsigned char *p; /**< ASN1 data, e.g. in ASCII. */
@@ -143,7 +157,8 @@ mbedtls_asn1_buf;
/** /**
* Container for ASN1 bit strings. * Container for ASN1 bit strings.
*/ */
typedef struct mbedtls_asn1_bitstring { typedef struct mbedtls_asn1_bitstring
{
size_t len; /**< ASN1 length, in octets. */ size_t len; /**< ASN1 length, in octets. */
unsigned char unused_bits; /**< Number of unused bits at the end of the string */ unsigned char unused_bits; /**< Number of unused bits at the end of the string */
unsigned char *p; /**< Raw ASN1 data for the bit string */ unsigned char *p; /**< Raw ASN1 data for the bit string */
@@ -153,7 +168,8 @@ mbedtls_asn1_bitstring;
/** /**
* Container for a sequence of ASN.1 items * Container for a sequence of ASN.1 items
*/ */
typedef struct mbedtls_asn1_sequence { typedef struct mbedtls_asn1_sequence
{
mbedtls_asn1_buf buf; /**< Buffer containing the given ASN.1 item. */ mbedtls_asn1_buf buf; /**< Buffer containing the given ASN.1 item. */
struct mbedtls_asn1_sequence *next; /**< The next entry in the sequence. */ struct mbedtls_asn1_sequence *next; /**< The next entry in the sequence. */
} }
@@ -162,7 +178,8 @@ mbedtls_asn1_sequence;
/** /**
* Container for a sequence or list of 'named' ASN.1 data items * Container for a sequence or list of 'named' ASN.1 data items
*/ */
typedef struct mbedtls_asn1_named_data { typedef struct mbedtls_asn1_named_data
{
mbedtls_asn1_buf oid; /**< The object identifier. */ mbedtls_asn1_buf oid; /**< The object identifier. */
mbedtls_asn1_buf val; /**< The named value. */ mbedtls_asn1_buf val; /**< The named value. */
struct mbedtls_asn1_named_data *next; /**< The next entry in the sequence. */ struct mbedtls_asn1_named_data *next; /**< The next entry in the sequence. */
@@ -174,119 +191,342 @@ mbedtls_asn1_named_data;
* \brief Get the length of an ASN.1 element. * \brief Get the length of an ASN.1 element.
* Updates the pointer to immediately behind the length. * Updates the pointer to immediately behind the length.
* *
* \param p The position in the ASN.1 data * \param p On entry, \c *p points to the first byte of the length,
* \param end End of data * i.e. immediately after the tag.
* \param len The variable that will receive the value * On successful completion, \c *p points to the first byte
* after the length, i.e. the first byte of the content.
* On error, the value of \c *p is undefined.
* \param end End of data.
* \param len On successful completion, \c *len contains the length
* read from the ASN.1 input.
* *
* \return 0 if successful, MBEDTLS_ERR_ASN1_OUT_OF_DATA on reaching * \return 0 if successful.
* end of data, MBEDTLS_ERR_ASN1_INVALID_LENGTH if length is * \return #MBEDTLS_ERR_ASN1_OUT_OF_DATA if the ASN.1 element
* unparseable. * would end beyond \p end.
* \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparseable.
*/ */
int mbedtls_asn1_get_len(unsigned char **p, int mbedtls_asn1_get_len( unsigned char **p,
const unsigned char *end, const unsigned char *end,
size_t *len); size_t *len );
/** /**
* \brief Get the tag and length of the tag. Check for the requested tag. * \brief Get the tag and length of the element.
* Check for the requested tag.
* Updates the pointer to immediately behind the tag and length. * Updates the pointer to immediately behind the tag and length.
* *
* \param p The position in the ASN.1 data * \param p On entry, \c *p points to the start of the ASN.1 element.
* \param end End of data * On successful completion, \c *p points to the first byte
* \param len The variable that will receive the length * after the length, i.e. the first byte of the content.
* \param tag The expected tag * On error, the value of \c *p is undefined.
* \param end End of data.
* \param len On successful completion, \c *len contains the length
* read from the ASN.1 input.
* \param tag The expected tag.
* *
* \return 0 if successful, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if tag did * \return 0 if successful.
* not match requested tag, or another specific ASN.1 error code. * \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the data does not start
* with the requested tag.
* \return #MBEDTLS_ERR_ASN1_OUT_OF_DATA if the ASN.1 element
* would end beyond \p end.
* \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparseable.
*/ */
int mbedtls_asn1_get_tag(unsigned char **p, int mbedtls_asn1_get_tag( unsigned char **p,
const unsigned char *end, const unsigned char *end,
size_t *len, int tag); size_t *len, int tag );
/** /**
* \brief Retrieve a boolean ASN.1 tag and its value. * \brief Retrieve a boolean ASN.1 tag and its value.
* Updates the pointer to immediately behind the full tag. * Updates the pointer to immediately behind the full tag.
* *
* \param p The position in the ASN.1 data * \param p On entry, \c *p points to the start of the ASN.1 element.
* \param end End of data * On successful completion, \c *p points to the first byte
* \param val The variable that will receive the value * beyond the ASN.1 element.
* On error, the value of \c *p is undefined.
* \param end End of data.
* \param val On success, the parsed value (\c 0 or \c 1).
* *
* \return 0 if successful or a specific ASN.1 error code. * \return 0 if successful.
* \return An ASN.1 error code if the input does not start with
* a valid ASN.1 BOOLEAN.
*/ */
int mbedtls_asn1_get_bool(unsigned char **p, int mbedtls_asn1_get_bool( unsigned char **p,
const unsigned char *end, const unsigned char *end,
int *val); int *val );
/** /**
* \brief Retrieve an integer ASN.1 tag and its value. * \brief Retrieve an integer ASN.1 tag and its value.
* Updates the pointer to immediately behind the full tag. * Updates the pointer to immediately behind the full tag.
* *
* \param p The position in the ASN.1 data * \param p On entry, \c *p points to the start of the ASN.1 element.
* \param end End of data * On successful completion, \c *p points to the first byte
* \param val The variable that will receive the value * beyond the ASN.1 element.
* On error, the value of \c *p is undefined.
* \param end End of data.
* \param val On success, the parsed value.
* *
* \return 0 if successful or a specific ASN.1 error code. * \return 0 if successful.
* \return An ASN.1 error code if the input does not start with
* a valid ASN.1 INTEGER.
* \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does
* not fit in an \c int.
*/ */
int mbedtls_asn1_get_int(unsigned char **p, int mbedtls_asn1_get_int( unsigned char **p,
const unsigned char *end, const unsigned char *end,
int *val); int *val );
/**
* \brief Retrieve an enumerated ASN.1 tag and its value.
* Updates the pointer to immediately behind the full tag.
*
* \param p On entry, \c *p points to the start of the ASN.1 element.
* On successful completion, \c *p points to the first byte
* beyond the ASN.1 element.
* On error, the value of \c *p is undefined.
* \param end End of data.
* \param val On success, the parsed value.
*
* \return 0 if successful.
* \return An ASN.1 error code if the input does not start with
* a valid ASN.1 ENUMERATED.
* \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does
* not fit in an \c int.
*/
int mbedtls_asn1_get_enum( unsigned char **p,
const unsigned char *end,
int *val );
/** /**
* \brief Retrieve a bitstring ASN.1 tag and its value. * \brief Retrieve a bitstring ASN.1 tag and its value.
* Updates the pointer to immediately behind the full tag. * Updates the pointer to immediately behind the full tag.
* *
* \param p The position in the ASN.1 data * \param p On entry, \c *p points to the start of the ASN.1 element.
* \param end End of data * On successful completion, \c *p is equal to \p end.
* \param bs The variable that will receive the value * On error, the value of \c *p is undefined.
* \param end End of data.
* \param bs On success, ::mbedtls_asn1_bitstring information about
* the parsed value.
* *
* \return 0 if successful or a specific ASN.1 error code. * \return 0 if successful.
* \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input contains
* extra data after a valid BIT STRING.
* \return An ASN.1 error code if the input does not start with
* a valid ASN.1 BIT STRING.
*/ */
int mbedtls_asn1_get_bitstring(unsigned char **p, const unsigned char *end, int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end,
mbedtls_asn1_bitstring *bs); mbedtls_asn1_bitstring *bs );
/** /**
* \brief Retrieve a bitstring ASN.1 tag without unused bits and its * \brief Retrieve a bitstring ASN.1 tag without unused bits and its
* value. * value.
* Updates the pointer to the beginning of the bit/octet string. * Updates the pointer to the beginning of the bit/octet string.
* *
* \param p The position in the ASN.1 data * \param p On entry, \c *p points to the start of the ASN.1 element.
* \param end End of data * On successful completion, \c *p points to the first byte
* \param len Length of the actual bit/octect string in bytes * of the content of the BIT STRING.
* On error, the value of \c *p is undefined.
* \param end End of data.
* \param len On success, \c *len is the length of the content in bytes.
* *
* \return 0 if successful or a specific ASN.1 error code. * \return 0 if successful.
* \return #MBEDTLS_ERR_ASN1_INVALID_DATA if the input starts with
* a valid BIT STRING with a nonzero number of unused bits.
* \return An ASN.1 error code if the input does not start with
* a valid ASN.1 BIT STRING.
*/ */
int mbedtls_asn1_get_bitstring_null(unsigned char **p, const unsigned char *end, int mbedtls_asn1_get_bitstring_null( unsigned char **p,
size_t *len); const unsigned char *end,
size_t *len );
/** /**
* \brief Parses and splits an ASN.1 "SEQUENCE OF <tag>" * \brief Parses and splits an ASN.1 "SEQUENCE OF <tag>".
* Updated the pointer to immediately behind the full sequence tag. * Updates the pointer to immediately behind the full sequence tag.
* *
* \param p The position in the ASN.1 data * This function allocates memory for the sequence elements. You can free
* \param end End of data * the allocated memory with mbedtls_asn1_sequence_free().
* \param cur First variable in the chain to fill
* \param tag Type of sequence
* *
* \return 0 if successful or a specific ASN.1 error code. * \note On error, this function may return a partial list in \p cur.
* You must set `cur->next = NULL` before calling this function!
* Otherwise it is impossible to distinguish a previously non-null
* pointer from a pointer to an object allocated by this function.
*
* \note If the sequence is empty, this function does not modify
* \c *cur. If the sequence is valid and non-empty, this
* function sets `cur->buf.tag` to \p tag. This allows
* callers to distinguish between an empty sequence and
* a one-element sequence.
*
* \param p On entry, \c *p points to the start of the ASN.1 element.
* On successful completion, \c *p is equal to \p end.
* On error, the value of \c *p is undefined.
* \param end End of data.
* \param cur A ::mbedtls_asn1_sequence which this function fills.
* When this function returns, \c *cur is the head of a linked
* list. Each node in this list is allocated with
* mbedtls_calloc() apart from \p cur itself, and should
* therefore be freed with mbedtls_free().
* The list describes the content of the sequence.
* The head of the list (i.e. \c *cur itself) describes the
* first element, `*cur->next` describes the second element, etc.
* For each element, `buf.tag == tag`, `buf.len` is the length
* of the content of the content of the element, and `buf.p`
* points to the first byte of the content (i.e. immediately
* past the length of the element).
* Note that list elements may be allocated even on error.
* \param tag Each element of the sequence must have this tag.
*
* \return 0 if successful.
* \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input contains
* extra data after a valid SEQUENCE OF \p tag.
* \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the input starts with
* an ASN.1 SEQUENCE in which an element has a tag that
* is different from \p tag.
* \return #MBEDTLS_ERR_ASN1_ALLOC_FAILED if a memory allocation failed.
* \return An ASN.1 error code if the input does not start with
* a valid ASN.1 SEQUENCE.
*/ */
int mbedtls_asn1_get_sequence_of(unsigned char **p, int mbedtls_asn1_get_sequence_of( unsigned char **p,
const unsigned char *end, const unsigned char *end,
mbedtls_asn1_sequence *cur, mbedtls_asn1_sequence *cur,
int tag); int tag );
/**
* \brief Free a heap-allocated linked list presentation of
* an ASN.1 sequence, including the first element.
*
* There are two common ways to manage the memory used for the representation
* of a parsed ASN.1 sequence:
* - Allocate a head node `mbedtls_asn1_sequence *head` with mbedtls_calloc().
* Pass this node as the `cur` argument to mbedtls_asn1_get_sequence_of().
* When you have finished processing the sequence,
* call mbedtls_asn1_sequence_free() on `head`.
* - Allocate a head node `mbedtls_asn1_sequence *head` in any manner,
* for example on the stack. Make sure that `head->next == NULL`.
* Pass `head` as the `cur` argument to mbedtls_asn1_get_sequence_of().
* When you have finished processing the sequence,
* call mbedtls_asn1_sequence_free() on `head->cur`,
* then free `head` itself in the appropriate manner.
*
* \param seq The address of the first sequence component. This may
* be \c NULL, in which case this functions returns
* immediately.
*/
void mbedtls_asn1_sequence_free( mbedtls_asn1_sequence *seq );
/**
* \brief Traverse an ASN.1 SEQUENCE container and
* call a callback for each entry.
*
* This function checks that the input is a SEQUENCE of elements that
* each have a "must" tag, and calls a callback function on the elements
* that have a "may" tag.
*
* For example, to validate that the input is a SEQUENCE of `tag1` and call
* `cb` on each element, use
* ```
* mbedtls_asn1_traverse_sequence_of(&p, end, 0xff, tag1, 0, 0, cb, ctx);
* ```
*
* To validate that the input is a SEQUENCE of ANY and call `cb` on
* each element, use
* ```
* mbedtls_asn1_traverse_sequence_of(&p, end, 0, 0, 0, 0, cb, ctx);
* ```
*
* To validate that the input is a SEQUENCE of CHOICE {NULL, OCTET STRING}
* and call `cb` on each element that is an OCTET STRING, use
* ```
* mbedtls_asn1_traverse_sequence_of(&p, end, 0xfe, 0x04, 0xff, 0x04, cb, ctx);
* ```
*
* The callback is called on the elements with a "may" tag from left to
* right. If the input is not a valid SEQUENCE of elements with a "must" tag,
* the callback is called on the elements up to the leftmost point where
* the input is invalid.
*
* \warning This function is still experimental and may change
* at any time.
*
* \param p The address of the pointer to the beginning of
* the ASN.1 SEQUENCE header. This is updated to
* point to the end of the ASN.1 SEQUENCE container
* on a successful invocation.
* \param end The end of the ASN.1 SEQUENCE container.
* \param tag_must_mask A mask to be applied to the ASN.1 tags found within
* the SEQUENCE before comparing to \p tag_must_value.
* \param tag_must_val The required value of each ASN.1 tag found in the
* SEQUENCE, after masking with \p tag_must_mask.
* Mismatching tags lead to an error.
* For example, a value of \c 0 for both \p tag_must_mask
* and \p tag_must_val means that every tag is allowed,
* while a value of \c 0xFF for \p tag_must_mask means
* that \p tag_must_val is the only allowed tag.
* \param tag_may_mask A mask to be applied to the ASN.1 tags found within
* the SEQUENCE before comparing to \p tag_may_value.
* \param tag_may_val The desired value of each ASN.1 tag found in the
* SEQUENCE, after masking with \p tag_may_mask.
* Mismatching tags will be silently ignored.
* For example, a value of \c 0 for \p tag_may_mask and
* \p tag_may_val means that any tag will be considered,
* while a value of \c 0xFF for \p tag_may_mask means
* that all tags with value different from \p tag_may_val
* will be ignored.
* \param cb The callback to trigger for each component
* in the ASN.1 SEQUENCE that matches \p tag_may_val.
* The callback function is called with the following
* parameters:
* - \p ctx.
* - The tag of the current element.
* - A pointer to the start of the current element's
* content inside the input.
* - The length of the content of the current element.
* If the callback returns a non-zero value,
* the function stops immediately,
* forwarding the callback's return value.
* \param ctx The context to be passed to the callback \p cb.
*
* \return \c 0 if successful the entire ASN.1 SEQUENCE
* was traversed without parsing or callback errors.
* \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input
* contains extra data after a valid SEQUENCE
* of elements with an accepted tag.
* \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the input starts
* with an ASN.1 SEQUENCE in which an element has a tag
* that is not accepted.
* \return An ASN.1 error code if the input does not start with
* a valid ASN.1 SEQUENCE.
* \return A non-zero error code forwarded from the callback
* \p cb in case the latter returns a non-zero value.
*/
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 );
#if defined(MBEDTLS_BIGNUM_C) #if defined(MBEDTLS_BIGNUM_C)
/** /**
* \brief Retrieve a MPI value from an integer ASN.1 tag. * \brief Retrieve an integer ASN.1 tag and its value.
* Updates the pointer to immediately behind the full tag. * Updates the pointer to immediately behind the full tag.
* *
* \param p The position in the ASN.1 data * \param p On entry, \c *p points to the start of the ASN.1 element.
* \param end End of data * On successful completion, \c *p points to the first byte
* \param X The MPI that will receive the value * beyond the ASN.1 element.
* On error, the value of \c *p is undefined.
* \param end End of data.
* \param X On success, the parsed value.
* *
* \return 0 if successful or a specific ASN.1 or MPI error code. * \return 0 if successful.
* \return An ASN.1 error code if the input does not start with
* a valid ASN.1 INTEGER.
* \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does
* not fit in an \c int.
* \return An MPI error code if the parsed value is too large.
*/ */
int mbedtls_asn1_get_mpi(unsigned char **p, int mbedtls_asn1_get_mpi( unsigned char **p,
const unsigned char *end, const unsigned char *end,
mbedtls_mpi *X); mbedtls_mpi *X );
#endif /* MBEDTLS_BIGNUM_C */ #endif /* MBEDTLS_BIGNUM_C */
/** /**
@@ -294,16 +534,20 @@ int mbedtls_asn1_get_mpi(unsigned char **p,
* Updates the pointer to immediately behind the full * Updates the pointer to immediately behind the full
* AlgorithmIdentifier. * AlgorithmIdentifier.
* *
* \param p The position in the ASN.1 data * \param p On entry, \c *p points to the start of the ASN.1 element.
* \param end End of data * On successful completion, \c *p points to the first byte
* \param alg The buffer to receive the OID * beyond the AlgorithmIdentifier element.
* \param params The buffer to receive the params (if any) * On error, the value of \c *p is undefined.
* \param end End of data.
* \param alg The buffer to receive the OID.
* \param params The buffer to receive the parameters.
* This is zeroized if there are no parameters.
* *
* \return 0 if successful or a specific ASN.1 or MPI error code. * \return 0 if successful or a specific ASN.1 or MPI error code.
*/ */
int mbedtls_asn1_get_alg(unsigned char **p, int mbedtls_asn1_get_alg( unsigned char **p,
const unsigned char *end, const unsigned char *end,
mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params); mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params );
/** /**
* \brief Retrieve an AlgorithmIdentifier ASN.1 sequence with NULL or no * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence with NULL or no
@@ -311,15 +555,18 @@ int mbedtls_asn1_get_alg(unsigned char **p,
* Updates the pointer to immediately behind the full * Updates the pointer to immediately behind the full
* AlgorithmIdentifier. * AlgorithmIdentifier.
* *
* \param p The position in the ASN.1 data * \param p On entry, \c *p points to the start of the ASN.1 element.
* \param end End of data * On successful completion, \c *p points to the first byte
* \param alg The buffer to receive the OID * beyond the AlgorithmIdentifier element.
* On error, the value of \c *p is undefined.
* \param end End of data.
* \param alg The buffer to receive the OID.
* *
* \return 0 if successful or a specific ASN.1 or MPI error code. * \return 0 if successful or a specific ASN.1 or MPI error code.
*/ */
int mbedtls_asn1_get_alg_null(unsigned char **p, int mbedtls_asn1_get_alg_null( unsigned char **p,
const unsigned char *end, const unsigned char *end,
mbedtls_asn1_buf *alg); mbedtls_asn1_buf *alg );
/** /**
* \brief Find a specific named_data entry in a sequence or list based on * \brief Find a specific named_data entry in a sequence or list based on
@@ -331,23 +578,27 @@ int mbedtls_asn1_get_alg_null(unsigned char **p,
* *
* \return NULL if not found, or a pointer to the existing entry. * \return NULL if not found, or a pointer to the existing entry.
*/ */
mbedtls_asn1_named_data *mbedtls_asn1_find_named_data(mbedtls_asn1_named_data *list, mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( mbedtls_asn1_named_data *list,
const char *oid, size_t len); const char *oid, size_t len );
/** /**
* \brief Free a mbedtls_asn1_named_data entry * \brief Free a mbedtls_asn1_named_data entry
* *
* \param entry The named data entry to free * \param entry The named data entry to free.
* This function calls mbedtls_free() on
* `entry->oid.p` and `entry->val.p`.
*/ */
void mbedtls_asn1_free_named_data(mbedtls_asn1_named_data *entry); void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *entry );
/** /**
* \brief Free all entries in a mbedtls_asn1_named_data list * \brief Free all entries in a mbedtls_asn1_named_data list.
* Head will be set to NULL
* *
* \param head Pointer to the head of the list of named data entries to free * \param head Pointer to the head of the list of named data entries to free.
* This function calls mbedtls_asn1_free_named_data() and
* mbedtls_free() on each list element and
* sets \c *head to \c NULL.
*/ */
void mbedtls_asn1_free_named_data_list(mbedtls_asn1_named_data **head); void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head );
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -1,36 +1,29 @@
/* /*
* Generic ASN.1 parsing * Generic ASN.1 parsing
* *
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
#if !defined(MBEDTLS_CONFIG_FILE) #include "common.h"
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_ASN1_PARSE_C) #if defined(MBEDTLS_ASN1_PARSE_C)
#include "mbedtls/asn1.h" #include "mbedtls/asn1.h"
#include "mbedtls/platform_util.h" #include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#include <string.h> #include <string.h>
@@ -49,321 +42,440 @@
/* /*
* ASN.1 DER decoding routines * ASN.1 DER decoding routines
*/ */
int mbedtls_asn1_get_len(unsigned char **p, int mbedtls_asn1_get_len( unsigned char **p,
const unsigned char *end, const unsigned char *end,
size_t *len) { size_t *len )
if ((end - *p) < 1) {
return (MBEDTLS_ERR_ASN1_OUT_OF_DATA); if( ( end - *p ) < 1 )
return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
if ((**p & 0x80) == 0) if( ( **p & 0x80 ) == 0 )
*len = *(*p)++; *len = *(*p)++;
else { else
switch (**p & 0x7F) { {
case 1: switch( **p & 0x7F )
if ((end - *p) < 2) {
return (MBEDTLS_ERR_ASN1_OUT_OF_DATA); case 1:
if( ( end - *p ) < 2 )
return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
*len = (*p)[1]; *len = (*p)[1];
(*p) += 2; (*p) += 2;
break; break;
case 2: case 2:
if ((end - *p) < 3) if( ( end - *p ) < 3 )
return (MBEDTLS_ERR_ASN1_OUT_OF_DATA); return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
*len = ((size_t)(*p)[1] << 8) | (*p)[2]; *len = ( (size_t)(*p)[1] << 8 ) | (*p)[2];
(*p) += 3; (*p) += 3;
break; break;
case 3: case 3:
if ((end - *p) < 4) if( ( end - *p ) < 4 )
return (MBEDTLS_ERR_ASN1_OUT_OF_DATA); return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
*len = ((size_t)(*p)[1] << 16) | *len = ( (size_t)(*p)[1] << 16 ) |
((size_t)(*p)[2] << 8) | (*p)[3]; ( (size_t)(*p)[2] << 8 ) | (*p)[3];
(*p) += 4; (*p) += 4;
break; break;
case 4: case 4:
if ((end - *p) < 5) if( ( end - *p ) < 5 )
return (MBEDTLS_ERR_ASN1_OUT_OF_DATA); return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
*len = ((size_t)(*p)[1] << 24) | ((size_t)(*p)[2] << 16) | *len = ( (size_t)(*p)[1] << 24 ) | ( (size_t)(*p)[2] << 16 ) |
((size_t)(*p)[3] << 8) | (*p)[4]; ( (size_t)(*p)[3] << 8 ) | (*p)[4];
(*p) += 5; (*p) += 5;
break; break;
default: default:
return (MBEDTLS_ERR_ASN1_INVALID_LENGTH); return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
} }
} }
if (*len > (size_t)(end - *p)) if( *len > (size_t) ( end - *p ) )
return (MBEDTLS_ERR_ASN1_OUT_OF_DATA); return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
return (0); return( 0 );
} }
int mbedtls_asn1_get_tag(unsigned char **p, int mbedtls_asn1_get_tag( unsigned char **p,
const unsigned char *end, const unsigned char *end,
size_t *len, int tag) { size_t *len, int tag )
if ((end - *p) < 1) {
return (MBEDTLS_ERR_ASN1_OUT_OF_DATA); if( ( end - *p ) < 1 )
return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
if (**p != tag) if( **p != tag )
return (MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); return( MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
(*p)++; (*p)++;
return (mbedtls_asn1_get_len(p, end, len)); return( mbedtls_asn1_get_len( p, end, len ) );
} }
int mbedtls_asn1_get_bool(unsigned char **p, int mbedtls_asn1_get_bool( unsigned char **p,
const unsigned char *end, const unsigned char *end,
int *val) { int *val )
int ret; {
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len; size_t len;
if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_BOOLEAN)) != 0) if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_BOOLEAN ) ) != 0 )
return (ret); return( ret );
if (len != 1) if( len != 1 )
return (MBEDTLS_ERR_ASN1_INVALID_LENGTH); return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
*val = (**p != 0) ? 1 : 0; *val = ( **p != 0 ) ? 1 : 0;
(*p)++; (*p)++;
return (0); return( 0 );
} }
int mbedtls_asn1_get_int(unsigned char **p, static int asn1_get_tagged_int( unsigned char **p,
const unsigned char *end, const unsigned char *end,
int *val) { int tag, int *val )
int ret; {
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len; size_t len;
if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) if( ( ret = mbedtls_asn1_get_tag( p, end, &len, tag ) ) != 0 )
return (ret); return( ret );
if (len == 0 || len > sizeof(int) || (**p & 0x80) != 0) /*
return (MBEDTLS_ERR_ASN1_INVALID_LENGTH); * 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; *val = 0;
while( len-- > 0 )
while (len-- > 0) { {
*val = (*val << 8) | **p; *val = ( *val << 8 ) | **p;
(*p)++; (*p)++;
} }
return (0); 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) #if defined(MBEDTLS_BIGNUM_C)
int mbedtls_asn1_get_mpi(unsigned char **p, int mbedtls_asn1_get_mpi( unsigned char **p,
const unsigned char *end, const unsigned char *end,
mbedtls_mpi *X) { mbedtls_mpi *X )
int ret; {
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len; size_t len;
if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 )
return (ret); return( ret );
ret = mbedtls_mpi_read_binary(X, *p, len); ret = mbedtls_mpi_read_binary( X, *p, len );
*p += len; *p += len;
return (ret); return( ret );
} }
#endif /* MBEDTLS_BIGNUM_C */ #endif /* MBEDTLS_BIGNUM_C */
int mbedtls_asn1_get_bitstring(unsigned char **p, const unsigned char *end, int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end,
mbedtls_asn1_bitstring *bs) { mbedtls_asn1_bitstring *bs)
int ret; {
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* Certificate type is a single byte bitstring */ /* Certificate type is a single byte bitstring */
if ((ret = mbedtls_asn1_get_tag(p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING)) != 0) if( ( ret = mbedtls_asn1_get_tag( p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 )
return (ret); return( ret );
/* Check length, subtract one for actual bit string length */ /* Check length, subtract one for actual bit string length */
if (bs->len < 1) if( bs->len < 1 )
return (MBEDTLS_ERR_ASN1_OUT_OF_DATA); return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
bs->len -= 1; bs->len -= 1;
/* Get number of unused bits, ensure unused bits <= 7 */ /* Get number of unused bits, ensure unused bits <= 7 */
bs->unused_bits = **p; bs->unused_bits = **p;
if (bs->unused_bits > 7) if( bs->unused_bits > 7 )
return (MBEDTLS_ERR_ASN1_INVALID_LENGTH); return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
(*p)++; (*p)++;
/* Get actual bitstring */ /* Get actual bitstring */
bs->p = *p; bs->p = *p;
*p += bs->len; *p += bs->len;
if (*p != end) if( *p != end )
return (MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
return (0); 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 * Get a bit string without unused bits
*/ */
int mbedtls_asn1_get_bitstring_null(unsigned char **p, const unsigned char *end, int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end,
size_t *len) { size_t *len )
int ret; {
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if ((ret = mbedtls_asn1_get_tag(p, end, len, MBEDTLS_ASN1_BIT_STRING)) != 0) if( ( ret = mbedtls_asn1_get_tag( p, end, len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 )
return (ret); return( ret );
if ((*len)-- < 2 || *(*p)++ != 0) if( *len == 0 )
return (MBEDTLS_ERR_ASN1_INVALID_DATA); return( MBEDTLS_ERR_ASN1_INVALID_DATA );
--( *len );
return (0); 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_platform_zeroize( seq, sizeof( *seq ) );
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>" * Parses and splits an ASN.1 "SEQUENCE OF <tag>"
*/ */
int mbedtls_asn1_get_sequence_of(unsigned char **p, int mbedtls_asn1_get_sequence_of( unsigned char **p,
const unsigned char *end, const unsigned char *end,
mbedtls_asn1_sequence *cur, mbedtls_asn1_sequence *cur,
int tag) { int tag)
int ret; {
size_t len; asn1_get_sequence_of_cb_ctx_t cb_ctx = { tag, cur };
mbedtls_asn1_buf *buf; memset( cur, 0, sizeof( mbedtls_asn1_sequence ) );
return( mbedtls_asn1_traverse_sequence_of(
/* Get main sequence tag */ p, end, 0xFF, tag, 0, 0,
if ((ret = mbedtls_asn1_get_tag(p, end, &len, asn1_get_sequence_of_cb, &cb_ctx ) );
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0)
return (ret);
if (*p + len != end)
return (MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
while (*p < end) {
buf = &(cur->buf);
buf->tag = **p;
if ((ret = mbedtls_asn1_get_tag(p, end, &buf->len, tag)) != 0)
return (ret);
buf->p = *p;
*p += buf->len;
/* Allocate and assign next pointer */
if (*p < end) {
cur->next = (mbedtls_asn1_sequence *)mbedtls_calloc(1,
sizeof(mbedtls_asn1_sequence));
if (cur->next == NULL)
return (MBEDTLS_ERR_ASN1_ALLOC_FAILED);
cur = cur->next;
}
}
/* Set final sequence entry's next pointer to NULL */
cur->next = NULL;
if (*p != end)
return (MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
return (0);
} }
int mbedtls_asn1_get_alg(unsigned char **p, int mbedtls_asn1_get_alg( unsigned char **p,
const unsigned char *end, const unsigned char *end,
mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params) { mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params )
int ret; {
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len; size_t len;
if ((ret = mbedtls_asn1_get_tag(p, end, &len, if( ( ret = mbedtls_asn1_get_tag( p, end, &len,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
return (ret); return( ret );
if ((end - *p) < 1) if( ( end - *p ) < 1 )
return (MBEDTLS_ERR_ASN1_OUT_OF_DATA); return( MBEDTLS_ERR_ASN1_OUT_OF_DATA );
alg->tag = **p; alg->tag = **p;
end = *p + len; end = *p + len;
if ((ret = mbedtls_asn1_get_tag(p, end, &alg->len, MBEDTLS_ASN1_OID)) != 0) if( ( ret = mbedtls_asn1_get_tag( p, end, &alg->len, MBEDTLS_ASN1_OID ) ) != 0 )
return (ret); return( ret );
alg->p = *p; alg->p = *p;
*p += alg->len; *p += alg->len;
if (*p == end) { if( *p == end )
mbedtls_platform_zeroize(params, sizeof(mbedtls_asn1_buf)); {
return (0); mbedtls_platform_zeroize( params, sizeof(mbedtls_asn1_buf) );
return( 0 );
} }
params->tag = **p; params->tag = **p;
(*p)++; (*p)++;
if ((ret = mbedtls_asn1_get_len(p, end, &params->len)) != 0) if( ( ret = mbedtls_asn1_get_len( p, end, &params->len ) ) != 0 )
return (ret); return( ret );
params->p = *p; params->p = *p;
*p += params->len; *p += params->len;
if (*p != end) if( *p != end )
return (MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );
return (0); return( 0 );
} }
int mbedtls_asn1_get_alg_null(unsigned char **p, int mbedtls_asn1_get_alg_null( unsigned char **p,
const unsigned char *end, const unsigned char *end,
mbedtls_asn1_buf *alg) { mbedtls_asn1_buf *alg )
int ret; {
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_asn1_buf params; mbedtls_asn1_buf params;
memset(&params, 0, sizeof(mbedtls_asn1_buf)); memset( &params, 0, sizeof(mbedtls_asn1_buf) );
if ((ret = mbedtls_asn1_get_alg(p, end, alg, &params)) != 0) if( ( ret = mbedtls_asn1_get_alg( p, end, alg, &params ) ) != 0 )
return (ret); return( ret );
if ((params.tag != MBEDTLS_ASN1_NULL && params.tag != 0) || params.len != 0) if( ( params.tag != MBEDTLS_ASN1_NULL && params.tag != 0 ) || params.len != 0 )
return (MBEDTLS_ERR_ASN1_INVALID_DATA); return( MBEDTLS_ERR_ASN1_INVALID_DATA );
return (0); return( 0 );
} }
void mbedtls_asn1_free_named_data(mbedtls_asn1_named_data *cur) { void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *cur )
if (cur == NULL) {
if( cur == NULL )
return; return;
mbedtls_free(cur->oid.p); mbedtls_free( cur->oid.p );
mbedtls_free(cur->val.p); mbedtls_free( cur->val.p );
mbedtls_platform_zeroize(cur, sizeof(mbedtls_asn1_named_data)); mbedtls_platform_zeroize( cur, sizeof( mbedtls_asn1_named_data ) );
} }
void mbedtls_asn1_free_named_data_list(mbedtls_asn1_named_data **head) { void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head )
{
mbedtls_asn1_named_data *cur; mbedtls_asn1_named_data *cur;
while ((cur = *head) != NULL) { while( ( cur = *head ) != NULL )
{
*head = cur->next; *head = cur->next;
mbedtls_asn1_free_named_data(cur); mbedtls_asn1_free_named_data( cur );
mbedtls_free(cur); mbedtls_free( cur );
} }
} }
mbedtls_asn1_named_data *mbedtls_asn1_find_named_data(mbedtls_asn1_named_data *list, mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( mbedtls_asn1_named_data *list,
const char *oid, size_t len) { const char *oid, size_t len )
while (list != NULL) { {
if (list->oid.len == len && while( list != NULL )
memcmp(list->oid.p, oid, len) == 0) { {
if( list->oid.len == len &&
memcmp( list->oid.p, oid, len ) == 0 )
{
break; break;
} }
list = list->next; list = list->next;
} }
return (list); return( list );
} }
#endif /* MBEDTLS_ASN1_PARSE_C */ #endif /* MBEDTLS_ASN1_PARSE_C */

View File

@@ -1,35 +1,28 @@
/* /*
* ASN.1 buffer writing functionality * ASN.1 buffer writing functionality
* *
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
#if !defined(MBEDTLS_CONFIG_FILE) #include "common.h"
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_ASN1_WRITE_C) #if defined(MBEDTLS_ASN1_WRITE_C)
#include "mbedtls/asn1write.h" #include "mbedtls/asn1write.h"
#include "mbedtls/error.h"
#include <string.h> #include <string.h>
@@ -41,327 +34,447 @@
#define mbedtls_free free #define mbedtls_free free
#endif #endif
int mbedtls_asn1_write_len(unsigned char **p, unsigned char *start, size_t len) { int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len )
if (len < 0x80) { {
if (*p - start < 1) if( len < 0x80 )
return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL); {
if( *p - start < 1 )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
*--(*p) = (unsigned char) len; *--(*p) = (unsigned char) len;
return (1); return( 1 );
} }
if (len <= 0xFF) { if( len <= 0xFF )
if (*p - start < 2) {
return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL); if( *p - start < 2 )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
*--(*p) = (unsigned char) len; *--(*p) = (unsigned char) len;
*--(*p) = 0x81; *--(*p) = 0x81;
return (2); return( 2 );
} }
if (len <= 0xFFFF) { if( len <= 0xFFFF )
if (*p - start < 3) {
return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL); if( *p - start < 3 )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
*--(*p) = (len) & 0xFF; *--(*p) = ( len ) & 0xFF;
*--(*p) = (len >> 8) & 0xFF; *--(*p) = ( len >> 8 ) & 0xFF;
*--(*p) = 0x82; *--(*p) = 0x82;
return (3); return( 3 );
} }
if (len <= 0xFFFFFF) { if( len <= 0xFFFFFF )
if (*p - start < 4) {
return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL); if( *p - start < 4 )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
*--(*p) = (len) & 0xFF; *--(*p) = ( len ) & 0xFF;
*--(*p) = (len >> 8) & 0xFF; *--(*p) = ( len >> 8 ) & 0xFF;
*--(*p) = (len >> 16) & 0xFF; *--(*p) = ( len >> 16 ) & 0xFF;
*--(*p) = 0x83; *--(*p) = 0x83;
return (4); return( 4 );
} }
#if SIZE_MAX > 0xFFFFFFFF #if SIZE_MAX > 0xFFFFFFFF
if (len <= 0xFFFFFFFF) if( len <= 0xFFFFFFFF )
#endif #endif
{ {
if (*p - start < 5) if( *p - start < 5 )
return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL); return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
*--(*p) = (len) & 0xFF; *--(*p) = ( len ) & 0xFF;
*--(*p) = (len >> 8) & 0xFF; *--(*p) = ( len >> 8 ) & 0xFF;
*--(*p) = (len >> 16) & 0xFF; *--(*p) = ( len >> 16 ) & 0xFF;
*--(*p) = (len >> 24) & 0xFF; *--(*p) = ( len >> 24 ) & 0xFF;
*--(*p) = 0x84; *--(*p) = 0x84;
return (5); return( 5 );
} }
#if SIZE_MAX > 0xFFFFFFFF #if SIZE_MAX > 0xFFFFFFFF
return (MBEDTLS_ERR_ASN1_INVALID_LENGTH); return( MBEDTLS_ERR_ASN1_INVALID_LENGTH );
#endif #endif
} }
int mbedtls_asn1_write_tag(unsigned char **p, unsigned char *start, unsigned char tag) { int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag )
if (*p - start < 1) {
return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL); if( *p - start < 1 )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
*--(*p) = tag; *--(*p) = tag;
return (1); return( 1 );
} }
int mbedtls_asn1_write_raw_buffer(unsigned char **p, unsigned char *start, int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start,
const unsigned char *buf, size_t size) { const unsigned char *buf, size_t size )
{
size_t len = 0; size_t len = 0;
if (*p < start || (size_t)(*p - start) < size) if( *p < start || (size_t)( *p - start ) < size )
return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL); return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
len = size; len = size;
(*p) -= len; (*p) -= len;
memcpy(*p, buf, len); memcpy( *p, buf, len );
return ((int) len); return( (int) len );
} }
#if defined(MBEDTLS_BIGNUM_C) #if defined(MBEDTLS_BIGNUM_C)
int mbedtls_asn1_write_mpi(unsigned char **p, unsigned char *start, const mbedtls_mpi *X) { int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X )
int ret; {
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0; size_t len = 0;
// Write the MPI // Write the MPI
// //
len = mbedtls_mpi_size(X); len = mbedtls_mpi_size( X );
if (*p < start || (size_t)(*p - start) < len) if( *p < start || (size_t)( *p - start ) < len )
return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL); return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
(*p) -= len; (*p) -= len;
MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(X, *p, len)); MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X, *p, len ) );
// DER format assumes 2s complement for numbers, so the leftmost bit // DER format assumes 2s complement for numbers, so the leftmost bit
// should be 0 for positive numbers and 1 for negative numbers. // should be 0 for positive numbers and 1 for negative numbers.
// //
if (X->s == 1 && **p & 0x80) { if( X->s ==1 && **p & 0x80 )
if (*p - start < 1) {
return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL); if( *p - start < 1 )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
*--(*p) = 0x00; *--(*p) = 0x00;
len += 1; len += 1;
} }
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_INTEGER)); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) );
ret = (int) len; ret = (int) len;
cleanup: cleanup:
return (ret); return( ret );
} }
#endif /* MBEDTLS_BIGNUM_C */ #endif /* MBEDTLS_BIGNUM_C */
int mbedtls_asn1_write_null(unsigned char **p, unsigned char *start) { int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start )
int ret; {
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0; size_t len = 0;
// Write NULL // Write NULL
// //
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, 0)); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, 0) );
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_NULL)); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_NULL ) );
return ((int) len); return( (int) len );
} }
int mbedtls_asn1_write_oid(unsigned char **p, unsigned char *start, int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start,
const char *oid, size_t oid_len) { const char *oid, size_t oid_len )
int ret; {
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0; size_t len = 0;
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
(const unsigned char *) oid, oid_len)); (const unsigned char *) oid, oid_len ) );
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_len( p, start, len ) );
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_OID)); MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) );
return ((int) len); return( (int) len );
} }
int mbedtls_asn1_write_algorithm_identifier(unsigned char **p, unsigned char *start, int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start,
const char *oid, size_t oid_len, const char *oid, size_t oid_len,
size_t par_len) { size_t par_len )
int ret; {
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0; size_t len = 0;
if (par_len == 0) if( par_len == 0 )
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_null(p, start)); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_null( p, start ) );
else else
len += par_len; len += par_len;
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len)); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) );
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)); MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) );
return ((int) len); return( (int) len );
} }
int mbedtls_asn1_write_bool(unsigned char **p, unsigned char *start, int boolean) { int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean )
int ret; {
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0; size_t len = 0;
if (*p - start < 1) if( *p - start < 1 )
return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL); return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
*--(*p) = (boolean) ? 255 : 0; *--(*p) = (boolean) ? 255 : 0;
len++; len++;
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_BOOLEAN)); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BOOLEAN ) );
return ((int) len); return( (int) len );
} }
int mbedtls_asn1_write_int(unsigned char **p, unsigned char *start, int val) { static int asn1_write_tagged_int( unsigned char **p, unsigned char *start, int val, int tag )
int ret; {
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0; size_t len = 0;
if (*p - start < 1) do
return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL); {
if( *p - start < 1 )
len += 1; return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
*--(*p) = val; len += 1;
*--(*p) = val & 0xff;
if (val > 0 && **p & 0x80) { val >>= 8;
if (*p - start < 1) }
return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL); while( val > 0 );
if( **p & 0x80 )
{
if( *p - start < 1 )
return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );
*--(*p) = 0x00; *--(*p) = 0x00;
len += 1; len += 1;
} }
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_INTEGER)); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) );
return ((int) len); return( (int) len );
} }
int mbedtls_asn1_write_printable_string(unsigned char **p, unsigned char *start, int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val )
const char *text, size_t text_len) { {
int ret; return( asn1_write_tagged_int( p, start, val, MBEDTLS_ASN1_INTEGER ) );
}
int mbedtls_asn1_write_enum( unsigned char **p, 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, unsigned char *start, int tag,
const char *text, size_t text_len )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0; size_t len = 0;
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start,
(const unsigned char *) text, text_len)); (const unsigned char *) text, text_len ) );
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_PRINTABLE_STRING)); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, tag ) );
return ((int) len); return( (int) len );
} }
int mbedtls_asn1_write_ia5_string(unsigned char **p, unsigned char *start, int mbedtls_asn1_write_utf8_string( unsigned char **p, unsigned char *start,
const char *text, size_t text_len) { const char *text, size_t text_len )
int ret; {
return( mbedtls_asn1_write_tagged_string(p, start, MBEDTLS_ASN1_UTF8_STRING, text, text_len) );
}
int mbedtls_asn1_write_printable_string( unsigned char **p, 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, 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,
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, unsigned char *start,
const unsigned char *buf, size_t bits )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
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;
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) );
return( (int) len );
}
int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start,
const unsigned char *buf, size_t size )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t len = 0; size_t len = 0;
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, buf, size ) );
(const unsigned char *) text, text_len));
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len)); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) );
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_IA5_STRING)); MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) );
return ((int) len); return( (int) len );
} }
int mbedtls_asn1_write_bitstring(unsigned char **p, unsigned char *start,
const unsigned char *buf, size_t bits) {
int ret;
size_t len = 0, size;
size = (bits / 8) + ((bits % 8) ? 1 : 0); /* 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. */
// Calculate byte length static mbedtls_asn1_named_data *asn1_find_named_data(
// mbedtls_asn1_named_data *list,
if (*p < start || (size_t)(*p - start) < size + 1) const char *oid, size_t len )
return (MBEDTLS_ERR_ASN1_BUF_TOO_SMALL); {
while( list != NULL )
len = size + 1; {
(*p) -= size; if( list->oid.len == len &&
memcpy(*p, buf, size); memcmp( list->oid.p, oid, len ) == 0 )
{
// Write unused bits break;
//
*--(*p) = (unsigned char)(size * 8 - bits);
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_BIT_STRING));
return ((int) len);
}
int mbedtls_asn1_write_octet_string(unsigned char **p, unsigned char *start,
const unsigned char *buf, size_t size) {
int ret;
size_t len = 0;
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, buf, size));
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_OCTET_STRING));
return ((int) len);
}
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 = mbedtls_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); list = list->next;
}
return( list );
}
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; cur->val.len = val_len;
cur->val.p = mbedtls_calloc(1, val_len); if( val_len != 0 )
if (cur->val.p == NULL) { {
mbedtls_free(cur->oid.p); cur->val.p = mbedtls_calloc( 1, val_len );
mbedtls_free(cur); if( cur->val.p == NULL )
return (NULL); {
mbedtls_free( cur->oid.p );
mbedtls_free( cur );
return( NULL );
}
} }
cur->next = *head; cur->next = *head;
*head = cur; *head = cur;
} else if (cur->val.len < val_len) { }
else if( val_len == 0 )
{
mbedtls_free( cur->val.p );
cur->val.p = NULL;
}
else if( cur->val.len != val_len )
{
/* /*
* Enlarge existing value buffer if needed * Enlarge existing value buffer if needed
* Preserve old data until the allocation succeeded, to leave list in * Preserve old data until the allocation succeeded, to leave list in
* a consistent state in case allocation fails. * a consistent state in case allocation fails.
*/ */
void *p = mbedtls_calloc(1, val_len); void *p = mbedtls_calloc( 1, val_len );
if (p == NULL) if( p == NULL )
return (NULL); return( NULL );
mbedtls_free(cur->val.p); mbedtls_free( cur->val.p );
cur->val.p = p; cur->val.p = p;
cur->val.len = val_len; cur->val.len = val_len;
} }
if (val != NULL) if( val != NULL )
memcpy(cur->val.p, val, val_len); memcpy( cur->val.p, val, val_len );
return (cur); return( cur );
} }
#endif /* MBEDTLS_ASN1_WRITE_C */ #endif /* MBEDTLS_ASN1_WRITE_C */

View File

@@ -4,215 +4,338 @@
* \brief ASN.1 buffer writing functionality * \brief ASN.1 buffer writing functionality
*/ */
/* /*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
#ifndef MBEDTLS_ASN1_WRITE_H #ifndef MBEDTLS_ASN1_WRITE_H
#define MBEDTLS_ASN1_WRITE_H #define MBEDTLS_ASN1_WRITE_H
#include "asn1.h" #if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#define MBEDTLS_ASN1_CHK_ADD(g, f) do { if( ( ret = f ) < 0 ) return( ret ); else \ #include "mbedtls/asn1.h"
g += ret; } while( 0 )
#define MBEDTLS_ASN1_CHK_ADD(g, f) \
do \
{ \
if( ( ret = (f) ) < 0 ) \
return( ret ); \
else \
(g) += ret; \
} while( 0 )
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/** /**
* \brief Write a length field in ASN.1 format * \brief Write a length field in ASN.1 format.
* Note: function works backwards in data buffer
* *
* \param p reference to current position pointer * \note This function works backwards in data buffer.
* \param start start of the buffer (for bounds-checking)
* \param len the length to write
* *
* \return the length written or a negative error code * \param p The reference to the current position pointer.
* \param start The start of the buffer, for bounds-checking.
* \param len The length value to write.
*
* \return The number of bytes written to \p p on success.
* \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/ */
int mbedtls_asn1_write_len(unsigned char **p, unsigned char *start, size_t len); int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start,
size_t len );
/**
* \brief Write an ASN.1 tag in ASN.1 format.
*
* \note This function works backwards in data buffer.
*
* \param p The reference to the current position pointer.
* \param start The start of the buffer, for bounds-checking.
* \param tag The tag to write.
*
* \return The number of bytes written to \p p on success.
* \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/
int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start,
unsigned char tag );
/** /**
* \brief Write a ASN.1 tag in ASN.1 format * \brief Write raw buffer data.
* Note: function works backwards in data buffer
* *
* \param p reference to current position pointer * \note This function works backwards in data buffer.
* \param start start of the buffer (for bounds-checking)
* \param tag the tag to write
* *
* \return the length written or a negative error code * \param p The reference to the current position pointer.
* \param start The start of the buffer, for bounds-checking.
* \param buf The data buffer to write.
* \param size The length of the data buffer.
*
* \return The number of bytes written to \p p on success.
* \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/ */
int mbedtls_asn1_write_tag(unsigned char **p, unsigned char *start, int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start,
unsigned char tag); const unsigned char *buf, size_t size );
/**
* \brief Write raw buffer data
* Note: function works backwards in data buffer
*
* \param p reference to current position pointer
* \param start start of the buffer (for bounds-checking)
* \param buf data buffer to write
* \param size length of the data buffer
*
* \return the length written or a negative error code
*/
int mbedtls_asn1_write_raw_buffer(unsigned char **p, unsigned char *start,
const unsigned char *buf, size_t size);
#if defined(MBEDTLS_BIGNUM_C) #if defined(MBEDTLS_BIGNUM_C)
/** /**
* \brief Write a big number (MBEDTLS_ASN1_INTEGER) in ASN.1 format * \brief Write a arbitrary-precision number (#MBEDTLS_ASN1_INTEGER)
* Note: function works backwards in data buffer * in ASN.1 format.
* *
* \param p reference to current position pointer * \note This function works backwards in data buffer.
* \param start start of the buffer (for bounds-checking)
* \param X the MPI to write
* *
* \return the length written or a negative error code * \param p The reference to the current position pointer.
* \param start The start of the buffer, for bounds-checking.
* \param X The MPI to write.
* It must be non-negative.
*
* \return The number of bytes written to \p p on success.
* \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/ */
int mbedtls_asn1_write_mpi(unsigned char **p, unsigned char *start, const mbedtls_mpi *X); int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start,
const mbedtls_mpi *X );
#endif /* MBEDTLS_BIGNUM_C */ #endif /* MBEDTLS_BIGNUM_C */
/** /**
* \brief Write a NULL tag (MBEDTLS_ASN1_NULL) with zero data in ASN.1 format * \brief Write a NULL tag (#MBEDTLS_ASN1_NULL) with zero data
* Note: function works backwards in data buffer * in ASN.1 format.
* *
* \param p reference to current position pointer * \note This function works backwards in data buffer.
* \param start start of the buffer (for bounds-checking)
* *
* \return the length written or a negative error code * \param p The reference to the current position pointer.
* \param start The start of the buffer, for bounds-checking.
*
* \return The number of bytes written to \p p on success.
* \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/ */
int mbedtls_asn1_write_null(unsigned char **p, unsigned char *start); int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start );
/** /**
* \brief Write an OID tag (MBEDTLS_ASN1_OID) and data in ASN.1 format * \brief Write an OID tag (#MBEDTLS_ASN1_OID) and data
* Note: function works backwards in data buffer * in ASN.1 format.
* *
* \param p reference to current position pointer * \note This function works backwards in data buffer.
* \param start start of the buffer (for bounds-checking)
* \param oid the OID to write
* \param oid_len length of the OID
* *
* \return the length written or a negative error code * \param p The reference to the current position pointer.
* \param start The start of the buffer, for bounds-checking.
* \param oid The OID to write.
* \param oid_len The length of the OID.
*
* \return The number of bytes written to \p p on success.
* \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/ */
int mbedtls_asn1_write_oid(unsigned char **p, unsigned char *start, int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start,
const char *oid, size_t oid_len); const char *oid, size_t oid_len );
/** /**
* \brief Write an AlgorithmIdentifier sequence in ASN.1 format * \brief Write an AlgorithmIdentifier sequence in ASN.1 format.
* Note: function works backwards in data buffer
* *
* \param p reference to current position pointer * \note This function works backwards in data buffer.
* \param start start of the buffer (for bounds-checking) *
* \param oid the OID of the algorithm * \param p The reference to the current position pointer.
* \param oid_len length of the OID * \param start The start of the buffer, for bounds-checking.
* \param par_len length of parameters, which must be already written. * \param oid The OID of the algorithm to write.
* \param oid_len The length of the algorithm's OID.
* \param par_len The length of the parameters, which must be already written.
* If 0, NULL parameters are added * If 0, NULL parameters are added
* *
* \return the length written or a negative error code * \return The number of bytes written to \p p on success.
* \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/ */
int mbedtls_asn1_write_algorithm_identifier(unsigned char **p, unsigned char *start, int mbedtls_asn1_write_algorithm_identifier( unsigned char **p,
const char *oid, size_t oid_len, unsigned char *start,
size_t par_len); const char *oid, size_t oid_len,
size_t par_len );
/** /**
* \brief Write a boolean tag (MBEDTLS_ASN1_BOOLEAN) and value in ASN.1 format * \brief Write a boolean tag (#MBEDTLS_ASN1_BOOLEAN) and value
* Note: function works backwards in data buffer * in ASN.1 format.
* *
* \param p reference to current position pointer * \note This function works backwards in data buffer.
* \param start start of the buffer (for bounds-checking)
* \param boolean 0 or 1
* *
* \return the length written or a negative error code * \param p The reference to the current position pointer.
* \param start The start of the buffer, for bounds-checking.
* \param boolean The boolean value to write, either \c 0 or \c 1.
*
* \return The number of bytes written to \p p on success.
* \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/ */
int mbedtls_asn1_write_bool(unsigned char **p, unsigned char *start, int boolean); int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start,
int boolean );
/** /**
* \brief Write an int tag (MBEDTLS_ASN1_INTEGER) and value in ASN.1 format * \brief Write an int tag (#MBEDTLS_ASN1_INTEGER) and value
* Note: function works backwards in data buffer * in ASN.1 format.
* *
* \param p reference to current position pointer * \note This function works backwards in data buffer.
* \param start start of the buffer (for bounds-checking)
* \param val the integer value
* *
* \return the length written or a negative error code * \param p The reference to the current position pointer.
* \param start The start of the buffer, for bounds-checking.
* \param val The integer value to write.
* It must be non-negative.
*
* \return The number of bytes written to \p p on success.
* \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/ */
int mbedtls_asn1_write_int(unsigned char **p, unsigned char *start, int val); int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val );
/** /**
* \brief Write a printable string tag (MBEDTLS_ASN1_PRINTABLE_STRING) and * \brief Write an enum tag (#MBEDTLS_ASN1_ENUMERATED) and value
* value in ASN.1 format * in ASN.1 format.
* Note: function works backwards in data buffer
* *
* \param p reference to current position pointer * \note This function works backwards in data buffer.
* \param start start of the buffer (for bounds-checking)
* \param text the text to write
* \param text_len length of the text
* *
* \return the length written or a negative error code * \param p The reference to the current position pointer.
* \param start The start of the buffer, for bounds-checking.
* \param val The integer value to write.
*
* \return The number of bytes written to \p p on success.
* \return A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/ */
int mbedtls_asn1_write_printable_string(unsigned char **p, unsigned char *start, int mbedtls_asn1_write_enum( unsigned char **p, unsigned char *start, int val );
const char *text, size_t text_len);
/** /**
* \brief Write an IA5 string tag (MBEDTLS_ASN1_IA5_STRING) and * \brief Write a string in ASN.1 format using a specific
* value in ASN.1 format * string encoding tag.
* Note: function works backwards in data buffer
* \note This function works backwards in data buffer.
* *
* \param p reference to current position pointer * \param p The reference to the current position pointer.
* \param start start of the buffer (for bounds-checking) * \param start The start of the buffer, for bounds-checking.
* \param text the text to write * \param tag The string encoding tag to write, e.g.
* \param text_len length of the text * #MBEDTLS_ASN1_UTF8_STRING.
* \param text The string to write.
* \param text_len The length of \p text in bytes (which might
* be strictly larger than the number of characters).
* *
* \return the length written or a negative error code * \return The number of bytes written to \p p on success.
* \return A negative error code on failure.
*/ */
int mbedtls_asn1_write_ia5_string(unsigned char **p, unsigned char *start, int mbedtls_asn1_write_tagged_string( unsigned char **p, unsigned char *start,
const char *text, size_t text_len); int tag, const char *text,
size_t text_len );
/** /**
* \brief Write a bitstring tag (MBEDTLS_ASN1_BIT_STRING) and * \brief Write a string in ASN.1 format using the PrintableString
* value in ASN.1 format * string encoding tag (#MBEDTLS_ASN1_PRINTABLE_STRING).
* Note: function works backwards in data buffer
* *
* \param p reference to current position pointer * \note This function works backwards in data buffer.
* \param start start of the buffer (for bounds-checking)
* \param buf the bitstring
* \param bits the total number of bits in the bitstring
* *
* \return the length written or a negative error code * \param p The reference to the current position pointer.
* \param start The start of the buffer, for bounds-checking.
* \param text The string to write.
* \param text_len The length of \p text in bytes (which might
* be strictly larger than the number of characters).
*
* \return The number of bytes written to \p p on success.
* \return A negative error code on failure.
*/ */
int mbedtls_asn1_write_bitstring(unsigned char **p, unsigned char *start, int mbedtls_asn1_write_printable_string( unsigned char **p,
const unsigned char *buf, size_t bits); unsigned char *start,
const char *text, size_t text_len );
/** /**
* \brief Write an octet string tag (MBEDTLS_ASN1_OCTET_STRING) and * \brief Write a UTF8 string in ASN.1 format using the UTF8String
* value in ASN.1 format * string encoding tag (#MBEDTLS_ASN1_UTF8_STRING).
* Note: function works backwards in data buffer
* *
* \param p reference to current position pointer * \note This function works backwards in data buffer.
* \param start start of the buffer (for bounds-checking)
* \param buf data buffer to write
* \param size length of the data buffer
* *
* \return the length written or a negative error code * \param p The reference to the current position pointer.
* \param start The start of the buffer, for bounds-checking.
* \param text The string to write.
* \param text_len The length of \p text in bytes (which might
* be strictly larger than the number of characters).
*
* \return The number of bytes written to \p p on success.
* \return A negative error code on failure.
*/ */
int mbedtls_asn1_write_octet_string(unsigned char **p, unsigned char *start, int mbedtls_asn1_write_utf8_string( unsigned char **p, unsigned char *start,
const unsigned char *buf, size_t size); const char *text, size_t text_len );
/**
* \brief Write a string in ASN.1 format using the IA5String
* string encoding tag (#MBEDTLS_ASN1_IA5_STRING).
*
* \note This function works backwards in data buffer.
*
* \param p The reference to the current position pointer.
* \param start The start of the buffer, for bounds-checking.
* \param text The string to write.
* \param text_len The length of \p text in bytes (which might
* be strictly larger than the number of characters).
*
* \return The number of bytes written to \p p on success.
* \return A negative error code on failure.
*/
int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start,
const char *text, size_t text_len );
/**
* \brief Write a bitstring tag (#MBEDTLS_ASN1_BIT_STRING) and
* value in ASN.1 format.
*
* \note This function works backwards in data buffer.
*
* \param p The reference to the current position pointer.
* \param start The start of the buffer, for bounds-checking.
* \param buf The bitstring to write.
* \param bits The total number of bits in the bitstring.
*
* \return The number of bytes written to \p p on success.
* \return A negative error code on failure.
*/
int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start,
const unsigned char *buf, size_t bits );
/**
* \brief This function writes a named bitstring tag
* (#MBEDTLS_ASN1_BIT_STRING) and value in ASN.1 format.
*
* As stated in RFC 5280 Appendix B, trailing zeroes are
* omitted when encoding named bitstrings in DER.
*
* \note This function works backwards within the data buffer.
*
* \param p The reference to the current position pointer.
* \param start The start of the buffer which is used for bounds-checking.
* \param buf The bitstring to write.
* \param bits The total number of bits in the bitstring.
*
* \return The number of bytes written to \p p on success.
* \return A negative error code on failure.
*/
int mbedtls_asn1_write_named_bitstring( unsigned char **p,
unsigned char *start,
const unsigned char *buf,
size_t bits );
/**
* \brief Write an octet string tag (#MBEDTLS_ASN1_OCTET_STRING)
* and value in ASN.1 format.
*
* \note This function works backwards in data buffer.
*
* \param p The reference to the current position pointer.
* \param start The start of the buffer, for bounds-checking.
* \param buf The buffer holding the data to write.
* \param size The length of the data buffer \p buf.
*
* \return The number of bytes written to \p p on success.
* \return A negative error code on failure.
*/
int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start,
const unsigned char *buf, size_t size );
/** /**
* \brief Create or find a specific named_data entry for writing in a * \brief Create or find a specific named_data entry for writing in a
@@ -220,20 +343,25 @@ int mbedtls_asn1_write_octet_string(unsigned char **p, unsigned char *start,
* a new entry is added to the head of the list. * a new entry is added to the head of the list.
* Warning: Destructive behaviour for the val data! * Warning: Destructive behaviour for the val data!
* *
* \param list Pointer to the location of the head of the list to seek * \param list The pointer to the location of the head of the list to seek
* through (will be updated in case of a new entry) * through (will be updated in case of a new entry).
* \param oid The OID to look for * \param oid The OID to look for.
* \param oid_len Size of the OID * \param oid_len The size of the OID.
* \param val Data to store (can be NULL if you want to fill it by hand) * \param val The associated data to store. If this is \c NULL,
* \param val_len Minimum length of the data buffer needed * no data is copied to the new or existing buffer.
* \param val_len The minimum length of the data buffer needed.
* If this is 0, do not allocate a buffer for the associated
* data.
* If the OID was already present, enlarge, shrink or free
* the existing buffer to fit \p val_len.
* *
* \return NULL if if there was a memory allocation error, or a pointer * \return A pointer to the new / existing entry on success.
* to the new / existing entry. * \return \c NULL if if there was a memory allocation error.
*/ */
mbedtls_asn1_named_data *mbedtls_asn1_store_named_data(mbedtls_asn1_named_data **list, mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **list,
const char *oid, size_t oid_len, const char *oid, size_t oid_len,
const unsigned char *val, const unsigned char *val,
size_t val_len); size_t val_len );
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -1,31 +1,23 @@
/* /*
* RFC 1521 base64 encoding/decoding * RFC 1521 base64 encoding/decoding
* *
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
#if !defined(MBEDTLS_CONFIG_FILE) #include "common.h"
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_BASE64_C) #if defined(MBEDTLS_BASE64_C)
@@ -43,7 +35,8 @@
#endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_SELF_TEST */
static const unsigned char base64_enc_map[64] = { static const unsigned char base64_enc_map[64] =
{
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
@@ -53,74 +46,185 @@ static const unsigned char base64_enc_map[64] = {
'8', '9', '+', '/' '8', '9', '+', '/'
}; };
static const unsigned char base64_dec_map[128] = { static const unsigned char base64_dec_map[128] =
{
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
127, 127, 127, 62, 127, 127, 127, 63, 52, 53, 127, 127, 127, 62, 127, 127, 127, 63, 52, 53,
54, 55, 56, 57, 58, 59, 60, 61, 127, 127, 54, 55, 56, 57, 58, 59, 60, 61, 127, 127,
127, 64, 127, 127, 127, 0, 1, 2, 3, 4, 127, 64, 127, 127, 127, 0, 1, 2, 3, 4,
5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 127, 127, 127, 127, 127, 127, 26, 27, 28, 25, 127, 127, 127, 127, 127, 127, 26, 27, 28,
29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 127, 127, 127, 127, 127 49, 50, 51, 127, 127, 127, 127, 127
}; };
#define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ #define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
/*
* Constant flow conditional assignment to unsigned char
*/
static void mbedtls_base64_cond_assign_uchar( unsigned char * dest, const unsigned char * const src,
unsigned char condition )
{
/* MSVC has a warning about unary minus on unsigned integer types,
* but this is well-defined and precisely what we want to do here. */
#if defined(_MSC_VER)
#pragma warning( push )
#pragma warning( disable : 4146 )
#endif
/* Generate bitmask from condition, mask will either be 0xFF or 0 */
unsigned char mask = ( condition | -condition );
mask >>= 7;
mask = -mask;
#if defined(_MSC_VER)
#pragma warning( pop )
#endif
*dest = ( ( *src ) & mask ) | ( ( *dest ) & ~mask );
}
/*
* Constant flow conditional assignment to uint_32
*/
static void mbedtls_base64_cond_assign_uint32( uint32_t * dest, const uint32_t src,
uint32_t condition )
{
/* MSVC has a warning about unary minus on unsigned integer types,
* but this is well-defined and precisely what we want to do here. */
#if defined(_MSC_VER)
#pragma warning( push )
#pragma warning( disable : 4146 )
#endif
/* Generate bitmask from condition, mask will either be 0xFFFFFFFF or 0 */
uint32_t mask = ( condition | -condition );
mask >>= 31;
mask = -mask;
#if defined(_MSC_VER)
#pragma warning( pop )
#endif
*dest = ( src & mask ) | ( ( *dest ) & ~mask );
}
/*
* Constant flow check for equality
*/
static unsigned char mbedtls_base64_eq( size_t in_a, size_t in_b )
{
size_t difference = in_a ^ in_b;
/* MSVC has a warning about unary minus on unsigned integer types,
* but this is well-defined and precisely what we want to do here. */
#if defined(_MSC_VER)
#pragma warning( push )
#pragma warning( disable : 4146 )
#endif
difference |= -difference;
#if defined(_MSC_VER)
#pragma warning( pop )
#endif
/* cope with the varying size of size_t per platform */
difference >>= ( sizeof( difference ) * 8 - 1 );
return (unsigned char) ( 1 ^ difference );
}
/*
* Constant flow lookup into table.
*/
static unsigned char mbedtls_base64_table_lookup( const unsigned char * const table,
const size_t table_size, const size_t table_index )
{
size_t i;
unsigned char result = 0;
for( i = 0; i < table_size; ++i )
{
mbedtls_base64_cond_assign_uchar( &result, &table[i], mbedtls_base64_eq( i, table_index ) );
}
return result;
}
/* /*
* Encode a buffer into base64 format * Encode a buffer into base64 format
*/ */
int mbedtls_base64_encode(unsigned char *dst, size_t dlen, size_t *olen, int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
const unsigned char *src, size_t slen) { const unsigned char *src, size_t slen )
{
size_t i, n; size_t i, n;
int C1, C2, C3; int C1, C2, C3;
unsigned char *p; unsigned char *p;
if (slen == 0) { if( slen == 0 )
{
*olen = 0; *olen = 0;
return (0); return( 0 );
} }
n = slen / 3 + (slen % 3 != 0); n = slen / 3 + ( slen % 3 != 0 );
if (n > (BASE64_SIZE_T_MAX - 1) / 4) { if( n > ( BASE64_SIZE_T_MAX - 1 ) / 4 )
{
*olen = BASE64_SIZE_T_MAX; *olen = BASE64_SIZE_T_MAX;
return (MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL); return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
} }
n *= 4; n *= 4;
if ((dlen < n + 1) || (NULL == dst)) { if( ( dlen < n + 1 ) || ( NULL == dst ) )
{
*olen = n + 1; *olen = n + 1;
return (MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL); return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
} }
n = (slen / 3) * 3; n = ( slen / 3 ) * 3;
for (i = 0, p = dst; i < n; i += 3) { for( i = 0, p = dst; i < n; i += 3 )
{
C1 = *src++; C1 = *src++;
C2 = *src++; C2 = *src++;
C3 = *src++; C3 = *src++;
*p++ = base64_enc_map[(C1 >> 2) & 0x3F]; *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
*p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; ( ( C1 >> 2 ) & 0x3F ) );
*p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
*p++ = base64_enc_map[C3 & 0x3F]; *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F ) );
*p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
( ( ( ( C2 & 15 ) << 2 ) + ( C3 >> 6 ) ) & 0x3F ) );
*p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
( C3 & 0x3F ) );
} }
if (i < slen) { if( i < slen )
{
C1 = *src++; C1 = *src++;
C2 = ((i + 1) < slen) ? *src++ : 0; C2 = ( ( i + 1 ) < slen ) ? *src++ : 0;
*p++ = base64_enc_map[(C1 >> 2) & 0x3F]; *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
*p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; ( ( C1 >> 2 ) & 0x3F ) );
if ((i + 1) < slen) *p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
*p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F]; ( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) & 0x3F ) );
if( ( i + 1 ) < slen )
*p++ = mbedtls_base64_table_lookup( base64_enc_map, sizeof( base64_enc_map ),
( ( ( C2 & 15 ) << 2 ) & 0x3F ) );
else *p++ = '='; else *p++ = '=';
*p++ = '='; *p++ = '=';
@@ -129,94 +233,107 @@ int mbedtls_base64_encode(unsigned char *dst, size_t dlen, size_t *olen,
*olen = p - dst; *olen = p - dst;
*p = 0; *p = 0;
return (0); return( 0 );
} }
/* /*
* Decode a base64-formatted buffer * Decode a base64-formatted buffer
*/ */
int mbedtls_base64_decode(unsigned char *dst, size_t dlen, size_t *olen, int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
const unsigned char *src, size_t slen) { const unsigned char *src, size_t slen )
{
size_t i, n; size_t i, n;
uint32_t j, x; uint32_t j, x;
unsigned char *p; unsigned char *p;
unsigned char dec_map_lookup;
/* First pass: check for validity and get output length */ /* First pass: check for validity and get output length */
for (i = n = j = 0; i < slen; i++) { for( i = n = j = 0; i < slen; i++ )
{
/* Skip spaces before checking for EOL */ /* Skip spaces before checking for EOL */
x = 0; x = 0;
while (i < slen && src[i] == ' ') { while( i < slen && src[i] == ' ' )
{
++i; ++i;
++x; ++x;
} }
/* Spaces at end of buffer are OK */ /* Spaces at end of buffer are OK */
if (i == slen) if( i == slen )
break; break;
if ((slen - i) >= 2 && if( ( slen - i ) >= 2 &&
src[i] == '\r' && src[i + 1] == '\n') src[i] == '\r' && src[i + 1] == '\n' )
continue; continue;
if (src[i] == '\n') if( src[i] == '\n' )
continue; continue;
/* Space inside a line is an error */ /* Space inside a line is an error */
if (x != 0) if( x != 0 )
return (MBEDTLS_ERR_BASE64_INVALID_CHARACTER); return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
if (src[i] == '=' && ++j > 2) if( src[i] == '=' && ++j > 2 )
return (MBEDTLS_ERR_BASE64_INVALID_CHARACTER); return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
if (src[i] > 127 || base64_dec_map[src[i]] == 127) dec_map_lookup = mbedtls_base64_table_lookup( base64_dec_map, sizeof( base64_dec_map ), src[i] );
return (MBEDTLS_ERR_BASE64_INVALID_CHARACTER);
if (base64_dec_map[src[i]] < 64 && j != 0) if( src[i] > 127 || dec_map_lookup == 127 )
return (MBEDTLS_ERR_BASE64_INVALID_CHARACTER); return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
if( dec_map_lookup < 64 && j != 0 )
return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER );
n++; n++;
} }
if (n == 0) { if( n == 0 )
{
*olen = 0; *olen = 0;
return (0); return( 0 );
} }
/* The following expression is to calculate the following formula without /* The following expression is to calculate the following formula without
* risk of integer overflow in n: * risk of integer overflow in n:
* n = ( ( n * 6 ) + 7 ) >> 3; * n = ( ( n * 6 ) + 7 ) >> 3;
*/ */
n = (6 * (n >> 3)) + ((6 * (n & 0x7) + 7) >> 3); n = ( 6 * ( n >> 3 ) ) + ( ( 6 * ( n & 0x7 ) + 7 ) >> 3 );
n -= j; n -= j;
if (dst == NULL || dlen < n) { if( dst == NULL || dlen < n )
{
*olen = n; *olen = n;
return (MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL); return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
} }
for (j = 3, n = x = 0, p = dst; i > 0; i--, src++) { for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
if (*src == '\r' || *src == '\n' || *src == ' ') {
if( *src == '\r' || *src == '\n' || *src == ' ' )
continue; continue;
j -= (base64_dec_map[*src] == 64); dec_map_lookup = mbedtls_base64_table_lookup( base64_dec_map, sizeof( base64_dec_map ), *src );
x = (x << 6) | (base64_dec_map[*src] & 0x3F);
if (++n == 4) { mbedtls_base64_cond_assign_uint32( &j, j - 1, mbedtls_base64_eq( dec_map_lookup, 64 ) );
x = ( x << 6 ) | ( dec_map_lookup & 0x3F );
if( ++n == 4 )
{
n = 0; n = 0;
if (j > 0) *p++ = (unsigned char)(x >> 16); if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
if (j > 1) *p++ = (unsigned char)(x >> 8); if( j > 1 ) *p++ = (unsigned char)( x >> 8 );
if (j > 2) *p++ = (unsigned char)(x); if( j > 2 ) *p++ = (unsigned char)( x );
} }
} }
*olen = p - dst; *olen = p - dst;
return (0); return( 0 );
} }
#if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_SELF_TEST)
static const unsigned char base64_test_dec[64] = { static const unsigned char base64_test_dec[64] =
{
0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD, 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD,
0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01, 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01,
0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09, 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09,
@@ -234,41 +351,44 @@ static const unsigned char base64_test_enc[] =
/* /*
* Checkup routine * Checkup routine
*/ */
int mbedtls_base64_self_test(int verbose) { int mbedtls_base64_self_test( int verbose )
{
size_t len; size_t len;
const unsigned char *src; const unsigned char *src;
unsigned char buffer[128]; unsigned char buffer[128];
if (verbose != 0) if( verbose != 0 )
mbedtls_printf(" Base64 encoding test: "); mbedtls_printf( " Base64 encoding test: " );
src = base64_test_dec; src = base64_test_dec;
if (mbedtls_base64_encode(buffer, sizeof(buffer), &len, src, 64) != 0 || if( mbedtls_base64_encode( buffer, sizeof( buffer ), &len, src, 64 ) != 0 ||
memcmp(base64_test_enc, buffer, 88) != 0) { memcmp( base64_test_enc, buffer, 88 ) != 0 )
if (verbose != 0) {
mbedtls_printf("failed\n"); if( verbose != 0 )
mbedtls_printf( "failed\n" );
return (1); return( 1 );
} }
if (verbose != 0) if( verbose != 0 )
mbedtls_printf("passed\n Base64 decoding test: "); mbedtls_printf( "passed\n Base64 decoding test: " );
src = base64_test_enc; src = base64_test_enc;
if (mbedtls_base64_decode(buffer, sizeof(buffer), &len, src, 88) != 0 || if( mbedtls_base64_decode( buffer, sizeof( buffer ), &len, src, 88 ) != 0 ||
memcmp(base64_test_dec, buffer, 64) != 0) { memcmp( base64_test_dec, buffer, 64 ) != 0 )
if (verbose != 0) {
mbedtls_printf("failed\n"); if( verbose != 0 )
mbedtls_printf( "failed\n" );
return (1); return( 1 );
} }
if (verbose != 0) if( verbose != 0 )
mbedtls_printf("passed\n\n"); mbedtls_printf( "passed\n\n" );
return (0); return( 0 );
} }
#endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_SELF_TEST */

View File

@@ -4,28 +4,30 @@
* \brief RFC 1521 base64 encoding/decoding * \brief RFC 1521 base64 encoding/decoding
*/ */
/* /*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
#ifndef MBEDTLS_BASE64_H #ifndef MBEDTLS_BASE64_H
#define MBEDTLS_BASE64_H #define MBEDTLS_BASE64_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include <stddef.h> #include <stddef.h>
#define MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL -0x002A /**< Output buffer too small. */ #define MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL -0x002A /**< Output buffer too small. */
@@ -54,8 +56,8 @@ extern "C" {
* \note Call this function with dlen = 0 to obtain the * \note Call this function with dlen = 0 to obtain the
* required buffer size in *olen * required buffer size in *olen
*/ */
int mbedtls_base64_encode(unsigned char *dst, size_t dlen, size_t *olen, int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
const unsigned char *src, size_t slen); const unsigned char *src, size_t slen );
/** /**
* \brief Decode a base64-formatted buffer * \brief Decode a base64-formatted buffer
@@ -74,15 +76,18 @@ int mbedtls_base64_encode(unsigned char *dst, size_t dlen, size_t *olen,
* \note Call this function with *dst = NULL or dlen = 0 to obtain * \note Call this function with *dst = NULL or dlen = 0 to obtain
* the required buffer size in *olen * the required buffer size in *olen
*/ */
int mbedtls_base64_decode(unsigned char *dst, size_t dlen, size_t *olen, int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
const unsigned char *src, size_t slen); const unsigned char *src, size_t slen );
#if defined(MBEDTLS_SELF_TEST)
/** /**
* \brief Checkup routine * \brief Checkup routine
* *
* \return 0 if successful, or 1 if the test failed * \return 0 if successful, or 1 if the test failed
*/ */
int mbedtls_base64_self_test(int verbose); int mbedtls_base64_self_test( int verbose );
#endif /* MBEDTLS_SELF_TEST */
#ifdef __cplusplus #ifdef __cplusplus
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,24 +1,20 @@
/* /*
* Blowfish implementation * Blowfish implementation
* *
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
/* /*
* The Blowfish block cipher was designed by Bruce Schneier in 1993. * The Blowfish block cipher was designed by Bruce Schneier in 1993.
@@ -27,11 +23,7 @@
* *
*/ */
#if !defined(MBEDTLS_CONFIG_FILE) #include "common.h"
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_BLOWFISH_C) #if defined(MBEDTLS_BLOWFISH_C)
@@ -42,68 +34,77 @@
#if !defined(MBEDTLS_BLOWFISH_ALT) #if !defined(MBEDTLS_BLOWFISH_ALT)
/* Parameter validation macros */
#define BLOWFISH_VALIDATE_RET( cond ) \
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA )
#define BLOWFISH_VALIDATE( cond ) \
MBEDTLS_INTERNAL_VALIDATE( cond )
/* /*
* 32-bit integer manipulation macros (big endian) * 32-bit integer manipulation macros (big endian)
*/ */
#ifndef GET_UINT32_BE #ifndef GET_UINT32_BE
#define GET_UINT32_BE(n,b,i) \ #define GET_UINT32_BE(n,b,i) \
{ \ { \
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \ (n) = ( (uint32_t) (b)[(i) ] << 24 ) \
| ( (uint32_t) (b)[(i) + 1] << 16 ) \ | ( (uint32_t) (b)[(i) + 1] << 16 ) \
| ( (uint32_t) (b)[(i) + 2] << 8 ) \ | ( (uint32_t) (b)[(i) + 2] << 8 ) \
| ( (uint32_t) (b)[(i) + 3] ); \ | ( (uint32_t) (b)[(i) + 3] ); \
} }
#endif #endif
#ifndef PUT_UINT32_BE #ifndef PUT_UINT32_BE
#define PUT_UINT32_BE(n,b,i) \ #define PUT_UINT32_BE(n,b,i) \
{ \ { \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 3] = (unsigned char) ( (n) ); \ (b)[(i) + 3] = (unsigned char) ( (n) ); \
} }
#endif #endif
static const uint32_t P[MBEDTLS_BLOWFISH_ROUNDS + 2] = { static const uint32_t P[MBEDTLS_BLOWFISH_ROUNDS + 2] = {
0x243F6A88L, 0x85A308D3L, 0x13198A2EL, 0x03707344L, 0x243F6A88L, 0x85A308D3L, 0x13198A2EL, 0x03707344L,
0xA4093822L, 0x299F31D0L, 0x082EFA98L, 0xEC4E6C89L, 0xA4093822L, 0x299F31D0L, 0x082EFA98L, 0xEC4E6C89L,
0x452821E6L, 0x38D01377L, 0xBE5466CFL, 0x34E90C6CL, 0x452821E6L, 0x38D01377L, 0xBE5466CFL, 0x34E90C6CL,
0xC0AC29B7L, 0xC97C50DDL, 0x3F84D5B5L, 0xB5470917L, 0xC0AC29B7L, 0xC97C50DDL, 0x3F84D5B5L, 0xB5470917L,
0x9216D5D9L, 0x8979FB1BL 0x9216D5D9L, 0x8979FB1BL
}; };
/* declarations of data at the end of this file */ /* declarations of data at the end of this file */
static const uint32_t S[4][256]; static const uint32_t S[4][256];
static uint32_t F(mbedtls_blowfish_context *ctx, uint32_t x) { static uint32_t F( mbedtls_blowfish_context *ctx, uint32_t x )
unsigned short a, b, c, d; {
uint32_t y; unsigned short a, b, c, d;
uint32_t y;
d = (unsigned short)(x & 0xFF); d = (unsigned short)(x & 0xFF);
x >>= 8; x >>= 8;
c = (unsigned short)(x & 0xFF); c = (unsigned short)(x & 0xFF);
x >>= 8; x >>= 8;
b = (unsigned short)(x & 0xFF); b = (unsigned short)(x & 0xFF);
x >>= 8; x >>= 8;
a = (unsigned short)(x & 0xFF); a = (unsigned short)(x & 0xFF);
y = ctx->S[0][a] + ctx->S[1][b]; y = ctx->S[0][a] + ctx->S[1][b];
y = y ^ ctx->S[2][c]; y = y ^ ctx->S[2][c];
y = y + ctx->S[3][d]; y = y + ctx->S[3][d];
return (y); return( y );
} }
static void blowfish_enc(mbedtls_blowfish_context *ctx, uint32_t *xl, uint32_t *xr) { static void blowfish_enc( mbedtls_blowfish_context *ctx, uint32_t *xl, uint32_t *xr )
{
uint32_t Xl, Xr, temp; uint32_t Xl, Xr, temp;
short i; short i;
Xl = *xl; Xl = *xl;
Xr = *xr; Xr = *xr;
for (i = 0; i < MBEDTLS_BLOWFISH_ROUNDS; ++i) { for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS; ++i )
{
Xl = Xl ^ ctx->P[i]; Xl = Xl ^ ctx->P[i];
Xr = F(ctx, Xl) ^ Xr; Xr = F( ctx, Xl ) ^ Xr;
temp = Xl; temp = Xl;
Xl = Xr; Xl = Xr;
@@ -121,16 +122,18 @@ static void blowfish_enc(mbedtls_blowfish_context *ctx, uint32_t *xl, uint32_t *
*xr = Xr; *xr = Xr;
} }
static void blowfish_dec(mbedtls_blowfish_context *ctx, uint32_t *xl, uint32_t *xr) { static void blowfish_dec( mbedtls_blowfish_context *ctx, uint32_t *xl, uint32_t *xr )
{
uint32_t Xl, Xr, temp; uint32_t Xl, Xr, temp;
short i; short i;
Xl = *xl; Xl = *xl;
Xr = *xr; Xr = *xr;
for (i = MBEDTLS_BLOWFISH_ROUNDS + 1; i > 1; --i) { for( i = MBEDTLS_BLOWFISH_ROUNDS + 1; i > 1; --i )
{
Xl = Xl ^ ctx->P[i]; Xl = Xl ^ ctx->P[i];
Xr = F(ctx, Xl) ^ Xr; Xr = F( ctx, Xl ) ^ Xr;
temp = Xl; temp = Xl;
Xl = Xr; Xl = Xr;
@@ -148,43 +151,55 @@ static void blowfish_dec(mbedtls_blowfish_context *ctx, uint32_t *xl, uint32_t *
*xr = Xr; *xr = Xr;
} }
void mbedtls_blowfish_init(mbedtls_blowfish_context *ctx) { void mbedtls_blowfish_init( mbedtls_blowfish_context *ctx )
memset(ctx, 0, sizeof(mbedtls_blowfish_context)); {
BLOWFISH_VALIDATE( ctx != NULL );
memset( ctx, 0, sizeof( mbedtls_blowfish_context ) );
} }
void mbedtls_blowfish_free(mbedtls_blowfish_context *ctx) { void mbedtls_blowfish_free( mbedtls_blowfish_context *ctx )
if (ctx == NULL) {
if( ctx == NULL )
return; return;
mbedtls_platform_zeroize(ctx, sizeof(mbedtls_blowfish_context)); mbedtls_platform_zeroize( ctx, sizeof( mbedtls_blowfish_context ) );
} }
/* /*
* Blowfish key schedule * Blowfish key schedule
*/ */
int mbedtls_blowfish_setkey(mbedtls_blowfish_context *ctx, const unsigned char *key, int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx,
unsigned int keybits) { const unsigned char *key,
unsigned int keybits )
{
unsigned int i, j, k; unsigned int i, j, k;
uint32_t data, datal, datar; uint32_t data, datal, datar;
BLOWFISH_VALIDATE_RET( ctx != NULL );
BLOWFISH_VALIDATE_RET( key != NULL );
if (keybits < MBEDTLS_BLOWFISH_MIN_KEY_BITS || keybits > MBEDTLS_BLOWFISH_MAX_KEY_BITS || if( keybits < MBEDTLS_BLOWFISH_MIN_KEY_BITS ||
(keybits % 8)) { keybits > MBEDTLS_BLOWFISH_MAX_KEY_BITS ||
return (MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH); keybits % 8 != 0 )
{
return( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA );
} }
keybits >>= 3; keybits >>= 3;
for (i = 0; i < 4; i++) { for( i = 0; i < 4; i++ )
for (j = 0; j < 256; j++) {
for( j = 0; j < 256; j++ )
ctx->S[i][j] = S[i][j]; ctx->S[i][j] = S[i][j];
} }
j = 0; j = 0;
for (i = 0; i < MBEDTLS_BLOWFISH_ROUNDS + 2; ++i) { for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS + 2; ++i )
{
data = 0x00000000; data = 0x00000000;
for (k = 0; k < 4; ++k) { for( k = 0; k < 4; ++k )
data = (data << 8) | key[j++]; {
if (j >= keybits) data = ( data << 8 ) | key[j++];
if( j >= keybits )
j = 0; j = 0;
} }
ctx->P[i] = P[i] ^ data; ctx->P[i] = P[i] ^ data;
@@ -193,83 +208,107 @@ int mbedtls_blowfish_setkey(mbedtls_blowfish_context *ctx, const unsigned char *
datal = 0x00000000; datal = 0x00000000;
datar = 0x00000000; datar = 0x00000000;
for (i = 0; i < MBEDTLS_BLOWFISH_ROUNDS + 2; i += 2) { for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS + 2; i += 2 )
blowfish_enc(ctx, &datal, &datar); {
blowfish_enc( ctx, &datal, &datar );
ctx->P[i] = datal; ctx->P[i] = datal;
ctx->P[i + 1] = datar; ctx->P[i + 1] = datar;
} }
for (i = 0; i < 4; i++) { for( i = 0; i < 4; i++ )
for (j = 0; j < 256; j += 2) { {
blowfish_enc(ctx, &datal, &datar); for( j = 0; j < 256; j += 2 )
{
blowfish_enc( ctx, &datal, &datar );
ctx->S[i][j] = datal; ctx->S[i][j] = datal;
ctx->S[i][j + 1] = datar; ctx->S[i][j + 1] = datar;
} }
} }
return (0); return( 0 );
} }
/* /*
* Blowfish-ECB block encryption/decryption * Blowfish-ECB block encryption/decryption
*/ */
int mbedtls_blowfish_crypt_ecb(mbedtls_blowfish_context *ctx, int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx,
int mode, int mode,
const unsigned char input[MBEDTLS_BLOWFISH_BLOCKSIZE], const unsigned char input[MBEDTLS_BLOWFISH_BLOCKSIZE],
unsigned char output[MBEDTLS_BLOWFISH_BLOCKSIZE]) { unsigned char output[MBEDTLS_BLOWFISH_BLOCKSIZE] )
{
uint32_t X0, X1; uint32_t X0, X1;
BLOWFISH_VALIDATE_RET( ctx != NULL );
BLOWFISH_VALIDATE_RET( mode == MBEDTLS_BLOWFISH_ENCRYPT ||
mode == MBEDTLS_BLOWFISH_DECRYPT );
BLOWFISH_VALIDATE_RET( input != NULL );
BLOWFISH_VALIDATE_RET( output != NULL );
GET_UINT32_BE(X0, input, 0); GET_UINT32_BE( X0, input, 0 );
GET_UINT32_BE(X1, input, 4); GET_UINT32_BE( X1, input, 4 );
if (mode == MBEDTLS_BLOWFISH_DECRYPT) { if( mode == MBEDTLS_BLOWFISH_DECRYPT )
blowfish_dec(ctx, &X0, &X1); {
} else { /* MBEDTLS_BLOWFISH_ENCRYPT */ blowfish_dec( ctx, &X0, &X1 );
blowfish_enc(ctx, &X0, &X1); }
else /* MBEDTLS_BLOWFISH_ENCRYPT */
{
blowfish_enc( ctx, &X0, &X1 );
} }
PUT_UINT32_BE(X0, output, 0); PUT_UINT32_BE( X0, output, 0 );
PUT_UINT32_BE(X1, output, 4); PUT_UINT32_BE( X1, output, 4 );
return (0); return( 0 );
} }
#if defined(MBEDTLS_CIPHER_MODE_CBC) #if defined(MBEDTLS_CIPHER_MODE_CBC)
/* /*
* Blowfish-CBC buffer encryption/decryption * Blowfish-CBC buffer encryption/decryption
*/ */
int mbedtls_blowfish_crypt_cbc(mbedtls_blowfish_context *ctx, int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx,
int mode, int mode,
size_t length, size_t length,
unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE],
const unsigned char *input, const unsigned char *input,
unsigned char *output) { unsigned char *output )
{
int i; int i;
unsigned char temp[MBEDTLS_BLOWFISH_BLOCKSIZE]; unsigned char temp[MBEDTLS_BLOWFISH_BLOCKSIZE];
BLOWFISH_VALIDATE_RET( ctx != NULL );
BLOWFISH_VALIDATE_RET( mode == MBEDTLS_BLOWFISH_ENCRYPT ||
mode == MBEDTLS_BLOWFISH_DECRYPT );
BLOWFISH_VALIDATE_RET( iv != NULL );
BLOWFISH_VALIDATE_RET( length == 0 || input != NULL );
BLOWFISH_VALIDATE_RET( length == 0 || output != NULL );
if (length % MBEDTLS_BLOWFISH_BLOCKSIZE) if( length % MBEDTLS_BLOWFISH_BLOCKSIZE )
return (MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH); return( MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH );
if (mode == MBEDTLS_BLOWFISH_DECRYPT) { if( mode == MBEDTLS_BLOWFISH_DECRYPT )
while (length > 0) { {
memcpy(temp, input, MBEDTLS_BLOWFISH_BLOCKSIZE); while( length > 0 )
mbedtls_blowfish_crypt_ecb(ctx, mode, input, output); {
memcpy( temp, input, MBEDTLS_BLOWFISH_BLOCKSIZE );
mbedtls_blowfish_crypt_ecb( ctx, mode, input, output );
for (i = 0; i < MBEDTLS_BLOWFISH_BLOCKSIZE; i++) for( i = 0; i < MBEDTLS_BLOWFISH_BLOCKSIZE;i++ )
output[i] = (unsigned char)(output[i] ^ iv[i]); output[i] = (unsigned char)( output[i] ^ iv[i] );
memcpy(iv, temp, MBEDTLS_BLOWFISH_BLOCKSIZE); memcpy( iv, temp, MBEDTLS_BLOWFISH_BLOCKSIZE );
input += MBEDTLS_BLOWFISH_BLOCKSIZE; input += MBEDTLS_BLOWFISH_BLOCKSIZE;
output += MBEDTLS_BLOWFISH_BLOCKSIZE; output += MBEDTLS_BLOWFISH_BLOCKSIZE;
length -= MBEDTLS_BLOWFISH_BLOCKSIZE; length -= MBEDTLS_BLOWFISH_BLOCKSIZE;
} }
} else { }
while (length > 0) { else
for (i = 0; i < MBEDTLS_BLOWFISH_BLOCKSIZE; i++) {
output[i] = (unsigned char)(input[i] ^ iv[i]); while( length > 0 )
{
for( i = 0; i < MBEDTLS_BLOWFISH_BLOCKSIZE; i++ )
output[i] = (unsigned char)( input[i] ^ iv[i] );
mbedtls_blowfish_crypt_ecb(ctx, mode, output, output); mbedtls_blowfish_crypt_ecb( ctx, mode, output, output );
memcpy(iv, output, MBEDTLS_BLOWFISH_BLOCKSIZE); memcpy( iv, output, MBEDTLS_BLOWFISH_BLOCKSIZE );
input += MBEDTLS_BLOWFISH_BLOCKSIZE; input += MBEDTLS_BLOWFISH_BLOCKSIZE;
output += MBEDTLS_BLOWFISH_BLOCKSIZE; output += MBEDTLS_BLOWFISH_BLOCKSIZE;
@@ -277,7 +316,7 @@ int mbedtls_blowfish_crypt_cbc(mbedtls_blowfish_context *ctx,
} }
} }
return (0); return( 0 );
} }
#endif /* MBEDTLS_CIPHER_MODE_CBC */ #endif /* MBEDTLS_CIPHER_MODE_CBC */
@@ -285,41 +324,59 @@ int mbedtls_blowfish_crypt_cbc(mbedtls_blowfish_context *ctx,
/* /*
* Blowfish CFB buffer encryption/decryption * Blowfish CFB buffer encryption/decryption
*/ */
int mbedtls_blowfish_crypt_cfb64(mbedtls_blowfish_context *ctx, int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx,
int mode, int mode,
size_t length, size_t length,
size_t *iv_off, size_t *iv_off,
unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE],
const unsigned char *input, const unsigned char *input,
unsigned char *output) { unsigned char *output )
{
int c; int c;
size_t n = *iv_off; size_t n;
if (mode == MBEDTLS_BLOWFISH_DECRYPT) { BLOWFISH_VALIDATE_RET( ctx != NULL );
while (length--) { BLOWFISH_VALIDATE_RET( mode == MBEDTLS_BLOWFISH_ENCRYPT ||
if (n == 0) mode == MBEDTLS_BLOWFISH_DECRYPT );
mbedtls_blowfish_crypt_ecb(ctx, MBEDTLS_BLOWFISH_ENCRYPT, iv, iv); BLOWFISH_VALIDATE_RET( iv != NULL );
BLOWFISH_VALIDATE_RET( iv_off != NULL );
BLOWFISH_VALIDATE_RET( length == 0 || input != NULL );
BLOWFISH_VALIDATE_RET( length == 0 || output != NULL );
n = *iv_off;
if( n >= 8 )
return( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA );
if( mode == MBEDTLS_BLOWFISH_DECRYPT )
{
while( length-- )
{
if( n == 0 )
mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, iv, iv );
c = *input++; c = *input++;
*output++ = (unsigned char)(c ^ iv[n]); *output++ = (unsigned char)( c ^ iv[n] );
iv[n] = (unsigned char) c; iv[n] = (unsigned char) c;
n = (n + 1) % MBEDTLS_BLOWFISH_BLOCKSIZE; n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE;
} }
} else { }
while (length--) { else
if (n == 0) {
mbedtls_blowfish_crypt_ecb(ctx, MBEDTLS_BLOWFISH_ENCRYPT, iv, iv); while( length-- )
{
if( n == 0 )
mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, iv, iv );
iv[n] = *output++ = (unsigned char)(iv[n] ^ *input++); iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
n = (n + 1) % MBEDTLS_BLOWFISH_BLOCKSIZE; n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE;
} }
} }
*iv_off = n; *iv_off = n;
return (0); return( 0 );
} }
#endif /*MBEDTLS_CIPHER_MODE_CFB */ #endif /*MBEDTLS_CIPHER_MODE_CFB */
@@ -327,40 +384,51 @@ int mbedtls_blowfish_crypt_cfb64(mbedtls_blowfish_context *ctx,
/* /*
* Blowfish CTR buffer encryption/decryption * Blowfish CTR buffer encryption/decryption
*/ */
int mbedtls_blowfish_crypt_ctr(mbedtls_blowfish_context *ctx, int mbedtls_blowfish_crypt_ctr( mbedtls_blowfish_context *ctx,
size_t length, size_t length,
size_t *nc_off, size_t *nc_off,
unsigned char nonce_counter[MBEDTLS_BLOWFISH_BLOCKSIZE], unsigned char nonce_counter[MBEDTLS_BLOWFISH_BLOCKSIZE],
unsigned char stream_block[MBEDTLS_BLOWFISH_BLOCKSIZE], unsigned char stream_block[MBEDTLS_BLOWFISH_BLOCKSIZE],
const unsigned char *input, const unsigned char *input,
unsigned char *output) { unsigned char *output )
{
int c, i; int c, i;
size_t n = *nc_off; size_t n;
BLOWFISH_VALIDATE_RET( ctx != NULL );
BLOWFISH_VALIDATE_RET( nonce_counter != NULL );
BLOWFISH_VALIDATE_RET( stream_block != NULL );
BLOWFISH_VALIDATE_RET( nc_off != NULL );
BLOWFISH_VALIDATE_RET( length == 0 || input != NULL );
BLOWFISH_VALIDATE_RET( length == 0 || output != NULL );
while (length--) { n = *nc_off;
if (n == 0) { if( n >= 8 )
mbedtls_blowfish_crypt_ecb(ctx, MBEDTLS_BLOWFISH_ENCRYPT, nonce_counter, return( MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA );
stream_block);
for (i = MBEDTLS_BLOWFISH_BLOCKSIZE; i > 0; i--) while( length-- )
if (++nonce_counter[i - 1] != 0) {
if( n == 0 ) {
mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, nonce_counter,
stream_block );
for( i = MBEDTLS_BLOWFISH_BLOCKSIZE; i > 0; i-- )
if( ++nonce_counter[i - 1] != 0 )
break; break;
} }
c = *input++; c = *input++;
*output++ = (unsigned char)(c ^ stream_block[n]); *output++ = (unsigned char)( c ^ stream_block[n] );
n = (n + 1) % MBEDTLS_BLOWFISH_BLOCKSIZE; n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE;
} }
*nc_off = n; *nc_off = n;
return (0); return( 0 );
} }
#endif /* MBEDTLS_CIPHER_MODE_CTR */ #endif /* MBEDTLS_CIPHER_MODE_CTR */
static const uint32_t S[4][256] = { static const uint32_t S[4][256] = {
{ { 0xD1310BA6L, 0x98DFB5ACL, 0x2FFD72DBL, 0xD01ADFB7L,
0xD1310BA6L, 0x98DFB5ACL, 0x2FFD72DBL, 0xD01ADFB7L,
0xB8E1AFEDL, 0x6A267E96L, 0xBA7C9045L, 0xF12C7F99L, 0xB8E1AFEDL, 0x6A267E96L, 0xBA7C9045L, 0xF12C7F99L,
0x24A19947L, 0xB3916CF7L, 0x0801F2E2L, 0x858EFC16L, 0x24A19947L, 0xB3916CF7L, 0x0801F2E2L, 0x858EFC16L,
0x636920D8L, 0x71574E69L, 0xA458FEA3L, 0xF4933D7EL, 0x636920D8L, 0x71574E69L, 0xA458FEA3L, 0xF4933D7EL,
@@ -423,10 +491,8 @@ static const uint32_t S[4][256] = {
0xD60F573FL, 0xBC9BC6E4L, 0x2B60A476L, 0x81E67400L, 0xD60F573FL, 0xBC9BC6E4L, 0x2B60A476L, 0x81E67400L,
0x08BA6FB5L, 0x571BE91FL, 0xF296EC6BL, 0x2A0DD915L, 0x08BA6FB5L, 0x571BE91FL, 0xF296EC6BL, 0x2A0DD915L,
0xB6636521L, 0xE7B9F9B6L, 0xFF34052EL, 0xC5855664L, 0xB6636521L, 0xE7B9F9B6L, 0xFF34052EL, 0xC5855664L,
0x53B02D5DL, 0xA99F8FA1L, 0x08BA4799L, 0x6E85076AL 0x53B02D5DL, 0xA99F8FA1L, 0x08BA4799L, 0x6E85076AL },
}, { 0x4B7A70E9L, 0xB5B32944L, 0xDB75092EL, 0xC4192623L,
{
0x4B7A70E9L, 0xB5B32944L, 0xDB75092EL, 0xC4192623L,
0xAD6EA6B0L, 0x49A7DF7DL, 0x9CEE60B8L, 0x8FEDB266L, 0xAD6EA6B0L, 0x49A7DF7DL, 0x9CEE60B8L, 0x8FEDB266L,
0xECAA8C71L, 0x699A17FFL, 0x5664526CL, 0xC2B19EE1L, 0xECAA8C71L, 0x699A17FFL, 0x5664526CL, 0xC2B19EE1L,
0x193602A5L, 0x75094C29L, 0xA0591340L, 0xE4183A3EL, 0x193602A5L, 0x75094C29L, 0xA0591340L, 0xE4183A3EL,
@@ -489,10 +555,8 @@ static const uint32_t S[4][256] = {
0x9E447A2EL, 0xC3453484L, 0xFDD56705L, 0x0E1E9EC9L, 0x9E447A2EL, 0xC3453484L, 0xFDD56705L, 0x0E1E9EC9L,
0xDB73DBD3L, 0x105588CDL, 0x675FDA79L, 0xE3674340L, 0xDB73DBD3L, 0x105588CDL, 0x675FDA79L, 0xE3674340L,
0xC5C43465L, 0x713E38D8L, 0x3D28F89EL, 0xF16DFF20L, 0xC5C43465L, 0x713E38D8L, 0x3D28F89EL, 0xF16DFF20L,
0x153E21E7L, 0x8FB03D4AL, 0xE6E39F2BL, 0xDB83ADF7L 0x153E21E7L, 0x8FB03D4AL, 0xE6E39F2BL, 0xDB83ADF7L },
}, { 0xE93D5A68L, 0x948140F7L, 0xF64C261CL, 0x94692934L,
{
0xE93D5A68L, 0x948140F7L, 0xF64C261CL, 0x94692934L,
0x411520F7L, 0x7602D4F7L, 0xBCF46B2EL, 0xD4A20068L, 0x411520F7L, 0x7602D4F7L, 0xBCF46B2EL, 0xD4A20068L,
0xD4082471L, 0x3320F46AL, 0x43B7D4B7L, 0x500061AFL, 0xD4082471L, 0x3320F46AL, 0x43B7D4B7L, 0x500061AFL,
0x1E39F62EL, 0x97244546L, 0x14214F74L, 0xBF8B8840L, 0x1E39F62EL, 0x97244546L, 0x14214F74L, 0xBF8B8840L,
@@ -555,10 +619,8 @@ static const uint32_t S[4][256] = {
0xED545578L, 0x08FCA5B5L, 0xD83D7CD3L, 0x4DAD0FC4L, 0xED545578L, 0x08FCA5B5L, 0xD83D7CD3L, 0x4DAD0FC4L,
0x1E50EF5EL, 0xB161E6F8L, 0xA28514D9L, 0x6C51133CL, 0x1E50EF5EL, 0xB161E6F8L, 0xA28514D9L, 0x6C51133CL,
0x6FD5C7E7L, 0x56E14EC4L, 0x362ABFCEL, 0xDDC6C837L, 0x6FD5C7E7L, 0x56E14EC4L, 0x362ABFCEL, 0xDDC6C837L,
0xD79A3234L, 0x92638212L, 0x670EFA8EL, 0x406000E0L 0xD79A3234L, 0x92638212L, 0x670EFA8EL, 0x406000E0L },
}, { 0x3A39CE37L, 0xD3FAF5CFL, 0xABC27737L, 0x5AC52D1BL,
{
0x3A39CE37L, 0xD3FAF5CFL, 0xABC27737L, 0x5AC52D1BL,
0x5CB0679EL, 0x4FA33742L, 0xD3822740L, 0x99BC9BBEL, 0x5CB0679EL, 0x4FA33742L, 0xD3822740L, 0x99BC9BBEL,
0xD5118E9DL, 0xBF0F7315L, 0xD62D1C7EL, 0xC700C47BL, 0xD5118E9DL, 0xBF0F7315L, 0xD62D1C7EL, 0xC700C47BL,
0xB78C1B6BL, 0x21A19045L, 0xB26EB1BEL, 0x6A366EB4L, 0xB78C1B6BL, 0x21A19045L, 0xB26EB1BEL, 0x6A366EB4L,
@@ -621,8 +683,7 @@ static const uint32_t S[4][256] = {
0x85CBFE4EL, 0x8AE88DD8L, 0x7AAAF9B0L, 0x4CF9AA7EL, 0x85CBFE4EL, 0x8AE88DD8L, 0x7AAAF9B0L, 0x4CF9AA7EL,
0x1948C25CL, 0x02FB8A8CL, 0x01C36AE4L, 0xD6EBE1F9L, 0x1948C25CL, 0x02FB8A8CL, 0x01C36AE4L, 0xD6EBE1F9L,
0x90D4F869L, 0xA65CDEA0L, 0x3F09252DL, 0xC208E69FL, 0x90D4F869L, 0xA65CDEA0L, 0x3F09252DL, 0xC208E69FL,
0xB74E6132L, 0xCE77E25BL, 0x578FDFE3L, 0x3AC372E6L 0xB74E6132L, 0xCE77E25BL, 0x578FDFE3L, 0x3AC372E6L }
}
}; };
#endif /* !MBEDTLS_BLOWFISH_ALT */ #endif /* !MBEDTLS_BLOWFISH_ALT */

View File

@@ -4,30 +4,26 @@
* \brief Blowfish block cipher * \brief Blowfish block cipher
*/ */
/* /*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
#ifndef MBEDTLS_BLOWFISH_H #ifndef MBEDTLS_BLOWFISH_H
#define MBEDTLS_BLOWFISH_H #define MBEDTLS_BLOWFISH_H
#if !defined(MBEDTLS_CONFIG_FILE) #if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h" #include "mbedtls/config.h"
#else #else
#include MBEDTLS_CONFIG_FILE #include MBEDTLS_CONFIG_FILE
#endif #endif
@@ -35,6 +31,8 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include "mbedtls/platform_util.h"
#define MBEDTLS_BLOWFISH_ENCRYPT 1 #define MBEDTLS_BLOWFISH_ENCRYPT 1
#define MBEDTLS_BLOWFISH_DECRYPT 0 #define MBEDTLS_BLOWFISH_DECRYPT 0
#define MBEDTLS_BLOWFISH_MAX_KEY_BITS 448 #define MBEDTLS_BLOWFISH_MAX_KEY_BITS 448
@@ -42,9 +40,16 @@
#define MBEDTLS_BLOWFISH_ROUNDS 16 /**< Rounds to use. When increasing this value, make sure to extend the initialisation vectors */ #define MBEDTLS_BLOWFISH_ROUNDS 16 /**< Rounds to use. When increasing this value, make sure to extend the initialisation vectors */
#define MBEDTLS_BLOWFISH_BLOCKSIZE 8 /* Blowfish uses 64 bit blocks */ #define MBEDTLS_BLOWFISH_BLOCKSIZE 8 /* Blowfish uses 64 bit blocks */
#define MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH -0x0016 /**< Invalid key length. */ #if !defined(MBEDTLS_DEPRECATED_REMOVED)
#define MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( -0x0016 )
#endif /* !MBEDTLS_DEPRECATED_REMOVED */
#define MBEDTLS_ERR_BLOWFISH_BAD_INPUT_DATA -0x0016 /**< Bad input data. */
#define MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH -0x0018 /**< Invalid data input length. */
/* MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED is deprecated and should not be used.
*/
#define MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED -0x0017 /**< Blowfish hardware accelerator failed. */ #define MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED -0x0017 /**< Blowfish hardware accelerator failed. */
#define MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH -0x0018 /**< Invalid data input length. */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@@ -57,7 +62,8 @@ extern "C" {
/** /**
* \brief Blowfish context structure * \brief Blowfish context structure
*/ */
typedef struct mbedtls_blowfish_context { typedef struct mbedtls_blowfish_context
{
uint32_t P[MBEDTLS_BLOWFISH_ROUNDS + 2]; /*!< Blowfish round keys */ uint32_t P[MBEDTLS_BLOWFISH_ROUNDS + 2]; /*!< Blowfish round keys */
uint32_t S[4][256]; /*!< key dependent S-boxes */ uint32_t S[4][256]; /*!< key dependent S-boxes */
} }
@@ -68,51 +74,62 @@ mbedtls_blowfish_context;
#endif /* MBEDTLS_BLOWFISH_ALT */ #endif /* MBEDTLS_BLOWFISH_ALT */
/** /**
* \brief Initialize Blowfish context * \brief Initialize a Blowfish context.
* *
* \param ctx Blowfish context to be initialized * \param ctx The Blowfish context to be initialized.
* This must not be \c NULL.
*/ */
void mbedtls_blowfish_init(mbedtls_blowfish_context *ctx); void mbedtls_blowfish_init( mbedtls_blowfish_context *ctx );
/** /**
* \brief Clear Blowfish context * \brief Clear a Blowfish context.
* *
* \param ctx Blowfish context to be cleared * \param ctx The Blowfish context to be cleared.
* This may be \c NULL, in which case this function
* returns immediately. If it is not \c NULL, it must
* point to an initialized Blowfish context.
*/ */
void mbedtls_blowfish_free(mbedtls_blowfish_context *ctx); void mbedtls_blowfish_free( mbedtls_blowfish_context *ctx );
/** /**
* \brief Blowfish key schedule * \brief Perform a Blowfish key schedule operation.
* *
* \param ctx Blowfish context to be initialized * \param ctx The Blowfish context to perform the key schedule on.
* \param key encryption key * \param key The encryption key. This must be a readable buffer of
* \param keybits must be between 32 and 448 bits * length \p keybits Bits.
* \param keybits The length of \p key in Bits. This must be between
* \c 32 and \c 448 and a multiple of \c 8.
* *
* \return 0 if successful, or MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH * \return \c 0 if successful.
* \return A negative error code on failure.
*/ */
int mbedtls_blowfish_setkey(mbedtls_blowfish_context *ctx, const unsigned char *key, int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx, const unsigned char *key,
unsigned int keybits); unsigned int keybits );
/** /**
* \brief Blowfish-ECB block encryption/decryption * \brief Perform a Blowfish-ECB block encryption/decryption operation.
* *
* \param ctx Blowfish context * \param ctx The Blowfish context to use. This must be initialized
* \param mode MBEDTLS_BLOWFISH_ENCRYPT or MBEDTLS_BLOWFISH_DECRYPT * and bound to a key.
* \param input 8-byte input block * \param mode The mode of operation. Possible values are
* \param output 8-byte output block * #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or
* #MBEDTLS_BLOWFISH_DECRYPT for decryption.
* \param input The input block. This must be a readable buffer
* of size \c 8 Bytes.
* \param output The output block. This must be a writable buffer
* of size \c 8 Bytes.
* *
* \return 0 if successful * \return \c 0 if successful.
* \return A negative error code on failure.
*/ */
int mbedtls_blowfish_crypt_ecb(mbedtls_blowfish_context *ctx, int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx,
int mode, int mode,
const unsigned char input[MBEDTLS_BLOWFISH_BLOCKSIZE], const unsigned char input[MBEDTLS_BLOWFISH_BLOCKSIZE],
unsigned char output[MBEDTLS_BLOWFISH_BLOCKSIZE]); unsigned char output[MBEDTLS_BLOWFISH_BLOCKSIZE] );
#if defined(MBEDTLS_CIPHER_MODE_CBC) #if defined(MBEDTLS_CIPHER_MODE_CBC)
/** /**
* \brief Blowfish-CBC buffer encryption/decryption * \brief Perform a Blowfish-CBC buffer encryption/decryption operation.
* Length should be a multiple of the block
* size (8 bytes)
* *
* \note Upon exit, the content of the IV is updated so that you can * \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following * call the function same function again on the following
@@ -122,27 +139,34 @@ int mbedtls_blowfish_crypt_ecb(mbedtls_blowfish_context *ctx,
* IV, you should either save it manually or use the cipher * IV, you should either save it manually or use the cipher
* module instead. * module instead.
* *
* \param ctx Blowfish context * \param ctx The Blowfish context to use. This must be initialized
* \param mode MBEDTLS_BLOWFISH_ENCRYPT or MBEDTLS_BLOWFISH_DECRYPT * and bound to a key.
* \param length length of the input data * \param mode The mode of operation. Possible values are
* \param iv initialization vector (updated after use) * #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or
* \param input buffer holding the input data * #MBEDTLS_BLOWFISH_DECRYPT for decryption.
* \param output buffer holding the output data * \param length The length of the input data in Bytes. This must be
* multiple of \c 8.
* \param iv The initialization vector. This must be a read/write buffer
* of length \c 8 Bytes. It is updated by this function.
* \param input The input data. This must be a readable buffer of length
* \p length Bytes.
* \param output The output data. This must be a writable buffer of length
* \p length Bytes.
* *
* \return 0 if successful, or * \return \c 0 if successful.
* MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH * \return A negative error code on failure.
*/ */
int mbedtls_blowfish_crypt_cbc(mbedtls_blowfish_context *ctx, int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx,
int mode, int mode,
size_t length, size_t length,
unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE],
const unsigned char *input, const unsigned char *input,
unsigned char *output); unsigned char *output );
#endif /* MBEDTLS_CIPHER_MODE_CBC */ #endif /* MBEDTLS_CIPHER_MODE_CBC */
#if defined(MBEDTLS_CIPHER_MODE_CFB) #if defined(MBEDTLS_CIPHER_MODE_CFB)
/** /**
* \brief Blowfish CFB buffer encryption/decryption. * \brief Perform a Blowfish CFB buffer encryption/decryption operation.
* *
* \note Upon exit, the content of the IV is updated so that you can * \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following * call the function same function again on the following
@@ -152,28 +176,38 @@ int mbedtls_blowfish_crypt_cbc(mbedtls_blowfish_context *ctx,
* IV, you should either save it manually or use the cipher * IV, you should either save it manually or use the cipher
* module instead. * module instead.
* *
* \param ctx Blowfish context * \param ctx The Blowfish context to use. This must be initialized
* \param mode MBEDTLS_BLOWFISH_ENCRYPT or MBEDTLS_BLOWFISH_DECRYPT * and bound to a key.
* \param length length of the input data * \param mode The mode of operation. Possible values are
* \param iv_off offset in IV (updated after use) * #MBEDTLS_BLOWFISH_ENCRYPT for encryption, or
* \param iv initialization vector (updated after use) * #MBEDTLS_BLOWFISH_DECRYPT for decryption.
* \param input buffer holding the input data * \param length The length of the input data in Bytes.
* \param output buffer holding the output data * \param iv_off The offset in the initialiation vector.
* The value pointed to must be smaller than \c 8 Bytes.
* It is updated by this function to support the aforementioned
* streaming usage.
* \param iv The initialization vector. This must be a read/write buffer
* of size \c 8 Bytes. It is updated after use.
* \param input The input data. This must be a readable buffer of length
* \p length Bytes.
* \param output The output data. This must be a writable buffer of length
* \p length Bytes.
* *
* \return 0 if successful * \return \c 0 if successful.
* \return A negative error code on failure.
*/ */
int mbedtls_blowfish_crypt_cfb64(mbedtls_blowfish_context *ctx, int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx,
int mode, int mode,
size_t length, size_t length,
size_t *iv_off, size_t *iv_off,
unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE],
const unsigned char *input, const unsigned char *input,
unsigned char *output); unsigned char *output );
#endif /*MBEDTLS_CIPHER_MODE_CFB */ #endif /*MBEDTLS_CIPHER_MODE_CFB */
#if defined(MBEDTLS_CIPHER_MODE_CTR) #if defined(MBEDTLS_CIPHER_MODE_CTR)
/** /**
* \brief Blowfish-CTR buffer encryption/decryption * \brief Perform a Blowfish-CTR buffer encryption/decryption operation.
* *
* \warning You must never reuse a nonce value with the same key. Doing so * \warning You must never reuse a nonce value with the same key. Doing so
* would void the encryption for the two messages encrypted with * would void the encryption for the two messages encrypted with
@@ -216,26 +250,32 @@ int mbedtls_blowfish_crypt_cfb64(mbedtls_blowfish_context *ctx,
* content must not be written to insecure storage and should be * content must not be written to insecure storage and should be
* securely discarded as soon as it's no longer needed. * securely discarded as soon as it's no longer needed.
* *
* \param ctx Blowfish context * \param ctx The Blowfish context to use. This must be initialized
* \param length The length of the data * and bound to a key.
* \param length The length of the input data in Bytes.
* \param nc_off The offset in the current stream_block (for resuming * \param nc_off The offset in the current stream_block (for resuming
* within current cipher stream). The offset pointer to * within current cipher stream). The offset pointer
* should be 0 at the start of a stream. * should be \c 0 at the start of a stream and must be
* \param nonce_counter The 64-bit nonce and counter. * smaller than \c 8. It is updated by this function.
* \param stream_block The saved stream-block for resuming. Is overwritten * \param nonce_counter The 64-bit nonce and counter. This must point to a
* by the function. * read/write buffer of length \c 8 Bytes.
* \param input The input data stream * \param stream_block The saved stream-block for resuming. This must point to
* \param output The output data stream * a read/write buffer of length \c 8 Bytes.
* \param input The input data. This must be a readable buffer of
* length \p length Bytes.
* \param output The output data. This must be a writable buffer of
* length \p length Bytes.
* *
* \return 0 if successful * \return \c 0 if successful.
* \return A negative error code on failure.
*/ */
int mbedtls_blowfish_crypt_ctr(mbedtls_blowfish_context *ctx, int mbedtls_blowfish_crypt_ctr( mbedtls_blowfish_context *ctx,
size_t length, size_t length,
size_t *nc_off, size_t *nc_off,
unsigned char nonce_counter[MBEDTLS_BLOWFISH_BLOCKSIZE], unsigned char nonce_counter[MBEDTLS_BLOWFISH_BLOCKSIZE],
unsigned char stream_block[MBEDTLS_BLOWFISH_BLOCKSIZE], unsigned char stream_block[MBEDTLS_BLOWFISH_BLOCKSIZE],
const unsigned char *input, const unsigned char *input,
unsigned char *output); unsigned char *output );
#endif /* MBEDTLS_CIPHER_MODE_CTR */ #endif /* MBEDTLS_CIPHER_MODE_CTR */
#ifdef __cplusplus #ifdef __cplusplus

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -4,30 +4,26 @@
* \brief Camellia block cipher * \brief Camellia block cipher
*/ */
/* /*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
#ifndef MBEDTLS_CAMELLIA_H #ifndef MBEDTLS_CAMELLIA_H
#define MBEDTLS_CAMELLIA_H #define MBEDTLS_CAMELLIA_H
#if !defined(MBEDTLS_CONFIG_FILE) #if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h" #include "mbedtls/config.h"
#else #else
#include MBEDTLS_CONFIG_FILE #include MBEDTLS_CONFIG_FILE
#endif #endif
@@ -35,11 +31,20 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include "mbedtls/platform_util.h"
#define MBEDTLS_CAMELLIA_ENCRYPT 1 #define MBEDTLS_CAMELLIA_ENCRYPT 1
#define MBEDTLS_CAMELLIA_DECRYPT 0 #define MBEDTLS_CAMELLIA_DECRYPT 0
#define MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH -0x0024 /**< Invalid key length. */ #if !defined(MBEDTLS_DEPRECATED_REMOVED)
#define MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 /**< Invalid data input length. */ #define MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( -0x0024 )
#endif /* !MBEDTLS_DEPRECATED_REMOVED */
#define MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA -0x0024 /**< Bad input data. */
#define MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 /**< Invalid data input length. */
/* MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED is deprecated and should not be used.
*/
#define MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED -0x0027 /**< Camellia hardware accelerator failed. */ #define MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED -0x0027 /**< Camellia hardware accelerator failed. */
#ifdef __cplusplus #ifdef __cplusplus
@@ -53,7 +58,8 @@ extern "C" {
/** /**
* \brief CAMELLIA context structure * \brief CAMELLIA context structure
*/ */
typedef struct mbedtls_camellia_context { typedef struct mbedtls_camellia_context
{
int nr; /*!< number of rounds */ int nr; /*!< number of rounds */
uint32_t rk[68]; /*!< CAMELLIA round keys */ uint32_t rk[68]; /*!< CAMELLIA round keys */
} }
@@ -64,63 +70,77 @@ mbedtls_camellia_context;
#endif /* MBEDTLS_CAMELLIA_ALT */ #endif /* MBEDTLS_CAMELLIA_ALT */
/** /**
* \brief Initialize CAMELLIA context * \brief Initialize a CAMELLIA context.
* *
* \param ctx CAMELLIA context to be initialized * \param ctx The CAMELLIA context to be initialized.
* This must not be \c NULL.
*/ */
void mbedtls_camellia_init(mbedtls_camellia_context *ctx); void mbedtls_camellia_init( mbedtls_camellia_context *ctx );
/** /**
* \brief Clear CAMELLIA context * \brief Clear a CAMELLIA context.
* *
* \param ctx CAMELLIA context to be cleared * \param ctx The CAMELLIA context to be cleared. This may be \c NULL,
* in which case this function returns immediately. If it is not
* \c NULL, it must be initialized.
*/ */
void mbedtls_camellia_free(mbedtls_camellia_context *ctx); void mbedtls_camellia_free( mbedtls_camellia_context *ctx );
/** /**
* \brief CAMELLIA key schedule (encryption) * \brief Perform a CAMELLIA key schedule operation for encryption.
* *
* \param ctx CAMELLIA context to be initialized * \param ctx The CAMELLIA context to use. This must be initialized.
* \param key encryption key * \param key The encryption key to use. This must be a readable buffer
* \param keybits must be 128, 192 or 256 * of size \p keybits Bits.
* \param keybits The length of \p key in Bits. This must be either \c 128,
* \c 192 or \c 256.
* *
* \return 0 if successful, or MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH * \return \c 0 if successful.
* \return A negative error code on failure.
*/ */
int mbedtls_camellia_setkey_enc(mbedtls_camellia_context *ctx, const unsigned char *key, int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx,
unsigned int keybits); const unsigned char *key,
unsigned int keybits );
/** /**
* \brief CAMELLIA key schedule (decryption) * \brief Perform a CAMELLIA key schedule operation for decryption.
* *
* \param ctx CAMELLIA context to be initialized * \param ctx The CAMELLIA context to use. This must be initialized.
* \param key decryption key * \param key The decryption key. This must be a readable buffer
* \param keybits must be 128, 192 or 256 * of size \p keybits Bits.
* \param keybits The length of \p key in Bits. This must be either \c 128,
* \c 192 or \c 256.
* *
* \return 0 if successful, or MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH * \return \c 0 if successful.
* \return A negative error code on failure.
*/ */
int mbedtls_camellia_setkey_dec(mbedtls_camellia_context *ctx, const unsigned char *key, int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx,
unsigned int keybits); const unsigned char *key,
unsigned int keybits );
/** /**
* \brief CAMELLIA-ECB block encryption/decryption * \brief Perform a CAMELLIA-ECB block encryption/decryption operation.
* *
* \param ctx CAMELLIA context * \param ctx The CAMELLIA context to use. This must be initialized
* \param mode MBEDTLS_CAMELLIA_ENCRYPT or MBEDTLS_CAMELLIA_DECRYPT * and bound to a key.
* \param input 16-byte input block * \param mode The mode of operation. This must be either
* \param output 16-byte output block * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT.
* \param input The input block. This must be a readable buffer
* of size \c 16 Bytes.
* \param output The output block. This must be a writable buffer
* of size \c 16 Bytes.
* *
* \return 0 if successful * \return \c 0 if successful.
* \return A negative error code on failure.
*/ */
int mbedtls_camellia_crypt_ecb(mbedtls_camellia_context *ctx, int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx,
int mode, int mode,
const unsigned char input[16], const unsigned char input[16],
unsigned char output[16]); unsigned char output[16] );
#if defined(MBEDTLS_CIPHER_MODE_CBC) #if defined(MBEDTLS_CIPHER_MODE_CBC)
/** /**
* \brief CAMELLIA-CBC buffer encryption/decryption * \brief Perform a CAMELLIA-CBC buffer encryption/decryption operation.
* Length should be a multiple of the block
* size (16 bytes)
* *
* \note Upon exit, the content of the IV is updated so that you can * \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following * call the function same function again on the following
@@ -130,31 +150,41 @@ int mbedtls_camellia_crypt_ecb(mbedtls_camellia_context *ctx,
* IV, you should either save it manually or use the cipher * IV, you should either save it manually or use the cipher
* module instead. * module instead.
* *
* \param ctx CAMELLIA context * \param ctx The CAMELLIA context to use. This must be initialized
* \param mode MBEDTLS_CAMELLIA_ENCRYPT or MBEDTLS_CAMELLIA_DECRYPT * and bound to a key.
* \param length length of the input data * \param mode The mode of operation. This must be either
* \param iv initialization vector (updated after use) * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT.
* \param input buffer holding the input data * \param length The length in Bytes of the input data \p input.
* \param output buffer holding the output data * This must be a multiple of \c 16 Bytes.
* \param iv The initialization vector. This must be a read/write buffer
* of length \c 16 Bytes. It is updated to allow streaming
* use as explained above.
* \param input The buffer holding the input data. This must point to a
* readable buffer of length \p length Bytes.
* \param output The buffer holding the output data. This must point to a
* writable buffer of length \p length Bytes.
* *
* \return 0 if successful, or * \return \c 0 if successful.
* MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH * \return A negative error code on failure.
*/ */
int mbedtls_camellia_crypt_cbc(mbedtls_camellia_context *ctx, int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx,
int mode, int mode,
size_t length, size_t length,
unsigned char iv[16], unsigned char iv[16],
const unsigned char *input, const unsigned char *input,
unsigned char *output); unsigned char *output );
#endif /* MBEDTLS_CIPHER_MODE_CBC */ #endif /* MBEDTLS_CIPHER_MODE_CBC */
#if defined(MBEDTLS_CIPHER_MODE_CFB) #if defined(MBEDTLS_CIPHER_MODE_CFB)
/** /**
* \brief CAMELLIA-CFB128 buffer encryption/decryption * \brief Perform a CAMELLIA-CFB128 buffer encryption/decryption
* operation.
* *
* Note: Due to the nature of CFB you should use the same key schedule for * \note Due to the nature of CFB mode, you should use the same
* both encryption and decryption. So a context initialized with * key for both encryption and decryption. In particular, calls
* mbedtls_camellia_setkey_enc() for both MBEDTLS_CAMELLIA_ENCRYPT and CAMELLIE_DECRYPT. * to this function should be preceded by a key-schedule via
* mbedtls_camellia_setkey_enc() regardless of whether \p mode
* is #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT.
* *
* \note Upon exit, the content of the IV is updated so that you can * \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following * call the function same function again on the following
@@ -164,33 +194,43 @@ int mbedtls_camellia_crypt_cbc(mbedtls_camellia_context *ctx,
* IV, you should either save it manually or use the cipher * IV, you should either save it manually or use the cipher
* module instead. * module instead.
* *
* \param ctx CAMELLIA context * \param ctx The CAMELLIA context to use. This must be initialized
* \param mode MBEDTLS_CAMELLIA_ENCRYPT or MBEDTLS_CAMELLIA_DECRYPT * and bound to a key.
* \param length length of the input data * \param mode The mode of operation. This must be either
* \param iv_off offset in IV (updated after use) * #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT.
* \param iv initialization vector (updated after use) * \param length The length of the input data \p input. Any value is allowed.
* \param input buffer holding the input data * \param iv_off The current offset in the IV. This must be smaller
* \param output buffer holding the output data * than \c 16 Bytes. It is updated after this call to allow
* the aforementioned streaming usage.
* \param iv The initialization vector. This must be a read/write buffer
* of length \c 16 Bytes. It is updated after this call to
* allow the aforementioned streaming usage.
* \param input The buffer holding the input data. This must be a readable
* buffer of size \p length Bytes.
* \param output The buffer to hold the output data. This must be a writable
* buffer of length \p length Bytes.
* *
* \return 0 if successful, or * \return \c 0 if successful.
* MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH * \return A negative error code on failure.
*/ */
int mbedtls_camellia_crypt_cfb128(mbedtls_camellia_context *ctx, int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx,
int mode, int mode,
size_t length, size_t length,
size_t *iv_off, size_t *iv_off,
unsigned char iv[16], unsigned char iv[16],
const unsigned char *input, const unsigned char *input,
unsigned char *output); unsigned char *output );
#endif /* MBEDTLS_CIPHER_MODE_CFB */ #endif /* MBEDTLS_CIPHER_MODE_CFB */
#if defined(MBEDTLS_CIPHER_MODE_CTR) #if defined(MBEDTLS_CIPHER_MODE_CTR)
/** /**
* \brief CAMELLIA-CTR buffer encryption/decryption * \brief Perform a CAMELLIA-CTR buffer encryption/decryption operation.
* *
* Note: Due to the nature of CTR you should use the same key schedule for * *note Due to the nature of CTR mode, you should use the same
* both encryption and decryption. So a context initialized with * key for both encryption and decryption. In particular, calls
* mbedtls_camellia_setkey_enc() for both MBEDTLS_CAMELLIA_ENCRYPT and MBEDTLS_CAMELLIA_DECRYPT. * to this function should be preceded by a key-schedule via
* mbedtls_camellia_setkey_enc() regardless of whether \p mode
* is #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT.
* *
* \warning You must never reuse a nonce value with the same key. Doing so * \warning You must never reuse a nonce value with the same key. Doing so
* would void the encryption for the two messages encrypted with * would void the encryption for the two messages encrypted with
@@ -213,57 +253,69 @@ int mbedtls_camellia_crypt_cfb128(mbedtls_camellia_context *ctx,
* per-message nonce, handled by yourself, and the second one * per-message nonce, handled by yourself, and the second one
* updated by this function internally. * updated by this function internally.
* *
* For example, you might reserve the first 12 bytes for the * For example, you might reserve the first \c 12 Bytes for the
* per-message nonce, and the last 4 bytes for internal use. In that * per-message nonce, and the last \c 4 Bytes for internal use.
* case, before calling this function on a new message you need to * In that case, before calling this function on a new message you
* set the first 12 bytes of \p nonce_counter to your chosen nonce * need to set the first \c 12 Bytes of \p nonce_counter to your
* value, the last 4 to 0, and \p nc_off to 0 (which will cause \p * chosen nonce value, the last four to \c 0, and \p nc_off to \c 0
* stream_block to be ignored). That way, you can encrypt at most * (which will cause \p stream_block to be ignored). That way, you
* 2**96 messages of up to 2**32 blocks each with the same key. * can encrypt at most \c 2**96 messages of up to \c 2**32 blocks
* each with the same key.
* *
* The per-message nonce (or information sufficient to reconstruct * The per-message nonce (or information sufficient to reconstruct
* it) needs to be communicated with the ciphertext and must be unique. * it) needs to be communicated with the ciphertext and must be
* The recommended way to ensure uniqueness is to use a message * unique. The recommended way to ensure uniqueness is to use a
* counter. An alternative is to generate random nonces, but this * message counter. An alternative is to generate random nonces,
* limits the number of messages that can be securely encrypted: * but this limits the number of messages that can be securely
* for example, with 96-bit random nonces, you should not encrypt * encrypted: for example, with 96-bit random nonces, you should
* more than 2**32 messages with the same key. * not encrypt more than 2**32 messages with the same key.
* *
* Note that for both stategies, sizes are measured in blocks and * Note that for both stategies, sizes are measured in blocks and
* that a CAMELLIA block is 16 bytes. * that a CAMELLIA block is \c 16 Bytes.
* *
* \warning Upon return, \p stream_block contains sensitive data. Its * \warning Upon return, \p stream_block contains sensitive data. Its
* content must not be written to insecure storage and should be * content must not be written to insecure storage and should be
* securely discarded as soon as it's no longer needed. * securely discarded as soon as it's no longer needed.
* *
* \param ctx CAMELLIA context * \param ctx The CAMELLIA context to use. This must be initialized
* \param length The length of the data * and bound to a key.
* \param nc_off The offset in the current stream_block (for resuming * \param length The length of the input data \p input in Bytes.
* Any value is allowed.
* \param nc_off The offset in the current \p stream_block (for resuming
* within current cipher stream). The offset pointer to * within current cipher stream). The offset pointer to
* should be 0 at the start of a stream. * should be \c 0 at the start of a stream. It is updated
* \param nonce_counter The 128-bit nonce and counter. * at the end of this call.
* \param stream_block The saved stream-block for resuming. Is overwritten * \param nonce_counter The 128-bit nonce and counter. This must be a read/write
* by the function. * buffer of length \c 16 Bytes.
* \param input The input data stream * \param stream_block The saved stream-block for resuming. This must be a
* \param output The output data stream * read/write buffer of length \c 16 Bytes.
* \param input The input data stream. This must be a readable buffer of
* size \p length Bytes.
* \param output The output data stream. This must be a writable buffer
* of size \p length Bytes.
* *
* \return 0 if successful * \return \c 0 if successful.
* \return A negative error code on failure.
*/ */
int mbedtls_camellia_crypt_ctr(mbedtls_camellia_context *ctx, int mbedtls_camellia_crypt_ctr( mbedtls_camellia_context *ctx,
size_t length, size_t length,
size_t *nc_off, size_t *nc_off,
unsigned char nonce_counter[16], unsigned char nonce_counter[16],
unsigned char stream_block[16], unsigned char stream_block[16],
const unsigned char *input, const unsigned char *input,
unsigned char *output); unsigned char *output );
#endif /* MBEDTLS_CIPHER_MODE_CTR */ #endif /* MBEDTLS_CIPHER_MODE_CTR */
#if defined(MBEDTLS_SELF_TEST)
/** /**
* \brief Checkup routine * \brief Checkup routine
* *
* \return 0 if successful, or 1 if the test failed * \return 0 if successful, or 1 if the test failed
*/ */
int mbedtls_camellia_self_test(int verbose); int mbedtls_camellia_self_test( int verbose );
#endif /* MBEDTLS_SELF_TEST */
#ifdef __cplusplus #ifdef __cplusplus
} }

547
common/mbedtls/ccm.c Normal file
View File

@@ -0,0 +1,547 @@
/*
* NIST SP800-38C compliant CCM implementation
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* 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 <string.h>
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
#if !defined(MBEDTLS_CCM_ALT)
#define CCM_VALIDATE_RET( cond ) \
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CCM_BAD_INPUT )
#define CCM_VALIDATE( cond ) \
MBEDTLS_INTERNAL_VALIDATE( cond )
#define CCM_ENCRYPT 0
#define CCM_DECRYPT 1
/*
* Initialize context
*/
void mbedtls_ccm_init( mbedtls_ccm_context *ctx )
{
CCM_VALIDATE( ctx != NULL );
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;
const mbedtls_cipher_info_t *cipher_info;
CCM_VALIDATE_RET( ctx != NULL );
CCM_VALIDATE_RET( key != NULL );
cipher_info = mbedtls_cipher_info_from_values( cipher, keybits,
MBEDTLS_MODE_ECB );
if( cipher_info == NULL )
return( MBEDTLS_ERR_CCM_BAD_INPUT );
if( cipher_info->block_size != 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 );
}
return( 0 );
}
/*
* Free context
*/
void mbedtls_ccm_free( mbedtls_ccm_context *ctx )
{
if( ctx == NULL )
return;
mbedtls_cipher_free( &ctx->cipher_ctx );
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ccm_context ) );
}
/*
* Macros for common operations.
* Results in smaller compiled code than static inline functions.
*/
/*
* Update the CBC-MAC state in y using a block in b
* (Always using b as the source helps the compiler optimise a bit better.)
*/
#define UPDATE_CBC_MAC \
for( i = 0; i < 16; i++ ) \
y[i] ^= b[i]; \
\
if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, y, 16, y, &olen ) ) != 0 ) \
return( ret );
/*
* Encrypt or decrypt a partial block with CTR
* Warning: using b for temporary storage! src and dst must not be b!
* This avoids allocating one more 16 bytes buffer while allowing src == dst.
*/
#define CTR_CRYPT( dst, src, len ) \
do \
{ \
if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctr, \
16, b, &olen ) ) != 0 ) \
{ \
return( ret ); \
} \
\
for( i = 0; i < (len); i++ ) \
(dst)[i] = (src)[i] ^ b[i]; \
} while( 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;
unsigned char i;
unsigned char q;
size_t len_left, olen;
unsigned char b[16];
unsigned char y[16];
unsigned char ctr[16];
const unsigned char *src;
unsigned char *dst;
/*
* 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 );
/* Also implies q is within bounds */
if( iv_len < 7 || iv_len > 13 )
return( MBEDTLS_ERR_CCM_BAD_INPUT );
if( add_len >= 0xFF00 )
return( MBEDTLS_ERR_CCM_BAD_INPUT );
q = 16 - 1 - (unsigned char) iv_len;
/*
* First block B_0:
* 0 .. 0 flags
* 1 .. iv_len nonce (aka iv)
* iv_len+1 .. 15 length
*
* With flags as (bits):
* 7 0
* 6 add present?
* 5 .. 3 (t - 2) / 2
* 2 .. 0 q - 1
*/
b[0] = 0;
b[0] |= ( add_len > 0 ) << 6;
b[0] |= ( ( tag_len - 2 ) / 2 ) << 3;
b[0] |= q - 1;
memcpy( b + 1, iv, iv_len );
for( i = 0, len_left = length; i < q; i++, len_left >>= 8 )
b[15-i] = (unsigned char)( len_left & 0xFF );
if( len_left > 0 )
return( MBEDTLS_ERR_CCM_BAD_INPUT );
/* Start CBC-MAC with first block */
memset( y, 0, 16 );
UPDATE_CBC_MAC;
/*
* If there is additional data, update CBC-MAC with
* add_len, add, 0 (padding to a block boundary)
*/
if( add_len > 0 )
{
size_t use_len;
len_left = add_len;
src = add;
memset( b, 0, 16 );
b[0] = (unsigned char)( ( add_len >> 8 ) & 0xFF );
b[1] = (unsigned char)( ( add_len ) & 0xFF );
use_len = len_left < 16 - 2 ? len_left : 16 - 2;
memcpy( b + 2, src, use_len );
len_left -= use_len;
src += use_len;
UPDATE_CBC_MAC;
while( len_left > 0 )
{
use_len = len_left > 16 ? 16 : len_left;
memset( b, 0, 16 );
memcpy( b, src, use_len );
UPDATE_CBC_MAC;
len_left -= use_len;
src += use_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
*/
ctr[0] = q - 1;
memcpy( ctr + 1, iv, iv_len );
memset( ctr + 1 + iv_len, 0, q );
ctr[15] = 1;
/*
* Authenticate and {en,de}crypt the message.
*
* The only difference between encryption and decryption is
* the respective order of authentication and {en,de}cryption.
*/
len_left = length;
src = input;
dst = output;
while( len_left > 0 )
{
size_t use_len = len_left > 16 ? 16 : len_left;
if( mode == CCM_ENCRYPT )
{
memset( b, 0, 16 );
memcpy( b, src, use_len );
UPDATE_CBC_MAC;
}
CTR_CRYPT( dst, src, use_len );
if( mode == CCM_DECRYPT )
{
memset( b, 0, 16 );
memcpy( b, dst, use_len );
UPDATE_CBC_MAC;
}
dst += use_len;
src += use_len;
len_left -= use_len;
/*
* Increment counter.
* No need to check for overflow thanks to the length check above.
*/
for( i = 0; i < q; i++ )
if( ++ctr[15-i] != 0 )
break;
}
/*
* Authentication: reset counter and crypt/mask internal tag
*/
for( i = 0; i < q; i++ )
ctr[15-i] = 0;
CTR_CRYPT( y, y, 16 );
memcpy( tag, y, tag_len );
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 )
{
CCM_VALIDATE_RET( ctx != NULL );
CCM_VALIDATE_RET( iv != NULL );
CCM_VALIDATE_RET( add_len == 0 || add != NULL );
CCM_VALIDATE_RET( length == 0 || input != NULL );
CCM_VALIDATE_RET( length == 0 || output != NULL );
CCM_VALIDATE_RET( tag_len == 0 || tag != NULL );
return( ccm_auth_crypt( ctx, CCM_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 )
{
CCM_VALIDATE_RET( ctx != NULL );
CCM_VALIDATE_RET( iv != NULL );
CCM_VALIDATE_RET( add_len == 0 || add != NULL );
CCM_VALIDATE_RET( length == 0 || input != NULL );
CCM_VALIDATE_RET( length == 0 || output != NULL );
CCM_VALIDATE_RET( tag_len == 0 || tag != NULL );
if( tag_len == 0 )
return( MBEDTLS_ERR_CCM_BAD_INPUT );
return( mbedtls_ccm_star_encrypt_and_tag( ctx, length, iv, iv_len, add,
add_len, input, output, tag, tag_len ) );
}
/*
* Authenticated decryption
*/
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 )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char check_tag[16];
unsigned char i;
int diff;
CCM_VALIDATE_RET( ctx != NULL );
CCM_VALIDATE_RET( iv != NULL );
CCM_VALIDATE_RET( add_len == 0 || add != NULL );
CCM_VALIDATE_RET( length == 0 || input != NULL );
CCM_VALIDATE_RET( length == 0 || output != NULL );
CCM_VALIDATE_RET( tag_len == 0 || tag != NULL );
if( ( ret = ccm_auth_crypt( ctx, CCM_DECRYPT, length,
iv, iv_len, add, add_len,
input, output, check_tag, tag_len ) ) != 0 )
{
return( ret );
}
/* Check tag in "constant-time" */
for( diff = 0, i = 0; i < tag_len; i++ )
diff |= tag[i] ^ check_tag[i];
if( diff != 0 )
{
mbedtls_platform_zeroize( output, length );
return( MBEDTLS_ERR_CCM_AUTH_FAILED );
}
return( 0 );
}
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 )
{
CCM_VALIDATE_RET( ctx != NULL );
CCM_VALIDATE_RET( iv != NULL );
CCM_VALIDATE_RET( add_len == 0 || add != NULL );
CCM_VALIDATE_RET( length == 0 || input != NULL );
CCM_VALIDATE_RET( length == 0 || output != NULL );
CCM_VALIDATE_RET( tag_len == 0 || tag != NULL );
if( tag_len == 0 )
return( MBEDTLS_ERR_CCM_BAD_INPUT );
return( mbedtls_ccm_star_auth_decrypt( ctx, length, iv, iv_len, add,
add_len, input, output, tag, tag_len ) );
}
#endif /* !MBEDTLS_CCM_ALT */
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
/*
* 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 */

308
common/mbedtls/ccm.h Normal file
View File

@@ -0,0 +1,308 @@
/**
* \file ccm.h
*
* \brief This file provides an API for the CCM authenticated encryption
* mode for block ciphers.
*
* CCM combines Counter mode encryption with CBC-MAC authentication
* for 128-bit block ciphers.
*
* Input to CCM includes the following elements:
* <ul><li>Payload - data that is both authenticated and encrypted.</li>
* <li>Associated data (Adata) - data that is authenticated but not
* encrypted, For example, a header.</li>
* <li>Nonce - A unique value that is assigned to the payload and the
* associated data.</li></ul>
*
* 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"
*
* Definition of CCM*:
* IEEE 802.15.4 - IEEE Standard for Local and metropolitan area networks
* Integer representation is fixed most-significant-octet-first order and
* the representation of octets is most-significant-bit-first order. This is
* consistent with RFC 3610.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBEDTLS_CCM_H
#define MBEDTLS_CCM_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include "mbedtls/cipher.h"
#define MBEDTLS_ERR_CCM_BAD_INPUT -0x000D /**< Bad input parameters to the function. */
#define MBEDTLS_ERR_CCM_AUTH_FAILED -0x000F /**< Authenticated decryption failed. */
/* MBEDTLS_ERR_CCM_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_CCM_HW_ACCEL_FAILED -0x0011 /**< CCM hardware accelerator failed. */
#ifdef __cplusplus
extern "C" {
#endif
#if !defined(MBEDTLS_CCM_ALT)
// Regular implementation
//
/**
* \brief The CCM context-type definition. The CCM context is passed
* to the APIs called.
*/
typedef struct mbedtls_ccm_context
{
mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */
}
mbedtls_ccm_context;
#else /* MBEDTLS_CCM_ALT */
#include "ccm_alt.h"
#endif /* MBEDTLS_CCM_ALT */
/**
* \brief This function initializes the specified CCM context,
* to make references valid, and prepare the context
* for mbedtls_ccm_setkey() or mbedtls_ccm_free().
*
* \param ctx The CCM context to initialize. This must not be \c NULL.
*/
void mbedtls_ccm_init( mbedtls_ccm_context *ctx );
/**
* \brief This function initializes the CCM context set in the
* \p ctx parameter and sets the encryption key.
*
* \param ctx The CCM context to initialize. This must be an initialized
* context.
* \param cipher The 128-bit block cipher to use.
* \param key The encryption key. This must not be \c NULL.
* \param keybits The key size in bits. This must be acceptable by the cipher.
*
* \return \c 0 on success.
* \return A CCM or cipher-specific error code on failure.
*/
int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx,
mbedtls_cipher_id_t cipher,
const unsigned char *key,
unsigned int keybits );
/**
* \brief This function releases and clears the specified CCM context
* and underlying cipher sub-context.
*
* \param ctx The CCM context to clear. If this is \c NULL, the function
* has no effect. Otherwise, this must be initialized.
*/
void mbedtls_ccm_free( mbedtls_ccm_context *ctx );
/**
* \brief This function encrypts a buffer using CCM.
*
* \note The tag is written to a separate buffer. To concatenate
* the \p tag with the \p output, as done in <em>RFC-3610:
* Counter with CBC-MAC (CCM)</em>, use
* \p tag = \p output + \p length, and make sure that the
* output buffer is at least \p length + \p tag_len wide.
*
* \param ctx The CCM context to use for encryption. This must be
* initialized and bound to a key.
* \param length The length of the input data in Bytes.
* \param iv The initialization vector (nonce). This must be a readable
* buffer of at least \p iv_len Bytes.
* \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
* or 13. The length L of the message length field is
* 15 - \p iv_len.
* \param add The additional data field. If \p add_len is greater than
* zero, \p add must be a readable buffer of at least that
* length.
* \param add_len The length of additional data in Bytes.
* This must be less than `2^16 - 2^8`.
* \param input The buffer holding the input data. If \p length is greater
* than zero, \p input must be a readable buffer of at least
* that length.
* \param output The buffer holding the output data. If \p length is greater
* than zero, \p output must be a writable buffer of at least
* that length.
* \param tag The buffer holding the authentication field. This must be a
* writable buffer of at least \p tag_len Bytes.
* \param tag_len The length of the authentication field to generate in Bytes:
* 4, 6, 8, 10, 12, 14 or 16.
*
* \return \c 0 on success.
* \return A CCM or cipher-specific error code on failure.
*/
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 );
/**
* \brief This function encrypts a buffer using CCM*.
*
* \note The tag is written to a separate buffer. To concatenate
* the \p tag with the \p output, as done in <em>RFC-3610:
* Counter with CBC-MAC (CCM)</em>, use
* \p tag = \p output + \p length, and make sure that the
* output buffer is at least \p length + \p tag_len wide.
*
* \note When using this function in a variable tag length context,
* the tag length has to be encoded into the \p iv passed to
* this function.
*
* \param ctx The CCM context to use for encryption. This must be
* initialized and bound to a key.
* \param length The length of the input data in Bytes.
* \param iv The initialization vector (nonce). This must be a readable
* buffer of at least \p iv_len Bytes.
* \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
* or 13. The length L of the message length field is
* 15 - \p iv_len.
* \param add The additional data field. This must be a readable buffer of
* at least \p add_len Bytes.
* \param add_len The length of additional data in Bytes.
* This must be less than 2^16 - 2^8.
* \param input The buffer holding the input data. If \p length is greater
* than zero, \p input must be a readable buffer of at least
* that length.
* \param output The buffer holding the output data. If \p length is greater
* than zero, \p output must be a writable buffer of at least
* that length.
* \param tag The buffer holding the authentication field. This must be a
* writable buffer of at least \p tag_len Bytes.
* \param tag_len The length of the authentication field to generate in Bytes:
* 0, 4, 6, 8, 10, 12, 14 or 16.
*
* \warning Passing \c 0 as \p tag_len means that the message is no
* longer authenticated.
*
* \return \c 0 on success.
* \return A CCM or cipher-specific error code on failure.
*/
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 );
/**
* \brief This function performs a CCM authenticated decryption of a
* buffer.
*
* \param ctx The CCM context to use for decryption. This must be
* initialized and bound to a key.
* \param length The length of the input data in Bytes.
* \param iv The initialization vector (nonce). This must be a readable
* buffer of at least \p iv_len Bytes.
* \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
* or 13. The length L of the message length field is
* 15 - \p iv_len.
* \param add The additional data field. This must be a readable buffer
* of at least that \p add_len Bytes..
* \param add_len The length of additional data in Bytes.
* This must be less than 2^16 - 2^8.
* \param input The buffer holding the input data. If \p length is greater
* than zero, \p input must be a readable buffer of at least
* that length.
* \param output The buffer holding the output data. If \p length is greater
* than zero, \p output must be a writable buffer of at least
* that length.
* \param tag The buffer holding the authentication field. This must be a
* readable buffer of at least \p tag_len Bytes.
* \param tag_len The length of the authentication field to generate in Bytes:
* 4, 6, 8, 10, 12, 14 or 16.
*
* \return \c 0 on success. This indicates that the message is authentic.
* \return #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match.
* \return A cipher-specific error code on calculation failure.
*/
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 );
/**
* \brief This function performs a CCM* authenticated decryption of a
* buffer.
*
* \note When using this function in a variable tag length context,
* the tag length has to be decoded from \p iv and passed to
* this function as \p tag_len. (\p tag needs to be adjusted
* accordingly.)
*
* \param ctx The CCM context to use for decryption. This must be
* initialized and bound to a key.
* \param length The length of the input data in Bytes.
* \param iv The initialization vector (nonce). This must be a readable
* buffer of at least \p iv_len Bytes.
* \param iv_len The length of the nonce in Bytes: 7, 8, 9, 10, 11, 12,
* or 13. The length L of the message length field is
* 15 - \p iv_len.
* \param add The additional data field. This must be a readable buffer of
* at least that \p add_len Bytes.
* \param add_len The length of additional data in Bytes.
* This must be less than 2^16 - 2^8.
* \param input The buffer holding the input data. If \p length is greater
* than zero, \p input must be a readable buffer of at least
* that length.
* \param output The buffer holding the output data. If \p length is greater
* than zero, \p output must be a writable buffer of at least
* that length.
* \param tag The buffer holding the authentication field. This must be a
* readable buffer of at least \p tag_len Bytes.
* \param tag_len The length of the authentication field in Bytes.
* 0, 4, 6, 8, 10, 12, 14 or 16.
*
* \warning Passing \c 0 as \p tag_len means that the message is nos
* longer authenticated.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CCM_AUTH_FAILED if the tag does not match.
* \return A cipher-specific error code on calculation failure.
*/
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 );
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
/**
* \brief The CCM checkup routine.
*
* \return \c 0 on success.
* \return \c 1 on failure.
*/
int mbedtls_ccm_self_test( int verbose );
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_CCM_H */

File diff suppressed because it is too large Load Diff

View File

@@ -4,96 +4,244 @@
* \brief Sample certificates and DHM parameters for testing * \brief Sample certificates and DHM parameters for testing
*/ */
/* /*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
#ifndef MBEDTLS_CERTS_H #ifndef MBEDTLS_CERTS_H
#define MBEDTLS_CERTS_H #define MBEDTLS_CERTS_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include <stddef.h> #include <stddef.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* List of all PEM-encoded CA certificates, terminated by NULL;
* PEM encoded if MBEDTLS_PEM_PARSE_C is enabled, DER encoded
* otherwise. */
extern const char * mbedtls_test_cas[];
extern const size_t mbedtls_test_cas_len[];
/* List of all DER-encoded CA certificates, terminated by NULL */
extern const unsigned char * mbedtls_test_cas_der[];
extern const size_t mbedtls_test_cas_der_len[];
#if defined(MBEDTLS_PEM_PARSE_C) #if defined(MBEDTLS_PEM_PARSE_C)
/* Concatenation of all CA certificates in PEM format if available */ /* Concatenation of all CA certificates in PEM format if available */
extern const char mbedtls_test_cas_pem[]; extern const char mbedtls_test_cas_pem[];
extern const size_t mbedtls_test_cas_pem_len; extern const size_t mbedtls_test_cas_pem_len;
#endif #endif /* MBEDTLS_PEM_PARSE_C */
/* List of all CA certificates, terminated by NULL */
extern const char *mbedtls_test_cas[];
extern const size_t mbedtls_test_cas_len[];
/* /*
* Convenience for users who just want a certificate: * CA test certificates
* RSA by default, or ECDSA if RSA is not available
*/ */
extern const char *mbedtls_test_ca_crt;
extern const size_t mbedtls_test_ca_crt_len;
extern const char *mbedtls_test_ca_key;
extern const size_t mbedtls_test_ca_key_len;
extern const char *mbedtls_test_ca_pwd;
extern const size_t mbedtls_test_ca_pwd_len;
extern const char *mbedtls_test_srv_crt;
extern const size_t mbedtls_test_srv_crt_len;
extern const char *mbedtls_test_srv_key;
extern const size_t mbedtls_test_srv_key_len;
extern const char *mbedtls_test_cli_crt;
extern const size_t mbedtls_test_cli_crt_len;
extern const char *mbedtls_test_cli_key;
extern const size_t mbedtls_test_cli_key_len;
#if defined(MBEDTLS_ECDSA_C) extern const char mbedtls_test_ca_crt_ec_pem[];
extern const char mbedtls_test_ca_crt_ec[]; extern const char mbedtls_test_ca_key_ec_pem[];
extern const char mbedtls_test_ca_pwd_ec_pem[];
extern const char mbedtls_test_ca_key_rsa_pem[];
extern const char mbedtls_test_ca_pwd_rsa_pem[];
extern const char mbedtls_test_ca_crt_rsa_sha1_pem[];
extern const char mbedtls_test_ca_crt_rsa_sha256_pem[];
extern const unsigned char mbedtls_test_ca_crt_ec_der[];
extern const unsigned char mbedtls_test_ca_key_ec_der[];
extern const unsigned char mbedtls_test_ca_key_rsa_der[];
extern const unsigned char mbedtls_test_ca_crt_rsa_sha1_der[];
extern const unsigned char mbedtls_test_ca_crt_rsa_sha256_der[];
extern const size_t mbedtls_test_ca_crt_ec_pem_len;
extern const size_t mbedtls_test_ca_key_ec_pem_len;
extern const size_t mbedtls_test_ca_pwd_ec_pem_len;
extern const size_t mbedtls_test_ca_key_rsa_pem_len;
extern const size_t mbedtls_test_ca_pwd_rsa_pem_len;
extern const size_t mbedtls_test_ca_crt_rsa_sha1_pem_len;
extern const size_t mbedtls_test_ca_crt_rsa_sha256_pem_len;
extern const size_t mbedtls_test_ca_crt_ec_der_len;
extern const size_t mbedtls_test_ca_key_ec_der_len;
extern const size_t mbedtls_test_ca_pwd_ec_der_len;
extern const size_t mbedtls_test_ca_key_rsa_der_len;
extern const size_t mbedtls_test_ca_pwd_rsa_der_len;
extern const size_t mbedtls_test_ca_crt_rsa_sha1_der_len;
extern const size_t mbedtls_test_ca_crt_rsa_sha256_der_len;
/* Config-dependent dispatch between PEM and DER encoding
* (PEM if enabled, otherwise DER) */
extern const char mbedtls_test_ca_crt_ec[];
extern const char mbedtls_test_ca_key_ec[];
extern const char mbedtls_test_ca_pwd_ec[];
extern const char mbedtls_test_ca_key_rsa[];
extern const char mbedtls_test_ca_pwd_rsa[];
extern const char mbedtls_test_ca_crt_rsa_sha1[];
extern const char mbedtls_test_ca_crt_rsa_sha256[];
extern const size_t mbedtls_test_ca_crt_ec_len; extern const size_t mbedtls_test_ca_crt_ec_len;
extern const char mbedtls_test_ca_key_ec[];
extern const size_t mbedtls_test_ca_key_ec_len; extern const size_t mbedtls_test_ca_key_ec_len;
extern const char mbedtls_test_ca_pwd_ec[];
extern const size_t mbedtls_test_ca_pwd_ec_len; extern const size_t mbedtls_test_ca_pwd_ec_len;
extern const char mbedtls_test_srv_crt_ec[];
extern const size_t mbedtls_test_srv_crt_ec_len;
extern const char mbedtls_test_srv_key_ec[];
extern const size_t mbedtls_test_srv_key_ec_len;
extern const char mbedtls_test_cli_crt_ec[];
extern const size_t mbedtls_test_cli_crt_ec_len;
extern const char mbedtls_test_cli_key_ec[];
extern const size_t mbedtls_test_cli_key_ec_len;
#endif
#if defined(MBEDTLS_RSA_C)
extern const char mbedtls_test_ca_crt_rsa[];
extern const size_t mbedtls_test_ca_crt_rsa_len;
extern const char mbedtls_test_ca_key_rsa[];
extern const size_t mbedtls_test_ca_key_rsa_len; extern const size_t mbedtls_test_ca_key_rsa_len;
extern const char mbedtls_test_ca_pwd_rsa[];
extern const size_t mbedtls_test_ca_pwd_rsa_len; extern const size_t mbedtls_test_ca_pwd_rsa_len;
extern const char mbedtls_test_srv_crt_rsa[]; extern const size_t mbedtls_test_ca_crt_rsa_sha1_len;
extern const size_t mbedtls_test_srv_crt_rsa_len; extern const size_t mbedtls_test_ca_crt_rsa_sha256_len;
extern const char mbedtls_test_srv_key_rsa[];
/* Config-dependent dispatch between SHA-1 and SHA-256
* (SHA-256 if enabled, otherwise SHA-1) */
extern const char mbedtls_test_ca_crt_rsa[];
extern const size_t mbedtls_test_ca_crt_rsa_len;
/* Config-dependent dispatch between EC and RSA
* (RSA if enabled, otherwise EC) */
extern const char * mbedtls_test_ca_crt;
extern const char * mbedtls_test_ca_key;
extern const char * mbedtls_test_ca_pwd;
extern const size_t mbedtls_test_ca_crt_len;
extern const size_t mbedtls_test_ca_key_len;
extern const size_t mbedtls_test_ca_pwd_len;
/*
* Server test certificates
*/
extern const char mbedtls_test_srv_crt_ec_pem[];
extern const char mbedtls_test_srv_key_ec_pem[];
extern const char mbedtls_test_srv_pwd_ec_pem[];
extern const char mbedtls_test_srv_key_rsa_pem[];
extern const char mbedtls_test_srv_pwd_rsa_pem[];
extern const char mbedtls_test_srv_crt_rsa_sha1_pem[];
extern const char mbedtls_test_srv_crt_rsa_sha256_pem[];
extern const unsigned char mbedtls_test_srv_crt_ec_der[];
extern const unsigned char mbedtls_test_srv_key_ec_der[];
extern const unsigned char mbedtls_test_srv_key_rsa_der[];
extern const unsigned char mbedtls_test_srv_crt_rsa_sha1_der[];
extern const unsigned char mbedtls_test_srv_crt_rsa_sha256_der[];
extern const size_t mbedtls_test_srv_crt_ec_pem_len;
extern const size_t mbedtls_test_srv_key_ec_pem_len;
extern const size_t mbedtls_test_srv_pwd_ec_pem_len;
extern const size_t mbedtls_test_srv_key_rsa_pem_len;
extern const size_t mbedtls_test_srv_pwd_rsa_pem_len;
extern const size_t mbedtls_test_srv_crt_rsa_sha1_pem_len;
extern const size_t mbedtls_test_srv_crt_rsa_sha256_pem_len;
extern const size_t mbedtls_test_srv_crt_ec_der_len;
extern const size_t mbedtls_test_srv_key_ec_der_len;
extern const size_t mbedtls_test_srv_pwd_ec_der_len;
extern const size_t mbedtls_test_srv_key_rsa_der_len;
extern const size_t mbedtls_test_srv_pwd_rsa_der_len;
extern const size_t mbedtls_test_srv_crt_rsa_sha1_der_len;
extern const size_t mbedtls_test_srv_crt_rsa_sha256_der_len;
/* Config-dependent dispatch between PEM and DER encoding
* (PEM if enabled, otherwise DER) */
extern const char mbedtls_test_srv_crt_ec[];
extern const char mbedtls_test_srv_key_ec[];
extern const char mbedtls_test_srv_pwd_ec[];
extern const char mbedtls_test_srv_key_rsa[];
extern const char mbedtls_test_srv_pwd_rsa[];
extern const char mbedtls_test_srv_crt_rsa_sha1[];
extern const char mbedtls_test_srv_crt_rsa_sha256[];
extern const size_t mbedtls_test_srv_crt_ec_len;
extern const size_t mbedtls_test_srv_key_ec_len;
extern const size_t mbedtls_test_srv_pwd_ec_len;
extern const size_t mbedtls_test_srv_key_rsa_len; extern const size_t mbedtls_test_srv_key_rsa_len;
extern const char mbedtls_test_cli_crt_rsa[]; extern const size_t mbedtls_test_srv_pwd_rsa_len;
extern const size_t mbedtls_test_cli_crt_rsa_len; extern const size_t mbedtls_test_srv_crt_rsa_sha1_len;
extern const char mbedtls_test_cli_key_rsa[]; extern const size_t mbedtls_test_srv_crt_rsa_sha256_len;
/* Config-dependent dispatch between SHA-1 and SHA-256
* (SHA-256 if enabled, otherwise SHA-1) */
extern const char mbedtls_test_srv_crt_rsa[];
extern const size_t mbedtls_test_srv_crt_rsa_len;
/* Config-dependent dispatch between EC and RSA
* (RSA if enabled, otherwise EC) */
extern const char * mbedtls_test_srv_crt;
extern const char * mbedtls_test_srv_key;
extern const char * mbedtls_test_srv_pwd;
extern const size_t mbedtls_test_srv_crt_len;
extern const size_t mbedtls_test_srv_key_len;
extern const size_t mbedtls_test_srv_pwd_len;
/*
* Client test certificates
*/
extern const char mbedtls_test_cli_crt_ec_pem[];
extern const char mbedtls_test_cli_key_ec_pem[];
extern const char mbedtls_test_cli_pwd_ec_pem[];
extern const char mbedtls_test_cli_key_rsa_pem[];
extern const char mbedtls_test_cli_pwd_rsa_pem[];
extern const char mbedtls_test_cli_crt_rsa_pem[];
extern const unsigned char mbedtls_test_cli_crt_ec_der[];
extern const unsigned char mbedtls_test_cli_key_ec_der[];
extern const unsigned char mbedtls_test_cli_key_rsa_der[];
extern const unsigned char mbedtls_test_cli_crt_rsa_der[];
extern const size_t mbedtls_test_cli_crt_ec_pem_len;
extern const size_t mbedtls_test_cli_key_ec_pem_len;
extern const size_t mbedtls_test_cli_pwd_ec_pem_len;
extern const size_t mbedtls_test_cli_key_rsa_pem_len;
extern const size_t mbedtls_test_cli_pwd_rsa_pem_len;
extern const size_t mbedtls_test_cli_crt_rsa_pem_len;
extern const size_t mbedtls_test_cli_crt_ec_der_len;
extern const size_t mbedtls_test_cli_key_ec_der_len;
extern const size_t mbedtls_test_cli_key_rsa_der_len;
extern const size_t mbedtls_test_cli_crt_rsa_der_len;
/* Config-dependent dispatch between PEM and DER encoding
* (PEM if enabled, otherwise DER) */
extern const char mbedtls_test_cli_crt_ec[];
extern const char mbedtls_test_cli_key_ec[];
extern const char mbedtls_test_cli_pwd_ec[];
extern const char mbedtls_test_cli_key_rsa[];
extern const char mbedtls_test_cli_pwd_rsa[];
extern const char mbedtls_test_cli_crt_rsa[];
extern const size_t mbedtls_test_cli_crt_ec_len;
extern const size_t mbedtls_test_cli_key_ec_len;
extern const size_t mbedtls_test_cli_pwd_ec_len;
extern const size_t mbedtls_test_cli_key_rsa_len; extern const size_t mbedtls_test_cli_key_rsa_len;
#endif extern const size_t mbedtls_test_cli_pwd_rsa_len;
extern const size_t mbedtls_test_cli_crt_rsa_len;
/* Config-dependent dispatch between EC and RSA
* (RSA if enabled, otherwise EC) */
extern const char * mbedtls_test_cli_crt;
extern const char * mbedtls_test_cli_key;
extern const char * mbedtls_test_cli_pwd;
extern const size_t mbedtls_test_cli_crt_len;
extern const size_t mbedtls_test_cli_key_len;
extern const size_t mbedtls_test_cli_pwd_len;
#ifdef __cplusplus #ifdef __cplusplus
} }

568
common/mbedtls/chacha20.c Normal file
View File

@@ -0,0 +1,568 @@
/**
* \file chacha20.c
*
* \brief ChaCha20 cipher.
*
* \author Daniel King <damaki.gh@gmail.com>
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#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>
#if defined(MBEDTLS_SELF_TEST)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */
#if !defined(MBEDTLS_CHACHA20_ALT)
#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
!defined(inline) && !defined(__cplusplus)
#define inline __inline
#endif
/* Parameter validation macros */
#define CHACHA20_VALIDATE_RET( cond ) \
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA )
#define CHACHA20_VALIDATE( cond ) \
MBEDTLS_INTERNAL_VALIDATE( cond )
#define BYTES_TO_U32_LE( data, offset ) \
( (uint32_t) (data)[offset] \
| (uint32_t) ( (uint32_t) (data)[( offset ) + 1] << 8 ) \
| (uint32_t) ( (uint32_t) (data)[( offset ) + 2] << 16 ) \
| (uint32_t) ( (uint32_t) (data)[( offset ) + 3] << 24 ) \
)
#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;
keystream[offset ] = (unsigned char)( working_state[i] );
keystream[offset + 1U] = (unsigned char)( working_state[i] >> 8 );
keystream[offset + 2U] = (unsigned char)( working_state[i] >> 16 );
keystream[offset + 3U] = (unsigned char)( working_state[i] >> 24 );
}
mbedtls_platform_zeroize( working_state, sizeof( working_state ) );
}
void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx )
{
CHACHA20_VALIDATE( ctx != NULL );
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_VALIDATE_RET( ctx != NULL );
CHACHA20_VALIDATE_RET( key != NULL );
/* 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] = BYTES_TO_U32_LE( key, 0 );
ctx->state[5] = BYTES_TO_U32_LE( key, 4 );
ctx->state[6] = BYTES_TO_U32_LE( key, 8 );
ctx->state[7] = BYTES_TO_U32_LE( key, 12 );
ctx->state[8] = BYTES_TO_U32_LE( key, 16 );
ctx->state[9] = BYTES_TO_U32_LE( key, 20 );
ctx->state[10] = BYTES_TO_U32_LE( key, 24 );
ctx->state[11] = BYTES_TO_U32_LE( key, 28 );
return( 0 );
}
int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx,
const unsigned char nonce[12],
uint32_t counter )
{
CHACHA20_VALIDATE_RET( ctx != NULL );
CHACHA20_VALIDATE_RET( nonce != NULL );
/* Counter */
ctx->state[12] = counter;
/* Nonce */
ctx->state[13] = BYTES_TO_U32_LE( nonce, 0 );
ctx->state[14] = BYTES_TO_U32_LE( nonce, 4 );
ctx->state[15] = BYTES_TO_U32_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;
size_t i;
CHACHA20_VALIDATE_RET( ctx != NULL );
CHACHA20_VALIDATE_RET( size == 0 || input != NULL );
CHACHA20_VALIDATE_RET( size == 0 || output != NULL );
/* 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]++;
for( i = 0U; i < 64U; i += 8U )
{
output[offset + i ] = input[offset + i ] ^ ctx->keystream8[i ];
output[offset + i+1] = input[offset + i+1] ^ ctx->keystream8[i+1];
output[offset + i+2] = input[offset + i+2] ^ ctx->keystream8[i+2];
output[offset + i+3] = input[offset + i+3] ^ ctx->keystream8[i+3];
output[offset + i+4] = input[offset + i+4] ^ ctx->keystream8[i+4];
output[offset + i+5] = input[offset + i+5] ^ ctx->keystream8[i+5];
output[offset + i+6] = input[offset + i+6] ^ ctx->keystream8[i+6];
output[offset + i+7] = input[offset + i+7] ^ ctx->keystream8[i+7];
}
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]++;
for( i = 0U; i < size; i++)
{
output[offset + i] = input[offset + i] ^ ctx->keystream8[i];
}
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;
CHACHA20_VALIDATE_RET( key != NULL );
CHACHA20_VALIDATE_RET( nonce != NULL );
CHACHA20_VALIDATE_RET( data_len == 0 || input != NULL );
CHACHA20_VALIDATE_RET( data_len == 0 || output != NULL );
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 */

225
common/mbedtls/chacha20.h Normal file
View File

@@ -0,0 +1,225 @@
/**
* \file chacha20.h
*
* \brief This file contains ChaCha20 definitions and functions.
*
* ChaCha20 is a stream cipher that can encrypt and decrypt
* information. ChaCha was created by Daniel Bernstein as a variant of
* its Salsa cipher https://cr.yp.to/chacha/chacha-20080128.pdf
* ChaCha20 is the variant with 20 rounds, that was also standardized
* in RFC 7539.
*
* \author Daniel King <damaki.gh@gmail.com>
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBEDTLS_CHACHA20_H
#define MBEDTLS_CHACHA20_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include <stdint.h>
#include <stddef.h>
#define MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA -0x0051 /**< Invalid input parameter(s). */
/* MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE is deprecated and should not be
* used. */
#define MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE -0x0053 /**< Feature not available. For example, s part of the API is not implemented. */
/* MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED is deprecated and should not be used.
*/
#define MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED -0x0055 /**< Chacha20 hardware accelerator failed. */
#ifdef __cplusplus
extern "C" {
#endif
#if !defined(MBEDTLS_CHACHA20_ALT)
typedef struct mbedtls_chacha20_context
{
uint32_t state[16]; /*! The state (before round operations). */
uint8_t keystream8[64]; /*! Leftover keystream bytes. */
size_t keystream_bytes_used; /*! Number of keystream bytes already used. */
}
mbedtls_chacha20_context;
#else /* MBEDTLS_CHACHA20_ALT */
#include "chacha20_alt.h"
#endif /* MBEDTLS_CHACHA20_ALT */
/**
* \brief This function initializes the specified ChaCha20 context.
*
* It must be the first API called before using
* the context.
*
* It is usually followed by calls to
* \c mbedtls_chacha20_setkey() and
* \c mbedtls_chacha20_starts(), then one or more calls to
* to \c mbedtls_chacha20_update(), and finally to
* \c mbedtls_chacha20_free().
*
* \param ctx The ChaCha20 context to initialize.
* This must not be \c NULL.
*/
void mbedtls_chacha20_init( mbedtls_chacha20_context *ctx );
/**
* \brief This function releases and clears the specified
* ChaCha20 context.
*
* \param ctx The ChaCha20 context to clear. This may be \c NULL,
* in which case this function is a no-op. If it is not
* \c NULL, it must point to an initialized context.
*
*/
void mbedtls_chacha20_free( mbedtls_chacha20_context *ctx );
/**
* \brief This function sets the encryption/decryption key.
*
* \note After using this function, you must also call
* \c mbedtls_chacha20_starts() to set a nonce before you
* start encrypting/decrypting data with
* \c mbedtls_chacha_update().
*
* \param ctx The ChaCha20 context to which the key should be bound.
* It must be initialized.
* \param key The encryption/decryption key. This must be \c 32 Bytes
* in length.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or key is NULL.
*/
int mbedtls_chacha20_setkey( mbedtls_chacha20_context *ctx,
const unsigned char key[32] );
/**
* \brief This function sets the nonce and initial counter value.
*
* \note A ChaCha20 context can be re-used with the same key by
* calling this function to change the nonce.
*
* \warning You must never use the same nonce twice with the same key.
* This would void any confidentiality guarantees for the
* messages encrypted with the same nonce and key.
*
* \param ctx The ChaCha20 context to which the nonce should be bound.
* It must be initialized and bound to a key.
* \param nonce The nonce. This must be \c 12 Bytes in size.
* \param counter The initial counter value. This is usually \c 0.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA if ctx or nonce is
* NULL.
*/
int mbedtls_chacha20_starts( mbedtls_chacha20_context* ctx,
const unsigned char nonce[12],
uint32_t counter );
/**
* \brief This function encrypts or decrypts data.
*
* Since ChaCha20 is a stream cipher, the same operation is
* used for encrypting and decrypting data.
*
* \note The \p input and \p output pointers must either be equal or
* point to non-overlapping buffers.
*
* \note \c mbedtls_chacha20_setkey() and
* \c mbedtls_chacha20_starts() must be called at least once
* to setup the context before this function can be called.
*
* \note This function can be called multiple times in a row in
* order to encrypt of decrypt data piecewise with the same
* key and nonce.
*
* \param ctx The ChaCha20 context to use for encryption or decryption.
* It must be initialized and bound to a key and nonce.
* \param size The length of the input data in Bytes.
* \param input The buffer holding the input data.
* This pointer can be \c NULL if `size == 0`.
* \param output The buffer holding the output data.
* This must be able to hold \p size Bytes.
* This pointer can be \c NULL if `size == 0`.
*
* \return \c 0 on success.
* \return A negative error code on failure.
*/
int mbedtls_chacha20_update( mbedtls_chacha20_context *ctx,
size_t size,
const unsigned char *input,
unsigned char *output );
/**
* \brief This function encrypts or decrypts data with ChaCha20 and
* the given key and nonce.
*
* Since ChaCha20 is a stream cipher, the same operation is
* used for encrypting and decrypting data.
*
* \warning You must never use the same (key, nonce) pair more than
* once. This would void any confidentiality guarantees for
* the messages encrypted with the same nonce and key.
*
* \note The \p input and \p output pointers must either be equal or
* point to non-overlapping buffers.
*
* \param key The encryption/decryption key.
* This must be \c 32 Bytes in length.
* \param nonce The nonce. This must be \c 12 Bytes in size.
* \param counter The initial counter value. This is usually \c 0.
* \param size The length of the input data in Bytes.
* \param input The buffer holding the input data.
* This pointer can be \c NULL if `size == 0`.
* \param output The buffer holding the output data.
* This must be able to hold \p size Bytes.
* This pointer can be \c NULL if `size == 0`.
*
* \return \c 0 on success.
* \return A negative error code on failure.
*/
int mbedtls_chacha20_crypt( const unsigned char key[32],
const unsigned char nonce[12],
uint32_t counter,
size_t size,
const unsigned char* input,
unsigned char* output );
#if defined(MBEDTLS_SELF_TEST)
/**
* \brief The ChaCha20 checkup routine.
*
* \return \c 0 on success.
* \return \c 1 on failure.
*/
int mbedtls_chacha20_self_test( int verbose );
#endif /* MBEDTLS_SELF_TEST */
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_CHACHA20_H */

538
common/mbedtls/chachapoly.c Normal file
View File

@@ -0,0 +1,538 @@
/**
* \file chachapoly.c
*
* \brief ChaCha20-Poly1305 AEAD construction based on RFC 7539.
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "common.h"
#if defined(MBEDTLS_CHACHAPOLY_C)
#include "mbedtls/chachapoly.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#include <string.h>
#if defined(MBEDTLS_SELF_TEST)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */
#if !defined(MBEDTLS_CHACHAPOLY_ALT)
/* Parameter validation macros */
#define CHACHAPOLY_VALIDATE_RET( cond ) \
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA )
#define CHACHAPOLY_VALIDATE( cond ) \
MBEDTLS_INTERNAL_VALIDATE( cond )
#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 )
{
CHACHAPOLY_VALIDATE( ctx != NULL );
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;
CHACHAPOLY_VALIDATE_RET( ctx != NULL );
CHACHAPOLY_VALIDATE_RET( key != NULL );
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];
CHACHAPOLY_VALIDATE_RET( ctx != NULL );
CHACHAPOLY_VALIDATE_RET( nonce != NULL );
/* 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 )
{
CHACHAPOLY_VALIDATE_RET( ctx != NULL );
CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
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;
CHACHAPOLY_VALIDATE_RET( ctx != NULL );
CHACHAPOLY_VALIDATE_RET( len == 0 || input != NULL );
CHACHAPOLY_VALIDATE_RET( len == 0 || output != NULL );
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];
CHACHAPOLY_VALIDATE_RET( ctx != NULL );
CHACHAPOLY_VALIDATE_RET( mac != NULL );
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.
*/
len_block[ 0] = (unsigned char)( ctx->aad_len );
len_block[ 1] = (unsigned char)( ctx->aad_len >> 8 );
len_block[ 2] = (unsigned char)( ctx->aad_len >> 16 );
len_block[ 3] = (unsigned char)( ctx->aad_len >> 24 );
len_block[ 4] = (unsigned char)( ctx->aad_len >> 32 );
len_block[ 5] = (unsigned char)( ctx->aad_len >> 40 );
len_block[ 6] = (unsigned char)( ctx->aad_len >> 48 );
len_block[ 7] = (unsigned char)( ctx->aad_len >> 56 );
len_block[ 8] = (unsigned char)( ctx->ciphertext_len );
len_block[ 9] = (unsigned char)( ctx->ciphertext_len >> 8 );
len_block[10] = (unsigned char)( ctx->ciphertext_len >> 16 );
len_block[11] = (unsigned char)( ctx->ciphertext_len >> 24 );
len_block[12] = (unsigned char)( ctx->ciphertext_len >> 32 );
len_block[13] = (unsigned char)( ctx->ciphertext_len >> 40 );
len_block[14] = (unsigned char)( ctx->ciphertext_len >> 48 );
len_block[15] = (unsigned char)( ctx->ciphertext_len >> 56 );
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] )
{
CHACHAPOLY_VALIDATE_RET( ctx != NULL );
CHACHAPOLY_VALIDATE_RET( nonce != NULL );
CHACHAPOLY_VALIDATE_RET( tag != NULL );
CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL );
CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL );
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];
size_t i;
int diff;
CHACHAPOLY_VALIDATE_RET( ctx != NULL );
CHACHAPOLY_VALIDATE_RET( nonce != NULL );
CHACHAPOLY_VALIDATE_RET( tag != NULL );
CHACHAPOLY_VALIDATE_RET( aad_len == 0 || aad != NULL );
CHACHAPOLY_VALIDATE_RET( length == 0 || input != NULL );
CHACHAPOLY_VALIDATE_RET( length == 0 || output != NULL );
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" */
for( diff = 0, i = 0; i < sizeof( check_tag ); i++ )
diff |= tag[i] ^ check_tag[i];
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 */

357
common/mbedtls/chachapoly.h Normal file
View File

@@ -0,0 +1,357 @@
/**
* \file chachapoly.h
*
* \brief This file contains the AEAD-ChaCha20-Poly1305 definitions and
* functions.
*
* ChaCha20-Poly1305 is an algorithm for Authenticated Encryption
* with Associated Data (AEAD) that can be used to encrypt and
* authenticate data. It is based on ChaCha20 and Poly1305 by Daniel
* Bernstein and was standardized in RFC 7539.
*
* \author Daniel King <damaki.gh@gmail.com>
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBEDTLS_CHACHAPOLY_H
#define MBEDTLS_CHACHAPOLY_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
/* for shared error codes */
#include "mbedtls/poly1305.h"
#define MBEDTLS_ERR_CHACHAPOLY_BAD_STATE -0x0054 /**< The requested operation is not permitted in the current state. */
#define MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED -0x0056 /**< Authenticated decryption failed: data was not authentic. */
#ifdef __cplusplus
extern "C" {
#endif
typedef enum
{
MBEDTLS_CHACHAPOLY_ENCRYPT, /**< The mode value for performing encryption. */
MBEDTLS_CHACHAPOLY_DECRYPT /**< The mode value for performing decryption. */
}
mbedtls_chachapoly_mode_t;
#if !defined(MBEDTLS_CHACHAPOLY_ALT)
#include "mbedtls/chacha20.h"
typedef struct mbedtls_chachapoly_context
{
mbedtls_chacha20_context chacha20_ctx; /**< The ChaCha20 context. */
mbedtls_poly1305_context poly1305_ctx; /**< The Poly1305 context. */
uint64_t aad_len; /**< The length (bytes) of the Additional Authenticated Data. */
uint64_t ciphertext_len; /**< The length (bytes) of the ciphertext. */
int state; /**< The current state of the context. */
mbedtls_chachapoly_mode_t mode; /**< Cipher mode (encrypt or decrypt). */
}
mbedtls_chachapoly_context;
#else /* !MBEDTLS_CHACHAPOLY_ALT */
#include "chachapoly_alt.h"
#endif /* !MBEDTLS_CHACHAPOLY_ALT */
/**
* \brief This function initializes the specified ChaCha20-Poly1305 context.
*
* It must be the first API called before using
* the context. It must be followed by a call to
* \c mbedtls_chachapoly_setkey() before any operation can be
* done, and to \c mbedtls_chachapoly_free() once all
* operations with that context have been finished.
*
* In order to encrypt or decrypt full messages at once, for
* each message you should make a single call to
* \c mbedtls_chachapoly_crypt_and_tag() or
* \c mbedtls_chachapoly_auth_decrypt().
*
* In order to encrypt messages piecewise, for each
* message you should make a call to
* \c mbedtls_chachapoly_starts(), then 0 or more calls to
* \c mbedtls_chachapoly_update_aad(), then 0 or more calls to
* \c mbedtls_chachapoly_update(), then one call to
* \c mbedtls_chachapoly_finish().
*
* \warning Decryption with the piecewise API is discouraged! Always
* use \c mbedtls_chachapoly_auth_decrypt() when possible!
*
* If however this is not possible because the data is too
* large to fit in memory, you need to:
*
* - call \c mbedtls_chachapoly_starts() and (if needed)
* \c mbedtls_chachapoly_update_aad() as above,
* - call \c mbedtls_chachapoly_update() multiple times and
* ensure its output (the plaintext) is NOT used in any other
* way than placing it in temporary storage at this point,
* - call \c mbedtls_chachapoly_finish() to compute the
* authentication tag and compared it in constant time to the
* tag received with the ciphertext.
*
* If the tags are not equal, you must immediately discard
* all previous outputs of \c mbedtls_chachapoly_update(),
* otherwise you can now safely use the plaintext.
*
* \param ctx The ChachaPoly context to initialize. Must not be \c NULL.
*/
void mbedtls_chachapoly_init( mbedtls_chachapoly_context *ctx );
/**
* \brief This function releases and clears the specified
* ChaCha20-Poly1305 context.
*
* \param ctx The ChachaPoly context to clear. This may be \c NULL, in which
* case this function is a no-op.
*/
void mbedtls_chachapoly_free( mbedtls_chachapoly_context *ctx );
/**
* \brief This function sets the ChaCha20-Poly1305
* symmetric encryption key.
*
* \param ctx The ChaCha20-Poly1305 context to which the key should be
* bound. This must be initialized.
* \param key The \c 256 Bit (\c 32 Bytes) key.
*
* \return \c 0 on success.
* \return A negative error code on failure.
*/
int mbedtls_chachapoly_setkey( mbedtls_chachapoly_context *ctx,
const unsigned char key[32] );
/**
* \brief This function starts a ChaCha20-Poly1305 encryption or
* decryption operation.
*
* \warning You must never use the same nonce twice with the same key.
* This would void any confidentiality and authenticity
* guarantees for the messages encrypted with the same nonce
* and key.
*
* \note If the context is being used for AAD only (no data to
* encrypt or decrypt) then \p mode can be set to any value.
*
* \warning Decryption with the piecewise API is discouraged, see the
* warning on \c mbedtls_chachapoly_init().
*
* \param ctx The ChaCha20-Poly1305 context. This must be initialized
* and bound to a key.
* \param nonce The nonce/IV to use for the message.
* This must be a redable buffer of length \c 12 Bytes.
* \param mode The operation to perform: #MBEDTLS_CHACHAPOLY_ENCRYPT or
* #MBEDTLS_CHACHAPOLY_DECRYPT (discouraged, see warning).
*
* \return \c 0 on success.
* \return A negative error code on failure.
*/
int mbedtls_chachapoly_starts( mbedtls_chachapoly_context *ctx,
const unsigned char nonce[12],
mbedtls_chachapoly_mode_t mode );
/**
* \brief This function feeds additional data to be authenticated
* into an ongoing ChaCha20-Poly1305 operation.
*
* The Additional Authenticated Data (AAD), also called
* Associated Data (AD) is only authenticated but not
* encrypted nor included in the encrypted output. It is
* usually transmitted separately from the ciphertext or
* computed locally by each party.
*
* \note This function is called before data is encrypted/decrypted.
* I.e. call this function to process the AAD before calling
* \c mbedtls_chachapoly_update().
*
* You may call this function multiple times to process
* an arbitrary amount of AAD. It is permitted to call
* this function 0 times, if no AAD is used.
*
* This function cannot be called any more if data has
* been processed by \c mbedtls_chachapoly_update(),
* or if the context has been finished.
*
* \warning Decryption with the piecewise API is discouraged, see the
* warning on \c mbedtls_chachapoly_init().
*
* \param ctx The ChaCha20-Poly1305 context. This must be initialized
* and bound to a key.
* \param aad_len The length in Bytes of the AAD. The length has no
* restrictions.
* \param aad Buffer containing the AAD.
* This pointer can be \c NULL if `aad_len == 0`.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA
* if \p ctx or \p aad are NULL.
* \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE
* if the operations has not been started or has been
* finished, or if the AAD has been finished.
*/
int mbedtls_chachapoly_update_aad( mbedtls_chachapoly_context *ctx,
const unsigned char *aad,
size_t aad_len );
/**
* \brief Thus function feeds data to be encrypted or decrypted
* into an on-going ChaCha20-Poly1305
* operation.
*
* The direction (encryption or decryption) depends on the
* mode that was given when calling
* \c mbedtls_chachapoly_starts().
*
* You may call this function multiple times to process
* an arbitrary amount of data. It is permitted to call
* this function 0 times, if no data is to be encrypted
* or decrypted.
*
* \warning Decryption with the piecewise API is discouraged, see the
* warning on \c mbedtls_chachapoly_init().
*
* \param ctx The ChaCha20-Poly1305 context to use. This must be initialized.
* \param len The length (in bytes) of the data to encrypt or decrypt.
* \param input The buffer containing the data to encrypt or decrypt.
* This pointer can be \c NULL if `len == 0`.
* \param output The buffer to where the encrypted or decrypted data is
* written. This must be able to hold \p len bytes.
* This pointer can be \c NULL if `len == 0`.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE
* if the operation has not been started or has been
* finished.
* \return Another negative error code on other kinds of failure.
*/
int mbedtls_chachapoly_update( mbedtls_chachapoly_context *ctx,
size_t len,
const unsigned char *input,
unsigned char *output );
/**
* \brief This function finished the ChaCha20-Poly1305 operation and
* generates the MAC (authentication tag).
*
* \param ctx The ChaCha20-Poly1305 context to use. This must be initialized.
* \param mac The buffer to where the 128-bit (16 bytes) MAC is written.
*
* \warning Decryption with the piecewise API is discouraged, see the
* warning on \c mbedtls_chachapoly_init().
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CHACHAPOLY_BAD_STATE
* if the operation has not been started or has been
* finished.
* \return Another negative error code on other kinds of failure.
*/
int mbedtls_chachapoly_finish( mbedtls_chachapoly_context *ctx,
unsigned char mac[16] );
/**
* \brief This function performs a complete ChaCha20-Poly1305
* authenticated encryption with the previously-set key.
*
* \note Before using this function, you must set the key with
* \c mbedtls_chachapoly_setkey().
*
* \warning You must never use the same nonce twice with the same key.
* This would void any confidentiality and authenticity
* guarantees for the messages encrypted with the same nonce
* and key.
*
* \param ctx The ChaCha20-Poly1305 context to use (holds the key).
* This must be initialized.
* \param length The length (in bytes) of the data to encrypt or decrypt.
* \param nonce The 96-bit (12 bytes) nonce/IV to use.
* \param aad The buffer containing the additional authenticated
* data (AAD). This pointer can be \c NULL if `aad_len == 0`.
* \param aad_len The length (in bytes) of the AAD data to process.
* \param input The buffer containing the data to encrypt or decrypt.
* This pointer can be \c NULL if `ilen == 0`.
* \param output The buffer to where the encrypted or decrypted data
* is written. This pointer can be \c NULL if `ilen == 0`.
* \param tag The buffer to where the computed 128-bit (16 bytes) MAC
* is written. This must not be \c NULL.
*
* \return \c 0 on success.
* \return A negative error code on failure.
*/
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] );
/**
* \brief This function performs a complete ChaCha20-Poly1305
* authenticated decryption with the previously-set key.
*
* \note Before using this function, you must set the key with
* \c mbedtls_chachapoly_setkey().
*
* \param ctx The ChaCha20-Poly1305 context to use (holds the key).
* \param length The length (in Bytes) of the data to decrypt.
* \param nonce The \c 96 Bit (\c 12 bytes) nonce/IV to use.
* \param aad The buffer containing the additional authenticated data (AAD).
* This pointer can be \c NULL if `aad_len == 0`.
* \param aad_len The length (in bytes) of the AAD data to process.
* \param tag The buffer holding the authentication tag.
* This must be a readable buffer of length \c 16 Bytes.
* \param input The buffer containing the data to decrypt.
* This pointer can be \c NULL if `ilen == 0`.
* \param output The buffer to where the decrypted data is written.
* This pointer can be \c NULL if `ilen == 0`.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED
* if the data was not authentic.
* \return Another negative error code on other kinds of failure.
*/
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 );
#if defined(MBEDTLS_SELF_TEST)
/**
* \brief The ChaCha20-Poly1305 checkup routine.
*
* \return \c 0 on success.
* \return \c 1 on failure.
*/
int mbedtls_chachapoly_self_test( int verbose );
#endif /* MBEDTLS_SELF_TEST */
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_CHACHAPOLY_H */

View File

@@ -4,24 +4,20 @@
* \brief Consistency checks for configuration options * \brief Consistency checks for configuration options
*/ */
/* /*
* Copyright (C) 2006-2018, ARM Limited, All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
/* /*
@@ -47,11 +43,16 @@
#endif #endif
/* Fix the config here. Not convenient to put an #ifdef _WIN32 in config.h as /* Fix the config here. Not convenient to put an #ifdef _WIN32 in config.h as
* it would confuse config.pl. */ * it would confuse config.py. */
#if !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && \ #if !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && \
!defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) !defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO)
#define MBEDTLS_PLATFORM_SNPRINTF_ALT #define MBEDTLS_PLATFORM_SNPRINTF_ALT
#endif #endif
#if !defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) && \
!defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO)
#define MBEDTLS_PLATFORM_VSNPRINTF_ALT
#endif
#endif /* _WIN32 */ #endif /* _WIN32 */
#if defined(TARGET_LIKE_MBED) && \ #if defined(TARGET_LIKE_MBED) && \
@@ -100,6 +101,17 @@
#if defined(MBEDTLS_ECDSA_C) && \ #if defined(MBEDTLS_ECDSA_C) && \
( !defined(MBEDTLS_ECP_C) || \ ( !defined(MBEDTLS_ECP_C) || \
!( defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \
defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \
defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \
defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \
defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \
defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \
defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) || \
defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \
defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \
defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) ) || \
!defined(MBEDTLS_ASN1_PARSE_C) || \ !defined(MBEDTLS_ASN1_PARSE_C) || \
!defined(MBEDTLS_ASN1_WRITE_C) ) !defined(MBEDTLS_ASN1_WRITE_C) )
#error "MBEDTLS_ECDSA_C defined, but not all prerequisites" #error "MBEDTLS_ECDSA_C defined, but not all prerequisites"
@@ -110,12 +122,33 @@
#error "MBEDTLS_ECJPAKE_C defined, but not all prerequisites" #error "MBEDTLS_ECJPAKE_C defined, but not all prerequisites"
#endif #endif
#if defined(MBEDTLS_ECP_RESTARTABLE) && \
( defined(MBEDTLS_USE_PSA_CRYPTO) || \
defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) || \
defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) || \
defined(MBEDTLS_ECDSA_SIGN_ALT) || \
defined(MBEDTLS_ECDSA_VERIFY_ALT) || \
defined(MBEDTLS_ECDSA_GENKEY_ALT) || \
defined(MBEDTLS_ECP_INTERNAL_ALT) || \
defined(MBEDTLS_ECP_ALT) )
#error "MBEDTLS_ECP_RESTARTABLE defined, but it cannot coexist with an alternative or PSA-based ECP implementation"
#endif
#if defined(MBEDTLS_ECP_RESTARTABLE) && \
! defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
#error "MBEDTLS_ECP_RESTARTABLE defined, but not MBEDTLS_ECDH_LEGACY_CONTEXT"
#endif
#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) && \
defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
#error "MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED defined, but MBEDTLS_ECDH_LEGACY_CONTEXT not disabled"
#endif
#if defined(MBEDTLS_ECDSA_DETERMINISTIC) && !defined(MBEDTLS_HMAC_DRBG_C) #if defined(MBEDTLS_ECDSA_DETERMINISTIC) && !defined(MBEDTLS_HMAC_DRBG_C)
#error "MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites" #error "MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites"
#endif #endif
#if defined(MBEDTLS_ECP_C) && ( !defined(MBEDTLS_BIGNUM_C) || ( \ #if defined(MBEDTLS_ECP_C) && ( !defined(MBEDTLS_BIGNUM_C) || ( \
!defined(MBEDTLS_ECP_DP_SECP128R1_ENABLED) && \
!defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) && \
!defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) && \
!defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) && \
@@ -126,10 +159,24 @@
!defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) && \
!defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) && \
!defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) && \ !defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) && \
!defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) ) ) !defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) && \
!defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) && \
!defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) ) )
#error "MBEDTLS_ECP_C defined, but not all prerequisites" #error "MBEDTLS_ECP_C defined, but not all prerequisites"
#endif #endif
#if defined(MBEDTLS_ECP_C) && !( \
defined(MBEDTLS_ECP_ALT) || \
defined(MBEDTLS_CTR_DRBG_C) || \
defined(MBEDTLS_HMAC_DRBG_C) || \
defined(MBEDTLS_ECP_NO_INTERNAL_RNG))
#error "MBEDTLS_ECP_C requires a DRBG module unless MBEDTLS_ECP_NO_INTERNAL_RNG is defined or an alternative implementation is used"
#endif
#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_ASN1_PARSE_C)
#error "MBEDTLS_PK_PARSE_C defined, but not all prerequesites"
#endif
#if defined(MBEDTLS_ENTROPY_C) && (!defined(MBEDTLS_SHA512_C) && \ #if defined(MBEDTLS_ENTROPY_C) && (!defined(MBEDTLS_SHA512_C) && \
!defined(MBEDTLS_SHA256_C)) !defined(MBEDTLS_SHA256_C))
#error "MBEDTLS_ENTROPY_C defined, but not all prerequisites" #error "MBEDTLS_ENTROPY_C defined, but not all prerequisites"
@@ -148,6 +195,16 @@
#error "MBEDTLS_ENTROPY_FORCE_SHA256 defined, but not all prerequisites" #error "MBEDTLS_ENTROPY_FORCE_SHA256 defined, but not all prerequisites"
#endif #endif
#if defined(__has_feature)
#if __has_feature(memory_sanitizer)
#define MBEDTLS_HAS_MEMSAN
#endif
#endif
#if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN) && !defined(MBEDTLS_HAS_MEMSAN)
#error "MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN requires building with MemorySanitizer"
#endif
#undef MBEDTLS_HAS_MEMSAN
#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ #if defined(MBEDTLS_TEST_NULL_ENTROPY) && \
( !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) ) ( !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) )
#error "MBEDTLS_TEST_NULL_ENTROPY defined, but not all prerequisites" #error "MBEDTLS_TEST_NULL_ENTROPY defined, but not all prerequisites"
@@ -159,7 +216,7 @@
#endif #endif
#if defined(MBEDTLS_GCM_C) && ( \ #if defined(MBEDTLS_GCM_C) && ( \
!defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) ) !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) && !defined(MBEDTLS_ARIA_C) )
#error "MBEDTLS_GCM_C defined, but not all prerequisites" #error "MBEDTLS_GCM_C defined, but not all prerequisites"
#endif #endif
@@ -195,6 +252,10 @@
#error "MBEDTLS_ECP_NORMALIZE_MXZ_ALT defined, but not all prerequisites" #error "MBEDTLS_ECP_NORMALIZE_MXZ_ALT defined, but not all prerequisites"
#endif #endif
#if defined(MBEDTLS_ECP_NO_FALLBACK) && !defined(MBEDTLS_ECP_INTERNAL_ALT)
#error "MBEDTLS_ECP_NO_FALLBACK defined, but no alternative implementation enabled"
#endif
#if defined(MBEDTLS_HAVEGE_C) && !defined(MBEDTLS_TIMING_C) #if defined(MBEDTLS_HAVEGE_C) && !defined(MBEDTLS_TIMING_C)
#error "MBEDTLS_HAVEGE_C defined, but not all prerequisites" #error "MBEDTLS_HAVEGE_C defined, but not all prerequisites"
#endif #endif
@@ -208,12 +269,14 @@
#endif #endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) && \ #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) && \
( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) ) ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_ECDSA_C) || \
!defined(MBEDTLS_X509_CRT_PARSE_C) )
#error "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites" #error "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites"
#endif #endif
#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \
( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) ) ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_RSA_C) || \
!defined(MBEDTLS_X509_CRT_PARSE_C) )
#error "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED defined, but not all prerequisites" #error "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED defined, but not all prerequisites"
#endif #endif
@@ -262,11 +325,27 @@
#error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites" #error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites"
#endif #endif
#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) && \
!defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) && \
( !defined(MBEDTLS_SHA256_C) && \
!defined(MBEDTLS_SHA512_C) && \
!defined(MBEDTLS_SHA1_C) )
#error "!MBEDTLS_SSL_KEEP_PEER_CERTIFICATE requires MBEDTLS_SHA512_C, MBEDTLS_SHA256_C or MBEDTLS_SHA1_C"
#endif
#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \ #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \
( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) )
#error "MBEDTLS_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites" #error "MBEDTLS_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites"
#endif #endif
#if defined(MBEDTLS_MEMORY_BACKTRACE) && !defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
#error "MBEDTLS_MEMORY_BACKTRACE defined, but not all prerequesites"
#endif
#if defined(MBEDTLS_MEMORY_DEBUG) && !defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
#error "MBEDTLS_MEMORY_DEBUG defined, but not all prerequesites"
#endif
#if defined(MBEDTLS_PADLOCK_C) && !defined(MBEDTLS_HAVE_ASM) #if defined(MBEDTLS_PADLOCK_C) && !defined(MBEDTLS_HAVE_ASM)
#error "MBEDTLS_PADLOCK_C defined, but not all prerequisites" #error "MBEDTLS_PADLOCK_C defined, but not all prerequisites"
#endif #endif
@@ -296,6 +375,14 @@
#error "MBEDTLS_PKCS11_C defined, but not all prerequisites" #error "MBEDTLS_PKCS11_C defined, but not all prerequisites"
#endif #endif
#if defined(MBEDTLS_PKCS11_C)
#if defined(MBEDTLS_DEPRECATED_REMOVED)
#error "MBEDTLS_PKCS11_C is deprecated and will be removed in a future version of Mbed TLS"
#elif defined(MBEDTLS_DEPRECATED_WARNING)
#warning "MBEDTLS_PKCS11_C is deprecated and will be removed in a future version of Mbed TLS"
#endif
#endif /* MBEDTLS_PKCS11_C */
#if defined(MBEDTLS_PLATFORM_EXIT_ALT) && !defined(MBEDTLS_PLATFORM_C) #if defined(MBEDTLS_PLATFORM_EXIT_ALT) && !defined(MBEDTLS_PLATFORM_C)
#error "MBEDTLS_PLATFORM_EXIT_ALT defined, but not all prerequisites" #error "MBEDTLS_PLATFORM_EXIT_ALT defined, but not all prerequisites"
#endif #endif
@@ -489,6 +576,54 @@
#error "MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_WRITE cannot be defined simultaneously" #error "MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_WRITE cannot be defined simultaneously"
#endif #endif
#if defined(MBEDTLS_PSA_CRYPTO_C) && \
!( ( ( defined(MBEDTLS_CTR_DRBG_C) || defined(MBEDTLS_HMAC_DRBG_C) ) && \
defined(MBEDTLS_ENTROPY_C) ) || \
defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) )
#error "MBEDTLS_PSA_CRYPTO_C defined, but not all prerequisites (missing RNG)"
#endif
#if defined(MBEDTLS_PSA_CRYPTO_SPM) && !defined(MBEDTLS_PSA_CRYPTO_C)
#error "MBEDTLS_PSA_CRYPTO_SPM defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PSA_CRYPTO_SE_C) && \
! ( defined(MBEDTLS_PSA_CRYPTO_C) && \
defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) )
#error "MBEDTLS_PSA_CRYPTO_SE_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) && \
! defined(MBEDTLS_PSA_CRYPTO_C)
#error "MBEDTLS_PSA_CRYPTO_STORAGE_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \
!( defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) && \
defined(MBEDTLS_ENTROPY_NV_SEED) )
#error "MBEDTLS_PSA_INJECT_ENTROPY defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \
!defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES)
#error "MBEDTLS_PSA_INJECT_ENTROPY is not compatible with actual entropy sources"
#endif
#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \
defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
#error "MBEDTLS_PSA_INJECT_ENTROPY is not compatible with MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG"
#endif
#if defined(MBEDTLS_PSA_ITS_FILE_C) && \
!defined(MBEDTLS_FS_IO)
#error "MBEDTLS_PSA_ITS_FILE_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) && \
defined(MBEDTLS_USE_PSA_CRYPTO)
#error "MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER defined, but it cannot coexist with MBEDTLS_USE_PSA_CRYPTO."
#endif
#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ #if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_BIGNUM_C) || \
!defined(MBEDTLS_OID_C) ) !defined(MBEDTLS_OID_C) )
#error "MBEDTLS_RSA_C defined, but not all prerequisites" #error "MBEDTLS_RSA_C defined, but not all prerequisites"
@@ -504,6 +639,10 @@
#error "MBEDTLS_X509_RSASSA_PSS_SUPPORT defined, but not all prerequisites" #error "MBEDTLS_X509_RSASSA_PSS_SUPPORT defined, but not all prerequisites"
#endif #endif
#if defined(MBEDTLS_SHA512_NO_SHA384) && !defined(MBEDTLS_SHA512_C)
#error "MBEDTLS_SHA512_NO_SHA384 defined without MBEDTLS_SHA512_C"
#endif
#if defined(MBEDTLS_SSL_PROTO_SSL3) && ( !defined(MBEDTLS_MD5_C) || \ #if defined(MBEDTLS_SSL_PROTO_SSL3) && ( !defined(MBEDTLS_MD5_C) || \
!defined(MBEDTLS_SHA1_C) ) !defined(MBEDTLS_SHA1_C) )
#error "MBEDTLS_SSL_PROTO_SSL3 defined, but not all prerequisites" #error "MBEDTLS_SSL_PROTO_SSL3 defined, but not all prerequisites"
@@ -524,6 +663,28 @@
#error "MBEDTLS_SSL_PROTO_TLS1_2 defined, but not all prerequisites" #error "MBEDTLS_SSL_PROTO_TLS1_2 defined, but not all prerequisites"
#endif #endif
#if defined(MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL) && ( !defined(MBEDTLS_HKDF_C) && \
!defined(MBEDTLS_SHA256_C) && !defined(MBEDTLS_SHA512_C) )
#error "MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL defined, but not all prerequisites"
#endif
#if (defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
defined(MBEDTLS_SSL_PROTO_TLS1_1) || defined(MBEDTLS_SSL_PROTO_TLS1_2)) && \
!(defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) )
#error "One or more versions of the TLS protocol are enabled " \
"but no key exchange methods defined with MBEDTLS_KEY_EXCHANGE_xxxx"
#endif
#if defined(MBEDTLS_SSL_PROTO_DTLS) && \ #if defined(MBEDTLS_SSL_PROTO_DTLS) && \
!defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \
!defined(MBEDTLS_SSL_PROTO_TLS1_2) !defined(MBEDTLS_SSL_PROTO_TLS1_2)
@@ -579,6 +740,23 @@
#error "MBEDTLS_SSL_DTLS_ANTI_REPLAY defined, but not all prerequisites" #error "MBEDTLS_SSL_DTLS_ANTI_REPLAY defined, but not all prerequisites"
#endif #endif
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \
( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) )
#error "MBEDTLS_SSL_DTLS_CONNECTION_ID defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \
defined(MBEDTLS_SSL_CID_IN_LEN_MAX) && \
MBEDTLS_SSL_CID_IN_LEN_MAX > 255
#error "MBEDTLS_SSL_CID_IN_LEN_MAX too large (max 255)"
#endif
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \
defined(MBEDTLS_SSL_CID_OUT_LEN_MAX) && \
MBEDTLS_SSL_CID_OUT_LEN_MAX > 255
#error "MBEDTLS_SSL_CID_OUT_LEN_MAX too large (max 255)"
#endif
#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) && \ #if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) && \
( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) )
#error "MBEDTLS_SSL_DTLS_BADMAC_LIMIT defined, but not all prerequisites" #error "MBEDTLS_SSL_DTLS_BADMAC_LIMIT defined, but not all prerequisites"
@@ -631,6 +809,10 @@
#endif #endif
#undef MBEDTLS_THREADING_IMPL #undef MBEDTLS_THREADING_IMPL
#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_PSA_CRYPTO_C)
#error "MBEDTLS_USE_PSA_CRYPTO defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_VERSION_FEATURES) && !defined(MBEDTLS_VERSION_C) #if defined(MBEDTLS_VERSION_FEATURES) && !defined(MBEDTLS_VERSION_C)
#error "MBEDTLS_VERSION_FEATURES defined, but not all prerequisites" #error "MBEDTLS_VERSION_FEATURES defined, but not all prerequisites"
#endif #endif
@@ -647,6 +829,10 @@
#error "MBEDTLS_X509_CREATE_C defined, but not all prerequisites" #error "MBEDTLS_X509_CREATE_C defined, but not all prerequisites"
#endif #endif
#if defined(MBEDTLS_CERTS_C) && !defined(MBEDTLS_X509_USE_C)
#error "MBEDTLS_CERTS_C defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_X509_CRT_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) #if defined(MBEDTLS_X509_CRT_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) )
#error "MBEDTLS_X509_CRT_PARSE_C defined, but not all prerequisites" #error "MBEDTLS_X509_CRT_PARSE_C defined, but not all prerequisites"
#endif #endif
@@ -676,10 +862,42 @@
#error "MBEDTLS_HAVE_INT32/MBEDTLS_HAVE_INT64 and MBEDTLS_HAVE_ASM cannot be defined simultaneously" #error "MBEDTLS_HAVE_INT32/MBEDTLS_HAVE_INT64 and MBEDTLS_HAVE_ASM cannot be defined simultaneously"
#endif /* (MBEDTLS_HAVE_INT32 || MBEDTLS_HAVE_INT64) && MBEDTLS_HAVE_ASM */ #endif /* (MBEDTLS_HAVE_INT32 || MBEDTLS_HAVE_INT64) && MBEDTLS_HAVE_ASM */
#if defined(MBEDTLS_SSL_PROTO_SSL3)
#if defined(MBEDTLS_DEPRECATED_REMOVED)
#error "MBEDTLS_SSL_PROTO_SSL3 is deprecated and will be removed in a future version of Mbed TLS"
#elif defined(MBEDTLS_DEPRECATED_WARNING)
#warning "MBEDTLS_SSL_PROTO_SSL3 is deprecated and will be removed in a future version of Mbed TLS"
#endif
#endif /* MBEDTLS_SSL_PROTO_SSL3 */
#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO)
#if defined(MBEDTLS_DEPRECATED_REMOVED)
#error "MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO is deprecated and will be removed in a future version of Mbed TLS"
#elif defined(MBEDTLS_DEPRECATED_WARNING)
#warning "MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO is deprecated and will be removed in a future version of Mbed TLS"
#endif
#endif /* MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO */
#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
#if defined(MBEDTLS_DEPRECATED_REMOVED)
#error "MBEDTLS_SSL_HW_RECORD_ACCEL is deprecated and will be removed in a future version of Mbed TLS"
#elif defined(MBEDTLS_DEPRECATED_WARNING)
#warning "MBEDTLS_SSL_HW_RECORD_ACCEL is deprecated and will be removed in a future version of Mbed TLS"
#endif /* MBEDTLS_DEPRECATED_REMOVED */
#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */
#if defined(MBEDTLS_SSL_DTLS_SRTP) && ( !defined(MBEDTLS_SSL_PROTO_DTLS) )
#error "MBEDTLS_SSL_DTLS_SRTP defined, but not all prerequisites"
#endif
#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) && ( !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) )
#error "MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH defined, but not all prerequisites"
#endif
/* /*
* Avoid warning from -pedantic. This is a convenient place for this * Avoid warning from -pedantic. This is a convenient place for this
* workaround since this is included by every single file before the * workaround since this is included by every single file before the
* #if defined(MBEDTLS_xxx_C) that results in emtpy translation units. * #if defined(MBEDTLS_xxx_C) that results in empty translation units.
*/ */
typedef int mbedtls_iso_c_forbids_empty_translation_units; typedef int mbedtls_iso_c_forbids_empty_translation_units;

View File

@@ -0,0 +1,72 @@
/**
* \file check_crypto_config.h
*
* \brief Consistency checks for PSA configuration options
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* 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_DETERMINISTIC_ECDSA) && \
!( defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) || \
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) || \
defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) )
#error "PSA_WANT_ALG_ECDSA defined, but not all prerequisites"
#endif
#if defined(PSA_WANT_ALG_RSA_PKCS1V15_CRYPT) && \
!( defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) || \
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) || \
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) || \
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) || \
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) && \
!defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
#error "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR defined, but not all prerequisites"
#endif
#endif /* MBEDTLS_CHECK_CRYPTO_CONFIG_H */

File diff suppressed because it is too large Load Diff

View File

@@ -8,36 +8,33 @@
* \author Adriaan de Jong <dejong@fox-it.com> * \author Adriaan de Jong <dejong@fox-it.com>
*/ */
/* /*
* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of Mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
#ifndef MBEDTLS_CIPHER_H #ifndef MBEDTLS_CIPHER_H
#define MBEDTLS_CIPHER_H #define MBEDTLS_CIPHER_H
#if !defined(MBEDTLS_CONFIG_FILE) #if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h" #include "mbedtls/config.h"
#else #else
#include MBEDTLS_CONFIG_FILE #include MBEDTLS_CONFIG_FILE
#endif #endif
#include <stddef.h> #include <stddef.h>
#include "mbedtls/platform_util.h"
#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_CHACHAPOLY_C) #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
#define MBEDTLS_CIPHER_MODE_AEAD #define MBEDTLS_CIPHER_MODE_AEAD
@@ -64,6 +61,8 @@
#define MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280 /**< Decryption of block requires a full block. */ #define MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280 /**< Decryption of block requires a full block. */
#define MBEDTLS_ERR_CIPHER_AUTH_FAILED -0x6300 /**< Authentication failed (for AEAD modes). */ #define MBEDTLS_ERR_CIPHER_AUTH_FAILED -0x6300 /**< Authentication failed (for AEAD modes). */
#define MBEDTLS_ERR_CIPHER_INVALID_CONTEXT -0x6380 /**< The context is invalid. For example, because it was freed. */ #define MBEDTLS_ERR_CIPHER_INVALID_CONTEXT -0x6380 /**< The context is invalid. For example, because it was freed. */
/* MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED -0x6400 /**< Cipher hardware accelerator failed. */ #define MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED -0x6400 /**< Cipher hardware accelerator failed. */
#define MBEDTLS_CIPHER_VARIABLE_IV_LEN 0x01 /**< Cipher accepts IVs of variable length. */ #define MBEDTLS_CIPHER_VARIABLE_IV_LEN 0x01 /**< Cipher accepts IVs of variable length. */
@@ -175,21 +174,29 @@ typedef enum {
MBEDTLS_CIPHER_AES_256_XTS, /**< AES 256-bit cipher in XTS block mode. */ MBEDTLS_CIPHER_AES_256_XTS, /**< AES 256-bit cipher in XTS block mode. */
MBEDTLS_CIPHER_CHACHA20, /**< ChaCha20 stream cipher. */ MBEDTLS_CIPHER_CHACHA20, /**< ChaCha20 stream cipher. */
MBEDTLS_CIPHER_CHACHA20_POLY1305, /**< ChaCha20-Poly1305 AEAD cipher. */ MBEDTLS_CIPHER_CHACHA20_POLY1305, /**< ChaCha20-Poly1305 AEAD cipher. */
MBEDTLS_CIPHER_AES_128_KW, /**< AES cipher with 128-bit NIST KW mode. */
MBEDTLS_CIPHER_AES_192_KW, /**< AES cipher with 192-bit NIST KW mode. */
MBEDTLS_CIPHER_AES_256_KW, /**< AES cipher with 256-bit NIST KW mode. */
MBEDTLS_CIPHER_AES_128_KWP, /**< AES cipher with 128-bit NIST KWP mode. */
MBEDTLS_CIPHER_AES_192_KWP, /**< AES cipher with 192-bit NIST KWP mode. */
MBEDTLS_CIPHER_AES_256_KWP, /**< AES cipher with 256-bit NIST KWP mode. */
} mbedtls_cipher_type_t; } mbedtls_cipher_type_t;
/** Supported cipher modes. */ /** Supported cipher modes. */
typedef enum { typedef enum {
MBEDTLS_MODE_NONE = 0, /**< None. */ MBEDTLS_MODE_NONE = 0, /**< None. */
MBEDTLS_MODE_ECB, /**< The ECB cipher mode. */ MBEDTLS_MODE_ECB, /**< The ECB cipher mode. */
MBEDTLS_MODE_CBC, /**< The CBC cipher mode. */ MBEDTLS_MODE_CBC, /**< The CBC cipher mode. */
MBEDTLS_MODE_CFB, /**< The CFB cipher mode. */ MBEDTLS_MODE_CFB, /**< The CFB cipher mode. */
MBEDTLS_MODE_OFB, /**< The OFB cipher mode. */ MBEDTLS_MODE_OFB, /**< The OFB cipher mode. */
MBEDTLS_MODE_CTR, /**< The CTR cipher mode. */ MBEDTLS_MODE_CTR, /**< The CTR cipher mode. */
MBEDTLS_MODE_GCM, /**< The GCM cipher mode. */ MBEDTLS_MODE_GCM, /**< The GCM cipher mode. */
MBEDTLS_MODE_STREAM, /**< The stream cipher mode. */ MBEDTLS_MODE_STREAM, /**< The stream cipher mode. */
MBEDTLS_MODE_CCM, /**< The CCM cipher mode. */ MBEDTLS_MODE_CCM, /**< The CCM cipher mode. */
MBEDTLS_MODE_XTS, /**< The XTS cipher mode. */ MBEDTLS_MODE_XTS, /**< The XTS cipher mode. */
MBEDTLS_MODE_CHACHAPOLY, /**< The ChaCha-Poly cipher mode. */ MBEDTLS_MODE_CHACHAPOLY, /**< The ChaCha-Poly cipher mode. */
MBEDTLS_MODE_KW, /**< The SP800-38F KW mode */
MBEDTLS_MODE_KWP, /**< The SP800-38F KWP mode */
} mbedtls_cipher_mode_t; } mbedtls_cipher_mode_t;
/** Supported cipher padding types. */ /** Supported cipher padding types. */
@@ -220,10 +227,30 @@ enum {
}; };
/** Maximum length of any IV, in Bytes. */ /** Maximum length of any IV, in Bytes. */
/* This should ideally be derived automatically from list of ciphers.
* This should be kept in sync with MBEDTLS_SSL_MAX_IV_LENGTH defined
* in ssl_internal.h. */
#define MBEDTLS_MAX_IV_LENGTH 16 #define MBEDTLS_MAX_IV_LENGTH 16
/** Maximum block size of any cipher, in Bytes. */ /** Maximum block size of any cipher, in Bytes. */
/* This should ideally be derived automatically from list of ciphers.
* This should be kept in sync with MBEDTLS_SSL_MAX_BLOCK_LENGTH defined
* in ssl_internal.h. */
#define MBEDTLS_MAX_BLOCK_LENGTH 16 #define MBEDTLS_MAX_BLOCK_LENGTH 16
/** Maximum key length, in Bytes. */
/* This should ideally be derived automatically from list of ciphers.
* For now, only check whether XTS is enabled which uses 64 Byte keys,
* and use 32 Bytes as an upper bound for the maximum key length otherwise.
* This should be kept in sync with MBEDTLS_SSL_MAX_BLOCK_LENGTH defined
* in ssl_internal.h, which however deliberately ignores the case of XTS
* since the latter isn't used in SSL/TLS. */
#if defined(MBEDTLS_CIPHER_MODE_XTS)
#define MBEDTLS_MAX_KEY_LENGTH 64
#else
#define MBEDTLS_MAX_KEY_LENGTH 32
#endif /* MBEDTLS_CIPHER_MODE_XTS */
/** /**
* Base cipher information (opaque struct). * Base cipher information (opaque struct).
*/ */
@@ -238,7 +265,8 @@ typedef struct mbedtls_cmac_context_t mbedtls_cmac_context_t;
* Cipher information. Allows calling cipher functions * Cipher information. Allows calling cipher functions
* in a generic way. * in a generic way.
*/ */
typedef struct mbedtls_cipher_info_t { typedef struct mbedtls_cipher_info_t
{
/** Full cipher identifier. For example, /** Full cipher identifier. For example,
* MBEDTLS_CIPHER_AES_256_CBC. * MBEDTLS_CIPHER_AES_256_CBC.
*/ */
@@ -254,7 +282,7 @@ typedef struct mbedtls_cipher_info_t {
unsigned int key_bitlen; unsigned int key_bitlen;
/** Name of the cipher. */ /** Name of the cipher. */
const char *name; const char * name;
/** IV or nonce size, in Bytes. /** IV or nonce size, in Bytes.
* For ciphers that accept variable IV sizes, * For ciphers that accept variable IV sizes,
@@ -279,7 +307,8 @@ typedef struct mbedtls_cipher_info_t {
/** /**
* Generic cipher context. * Generic cipher context.
*/ */
typedef struct mbedtls_cipher_context_t { typedef struct mbedtls_cipher_context_t
{
/** Information about the associated cipher. */ /** Information about the associated cipher. */
const mbedtls_cipher_info_t *cipher_info; const mbedtls_cipher_info_t *cipher_info;
@@ -295,8 +324,8 @@ typedef struct mbedtls_cipher_context_t {
/** Padding functions to use, if relevant for /** Padding functions to use, if relevant for
* the specific cipher mode. * the specific cipher mode.
*/ */
void (*add_padding)(unsigned char *output, size_t olen, size_t data_len); void (*add_padding)( unsigned char *output, size_t olen, size_t data_len );
int (*get_padding)(unsigned char *input, size_t ilen, size_t *data_len); int (*get_padding)( unsigned char *input, size_t ilen, size_t *data_len );
#endif #endif
/** Buffer for input that has not been processed yet. */ /** Buffer for input that has not been processed yet. */
@@ -319,28 +348,47 @@ typedef struct mbedtls_cipher_context_t {
/** CMAC-specific context. */ /** CMAC-specific context. */
mbedtls_cmac_context_t *cmac_ctx; mbedtls_cmac_context_t *cmac_ctx;
#endif #endif
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/** Indicates whether the cipher operations should be performed
* by Mbed TLS' own crypto library or an external implementation
* of the PSA Crypto API.
* This is unset if the cipher context was established through
* mbedtls_cipher_setup(), and set if it was established through
* mbedtls_cipher_setup_psa().
*/
unsigned char psa_enabled;
#endif /* MBEDTLS_USE_PSA_CRYPTO */
} mbedtls_cipher_context_t; } mbedtls_cipher_context_t;
/** /**
* \brief This function retrieves the list of ciphers supported by the generic * \brief This function retrieves the list of ciphers supported
* cipher module. * by the generic cipher module.
* *
* \return A statically-allocated array of ciphers. The last entry * For any cipher identifier in the returned list, you can
* is zero. * obtain the corresponding generic cipher information structure
* via mbedtls_cipher_info_from_type(), which can then be used
* to prepare a cipher context via mbedtls_cipher_setup().
*
*
* \return A statically-allocated array of cipher identifiers
* of type cipher_type_t. The last entry is zero.
*/ */
const int *mbedtls_cipher_list(void); const int *mbedtls_cipher_list( void );
/** /**
* \brief This function retrieves the cipher-information * \brief This function retrieves the cipher-information
* structure associated with the given cipher name. * structure associated with the given cipher name.
* *
* \param cipher_name Name of the cipher to search for. * \param cipher_name Name of the cipher to search for. This must not be
* \c NULL.
* *
* \return The cipher information structure associated with the * \return The cipher information structure associated with the
* given \p cipher_name. * given \p cipher_name.
* \return NULL if the associated cipher information is not found. * \return \c NULL if the associated cipher information is not found.
*/ */
const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string(const char *cipher_name); const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name );
/** /**
* \brief This function retrieves the cipher-information * \brief This function retrieves the cipher-information
@@ -350,9 +398,9 @@ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string(const char *cipher_
* *
* \return The cipher information structure associated with the * \return The cipher information structure associated with the
* given \p cipher_type. * given \p cipher_type.
* \return NULL if the associated cipher information is not found. * \return \c NULL if the associated cipher information is not found.
*/ */
const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type(const mbedtls_cipher_type_t cipher_type); const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type );
/** /**
* \brief This function retrieves the cipher-information * \brief This function retrieves the cipher-information
@@ -366,31 +414,36 @@ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type(const mbedtls_cipher_
* *
* \return The cipher information structure associated with the * \return The cipher information structure associated with the
* given \p cipher_id. * given \p cipher_id.
* \return NULL if the associated cipher information is not found. * \return \c NULL if the associated cipher information is not found.
*/ */
const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values(const mbedtls_cipher_id_t cipher_id, const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id,
int key_bitlen, int key_bitlen,
const mbedtls_cipher_mode_t mode); const mbedtls_cipher_mode_t mode );
/** /**
* \brief This function initializes a \p cipher_context as NONE. * \brief This function initializes a \p cipher_context as NONE.
*
* \param ctx The context to be initialized. This must not be \c NULL.
*/ */
void mbedtls_cipher_init(mbedtls_cipher_context_t *ctx); void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx );
/** /**
* \brief This function frees and clears the cipher-specific * \brief This function frees and clears the cipher-specific
* context of \p ctx. Freeing \p ctx itself remains the * context of \p ctx. Freeing \p ctx itself remains the
* responsibility of the caller. * responsibility of the caller.
*
* \param ctx The context to be freed. If this is \c NULL, the
* function has no effect, otherwise this must point to an
* initialized context.
*/ */
void mbedtls_cipher_free(mbedtls_cipher_context_t *ctx); void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx );
/** /**
* \brief This function initializes and fills the cipher-context * \brief This function initializes a cipher context for
* structure with the appropriate values. It also clears * use with the given cipher primitive.
* the structure.
* *
* \param ctx The context to initialize. May not be NULL. * \param ctx The context to initialize. This must be initialized.
* \param cipher_info The cipher to use. * \param cipher_info The cipher to use.
* *
* \return \c 0 on success. * \return \c 0 on success.
@@ -403,18 +456,49 @@ void mbedtls_cipher_free(mbedtls_cipher_context_t *ctx);
* In future versions, the caller will be required to call * In future versions, the caller will be required to call
* mbedtls_cipher_init() on the structure first. * mbedtls_cipher_init() on the structure first.
*/ */
int mbedtls_cipher_setup(mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info); int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx,
const mbedtls_cipher_info_t *cipher_info );
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/**
* \brief This function initializes a cipher context for
* PSA-based use with the given cipher primitive.
*
* \note See #MBEDTLS_USE_PSA_CRYPTO for information on PSA.
*
* \param ctx The context to initialize. May not be \c NULL.
* \param cipher_info The cipher to use.
* \param taglen For AEAD ciphers, the length in bytes of the
* authentication tag to use. Subsequent uses of
* mbedtls_cipher_auth_encrypt() or
* mbedtls_cipher_auth_decrypt() must provide
* the same tag length.
* For non-AEAD ciphers, the value must be \c 0.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on
* parameter-verification failure.
* \return #MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the
* cipher-specific context fails.
*/
int mbedtls_cipher_setup_psa( mbedtls_cipher_context_t *ctx,
const mbedtls_cipher_info_t *cipher_info,
size_t taglen );
#endif /* MBEDTLS_USE_PSA_CRYPTO */
/** /**
* \brief This function returns the block size of the given cipher. * \brief This function returns the block size of the given cipher.
* *
* \param ctx The context of the cipher. Must be initialized. * \param ctx The context of the cipher. This must be initialized.
* *
* \return The size of the blocks of the cipher. * \return The block size of the underlying cipher.
* \return 0 if \p ctx has not been initialized. * \return \c 0 if \p ctx has not been initialized.
*/ */
static inline unsigned int mbedtls_cipher_get_block_size(const mbedtls_cipher_context_t *ctx) { static inline unsigned int mbedtls_cipher_get_block_size(
if (NULL == ctx || NULL == ctx->cipher_info) const mbedtls_cipher_context_t *ctx )
{
MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 );
if( ctx->cipher_info == NULL )
return 0; return 0;
return ctx->cipher_info->block_size; return ctx->cipher_info->block_size;
@@ -424,13 +508,16 @@ static inline unsigned int mbedtls_cipher_get_block_size(const mbedtls_cipher_co
* \brief This function returns the mode of operation for * \brief This function returns the mode of operation for
* the cipher. For example, MBEDTLS_MODE_CBC. * the cipher. For example, MBEDTLS_MODE_CBC.
* *
* \param ctx The context of the cipher. Must be initialized. * \param ctx The context of the cipher. This must be initialized.
* *
* \return The mode of operation. * \return The mode of operation.
* \return #MBEDTLS_MODE_NONE if \p ctx has not been initialized. * \return #MBEDTLS_MODE_NONE if \p ctx has not been initialized.
*/ */
static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode(const mbedtls_cipher_context_t *ctx) { static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode(
if (NULL == ctx || NULL == ctx->cipher_info) const mbedtls_cipher_context_t *ctx )
{
MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, MBEDTLS_MODE_NONE );
if( ctx->cipher_info == NULL )
return MBEDTLS_MODE_NONE; return MBEDTLS_MODE_NONE;
return ctx->cipher_info->mode; return ctx->cipher_info->mode;
@@ -440,17 +527,20 @@ static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode(const mbedtls
* \brief This function returns the size of the IV or nonce * \brief This function returns the size of the IV or nonce
* of the cipher, in Bytes. * of the cipher, in Bytes.
* *
* \param ctx The context of the cipher. Must be initialized. * \param ctx The context of the cipher. This must be initialized.
* *
* \return The recommended IV size if no IV has been set. * \return The recommended IV size if no IV has been set.
* \return \c 0 for ciphers not using an IV or a nonce. * \return \c 0 for ciphers not using an IV or a nonce.
* \return The actual size if an IV has been set. * \return The actual size if an IV has been set.
*/ */
static inline int mbedtls_cipher_get_iv_size(const mbedtls_cipher_context_t *ctx) { static inline int mbedtls_cipher_get_iv_size(
if (NULL == ctx || NULL == ctx->cipher_info) const mbedtls_cipher_context_t *ctx )
{
MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 );
if( ctx->cipher_info == NULL )
return 0; return 0;
if (ctx->iv_size != 0) if( ctx->iv_size != 0 )
return (int) ctx->iv_size; return (int) ctx->iv_size;
return (int) ctx->cipher_info->iv_size; return (int) ctx->cipher_info->iv_size;
@@ -459,13 +549,17 @@ static inline int mbedtls_cipher_get_iv_size(const mbedtls_cipher_context_t *ctx
/** /**
* \brief This function returns the type of the given cipher. * \brief This function returns the type of the given cipher.
* *
* \param ctx The context of the cipher. Must be initialized. * \param ctx The context of the cipher. This must be initialized.
* *
* \return The type of the cipher. * \return The type of the cipher.
* \return #MBEDTLS_CIPHER_NONE if \p ctx has not been initialized. * \return #MBEDTLS_CIPHER_NONE if \p ctx has not been initialized.
*/ */
static inline mbedtls_cipher_type_t mbedtls_cipher_get_type(const mbedtls_cipher_context_t *ctx) { static inline mbedtls_cipher_type_t mbedtls_cipher_get_type(
if (NULL == ctx || NULL == ctx->cipher_info) const mbedtls_cipher_context_t *ctx )
{
MBEDTLS_INTERNAL_VALIDATE_RET(
ctx != NULL, MBEDTLS_CIPHER_NONE );
if( ctx->cipher_info == NULL )
return MBEDTLS_CIPHER_NONE; return MBEDTLS_CIPHER_NONE;
return ctx->cipher_info->type; return ctx->cipher_info->type;
@@ -475,13 +569,16 @@ static inline mbedtls_cipher_type_t mbedtls_cipher_get_type(const mbedtls_cipher
* \brief This function returns the name of the given cipher * \brief This function returns the name of the given cipher
* as a string. * as a string.
* *
* \param ctx The context of the cipher. Must be initialized. * \param ctx The context of the cipher. This must be initialized.
* *
* \return The name of the cipher. * \return The name of the cipher.
* \return NULL if \p ctx has not been not initialized. * \return NULL if \p ctx has not been not initialized.
*/ */
static inline const char *mbedtls_cipher_get_name(const mbedtls_cipher_context_t *ctx) { static inline const char *mbedtls_cipher_get_name(
if (NULL == ctx || NULL == ctx->cipher_info) const mbedtls_cipher_context_t *ctx )
{
MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 );
if( ctx->cipher_info == NULL )
return 0; return 0;
return ctx->cipher_info->name; return ctx->cipher_info->name;
@@ -490,14 +587,18 @@ static inline const char *mbedtls_cipher_get_name(const mbedtls_cipher_context_t
/** /**
* \brief This function returns the key length of the cipher. * \brief This function returns the key length of the cipher.
* *
* \param ctx The context of the cipher. Must be initialized. * \param ctx The context of the cipher. This must be initialized.
* *
* \return The key length of the cipher in bits. * \return The key length of the cipher in bits.
* \return #MBEDTLS_KEY_LENGTH_NONE if ctx \p has not been * \return #MBEDTLS_KEY_LENGTH_NONE if ctx \p has not been
* initialized. * initialized.
*/ */
static inline int mbedtls_cipher_get_key_bitlen(const mbedtls_cipher_context_t *ctx) { static inline int mbedtls_cipher_get_key_bitlen(
if (NULL == ctx || NULL == ctx->cipher_info) const mbedtls_cipher_context_t *ctx )
{
MBEDTLS_INTERNAL_VALIDATE_RET(
ctx != NULL, MBEDTLS_KEY_LENGTH_NONE );
if( ctx->cipher_info == NULL )
return MBEDTLS_KEY_LENGTH_NONE; return MBEDTLS_KEY_LENGTH_NONE;
return (int) ctx->cipher_info->key_bitlen; return (int) ctx->cipher_info->key_bitlen;
@@ -506,13 +607,17 @@ static inline int mbedtls_cipher_get_key_bitlen(const mbedtls_cipher_context_t *
/** /**
* \brief This function returns the operation of the given cipher. * \brief This function returns the operation of the given cipher.
* *
* \param ctx The context of the cipher. Must be initialized. * \param ctx The context of the cipher. This must be initialized.
* *
* \return The type of operation: #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT. * \return The type of operation: #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT.
* \return #MBEDTLS_OPERATION_NONE if \p ctx has not been initialized. * \return #MBEDTLS_OPERATION_NONE if \p ctx has not been initialized.
*/ */
static inline mbedtls_operation_t mbedtls_cipher_get_operation(const mbedtls_cipher_context_t *ctx) { static inline mbedtls_operation_t mbedtls_cipher_get_operation(
if (NULL == ctx || NULL == ctx->cipher_info) const mbedtls_cipher_context_t *ctx )
{
MBEDTLS_INTERNAL_VALIDATE_RET(
ctx != NULL, MBEDTLS_OPERATION_NONE );
if( ctx->cipher_info == NULL )
return MBEDTLS_OPERATION_NONE; return MBEDTLS_OPERATION_NONE;
return ctx->operation; return ctx->operation;
@@ -521,11 +626,11 @@ static inline mbedtls_operation_t mbedtls_cipher_get_operation(const mbedtls_cip
/** /**
* \brief This function sets the key to use with the given context. * \brief This function sets the key to use with the given context.
* *
* \param ctx The generic cipher context. May not be NULL. Must have * \param ctx The generic cipher context. This must be initialized and
* been initialized using mbedtls_cipher_info_from_type() * bound to a cipher information structure.
* or mbedtls_cipher_info_from_string(). * \param key The key to use. This must be a readable buffer of at
* \param key The key to use. * least \p key_bitlen Bits.
* \param key_bitlen The key length to use, in bits. * \param key_bitlen The key length to use, in Bits.
* \param operation The operation that the key will be used for: * \param operation The operation that the key will be used for:
* #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT. * #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT.
* *
@@ -534,8 +639,10 @@ static inline mbedtls_operation_t mbedtls_cipher_get_operation(const mbedtls_cip
* parameter-verification failure. * parameter-verification failure.
* \return A cipher-specific error code on failure. * \return A cipher-specific error code on failure.
*/ */
int mbedtls_cipher_setkey(mbedtls_cipher_context_t *ctx, const unsigned char *key, int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx,
int key_bitlen, const mbedtls_operation_t operation); const unsigned char *key,
int key_bitlen,
const mbedtls_operation_t operation );
#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) #if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
/** /**
@@ -544,7 +651,8 @@ int mbedtls_cipher_setkey(mbedtls_cipher_context_t *ctx, const unsigned char *ke
* *
* The default passing mode is PKCS7 padding. * The default passing mode is PKCS7 padding.
* *
* \param ctx The generic cipher context. * \param ctx The generic cipher context. This must be initialized and
* bound to a cipher information structure.
* \param mode The padding mode. * \param mode The padding mode.
* *
* \return \c 0 on success. * \return \c 0 on success.
@@ -553,7 +661,8 @@ int mbedtls_cipher_setkey(mbedtls_cipher_context_t *ctx, const unsigned char *ke
* \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode
* does not support padding. * does not support padding.
*/ */
int mbedtls_cipher_set_padding_mode(mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode); int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx,
mbedtls_cipher_padding_t mode );
#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ #endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
/** /**
@@ -563,8 +672,10 @@ int mbedtls_cipher_set_padding_mode(mbedtls_cipher_context_t *ctx, mbedtls_ciphe
* \note Some ciphers do not use IVs nor nonce. For these * \note Some ciphers do not use IVs nor nonce. For these
* ciphers, this function has no effect. * ciphers, this function has no effect.
* *
* \param ctx The generic cipher context. * \param ctx The generic cipher context. This must be initialized and
* \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. * bound to a cipher information structure.
* \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. This
* must be a readable buffer of at least \p iv_len Bytes.
* \param iv_len The IV length for ciphers with variable-size IV. * \param iv_len The IV length for ciphers with variable-size IV.
* This parameter is discarded by ciphers with fixed-size IV. * This parameter is discarded by ciphers with fixed-size IV.
* *
@@ -572,35 +683,38 @@ int mbedtls_cipher_set_padding_mode(mbedtls_cipher_context_t *ctx, mbedtls_ciphe
* \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on
* parameter-verification failure. * parameter-verification failure.
*/ */
int mbedtls_cipher_set_iv(mbedtls_cipher_context_t *ctx, int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx,
const unsigned char *iv, size_t iv_len); const unsigned char *iv,
size_t iv_len );
/** /**
* \brief This function resets the cipher state. * \brief This function resets the cipher state.
* *
* \param ctx The generic cipher context. * \param ctx The generic cipher context. This must be initialized.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on
* parameter-verification failure. * parameter-verification failure.
*/ */
int mbedtls_cipher_reset(mbedtls_cipher_context_t *ctx); int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx );
#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
/** /**
* \brief This function adds additional data for AEAD ciphers. * \brief This function adds additional data for AEAD ciphers.
* Currently supported with GCM and ChaCha20+Poly1305. * Currently supported with GCM and ChaCha20+Poly1305.
* Must be called exactly once, after mbedtls_cipher_reset(). * This must be called exactly once, after
* mbedtls_cipher_reset().
* *
* \param ctx The generic cipher context. * \param ctx The generic cipher context. This must be initialized.
* \param ad The additional data to use. * \param ad The additional data to use. This must be a readable
* \param ad_len the Length of \p ad. * buffer of at least \p ad_len Bytes.
* \param ad_len The length of \p ad in Bytes.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return A specific error code on failure. * \return A specific error code on failure.
*/ */
int mbedtls_cipher_update_ad(mbedtls_cipher_context_t *ctx, int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx,
const unsigned char *ad, size_t ad_len); const unsigned char *ad, size_t ad_len );
#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
/** /**
@@ -618,14 +732,17 @@ int mbedtls_cipher_update_ad(mbedtls_cipher_context_t *ctx,
* mbedtls_cipher_finish(), must have \p ilen as a * mbedtls_cipher_finish(), must have \p ilen as a
* multiple of the block size of the cipher. * multiple of the block size of the cipher.
* *
* \param ctx The generic cipher context. * \param ctx The generic cipher context. This must be initialized and
* \param input The buffer holding the input data. * bound to a key.
* \param input The buffer holding the input data. This must be a
* readable buffer of at least \p ilen Bytes.
* \param ilen The length of the input data. * \param ilen The length of the input data.
* \param output The buffer for the output data. Must be able to hold at * \param output The buffer for the output data. This must be able to
* least \p ilen + block_size. Must not be the same buffer * hold at least `ilen + block_size`. This must not be the
* as input. * same buffer as \p input.
* \param olen The length of the output data, to be updated with the * \param olen The length of the output data, to be updated with the
* actual number of Bytes written. * actual number of Bytes written. This must not be
* \c NULL.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on
@@ -634,8 +751,10 @@ int mbedtls_cipher_update_ad(mbedtls_cipher_context_t *ctx,
* unsupported mode for a cipher. * unsupported mode for a cipher.
* \return A cipher-specific error code on failure. * \return A cipher-specific error code on failure.
*/ */
int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *input, int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx,
size_t ilen, unsigned char *output, size_t *olen); const unsigned char *input,
size_t ilen, unsigned char *output,
size_t *olen );
/** /**
* \brief The generic cipher finalization function. If data still * \brief The generic cipher finalization function. If data still
@@ -643,9 +762,12 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *in
* contained in it is padded to the size of * contained in it is padded to the size of
* the last block, and written to the \p output buffer. * the last block, and written to the \p output buffer.
* *
* \param ctx The generic cipher context. * \param ctx The generic cipher context. This must be initialized and
* \param output The buffer to write data to. Needs block_size available. * bound to a key.
* \param output The buffer to write data to. This needs to be a writable
* buffer of at least \p block_size Bytes.
* \param olen The length of the data written to the \p output buffer. * \param olen The length of the data written to the \p output buffer.
* This may not be \c NULL.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on
@@ -656,57 +778,66 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *in
* while decrypting. * while decrypting.
* \return A cipher-specific error code on failure. * \return A cipher-specific error code on failure.
*/ */
int mbedtls_cipher_finish(mbedtls_cipher_context_t *ctx, int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx,
unsigned char *output, size_t *olen); unsigned char *output, size_t *olen );
#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) #if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C)
/** /**
* \brief This function writes a tag for AEAD ciphers. * \brief This function writes a tag for AEAD ciphers.
* Currently supported with GCM and ChaCha20+Poly1305. * Currently supported with GCM and ChaCha20+Poly1305.
* Must be called after mbedtls_cipher_finish(). * This must be called after mbedtls_cipher_finish().
* *
* \param ctx The generic cipher context. * \param ctx The generic cipher context. This must be initialized,
* \param tag The buffer to write the tag to. * bound to a key, and have just completed a cipher
* operation through mbedtls_cipher_finish() the tag for
* which should be written.
* \param tag The buffer to write the tag to. This must be a writable
* buffer of at least \p tag_len Bytes.
* \param tag_len The length of the tag to write. * \param tag_len The length of the tag to write.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return A specific error code on failure. * \return A specific error code on failure.
*/ */
int mbedtls_cipher_write_tag(mbedtls_cipher_context_t *ctx, int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx,
unsigned char *tag, size_t tag_len); unsigned char *tag, size_t tag_len );
/** /**
* \brief This function checks the tag for AEAD ciphers. * \brief This function checks the tag for AEAD ciphers.
* Currently supported with GCM and ChaCha20+Poly1305. * Currently supported with GCM and ChaCha20+Poly1305.
* Must be called after mbedtls_cipher_finish(). * This must be called after mbedtls_cipher_finish().
* *
* \param ctx The generic cipher context. * \param ctx The generic cipher context. This must be initialized.
* \param tag The buffer holding the tag. * \param tag The buffer holding the tag. This must be a readable
* buffer of at least \p tag_len Bytes.
* \param tag_len The length of the tag to check. * \param tag_len The length of the tag to check.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return A specific error code on failure. * \return A specific error code on failure.
*/ */
int mbedtls_cipher_check_tag(mbedtls_cipher_context_t *ctx, int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx,
const unsigned char *tag, size_t tag_len); const unsigned char *tag, size_t tag_len );
#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ #endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */
/** /**
* \brief The generic all-in-one encryption/decryption function, * \brief The generic all-in-one encryption/decryption function,
* for all ciphers except AEAD constructs. * for all ciphers except AEAD constructs.
* *
* \param ctx The generic cipher context. * \param ctx The generic cipher context. This must be initialized.
* \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers.
* This must be a readable buffer of at least \p iv_len
* Bytes.
* \param iv_len The IV length for ciphers with variable-size IV. * \param iv_len The IV length for ciphers with variable-size IV.
* This parameter is discarded by ciphers with fixed-size * This parameter is discarded by ciphers with fixed-size
* IV. * IV.
* \param input The buffer holding the input data. * \param input The buffer holding the input data. This must be a
* \param ilen The length of the input data. * readable buffer of at least \p ilen Bytes.
* \param output The buffer for the output data. Must be able to hold at * \param ilen The length of the input data in Bytes.
* least \p ilen + block_size. Must not be the same buffer * \param output The buffer for the output data. This must be able to
* as input. * hold at least `ilen + block_size`. This must not be the
* same buffer as \p input.
* \param olen The length of the output data, to be updated with the * \param olen The length of the output data, to be updated with the
* actual number of Bytes written. * actual number of Bytes written. This must not be
* \c NULL.
* *
* \note Some ciphers do not use IVs nor nonce. For these * \note Some ciphers do not use IVs nor nonce. For these
* ciphers, use \p iv = NULL and \p iv_len = 0. * ciphers, use \p iv = NULL and \p iv_len = 0.
@@ -720,63 +851,116 @@ int mbedtls_cipher_check_tag(mbedtls_cipher_context_t *ctx,
* while decrypting. * while decrypting.
* \return A cipher-specific error code on failure. * \return A cipher-specific error code on failure.
*/ */
int mbedtls_cipher_crypt(mbedtls_cipher_context_t *ctx, int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx,
const unsigned char *iv, size_t iv_len, const unsigned char *iv, size_t iv_len,
const unsigned char *input, size_t ilen, const unsigned char *input, size_t ilen,
unsigned char *output, size_t *olen); unsigned char *output, size_t *olen );
#if defined(MBEDTLS_CIPHER_MODE_AEAD) #if defined(MBEDTLS_CIPHER_MODE_AEAD)
#if ! defined(MBEDTLS_DEPRECATED_REMOVED)
#if defined(MBEDTLS_DEPRECATED_WARNING)
#define MBEDTLS_DEPRECATED __attribute__((deprecated))
#else
#define MBEDTLS_DEPRECATED
#endif /* MBEDTLS_DEPRECATED_WARNING */
/** /**
* \brief The generic autenticated encryption (AEAD) function. * \brief The generic authenticated encryption (AEAD) function.
* *
* \param ctx The generic cipher context. * \deprecated Superseded by mbedtls_cipher_auth_encrypt_ext().
* \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. *
* \param iv_len The IV length for ciphers with variable-size IV. * \note This function only supports AEAD algorithms, not key
* This parameter is discarded by ciphers with fixed-size IV. * wrapping algorithms such as NIST_KW; for this, see
* \param ad The additional data to authenticate. * mbedtls_cipher_auth_encrypt_ext().
*
* \param ctx The generic cipher context. This must be initialized and
* bound to a key associated with an AEAD algorithm.
* \param iv The nonce to use. This must be a readable buffer of
* at least \p iv_len Bytes and must not be \c NULL.
* \param iv_len The length of the nonce. This must satisfy the
* constraints imposed by the AEAD cipher used.
* \param ad The additional data to authenticate. This must be a
* readable buffer of at least \p ad_len Bytes, and may
* be \c NULL is \p ad_len is \c 0.
* \param ad_len The length of \p ad. * \param ad_len The length of \p ad.
* \param input The buffer holding the input data. * \param input The buffer holding the input data. This must be a
* readable buffer of at least \p ilen Bytes, and may be
* \c NULL if \p ilen is \c 0.
* \param ilen The length of the input data. * \param ilen The length of the input data.
* \param output The buffer for the output data. * \param output The buffer for the output data. This must be a
* Must be able to hold at least \p ilen. * writable buffer of at least \p ilen Bytes, and must
* \param olen The length of the output data, to be updated with the * not be \c NULL.
* actual number of Bytes written. * \param olen This will be filled with the actual number of Bytes
* \param tag The buffer for the authentication tag. * written to the \p output buffer. This must point to a
* \param tag_len The desired length of the authentication tag. * writable object of type \c size_t.
* \param tag The buffer for the authentication tag. This must be a
* writable buffer of at least \p tag_len Bytes. See note
* below regarding restrictions with PSA-based contexts.
* \param tag_len The desired length of the authentication tag. This
* must match the constraints imposed by the AEAD cipher
* used, and in particular must not be \c 0.
*
* \note If the context is based on PSA (that is, it was set up
* with mbedtls_cipher_setup_psa()), then it is required
* that \c tag == output + ilen. That is, the tag must be
* appended to the ciphertext as recommended by RFC 5116.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on
* parameter-verification failure. * parameter-verification failure.
* \return A cipher-specific error code on failure. * \return A cipher-specific error code on failure.
*/ */
int mbedtls_cipher_auth_encrypt(mbedtls_cipher_context_t *ctx, int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx,
const unsigned char *iv, size_t iv_len, const unsigned char *iv, size_t iv_len,
const unsigned char *ad, size_t ad_len, const unsigned char *ad, size_t ad_len,
const unsigned char *input, size_t ilen, const unsigned char *input, size_t ilen,
unsigned char *output, size_t *olen, unsigned char *output, size_t *olen,
unsigned char *tag, size_t tag_len); unsigned char *tag, size_t tag_len )
MBEDTLS_DEPRECATED;
/** /**
* \brief The generic autenticated decryption (AEAD) function. * \brief The generic authenticated decryption (AEAD) function.
*
* \deprecated Superseded by mbedtls_cipher_auth_decrypt_ext().
*
* \note This function only supports AEAD algorithms, not key
* wrapping algorithms such as NIST_KW; for this, see
* mbedtls_cipher_auth_decrypt_ext().
* *
* \note If the data is not authentic, then the output buffer * \note If the data is not authentic, then the output buffer
* is zeroed out to prevent the unauthentic plaintext being * is zeroed out to prevent the unauthentic plaintext being
* used, making this interface safer. * used, making this interface safer.
* *
* \param ctx The generic cipher context. * \param ctx The generic cipher context. This must be initialized and
* \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. * bound to a key associated with an AEAD algorithm.
* \param iv_len The IV length for ciphers with variable-size IV. * \param iv The nonce to use. This must be a readable buffer of
* This parameter is discarded by ciphers with fixed-size IV. * at least \p iv_len Bytes and must not be \c NULL.
* \param ad The additional data to be authenticated. * \param iv_len The length of the nonce. This must satisfy the
* constraints imposed by the AEAD cipher used.
* \param ad The additional data to authenticate. This must be a
* readable buffer of at least \p ad_len Bytes, and may
* be \c NULL is \p ad_len is \c 0.
* \param ad_len The length of \p ad. * \param ad_len The length of \p ad.
* \param input The buffer holding the input data. * \param input The buffer holding the input data. This must be a
* readable buffer of at least \p ilen Bytes, and may be
* \c NULL if \p ilen is \c 0.
* \param ilen The length of the input data. * \param ilen The length of the input data.
* \param output The buffer for the output data. * \param output The buffer for the output data. This must be a
* Must be able to hold at least \p ilen. * writable buffer of at least \p ilen Bytes, and must
* \param olen The length of the output data, to be updated with the * not be \c NULL.
* actual number of Bytes written. * \param olen This will be filled with the actual number of Bytes
* \param tag The buffer holding the authentication tag. * written to the \p output buffer. This must point to a
* \param tag_len The length of the authentication tag. * writable object of type \c size_t.
* \param tag The buffer for the authentication tag. This must be a
* readable buffer of at least \p tag_len Bytes. See note
* below regarding restrictions with PSA-based contexts.
* \param tag_len The length of the authentication tag. This must match
* the constraints imposed by the AEAD cipher used, and in
* particular must not be \c 0.
*
* \note If the context is based on PSA (that is, it was set up
* with mbedtls_cipher_setup_psa()), then it is required
* that \c tag == input + len. That is, the tag must be
* appended to the ciphertext as recommended by RFC 5116.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on
@@ -784,14 +968,125 @@ int mbedtls_cipher_auth_encrypt(mbedtls_cipher_context_t *ctx,
* \return #MBEDTLS_ERR_CIPHER_AUTH_FAILED if data is not authentic. * \return #MBEDTLS_ERR_CIPHER_AUTH_FAILED if data is not authentic.
* \return A cipher-specific error code on failure. * \return A cipher-specific error code on failure.
*/ */
int mbedtls_cipher_auth_decrypt(mbedtls_cipher_context_t *ctx, int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx,
const unsigned char *iv, size_t iv_len, const unsigned char *iv, size_t iv_len,
const unsigned char *ad, size_t ad_len, const unsigned char *ad, size_t ad_len,
const unsigned char *input, size_t ilen, const unsigned char *input, size_t ilen,
unsigned char *output, size_t *olen, unsigned char *output, size_t *olen,
const unsigned char *tag, size_t tag_len); const unsigned char *tag, size_t tag_len )
MBEDTLS_DEPRECATED;
#undef MBEDTLS_DEPRECATED
#endif /* MBEDTLS_DEPRECATED_REMOVED */
#endif /* MBEDTLS_CIPHER_MODE_AEAD */ #endif /* MBEDTLS_CIPHER_MODE_AEAD */
#if defined(MBEDTLS_CIPHER_MODE_AEAD) || defined(MBEDTLS_NIST_KW_C)
/**
* \brief The authenticated encryption (AEAD/NIST_KW) function.
*
* \note For AEAD modes, the tag will be appended to the
* ciphertext, as recommended by RFC 5116.
* (NIST_KW doesn't have a separate tag.)
*
* \param ctx The generic cipher context. This must be initialized and
* bound to a key, with an AEAD algorithm or NIST_KW.
* \param iv The nonce to use. This must be a readable buffer of
* at least \p iv_len Bytes and may be \c NULL if \p
* iv_len is \c 0.
* \param iv_len The length of the nonce. For AEAD ciphers, this must
* satisfy the constraints imposed by the cipher used.
* For NIST_KW, this must be \c 0.
* \param ad The additional data to authenticate. This must be a
* readable buffer of at least \p ad_len Bytes, and may
* be \c NULL is \p ad_len is \c 0.
* \param ad_len The length of \p ad. For NIST_KW, this must be \c 0.
* \param input The buffer holding the input data. This must be a
* readable buffer of at least \p ilen Bytes, and may be
* \c NULL if \p ilen is \c 0.
* \param ilen The length of the input data.
* \param output The buffer for the output data. This must be a
* writable buffer of at least \p output_len Bytes, and
* must not be \c NULL.
* \param output_len The length of the \p output buffer in Bytes. For AEAD
* ciphers, this must be at least \p ilen + \p tag_len.
* For NIST_KW, this must be at least \p ilen + 8
* (rounded up to a multiple of 8 if KWP is used);
* \p ilen + 15 is always a safe value.
* \param olen This will be filled with the actual number of Bytes
* written to the \p output buffer. This must point to a
* writable object of type \c size_t.
* \param tag_len The desired length of the authentication tag. For AEAD
* ciphers, this must match the constraints imposed by
* the cipher used, and in particular must not be \c 0.
* For NIST_KW, this must be \c 0.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on
* parameter-verification failure.
* \return A cipher-specific error code on failure.
*/
int mbedtls_cipher_auth_encrypt_ext( mbedtls_cipher_context_t *ctx,
const unsigned char *iv, size_t iv_len,
const unsigned char *ad, size_t ad_len,
const unsigned char *input, size_t ilen,
unsigned char *output, size_t output_len,
size_t *olen, size_t tag_len );
/**
* \brief The authenticated encryption (AEAD/NIST_KW) function.
*
* \note If the data is not authentic, then the output buffer
* is zeroed out to prevent the unauthentic plaintext being
* used, making this interface safer.
*
* \note For AEAD modes, the tag must be appended to the
* ciphertext, as recommended by RFC 5116.
* (NIST_KW doesn't have a separate tag.)
*
* \param ctx The generic cipher context. This must be initialized and
* bound to a key, with an AEAD algorithm or NIST_KW.
* \param iv The nonce to use. This must be a readable buffer of
* at least \p iv_len Bytes and may be \c NULL if \p
* iv_len is \c 0.
* \param iv_len The length of the nonce. For AEAD ciphers, this must
* satisfy the constraints imposed by the cipher used.
* For NIST_KW, this must be \c 0.
* \param ad The additional data to authenticate. This must be a
* readable buffer of at least \p ad_len Bytes, and may
* be \c NULL is \p ad_len is \c 0.
* \param ad_len The length of \p ad. For NIST_KW, this must be \c 0.
* \param input The buffer holding the input data. This must be a
* readable buffer of at least \p ilen Bytes, and may be
* \c NULL if \p ilen is \c 0.
* \param ilen The length of the input data. For AEAD ciphers this
* must be at least \p tag_len. For NIST_KW this must be
* at least \c 8.
* \param output The buffer for the output data. This must be a
* writable buffer of at least \p output_len Bytes, and
* may be \c NULL if \p output_len is \c 0.
* \param output_len The length of the \p output buffer in Bytes. For AEAD
* ciphers, this must be at least \p ilen - \p tag_len.
* For NIST_KW, this must be at least \p ilen - 8.
* \param olen This will be filled with the actual number of Bytes
* written to the \p output buffer. This must point to a
* writable object of type \c size_t.
* \param tag_len The actual length of the authentication tag. For AEAD
* ciphers, this must match the constraints imposed by
* the cipher used, and in particular must not be \c 0.
* For NIST_KW, this must be \c 0.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on
* parameter-verification failure.
* \return #MBEDTLS_ERR_CIPHER_AUTH_FAILED if data is not authentic.
* \return A cipher-specific error code on failure.
*/
int mbedtls_cipher_auth_decrypt_ext( mbedtls_cipher_context_t *ctx,
const unsigned char *iv, size_t iv_len,
const unsigned char *ad, size_t ad_len,
const unsigned char *input, size_t ilen,
unsigned char *output, size_t output_len,
size_t *olen, size_t tag_len );
#endif /* MBEDTLS_CIPHER_MODE_AEAD || MBEDTLS_NIST_KW_C */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -6,35 +6,35 @@
* \author Adriaan de Jong <dejong@fox-it.com> * \author Adriaan de Jong <dejong@fox-it.com>
*/ */
/* /*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
#ifndef MBEDTLS_CIPHER_WRAP_H #ifndef MBEDTLS_CIPHER_WRAP_H
#define MBEDTLS_CIPHER_WRAP_H #define MBEDTLS_CIPHER_WRAP_H
#if !defined(MBEDTLS_CONFIG_FILE) #if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h" #include "mbedtls/config.h"
#else #else
#include MBEDTLS_CONFIG_FILE #include MBEDTLS_CONFIG_FILE
#endif #endif
#include "cipher.h" #include "mbedtls/cipher.h"
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#include "psa/crypto.h"
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@@ -43,77 +43,102 @@ extern "C" {
/** /**
* Base cipher information. The non-mode specific functions and values. * Base cipher information. The non-mode specific functions and values.
*/ */
struct mbedtls_cipher_base_t { struct mbedtls_cipher_base_t
{
/** Base Cipher type (e.g. MBEDTLS_CIPHER_ID_AES) */ /** Base Cipher type (e.g. MBEDTLS_CIPHER_ID_AES) */
mbedtls_cipher_id_t cipher; mbedtls_cipher_id_t cipher;
/** Encrypt using ECB */ /** Encrypt using ECB */
int (*ecb_func)(void *ctx, mbedtls_operation_t mode, int (*ecb_func)( void *ctx, mbedtls_operation_t mode,
const unsigned char *input, unsigned char *output); const unsigned char *input, unsigned char *output );
#if defined(MBEDTLS_CIPHER_MODE_CBC) #if defined(MBEDTLS_CIPHER_MODE_CBC)
/** Encrypt using CBC */ /** Encrypt using CBC */
int (*cbc_func)(void *ctx, mbedtls_operation_t mode, size_t length, int (*cbc_func)( void *ctx, mbedtls_operation_t mode, size_t length,
unsigned char *iv, const unsigned char *input, unsigned char *iv, const unsigned char *input,
unsigned char *output); unsigned char *output );
#endif #endif
#if defined(MBEDTLS_CIPHER_MODE_CFB) #if defined(MBEDTLS_CIPHER_MODE_CFB)
/** Encrypt using CFB (Full length) */ /** Encrypt using CFB (Full length) */
int (*cfb_func)(void *ctx, mbedtls_operation_t mode, size_t length, size_t *iv_off, 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 *iv, const unsigned char *input,
unsigned char *output); unsigned char *output );
#endif #endif
#if defined(MBEDTLS_CIPHER_MODE_OFB) #if defined(MBEDTLS_CIPHER_MODE_OFB)
/** Encrypt using OFB (Full length) */ /** Encrypt using OFB (Full length) */
int (*ofb_func)(void *ctx, size_t length, size_t *iv_off, int (*ofb_func)( void *ctx, size_t length, size_t *iv_off,
unsigned char *iv, unsigned char *iv,
const unsigned char *input, const unsigned char *input,
unsigned char *output); unsigned char *output );
#endif #endif
#if defined(MBEDTLS_CIPHER_MODE_CTR) #if defined(MBEDTLS_CIPHER_MODE_CTR)
/** Encrypt using CTR */ /** Encrypt using CTR */
int (*ctr_func)(void *ctx, size_t length, size_t *nc_off, int (*ctr_func)( void *ctx, size_t length, size_t *nc_off,
unsigned char *nonce_counter, unsigned char *stream_block, unsigned char *nonce_counter, unsigned char *stream_block,
const unsigned char *input, unsigned char *output); const unsigned char *input, unsigned char *output );
#endif #endif
#if defined(MBEDTLS_CIPHER_MODE_XTS) #if defined(MBEDTLS_CIPHER_MODE_XTS)
/** Encrypt or decrypt using XTS. */ /** Encrypt or decrypt using XTS. */
int (*xts_func)(void *ctx, mbedtls_operation_t mode, size_t length, int (*xts_func)( void *ctx, mbedtls_operation_t mode, size_t length,
const unsigned char data_unit[16], const unsigned char data_unit[16],
const unsigned char *input, unsigned char *output); const unsigned char *input, unsigned char *output );
#endif #endif
#if defined(MBEDTLS_CIPHER_MODE_STREAM) #if defined(MBEDTLS_CIPHER_MODE_STREAM)
/** Encrypt using STREAM */ /** Encrypt using STREAM */
int (*stream_func)(void *ctx, size_t length, int (*stream_func)( void *ctx, size_t length,
const unsigned char *input, unsigned char *output); const unsigned char *input, unsigned char *output );
#endif #endif
/** Set key for encryption purposes */ /** Set key for encryption purposes */
int (*setkey_enc_func)(void *ctx, const unsigned char *key, int (*setkey_enc_func)( void *ctx, const unsigned char *key,
unsigned int key_bitlen); unsigned int key_bitlen );
/** Set key for decryption purposes */ /** Set key for decryption purposes */
int (*setkey_dec_func)(void *ctx, const unsigned char *key, int (*setkey_dec_func)( void *ctx, const unsigned char *key,
unsigned int key_bitlen); unsigned int key_bitlen);
/** Allocate a new context */ /** Allocate a new context */
void *(*ctx_alloc_func)(void); void * (*ctx_alloc_func)( void );
/** Free the given context */ /** Free the given context */
void (*ctx_free_func)(void *ctx); void (*ctx_free_func)( void *ctx );
}; };
typedef struct { typedef struct
{
mbedtls_cipher_type_t type; mbedtls_cipher_type_t type;
const mbedtls_cipher_info_t *info; const mbedtls_cipher_info_t *info;
} mbedtls_cipher_definition_t; } 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;
psa_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 const mbedtls_cipher_definition_t mbedtls_cipher_definitions[];
extern int mbedtls_cipher_supported[]; extern int mbedtls_cipher_supported[];

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -7,35 +7,38 @@
* Authentication is defined in <em>RFC-4493: The AES-CMAC Algorithm</em>. * Authentication is defined in <em>RFC-4493: The AES-CMAC Algorithm</em>.
*/ */
/* /*
* Copyright (C) 2015-2018, Arm Limited (or its affiliates), All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of Mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
#ifndef MBEDTLS_CMAC_H #ifndef MBEDTLS_CMAC_H
#define MBEDTLS_CMAC_H #define MBEDTLS_CMAC_H
#include "cipher.h" #if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include "mbedtls/cipher.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/* MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED -0x007A /**< CMAC hardware accelerator failed. */ #define MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED -0x007A /**< CMAC hardware accelerator failed. */
#define MBEDTLS_AES_BLOCK_SIZE 16 #define MBEDTLS_AES_BLOCK_SIZE 16
@@ -52,7 +55,8 @@ extern "C" {
/** /**
* The CMAC context structure. * The CMAC context structure.
*/ */
struct mbedtls_cmac_context_t { struct mbedtls_cmac_context_t
{
/** The internal state of the CMAC algorithm. */ /** The internal state of the CMAC algorithm. */
unsigned char state[MBEDTLS_CIPHER_BLKSIZE_MAX]; unsigned char state[MBEDTLS_CIPHER_BLKSIZE_MAX];
@@ -84,8 +88,8 @@ struct mbedtls_cmac_context_t {
* \return \c 0 on success. * \return \c 0 on success.
* \return A cipher-specific error code on failure. * \return A cipher-specific error code on failure.
*/ */
int mbedtls_cipher_cmac_starts(mbedtls_cipher_context_t *ctx, int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx,
const unsigned char *key, size_t keybits); const unsigned char *key, size_t keybits );
/** /**
* \brief This function feeds an input buffer into an ongoing CMAC * \brief This function feeds an input buffer into an ongoing CMAC
@@ -103,8 +107,8 @@ int mbedtls_cipher_cmac_starts(mbedtls_cipher_context_t *ctx,
* \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA
* if parameter verification fails. * if parameter verification fails.
*/ */
int mbedtls_cipher_cmac_update(mbedtls_cipher_context_t *ctx, int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx,
const unsigned char *input, size_t ilen); const unsigned char *input, size_t ilen );
/** /**
* \brief This function finishes the CMAC operation, and writes * \brief This function finishes the CMAC operation, and writes
@@ -121,8 +125,8 @@ int mbedtls_cipher_cmac_update(mbedtls_cipher_context_t *ctx,
* \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA
* if parameter verification fails. * if parameter verification fails.
*/ */
int mbedtls_cipher_cmac_finish(mbedtls_cipher_context_t *ctx, int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx,
unsigned char *output); unsigned char *output );
/** /**
* \brief This function prepares the authentication of another * \brief This function prepares the authentication of another
@@ -138,7 +142,7 @@ int mbedtls_cipher_cmac_finish(mbedtls_cipher_context_t *ctx,
* \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA
* if parameter verification fails. * if parameter verification fails.
*/ */
int mbedtls_cipher_cmac_reset(mbedtls_cipher_context_t *ctx); int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx );
/** /**
* \brief This function calculates the full generic CMAC * \brief This function calculates the full generic CMAC
@@ -162,10 +166,10 @@ int mbedtls_cipher_cmac_reset(mbedtls_cipher_context_t *ctx);
* \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA
* if parameter verification fails. * if parameter verification fails.
*/ */
int mbedtls_cipher_cmac(const mbedtls_cipher_info_t *cipher_info, int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info,
const unsigned char *key, size_t keylen, const unsigned char *key, size_t keylen,
const unsigned char *input, size_t ilen, const unsigned char *input, size_t ilen,
unsigned char *output); unsigned char *output );
#if defined(MBEDTLS_AES_C) #if defined(MBEDTLS_AES_C)
/** /**
@@ -185,9 +189,9 @@ int mbedtls_cipher_cmac(const mbedtls_cipher_info_t *cipher_info,
* *
* \return \c 0 on success. * \return \c 0 on success.
*/ */
int mbedtls_aes_cmac_prf_128(const unsigned char *key, size_t key_len, int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_len,
const unsigned char *input, size_t in_len, const unsigned char *input, size_t in_len,
unsigned char *output); unsigned char output[16] );
#endif /* MBEDTLS_AES_C */ #endif /* MBEDTLS_AES_C */
#if defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) ) #if defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) )
@@ -197,7 +201,7 @@ int mbedtls_aes_cmac_prf_128(const unsigned char *key, size_t key_len,
* \return \c 0 on success. * \return \c 0 on success.
* \return \c 1 on failure. * \return \c 1 on failure.
*/ */
int mbedtls_cmac_self_test(int verbose); int mbedtls_cmac_self_test( int verbose );
#endif /* MBEDTLS_SELF_TEST && ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ #endif /* MBEDTLS_SELF_TEST && ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */
#ifdef __cplusplus #ifdef __cplusplus

53
common/mbedtls/common.h Normal file
View File

@@ -0,0 +1,53 @@
/**
* \file common.h
*
* \brief Utility macros for internal use in the library
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBEDTLS_LIBRARY_COMMON_H
#define MBEDTLS_LIBRARY_COMMON_H
#if defined(MBEDTLS_CONFIG_FILE)
#include MBEDTLS_CONFIG_FILE
#else
#include "mbedtls/config.h"
#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
#endif /* MBEDTLS_LIBRARY_COMMON_H */

2529
common/mbedtls/compat-1.3.h Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

544
common/mbedtls/config_psa.h Normal file
View File

@@ -0,0 +1,544 @@
/**
* \file mbedtls/config_psa.h
* \brief PSA crypto configuration options (set of defines)
*
* This set of compile-time options takes settings defined in
* include/mbedtls/config.h and include/psa/crypto_config.h and uses
* those definitions to define symbols used in the library code.
*
* Users and integrators should not edit this file, please edit
* include/mbedtls/config.h for MBETLS_XXX settings or
* include/psa/crypto_config.h for PSA_WANT_XXX settings.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBEDTLS_CONFIG_PSA_H
#define MBEDTLS_CONFIG_PSA_H
#if defined(MBEDTLS_PSA_CRYPTO_CONFIG)
#include "psa/crypto_config.h"
#endif /* defined(MBEDTLS_PSA_CRYPTO_CONFIG) */
#ifdef __cplusplus
extern "C" {
#endif
#if defined(MBEDTLS_PSA_CRYPTO_CONFIG)
#if defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA)
#if !defined(MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA)
#define MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA 1
#define MBEDTLS_ECDSA_DETERMINISTIC
#define MBEDTLS_ECDSA_C
#define MBEDTLS_HMAC_DRBG_C
#define MBEDTLS_MD_C
#endif /* !MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA */
#endif /* PSA_WANT_ALG_DETERMINISTIC_ECDSA */
#if defined(PSA_WANT_ALG_ECDH)
#if !defined(MBEDTLS_PSA_ACCEL_ALG_ECDH)
#define MBEDTLS_PSA_BUILTIN_ALG_ECDH 1
#define MBEDTLS_ECDH_C
#define MBEDTLS_ECP_C
#define MBEDTLS_BIGNUM_C
#endif /* !MBEDTLS_PSA_ACCEL_ALG_ECDH */
#endif /* PSA_WANT_ALG_ECDH */
#if defined(PSA_WANT_ALG_ECDSA)
#if !defined(MBEDTLS_PSA_ACCEL_ALG_ECDSA)
#define MBEDTLS_PSA_BUILTIN_ALG_ECDSA 1
#define MBEDTLS_ECDSA_C
#endif /* !MBEDTLS_PSA_ACCEL_ALG_ECDSA */
#endif /* PSA_WANT_ALG_ECDSA */
#if defined(PSA_WANT_ALG_HKDF)
#if !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF)
#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1
#define MBEDTLS_PSA_BUILTIN_ALG_HKDF 1
#endif /* !MBEDTLS_PSA_ACCEL_ALG_HKDF */
#endif /* PSA_WANT_ALG_HKDF */
#if defined(PSA_WANT_ALG_HMAC)
#if !defined(MBEDTLS_PSA_ACCEL_ALG_HMAC)
#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1
#endif /* !MBEDTLS_PSA_ACCEL_ALG_HMAC */
#endif /* PSA_WANT_ALG_HMAC */
#if defined(PSA_WANT_ALG_MD2) && !defined(MBEDTLS_PSA_ACCEL_ALG_MD2)
#define MBEDTLS_PSA_BUILTIN_ALG_MD2 1
#define MBEDTLS_MD2_C
#endif
#if defined(PSA_WANT_ALG_MD4) && !defined(MBEDTLS_PSA_ACCEL_ALG_MD4)
#define MBEDTLS_PSA_BUILTIN_ALG_MD4 1
#define MBEDTLS_MD4_C
#endif
#if defined(PSA_WANT_ALG_MD5) && !defined(MBEDTLS_PSA_ACCEL_ALG_MD5)
#define MBEDTLS_PSA_BUILTIN_ALG_MD5 1
#define MBEDTLS_MD5_C
#endif
#if defined(PSA_WANT_ALG_RIPEMD160) && !defined(MBEDTLS_PSA_ACCEL_ALG_RIPEMD160)
#define MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160 1
#define MBEDTLS_RIPEMD160_C
#endif
#if defined(PSA_WANT_ALG_RSA_OAEP)
#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_OAEP)
#define MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP 1
#define MBEDTLS_RSA_C
#define MBEDTLS_BIGNUM_C
#define MBEDTLS_OID_C
#define MBEDTLS_PKCS1_V21
#define MBEDTLS_MD_C
#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_OAEP */
#endif /* PSA_WANT_ALG_RSA_OAEP */
#if defined(PSA_WANT_ALG_RSA_PKCS1V15_CRYPT)
#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_CRYPT)
#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT 1
#define MBEDTLS_RSA_C
#define MBEDTLS_BIGNUM_C
#define MBEDTLS_OID_C
#define MBEDTLS_PKCS1_V15
#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_CRYPT */
#endif /* PSA_WANT_ALG_RSA_PKCS1V15_CRYPT */
#if defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN)
#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN)
#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN 1
#define MBEDTLS_RSA_C
#define MBEDTLS_BIGNUM_C
#define MBEDTLS_OID_C
#define MBEDTLS_PKCS1_V15
#define MBEDTLS_MD_C
#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN */
#endif /* PSA_WANT_ALG_RSA_PKCS1V15_SIGN */
#if defined(PSA_WANT_ALG_RSA_PSS)
#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PSS)
#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS 1
#define MBEDTLS_RSA_C
#define MBEDTLS_BIGNUM_C
#define MBEDTLS_OID_C
#define MBEDTLS_PKCS1_V21
#define MBEDTLS_MD_C
#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PSS */
#endif /* PSA_WANT_ALG_RSA_PSS */
#if defined(PSA_WANT_ALG_SHA_1) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_1)
#define MBEDTLS_PSA_BUILTIN_ALG_SHA_1 1
#define MBEDTLS_SHA1_C
#endif
#if defined(PSA_WANT_ALG_SHA_224) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224)
#define MBEDTLS_PSA_BUILTIN_ALG_SHA_224 1
#define MBEDTLS_SHA256_C
#endif
#if defined(PSA_WANT_ALG_SHA_256) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256)
#define MBEDTLS_PSA_BUILTIN_ALG_SHA_256 1
#define MBEDTLS_SHA256_C
#endif
#if defined(PSA_WANT_ALG_SHA_384) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384)
#define MBEDTLS_PSA_BUILTIN_ALG_SHA_384 1
#define MBEDTLS_SHA512_C
#endif
#if defined(PSA_WANT_ALG_SHA_512) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512)
#define MBEDTLS_PSA_BUILTIN_ALG_SHA_512 1
#define MBEDTLS_SHA512_C
#endif
#if defined(PSA_WANT_ALG_TLS12_PRF)
#if !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PRF)
#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF 1
#endif /* !MBEDTLS_PSA_ACCEL_ALG_TLS12_PRF */
#endif /* PSA_WANT_ALG_TLS12_PRF */
#if defined(PSA_WANT_ALG_TLS12_PSK_TO_MS)
#if !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PSK_TO_MS)
#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS 1
#endif /* !MBEDTLS_PSA_ACCEL_ALG_TLS12_PSK_TO_MS */
#endif /* PSA_WANT_ALG_TLS12_PSK_TO_MS */
#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR)
#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR)
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR 1
#define MBEDTLS_ECP_C
#define MBEDTLS_BIGNUM_C
#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR */
#endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR */
#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY)
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY 1
#define MBEDTLS_ECP_C
#define MBEDTLS_BIGNUM_C
#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY */
#endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */
#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)
#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR)
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR 1
#define MBEDTLS_RSA_C
#define MBEDTLS_BIGNUM_C
#define MBEDTLS_OID_C
#define MBEDTLS_GENPRIME
#define MBEDTLS_PK_PARSE_C
#define MBEDTLS_PK_WRITE_C
#define MBEDTLS_PK_C
#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR */
#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR */
#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY)
#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY)
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY 1
#define MBEDTLS_RSA_C
#define MBEDTLS_BIGNUM_C
#define MBEDTLS_OID_C
#define MBEDTLS_PK_PARSE_C
#define MBEDTLS_PK_WRITE_C
#define MBEDTLS_PK_C
#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY */
#endif /* PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY */
/* If any of the block modes are requested that don't have an
* associated HW assist, define PSA_HAVE_SOFT_BLOCK_MODE for checking
* in the block cipher key types. */
#if (defined(PSA_WANT_ALG_CTR) && !defined(MBEDTLS_PSA_ACCEL_ALG_CTR)) || \
(defined(PSA_WANT_ALG_CFB) && !defined(MBEDTLS_PSA_ACCEL_ALG_CFB)) || \
(defined(PSA_WANT_ALG_OFB) && !defined(MBEDTLS_PSA_ACCEL_ALG_OFB)) || \
(defined(PSA_WANT_ALG_XTS) && !defined(MBEDTLS_PSA_ACCEL_ALG_XTS)) || \
defined(PSA_WANT_ALG_ECB_NO_PADDING) || \
(defined(PSA_WANT_ALG_CBC_NO_PADDING) && \
!defined(MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING)) || \
(defined(PSA_WANT_ALG_CBC_PKCS7) && \
!defined(MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7))
#define PSA_HAVE_SOFT_BLOCK_MODE 1
#endif
#if defined(PSA_WANT_KEY_TYPE_AES)
#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_AES)
#define PSA_HAVE_SOFT_KEY_TYPE_AES 1
#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_AES */
#if defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \
defined(PSA_HAVE_SOFT_BLOCK_MODE)
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES 1
#define MBEDTLS_AES_C
#endif /* PSA_HAVE_SOFT_KEY_TYPE_AES || PSA_HAVE_SOFT_BLOCK_MODE */
#endif /* PSA_WANT_KEY_TYPE_AES */
#if defined(PSA_WANT_KEY_TYPE_ARC4)
#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ARC4)
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARC4 1
#define MBEDTLS_ARC4_C
#endif /*!MBEDTLS_PSA_ACCEL_KEY_TYPE_ARC4 */
#endif /* PSA_WANT_KEY_TYPE_ARC4 */
#if defined(PSA_WANT_KEY_TYPE_CAMELLIA)
#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA)
#define PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA 1
#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA */
#if defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA) || \
defined(PSA_HAVE_SOFT_BLOCK_MODE)
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA 1
#define MBEDTLS_CAMELLIA_C
#endif /* PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA || PSA_HAVE_SOFT_BLOCK_MODE */
#endif /* PSA_WANT_KEY_TYPE_CAMELLIA */
#if defined(PSA_WANT_KEY_TYPE_DES)
#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DES)
#define PSA_HAVE_SOFT_KEY_TYPE_DES 1
#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DES */
#if defined(PSA_HAVE_SOFT_KEY_TYPE_DES) || \
defined(PSA_HAVE_SOFT_BLOCK_MODE)
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES 1
#define MBEDTLS_DES_C
#endif /*PSA_HAVE_SOFT_KEY_TYPE_DES || PSA_HAVE_SOFT_BLOCK_MODE */
#endif /* PSA_WANT_KEY_TYPE_DES */
#if defined(PSA_WANT_KEY_TYPE_CHACHA20)
#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_CHACHA20)
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20 1
#define MBEDTLS_CHACHA20_C
#endif /*!MBEDTLS_PSA_ACCEL_KEY_TYPE_CHACHA20 */
#endif /* PSA_WANT_KEY_TYPE_CHACHA20 */
/* If any of the software block ciphers are selected, define
* PSA_HAVE_SOFT_BLOCK_CIPHER, which can be used in any of these
* situations. */
#if defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \
defined(PSA_HAVE_SOFT_KEY_TYPE_DES) || \
defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA)
#define PSA_HAVE_SOFT_BLOCK_CIPHER 1
#endif
#if defined(PSA_WANT_ALG_STREAM_CIPHER)
#define MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER 1
#endif /* PSA_WANT_ALG_STREAM_CIPHER */
#if defined(PSA_WANT_ALG_CTR)
#if !defined(MBEDTLS_PSA_ACCEL_ALG_CTR) || \
defined(PSA_HAVE_SOFT_BLOCK_CIPHER)
#define MBEDTLS_PSA_BUILTIN_ALG_CTR 1
#define MBEDTLS_CIPHER_MODE_CTR
#endif
#endif /* PSA_WANT_ALG_CTR */
#if defined(PSA_WANT_ALG_CFB)
#if !defined(MBEDTLS_PSA_ACCEL_ALG_CFB) || \
defined(PSA_HAVE_SOFT_BLOCK_CIPHER)
#define MBEDTLS_PSA_BUILTIN_ALG_CFB 1
#define MBEDTLS_CIPHER_MODE_CFB
#endif
#endif /* PSA_WANT_ALG_CFB */
#if defined(PSA_WANT_ALG_OFB)
#if !defined(MBEDTLS_PSA_ACCEL_ALG_OFB) || \
defined(PSA_HAVE_SOFT_BLOCK_CIPHER)
#define MBEDTLS_PSA_BUILTIN_ALG_OFB 1
#define MBEDTLS_CIPHER_MODE_OFB
#endif
#endif /* PSA_WANT_ALG_OFB */
#if defined(PSA_WANT_ALG_XTS)
#if !defined(MBEDTLS_PSA_ACCEL_ALG_XTS) || \
defined(PSA_HAVE_SOFT_BLOCK_CIPHER)
#define MBEDTLS_PSA_BUILTIN_ALG_XTS 1
#define MBEDTLS_CIPHER_MODE_XTS
#endif
#endif /* PSA_WANT_ALG_XTS */
#if defined(PSA_WANT_ALG_ECB_NO_PADDING)
#define MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING 1
#endif
#if defined(PSA_WANT_ALG_CBC_NO_PADDING)
#if !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING) || \
defined(PSA_HAVE_SOFT_BLOCK_CIPHER)
#define MBEDTLS_CIPHER_MODE_CBC
#define MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING 1
#endif
#endif /* PSA_WANT_ALG_CBC_NO_PADDING */
#if defined(PSA_WANT_ALG_CBC_PKCS7)
#if !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7) || \
defined(PSA_HAVE_SOFT_BLOCK_CIPHER)
#define MBEDTLS_CIPHER_MODE_CBC
#define MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 1
#define MBEDTLS_CIPHER_PADDING_PKCS7
#endif
#endif /* PSA_WANT_ALG_CBC_PKCS7 */
#if defined(PSA_WANT_ALG_CHACHA20_POLY1305)
#if defined(PSA_WANT_KEY_TYPE_CHACHA20)
#define MBEDTLS_CHACHAPOLY_C
#define MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 1
#endif /* PSA_WANT_KEY_TYPE_CHACHA20 */
#endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */
#else /* MBEDTLS_PSA_CRYPTO_CONFIG */
/*
* Ensure PSA_WANT_* defines are setup properly if MBEDTLS_PSA_CRYPTO_CONFIG
* is not defined
*/
#if defined(MBEDTLS_ECDH_C)
#define MBEDTLS_PSA_BUILTIN_ALG_ECDH 1
#define PSA_WANT_ALG_ECDH 1
#endif /* MBEDTLS_ECDH_C */
#if defined(MBEDTLS_ECDSA_C)
#define MBEDTLS_PSA_BUILTIN_ALG_ECDSA 1
#define PSA_WANT_ALG_ECDSA 1
// Only add in DETERMINISTIC support if ECDSA is also enabled
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
#define MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA 1
#define PSA_WANT_ALG_DETERMINISTIC_ECDSA 1
#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
#endif /* MBEDTLS_ECDSA_C */
#if defined(MBEDTLS_ECP_C)
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR 1
#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR 1
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY 1
#define PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY 1
#endif /* MBEDTLS_ECP_C */
#if defined(MBEDTLS_HKDF_C)
#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1
#define PSA_WANT_ALG_HMAC 1
#define MBEDTLS_PSA_BUILTIN_ALG_HKDF 1
#define PSA_WANT_ALG_HKDF 1
#endif /* MBEDTLS_HKDF_C */
#if defined(MBEDTLS_MD_C)
#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1
#define PSA_WANT_ALG_HMAC 1
#define PSA_WANT_KEY_TYPE_HMAC
#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF 1
#define PSA_WANT_ALG_TLS12_PRF 1
#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS 1
#define PSA_WANT_ALG_TLS12_PSK_TO_MS 1
#endif /* MBEDTLS_MD_C */
#if defined(MBEDTLS_MD2_C)
#define MBEDTLS_PSA_BUILTIN_ALG_MD2 1
#define PSA_WANT_ALG_MD2 1
#endif
#if defined(MBEDTLS_MD4_C)
#define MBEDTLS_PSA_BUILTIN_ALG_MD4 1
#define PSA_WANT_ALG_MD4 1
#endif
#if defined(MBEDTLS_MD5_C)
#define MBEDTLS_PSA_BUILTIN_ALG_MD5 1
#define PSA_WANT_ALG_MD5 1
#endif
#if defined(MBEDTLS_RIPEMD160_C)
#define MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160 1
#define PSA_WANT_ALG_RIPEMD160 1
#endif
#if defined(MBEDTLS_RSA_C)
#if defined(MBEDTLS_PKCS1_V15)
#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT 1
#define PSA_WANT_ALG_RSA_PKCS1V15_CRYPT 1
#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN 1
#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN 1
#endif /* MBEDTLSS_PKCS1_V15 */
#if defined(MBEDTLS_PKCS1_V21)
#define MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP 1
#define PSA_WANT_ALG_RSA_OAEP 1
#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS 1
#define PSA_WANT_ALG_RSA_PSS 1
#endif /* MBEDTLS_PKCS1_V21 */
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR 1
#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR 1
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY 1
#define PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY 1
#endif /* MBEDTLS_RSA_C */
#if defined(MBEDTLS_SHA1_C)
#define MBEDTLS_PSA_BUILTIN_ALG_SHA_1 1
#define PSA_WANT_ALG_SHA_1 1
#endif
#if defined(MBEDTLS_SHA256_C)
#define MBEDTLS_PSA_BUILTIN_ALG_SHA_224 1
#define MBEDTLS_PSA_BUILTIN_ALG_SHA_256 1
#define PSA_WANT_ALG_SHA_224 1
#define PSA_WANT_ALG_SHA_256 1
#endif
#if defined(MBEDTLS_SHA512_C)
#if !defined(MBEDTLS_SHA512_NO_SHA384)
#define MBEDTLS_PSA_BUILTIN_ALG_SHA_384 1
#define PSA_WANT_ALG_SHA_384 1
#endif
#define MBEDTLS_PSA_BUILTIN_ALG_SHA_512 1
#define PSA_WANT_ALG_SHA_512 1
#endif
#if defined(MBEDTLS_AES_C)
#define PSA_WANT_KEY_TYPE_AES 1
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES 1
#endif
#if defined(MBEDTLS_ARC4_C)
#define PSA_WANT_KEY_TYPE_ARC4 1
#define PSA_WANT_ALG_STREAM_CIPHER 1
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARC4 1
#define MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER 1
#endif
#if defined(MBEDTLS_CAMELLIA_C)
#define PSA_WANT_KEY_TYPE_CAMELLIA 1
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA 1
#endif
#if defined(MBEDTLS_DES_C)
#define PSA_WANT_KEY_TYPE_DES 1
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES 1
#endif
#if defined(MBEDTLS_CHACHA20_C)
#define PSA_WANT_KEY_TYPE_CHACHA20 1
#define PSA_WANT_ALG_STREAM_CIPHER 1
#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20 1
#define MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER 1
#if defined(MBEDTLS_CHACHAPOLY_C)
#define PSA_WANT_ALG_CHACHA20_POLY1305 1
#define MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 1
#endif
#endif
#if defined(MBEDTLS_CIPHER_MODE_CBC)
#define MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING 1
#define PSA_WANT_ALG_CBC_NO_PADDING 1
#if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
#define MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 1
#define PSA_WANT_ALG_CBC_PKCS7 1
#endif
#endif
#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) || \
defined(MBEDTLS_CAMELLIA_C)
#define MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING 1
#define PSA_WANT_ALG_ECB_NO_PADDING 1
#endif
#if defined(MBEDTLS_CIPHER_MODE_CFB)
#define MBEDTLS_PSA_BUILTIN_ALG_CFB 1
#define PSA_WANT_ALG_CFB 1
#endif
#if defined(MBEDTLS_CIPHER_MODE_CTR)
#define MBEDTLS_PSA_BUILTIN_ALG_CTR 1
#define PSA_WANT_ALG_CTR 1
#endif
#if defined(MBEDTLS_CIPHER_MODE_OFB)
#define MBEDTLS_PSA_BUILTIN_ALG_OFB 1
#define PSA_WANT_ALG_OFB 1
#endif
#if defined(MBEDTLS_CIPHER_MODE_XTS)
#define MBEDTLS_PSA_BUILTIN_ALG_XTS 1
#define PSA_WANT_ALG_XTS 1
#endif
#endif /* MBEDTLS_PSA_CRYPTO_CONFIG */
/* These features are always enabled. */
#define PSA_WANT_KEY_TYPE_DERIVE 1
#define PSA_WANT_KEY_TYPE_RAW_DATA 1
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_CONFIG_PSA_H */

File diff suppressed because it is too large Load Diff

View File

@@ -1,44 +1,56 @@
/** /**
* \file ctr_drbg.h * \file ctr_drbg.h
* *
* \brief This file contains CTR_DRBG definitions and functions. * \brief This file contains definitions and functions for the
* CTR_DRBG pseudorandom generator.
* *
* CTR_DRBG is a standardized way of building a PRNG from a block-cipher * CTR_DRBG is a standardized way of building a PRNG from a block-cipher
* in counter mode operation, as defined in <em>NIST SP 800-90A: * in counter mode operation, as defined in <em>NIST SP 800-90A:
* Recommendation for Random Number Generation Using Deterministic Random * Recommendation for Random Number Generation Using Deterministic Random
* Bit Generators</em>. * Bit Generators</em>.
* *
* The Mbed TLS implementation of CTR_DRBG uses AES-256 as the underlying * The Mbed TLS implementation of CTR_DRBG uses AES-256 (default) or AES-128
* block cipher. * (if \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled at compile time)
* as the underlying block cipher, with a derivation function.
*
* The security strength as defined in NIST SP 800-90A is
* 128 bits when AES-128 is used (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY enabled)
* and 256 bits otherwise, provided that #MBEDTLS_CTR_DRBG_ENTROPY_LEN is
* kept at its default value (and not overridden in config.h) and that the
* DRBG instance is set up with default parameters.
* See the documentation of mbedtls_ctr_drbg_seed() for more
* information.
*/ */
/* /*
* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of Mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
#ifndef MBEDTLS_CTR_DRBG_H #ifndef MBEDTLS_CTR_DRBG_H
#define MBEDTLS_CTR_DRBG_H #define MBEDTLS_CTR_DRBG_H
#include "aes.h" #if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include "mbedtls/aes.h"
#if defined(MBEDTLS_THREADING_C) #if defined(MBEDTLS_THREADING_C)
#include "threading.h" #include "mbedtls/threading.h"
#endif #endif
#define MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -0x0034 /**< The entropy source failed. */ #define MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -0x0034 /**< The entropy source failed. */
@@ -47,7 +59,23 @@
#define MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR -0x003A /**< Read or write error in file. */ #define MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR -0x003A /**< Read or write error in file. */
#define MBEDTLS_CTR_DRBG_BLOCKSIZE 16 /**< The block size used by the cipher. */ #define MBEDTLS_CTR_DRBG_BLOCKSIZE 16 /**< The block size used by the cipher. */
#define MBEDTLS_CTR_DRBG_KEYSIZE 32 /**< The key size used by the cipher. */
#if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
#define MBEDTLS_CTR_DRBG_KEYSIZE 16
/**< The key size in bytes used by the cipher.
*
* Compile-time choice: 16 bytes (128 bits)
* because #MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled.
*/
#else
#define MBEDTLS_CTR_DRBG_KEYSIZE 32
/**< The key size in bytes used by the cipher.
*
* Compile-time choice: 32 bytes (256 bits)
* because \c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is disabled.
*/
#endif
#define MBEDTLS_CTR_DRBG_KEYBITS ( MBEDTLS_CTR_DRBG_KEYSIZE * 8 ) /**< The key size for the DRBG operation, in bits. */ #define MBEDTLS_CTR_DRBG_KEYBITS ( MBEDTLS_CTR_DRBG_KEYSIZE * 8 ) /**< The key size for the DRBG operation, in bits. */
#define MBEDTLS_CTR_DRBG_SEEDLEN ( MBEDTLS_CTR_DRBG_KEYSIZE + MBEDTLS_CTR_DRBG_BLOCKSIZE ) /**< The seed length, calculated as (counter + AES key). */ #define MBEDTLS_CTR_DRBG_SEEDLEN ( MBEDTLS_CTR_DRBG_KEYSIZE + MBEDTLS_CTR_DRBG_BLOCKSIZE ) /**< The seed length, calculated as (counter + AES key). */
@@ -60,21 +88,31 @@
* \{ * \{
*/ */
/** \def MBEDTLS_CTR_DRBG_ENTROPY_LEN
*
* \brief The amount of entropy used per seed by default, in bytes.
*/
#if !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) #if !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN)
#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) #if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256)
/** This is 48 bytes because the entropy module uses SHA-512
* (\c MBEDTLS_ENTROPY_FORCE_SHA256 is disabled).
*/
#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 #define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48
/**< The amount of entropy used per seed by default:
* <ul><li>48 with SHA-512.</li> #else /* defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) */
* <li>32 with SHA-256.</li></ul>
/** This is 32 bytes because the entropy module uses SHA-256
* (the SHA512 module is disabled or
* \c MBEDTLS_ENTROPY_FORCE_SHA256 is enabled).
*/ */
#else #if !defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
/** \warning To achieve a 256-bit security strength, you must pass a nonce
* to mbedtls_ctr_drbg_seed().
*/
#endif /* !defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) */
#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 32 #define MBEDTLS_CTR_DRBG_ENTROPY_LEN 32
/**< Amount of entropy used per seed by default: #endif /* defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) */
* <ul><li>48 with SHA-512.</li> #endif /* !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) */
* <li>32 with SHA-256.</li></ul>
*/
#endif
#endif
#if !defined(MBEDTLS_CTR_DRBG_RESEED_INTERVAL) #if !defined(MBEDTLS_CTR_DRBG_RESEED_INTERVAL)
#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 #define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000
@@ -93,7 +131,7 @@
#if !defined(MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) #if !defined(MBEDTLS_CTR_DRBG_MAX_SEED_INPUT)
#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 #define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384
/**< The maximum size of seed or reseed buffer. */ /**< The maximum size of seed or reseed buffer in bytes. */
#endif #endif
/* \} name SECTION: Module settings */ /* \} name SECTION: Module settings */
@@ -107,19 +145,49 @@
extern "C" { extern "C" {
#endif #endif
#if MBEDTLS_CTR_DRBG_ENTROPY_LEN >= MBEDTLS_CTR_DRBG_KEYSIZE * 3 / 2
/** The default length of the nonce read from the entropy source.
*
* This is \c 0 because a single read from the entropy source is sufficient
* to include a nonce.
* See the documentation of mbedtls_ctr_drbg_seed() for more information.
*/
#define MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN 0
#else
/** The default length of the nonce read from the entropy source.
*
* This is half of the default entropy length because a single read from
* the entropy source does not provide enough material to form a nonce.
* See the documentation of mbedtls_ctr_drbg_seed() for more information.
*/
#define MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN ( MBEDTLS_CTR_DRBG_ENTROPY_LEN + 1 ) / 2
#endif
/** /**
* \brief The CTR_DRBG context structure. * \brief The CTR_DRBG context structure.
*/ */
typedef struct mbedtls_ctr_drbg_context { typedef struct mbedtls_ctr_drbg_context
{
unsigned char counter[16]; /*!< The counter (V). */ unsigned char counter[16]; /*!< The counter (V). */
int reseed_counter; /*!< The reseed counter. */ int reseed_counter; /*!< The reseed counter.
* This is the number of requests that have
* been made since the last (re)seeding,
* minus one.
* Before the initial seeding, this field
* contains the amount of entropy in bytes
* to use as a nonce for the initial seeding,
* or -1 if no nonce length has been explicitly
* set (see mbedtls_ctr_drbg_set_nonce_len()).
*/
int prediction_resistance; /*!< This determines whether prediction int prediction_resistance; /*!< This determines whether prediction
resistance is enabled, that is resistance is enabled, that is
whether to systematically reseed before whether to systematically reseed before
each random generation. */ each random generation. */
size_t entropy_len; /*!< The amount of entropy grabbed on each size_t entropy_len; /*!< The amount of entropy grabbed on each
seed or reseed operation. */ seed or reseed operation, in bytes. */
int reseed_interval; /*!< The reseed interval. */ int reseed_interval; /*!< The reseed interval.
* This is the maximum number of requests
* that can be made between reseedings. */
mbedtls_aes_context aes_ctx; /*!< The AES context. */ mbedtls_aes_context aes_ctx; /*!< The AES context. */
@@ -127,11 +195,18 @@ typedef struct mbedtls_ctr_drbg_context {
* Callbacks (Entropy) * Callbacks (Entropy)
*/ */
int (*f_entropy)(void *, unsigned char *, size_t); int (*f_entropy)(void *, unsigned char *, size_t);
/*!< The entropy callback function. */ /*!< The entropy callback function. */
void *p_entropy; /*!< The context for the entropy function. */ void *p_entropy; /*!< The context for the entropy function. */
#if defined(MBEDTLS_THREADING_C) #if defined(MBEDTLS_THREADING_C)
/* Invariant: the mutex is initialized if and only if f_entropy != NULL.
* This means that the mutex is initialized during the initial seeding
* in mbedtls_ctr_drbg_seed() and freed in mbedtls_ctr_drbg_free().
*
* Note that this invariant may change without notice. Do not rely on it
* and do not access the mutex directly in application code.
*/
mbedtls_threading_mutex_t mutex; mbedtls_threading_mutex_t mutex;
#endif #endif
} }
@@ -142,95 +217,330 @@ mbedtls_ctr_drbg_context;
* and prepares it for mbedtls_ctr_drbg_seed() * and prepares it for mbedtls_ctr_drbg_seed()
* or mbedtls_ctr_drbg_free(). * or mbedtls_ctr_drbg_free().
* *
* \note The reseed interval is
* #MBEDTLS_CTR_DRBG_RESEED_INTERVAL by default.
* You can override it by calling
* mbedtls_ctr_drbg_set_reseed_interval().
*
* \param ctx The CTR_DRBG context to initialize. * \param ctx The CTR_DRBG context to initialize.
*/ */
void mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context *ctx); void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx );
/** /**
* \brief This function seeds and sets up the CTR_DRBG * \brief This function seeds and sets up the CTR_DRBG
* entropy source for future reseeds. * entropy source for future reseeds.
* *
* \note Personalization data can be provided in addition to the more generic * A typical choice for the \p f_entropy and \p p_entropy parameters is
* entropy source, to make this instantiation as unique as possible. * to use the entropy module:
* - \p f_entropy is mbedtls_entropy_func();
* - \p p_entropy is an instance of ::mbedtls_entropy_context initialized
* with mbedtls_entropy_init() (which registers the platform's default
* entropy sources).
*
* The entropy length is #MBEDTLS_CTR_DRBG_ENTROPY_LEN by default.
* You can override it by calling mbedtls_ctr_drbg_set_entropy_len().
*
* The entropy nonce length is:
* - \c 0 if the entropy length is at least 3/2 times the entropy length,
* which guarantees that the security strength is the maximum permitted
* by the key size and entropy length according to NIST SP 800-90A §10.2.1;
* - Half the entropy length otherwise.
* You can override it by calling mbedtls_ctr_drbg_set_nonce_len().
* With the default entropy length, the entropy nonce length is
* #MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN.
*
* You can provide a nonce and personalization string in addition to the
* entropy source, to make this instantiation as unique as possible.
* See SP 800-90A §8.6.7 for more details about nonces.
*
* The _seed_material_ value passed to the derivation function in
* the CTR_DRBG Instantiate Process described in NIST SP 800-90A §10.2.1.3.2
* is the concatenation of the following strings:
* - A string obtained by calling \p f_entropy function for the entropy
* length.
*/
#if MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN == 0
/**
* - If mbedtls_ctr_drbg_set_nonce_len() has been called, a string
* obtained by calling \p f_entropy function for the specified length.
*/
#else
/**
* - A string obtained by calling \p f_entropy function for the entropy nonce
* length. If the entropy nonce length is \c 0, this function does not
* make a second call to \p f_entropy.
*/
#endif
#if defined(MBEDTLS_THREADING_C)
/**
* \note When Mbed TLS is built with threading support,
* after this function returns successfully,
* it is safe to call mbedtls_ctr_drbg_random()
* from multiple threads. Other operations, including
* reseeding, are not thread-safe.
*/
#endif /* MBEDTLS_THREADING_C */
/**
* - The \p custom string.
*
* \note To achieve the nominal security strength permitted
* by CTR_DRBG, the entropy length must be:
* - at least 16 bytes for a 128-bit strength
* (maximum achievable strength when using AES-128);
* - at least 32 bytes for a 256-bit strength
* (maximum achievable strength when using AES-256).
*
* In addition, if you do not pass a nonce in \p custom,
* the sum of the entropy length
* and the entropy nonce length must be:
* - at least 24 bytes for a 128-bit strength
* (maximum achievable strength when using AES-128);
* - at least 48 bytes for a 256-bit strength
* (maximum achievable strength when using AES-256).
* *
* \param ctx The CTR_DRBG context to seed. * \param ctx The CTR_DRBG context to seed.
* It must have been initialized with
* mbedtls_ctr_drbg_init().
* After a successful call to mbedtls_ctr_drbg_seed(),
* you may not call mbedtls_ctr_drbg_seed() again on
* the same context unless you call
* mbedtls_ctr_drbg_free() and mbedtls_ctr_drbg_init()
* again first.
* After a failed call to mbedtls_ctr_drbg_seed(),
* you must call mbedtls_ctr_drbg_free().
* \param f_entropy The entropy callback, taking as arguments the * \param f_entropy The entropy callback, taking as arguments the
* \p p_entropy context, the buffer to fill, and the * \p p_entropy context, the buffer to fill, and the
length of the buffer. * length of the buffer.
* \param p_entropy The entropy context. * \p f_entropy is always called with a buffer size
* \param custom Personalization data, that is device-specific * less than or equal to the entropy length.
identifiers. Can be NULL. * \param p_entropy The entropy context to pass to \p f_entropy.
* \param len The length of the personalization data. * \param custom The personalization string.
* This can be \c NULL, in which case the personalization
* string is empty regardless of the value of \p len.
* \param len The length of the personalization string.
* This must be at most
* #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
* - #MBEDTLS_CTR_DRBG_ENTROPY_LEN.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure. * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure.
*/ */
int mbedtls_ctr_drbg_seed(mbedtls_ctr_drbg_context *ctx, int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx,
int (*f_entropy)(void *, unsigned char *, size_t), int (*f_entropy)(void *, unsigned char *, size_t),
void *p_entropy, void *p_entropy,
const unsigned char *custom, const unsigned char *custom,
size_t len); size_t len );
/** /**
* \brief This function clears CTR_CRBG context data. * \brief This function resets CTR_DRBG context to the state immediately
* after initial call of mbedtls_ctr_drbg_init().
* *
* \param ctx The CTR_DRBG context to clear. * \param ctx The CTR_DRBG context to clear.
*/ */
void mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context *ctx); void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx );
/** /**
* \brief This function turns prediction resistance on or off. * \brief This function turns prediction resistance on or off.
* The default value is off. * The default value is off.
* *
* \note If enabled, entropy is gathered at the beginning of * \note If enabled, entropy is gathered at the beginning of
* every call to mbedtls_ctr_drbg_random_with_add(). * every call to mbedtls_ctr_drbg_random_with_add()
* or mbedtls_ctr_drbg_random().
* Only use this if your entropy source has sufficient * Only use this if your entropy source has sufficient
* throughput. * throughput.
* *
* \param ctx The CTR_DRBG context. * \param ctx The CTR_DRBG context.
* \param resistance #MBEDTLS_CTR_DRBG_PR_ON or #MBEDTLS_CTR_DRBG_PR_OFF. * \param resistance #MBEDTLS_CTR_DRBG_PR_ON or #MBEDTLS_CTR_DRBG_PR_OFF.
*/ */
void mbedtls_ctr_drbg_set_prediction_resistance(mbedtls_ctr_drbg_context *ctx, void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx,
int resistance); int resistance );
/** /**
* \brief This function sets the amount of entropy grabbed on each * \brief This function sets the amount of entropy grabbed on each
* seed or reseed. The default value is * seed or reseed.
* #MBEDTLS_CTR_DRBG_ENTROPY_LEN. *
* The default value is #MBEDTLS_CTR_DRBG_ENTROPY_LEN.
*
* \note The security strength of CTR_DRBG is bounded by the
* entropy length. Thus:
* - When using AES-256
* (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is disabled,
* which is the default),
* \p len must be at least 32 (in bytes)
* to achieve a 256-bit strength.
* - When using AES-128
* (\c MBEDTLS_CTR_DRBG_USE_128_BIT_KEY is enabled)
* \p len must be at least 16 (in bytes)
* to achieve a 128-bit strength.
* *
* \param ctx The CTR_DRBG context. * \param ctx The CTR_DRBG context.
* \param len The amount of entropy to grab. * \param len The amount of entropy to grab, in bytes.
* This must be at most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
* and at most the maximum length accepted by the
* entropy function that is set in the context.
*/ */
void mbedtls_ctr_drbg_set_entropy_len(mbedtls_ctr_drbg_context *ctx, void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx,
size_t len); size_t len );
/**
* \brief This function sets the amount of entropy grabbed
* as a nonce for the initial seeding.
*
* Call this function before calling mbedtls_ctr_drbg_seed() to read
* a nonce from the entropy source during the initial seeding.
*
* \param ctx The CTR_DRBG context.
* \param len The amount of entropy to grab for the nonce, in bytes.
* This must be at most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT
* and at most the maximum length accepted by the
* entropy function that is set in the context.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if \p len is
* more than #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT.
* \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED
* if the initial seeding has already taken place.
*/
int mbedtls_ctr_drbg_set_nonce_len( mbedtls_ctr_drbg_context *ctx,
size_t len );
/** /**
* \brief This function sets the reseed interval. * \brief This function sets the reseed interval.
* The default value is #MBEDTLS_CTR_DRBG_RESEED_INTERVAL. *
* The reseed interval is the number of calls to mbedtls_ctr_drbg_random()
* or mbedtls_ctr_drbg_random_with_add() after which the entropy function
* is called again.
*
* The default value is #MBEDTLS_CTR_DRBG_RESEED_INTERVAL.
* *
* \param ctx The CTR_DRBG context. * \param ctx The CTR_DRBG context.
* \param interval The reseed interval. * \param interval The reseed interval.
*/ */
void mbedtls_ctr_drbg_set_reseed_interval(mbedtls_ctr_drbg_context *ctx, void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx,
int interval); int interval );
/** /**
* \brief This function reseeds the CTR_DRBG context, that is * \brief This function reseeds the CTR_DRBG context, that is
* extracts data from the entropy source. * extracts data from the entropy source.
* *
* \note This function is not thread-safe. It is not safe
* to call this function if another thread might be
* concurrently obtaining random numbers from the same
* context or updating or reseeding the same context.
*
* \param ctx The CTR_DRBG context. * \param ctx The CTR_DRBG context.
* \param additional Additional data to add to the state. Can be NULL. * \param additional Additional data to add to the state. Can be \c NULL.
* \param len The length of the additional data. * \param len The length of the additional data.
* This must be less than
* #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - \c entropy_len
* where \c entropy_len is the entropy length
* configured for the context.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure. * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure.
*/ */
int mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context *ctx, int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx,
const unsigned char *additional, size_t len); const unsigned char *additional, size_t len );
/** /**
* \brief This function updates the state of the CTR_DRBG context. * \brief This function updates the state of the CTR_DRBG context.
* *
* \note This function is not thread-safe. It is not safe
* to call this function if another thread might be
* concurrently obtaining random numbers from the same
* context or updating or reseeding the same context.
*
* \param ctx The CTR_DRBG context.
* \param additional The data to update the state with. This must not be
* \c NULL unless \p add_len is \c 0.
* \param add_len Length of \p additional in bytes. This must be at
* most #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if
* \p add_len is more than
* #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT.
* \return An error from the underlying AES cipher on failure.
*/
int mbedtls_ctr_drbg_update_ret( mbedtls_ctr_drbg_context *ctx,
const unsigned char *additional,
size_t add_len );
/**
* \brief This function updates a CTR_DRBG instance with additional
* data and uses it to generate random data.
*
* This function automatically reseeds if the reseed counter is exceeded
* or prediction resistance is enabled.
*
* \note This function is not thread-safe. It is not safe
* to call this function if another thread might be
* concurrently obtaining random numbers from the same
* context or updating or reseeding the same context.
*
* \param p_rng The CTR_DRBG context. This must be a pointer to a
* #mbedtls_ctr_drbg_context structure.
* \param output The buffer to fill.
* \param output_len The length of the buffer in bytes.
* \param additional Additional data to update. Can be \c NULL, in which
* case the additional data is empty regardless of
* the value of \p add_len.
* \param add_len The length of the additional data
* if \p additional is not \c NULL.
* This must be less than #MBEDTLS_CTR_DRBG_MAX_INPUT
* and less than
* #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - \c entropy_len
* where \c entropy_len is the entropy length
* configured for the context.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or
* #MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure.
*/
int mbedtls_ctr_drbg_random_with_add( void *p_rng,
unsigned char *output, size_t output_len,
const unsigned char *additional, size_t add_len );
/**
* \brief This function uses CTR_DRBG to generate random data.
*
* This function automatically reseeds if the reseed counter is exceeded
* or prediction resistance is enabled.
*/
#if defined(MBEDTLS_THREADING_C)
/**
* \note When Mbed TLS is built with threading support,
* it is safe to call mbedtls_ctr_drbg_random()
* from multiple threads. Other operations, including
* reseeding, are not thread-safe.
*/
#endif /* MBEDTLS_THREADING_C */
/**
* \param p_rng The CTR_DRBG context. This must be a pointer to a
* #mbedtls_ctr_drbg_context structure.
* \param output The buffer to fill.
* \param output_len The length of the buffer in bytes.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or
* #MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure.
*/
int mbedtls_ctr_drbg_random( void *p_rng,
unsigned char *output, size_t output_len );
#if ! defined(MBEDTLS_DEPRECATED_REMOVED)
#if defined(MBEDTLS_DEPRECATED_WARNING)
#define MBEDTLS_DEPRECATED __attribute__((deprecated))
#else
#define MBEDTLS_DEPRECATED
#endif
/**
* \brief This function updates the state of the CTR_DRBG context.
*
* \deprecated Superseded by mbedtls_ctr_drbg_update_ret()
* in 2.16.0.
*
* \note If \p add_len is greater than * \note If \p add_len is greater than
* #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT, only the first * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT, only the first
* #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT Bytes are used. * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT Bytes are used.
@@ -239,48 +549,13 @@ int mbedtls_ctr_drbg_reseed(mbedtls_ctr_drbg_context *ctx,
* \param ctx The CTR_DRBG context. * \param ctx The CTR_DRBG context.
* \param additional The data to update the state with. * \param additional The data to update the state with.
* \param add_len Length of \p additional data. * \param add_len Length of \p additional data.
*
*/ */
void mbedtls_ctr_drbg_update(mbedtls_ctr_drbg_context *ctx, MBEDTLS_DEPRECATED void mbedtls_ctr_drbg_update(
const unsigned char *additional, size_t add_len); mbedtls_ctr_drbg_context *ctx,
const unsigned char *additional,
/** size_t add_len );
* \brief This function updates a CTR_DRBG instance with additional #undef MBEDTLS_DEPRECATED
* data and uses it to generate random data. #endif /* !MBEDTLS_DEPRECATED_REMOVED */
*
* \note The function automatically reseeds if the reseed counter is exceeded.
*
* \param p_rng The CTR_DRBG context. This must be a pointer to a
* #mbedtls_ctr_drbg_context structure.
* \param output The buffer to fill.
* \param output_len The length of the buffer.
* \param additional Additional data to update. Can be NULL.
* \param add_len The length of the additional data.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or
* #MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure.
*/
int mbedtls_ctr_drbg_random_with_add(void *p_rng,
unsigned char *output, size_t output_len,
const unsigned char *additional, size_t add_len);
/**
* \brief This function uses CTR_DRBG to generate random data.
*
* \note The function automatically reseeds if the reseed counter is exceeded.
*
* \param p_rng The CTR_DRBG context. This must be a pointer to a
* #mbedtls_ctr_drbg_context structure.
* \param output The buffer to fill.
* \param output_len The length of the buffer.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or
* #MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure.
*/
int mbedtls_ctr_drbg_random(void *p_rng,
unsigned char *output, size_t output_len);
#if defined(MBEDTLS_FS_IO) #if defined(MBEDTLS_FS_IO)
/** /**
@@ -291,10 +566,10 @@ int mbedtls_ctr_drbg_random(void *p_rng,
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error. * \return #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error.
* \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on reseed
* failure. * failure.
*/ */
int mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context *ctx, const char *path); int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path );
/** /**
* \brief This function reads and updates a seed file. The seed * \brief This function reads and updates a seed file. The seed
@@ -305,24 +580,25 @@ int mbedtls_ctr_drbg_write_seed_file(mbedtls_ctr_drbg_context *ctx, const char *
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error. * \return #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error.
* \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on
* #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG on failure. * reseed failure.
* \return #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG if the existing
* seed file is too large.
*/ */
int mbedtls_ctr_drbg_update_seed_file(mbedtls_ctr_drbg_context *ctx, const char *path); int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path );
#endif /* MBEDTLS_FS_IO */ #endif /* MBEDTLS_FS_IO */
#if defined(MBEDTLS_SELF_TEST)
/** /**
* \brief The CTR_DRBG checkup routine. * \brief The CTR_DRBG checkup routine.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return \c 1 on failure. * \return \c 1 on failure.
*/ */
int mbedtls_ctr_drbg_self_test(int verbose); int mbedtls_ctr_drbg_self_test( int verbose );
/* Internal functions (do not call directly) */ #endif /* MBEDTLS_SELF_TEST */
int mbedtls_ctr_drbg_seed_entropy_len(mbedtls_ctr_drbg_context *,
int (*)(void *, unsigned char *, size_t), void *,
const unsigned char *, size_t, size_t);
#ifdef __cplusplus #ifdef __cplusplus
} }

434
common/mbedtls/debug.c Normal file
View File

@@ -0,0 +1,434 @@
/*
* Debugging routines
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "common.h"
#if defined(MBEDTLS_DEBUG_C)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdlib.h>
#define mbedtls_calloc calloc
#define mbedtls_free free
#define mbedtls_time_t time_t
#define mbedtls_snprintf snprintf
#define mbedtls_vsnprintf vsnprintf
#endif
#include "mbedtls/debug.h"
#include "mbedtls/error.h"
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
!defined(inline) && !defined(__cplusplus)
#define inline __inline
#endif
#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;
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 < DEBUG_BUF_SIZE - 1 )
{
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 is 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 );
idx = 0;
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_C)
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_C */
#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];
int j, k, zeros = 1;
size_t i, n, idx = 0;
if( NULL == ssl ||
NULL == ssl->conf ||
NULL == ssl->conf->f_dbg ||
NULL == X ||
level > debug_threshold )
{
return;
}
for( n = X->n - 1; n > 0; n-- )
if( X->p[n] != 0 )
break;
for( j = ( sizeof(mbedtls_mpi_uint) << 3 ) - 1; j >= 0; j-- )
if( ( ( X->p[n] >> j ) & 1 ) != 0 )
break;
mbedtls_snprintf( str + idx, sizeof( str ) - idx, "value of '%s' (%d bits) is:\n",
text, (int) ( ( n * ( sizeof(mbedtls_mpi_uint) << 3 ) ) + j + 1 ) );
debug_send_line( ssl, level, file, line, str );
idx = 0;
for( i = n + 1, j = 0; i > 0; i-- )
{
if( zeros && X->p[i - 1] == 0 )
continue;
for( k = sizeof( mbedtls_mpi_uint ) - 1; k >= 0; k-- )
{
if( zeros && ( ( X->p[i - 1] >> ( k << 3 ) ) & 0xFF ) == 0 )
continue;
else
zeros = 0;
if( j % 16 == 0 )
{
if( j > 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)
( X->p[i - 1] >> ( k << 3 ) ) & 0xFF );
j++;
}
}
if( zeros == 1 )
idx += mbedtls_snprintf( str + idx, sizeof( str ) - idx, " 00" );
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)
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( items[i].type == MBEDTLS_PK_DEBUG_MPI )
mbedtls_debug_print_mpi( ssl, level, file, line, name, items[i].value );
else
#if defined(MBEDTLS_ECP_C)
if( items[i].type == MBEDTLS_PK_DEBUG_ECP )
mbedtls_debug_print_ecp( ssl, level, file, line, name, items[i].value );
else
#endif
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 = 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 */
#if 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_ECDH_C */
#endif /* MBEDTLS_DEBUG_C */

306
common/mbedtls/debug.h Normal file
View File

@@ -0,0 +1,306 @@
/**
* \file debug.h
*
* \brief Functions for controlling and providing debug output from the library.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBEDTLS_DEBUG_H
#define MBEDTLS_DEBUG_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include "mbedtls/ssl.h"
#if defined(MBEDTLS_ECP_C)
#include "mbedtls/ecp.h"
#endif
#if defined(MBEDTLS_DEBUG_C)
#define MBEDTLS_DEBUG_STRIP_PARENS( ... ) __VA_ARGS__
#define MBEDTLS_SSL_DEBUG_MSG( level, args ) \
mbedtls_debug_print_msg( ssl, level, __FILE__, __LINE__, \
MBEDTLS_DEBUG_STRIP_PARENS args )
#define MBEDTLS_SSL_DEBUG_RET( level, text, ret ) \
mbedtls_debug_print_ret( ssl, level, __FILE__, __LINE__, text, ret )
#define MBEDTLS_SSL_DEBUG_BUF( level, text, buf, len ) \
mbedtls_debug_print_buf( ssl, level, __FILE__, __LINE__, text, buf, len )
#if defined(MBEDTLS_BIGNUM_C)
#define MBEDTLS_SSL_DEBUG_MPI( level, text, X ) \
mbedtls_debug_print_mpi( ssl, level, __FILE__, __LINE__, text, X )
#endif
#if defined(MBEDTLS_ECP_C)
#define MBEDTLS_SSL_DEBUG_ECP( level, text, X ) \
mbedtls_debug_print_ecp( ssl, level, __FILE__, __LINE__, text, X )
#endif
#if defined(MBEDTLS_X509_CRT_PARSE_C)
#define MBEDTLS_SSL_DEBUG_CRT( level, text, crt ) \
mbedtls_debug_print_crt( ssl, level, __FILE__, __LINE__, text, crt )
#endif
#if defined(MBEDTLS_ECDH_C)
#define MBEDTLS_SSL_DEBUG_ECDH( level, ecdh, attr ) \
mbedtls_debug_printf_ecdh( ssl, level, __FILE__, __LINE__, ecdh, attr )
#endif
#else /* MBEDTLS_DEBUG_C */
#define MBEDTLS_SSL_DEBUG_MSG( level, args ) do { } while( 0 )
#define MBEDTLS_SSL_DEBUG_RET( level, text, ret ) do { } while( 0 )
#define MBEDTLS_SSL_DEBUG_BUF( level, text, buf, len ) do { } while( 0 )
#define MBEDTLS_SSL_DEBUG_MPI( level, text, X ) do { } while( 0 )
#define MBEDTLS_SSL_DEBUG_ECP( level, text, X ) do { } while( 0 )
#define MBEDTLS_SSL_DEBUG_CRT( level, text, crt ) do { } while( 0 )
#define MBEDTLS_SSL_DEBUG_ECDH( level, ecdh, attr ) do { } while( 0 )
#endif /* MBEDTLS_DEBUG_C */
/**
* \def MBEDTLS_PRINTF_ATTRIBUTE
*
* Mark a function as having printf attributes, and thus enable checking
* via -wFormat and other flags. This does nothing on builds with compilers
* that do not support the format attribute
*
* Module: library/debug.c
* Caller:
*
* This module provides debugging functions.
*/
#if defined(__has_attribute)
#if __has_attribute(format)
#define MBEDTLS_PRINTF_ATTRIBUTE(string_index, first_to_check) \
__attribute__((format (printf, string_index, first_to_check)))
#else /* __has_attribute(format) */
#define MBEDTLS_PRINTF_ATTRIBUTE(string_index, first_to_check)
#endif /* __has_attribute(format) */
#else /* defined(__has_attribute) */
#define MBEDTLS_PRINTF_ATTRIBUTE(string_index, first_to_check)
#endif
/**
* \def MBEDTLS_PRINTF_SIZET
*
* MBEDTLS_PRINTF_xxx: Due to issues with older window compilers
* and MinGW we need to define the printf specifier for size_t
* and long long per platform.
*
* Module: library/debug.c
* Caller:
*
* This module provides debugging functions.
*/
#if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER < 1800)
#include <inttypes.h>
#define MBEDTLS_PRINTF_SIZET PRIuPTR
#define MBEDTLS_PRINTF_LONGLONG "I64d"
#else /* defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER < 1800) */
#define MBEDTLS_PRINTF_SIZET "zu"
#define MBEDTLS_PRINTF_LONGLONG "lld"
#endif /* defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER < 1800) */
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Set the threshold error level to handle globally all debug output.
* Debug messages that have a level over the threshold value are
* discarded.
* (Default value: 0 = No debug )
*
* \param threshold theshold level of messages to filter on. Messages at a
* higher level will be discarded.
* - Debug levels
* - 0 No debug
* - 1 Error
* - 2 State change
* - 3 Informational
* - 4 Verbose
*/
void mbedtls_debug_set_threshold( int threshold );
/**
* \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_C)
/**
* \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)
/**
* \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
#if 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
#ifdef __cplusplus
}
#endif
#endif /* debug.h */

File diff suppressed because it is too large Load Diff

View File

@@ -8,31 +8,27 @@
* instead. * instead.
*/ */
/* /*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of mbed TLS (https://tls.mbed.org) * limitations under the License.
* *
*/ */
#ifndef MBEDTLS_DES_H #ifndef MBEDTLS_DES_H
#define MBEDTLS_DES_H #define MBEDTLS_DES_H
#if !defined(MBEDTLS_CONFIG_FILE) #if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h" #include "mbedtls/config.h"
#else #else
#include MBEDTLS_CONFIG_FILE #include MBEDTLS_CONFIG_FILE
#endif #endif
@@ -44,6 +40,8 @@
#define MBEDTLS_DES_DECRYPT 0 #define MBEDTLS_DES_DECRYPT 0
#define MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH -0x0032 /**< The data input has an invalid length. */ #define MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH -0x0032 /**< The data input has an invalid length. */
/* MBEDTLS_ERR_DES_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_DES_HW_ACCEL_FAILED -0x0033 /**< DES hardware accelerator failed. */ #define MBEDTLS_ERR_DES_HW_ACCEL_FAILED -0x0033 /**< DES hardware accelerator failed. */
#define MBEDTLS_DES_KEY_SIZE 8 #define MBEDTLS_DES_KEY_SIZE 8
@@ -63,7 +61,8 @@ extern "C" {
* security risk. We recommend considering stronger ciphers * security risk. We recommend considering stronger ciphers
* instead. * instead.
*/ */
typedef struct mbedtls_des_context { typedef struct mbedtls_des_context
{
uint32_t sk[32]; /*!< DES subkeys */ uint32_t sk[32]; /*!< DES subkeys */
} }
mbedtls_des_context; mbedtls_des_context;
@@ -71,7 +70,8 @@ mbedtls_des_context;
/** /**
* \brief Triple-DES context structure * \brief Triple-DES context structure
*/ */
typedef struct mbedtls_des3_context { typedef struct mbedtls_des3_context
{
uint32_t sk[96]; /*!< 3DES subkeys */ uint32_t sk[96]; /*!< 3DES subkeys */
} }
mbedtls_des3_context; mbedtls_des3_context;
@@ -89,7 +89,7 @@ mbedtls_des3_context;
* security risk. We recommend considering stronger ciphers * security risk. We recommend considering stronger ciphers
* instead. * instead.
*/ */
void mbedtls_des_init(mbedtls_des_context *ctx); void mbedtls_des_init( mbedtls_des_context *ctx );
/** /**
* \brief Clear DES context * \brief Clear DES context
@@ -100,21 +100,21 @@ void mbedtls_des_init(mbedtls_des_context *ctx);
* security risk. We recommend considering stronger ciphers * security risk. We recommend considering stronger ciphers
* instead. * instead.
*/ */
void mbedtls_des_free(mbedtls_des_context *ctx); void mbedtls_des_free( mbedtls_des_context *ctx );
/** /**
* \brief Initialize Triple-DES context * \brief Initialize Triple-DES context
* *
* \param ctx DES3 context to be initialized * \param ctx DES3 context to be initialized
*/ */
void mbedtls_des3_init(mbedtls_des3_context *ctx); void mbedtls_des3_init( mbedtls_des3_context *ctx );
/** /**
* \brief Clear Triple-DES context * \brief Clear Triple-DES context
* *
* \param ctx DES3 context to be cleared * \param ctx DES3 context to be cleared
*/ */
void mbedtls_des3_free(mbedtls_des3_context *ctx); void mbedtls_des3_free( mbedtls_des3_context *ctx );
/** /**
* \brief Set key parity on the given key to odd. * \brief Set key parity on the given key to odd.
@@ -128,7 +128,7 @@ void mbedtls_des3_free(mbedtls_des3_context *ctx);
* security risk. We recommend considering stronger ciphers * security risk. We recommend considering stronger ciphers
* instead. * instead.
*/ */
void mbedtls_des_key_set_parity(unsigned char key[MBEDTLS_DES_KEY_SIZE]); void mbedtls_des_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] );
/** /**
* \brief Check that key parity on the given key is odd. * \brief Check that key parity on the given key is odd.
@@ -144,7 +144,7 @@ void mbedtls_des_key_set_parity(unsigned char key[MBEDTLS_DES_KEY_SIZE]);
* security risk. We recommend considering stronger ciphers * security risk. We recommend considering stronger ciphers
* instead. * instead.
*/ */
int mbedtls_des_key_check_key_parity(const unsigned char key[MBEDTLS_DES_KEY_SIZE]); int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
/** /**
* \brief Check that key is not a weak or semi-weak DES key * \brief Check that key is not a weak or semi-weak DES key
@@ -157,7 +157,7 @@ int mbedtls_des_key_check_key_parity(const unsigned char key[MBEDTLS_DES_KEY_SIZ
* security risk. We recommend considering stronger ciphers * security risk. We recommend considering stronger ciphers
* instead. * instead.
*/ */
int mbedtls_des_key_check_weak(const unsigned char key[MBEDTLS_DES_KEY_SIZE]); int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
/** /**
* \brief DES key schedule (56-bit, encryption) * \brief DES key schedule (56-bit, encryption)
@@ -171,7 +171,7 @@ int mbedtls_des_key_check_weak(const unsigned char key[MBEDTLS_DES_KEY_SIZE]);
* security risk. We recommend considering stronger ciphers * security risk. We recommend considering stronger ciphers
* instead. * instead.
*/ */
int mbedtls_des_setkey_enc(mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE]); int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
/** /**
* \brief DES key schedule (56-bit, decryption) * \brief DES key schedule (56-bit, decryption)
@@ -185,7 +185,7 @@ int mbedtls_des_setkey_enc(mbedtls_des_context *ctx, const unsigned char key[MBE
* security risk. We recommend considering stronger ciphers * security risk. We recommend considering stronger ciphers
* instead. * instead.
*/ */
int mbedtls_des_setkey_dec(mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE]); int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
/** /**
* \brief Triple-DES key schedule (112-bit, encryption) * \brief Triple-DES key schedule (112-bit, encryption)
@@ -195,8 +195,8 @@ int mbedtls_des_setkey_dec(mbedtls_des_context *ctx, const unsigned char key[MBE
* *
* \return 0 * \return 0
*/ */
int mbedtls_des3_set2key_enc(mbedtls_des3_context *ctx, int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx,
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2]); const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] );
/** /**
* \brief Triple-DES key schedule (112-bit, decryption) * \brief Triple-DES key schedule (112-bit, decryption)
@@ -206,8 +206,8 @@ int mbedtls_des3_set2key_enc(mbedtls_des3_context *ctx,
* *
* \return 0 * \return 0
*/ */
int mbedtls_des3_set2key_dec(mbedtls_des3_context *ctx, int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx,
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2]); const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] );
/** /**
* \brief Triple-DES key schedule (168-bit, encryption) * \brief Triple-DES key schedule (168-bit, encryption)
@@ -217,8 +217,8 @@ int mbedtls_des3_set2key_dec(mbedtls_des3_context *ctx,
* *
* \return 0 * \return 0
*/ */
int mbedtls_des3_set3key_enc(mbedtls_des3_context *ctx, int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx,
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3]); const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] );
/** /**
* \brief Triple-DES key schedule (168-bit, decryption) * \brief Triple-DES key schedule (168-bit, decryption)
@@ -228,8 +228,8 @@ int mbedtls_des3_set3key_enc(mbedtls_des3_context *ctx,
* *
* \return 0 * \return 0
*/ */
int mbedtls_des3_set3key_dec(mbedtls_des3_context *ctx, int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx,
const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3]); const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] );
/** /**
* \brief DES-ECB block encryption/decryption * \brief DES-ECB block encryption/decryption
@@ -244,9 +244,9 @@ int mbedtls_des3_set3key_dec(mbedtls_des3_context *ctx,
* security risk. We recommend considering stronger ciphers * security risk. We recommend considering stronger ciphers
* instead. * instead.
*/ */
int mbedtls_des_crypt_ecb(mbedtls_des_context *ctx, int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx,
const unsigned char input[8], const unsigned char input[8],
unsigned char output[8]); unsigned char output[8] );
#if defined(MBEDTLS_CIPHER_MODE_CBC) #if defined(MBEDTLS_CIPHER_MODE_CBC)
/** /**
@@ -271,12 +271,12 @@ int mbedtls_des_crypt_ecb(mbedtls_des_context *ctx,
* security risk. We recommend considering stronger ciphers * security risk. We recommend considering stronger ciphers
* instead. * instead.
*/ */
int mbedtls_des_crypt_cbc(mbedtls_des_context *ctx, int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx,
int mode, int mode,
size_t length, size_t length,
unsigned char iv[8], unsigned char iv[8],
const unsigned char *input, const unsigned char *input,
unsigned char *output); unsigned char *output );
#endif /* MBEDTLS_CIPHER_MODE_CBC */ #endif /* MBEDTLS_CIPHER_MODE_CBC */
/** /**
@@ -288,9 +288,9 @@ int mbedtls_des_crypt_cbc(mbedtls_des_context *ctx,
* *
* \return 0 if successful * \return 0 if successful
*/ */
int mbedtls_des3_crypt_ecb(mbedtls_des3_context *ctx, int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx,
const unsigned char input[8], const unsigned char input[8],
unsigned char output[8]); unsigned char output[8] );
#if defined(MBEDTLS_CIPHER_MODE_CBC) #if defined(MBEDTLS_CIPHER_MODE_CBC)
/** /**
@@ -313,12 +313,12 @@ int mbedtls_des3_crypt_ecb(mbedtls_des3_context *ctx,
* *
* \return 0 if successful, or MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH * \return 0 if successful, or MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH
*/ */
int mbedtls_des3_crypt_cbc(mbedtls_des3_context *ctx, int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx,
int mode, int mode,
size_t length, size_t length,
unsigned char iv[8], unsigned char iv[8],
const unsigned char *input, const unsigned char *input,
unsigned char *output); unsigned char *output );
#endif /* MBEDTLS_CIPHER_MODE_CBC */ #endif /* MBEDTLS_CIPHER_MODE_CBC */
/** /**
@@ -333,15 +333,19 @@ int mbedtls_des3_crypt_cbc(mbedtls_des3_context *ctx,
* security risk. We recommend considering stronger ciphers * security risk. We recommend considering stronger ciphers
* instead. * instead.
*/ */
void mbedtls_des_setkey(uint32_t SK[32], void mbedtls_des_setkey( uint32_t SK[32],
const unsigned char key[MBEDTLS_DES_KEY_SIZE]); const unsigned char key[MBEDTLS_DES_KEY_SIZE] );
#if defined(MBEDTLS_SELF_TEST)
/** /**
* \brief Checkup routine * \brief Checkup routine
* *
* \return 0 if successful, or 1 if the test failed * \return 0 if successful, or 1 if the test failed
*/ */
int mbedtls_des_self_test(int verbose); int mbedtls_des_self_test( int verbose );
#endif /* MBEDTLS_SELF_TEST */
#ifdef __cplusplus #ifdef __cplusplus
} }

735
common/mbedtls/dhm.c Normal file
View File

@@ -0,0 +1,735 @@
/*
* Diffie-Hellman-Merkle key exchange
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* 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
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdlib.h>
#include <stdio.h>
#define mbedtls_printf printf
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif
#if !defined(MBEDTLS_DHM_ALT)
#define DHM_VALIDATE_RET( cond ) \
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_DHM_BAD_INPUT_DATA )
#define DHM_VALIDATE( cond ) \
MBEDTLS_INTERNAL_VALIDATE( cond )
/*
* 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 = ( (*p)[0] << 8 ) | (*p)[1];
(*p) += 2;
if( (int)( end - *p ) < n )
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
if( ( ret = mbedtls_mpi_read_binary( X, *p, n ) ) != 0 )
return( 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 L, U;
int ret = 0;
mbedtls_mpi_init( &L ); mbedtls_mpi_init( &U );
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &L, 2 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) );
if( mbedtls_mpi_cmp_mpi( param, &L ) < 0 ||
mbedtls_mpi_cmp_mpi( param, &U ) > 0 )
{
ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
}
cleanup:
mbedtls_mpi_free( &L ); mbedtls_mpi_free( &U );
return( ret );
}
void mbedtls_dhm_init( mbedtls_dhm_context *ctx )
{
DHM_VALIDATE( ctx != NULL );
memset( ctx, 0, sizeof( mbedtls_dhm_context ) );
}
/*
* 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;
DHM_VALIDATE_RET( ctx != NULL );
DHM_VALIDATE_RET( p != NULL && *p != NULL );
DHM_VALIDATE_RET( end != NULL );
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 );
ctx->len = mbedtls_mpi_size( &ctx->P );
return( 0 );
}
/*
* 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, count = 0;
size_t n1, n2, n3;
unsigned char *p;
DHM_VALIDATE_RET( ctx != NULL );
DHM_VALIDATE_RET( output != NULL );
DHM_VALIDATE_RET( olen != NULL );
DHM_VALIDATE_RET( f_rng != NULL );
if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
/*
* Generate X as large as possible ( < P )
*/
do
{
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) );
if( count++ > 10 )
return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED );
}
while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
/*
* 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 );
/*
* export P, G, GX
*/
#define DHM_MPI_EXPORT( X, n ) \
do { \
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ), \
p + 2, \
( n ) ) ); \
*p++ = (unsigned char)( ( n ) >> 8 ); \
*p++ = (unsigned char)( ( 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 = p - output;
ctx->len = n1;
cleanup:
if( ret != 0 )
return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED + ret );
return( 0 );
}
/*
* 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;
DHM_VALIDATE_RET( ctx != NULL );
DHM_VALIDATE_RET( P != NULL );
DHM_VALIDATE_RET( G != NULL );
if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ||
( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 )
{
return( MBEDTLS_ERR_DHM_SET_GROUP_FAILED + ret );
}
ctx->len = mbedtls_mpi_size( &ctx->P );
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;
DHM_VALIDATE_RET( ctx != NULL );
DHM_VALIDATE_RET( input != NULL );
if( ilen < 1 || ilen > ctx->len )
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
return( 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, count = 0;
DHM_VALIDATE_RET( ctx != NULL );
DHM_VALIDATE_RET( output != NULL );
DHM_VALIDATE_RET( f_rng != NULL );
if( olen < 1 || olen > ctx->len )
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
/*
* generate X and calculate GX = G^X mod P
*/
do
{
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) );
if( count++ > 10 )
return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED );
}
while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
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 );
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) );
cleanup:
if( ret != 0 )
return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED + ret );
return( 0 );
}
/*
* Pick a random R in the range [2, M) for blinding purposes
*/
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, count;
count = 0;
do
{
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( R, mbedtls_mpi_size( M ), f_rng, p_rng ) );
while( mbedtls_mpi_cmp_mpi( R, M ) >= 0 )
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( R, 1 ) );
if( count++ > 10 )
return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
}
while( mbedtls_mpi_cmp_int( R, 1 ) <= 0 );
cleanup:
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-1 ) */
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;
DHM_VALIDATE_RET( ctx != NULL );
DHM_VALIDATE_RET( output != NULL );
DHM_VALIDATE_RET( olen != NULL );
if( output_size < ctx->len )
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 */
if( f_rng != NULL )
{
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 ) );
}
else
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) );
/* Do modular exponentiation */
MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X,
&ctx->P, &ctx->RP ) );
/* Unblind secret value */
if( f_rng != NULL )
{
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 ) );
}
*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_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 */
DHM_VALIDATE_RET( dhm != NULL );
DHM_VALIDATE_RET( dhmin != NULL );
#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_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_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_ERR_DHM_INVALID_FORMAT + ret;
goto exit;
}
if ( p != end )
{
ret = MBEDTLS_ERR_DHM_INVALID_FORMAT +
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
goto exit;
}
}
ret = 0;
dhm->len = mbedtls_mpi_size( &dhm->P );
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 );
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_platform_zeroize( *buf, *n + 1 );
mbedtls_free( *buf );
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;
DHM_VALIDATE_RET( dhm != NULL );
DHM_VALIDATE_RET( path != NULL );
if( ( ret = load_file( path, &buf, &n ) ) != 0 )
return( ret );
ret = mbedtls_dhm_parse_dhm( dhm, buf, n );
mbedtls_platform_zeroize( buf, n );
mbedtls_free( buf );
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 */

1092
common/mbedtls/dhm.h Normal file

File diff suppressed because it is too large Load Diff

729
common/mbedtls/ecdh.c Normal file
View File

@@ -0,0 +1,729 @@
/*
* Elliptic curve Diffie-Hellman
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* References:
*
* SEC1 http://www.secg.org/index.php?action=secg,docs_secg
* 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>
/* Parameter validation macros based on platform_util.h */
#define ECDH_VALIDATE_RET( cond ) \
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
#define ECDH_VALIDATE( cond ) \
MBEDTLS_INTERNAL_VALIDATE( cond )
#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;
/* If multiplication is in progress, we already generated a privkey */
#if defined(MBEDTLS_ECP_RESTARTABLE)
if( rs_ctx == NULL || rs_ctx->rsm == NULL )
#endif
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 )
{
ECDH_VALIDATE_RET( grp != NULL );
ECDH_VALIDATE_RET( d != NULL );
ECDH_VALIDATE_RET( Q != NULL );
ECDH_VALIDATE_RET( f_rng != NULL );
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 )
{
ECDH_VALIDATE_RET( grp != NULL );
ECDH_VALIDATE_RET( Q != NULL );
ECDH_VALIDATE_RET( d != NULL );
ECDH_VALIDATE_RET( z != NULL );
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
}
/*
* Initialize context
*/
void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx )
{
ECDH_VALIDATE( ctx != NULL );
#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 )
{
ECDH_VALIDATE_RET( ctx != NULL );
#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 )
{
ECDH_VALIDATE( ctx != NULL );
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;
ECDH_VALIDATE_RET( ctx != NULL );
ECDH_VALIDATE_RET( olen != NULL );
ECDH_VALIDATE_RET( buf != NULL );
ECDH_VALIDATE_RET( f_rng != NULL );
#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,
end - *buf ) );
}
/*
* Read the ServerKeyExhange 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;
ECDH_VALIDATE_RET( ctx != NULL );
ECDH_VALIDATE_RET( buf != NULL );
ECDH_VALIDATE_RET( *buf != NULL );
ECDH_VALIDATE_RET( end != NULL );
if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, 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;
ECDH_VALIDATE_RET( ctx != NULL );
ECDH_VALIDATE_RET( key != NULL );
ECDH_VALIDATE_RET( side == MBEDTLS_ECDH_OURS ||
side == MBEDTLS_ECDH_THEIRS );
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;
ECDH_VALIDATE_RET( ctx != NULL );
ECDH_VALIDATE_RET( olen != NULL );
ECDH_VALIDATE_RET( buf != NULL );
ECDH_VALIDATE_RET( f_rng != NULL );
#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 )
{
ECDH_VALIDATE_RET( ctx != NULL );
ECDH_VALIDATE_RET( buf != NULL );
#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;
ECDH_VALIDATE_RET( ctx != NULL );
ECDH_VALIDATE_RET( olen != NULL );
ECDH_VALIDATE_RET( buf != NULL );
#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 */

446
common/mbedtls/ecdh.h Normal file
View File

@@ -0,0 +1,446 @@
/**
* \file ecdh.h
*
* \brief This file contains ECDH definitions and functions.
*
* The Elliptic Curve Diffie-Hellman (ECDH) protocol is an anonymous
* key agreement protocol allowing two parties to establish a shared
* secret over an insecure channel. Each party must have an
* elliptic-curve publicprivate key pair.
*
* For more information, see <em>NIST SP 800-56A Rev. 2: Recommendation for
* Pair-Wise Key Establishment Schemes Using Discrete Logarithm
* Cryptography</em>.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBEDTLS_ECDH_H
#define MBEDTLS_ECDH_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include "mbedtls/ecp.h"
#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
#undef MBEDTLS_ECDH_LEGACY_CONTEXT
#include "everest/everest.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/**
* Defines the source of the imported EC key.
*/
typedef enum
{
MBEDTLS_ECDH_OURS, /**< Our key. */
MBEDTLS_ECDH_THEIRS, /**< The key of the peer. */
} mbedtls_ecdh_side;
#if !defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
/**
* Defines the ECDH implementation used.
*
* Later versions of the library may add new variants, therefore users should
* not make any assumptions about them.
*/
typedef enum
{
MBEDTLS_ECDH_VARIANT_NONE = 0, /*!< Implementation not defined. */
MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0,/*!< The default Mbed TLS implementation */
#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
MBEDTLS_ECDH_VARIANT_EVEREST /*!< Everest implementation */
#endif
} mbedtls_ecdh_variant;
/**
* The context used by the default ECDH implementation.
*
* Later versions might change the structure of this context, therefore users
* should not make any assumptions about the structure of
* mbedtls_ecdh_context_mbed.
*/
typedef struct mbedtls_ecdh_context_mbed
{
mbedtls_ecp_group grp; /*!< The elliptic curve used. */
mbedtls_mpi d; /*!< The private key. */
mbedtls_ecp_point Q; /*!< The public key. */
mbedtls_ecp_point Qp; /*!< The value of the public key of the peer. */
mbedtls_mpi z; /*!< The shared secret. */
#if defined(MBEDTLS_ECP_RESTARTABLE)
mbedtls_ecp_restart_ctx rs; /*!< The restart context for EC computations. */
#endif
} mbedtls_ecdh_context_mbed;
#endif
/**
*
* \warning Performing multiple operations concurrently on the same
* ECDSA context is not supported; objects of this type
* should not be shared between multiple threads.
* \brief The ECDH context structure.
*/
typedef struct mbedtls_ecdh_context
{
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
mbedtls_ecp_group grp; /*!< The elliptic curve used. */
mbedtls_mpi d; /*!< The private key. */
mbedtls_ecp_point Q; /*!< The public key. */
mbedtls_ecp_point Qp; /*!< The value of the public key of the peer. */
mbedtls_mpi z; /*!< The shared secret. */
int point_format; /*!< The format of point export in TLS messages. */
mbedtls_ecp_point Vi; /*!< The blinding value. */
mbedtls_ecp_point Vf; /*!< The unblinding value. */
mbedtls_mpi _d; /*!< The previous \p d. */
#if defined(MBEDTLS_ECP_RESTARTABLE)
int restart_enabled; /*!< The flag for restartable mode. */
mbedtls_ecp_restart_ctx rs; /*!< The restart context for EC computations. */
#endif /* MBEDTLS_ECP_RESTARTABLE */
#else
uint8_t point_format; /*!< The format of point export in TLS messages
as defined in RFC 4492. */
mbedtls_ecp_group_id grp_id;/*!< The elliptic curve used. */
mbedtls_ecdh_variant var; /*!< The ECDH implementation/structure used. */
union
{
mbedtls_ecdh_context_mbed mbed_ecdh;
#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
mbedtls_ecdh_context_everest everest_ecdh;
#endif
} ctx; /*!< Implementation-specific context. The
context in use is specified by the \c var
field. */
#if defined(MBEDTLS_ECP_RESTARTABLE)
uint8_t restart_enabled; /*!< The flag for restartable mode. Functions of
an alternative implementation not supporting
restartable mode must return
MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED error
if this flag is set. */
#endif /* MBEDTLS_ECP_RESTARTABLE */
#endif /* MBEDTLS_ECDH_LEGACY_CONTEXT */
}
mbedtls_ecdh_context;
/**
* \brief Check whether a given group can be used for ECDH.
*
* \param gid The ECP group ID to check.
*
* \return \c 1 if the group can be used, \c 0 otherwise
*/
int mbedtls_ecdh_can_do( mbedtls_ecp_group_id gid );
/**
* \brief This function generates an ECDH keypair on an elliptic
* curve.
*
* This function performs the first of two core computations
* implemented during the ECDH key exchange. The second core
* computation is performed by mbedtls_ecdh_compute_shared().
*
* \see ecp.h
*
* \param grp The ECP group to use. This must be initialized and have
* domain parameters loaded, for example through
* mbedtls_ecp_load() or mbedtls_ecp_tls_read_group().
* \param d The destination MPI (private key).
* This must be initialized.
* \param Q The destination point (public key).
* This must be initialized.
* \param f_rng The RNG function to use. This must not be \c NULL.
* \param p_rng The RNG context to be passed to \p f_rng. This may be
* \c NULL in case \p f_rng doesn't need a context argument.
*
* \return \c 0 on success.
* \return Another \c MBEDTLS_ERR_ECP_XXX or
* \c MBEDTLS_MPI_XXX error code on failure.
*/
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 );
/**
* \brief This function computes the shared secret.
*
* This function performs the second of two core computations
* implemented during the ECDH key exchange. The first core
* computation is performed by mbedtls_ecdh_gen_public().
*
* \see ecp.h
*
* \note If \p f_rng is not NULL, it is used to implement
* countermeasures against side-channel attacks.
* For more information, see mbedtls_ecp_mul().
*
* \param grp The ECP group to use. This must be initialized and have
* domain parameters loaded, for example through
* mbedtls_ecp_load() or mbedtls_ecp_tls_read_group().
* \param z The destination MPI (shared secret).
* This must be initialized.
* \param Q The public key from another party.
* This must be initialized.
* \param d Our secret exponent (private key).
* This must be initialized.
* \param f_rng The RNG function. This may be \c NULL if randomization
* of intermediate results during the ECP computations is
* not needed (discouraged). See the documentation of
* mbedtls_ecp_mul() for more.
* \param p_rng The RNG context to be passed to \p f_rng. This may be
* \c NULL if \p f_rng is \c NULL or doesn't need a
* context argument.
*
* \return \c 0 on success.
* \return Another \c MBEDTLS_ERR_ECP_XXX or
* \c MBEDTLS_MPI_XXX error code on failure.
*/
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 );
/**
* \brief This function initializes an ECDH context.
*
* \param ctx The ECDH context to initialize. This must not be \c NULL.
*/
void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx );
/**
* \brief This function sets up the ECDH context with the information
* given.
*
* This function should be called after mbedtls_ecdh_init() but
* before mbedtls_ecdh_make_params(). There is no need to call
* this function before mbedtls_ecdh_read_params().
*
* This is the first function used by a TLS server for ECDHE
* ciphersuites.
*
* \param ctx The ECDH context to set up. This must be initialized.
* \param grp_id The group id of the group to set up the context for.
*
* \return \c 0 on success.
*/
int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx,
mbedtls_ecp_group_id grp_id );
/**
* \brief This function frees a context.
*
* \param ctx The context to free. This may be \c NULL, in which
* case this function does nothing. If it is not \c NULL,
* it must point to an initialized ECDH context.
*/
void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx );
/**
* \brief This function generates an EC key pair and exports its
* in the format used in a TLS ServerKeyExchange handshake
* message.
*
* This is the second function used by a TLS server for ECDHE
* ciphersuites. (It is called after mbedtls_ecdh_setup().)
*
* \see ecp.h
*
* \param ctx The ECDH context to use. This must be initialized
* and bound to a group, for example via mbedtls_ecdh_setup().
* \param olen The address at which to store the number of Bytes written.
* \param buf The destination buffer. This must be a writable buffer of
* length \p blen Bytes.
* \param blen The length of the destination buffer \p buf in Bytes.
* \param f_rng The RNG function to use. This must not be \c NULL.
* \param p_rng The RNG context to be passed to \p f_rng. This may be
* \c NULL in case \p f_rng doesn't need a context argument.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
* operations was reached: see \c mbedtls_ecp_set_max_ops().
* \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure.
*/
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 );
/**
* \brief This function parses the ECDHE parameters in a
* TLS ServerKeyExchange handshake message.
*
* \note In a TLS handshake, this is the how the client
* sets up its ECDHE context from the server's public
* ECDHE key material.
*
* \see ecp.h
*
* \param ctx The ECDHE context to use. This must be initialized.
* \param buf On input, \c *buf must be the start of the input buffer.
* On output, \c *buf is updated to point to the end of the
* data that has been read. On success, this is the first byte
* past the end of the ServerKeyExchange parameters.
* On error, this is the point at which an error has been
* detected, which is usually not useful except to debug
* failures.
* \param end The end of the input buffer.
*
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_ECP_XXX error code on failure.
*
*/
int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx,
const unsigned char **buf,
const unsigned char *end );
/**
* \brief This function sets up an ECDH context from an EC key.
*
* It is used by clients and servers in place of the
* ServerKeyEchange for static ECDH, and imports ECDH
* parameters from the EC key information of a certificate.
*
* \see ecp.h
*
* \param ctx The ECDH context to set up. This must be initialized.
* \param key The EC key to use. This must be initialized.
* \param side Defines the source of the key. Possible values are:
* - #MBEDTLS_ECDH_OURS: The key is ours.
* - #MBEDTLS_ECDH_THEIRS: The key is that of the peer.
*
* \return \c 0 on success.
* \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure.
*
*/
int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx,
const mbedtls_ecp_keypair *key,
mbedtls_ecdh_side side );
/**
* \brief This function generates a public key and exports it
* as a TLS ClientKeyExchange payload.
*
* This is the second function used by a TLS client for ECDH(E)
* ciphersuites.
*
* \see ecp.h
*
* \param ctx The ECDH context to use. This must be initialized
* and bound to a group, the latter usually by
* mbedtls_ecdh_read_params().
* \param olen The address at which to store the number of Bytes written.
* This must not be \c NULL.
* \param buf The destination buffer. This must be a writable buffer
* of length \p blen Bytes.
* \param blen The size of the destination buffer \p buf in Bytes.
* \param f_rng The RNG function to use. This must not be \c NULL.
* \param p_rng The RNG context to be passed to \p f_rng. This may be
* \c NULL in case \p f_rng doesn't need a context argument.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
* operations was reached: see \c mbedtls_ecp_set_max_ops().
* \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure.
*/
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 );
/**
* \brief This function parses and processes the ECDHE payload of a
* TLS ClientKeyExchange message.
*
* This is the third function used by a TLS server for ECDH(E)
* ciphersuites. (It is called after mbedtls_ecdh_setup() and
* mbedtls_ecdh_make_params().)
*
* \see ecp.h
*
* \param ctx The ECDH context to use. This must be initialized
* and bound to a group, for example via mbedtls_ecdh_setup().
* \param buf The pointer to the ClientKeyExchange payload. This must
* be a readable buffer of length \p blen Bytes.
* \param blen The length of the input buffer \p buf in Bytes.
*
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_ECP_XXX error code on failure.
*/
int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx,
const unsigned char *buf, size_t blen );
/**
* \brief This function derives and exports the shared secret.
*
* This is the last function used by both TLS client
* and servers.
*
* \note If \p f_rng is not NULL, it is used to implement
* countermeasures against side-channel attacks.
* For more information, see mbedtls_ecp_mul().
*
* \see ecp.h
* \param ctx The ECDH context to use. This must be initialized
* and have its own private key generated and the peer's
* public key imported.
* \param olen The address at which to store the total number of
* Bytes written on success. This must not be \c NULL.
* \param buf The buffer to write the generated shared key to. This
* must be a writable buffer of size \p blen Bytes.
* \param blen The length of the destination buffer \p buf in Bytes.
* \param f_rng The RNG function, for blinding purposes. This may
* b \c NULL if blinding isn't needed.
* \param p_rng The RNG context. This may be \c NULL if \p f_rng
* doesn't need a context argument.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
* operations was reached: see \c mbedtls_ecp_set_max_ops().
* \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure.
*/
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 );
#if defined(MBEDTLS_ECP_RESTARTABLE)
/**
* \brief This function enables restartable EC computations for this
* context. (Default: disabled.)
*
* \see \c mbedtls_ecp_set_max_ops()
*
* \note It is not possible to safely disable restartable
* computations once enabled, except by free-ing the context,
* which cancels possible in-progress operations.
*
* \param ctx The ECDH context to use. This must be initialized.
*/
void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx );
#endif /* MBEDTLS_ECP_RESTARTABLE */
#ifdef __cplusplus
}
#endif
#endif /* ecdh.h */

File diff suppressed because it is too large Load Diff

View File

@@ -11,66 +11,134 @@
* *
*/ */
/* /*
* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of Mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
#ifndef MBEDTLS_ECDSA_H #ifndef MBEDTLS_ECDSA_H
#define MBEDTLS_ECDSA_H #define MBEDTLS_ECDSA_H
#include "ecp.h" #if !defined(MBEDTLS_CONFIG_FILE)
#include "md.h" #include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
/* #include "mbedtls/ecp.h"
* RFC-4492 page 20: #include "mbedtls/md.h"
/**
* \brief Maximum ECDSA signature size for a given curve bit size
* *
* \param bits Curve size in bits
* \return Maximum signature size in bytes
*
* \note This macro returns a compile-time constant if its argument
* is one. It may evaluate its argument multiple times.
*/
/*
* Ecdsa-Sig-Value ::= SEQUENCE { * Ecdsa-Sig-Value ::= SEQUENCE {
* r INTEGER, * r INTEGER,
* s INTEGER * s INTEGER
* } * }
* *
* Size is at most * For each of r and s, the value (V) may include an extra initial "0" bit.
* 1 (tag) + 1 (len) + 1 (initial 0) + ECP_MAX_BYTES for each of r and s,
* twice that + 1 (tag) + 2 (len) for the sequence
* (assuming ECP_MAX_BYTES is less than 126 for r and s,
* and less than 124 (total len <= 255) for the sequence)
*/ */
#if MBEDTLS_ECP_MAX_BYTES > 124 #define MBEDTLS_ECDSA_MAX_SIG_LEN( bits ) \
#error "MBEDTLS_ECP_MAX_BYTES bigger than expected, please fix MBEDTLS_ECDSA_MAX_LEN" ( /*T,L of SEQUENCE*/ ( ( bits ) >= 61 * 8 ? 3 : 2 ) + \
#endif /*T,L of r,s*/ 2 * ( ( ( bits ) >= 127 * 8 ? 3 : 2 ) + \
/** The maximal size of an ECDSA signature in Bytes. */ /*V of r,s*/ ( ( bits ) + 8 ) / 8 ) )
#define MBEDTLS_ECDSA_MAX_LEN ( 3 + 2 * ( 3 + MBEDTLS_ECP_MAX_BYTES ) )
/** /** The maximal size of an ECDSA signature in Bytes. */
* \brief The ECDSA context structure. #define MBEDTLS_ECDSA_MAX_LEN MBEDTLS_ECDSA_MAX_SIG_LEN( MBEDTLS_ECP_MAX_BITS )
*/
typedef mbedtls_ecp_keypair mbedtls_ecdsa_context;
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/**
* \brief The ECDSA context structure.
*
* \warning Performing multiple operations concurrently on the same
* ECDSA context is not supported; objects of this type
* should not be shared between multiple threads.
*/
typedef mbedtls_ecp_keypair mbedtls_ecdsa_context;
#if defined(MBEDTLS_ECP_RESTARTABLE)
/**
* \brief Internal restart context for ecdsa_verify()
*
* \note Opaque struct, defined in ecdsa.c
*/
typedef struct mbedtls_ecdsa_restart_ver mbedtls_ecdsa_restart_ver_ctx;
/**
* \brief Internal restart context for ecdsa_sign()
*
* \note Opaque struct, defined in ecdsa.c
*/
typedef struct mbedtls_ecdsa_restart_sig mbedtls_ecdsa_restart_sig_ctx;
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
/**
* \brief Internal restart context for ecdsa_sign_det()
*
* \note Opaque struct, defined in ecdsa.c
*/
typedef struct mbedtls_ecdsa_restart_det mbedtls_ecdsa_restart_det_ctx;
#endif
/**
* \brief General context for resuming ECDSA operations
*/
typedef struct
{
mbedtls_ecp_restart_ctx ecp; /*!< base context for ECP restart and
shared administrative info */
mbedtls_ecdsa_restart_ver_ctx *ver; /*!< ecdsa_verify() sub-context */
mbedtls_ecdsa_restart_sig_ctx *sig; /*!< ecdsa_sign() sub-context */
#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
mbedtls_ecdsa_restart_det_ctx *det; /*!< ecdsa_sign_det() sub-context */
#endif
} mbedtls_ecdsa_restart_ctx;
#else /* MBEDTLS_ECP_RESTARTABLE */
/* Now we can declare functions that take a pointer to that */
typedef void mbedtls_ecdsa_restart_ctx;
#endif /* MBEDTLS_ECP_RESTARTABLE */
/**
* \brief This function checks whether a given group can be used
* for ECDSA.
*
* \param gid The ECP group ID to check.
*
* \return \c 1 if the group can be used, \c 0 otherwise
*/
int mbedtls_ecdsa_can_do( mbedtls_ecp_group_id gid );
/** /**
* \brief This function computes the ECDSA signature of a * \brief This function computes the ECDSA signature of a
* previously-hashed message. * previously-hashed message.
* *
* \note The deterministic version is usually preferred. * \note The deterministic version implemented in
* mbedtls_ecdsa_sign_det() is usually preferred.
* *
* \note If the bitlength of the message hash is larger than the * \note If the bitlength of the message hash is larger than the
* bitlength of the group order, then the hash is truncated * bitlength of the group order, then the hash is truncated
@@ -80,24 +148,93 @@ extern "C" {
* *
* \see ecp.h * \see ecp.h
* *
* \param grp The ECP group. * \param grp The context for the elliptic curve to use.
* \param r The first output integer. * This must be initialized and have group parameters
* \param s The second output integer. * set, for example through mbedtls_ecp_group_load().
* \param d The private signing key. * \param r The MPI context in which to store the first part
* \param buf The message hash. * the signature. This must be initialized.
* \param blen The length of \p buf. * \param s The MPI context in which to store the second part
* \param f_rng The RNG function. * the signature. This must be initialized.
* \param p_rng The RNG context. * \param d The private signing key. This must be initialized.
* \param buf The content to be signed. This is usually the hash of
* the original data to be signed. This must be a readable
* buffer of length \p blen Bytes. It may be \c NULL if
* \p blen is zero.
* \param blen The length of \p buf in Bytes.
* \param f_rng The RNG function. This must not be \c NULL.
* \param p_rng The RNG context to be passed to \p f_rng. This may be
* \c NULL if \p f_rng doesn't need a context parameter.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return An \c MBEDTLS_ERR_ECP_XXX * \return An \c MBEDTLS_ERR_ECP_XXX
* or \c MBEDTLS_MPI_XXX error code on failure. * or \c MBEDTLS_MPI_XXX error code on failure.
*/ */
int mbedtls_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, 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, 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)(void *, unsigned char *, size_t), void *p_rng );
#if defined(MBEDTLS_ECDSA_DETERMINISTIC) #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
#if ! defined(MBEDTLS_DEPRECATED_REMOVED)
#if defined(MBEDTLS_DEPRECATED_WARNING)
#define MBEDTLS_DEPRECATED __attribute__((deprecated))
#else
#define MBEDTLS_DEPRECATED
#endif
/**
* \brief This function computes the ECDSA signature of a
* previously-hashed message, deterministic version.
*
* For more information, see <em>RFC-6979: Deterministic
* Usage of the Digital Signature Algorithm (DSA) and Elliptic
* Curve Digital Signature Algorithm (ECDSA)</em>.
*
* \note If the bitlength of the message hash is larger than the
* bitlength of the group order, then the hash is truncated as
* defined in <em>Standards for Efficient Cryptography Group
* (SECG): SEC1 Elliptic Curve Cryptography</em>, section
* 4.1.3, step 5.
*
* \warning Since the output of the internal RNG is always the same for
* the same key and message, this limits the efficiency of
* blinding and leaks information through side channels. For
* secure behavior use mbedtls_ecdsa_sign_det_ext() instead.
*
* (Optimally the blinding is a random value that is different
* on every execution. In this case the blinding is still
* random from the attackers perspective, but is the same on
* each execution. This means that this blinding does not
* prevent attackers from recovering secrets by combining
* several measurement traces, but may prevent some attacks
* that exploit relationships between secret data.)
*
* \see ecp.h
*
* \param grp The context for the elliptic curve to use.
* This must be initialized and have group parameters
* set, for example through mbedtls_ecp_group_load().
* \param r The MPI context in which to store the first part
* the signature. This must be initialized.
* \param s The MPI context in which to store the second part
* the signature. This must be initialized.
* \param d The private signing key. This must be initialized
* and setup, for example through mbedtls_ecp_gen_privkey().
* \param buf The hashed content to be signed. This must be a readable
* buffer of length \p blen Bytes. It may be \c NULL if
* \p blen is zero.
* \param blen The length of \p buf in Bytes.
* \param md_alg The hash algorithm used to hash the original data.
*
* \return \c 0 on success.
* \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX
* error code on failure.
*/
int mbedtls_ecdsa_sign_det( 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 ) MBEDTLS_DEPRECATED;
#undef MBEDTLS_DEPRECATED
#endif /* MBEDTLS_DEPRECATED_REMOVED */
/** /**
* \brief This function computes the ECDSA signature of a * \brief This function computes the ECDSA signature of a
* previously-hashed message, deterministic version. * previously-hashed message, deterministic version.
@@ -114,21 +251,35 @@ int mbedtls_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
* *
* \see ecp.h * \see ecp.h
* *
* \param grp The ECP group. * \param grp The context for the elliptic curve to use.
* \param r The first output integer. * This must be initialized and have group parameters
* \param s The second output integer. * set, for example through mbedtls_ecp_group_load().
* \param d The private signing key. * \param r The MPI context in which to store the first part
* \param buf The message hash. * the signature. This must be initialized.
* \param blen The length of \p buf. * \param s The MPI context in which to store the second part
* \param md_alg The MD algorithm used to hash the message. * the signature. This must be initialized.
* \param d The private signing key. This must be initialized
* and setup, for example through mbedtls_ecp_gen_privkey().
* \param buf The hashed content to be signed. This must be a readable
* buffer of length \p blen Bytes. It may be \c NULL if
* \p blen is zero.
* \param blen The length of \p buf in Bytes.
* \param md_alg The hash algorithm used to hash the original data.
* \param f_rng_blind The RNG function used for blinding. This must not be
* \c NULL.
* \param p_rng_blind The RNG context to be passed to \p f_rng. This may be
* \c NULL if \p f_rng doesn't need a context parameter.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX
* error code on failure. * error code on failure.
*/ */
int mbedtls_ecdsa_sign_det(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, int mbedtls_ecdsa_sign_det_ext( mbedtls_ecp_group *grp, mbedtls_mpi *r,
const mbedtls_mpi *d, const unsigned char *buf, size_t blen, mbedtls_mpi *s, const mbedtls_mpi *d,
mbedtls_md_type_t md_alg); 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 );
#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
/** /**
@@ -143,12 +294,19 @@ int mbedtls_ecdsa_sign_det(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *
* *
* \see ecp.h * \see ecp.h
* *
* \param grp The ECP group. * \param grp The ECP group to use.
* \param buf The message hash. * This must be initialized and have group parameters
* \param blen The length of \p buf. * set, for example through mbedtls_ecp_group_load().
* \param Q The public key to use for verification. * \param buf The hashed content that was signed. This must be a readable
* buffer of length \p blen Bytes. It may be \c NULL if
* \p blen is zero.
* \param blen The length of \p buf in Bytes.
* \param Q The public key to use for verification. This must be
* initialized and setup.
* \param r The first integer of the signature. * \param r The first integer of the signature.
* This must be initialized.
* \param s The second integer of the signature. * \param s The second integer of the signature.
* This must be initialized.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the signature * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the signature
@@ -156,9 +314,10 @@ int mbedtls_ecdsa_sign_det(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *
* \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX
* error code on failure for any other reason. * error code on failure for any other reason.
*/ */
int mbedtls_ecdsa_verify(mbedtls_ecp_group *grp, int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
const unsigned char *buf, size_t blen, const unsigned char *buf, size_t blen,
const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s); const mbedtls_ecp_point *Q, const mbedtls_mpi *r,
const mbedtls_mpi *s);
/** /**
* \brief This function computes the ECDSA signature and writes it * \brief This function computes the ECDSA signature and writes it
@@ -175,11 +334,6 @@ int mbedtls_ecdsa_verify(mbedtls_ecp_group *grp,
* of the Digital Signature Algorithm (DSA) and Elliptic * of the Digital Signature Algorithm (DSA) and Elliptic
* Curve Digital Signature Algorithm (ECDSA)</em>. * Curve Digital Signature Algorithm (ECDSA)</em>.
* *
* \note The \p sig buffer must be at least twice as large as the
* size of the curve used, plus 9. For example, 73 Bytes if
* a 256-bit curve is used. A buffer length of
* #MBEDTLS_ECDSA_MAX_LEN is always safe.
*
* \note If the bitlength of the message hash is larger than the * \note If the bitlength of the message hash is larger than the
* bitlength of the group order, then the hash is truncated as * bitlength of the group order, then the hash is truncated as
* defined in <em>Standards for Efficient Cryptography Group * defined in <em>Standards for Efficient Cryptography Group
@@ -188,24 +342,84 @@ int mbedtls_ecdsa_verify(mbedtls_ecp_group *grp,
* *
* \see ecp.h * \see ecp.h
* *
* \param ctx The ECDSA context. * \param ctx The ECDSA context to use. This must be initialized
* and have a group and private key bound to it, for example
* via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair().
* \param md_alg The message digest that was used to hash the message. * \param md_alg The message digest that was used to hash the message.
* \param hash The message hash. * \param hash The message hash to be signed. This must be a readable
* \param hlen The length of the hash. * buffer of length \p blen Bytes.
* \param sig The buffer that holds the signature. * \param hlen The length of the hash \p hash in Bytes.
* \param slen The length of the signature written. * \param sig The buffer to which to write the signature. This must be a
* \param f_rng The RNG function. * writable buffer of length at least twice as large as the
* \param p_rng The RNG context. * size of the curve used, plus 9. For example, 73 Bytes if
* a 256-bit curve is used. A buffer length of
* #MBEDTLS_ECDSA_MAX_LEN is always safe.
* \param slen The address at which to store the actual length of
* the signature written. Must not be \c NULL.
* \param f_rng The RNG function. This must not be \c NULL if
* #MBEDTLS_ECDSA_DETERMINISTIC is unset. Otherwise,
* it is used only for blinding and may be set to \c NULL, but
* doing so is DEPRECATED.
* \param p_rng The RNG context to be passed to \p f_rng. This may be
* \c NULL if \p f_rng is \c NULL or doesn't use a context.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return An \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or * \return An \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or
* \c MBEDTLS_ERR_ASN1_XXX error code on failure. * \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/ */
int mbedtls_ecdsa_write_signature(mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx,
const unsigned char *hash, size_t hlen, mbedtls_md_type_t md_alg,
unsigned char *sig, size_t *slen, const unsigned char *hash, size_t hlen,
int (*f_rng)(void *, unsigned char *, size_t), unsigned char *sig, size_t *slen,
void *p_rng); int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
/**
* \brief This function computes the ECDSA signature and writes it
* to a buffer, in a restartable way.
*
* \see \c mbedtls_ecdsa_write_signature()
*
* \note This function is like \c mbedtls_ecdsa_write_signature()
* but it can return early and restart according to the limit
* set with \c mbedtls_ecp_set_max_ops() to reduce blocking.
*
* \param ctx The ECDSA context to use. This must be initialized
* and have a group and private key bound to it, for example
* via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair().
* \param md_alg The message digest that was used to hash the message.
* \param hash The message hash to be signed. This must be a readable
* buffer of length \p blen Bytes.
* \param hlen The length of the hash \p hash in Bytes.
* \param sig The buffer to which to write the signature. This must be a
* writable buffer of length at least twice as large as the
* size of the curve used, plus 9. For example, 73 Bytes if
* a 256-bit curve is used. A buffer length of
* #MBEDTLS_ECDSA_MAX_LEN is always safe.
* \param slen The address at which to store the actual length of
* the signature written. Must not be \c NULL.
* \param f_rng The RNG function. This must not be \c NULL if
* #MBEDTLS_ECDSA_DETERMINISTIC is unset. Otherwise,
* it is unused and may be set to \c NULL.
* \param p_rng The RNG context to be passed to \p f_rng. This may be
* \c NULL if \p f_rng is \c NULL or doesn't use a context.
* \param rs_ctx The restart context to use. This may be \c NULL to disable
* restarting. If it is not \c NULL, it must point to an
* initialized restart context.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
* operations was reached: see \c mbedtls_ecp_set_max_ops().
* \return Another \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or
* \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/
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 *slen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng,
mbedtls_ecdsa_restart_ctx *rs_ctx );
#if defined(MBEDTLS_ECDSA_DETERMINISTIC) #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
#if ! defined(MBEDTLS_DEPRECATED_REMOVED) #if ! defined(MBEDTLS_DEPRECATED_REMOVED)
@@ -227,11 +441,6 @@ int mbedtls_ecdsa_write_signature(mbedtls_ecdsa_context *ctx, mbedtls_md_type_t
* \warning It is not thread-safe to use the same context in * \warning It is not thread-safe to use the same context in
* multiple threads. * multiple threads.
* *
* \note The \p sig buffer must be at least twice as large as the
* size of the curve used, plus 9. For example, 73 Bytes if a
* 256-bit curve is used. A buffer length of
* #MBEDTLS_ECDSA_MAX_LEN is always safe.
*
* \note If the bitlength of the message hash is larger than the * \note If the bitlength of the message hash is larger than the
* bitlength of the group order, then the hash is truncated as * bitlength of the group order, then the hash is truncated as
* defined in <em>Standards for Efficient Cryptography Group * defined in <em>Standards for Efficient Cryptography Group
@@ -243,21 +452,29 @@ int mbedtls_ecdsa_write_signature(mbedtls_ecdsa_context *ctx, mbedtls_md_type_t
* \deprecated Superseded by mbedtls_ecdsa_write_signature() in * \deprecated Superseded by mbedtls_ecdsa_write_signature() in
* Mbed TLS version 2.0 and later. * Mbed TLS version 2.0 and later.
* *
* \param ctx The ECDSA context. * \param ctx The ECDSA context to use. This must be initialized
* \param hash The message hash. * and have a group and private key bound to it, for example
* \param hlen The length of the hash. * via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair().
* \param sig The buffer that holds the signature. * \param hash The message hash to be signed. This must be a readable
* \param slen The length of the signature written. * buffer of length \p blen Bytes.
* \param md_alg The MD algorithm used to hash the message. * \param hlen The length of the hash \p hash in Bytes.
* \param sig The buffer to which to write the signature. This must be a
* writable buffer of length at least twice as large as the
* size of the curve used, plus 9. For example, 73 Bytes if
* a 256-bit curve is used. A buffer length of
* #MBEDTLS_ECDSA_MAX_LEN is always safe.
* \param slen The address at which to store the actual length of
* the signature written. Must not be \c NULL.
* \param md_alg The message digest that was used to hash the message.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return An \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or * \return An \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or
* \c MBEDTLS_ERR_ASN1_XXX error code on failure. * \c MBEDTLS_ERR_ASN1_XXX error code on failure.
*/ */
int mbedtls_ecdsa_write_signature_det(mbedtls_ecdsa_context *ctx, int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx,
const unsigned char *hash, size_t hlen, const unsigned char *hash, size_t hlen,
unsigned char *sig, size_t *slen, unsigned char *sig, size_t *slen,
mbedtls_md_type_t md_alg) MBEDTLS_DEPRECATED; mbedtls_md_type_t md_alg ) MBEDTLS_DEPRECATED;
#undef MBEDTLS_DEPRECATED #undef MBEDTLS_DEPRECATED
#endif /* MBEDTLS_DEPRECATED_REMOVED */ #endif /* MBEDTLS_DEPRECATED_REMOVED */
#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
@@ -273,11 +490,14 @@ int mbedtls_ecdsa_write_signature_det(mbedtls_ecdsa_context *ctx,
* *
* \see ecp.h * \see ecp.h
* *
* \param ctx The ECDSA context. * \param ctx The ECDSA context to use. This must be initialized
* \param hash The message hash. * and have a group and public key bound to it.
* \param hlen The size of the hash. * \param hash The message hash that was signed. This must be a readable
* \param sig The signature to read and verify. * buffer of length \p size Bytes.
* \param slen The size of \p sig. * \param hlen The size of the hash \p hash.
* \param sig The signature to read and verify. This must be a readable
* buffer of length \p slen Bytes.
* \param slen The size of \p sig in Bytes.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid.
@@ -286,9 +506,45 @@ int mbedtls_ecdsa_write_signature_det(mbedtls_ecdsa_context *ctx,
* \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX
* error code on failure for any other reason. * error code on failure for any other reason.
*/ */
int mbedtls_ecdsa_read_signature(mbedtls_ecdsa_context *ctx, int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx,
const unsigned char *hash, size_t hlen, const unsigned char *hash, size_t hlen,
const unsigned char *sig, size_t slen); const unsigned char *sig, size_t slen );
/**
* \brief This function reads and verifies an ECDSA signature,
* in a restartable way.
*
* \see \c mbedtls_ecdsa_read_signature()
*
* \note This function is like \c mbedtls_ecdsa_read_signature()
* but it can return early and restart according to the limit
* set with \c mbedtls_ecp_set_max_ops() to reduce blocking.
*
* \param ctx The ECDSA context to use. This must be initialized
* and have a group and public key bound to it.
* \param hash The message hash that was signed. This must be a readable
* buffer of length \p size Bytes.
* \param hlen The size of the hash \p hash.
* \param sig The signature to read and verify. This must be a readable
* buffer of length \p slen Bytes.
* \param slen The size of \p sig in Bytes.
* \param rs_ctx The restart context to use. This may be \c NULL to disable
* restarting. If it is not \c NULL, it must point to an
* initialized restart context.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid.
* \return #MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if there is a valid
* signature in \p sig, but its length is less than \p siglen.
* \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
* operations was reached: see \c mbedtls_ecp_set_max_ops().
* \return Another \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX
* error code on failure for any other reason.
*/
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 );
/** /**
* \brief This function generates an ECDSA keypair on the given curve. * \brief This function generates an ECDSA keypair on the given curve.
@@ -296,45 +552,72 @@ int mbedtls_ecdsa_read_signature(mbedtls_ecdsa_context *ctx,
* \see ecp.h * \see ecp.h
* *
* \param ctx The ECDSA context to store the keypair in. * \param ctx The ECDSA context to store the keypair in.
* This must be initialized.
* \param gid The elliptic curve to use. One of the various * \param gid The elliptic curve to use. One of the various
* \c MBEDTLS_ECP_DP_XXX macros depending on configuration. * \c MBEDTLS_ECP_DP_XXX macros depending on configuration.
* \param f_rng The RNG function. * \param f_rng The RNG function to use. This must not be \c NULL.
* \param p_rng The RNG context. * \param p_rng The RNG context 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 on success. * \return \c 0 on success.
* \return An \c MBEDTLS_ERR_ECP_XXX code on failure. * \return An \c MBEDTLS_ERR_ECP_XXX code on failure.
*/ */
int mbedtls_ecdsa_genkey(mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, 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 (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
/** /**
* \brief This function sets an ECDSA context from an EC key pair. * \brief This function sets up an ECDSA context from an EC key pair.
* *
* \see ecp.h * \see ecp.h
* *
* \param ctx The ECDSA context to set. * \param ctx The ECDSA context to setup. This must be initialized.
* \param key The EC key to use. * \param key The EC key to use. This must be initialized and hold
* a private-public key pair or a public key. In the former
* case, the ECDSA context may be used for signature creation
* and verification after this call. In the latter case, it
* may be used for signature verification.
* *
* \return \c 0 on success. * \return \c 0 on success.
* \return An \c MBEDTLS_ERR_ECP_XXX code on failure. * \return An \c MBEDTLS_ERR_ECP_XXX code on failure.
*/ */
int mbedtls_ecdsa_from_keypair(mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key); int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx,
const mbedtls_ecp_keypair *key );
/** /**
* \brief This function initializes an ECDSA context. * \brief This function initializes an ECDSA context.
* *
* \param ctx The ECDSA context to initialize. * \param ctx The ECDSA context to initialize.
* This must not be \c NULL.
*/ */
void mbedtls_ecdsa_init(mbedtls_ecdsa_context *ctx); void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx );
/** /**
* \brief This function frees an ECDSA context. * \brief This function frees an ECDSA context.
* *
* \param ctx The ECDSA context to free. * \param ctx The ECDSA context to free. This may be \c NULL,
* in which case this function does nothing. If it
* is not \c NULL, it must be initialized.
*/ */
void mbedtls_ecdsa_free(mbedtls_ecdsa_context *ctx); void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx );
int ecdsa_signature_to_asn1(const mbedtls_mpi *r, const mbedtls_mpi *s, unsigned char *sig, size_t *slen); #if defined(MBEDTLS_ECP_RESTARTABLE)
/**
* \brief Initialize a restart context.
*
* \param ctx The restart context to initialize.
* This must not be \c NULL.
*/
void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx );
/**
* \brief Free the components of a restart context.
*
* \param ctx The restart context to free. This may be \c NULL,
* in which case this function does nothing. If it
* is not \c NULL, it must be initialized.
*/
void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx );
#endif /* MBEDTLS_ECP_RESTARTABLE */
#ifdef __cplusplus #ifdef __cplusplus
} }

1146
common/mbedtls/ecjpake.c Normal file

File diff suppressed because it is too large Load Diff

275
common/mbedtls/ecjpake.h Normal file
View File

@@ -0,0 +1,275 @@
/**
* \file ecjpake.h
*
* \brief Elliptic curve J-PAKE
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBEDTLS_ECJPAKE_H
#define MBEDTLS_ECJPAKE_H
/*
* J-PAKE is a password-authenticated key exchange that allows deriving a
* strong shared secret from a (potentially low entropy) pre-shared
* passphrase, with forward secrecy and mutual authentication.
* https://en.wikipedia.org/wiki/Password_Authenticated_Key_Exchange_by_Juggling
*
* This file implements the Elliptic Curve variant of J-PAKE,
* as defined in Chapter 7.4 of the Thread v1.0 Specification,
* available to members of the Thread Group http://threadgroup.org/
*
* As the J-PAKE algorithm is inherently symmetric, so is our API.
* Each party needs to send its first round message, in any order, to the
* other party, then each sends its second round message, in any order.
* The payloads are serialized in a way suitable for use in TLS, but could
* also be use outside TLS.
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include "mbedtls/ecp.h"
#include "mbedtls/md.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Roles in the EC J-PAKE exchange
*/
typedef enum {
MBEDTLS_ECJPAKE_CLIENT = 0, /**< Client */
MBEDTLS_ECJPAKE_SERVER, /**< Server */
} mbedtls_ecjpake_role;
#if !defined(MBEDTLS_ECJPAKE_ALT)
/**
* EC J-PAKE context structure.
*
* J-PAKE is a symmetric protocol, except for the identifiers used in
* Zero-Knowledge Proofs, and the serialization of the second message
* (KeyExchange) as defined by the Thread spec.
*
* In order to benefit from this symmetry, we choose a different naming
* convetion from the Thread v1.0 spec. Correspondance is indicated in the
* description as a pair C: client name, S: server name
*/
typedef struct mbedtls_ecjpake_context
{
const mbedtls_md_info_t *md_info; /**< Hash to use */
mbedtls_ecp_group grp; /**< Elliptic curve */
mbedtls_ecjpake_role role; /**< Are we client or server? */
int point_format; /**< Format for point export */
mbedtls_ecp_point Xm1; /**< My public key 1 C: X1, S: X3 */
mbedtls_ecp_point Xm2; /**< My public key 2 C: X2, S: X4 */
mbedtls_ecp_point Xp1; /**< Peer public key 1 C: X3, S: X1 */
mbedtls_ecp_point Xp2; /**< Peer public key 2 C: X4, S: X2 */
mbedtls_ecp_point Xp; /**< Peer public key C: Xs, S: Xc */
mbedtls_mpi xm1; /**< My private key 1 C: x1, S: x3 */
mbedtls_mpi xm2; /**< My private key 2 C: x2, S: x4 */
mbedtls_mpi s; /**< Pre-shared secret (passphrase) */
} mbedtls_ecjpake_context;
#else /* MBEDTLS_ECJPAKE_ALT */
#include "ecjpake_alt.h"
#endif /* MBEDTLS_ECJPAKE_ALT */
/**
* \brief Initialize an ECJPAKE context.
*
* \param ctx The ECJPAKE context to initialize.
* This must not be \c NULL.
*/
void mbedtls_ecjpake_init( mbedtls_ecjpake_context *ctx );
/**
* \brief Set up an ECJPAKE context for use.
*
* \note Currently the only values for hash/curve allowed by the
* standard are #MBEDTLS_MD_SHA256/#MBEDTLS_ECP_DP_SECP256R1.
*
* \param ctx The ECJPAKE context to set up. This must be initialized.
* \param role The role of the caller. This must be either
* #MBEDTLS_ECJPAKE_CLIENT or #MBEDTLS_ECJPAKE_SERVER.
* \param hash The identifier of the hash function to use,
* for example #MBEDTLS_MD_SHA256.
* \param curve The identifier of the elliptic curve to use,
* for example #MBEDTLS_ECP_DP_SECP256R1.
* \param secret The pre-shared secret (passphrase). This must be
* a readable buffer of length \p len Bytes. It need
* only be valid for the duration of this call.
* \param len The length of the pre-shared secret \p secret.
*
* \return \c 0 if successful.
* \return A negative error code on failure.
*/
int mbedtls_ecjpake_setup( mbedtls_ecjpake_context *ctx,
mbedtls_ecjpake_role role,
mbedtls_md_type_t hash,
mbedtls_ecp_group_id curve,
const unsigned char *secret,
size_t len );
/**
* \brief Check if an ECJPAKE context is ready for use.
*
* \param ctx The ECJPAKE context to check. This must be
* initialized.
*
* \return \c 0 if the context is ready for use.
* \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise.
*/
int mbedtls_ecjpake_check( const mbedtls_ecjpake_context *ctx );
/**
* \brief Generate and write the first round message
* (TLS: contents of the Client/ServerHello extension,
* excluding extension type and length bytes).
*
* \param ctx The ECJPAKE context to use. This must be
* initialized and set up.
* \param buf The buffer to write the contents to. This must be a
* writable buffer of length \p len Bytes.
* \param len The length of \p buf in Bytes.
* \param olen The address at which to store the total number
* of Bytes written to \p buf. This must not be \c NULL.
* \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 use a context.
*
* \return \c 0 if successful.
* \return A negative error code on failure.
*/
int mbedtls_ecjpake_write_round_one( mbedtls_ecjpake_context *ctx,
unsigned char *buf, size_t len, size_t *olen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
/**
* \brief Read and process the first round message
* (TLS: contents of the Client/ServerHello extension,
* excluding extension type and length bytes).
*
* \param ctx The ECJPAKE context to use. This must be initialized
* and set up.
* \param buf The buffer holding the first round message. This must
* be a readable buffer of length \p len Bytes.
* \param len The length in Bytes of \p buf.
*
* \return \c 0 if successful.
* \return A negative error code on failure.
*/
int mbedtls_ecjpake_read_round_one( mbedtls_ecjpake_context *ctx,
const unsigned char *buf,
size_t len );
/**
* \brief Generate and write the second round message
* (TLS: contents of the Client/ServerKeyExchange).
*
* \param ctx The ECJPAKE context to use. This must be initialized,
* set up, and already have performed round one.
* \param buf The buffer to write the round two contents to.
* This must be a writable buffer of length \p len Bytes.
* \param len The size of \p buf in Bytes.
* \param olen The address at which to store the total number of Bytes
* written to \p buf. This must not be \c NULL.
* \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 use a context.
*
* \return \c 0 if successful.
* \return A negative error code on failure.
*/
int mbedtls_ecjpake_write_round_two( mbedtls_ecjpake_context *ctx,
unsigned char *buf, size_t len, size_t *olen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
/**
* \brief Read and process the second round message
* (TLS: contents of the Client/ServerKeyExchange).
*
* \param ctx The ECJPAKE context to use. This must be initialized
* and set up and already have performed round one.
* \param buf The buffer holding the second round message. This must
* be a readable buffer of length \p len Bytes.
* \param len The length in Bytes of \p buf.
*
* \return \c 0 if successful.
* \return A negative error code on failure.
*/
int mbedtls_ecjpake_read_round_two( mbedtls_ecjpake_context *ctx,
const unsigned char *buf,
size_t len );
/**
* \brief Derive the shared secret
* (TLS: Pre-Master Secret).
*
* \param ctx The ECJPAKE context to use. This must be initialized,
* set up and have performed both round one and two.
* \param buf The buffer to write the derived secret to. This must
* be a writable buffer of length \p len Bytes.
* \param len The length of \p buf in Bytes.
* \param olen The address at which to store the total number of Bytes
* written to \p buf. This must not be \c NULL.
* \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 use a context.
*
* \return \c 0 if successful.
* \return A negative error code on failure.
*/
int mbedtls_ecjpake_derive_secret( mbedtls_ecjpake_context *ctx,
unsigned char *buf, size_t len, size_t *olen,
int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng );
/**
* \brief This clears an ECJPAKE context and frees any
* embedded data structure.
*
* \param ctx The ECJPAKE context to free. This may be \c NULL,
* in which case this function does nothing. If it is not
* \c NULL, it must point to an initialized ECJPAKE context.
*/
void mbedtls_ecjpake_free( mbedtls_ecjpake_context *ctx );
#if defined(MBEDTLS_SELF_TEST)
/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if a test failed
*/
int mbedtls_ecjpake_self_test( int verbose );
#endif /* MBEDTLS_SELF_TEST */
#ifdef __cplusplus
}
#endif
#endif /* ecjpake.h */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -5,24 +5,20 @@
* point arithmetic. * point arithmetic.
*/ */
/* /*
* Copyright (C) 2016, ARM Limited, All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
/* /*
@@ -63,6 +59,12 @@
#ifndef MBEDTLS_ECP_INTERNAL_H #ifndef MBEDTLS_ECP_INTERNAL_H
#define MBEDTLS_ECP_INTERNAL_H #define MBEDTLS_ECP_INTERNAL_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_ECP_INTERNAL_ALT) #if defined(MBEDTLS_ECP_INTERNAL_ALT)
/** /**
@@ -74,7 +76,7 @@
* *
* \return Non-zero if successful. * \return Non-zero if successful.
*/ */
unsigned char mbedtls_internal_ecp_grp_capable(const mbedtls_ecp_group *grp); unsigned char mbedtls_internal_ecp_grp_capable( const mbedtls_ecp_group *grp );
/** /**
* \brief Initialise the Elliptic Curve Point module extension. * \brief Initialise the Elliptic Curve Point module extension.
@@ -91,7 +93,7 @@ unsigned char mbedtls_internal_ecp_grp_capable(const mbedtls_ecp_group *grp);
* *
* \return 0 if successful. * \return 0 if successful.
*/ */
int mbedtls_internal_ecp_init(const mbedtls_ecp_group *grp); int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp );
/** /**
* \brief Frees and deallocates the Elliptic Curve Point module * \brief Frees and deallocates the Elliptic Curve Point module
@@ -99,9 +101,9 @@ int mbedtls_internal_ecp_init(const mbedtls_ecp_group *grp);
* *
* \param grp The pointer to the group the module was initialised for. * \param grp The pointer to the group the module was initialised for.
*/ */
void mbedtls_internal_ecp_free(const mbedtls_ecp_group *grp); void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp );
#if defined(ECP_SHORTWEIERSTRASS) #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) #if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
/** /**
@@ -119,9 +121,9 @@ void mbedtls_internal_ecp_free(const mbedtls_ecp_group *grp);
* *
* \return 0 if successful. * \return 0 if successful.
*/ */
int mbedtls_internal_ecp_randomize_jac(const mbedtls_ecp_group *grp, int mbedtls_internal_ecp_randomize_jac( const mbedtls_ecp_group *grp,
mbedtls_ecp_point *pt, int (*f_rng)(void *, unsigned char *, size_t), mbedtls_ecp_point *pt, int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng); void *p_rng );
#endif #endif
#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) #if defined(MBEDTLS_ECP_ADD_MIXED_ALT)
@@ -164,9 +166,9 @@ int mbedtls_internal_ecp_randomize_jac(const mbedtls_ecp_group *grp,
* *
* \return 0 if successful. * \return 0 if successful.
*/ */
int mbedtls_internal_ecp_add_mixed(const mbedtls_ecp_group *grp, int mbedtls_internal_ecp_add_mixed( const mbedtls_ecp_group *grp,
mbedtls_ecp_point *R, const mbedtls_ecp_point *P, mbedtls_ecp_point *R, const mbedtls_ecp_point *P,
const mbedtls_ecp_point *Q); const mbedtls_ecp_point *Q );
#endif #endif
/** /**
@@ -189,8 +191,8 @@ int mbedtls_internal_ecp_add_mixed(const mbedtls_ecp_group *grp,
* \return 0 if successful. * \return 0 if successful.
*/ */
#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) #if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)
int mbedtls_internal_ecp_double_jac(const mbedtls_ecp_group *grp, int mbedtls_internal_ecp_double_jac( const mbedtls_ecp_group *grp,
mbedtls_ecp_point *R, const mbedtls_ecp_point *P); mbedtls_ecp_point *R, const mbedtls_ecp_point *P );
#endif #endif
/** /**
@@ -219,8 +221,8 @@ int mbedtls_internal_ecp_double_jac(const mbedtls_ecp_group *grp,
* an error if one of the points is zero. * an error if one of the points is zero.
*/ */
#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) #if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)
int mbedtls_internal_ecp_normalize_jac_many(const mbedtls_ecp_group *grp, int mbedtls_internal_ecp_normalize_jac_many( const mbedtls_ecp_group *grp,
mbedtls_ecp_point *T[], size_t t_len); mbedtls_ecp_point *T[], size_t t_len );
#endif #endif
/** /**
@@ -237,18 +239,18 @@ int mbedtls_internal_ecp_normalize_jac_many(const mbedtls_ecp_group *grp,
* \return 0 if successful. * \return 0 if successful.
*/ */
#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) #if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)
int mbedtls_internal_ecp_normalize_jac(const mbedtls_ecp_group *grp, int mbedtls_internal_ecp_normalize_jac( const mbedtls_ecp_group *grp,
mbedtls_ecp_point *pt); mbedtls_ecp_point *pt );
#endif #endif
#endif /* ECP_SHORTWEIERSTRASS */ #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */
#if defined(ECP_MONTGOMERY) #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) #if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
int mbedtls_internal_ecp_double_add_mxz(const mbedtls_ecp_group *grp, 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, mbedtls_ecp_point *R, mbedtls_ecp_point *S, const mbedtls_ecp_point *P,
const mbedtls_ecp_point *Q, const mbedtls_mpi *d); const mbedtls_ecp_point *Q, const mbedtls_mpi *d );
#endif #endif
/** /**
@@ -267,9 +269,9 @@ int mbedtls_internal_ecp_double_add_mxz(const mbedtls_ecp_group *grp,
* \return 0 if successful * \return 0 if successful
*/ */
#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) #if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)
int mbedtls_internal_ecp_randomize_mxz(const mbedtls_ecp_group *grp, int mbedtls_internal_ecp_randomize_mxz( const mbedtls_ecp_group *grp,
mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t),
void *p_rng); void *p_rng );
#endif #endif
/** /**
@@ -283,11 +285,11 @@ int mbedtls_internal_ecp_randomize_mxz(const mbedtls_ecp_group *grp,
* \return 0 if successful * \return 0 if successful
*/ */
#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) #if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
int mbedtls_internal_ecp_normalize_mxz(const mbedtls_ecp_group *grp, int mbedtls_internal_ecp_normalize_mxz( const mbedtls_ecp_group *grp,
mbedtls_ecp_point *P); mbedtls_ecp_point *P );
#endif #endif
#endif /* ECP_MONTGOMERY */ #endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */
#endif /* MBEDTLS_ECP_INTERNAL_ALT */ #endif /* MBEDTLS_ECP_INTERNAL_ALT */

View File

@@ -1,31 +1,23 @@
/* /*
* Entropy accumulator implementation * Entropy accumulator implementation
* *
* Copyright (C) 2006-2016, ARM Limited, All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
#if !defined(MBEDTLS_CONFIG_FILE) #include "common.h"
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_ENTROPY_C) #if defined(MBEDTLS_ENTROPY_C)
@@ -38,6 +30,7 @@
#include "mbedtls/entropy.h" #include "mbedtls/entropy.h"
#include "mbedtls/entropy_poll.h" #include "mbedtls/entropy_poll.h"
#include "mbedtls/platform_util.h" #include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#include <string.h> #include <string.h>
@@ -64,94 +57,103 @@
#define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */ #define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */
void mbedtls_entropy_init(mbedtls_entropy_context *ctx) { void mbedtls_entropy_init( mbedtls_entropy_context *ctx )
{
ctx->source_count = 0; ctx->source_count = 0;
memset(ctx->source, 0, sizeof(ctx->source)); memset( ctx->source, 0, sizeof( ctx->source ) );
#if defined(MBEDTLS_THREADING_C) #if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_init(&ctx->mutex); mbedtls_mutex_init( &ctx->mutex );
#endif #endif
ctx->accumulator_started = 0; ctx->accumulator_started = 0;
#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
mbedtls_sha512_init(&ctx->accumulator); mbedtls_sha512_init( &ctx->accumulator );
#else #else
mbedtls_sha256_init(&ctx->accumulator); mbedtls_sha256_init( &ctx->accumulator );
#endif #endif
#if defined(MBEDTLS_HAVEGE_C) #if defined(MBEDTLS_HAVEGE_C)
mbedtls_havege_init(&ctx->havege_data); mbedtls_havege_init( &ctx->havege_data );
#endif #endif
/* Reminder: Update ENTROPY_HAVE_STRONG in the test files /* Reminder: Update ENTROPY_HAVE_STRONG in the test files
* when adding more strong entropy sources here. */ * when adding more strong entropy sources here. */
#if defined(MBEDTLS_TEST_NULL_ENTROPY) #if defined(MBEDTLS_TEST_NULL_ENTROPY)
mbedtls_entropy_add_source(ctx, mbedtls_null_entropy_poll, NULL, mbedtls_entropy_add_source( ctx, mbedtls_null_entropy_poll, NULL,
1, MBEDTLS_ENTROPY_SOURCE_STRONG); 1, MBEDTLS_ENTROPY_SOURCE_STRONG );
#endif #endif
#if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) #if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES)
#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
mbedtls_entropy_add_source(ctx, mbedtls_platform_entropy_poll, NULL, mbedtls_entropy_add_source( ctx, mbedtls_platform_entropy_poll, NULL,
MBEDTLS_ENTROPY_MIN_PLATFORM, MBEDTLS_ENTROPY_MIN_PLATFORM,
MBEDTLS_ENTROPY_SOURCE_STRONG); MBEDTLS_ENTROPY_SOURCE_STRONG );
#endif #endif
#if defined(MBEDTLS_TIMING_C) #if defined(MBEDTLS_TIMING_C)
mbedtls_entropy_add_source(ctx, mbedtls_hardclock_poll, NULL, mbedtls_entropy_add_source( ctx, mbedtls_hardclock_poll, NULL,
MBEDTLS_ENTROPY_MIN_HARDCLOCK, MBEDTLS_ENTROPY_MIN_HARDCLOCK,
MBEDTLS_ENTROPY_SOURCE_WEAK); MBEDTLS_ENTROPY_SOURCE_WEAK );
#endif #endif
#if defined(MBEDTLS_HAVEGE_C) #if defined(MBEDTLS_HAVEGE_C)
mbedtls_entropy_add_source(ctx, mbedtls_havege_poll, &ctx->havege_data, mbedtls_entropy_add_source( ctx, mbedtls_havege_poll, &ctx->havege_data,
MBEDTLS_ENTROPY_MIN_HAVEGE, MBEDTLS_ENTROPY_MIN_HAVEGE,
MBEDTLS_ENTROPY_SOURCE_STRONG); MBEDTLS_ENTROPY_SOURCE_STRONG );
#endif #endif
#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
mbedtls_entropy_add_source(ctx, mbedtls_hardware_poll, NULL, mbedtls_entropy_add_source( ctx, mbedtls_hardware_poll, NULL,
MBEDTLS_ENTROPY_MIN_HARDWARE, MBEDTLS_ENTROPY_MIN_HARDWARE,
MBEDTLS_ENTROPY_SOURCE_STRONG); MBEDTLS_ENTROPY_SOURCE_STRONG );
#endif #endif
#if defined(MBEDTLS_ENTROPY_NV_SEED) #if defined(MBEDTLS_ENTROPY_NV_SEED)
mbedtls_entropy_add_source(ctx, mbedtls_nv_seed_poll, NULL, mbedtls_entropy_add_source( ctx, mbedtls_nv_seed_poll, NULL,
MBEDTLS_ENTROPY_BLOCK_SIZE, MBEDTLS_ENTROPY_BLOCK_SIZE,
MBEDTLS_ENTROPY_SOURCE_STRONG); MBEDTLS_ENTROPY_SOURCE_STRONG );
ctx->initial_entropy_run = 0; ctx->initial_entropy_run = 0;
#endif #endif
#endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ #endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */
} }
void mbedtls_entropy_free(mbedtls_entropy_context *ctx) { void mbedtls_entropy_free( mbedtls_entropy_context *ctx )
{
/* 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_HAVEGE_C) #if defined(MBEDTLS_HAVEGE_C)
mbedtls_havege_free(&ctx->havege_data); mbedtls_havege_free( &ctx->havege_data );
#endif #endif
#if defined(MBEDTLS_THREADING_C) #if defined(MBEDTLS_THREADING_C)
mbedtls_mutex_free(&ctx->mutex); mbedtls_mutex_free( &ctx->mutex );
#endif #endif
#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
mbedtls_sha512_free(&ctx->accumulator); mbedtls_sha512_free( &ctx->accumulator );
#else #else
mbedtls_sha256_free(&ctx->accumulator); mbedtls_sha256_free( &ctx->accumulator );
#endif #endif
#if defined(MBEDTLS_ENTROPY_NV_SEED) #if defined(MBEDTLS_ENTROPY_NV_SEED)
ctx->initial_entropy_run = 0; ctx->initial_entropy_run = 0;
#endif #endif
ctx->source_count = 0; ctx->source_count = 0;
mbedtls_platform_zeroize(ctx->source, sizeof(ctx->source)); mbedtls_platform_zeroize( ctx->source, sizeof( ctx->source ) );
ctx->accumulator_started = 0; ctx->accumulator_started = -1;
} }
int mbedtls_entropy_add_source(mbedtls_entropy_context *ctx, int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx,
mbedtls_entropy_f_source_ptr f_source, void *p_source, mbedtls_entropy_f_source_ptr f_source, void *p_source,
size_t threshold, int strong) { size_t threshold, int strong )
{
int idx, ret = 0; int idx, ret = 0;
#if defined(MBEDTLS_THREADING_C) #if defined(MBEDTLS_THREADING_C)
if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
return (ret); return( ret );
#endif #endif
idx = ctx->source_count; idx = ctx->source_count;
if (idx >= MBEDTLS_ENTROPY_MAX_SOURCES) { if( idx >= MBEDTLS_ENTROPY_MAX_SOURCES )
{
ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES; ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES;
goto exit; goto exit;
} }
@@ -165,30 +167,32 @@ int mbedtls_entropy_add_source(mbedtls_entropy_context *ctx,
exit: exit:
#if defined(MBEDTLS_THREADING_C) #if defined(MBEDTLS_THREADING_C)
if (mbedtls_mutex_unlock(&ctx->mutex) != 0) if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
return (MBEDTLS_ERR_THREADING_MUTEX_ERROR); return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
#endif #endif
return (ret); return( ret );
} }
/* /*
* Entropy accumulator update * Entropy accumulator update
*/ */
static int entropy_update(mbedtls_entropy_context *ctx, unsigned char source_id, static int entropy_update( mbedtls_entropy_context *ctx, unsigned char source_id,
const unsigned char *data, size_t len) { const unsigned char *data, size_t len )
{
unsigned char header[2]; unsigned char header[2];
unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE]; unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE];
size_t use_len = len; size_t use_len = len;
const unsigned char *p = data; const unsigned char *p = data;
int ret = 0; int ret = 0;
if (use_len > MBEDTLS_ENTROPY_BLOCK_SIZE) { if( use_len > MBEDTLS_ENTROPY_BLOCK_SIZE )
{
#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
if ((ret = mbedtls_sha512_ret(data, len, tmp, 0)) != 0) if( ( ret = mbedtls_sha512_ret( data, len, tmp, 0 ) ) != 0 )
goto cleanup; goto cleanup;
#else #else
if ((ret = mbedtls_sha256_ret(data, len, tmp, 0)) != 0) if( ( ret = mbedtls_sha256_ret( data, len, tmp, 0 ) ) != 0 )
goto cleanup; goto cleanup;
#endif #endif
p = tmp; p = tmp;
@@ -204,158 +208,177 @@ static int entropy_update(mbedtls_entropy_context *ctx, unsigned char source_id,
* gather entropy eventually execute this code. * gather entropy eventually execute this code.
*/ */
#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
if (ctx->accumulator_started == 0 && if( ctx->accumulator_started == 0 &&
(ret = mbedtls_sha512_starts_ret(&ctx->accumulator, 0)) != 0) ( ret = mbedtls_sha512_starts_ret( &ctx->accumulator, 0 ) ) != 0 )
goto cleanup; goto cleanup;
else else
ctx->accumulator_started = 1; ctx->accumulator_started = 1;
if ((ret = mbedtls_sha512_update_ret(&ctx->accumulator, header, 2)) != 0) if( ( ret = mbedtls_sha512_update_ret( &ctx->accumulator, header, 2 ) ) != 0 )
goto cleanup; goto cleanup;
ret = mbedtls_sha512_update_ret(&ctx->accumulator, p, use_len); ret = mbedtls_sha512_update_ret( &ctx->accumulator, p, use_len );
#else #else
if (ctx->accumulator_started == 0 && if( ctx->accumulator_started == 0 &&
(ret = mbedtls_sha256_starts_ret(&ctx->accumulator, 0)) != 0) ( ret = mbedtls_sha256_starts_ret( &ctx->accumulator, 0 ) ) != 0 )
goto cleanup; goto cleanup;
else else
ctx->accumulator_started = 1; ctx->accumulator_started = 1;
if ((ret = mbedtls_sha256_update_ret(&ctx->accumulator, header, 2)) != 0) if( ( ret = mbedtls_sha256_update_ret( &ctx->accumulator, header, 2 ) ) != 0 )
goto cleanup; goto cleanup;
ret = mbedtls_sha256_update_ret(&ctx->accumulator, p, use_len); ret = mbedtls_sha256_update_ret( &ctx->accumulator, p, use_len );
#endif #endif
cleanup: cleanup:
mbedtls_platform_zeroize(tmp, sizeof(tmp)); mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
return (ret); return( ret );
} }
int mbedtls_entropy_update_manual(mbedtls_entropy_context *ctx, int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx,
const unsigned char *data, size_t len) { const unsigned char *data, size_t len )
int ret; {
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_THREADING_C) #if defined(MBEDTLS_THREADING_C)
if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
return (ret); return( ret );
#endif #endif
ret = entropy_update(ctx, MBEDTLS_ENTROPY_SOURCE_MANUAL, data, len); ret = entropy_update( ctx, MBEDTLS_ENTROPY_SOURCE_MANUAL, data, len );
#if defined(MBEDTLS_THREADING_C) #if defined(MBEDTLS_THREADING_C)
if (mbedtls_mutex_unlock(&ctx->mutex) != 0) if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
return (MBEDTLS_ERR_THREADING_MUTEX_ERROR); return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
#endif #endif
return (ret); return( ret );
} }
/* /*
* Run through the different sources to add entropy to our accumulator * Run through the different sources to add entropy to our accumulator
*/ */
static int entropy_gather_internal(mbedtls_entropy_context *ctx) { static int entropy_gather_internal( mbedtls_entropy_context *ctx )
int ret, i, have_one_strong = 0; {
int ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
int i;
int have_one_strong = 0;
unsigned char buf[MBEDTLS_ENTROPY_MAX_GATHER]; unsigned char buf[MBEDTLS_ENTROPY_MAX_GATHER];
size_t olen; size_t olen;
if (ctx->source_count == 0) if( ctx->source_count == 0 )
return (MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED); return( MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED );
/* /*
* Run through our entropy sources * Run through our entropy sources
*/ */
for (i = 0; i < ctx->source_count; i++) { for( i = 0; i < ctx->source_count; i++ )
if (ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG) {
if( ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG )
have_one_strong = 1; have_one_strong = 1;
olen = 0; olen = 0;
if ((ret = ctx->source[i].f_source(ctx->source[i].p_source, if( ( ret = ctx->source[i].f_source( ctx->source[i].p_source,
buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen)) != 0) { buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen ) ) != 0 )
{
goto cleanup; goto cleanup;
} }
/* /*
* Add if we actually gathered something * Add if we actually gathered something
*/ */
if (olen > 0) { if( olen > 0 )
if ((ret = entropy_update(ctx, (unsigned char) i, {
buf, olen)) != 0) if( ( ret = entropy_update( ctx, (unsigned char) i,
return (ret); buf, olen ) ) != 0 )
return( ret );
ctx->source[i].size += olen; ctx->source[i].size += olen;
} }
} }
if (have_one_strong == 0) if( have_one_strong == 0 )
ret = MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE; ret = MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE;
cleanup: cleanup:
mbedtls_platform_zeroize(buf, sizeof(buf)); mbedtls_platform_zeroize( buf, sizeof( buf ) );
return (ret); return( ret );
} }
/* /*
* Thread-safe wrapper for entropy_gather_internal() * Thread-safe wrapper for entropy_gather_internal()
*/ */
int mbedtls_entropy_gather(mbedtls_entropy_context *ctx) { int mbedtls_entropy_gather( mbedtls_entropy_context *ctx )
int ret; {
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
#if defined(MBEDTLS_THREADING_C) #if defined(MBEDTLS_THREADING_C)
if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
return (ret); return( ret );
#endif #endif
ret = entropy_gather_internal(ctx); ret = entropy_gather_internal( ctx );
#if defined(MBEDTLS_THREADING_C) #if defined(MBEDTLS_THREADING_C)
if (mbedtls_mutex_unlock(&ctx->mutex) != 0) if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
return (MBEDTLS_ERR_THREADING_MUTEX_ERROR); return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
#endif #endif
return (ret); return( ret );
} }
int mbedtls_entropy_func(void *data, unsigned char *output, size_t len) { int mbedtls_entropy_func( void *data, unsigned char *output, size_t len )
int ret, count = 0, i, done; {
int ret, count = 0, i, thresholds_reached;
size_t strong_size;
mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data; mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data;
unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
if (len > MBEDTLS_ENTROPY_BLOCK_SIZE) if( len > MBEDTLS_ENTROPY_BLOCK_SIZE )
return (MBEDTLS_ERR_ENTROPY_SOURCE_FAILED); return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
#if defined(MBEDTLS_ENTROPY_NV_SEED) #if defined(MBEDTLS_ENTROPY_NV_SEED)
/* Update the NV entropy seed before generating any entropy for outside /* Update the NV entropy seed before generating any entropy for outside
* use. * use.
*/ */
if (ctx->initial_entropy_run == 0) { if( ctx->initial_entropy_run == 0 )
{
ctx->initial_entropy_run = 1; ctx->initial_entropy_run = 1;
if ((ret = mbedtls_entropy_update_nv_seed(ctx)) != 0) if( ( ret = mbedtls_entropy_update_nv_seed( ctx ) ) != 0 )
return (ret); return( ret );
} }
#endif #endif
#if defined(MBEDTLS_THREADING_C) #if defined(MBEDTLS_THREADING_C)
if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 )
return (ret); return( ret );
#endif #endif
/* /*
* Always gather extra entropy before a call * Always gather extra entropy before a call
*/ */
do { do
if (count++ > ENTROPY_MAX_LOOP) { {
if( count++ > ENTROPY_MAX_LOOP )
{
ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
goto exit; goto exit;
} }
if ((ret = entropy_gather_internal(ctx)) != 0) if( ( ret = entropy_gather_internal( ctx ) ) != 0 )
goto exit; goto exit;
done = 1; thresholds_reached = 1;
for (i = 0; i < ctx->source_count; i++) strong_size = 0;
if (ctx->source[i].size < ctx->source[i].threshold) for( i = 0; i < ctx->source_count; i++ )
done = 0; {
} while (! done); 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); memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
/* /*
@@ -363,100 +386,103 @@ int mbedtls_entropy_func(void *data, unsigned char *output, size_t len) {
* in a previous call to entropy_update(). If this is not guaranteed, the * in a previous call to entropy_update(). If this is not guaranteed, the
* code below will fail. * code below will fail.
*/ */
if ((ret = mbedtls_sha512_finish_ret(&ctx->accumulator, buf)) != 0) if( ( ret = mbedtls_sha512_finish_ret( &ctx->accumulator, buf ) ) != 0 )
goto exit; goto exit;
/* /*
* Reset accumulator and counters and recycle existing entropy * Reset accumulator and counters and recycle existing entropy
*/ */
mbedtls_sha512_free(&ctx->accumulator); mbedtls_sha512_free( &ctx->accumulator );
mbedtls_sha512_init(&ctx->accumulator); mbedtls_sha512_init( &ctx->accumulator );
if ((ret = mbedtls_sha512_starts_ret(&ctx->accumulator, 0)) != 0) if( ( ret = mbedtls_sha512_starts_ret( &ctx->accumulator, 0 ) ) != 0 )
goto exit; goto exit;
if ((ret = mbedtls_sha512_update_ret(&ctx->accumulator, buf, if( ( ret = mbedtls_sha512_update_ret( &ctx->accumulator, buf,
MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 )
goto exit; goto exit;
/* /*
* Perform second SHA-512 on entropy * Perform second SHA-512 on entropy
*/ */
if ((ret = mbedtls_sha512_ret(buf, MBEDTLS_ENTROPY_BLOCK_SIZE, if( ( ret = mbedtls_sha512_ret( buf, MBEDTLS_ENTROPY_BLOCK_SIZE,
buf, 0)) != 0) buf, 0 ) ) != 0 )
goto exit; goto exit;
#else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ #else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */
if ((ret = mbedtls_sha256_finish_ret(&ctx->accumulator, buf)) != 0) if( ( ret = mbedtls_sha256_finish_ret( &ctx->accumulator, buf ) ) != 0 )
goto exit; goto exit;
/* /*
* Reset accumulator and counters and recycle existing entropy * Reset accumulator and counters and recycle existing entropy
*/ */
mbedtls_sha256_free(&ctx->accumulator); mbedtls_sha256_free( &ctx->accumulator );
mbedtls_sha256_init(&ctx->accumulator); mbedtls_sha256_init( &ctx->accumulator );
if ((ret = mbedtls_sha256_starts_ret(&ctx->accumulator, 0)) != 0) if( ( ret = mbedtls_sha256_starts_ret( &ctx->accumulator, 0 ) ) != 0 )
goto exit; goto exit;
if ((ret = mbedtls_sha256_update_ret(&ctx->accumulator, buf, if( ( ret = mbedtls_sha256_update_ret( &ctx->accumulator, buf,
MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 )
goto exit; goto exit;
/* /*
* Perform second SHA-256 on entropy * Perform second SHA-256 on entropy
*/ */
if ((ret = mbedtls_sha256_ret(buf, MBEDTLS_ENTROPY_BLOCK_SIZE, if( ( ret = mbedtls_sha256_ret( buf, MBEDTLS_ENTROPY_BLOCK_SIZE,
buf, 0)) != 0) buf, 0 ) ) != 0 )
goto exit; goto exit;
#endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ #endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */
for (i = 0; i < ctx->source_count; i++) for( i = 0; i < ctx->source_count; i++ )
ctx->source[i].size = 0; ctx->source[i].size = 0;
memcpy(output, buf, len); memcpy( output, buf, len );
ret = 0; ret = 0;
exit: exit:
mbedtls_platform_zeroize(buf, sizeof(buf)); mbedtls_platform_zeroize( buf, sizeof( buf ) );
#if defined(MBEDTLS_THREADING_C) #if defined(MBEDTLS_THREADING_C)
if (mbedtls_mutex_unlock(&ctx->mutex) != 0) if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 )
return (MBEDTLS_ERR_THREADING_MUTEX_ERROR); return( MBEDTLS_ERR_THREADING_MUTEX_ERROR );
#endif #endif
return (ret); return( ret );
} }
#if defined(MBEDTLS_ENTROPY_NV_SEED) #if defined(MBEDTLS_ENTROPY_NV_SEED)
int mbedtls_entropy_update_nv_seed(mbedtls_entropy_context *ctx) { int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx )
{
int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
/* Read new seed and write it to NV */ /* Read new seed and write it to NV */
if ((ret = mbedtls_entropy_func(ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 )
return (ret); return( ret );
if (mbedtls_nv_seed_write(buf, MBEDTLS_ENTROPY_BLOCK_SIZE) < 0) if( mbedtls_nv_seed_write( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 )
return (MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR); return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR );
/* Manually update the remaining stream with a separator value to diverge */ /* Manually update the remaining stream with a separator value to diverge */
memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE); memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
ret = mbedtls_entropy_update_manual(ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE); ret = mbedtls_entropy_update_manual( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE );
return (ret); return( ret );
} }
#endif /* MBEDTLS_ENTROPY_NV_SEED */ #endif /* MBEDTLS_ENTROPY_NV_SEED */
#if defined(MBEDTLS_FS_IO) #if defined(MBEDTLS_FS_IO)
int mbedtls_entropy_write_seed_file(mbedtls_entropy_context *ctx, const char *path) { int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path )
{
int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
FILE *f; FILE *f;
unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
if ((f = fopen(path, "wb")) == NULL) if( ( f = fopen( path, "wb" ) ) == NULL )
return (MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR); return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR );
if ((ret = mbedtls_entropy_func(ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 )
goto exit; goto exit;
if (fwrite(buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f) != MBEDTLS_ENTROPY_BLOCK_SIZE) { if( fwrite( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) != MBEDTLS_ENTROPY_BLOCK_SIZE )
{
ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
goto exit; goto exit;
} }
@@ -464,41 +490,42 @@ int mbedtls_entropy_write_seed_file(mbedtls_entropy_context *ctx, const char *pa
ret = 0; ret = 0;
exit: exit:
mbedtls_platform_zeroize(buf, sizeof(buf)); mbedtls_platform_zeroize( buf, sizeof( buf ) );
fclose(f); fclose( f );
return (ret); return( ret );
} }
int mbedtls_entropy_update_seed_file(mbedtls_entropy_context *ctx, const char *path) { int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path )
{
int ret = 0; int ret = 0;
FILE *f; FILE *f;
size_t n; size_t n;
unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ]; unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ];
if ((f = fopen(path, "rb")) == NULL) if( ( f = fopen( path, "rb" ) ) == NULL )
return (MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR); return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR );
fseek(f, 0, SEEK_END); fseek( f, 0, SEEK_END );
n = (size_t) ftell(f); n = (size_t) ftell( f );
fseek(f, 0, SEEK_SET); fseek( f, 0, SEEK_SET );
if (n > MBEDTLS_ENTROPY_MAX_SEED_SIZE) if( n > MBEDTLS_ENTROPY_MAX_SEED_SIZE )
n = MBEDTLS_ENTROPY_MAX_SEED_SIZE; n = MBEDTLS_ENTROPY_MAX_SEED_SIZE;
if (fread(buf, 1, n, f) != n) if( fread( buf, 1, n, f ) != n )
ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
else else
ret = mbedtls_entropy_update_manual(ctx, buf, n); ret = mbedtls_entropy_update_manual( ctx, buf, n );
fclose(f); fclose( f );
mbedtls_platform_zeroize(buf, sizeof(buf)); mbedtls_platform_zeroize( buf, sizeof( buf ) );
if (ret != 0) if( ret != 0 )
return (ret); return( ret );
return (mbedtls_entropy_write_seed_file(ctx, path)); return( mbedtls_entropy_write_seed_file( ctx, path ) );
} }
#endif /* MBEDTLS_FS_IO */ #endif /* MBEDTLS_FS_IO */
@@ -507,54 +534,60 @@ int mbedtls_entropy_update_seed_file(mbedtls_entropy_context *ctx, const char *p
/* /*
* Dummy source function * Dummy source function
*/ */
static int entropy_dummy_source(void *data, unsigned char *output, static int entropy_dummy_source( void *data, unsigned char *output,
size_t len, size_t *olen) { size_t len, size_t *olen )
{
((void) data); ((void) data);
memset(output, 0x2a, len); memset( output, 0x2a, len );
*olen = len; *olen = len;
return (0); return( 0 );
} }
#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ #endif /* !MBEDTLS_TEST_NULL_ENTROPY */
#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
static int mbedtls_entropy_source_self_test_gather(unsigned char *buf, size_t buf_len) { static int mbedtls_entropy_source_self_test_gather( unsigned char *buf, size_t buf_len )
{
int ret = 0; int ret = 0;
size_t entropy_len = 0; size_t entropy_len = 0;
size_t olen = 0; size_t olen = 0;
size_t attempts = buf_len; size_t attempts = buf_len;
while (attempts > 0 && entropy_len < buf_len) { while( attempts > 0 && entropy_len < buf_len )
if ((ret = mbedtls_hardware_poll(NULL, buf + entropy_len, {
buf_len - entropy_len, &olen)) != 0) if( ( ret = mbedtls_hardware_poll( NULL, buf + entropy_len,
return (ret); buf_len - entropy_len, &olen ) ) != 0 )
return( ret );
entropy_len += olen; entropy_len += olen;
attempts--; attempts--;
} }
if (entropy_len < buf_len) { if( entropy_len < buf_len )
{
ret = 1; ret = 1;
} }
return (ret); return( ret );
} }
static int mbedtls_entropy_source_self_test_check_bits(const unsigned char *buf, static int mbedtls_entropy_source_self_test_check_bits( const unsigned char *buf,
size_t buf_len) { size_t buf_len )
unsigned char set = 0xFF; {
unsigned char set= 0xFF;
unsigned char unset = 0x00; unsigned char unset = 0x00;
size_t i; size_t i;
for (i = 0; i < buf_len; i++) { for( i = 0; i < buf_len; i++ )
{
set &= buf[i]; set &= buf[i];
unset |= buf[i]; unset |= buf[i];
} }
return (set == 0xFF || unset == 0x00); return( set == 0xFF || unset == 0x00 );
} }
/* /*
@@ -568,43 +601,45 @@ static int mbedtls_entropy_source_self_test_check_bits(const unsigned char *buf,
* are not equal. * are not equal.
* - The error code returned by the entropy source is not an error. * - The error code returned by the entropy source is not an error.
*/ */
int mbedtls_entropy_source_self_test(int verbose) { int mbedtls_entropy_source_self_test( int verbose )
{
int ret = 0; int ret = 0;
unsigned char buf0[2 * sizeof(unsigned long long int)]; unsigned char buf0[2 * sizeof( unsigned long long int )];
unsigned char buf1[2 * sizeof(unsigned long long int)]; unsigned char buf1[2 * sizeof( unsigned long long int )];
if (verbose != 0) if( verbose != 0 )
mbedtls_printf(" ENTROPY_BIAS test: "); mbedtls_printf( " ENTROPY_BIAS test: " );
memset(buf0, 0x00, sizeof(buf0)); memset( buf0, 0x00, sizeof( buf0 ) );
memset(buf1, 0x00, sizeof(buf1)); memset( buf1, 0x00, sizeof( buf1 ) );
if ((ret = mbedtls_entropy_source_self_test_gather(buf0, sizeof(buf0))) != 0) if( ( ret = mbedtls_entropy_source_self_test_gather( buf0, sizeof( buf0 ) ) ) != 0 )
goto cleanup; goto cleanup;
if ((ret = mbedtls_entropy_source_self_test_gather(buf1, sizeof(buf1))) != 0) if( ( ret = mbedtls_entropy_source_self_test_gather( buf1, sizeof( buf1 ) ) ) != 0 )
goto cleanup; goto cleanup;
/* Make sure that the returned values are not all 0 or 1 */ /* 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) if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf0, sizeof( buf0 ) ) ) != 0 )
goto cleanup; goto cleanup;
if ((ret = mbedtls_entropy_source_self_test_check_bits(buf1, sizeof(buf1))) != 0) if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf1, sizeof( buf1 ) ) ) != 0 )
goto cleanup; goto cleanup;
/* Make sure that the entropy source is not returning values in a /* Make sure that the entropy source is not returning values in a
* pattern */ * pattern */
ret = memcmp(buf0, buf1, sizeof(buf0)) == 0; ret = memcmp( buf0, buf1, sizeof( buf0 ) ) == 0;
cleanup: cleanup:
if (verbose != 0) { if( verbose != 0 )
if (ret != 0) {
mbedtls_printf("failed\n"); if( ret != 0 )
mbedtls_printf( "failed\n" );
else else
mbedtls_printf("passed\n"); mbedtls_printf( "passed\n" );
mbedtls_printf("\n"); mbedtls_printf( "\n" );
} }
return (ret != 0); return( ret != 0 );
} }
#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ #endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */
@@ -614,7 +649,8 @@ cleanup:
* test that the functions don't cause errors and write the correct * test that the functions don't cause errors and write the correct
* amount of data to buffers. * amount of data to buffers.
*/ */
int mbedtls_entropy_self_test(int verbose) { int mbedtls_entropy_self_test( int verbose )
{
int ret = 1; int ret = 1;
#if !defined(MBEDTLS_TEST_NULL_ENTROPY) #if !defined(MBEDTLS_TEST_NULL_ENTROPY)
mbedtls_entropy_context ctx; mbedtls_entropy_context ctx;
@@ -623,22 +659,22 @@ int mbedtls_entropy_self_test(int verbose) {
size_t i, j; size_t i, j;
#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ #endif /* !MBEDTLS_TEST_NULL_ENTROPY */
if (verbose != 0) if( verbose != 0 )
mbedtls_printf(" ENTROPY test: "); mbedtls_printf( " ENTROPY test: " );
#if !defined(MBEDTLS_TEST_NULL_ENTROPY) #if !defined(MBEDTLS_TEST_NULL_ENTROPY)
mbedtls_entropy_init(&ctx); mbedtls_entropy_init( &ctx );
/* First do a gather to make sure we have default sources */ /* First do a gather to make sure we have default sources */
if ((ret = mbedtls_entropy_gather(&ctx)) != 0) if( ( ret = mbedtls_entropy_gather( &ctx ) ) != 0 )
goto cleanup; goto cleanup;
ret = mbedtls_entropy_add_source(&ctx, entropy_dummy_source, NULL, 16, ret = mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL, 16,
MBEDTLS_ENTROPY_SOURCE_WEAK); MBEDTLS_ENTROPY_SOURCE_WEAK );
if (ret != 0) if( ret != 0 )
goto cleanup; goto cleanup;
if ((ret = mbedtls_entropy_update_manual(&ctx, buf, sizeof buf)) != 0) if( ( ret = mbedtls_entropy_update_manual( &ctx, buf, sizeof buf ) ) != 0 )
goto cleanup; goto cleanup;
/* /*
@@ -649,40 +685,44 @@ int mbedtls_entropy_self_test(int verbose) {
* each of the 32 or 64 bytes to be non-zero has a false failure rate * each of the 32 or 64 bytes to be non-zero has a false failure rate
* of at most 2^(-58) which is acceptable. * of at most 2^(-58) which is acceptable.
*/ */
for (i = 0; i < 8; i++) { for( i = 0; i < 8; i++ )
if ((ret = mbedtls_entropy_func(&ctx, buf, sizeof(buf))) != 0) {
if( ( ret = mbedtls_entropy_func( &ctx, buf, sizeof( buf ) ) ) != 0 )
goto cleanup; goto cleanup;
for (j = 0; j < sizeof(buf); j++) for( j = 0; j < sizeof( buf ); j++ )
acc[j] |= buf[j]; acc[j] |= buf[j];
} }
for (j = 0; j < sizeof(buf); j++) { for( j = 0; j < sizeof( buf ); j++ )
if (acc[j] == 0) { {
if( acc[j] == 0 )
{
ret = 1; ret = 1;
goto cleanup; goto cleanup;
} }
} }
#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
if ((ret = mbedtls_entropy_source_self_test(0)) != 0) if( ( ret = mbedtls_entropy_source_self_test( 0 ) ) != 0 )
goto cleanup; goto cleanup;
#endif #endif
cleanup: cleanup:
mbedtls_entropy_free(&ctx); mbedtls_entropy_free( &ctx );
#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ #endif /* !MBEDTLS_TEST_NULL_ENTROPY */
if (verbose != 0) { if( verbose != 0 )
if (ret != 0) {
mbedtls_printf("failed\n"); if( ret != 0 )
mbedtls_printf( "failed\n" );
else else
mbedtls_printf("passed\n"); mbedtls_printf( "passed\n" );
mbedtls_printf("\n"); mbedtls_printf( "\n" );
} }
return (ret != 0); return( ret != 0 );
} }
#endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_SELF_TEST */

View File

@@ -4,30 +4,26 @@
* \brief Entropy accumulator implementation * \brief Entropy accumulator implementation
*/ */
/* /*
* Copyright (C) 2006-2016, ARM Limited, All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
#ifndef MBEDTLS_ENTROPY_H #ifndef MBEDTLS_ENTROPY_H
#define MBEDTLS_ENTROPY_H #define MBEDTLS_ENTROPY_H
#if !defined(MBEDTLS_CONFIG_FILE) #if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h" #include "mbedtls/config.h"
#else #else
#include MBEDTLS_CONFIG_FILE #include MBEDTLS_CONFIG_FILE
#endif #endif
@@ -35,21 +31,21 @@
#include <stddef.h> #include <stddef.h>
#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) #if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256)
#include "sha512.h" #include "mbedtls/sha512.h"
#define MBEDTLS_ENTROPY_SHA512_ACCUMULATOR #define MBEDTLS_ENTROPY_SHA512_ACCUMULATOR
#else #else
#if defined(MBEDTLS_SHA256_C) #if defined(MBEDTLS_SHA256_C)
#define MBEDTLS_ENTROPY_SHA256_ACCUMULATOR #define MBEDTLS_ENTROPY_SHA256_ACCUMULATOR
#include "sha256.h" #include "mbedtls/sha256.h"
#endif #endif
#endif #endif
#if defined(MBEDTLS_THREADING_C) #if defined(MBEDTLS_THREADING_C)
#include "threading.h" #include "mbedtls/threading.h"
#endif #endif
#if defined(MBEDTLS_HAVEGE_C) #if defined(MBEDTLS_HAVEGE_C)
#include "havege.h" #include "mbedtls/havege.h"
#endif #endif
#define MBEDTLS_ERR_ENTROPY_SOURCE_FAILED -0x003C /**< Critical entropy source failure. */ #define MBEDTLS_ERR_ENTROPY_SOURCE_FAILED -0x003C /**< Critical entropy source failure. */
@@ -104,14 +100,15 @@ extern "C" {
* MBEDTLS_ERR_ENTROPY_SOURCE_FAILED otherwise * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED otherwise
*/ */
typedef int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output, size_t len, typedef int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output, size_t len,
size_t *olen); size_t *olen);
/** /**
* \brief Entropy source state * \brief Entropy source state
*/ */
typedef struct mbedtls_entropy_source_state { typedef struct mbedtls_entropy_source_state
{
mbedtls_entropy_f_source_ptr f_source; /**< The entropy source callback */ mbedtls_entropy_f_source_ptr f_source; /**< The entropy source callback */
void *p_source; /**< The callback data pointer */ void * p_source; /**< The callback data pointer */
size_t size; /**< Amount received in bytes */ size_t size; /**< Amount received in bytes */
size_t threshold; /**< Minimum bytes required before release */ size_t threshold; /**< Minimum bytes required before release */
int strong; /**< Is the source strong? */ int strong; /**< Is the source strong? */
@@ -121,14 +118,17 @@ mbedtls_entropy_source_state;
/** /**
* \brief Entropy context structure * \brief Entropy context structure
*/ */
typedef struct mbedtls_entropy_context { typedef struct mbedtls_entropy_context
int accumulator_started; {
int accumulator_started; /* 0 after init.
* 1 after the first update.
* -1 after free. */
#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) #if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
mbedtls_sha512_context accumulator; mbedtls_sha512_context accumulator;
#else #else
mbedtls_sha256_context accumulator; mbedtls_sha256_context accumulator;
#endif #endif
int source_count; int source_count; /* Number of entries used in source. */
mbedtls_entropy_source_state source[MBEDTLS_ENTROPY_MAX_SOURCES]; mbedtls_entropy_source_state source[MBEDTLS_ENTROPY_MAX_SOURCES];
#if defined(MBEDTLS_HAVEGE_C) #if defined(MBEDTLS_HAVEGE_C)
mbedtls_havege_state havege_data; mbedtls_havege_state havege_data;
@@ -147,14 +147,14 @@ mbedtls_entropy_context;
* *
* \param ctx Entropy context to initialize * \param ctx Entropy context to initialize
*/ */
void mbedtls_entropy_init(mbedtls_entropy_context *ctx); void mbedtls_entropy_init( mbedtls_entropy_context *ctx );
/** /**
* \brief Free the data in the context * \brief Free the data in the context
* *
* \param ctx Entropy context to free * \param ctx Entropy context to free
*/ */
void mbedtls_entropy_free(mbedtls_entropy_context *ctx); void mbedtls_entropy_free( mbedtls_entropy_context *ctx );
/** /**
* \brief Adds an entropy source to poll * \brief Adds an entropy source to poll
@@ -173,9 +173,9 @@ void mbedtls_entropy_free(mbedtls_entropy_context *ctx);
* *
* \return 0 if successful or MBEDTLS_ERR_ENTROPY_MAX_SOURCES * \return 0 if successful or MBEDTLS_ERR_ENTROPY_MAX_SOURCES
*/ */
int mbedtls_entropy_add_source(mbedtls_entropy_context *ctx, int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx,
mbedtls_entropy_f_source_ptr f_source, void *p_source, mbedtls_entropy_f_source_ptr f_source, void *p_source,
size_t threshold, int strong); size_t threshold, int strong );
/** /**
* \brief Trigger an extra gather poll for the accumulator * \brief Trigger an extra gather poll for the accumulator
@@ -185,7 +185,7 @@ int mbedtls_entropy_add_source(mbedtls_entropy_context *ctx,
* *
* \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED * \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
*/ */
int mbedtls_entropy_gather(mbedtls_entropy_context *ctx); int mbedtls_entropy_gather( mbedtls_entropy_context *ctx );
/** /**
* \brief Retrieve entropy from the accumulator * \brief Retrieve entropy from the accumulator
@@ -198,7 +198,7 @@ int mbedtls_entropy_gather(mbedtls_entropy_context *ctx);
* *
* \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED * \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
*/ */
int mbedtls_entropy_func(void *data, unsigned char *output, size_t len); int mbedtls_entropy_func( void *data, unsigned char *output, size_t len );
/** /**
* \brief Add data to the accumulator manually * \brief Add data to the accumulator manually
@@ -210,8 +210,8 @@ int mbedtls_entropy_func(void *data, unsigned char *output, size_t len);
* *
* \return 0 if successful * \return 0 if successful
*/ */
int mbedtls_entropy_update_manual(mbedtls_entropy_context *ctx, int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx,
const unsigned char *data, size_t len); const unsigned char *data, size_t len );
#if defined(MBEDTLS_ENTROPY_NV_SEED) #if defined(MBEDTLS_ENTROPY_NV_SEED)
/** /**
@@ -222,7 +222,7 @@ int mbedtls_entropy_update_manual(mbedtls_entropy_context *ctx,
* *
* \return 0 if successful * \return 0 if successful
*/ */
int mbedtls_entropy_update_nv_seed(mbedtls_entropy_context *ctx); int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx );
#endif /* MBEDTLS_ENTROPY_NV_SEED */ #endif /* MBEDTLS_ENTROPY_NV_SEED */
#if defined(MBEDTLS_FS_IO) #if defined(MBEDTLS_FS_IO)
@@ -236,7 +236,7 @@ int mbedtls_entropy_update_nv_seed(mbedtls_entropy_context *ctx);
* MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error, or * MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error, or
* MBEDTLS_ERR_ENTROPY_SOURCE_FAILED * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
*/ */
int mbedtls_entropy_write_seed_file(mbedtls_entropy_context *ctx, const char *path); int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path );
/** /**
* \brief Read and update a seed file. Seed is added to this * \brief Read and update a seed file. Seed is added to this
@@ -250,7 +250,7 @@ int mbedtls_entropy_write_seed_file(mbedtls_entropy_context *ctx, const char *pa
* MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error, * MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error,
* MBEDTLS_ERR_ENTROPY_SOURCE_FAILED * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED
*/ */
int mbedtls_entropy_update_seed_file(mbedtls_entropy_context *ctx, const char *path); int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path );
#endif /* MBEDTLS_FS_IO */ #endif /* MBEDTLS_FS_IO */
#if defined(MBEDTLS_SELF_TEST) #if defined(MBEDTLS_SELF_TEST)
@@ -262,7 +262,7 @@ int mbedtls_entropy_update_seed_file(mbedtls_entropy_context *ctx, const char *p
* *
* \return 0 if successful, or 1 if a test failed * \return 0 if successful, or 1 if a test failed
*/ */
int mbedtls_entropy_self_test(int verbose); int mbedtls_entropy_self_test( int verbose );
#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
/** /**
@@ -278,7 +278,7 @@ int mbedtls_entropy_self_test(int verbose);
* *
* \return 0 if successful, or 1 if a test failed * \return 0 if successful, or 1 if a test failed
*/ */
int mbedtls_entropy_source_self_test(int verbose); int mbedtls_entropy_source_self_test( int verbose );
#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ #endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */
#endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_SELF_TEST */

View File

@@ -1,36 +1,28 @@
/* /*
* Platform-specific and custom entropy polling functions * Platform-specific and custom entropy polling functions
* *
* Copyright (C) 2006-2016, ARM Limited, All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
#if defined(__linux__) #if defined(__linux__) && !defined(_GNU_SOURCE)
/* Ensure that syscall() is available even when compiling with -std=c99 */ /* Ensure that syscall() is available even when compiling with -std=c99 */
#define _GNU_SOURCE #define _GNU_SOURCE
#endif #endif
#if !defined(MBEDTLS_CONFIG_FILE) #include "common.h"
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include <string.h> #include <string.h>
@@ -38,6 +30,7 @@
#include "mbedtls/entropy.h" #include "mbedtls/entropy.h"
#include "mbedtls/entropy_poll.h" #include "mbedtls/entropy_poll.h"
#include "mbedtls/error.h"
#if defined(MBEDTLS_TIMING_C) #if defined(MBEDTLS_TIMING_C)
#include "mbedtls/timing.h" #include "mbedtls/timing.h"
@@ -53,7 +46,7 @@
#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ #if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
!defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \
!defined(__HAIKU__) !defined(__HAIKU__) && !defined(__midipix__)
#error "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in config.h" #error "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in config.h"
#endif #endif
@@ -65,26 +58,29 @@
#include <windows.h> #include <windows.h>
#include <wincrypt.h> #include <wincrypt.h>
int mbedtls_platform_entropy_poll(void *data, unsigned char *output, size_t len, int mbedtls_platform_entropy_poll( void *data, unsigned char *output, size_t len,
size_t *olen) { size_t *olen )
{
HCRYPTPROV provider; HCRYPTPROV provider;
((void) data); ((void) data);
*olen = 0; *olen = 0;
if (CryptAcquireContext(&provider, NULL, NULL, if( CryptAcquireContext( &provider, NULL, NULL,
PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) == FALSE) { PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE )
return (MBEDTLS_ERR_ENTROPY_SOURCE_FAILED); {
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
} }
if (CryptGenRandom(provider, (DWORD) len, output) == FALSE) { if( CryptGenRandom( provider, (DWORD) len, output ) == FALSE )
CryptReleaseContext(provider, 0); {
return (MBEDTLS_ERR_ENTROPY_SOURCE_FAILED); CryptReleaseContext( provider, 0 );
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
} }
CryptReleaseContext(provider, 0); CryptReleaseContext( provider, 0 );
*olen = len; *olen = len;
return (0); return( 0 );
} }
#else /* _WIN32 && !EFIX64 && !EFI32 */ #else /* _WIN32 && !EFIX64 && !EFI32 */
@@ -93,172 +89,202 @@ int mbedtls_platform_entropy_poll(void *data, unsigned char *output, size_t len,
* Since there is no wrapper in the libc yet, use the generic syscall wrapper * Since there is no wrapper in the libc yet, use the generic syscall wrapper
* available in GNU libc and compatible libc's (eg uClibc). * available in GNU libc and compatible libc's (eg uClibc).
*/ */
#if defined(__linux__) && defined(__GLIBC__) #if ((defined(__linux__) && defined(__GLIBC__)) || defined(__midipix__))
#include <unistd.h> #include <unistd.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#if defined(SYS_getrandom) #if defined(SYS_getrandom)
#define HAVE_GETRANDOM #define HAVE_GETRANDOM
#include <errno.h>
static int getrandom_wrapper(void *buf, size_t buflen, unsigned int flags) { static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags )
{
/* MemSan cannot understand that the syscall writes to the buffer */ /* MemSan cannot understand that the syscall writes to the buffer */
#if defined(__has_feature) #if defined(__has_feature)
#if __has_feature(memory_sanitizer) #if __has_feature(memory_sanitizer)
memset(buf, 0, buflen); memset( buf, 0, buflen );
#endif #endif
#endif #endif
return( syscall( SYS_getrandom, buf, buflen, flags ) );
return (syscall(SYS_getrandom, buf, buflen, flags));
} }
#include <sys/utsname.h>
/* Check if version is at least 3.17.0 */
static int check_version_3_17_plus(void) {
int minor;
struct utsname un;
const char *ver;
/* Get version information */
uname(&un);
ver = un.release;
/* Check major version; assume a single digit */
if (ver[0] < '3' || ver[0] > '9' || ver [1] != '.')
return (-1);
if (ver[0] - '0' > 3)
return (0);
/* Ok, so now we know major == 3, check minor.
* Assume 1 or 2 digits. */
if (ver[2] < '0' || ver[2] > '9')
return (-1);
minor = ver[2] - '0';
if (ver[3] >= '0' && ver[3] <= '9')
minor = 10 * minor + ver[3] - '0';
else if (ver [3] != '.')
return (-1);
if (minor < 17)
return (-1);
return (0);
}
static int has_getrandom = -1;
#endif /* SYS_getrandom */ #endif /* SYS_getrandom */
#endif /* __linux__ */ #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 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> #include <stdio.h>
int mbedtls_platform_entropy_poll(void *data, int mbedtls_platform_entropy_poll( void *data,
unsigned char *output, size_t len, size_t *olen) { unsigned char *output, size_t len, size_t *olen )
{
FILE *file; FILE *file;
size_t read_len; size_t read_len;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
((void) data); ((void) data);
#if defined(HAVE_GETRANDOM) #if defined(HAVE_GETRANDOM)
if (has_getrandom == -1) ret = getrandom_wrapper( output, len, 0 );
has_getrandom = (check_version_3_17_plus() == 0); if( ret >= 0 )
{
if (has_getrandom) {
int ret;
if ((ret = getrandom_wrapper(output, len, 0)) < 0)
return (MBEDTLS_ERR_ENTROPY_SOURCE_FAILED);
*olen = ret; *olen = ret;
return (0); 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 */ #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; *olen = 0;
file = fopen("/dev/urandom", "rb"); file = fopen( "/dev/urandom", "rb" );
if (file == NULL) if( file == NULL )
return (MBEDTLS_ERR_ENTROPY_SOURCE_FAILED); return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
read_len = fread(output, 1, len, file); read_len = fread( output, 1, len, file );
if (read_len != len) { if( read_len != len )
fclose(file); {
return (MBEDTLS_ERR_ENTROPY_SOURCE_FAILED); fclose( file );
return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
} }
fclose(file); fclose( file );
*olen = len; *olen = len;
return (0); return( 0 );
#endif /* HAVE_SYSCTL_ARND */
} }
#endif /* _WIN32 && !EFIX64 && !EFI32 */ #endif /* _WIN32 && !EFIX64 && !EFI32 */
#endif /* !MBEDTLS_NO_PLATFORM_ENTROPY */ #endif /* !MBEDTLS_NO_PLATFORM_ENTROPY */
#if defined(MBEDTLS_TEST_NULL_ENTROPY) #if defined(MBEDTLS_TEST_NULL_ENTROPY)
int mbedtls_null_entropy_poll(void *data, int mbedtls_null_entropy_poll( void *data,
unsigned char *output, size_t len, size_t *olen) { unsigned char *output, size_t len, size_t *olen )
{
((void) data); ((void) data);
((void) output); ((void) output);
*olen = 0; *olen = 0;
if( len < sizeof(unsigned char) )
return( 0 );
if (len < sizeof(unsigned char)) output[0] = 0;
return (0);
*olen = sizeof(unsigned char); *olen = sizeof(unsigned char);
return( 0 );
return (0);
} }
#endif #endif
#if defined(MBEDTLS_TIMING_C) #if defined(MBEDTLS_TIMING_C)
int mbedtls_hardclock_poll(void *data, int mbedtls_hardclock_poll( void *data,
unsigned char *output, size_t len, size_t *olen) { unsigned char *output, size_t len, size_t *olen )
{
unsigned long timer = mbedtls_timing_hardclock(); unsigned long timer = mbedtls_timing_hardclock();
((void) data); ((void) data);
*olen = 0; *olen = 0;
if (len < sizeof(unsigned long)) if( len < sizeof(unsigned long) )
return (0); return( 0 );
memcpy(output, &timer, sizeof(unsigned long)); memcpy( output, &timer, sizeof(unsigned long) );
*olen = sizeof(unsigned long); *olen = sizeof(unsigned long);
return (0); return( 0 );
} }
#endif /* MBEDTLS_TIMING_C */ #endif /* MBEDTLS_TIMING_C */
#if defined(MBEDTLS_HAVEGE_C) #if defined(MBEDTLS_HAVEGE_C)
int mbedtls_havege_poll(void *data, int mbedtls_havege_poll( void *data,
unsigned char *output, size_t len, size_t *olen) { unsigned char *output, size_t len, size_t *olen )
{
mbedtls_havege_state *hs = (mbedtls_havege_state *) data; mbedtls_havege_state *hs = (mbedtls_havege_state *) data;
*olen = 0; *olen = 0;
if (mbedtls_havege_random(hs, output, len) != 0) if( mbedtls_havege_random( hs, output, len ) != 0 )
return (MBEDTLS_ERR_ENTROPY_SOURCE_FAILED); return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
*olen = len; *olen = len;
return (0); return( 0 );
} }
#endif /* MBEDTLS_HAVEGE_C */ #endif /* MBEDTLS_HAVEGE_C */
#if defined(MBEDTLS_ENTROPY_NV_SEED) #if defined(MBEDTLS_ENTROPY_NV_SEED)
int mbedtls_nv_seed_poll(void *data, int mbedtls_nv_seed_poll( void *data,
unsigned char *output, size_t len, size_t *olen) { unsigned char *output, size_t len, size_t *olen )
{
unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
size_t use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; size_t use_len = MBEDTLS_ENTROPY_BLOCK_SIZE;
((void) data); ((void) data);
memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE); memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE );
if (mbedtls_nv_seed_read(buf, MBEDTLS_ENTROPY_BLOCK_SIZE) < 0) if( mbedtls_nv_seed_read( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 )
return (MBEDTLS_ERR_ENTROPY_SOURCE_FAILED); return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
if (len < use_len) if( len < use_len )
use_len = len; use_len = len;
memcpy(output, buf, use_len); memcpy( output, buf, use_len );
*olen = use_len; *olen = use_len;
return (0); return( 0 );
} }
#endif /* MBEDTLS_ENTROPY_NV_SEED */ #endif /* MBEDTLS_ENTROPY_NV_SEED */

View File

@@ -4,30 +4,26 @@
* \brief Platform-specific and custom entropy polling functions * \brief Platform-specific and custom entropy polling functions
*/ */
/* /*
* Copyright (C) 2006-2016, ARM Limited, All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
#ifndef MBEDTLS_ENTROPY_POLL_H #ifndef MBEDTLS_ENTROPY_POLL_H
#define MBEDTLS_ENTROPY_POLL_H #define MBEDTLS_ENTROPY_POLL_H
#if !defined(MBEDTLS_CONFIG_FILE) #if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h" #include "mbedtls/config.h"
#else #else
#include MBEDTLS_CONFIG_FILE #include MBEDTLS_CONFIG_FILE
#endif #endif
@@ -52,16 +48,16 @@ extern "C" {
* \brief Entropy poll callback that provides 0 entropy. * \brief Entropy poll callback that provides 0 entropy.
*/ */
#if defined(MBEDTLS_TEST_NULL_ENTROPY) #if defined(MBEDTLS_TEST_NULL_ENTROPY)
int mbedtls_null_entropy_poll(void *data, int mbedtls_null_entropy_poll( void *data,
unsigned char *output, size_t len, size_t *olen); unsigned char *output, size_t len, size_t *olen );
#endif #endif
#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
/** /**
* \brief Platform-specific entropy poll callback * \brief Platform-specific entropy poll callback
*/ */
int mbedtls_platform_entropy_poll(void *data, int mbedtls_platform_entropy_poll( void *data,
unsigned char *output, size_t len, size_t *olen); unsigned char *output, size_t len, size_t *olen );
#endif #endif
#if defined(MBEDTLS_HAVEGE_C) #if defined(MBEDTLS_HAVEGE_C)
@@ -70,16 +66,16 @@ int mbedtls_platform_entropy_poll(void *data,
* *
* Requires an HAVEGE state as its data pointer. * Requires an HAVEGE state as its data pointer.
*/ */
int mbedtls_havege_poll(void *data, int mbedtls_havege_poll( void *data,
unsigned char *output, size_t len, size_t *olen); unsigned char *output, size_t len, size_t *olen );
#endif #endif
#if defined(MBEDTLS_TIMING_C) #if defined(MBEDTLS_TIMING_C)
/** /**
* \brief mbedtls_timing_hardclock-based entropy poll callback * \brief mbedtls_timing_hardclock-based entropy poll callback
*/ */
int mbedtls_hardclock_poll(void *data, int mbedtls_hardclock_poll( void *data,
unsigned char *output, size_t len, size_t *olen); unsigned char *output, size_t len, size_t *olen );
#endif #endif
#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
@@ -91,8 +87,8 @@ int mbedtls_hardclock_poll(void *data,
* *
* \note This must accept NULL as its first argument. * \note This must accept NULL as its first argument.
*/ */
int mbedtls_hardware_poll(void *data, int mbedtls_hardware_poll( void *data,
unsigned char *output, size_t len, size_t *olen); unsigned char *output, size_t len, size_t *olen );
#endif #endif
#if defined(MBEDTLS_ENTROPY_NV_SEED) #if defined(MBEDTLS_ENTROPY_NV_SEED)
@@ -101,8 +97,8 @@ int mbedtls_hardware_poll(void *data,
* *
* \note This must accept NULL as its first argument. * \note This must accept NULL as its first argument.
*/ */
int mbedtls_nv_seed_poll(void *data, int mbedtls_nv_seed_poll( void *data,
unsigned char *output, size_t len, size_t *olen); unsigned char *output, size_t len, size_t *olen );
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus

File diff suppressed because it is too large Load Diff

View File

@@ -4,28 +4,30 @@
* \brief Error to string translation * \brief Error to string translation
*/ */
/* /*
* Copyright (C) 2006-2018, ARM Limited, All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
#ifndef MBEDTLS_ERROR_H #ifndef MBEDTLS_ERROR_H
#define MBEDTLS_ERROR_H #define MBEDTLS_ERROR_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include <stddef.h> #include <stddef.h>
/** /**
@@ -48,9 +50,10 @@
* For historical reasons, low-level error codes are divided in even and odd, * For historical reasons, low-level error codes are divided in even and odd,
* even codes were assigned first, and -1 is reserved for other errors. * even codes were assigned first, and -1 is reserved for other errors.
* *
* Low-level module errors (0x0002-0x007E, 0x0003-0x007F) * Low-level module errors (0x0002-0x007E, 0x0001-0x007F)
* *
* Module Nr Codes assigned * Module Nr Codes assigned
* ERROR 2 0x006E 0x0001
* MPI 7 0x0002-0x0010 * MPI 7 0x0002-0x0010
* GCM 3 0x0012-0x0014 0x0013-0x0013 * GCM 3 0x0012-0x0014 0x0013-0x0013
* BLOWFISH 3 0x0016-0x0018 0x0017-0x0017 * BLOWFISH 3 0x0016-0x0018 0x0017-0x0017
@@ -76,12 +79,13 @@
* MD4 1 0x002D-0x002D * MD4 1 0x002D-0x002D
* MD5 1 0x002F-0x002F * MD5 1 0x002F-0x002F
* RIPEMD160 1 0x0031-0x0031 * RIPEMD160 1 0x0031-0x0031
* SHA1 1 0x0035-0x0035 * SHA1 1 0x0035-0x0035 0x0073-0x0073
* SHA256 1 0x0037-0x0037 * SHA256 1 0x0037-0x0037 0x0074-0x0074
* SHA512 1 0x0039-0x0039 * SHA512 1 0x0039-0x0039 0x0075-0x0075
* CHACHA20 3 0x0051-0x0055 * CHACHA20 3 0x0051-0x0055
* POLY1305 3 0x0057-0x005B * POLY1305 3 0x0057-0x005B
* CHACHAPOLY 2 0x0054-0x0056 * CHACHAPOLY 2 0x0054-0x0056
* PLATFORM 2 0x0070-0x0072
* *
* High-level module nr (3 bits - 0x0...-0x7...) * High-level module nr (3 bits - 0x0...-0x7...)
* Name ID Nr of Errors * Name ID Nr of Errors
@@ -92,12 +96,13 @@
* DHM 3 11 * DHM 3 11
* PK 3 15 (Started from top) * PK 3 15 (Started from top)
* RSA 4 11 * RSA 4 11
* ECP 4 9 (Started from top) * ECP 4 10 (Started from top)
* MD 5 5 * MD 5 5
* HKDF 5 1 (Started from top) * HKDF 5 1 (Started from top)
* CIPHER 6 8 * SSL 5 2 (Started from 0x5F00)
* SSL 6 22 (Started from top) * CIPHER 6 8 (Started from 0x6080)
* SSL 7 31 * SSL 6 24 (Started from top, plus 0x6000)
* SSL 7 32
* *
* Module dependent error code (5 bits 0x.00.-0x.F8.) * Module dependent error code (5 bits 0x.00.-0x.F8.)
*/ */
@@ -106,6 +111,9 @@
extern "C" { extern "C" {
#endif #endif
#define MBEDTLS_ERR_ERROR_GENERIC_ERROR -0x0001 /**< Generic error */
#define MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED -0x006E /**< This is a bug in the library */
/** /**
* \brief Translate a mbed TLS error code into a string representation, * \brief Translate a mbed TLS error code into a string representation,
* Result is truncated if necessary and always includes a terminating * Result is truncated if necessary and always includes a terminating
@@ -115,7 +123,37 @@ extern "C" {
* \param buffer buffer to place representation in * \param buffer buffer to place representation in
* \param buflen length of the buffer * \param buflen length of the buffer
*/ */
void mbedtls_strerror(int errnum, char *buffer, size_t buflen); void mbedtls_strerror( int errnum, char *buffer, size_t buflen );
/**
* \brief Translate the high-level part of an Mbed TLS error code into a string
* representation.
*
* This function returns a const pointer to an un-modifiable string. The caller
* must not try to modify the string. It is intended to be used mostly for
* logging purposes.
*
* \param error_code error code
*
* \return The string representation of the error code, or \c NULL if the error
* code is unknown.
*/
const char * mbedtls_high_level_strerr( int error_code );
/**
* \brief Translate the low-level part of an Mbed TLS error code into a string
* representation.
*
* This function returns a const pointer to an un-modifiable string. The caller
* must not try to modify the string. It is intended to be used mostly for
* logging purposes.
*
* \param error_code error code
*
* \return The string representation of the error code, or \c NULL if the error
* code is unknown.
*/
const char * mbedtls_low_level_strerr( int error_code );
#ifdef __cplusplus #ifdef __cplusplus
} }

1024
common/mbedtls/gcm.c Normal file

File diff suppressed because it is too large Load Diff

324
common/mbedtls/gcm.h Normal file
View File

@@ -0,0 +1,324 @@
/**
* \file gcm.h
*
* \brief This file contains GCM definitions and functions.
*
* The Galois/Counter Mode (GCM) for 128-bit block ciphers is defined
* in <em>D. McGrew, J. Viega, The Galois/Counter Mode of Operation
* (GCM), Natl. Inst. Stand. Technol.</em>
*
* For more information on GCM, see <em>NIST SP 800-38D: Recommendation for
* Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC</em>.
*
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBEDTLS_GCM_H
#define MBEDTLS_GCM_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include "mbedtls/cipher.h"
#include <stdint.h>
#define MBEDTLS_GCM_ENCRYPT 1
#define MBEDTLS_GCM_DECRYPT 0
#define MBEDTLS_ERR_GCM_AUTH_FAILED -0x0012 /**< Authenticated decryption failed. */
/* MBEDTLS_ERR_GCM_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_GCM_HW_ACCEL_FAILED -0x0013 /**< GCM hardware accelerator failed. */
#define MBEDTLS_ERR_GCM_BAD_INPUT -0x0014 /**< Bad input parameters to function. */
#ifdef __cplusplus
extern "C" {
#endif
#if !defined(MBEDTLS_GCM_ALT)
/**
* \brief The GCM context structure.
*/
typedef struct mbedtls_gcm_context
{
mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */
uint64_t HL[16]; /*!< Precalculated HTable low. */
uint64_t HH[16]; /*!< Precalculated HTable high. */
uint64_t len; /*!< The total length of the encrypted data. */
uint64_t add_len; /*!< The total length of the additional data. */
unsigned char base_ectr[16]; /*!< The first ECTR for tag. */
unsigned char y[16]; /*!< The Y working value. */
unsigned char buf[16]; /*!< The buf working value. */
int mode; /*!< The operation to perform:
#MBEDTLS_GCM_ENCRYPT or
#MBEDTLS_GCM_DECRYPT. */
}
mbedtls_gcm_context;
#else /* !MBEDTLS_GCM_ALT */
#include "gcm_alt.h"
#endif /* !MBEDTLS_GCM_ALT */
/**
* \brief This function initializes the specified GCM context,
* to make references valid, and prepares the context
* for mbedtls_gcm_setkey() or mbedtls_gcm_free().
*
* The function does not bind the GCM context to a particular
* cipher, nor set the key. For this purpose, use
* mbedtls_gcm_setkey().
*
* \param ctx The GCM context to initialize. This must not be \c NULL.
*/
void mbedtls_gcm_init( mbedtls_gcm_context *ctx );
/**
* \brief This function associates a GCM context with a
* cipher algorithm and a key.
*
* \param ctx The GCM context. This must be initialized.
* \param cipher The 128-bit block cipher to use.
* \param key The encryption key. This must be a readable buffer of at
* least \p keybits bits.
* \param keybits The key size in bits. Valid options are:
* <ul><li>128 bits</li>
* <li>192 bits</li>
* <li>256 bits</li></ul>
*
* \return \c 0 on success.
* \return A cipher-specific error code on failure.
*/
int mbedtls_gcm_setkey( mbedtls_gcm_context *ctx,
mbedtls_cipher_id_t cipher,
const unsigned char *key,
unsigned int keybits );
/**
* \brief This function performs GCM encryption or decryption of a buffer.
*
* \note For encryption, the output buffer can be the same as the
* input buffer. For decryption, the output buffer cannot be
* the same as input buffer. If the buffers overlap, the output
* buffer must trail at least 8 Bytes behind the input buffer.
*
* \warning When this function performs a decryption, it outputs the
* authentication tag and does not verify that the data is
* authentic. You should use this function to perform encryption
* only. For decryption, use mbedtls_gcm_auth_decrypt() instead.
*
* \param ctx The GCM context to use for encryption or decryption. This
* must be initialized.
* \param mode The operation to perform:
* - #MBEDTLS_GCM_ENCRYPT to perform authenticated encryption.
* The ciphertext is written to \p output and the
* authentication tag is written to \p tag.
* - #MBEDTLS_GCM_DECRYPT to perform decryption.
* The plaintext is written to \p output and the
* authentication tag is written to \p tag.
* Note that this mode is not recommended, because it does
* not verify the authenticity of the data. For this reason,
* you should use mbedtls_gcm_auth_decrypt() instead of
* calling this function in decryption mode.
* \param length The length of the input data, which is equal to the length
* of the output data.
* \param iv The initialization vector. This must be a readable buffer of
* at least \p iv_len Bytes.
* \param iv_len The length of the IV.
* \param add The buffer holding the additional data. This must be of at
* least that size in Bytes.
* \param add_len The length of the additional data.
* \param input The buffer holding the input data. If \p length is greater
* than zero, this must be a readable buffer of at least that
* size in Bytes.
* \param output The buffer for holding the output data. If \p length is greater
* than zero, this must be a writable buffer of at least that
* size in Bytes.
* \param tag_len The length of the tag to generate.
* \param tag The buffer for holding the tag. This must be a writable
* buffer of at least \p tag_len Bytes.
*
* \return \c 0 if the encryption or decryption was performed
* successfully. Note that in #MBEDTLS_GCM_DECRYPT mode,
* this does not indicate that the data is authentic.
* \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths or pointers are
* not valid or a cipher-specific error code if the encryption
* or decryption failed.
*/
int mbedtls_gcm_crypt_and_tag( mbedtls_gcm_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,
size_t tag_len,
unsigned char *tag );
/**
* \brief This function performs a GCM authenticated decryption of a
* buffer.
*
* \note For decryption, the output buffer cannot be the same as
* input buffer. If the buffers overlap, the output buffer
* must trail at least 8 Bytes behind the input buffer.
*
* \param ctx The GCM context. This must be initialized.
* \param length The length of the ciphertext to decrypt, which is also
* the length of the decrypted plaintext.
* \param iv The initialization vector. This must be a readable buffer
* of at least \p iv_len Bytes.
* \param iv_len The length of the IV.
* \param add The buffer holding the additional data. This must be of at
* least that size in Bytes.
* \param add_len The length of the additional data.
* \param tag The buffer holding the tag to verify. This must be a
* readable buffer of at least \p tag_len Bytes.
* \param tag_len The length of the tag to verify.
* \param input The buffer holding the ciphertext. If \p length is greater
* than zero, this must be a readable buffer of at least that
* size.
* \param output The buffer for holding the decrypted plaintext. If \p length
* is greater than zero, this must be a writable buffer of at
* least that size.
*
* \return \c 0 if successful and authenticated.
* \return #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match.
* \return #MBEDTLS_ERR_GCM_BAD_INPUT if the lengths or pointers are
* not valid or a cipher-specific error code if the decryption
* failed.
*/
int mbedtls_gcm_auth_decrypt( mbedtls_gcm_context *ctx,
size_t length,
const unsigned char *iv,
size_t iv_len,
const unsigned char *add,
size_t add_len,
const unsigned char *tag,
size_t tag_len,
const unsigned char *input,
unsigned char *output );
/**
* \brief This function starts a GCM encryption or decryption
* operation.
*
* \param ctx The GCM context. This must be initialized.
* \param mode The operation to perform: #MBEDTLS_GCM_ENCRYPT or
* #MBEDTLS_GCM_DECRYPT.
* \param iv The initialization vector. This must be a readable buffer of
* at least \p iv_len Bytes.
* \param iv_len The length of the IV.
* \param add The buffer holding the additional data, or \c NULL
* if \p add_len is \c 0.
* \param add_len The length of the additional data. If \c 0,
* \p add may be \c NULL.
*
* \return \c 0 on success.
*/
int mbedtls_gcm_starts( mbedtls_gcm_context *ctx,
int mode,
const unsigned char *iv,
size_t iv_len,
const unsigned char *add,
size_t add_len );
/**
* \brief This function feeds an input buffer into an ongoing GCM
* encryption or decryption operation.
*
* ` The function expects input to be a multiple of 16
* Bytes. Only the last call before calling
* mbedtls_gcm_finish() can be less than 16 Bytes.
*
* \note For decryption, the output buffer cannot be the same as
* input buffer. If the buffers overlap, the output buffer
* must trail at least 8 Bytes behind the input buffer.
*
* \param ctx The GCM context. This must be initialized.
* \param length The length of the input data. This must be a multiple of
* 16 except in the last call before mbedtls_gcm_finish().
* \param input The buffer holding the input data. If \p length is greater
* than zero, this must be a readable buffer of at least that
* size in Bytes.
* \param output The buffer for holding the output data. If \p length is
* greater than zero, this must be a writable buffer of at
* least that size in Bytes.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure.
*/
int mbedtls_gcm_update( mbedtls_gcm_context *ctx,
size_t length,
const unsigned char *input,
unsigned char *output );
/**
* \brief This function finishes the GCM operation and generates
* the authentication tag.
*
* It wraps up the GCM stream, and generates the
* tag. The tag can have a maximum length of 16 Bytes.
*
* \param ctx The GCM context. This must be initialized.
* \param tag The buffer for holding the tag. This must be a writable
* buffer of at least \p tag_len Bytes.
* \param tag_len The length of the tag to generate. This must be at least
* four.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure.
*/
int mbedtls_gcm_finish( mbedtls_gcm_context *ctx,
unsigned char *tag,
size_t tag_len );
/**
* \brief This function clears a GCM context and the underlying
* cipher sub-context.
*
* \param ctx The GCM context to clear. If this is \c NULL, the call has
* no effect. Otherwise, this must be initialized.
*/
void mbedtls_gcm_free( mbedtls_gcm_context *ctx );
#if defined(MBEDTLS_SELF_TEST)
/**
* \brief The GCM checkup routine.
*
* \return \c 0 on success.
* \return \c 1 on failure.
*/
int mbedtls_gcm_self_test( int verbose );
#endif /* MBEDTLS_SELF_TEST */
#ifdef __cplusplus
}
#endif
#endif /* gcm.h */

237
common/mbedtls/havege.c Normal file
View File

@@ -0,0 +1,237 @@
/**
* \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* The HAVEGE RNG was designed by Andre Seznec in 2002.
*
* http://www.irisa.fr/caps/projects/hipsor/publi.php
*
* Contact: seznec(at)irisa_dot_fr - orocheco(at)irisa_dot_fr
*/
#include "common.h"
#if defined(MBEDTLS_HAVEGE_C)
#include "mbedtls/havege.h"
#include "mbedtls/timing.h"
#include "mbedtls/platform_util.h"
#include <stdint.h>
#include <string.h>
/* ------------------------------------------------------------------------
* On average, one iteration accesses two 8-word blocks in the havege WALK
* table, and generates 16 words in the RES array.
*
* The data read in the WALK table is updated and permuted after each use.
* The result of the hardware clock counter read is used for this update.
*
* 25 conditional tests are present. The conditional tests are grouped in
* two nested groups of 12 conditional tests and 1 test that controls the
* permutation; on average, there should be 6 tests executed and 3 of them
* should be mispredicted.
* ------------------------------------------------------------------------
*/
#define SWAP(X,Y) { uint32_t *T = (X); (X) = (Y); (Y) = T; }
#define TST1_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1;
#define TST2_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1;
#define TST1_LEAVE U1++; }
#define TST2_LEAVE U2++; }
#define ONE_ITERATION \
\
PTEST = PT1 >> 20; \
\
TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \
TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \
TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \
\
TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \
TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \
TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \
\
PTX = (PT1 >> 18) & 7; \
PT1 &= 0x1FFF; \
PT2 &= 0x1FFF; \
CLK = (uint32_t) mbedtls_timing_hardclock(); \
\
i = 0; \
A = &WALK[PT1 ]; RES[i++] ^= *A; \
B = &WALK[PT2 ]; RES[i++] ^= *B; \
C = &WALK[PT1 ^ 1]; RES[i++] ^= *C; \
D = &WALK[PT2 ^ 4]; RES[i++] ^= *D; \
\
IN = (*A >> (1)) ^ (*A << (31)) ^ CLK; \
*A = (*B >> (2)) ^ (*B << (30)) ^ CLK; \
*B = IN ^ U1; \
*C = (*C >> (3)) ^ (*C << (29)) ^ CLK; \
*D = (*D >> (4)) ^ (*D << (28)) ^ CLK; \
\
A = &WALK[PT1 ^ 2]; RES[i++] ^= *A; \
B = &WALK[PT2 ^ 2]; RES[i++] ^= *B; \
C = &WALK[PT1 ^ 3]; RES[i++] ^= *C; \
D = &WALK[PT2 ^ 6]; RES[i++] ^= *D; \
\
if( PTEST & 1 ) SWAP( A, C ); \
\
IN = (*A >> (5)) ^ (*A << (27)) ^ CLK; \
*A = (*B >> (6)) ^ (*B << (26)) ^ CLK; \
*B = IN; CLK = (uint32_t) mbedtls_timing_hardclock(); \
*C = (*C >> (7)) ^ (*C << (25)) ^ CLK; \
*D = (*D >> (8)) ^ (*D << (24)) ^ CLK; \
\
A = &WALK[PT1 ^ 4]; \
B = &WALK[PT2 ^ 1]; \
\
PTEST = PT2 >> 1; \
\
PT2 = (RES[(i - 8) ^ PTY] ^ WALK[PT2 ^ PTY ^ 7]); \
PT2 = ((PT2 & 0x1FFF) & (~8)) ^ ((PT1 ^ 8) & 0x8); \
PTY = (PT2 >> 10) & 7; \
\
TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \
TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \
TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \
\
TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \
TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \
TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \
\
C = &WALK[PT1 ^ 5]; \
D = &WALK[PT2 ^ 5]; \
\
RES[i++] ^= *A; \
RES[i++] ^= *B; \
RES[i++] ^= *C; \
RES[i++] ^= *D; \
\
IN = (*A >> ( 9)) ^ (*A << (23)) ^ CLK; \
*A = (*B >> (10)) ^ (*B << (22)) ^ CLK; \
*B = IN ^ U2; \
*C = (*C >> (11)) ^ (*C << (21)) ^ CLK; \
*D = (*D >> (12)) ^ (*D << (20)) ^ CLK; \
\
A = &WALK[PT1 ^ 6]; RES[i++] ^= *A; \
B = &WALK[PT2 ^ 3]; RES[i++] ^= *B; \
C = &WALK[PT1 ^ 7]; RES[i++] ^= *C; \
D = &WALK[PT2 ^ 7]; RES[i++] ^= *D; \
\
IN = (*A >> (13)) ^ (*A << (19)) ^ CLK; \
*A = (*B >> (14)) ^ (*B << (18)) ^ CLK; \
*B = IN; \
*C = (*C >> (15)) ^ (*C << (17)) ^ CLK; \
*D = (*D >> (16)) ^ (*D << (16)) ^ CLK; \
\
PT1 = ( RES[( i - 8 ) ^ PTX] ^ \
WALK[PT1 ^ PTX ^ 7] ) & (~1); \
PT1 ^= (PT2 ^ 0x10) & 0x10; \
\
for( n++, i = 0; i < 16; i++ ) \
hs->pool[n % MBEDTLS_HAVEGE_COLLECT_SIZE] ^= RES[i];
/*
* Entropy gathering function
*/
static void havege_fill( mbedtls_havege_state *hs )
{
size_t n = 0;
size_t i;
uint32_t U1, U2, *A, *B, *C, *D;
uint32_t PT1, PT2, *WALK, RES[16];
uint32_t PTX, PTY, CLK, PTEST, IN;
WALK = hs->WALK;
PT1 = hs->PT1;
PT2 = hs->PT2;
PTX = U1 = 0;
PTY = U2 = 0;
(void)PTX;
memset( RES, 0, sizeof( RES ) );
while( n < MBEDTLS_HAVEGE_COLLECT_SIZE * 4 )
{
ONE_ITERATION
ONE_ITERATION
ONE_ITERATION
ONE_ITERATION
}
hs->PT1 = PT1;
hs->PT2 = PT2;
hs->offset[0] = 0;
hs->offset[1] = MBEDTLS_HAVEGE_COLLECT_SIZE / 2;
}
/*
* HAVEGE initialization
*/
void mbedtls_havege_init( mbedtls_havege_state *hs )
{
memset( hs, 0, sizeof( mbedtls_havege_state ) );
havege_fill( hs );
}
void mbedtls_havege_free( mbedtls_havege_state *hs )
{
if( hs == NULL )
return;
mbedtls_platform_zeroize( hs, sizeof( mbedtls_havege_state ) );
}
/*
* HAVEGE rand function
*/
int mbedtls_havege_random( void *p_rng, unsigned char *buf, size_t len )
{
uint32_t val;
size_t use_len;
mbedtls_havege_state *hs = (mbedtls_havege_state *) p_rng;
unsigned char *p = buf;
while( len > 0 )
{
use_len = len;
if( use_len > sizeof( val ) )
use_len = sizeof( val );
if( hs->offset[1] >= MBEDTLS_HAVEGE_COLLECT_SIZE )
havege_fill( hs );
val = hs->pool[hs->offset[0]++];
val ^= hs->pool[hs->offset[1]++];
memcpy( p, &val, use_len );
len -= use_len;
p += use_len;
}
return( 0 );
}
#endif /* MBEDTLS_HAVEGE_C */

80
common/mbedtls/havege.h Normal file
View File

@@ -0,0 +1,80 @@
/**
* \file havege.h
*
* \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBEDTLS_HAVEGE_H
#define MBEDTLS_HAVEGE_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include <stddef.h>
#include <stdint.h>
#define MBEDTLS_HAVEGE_COLLECT_SIZE 1024
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief HAVEGE state structure
*/
typedef struct mbedtls_havege_state
{
uint32_t PT1, PT2, offset[2];
uint32_t pool[MBEDTLS_HAVEGE_COLLECT_SIZE];
uint32_t WALK[8192];
}
mbedtls_havege_state;
/**
* \brief HAVEGE initialization
*
* \param hs HAVEGE state to be initialized
*/
void mbedtls_havege_init( mbedtls_havege_state *hs );
/**
* \brief Clear HAVEGE state
*
* \param hs HAVEGE state to be cleared
*/
void mbedtls_havege_free( mbedtls_havege_state *hs );
/**
* \brief HAVEGE rand function
*
* \param p_rng A HAVEGE state
* \param output Buffer to fill
* \param len Length of buffer
*
* \return 0
*/
int mbedtls_havege_random( void *p_rng, unsigned char *output, size_t len );
#ifdef __cplusplus
}
#endif
#endif /* havege.h */

189
common/mbedtls/hkdf.c Normal file
View File

@@ -0,0 +1,189 @@
/*
* HKDF implementation -- RFC 5869
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#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 */

139
common/mbedtls/hkdf.h Normal file
View File

@@ -0,0 +1,139 @@
/**
* \file hkdf.h
*
* \brief This file contains the HKDF interface.
*
* The HMAC-based Extract-and-Expand Key Derivation Function (HKDF) is
* specified by RFC 5869.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBEDTLS_HKDF_H
#define MBEDTLS_HKDF_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include "mbedtls/md.h"
/**
* \name HKDF Error codes
* \{
*/
#define MBEDTLS_ERR_HKDF_BAD_INPUT_DATA -0x5F80 /**< Bad input parameters to function. */
/* \} name */
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief This is the HMAC-based Extract-and-Expand Key Derivation Function
* (HKDF).
*
* \param md A hash function; md.size denotes the length of the hash
* function output in bytes.
* \param salt An optional salt value (a non-secret random value);
* if the salt is not provided, a string of all zeros of
* md.size length is used as the salt.
* \param salt_len The length in bytes of the optional \p salt.
* \param ikm The input keying material.
* \param ikm_len The length in bytes of \p ikm.
* \param info An optional context and application specific information
* string. This can be a zero-length string.
* \param info_len The length of \p info in bytes.
* \param okm The output keying material of \p okm_len bytes.
* \param okm_len The length of the output keying material in bytes. This
* must be less than or equal to 255 * md.size bytes.
*
* \return 0 on success.
* \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid.
* \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying
* MD layer.
*/
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 );
/**
* \brief Take the input keying material \p ikm and extract from it a
* fixed-length pseudorandom key \p prk.
*
* \warning This function should only be used if the security of it has been
* studied and established in that particular context (eg. TLS 1.3
* key schedule). For standard HKDF security guarantees use
* \c mbedtls_hkdf instead.
*
* \param md A hash function; md.size denotes the length of the
* hash function output in bytes.
* \param salt An optional salt value (a non-secret random value);
* if the salt is not provided, a string of all zeros
* of md.size length is used as the salt.
* \param salt_len The length in bytes of the optional \p salt.
* \param ikm The input keying material.
* \param ikm_len The length in bytes of \p ikm.
* \param[out] prk A pseudorandom key of at least md.size bytes.
*
* \return 0 on success.
* \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid.
* \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying
* MD layer.
*/
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 );
/**
* \brief Expand the supplied \p prk into several additional pseudorandom
* keys, which is the output of the HKDF.
*
* \warning This function should only be used if the security of it has been
* studied and established in that particular context (eg. TLS 1.3
* key schedule). For standard HKDF security guarantees use
* \c mbedtls_hkdf instead.
*
* \param md A hash function; md.size denotes the length of the hash
* function output in bytes.
* \param prk A pseudorandom key of at least md.size bytes. \p prk is
* usually the output from the HKDF extract step.
* \param prk_len The length in bytes of \p prk.
* \param info An optional context and application specific information
* string. This can be a zero-length string.
* \param info_len The length of \p info in bytes.
* \param okm The output keying material of \p okm_len bytes.
* \param okm_len The length of the output keying material in bytes. This
* must be less than or equal to 255 * md.size bytes.
*
* \return 0 on success.
* \return #MBEDTLS_ERR_HKDF_BAD_INPUT_DATA when the parameters are invalid.
* \return An MBEDTLS_ERR_MD_* error for errors returned from the underlying
* MD layer.
*/
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 );
#ifdef __cplusplus
}
#endif
#endif /* hkdf.h */

629
common/mbedtls/hmac_drbg.c Normal file
View File

@@ -0,0 +1,629 @@
/*
* HMAC_DRBG implementation (NIST SP 800-90)
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* 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
#if defined(MBEDTLS_SELF_TEST)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_SELF_TEST */
#endif /* MBEDTLS_PLATFORM_C */
/*
* 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_ret( 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 );
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_hmac_drbg_update( mbedtls_hmac_drbg_context *ctx,
const unsigned char *additional,
size_t add_len )
{
(void) mbedtls_hmac_drbg_update_ret( ctx, additional, add_len );
}
#endif /* MBEDTLS_DEPRECATED_REMOVED */
/*
* 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_ret( 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_ret( 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_ret( 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_ret( 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 );
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 );
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_ret( 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_SHA1_C)
/* 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_SHA1_C */
#endif /* MBEDTLS_SELF_TEST */
#endif /* MBEDTLS_HMAC_DRBG_C */

470
common/mbedtls/hmac_drbg.h Normal file
View File

@@ -0,0 +1,470 @@
/**
* \file hmac_drbg.h
*
* \brief The HMAC_DRBG pseudorandom generator.
*
* This module implements the HMAC_DRBG pseudorandom generator described
* in <em>NIST SP 800-90A: Recommendation for Random Number Generation Using
* Deterministic Random Bit Generators</em>.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBEDTLS_HMAC_DRBG_H
#define MBEDTLS_HMAC_DRBG_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include "mbedtls/md.h"
#if defined(MBEDTLS_THREADING_C)
#include "mbedtls/threading.h"
#endif
/*
* Error codes
*/
#define MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG -0x0003 /**< Too many random requested in single call. */
#define MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG -0x0005 /**< Input too large (Entropy + additional). */
#define MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR -0x0007 /**< Read/write error in file. */
#define MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED -0x0009 /**< The entropy source failed. */
/**
* \name SECTION: Module settings
*
* The configuration options you can set for this module are in this section.
* Either change them in config.h or define them on the compiler command line.
* \{
*/
#if !defined(MBEDTLS_HMAC_DRBG_RESEED_INTERVAL)
#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */
#endif
#if !defined(MBEDTLS_HMAC_DRBG_MAX_INPUT)
#define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */
#endif
#if !defined(MBEDTLS_HMAC_DRBG_MAX_REQUEST)
#define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */
#endif
#if !defined(MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT)
#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */
#endif
/* \} name SECTION: Module settings */
#define MBEDTLS_HMAC_DRBG_PR_OFF 0 /**< No prediction resistance */
#define MBEDTLS_HMAC_DRBG_PR_ON 1 /**< Prediction resistance enabled */
#ifdef __cplusplus
extern "C" {
#endif
/**
* HMAC_DRBG context.
*/
typedef struct mbedtls_hmac_drbg_context
{
/* Working state: the key K is not stored explicitly,
* but is implied by the HMAC context */
mbedtls_md_context_t md_ctx; /*!< HMAC context (inc. K) */
unsigned char V[MBEDTLS_MD_MAX_SIZE]; /*!< V in the spec */
int reseed_counter; /*!< reseed counter */
/* Administrative state */
size_t entropy_len; /*!< entropy bytes grabbed on each (re)seed */
int prediction_resistance; /*!< enable prediction resistance (Automatic
reseed before every random generation) */
int reseed_interval; /*!< reseed interval */
/* Callbacks */
int (*f_entropy)(void *, unsigned char *, size_t); /*!< entropy function */
void *p_entropy; /*!< context for the entropy function */
#if defined(MBEDTLS_THREADING_C)
/* Invariant: the mutex is initialized if and only if
* md_ctx->md_info != NULL. This means that the mutex is initialized
* during the initial seeding in mbedtls_hmac_drbg_seed() or
* mbedtls_hmac_drbg_seed_buf() and freed in mbedtls_ctr_drbg_free().
*
* Note that this invariant may change without notice. Do not rely on it
* and do not access the mutex directly in application code.
*/
mbedtls_threading_mutex_t mutex;
#endif
} mbedtls_hmac_drbg_context;
/**
* \brief HMAC_DRBG context initialization.
*
* This function makes the context ready for mbedtls_hmac_drbg_seed(),
* mbedtls_hmac_drbg_seed_buf() or mbedtls_hmac_drbg_free().
*
* \note The reseed interval is #MBEDTLS_HMAC_DRBG_RESEED_INTERVAL
* by default. Override this value by calling
* mbedtls_hmac_drbg_set_reseed_interval().
*
* \param ctx HMAC_DRBG context to be initialized.
*/
void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx );
/**
* \brief HMAC_DRBG initial seeding.
*
* Set the initial seed and set up the entropy source for future reseeds.
*
* A typical choice for the \p f_entropy and \p p_entropy parameters is
* to use the entropy module:
* - \p f_entropy is mbedtls_entropy_func();
* - \p p_entropy is an instance of ::mbedtls_entropy_context initialized
* with mbedtls_entropy_init() (which registers the platform's default
* entropy sources).
*
* You can provide a personalization string in addition to the
* entropy source, to make this instantiation as unique as possible.
*
* \note By default, the security strength as defined by NIST is:
* - 128 bits if \p md_info is SHA-1;
* - 192 bits if \p md_info is SHA-224;
* - 256 bits if \p md_info is SHA-256, SHA-384 or SHA-512.
* Note that SHA-256 is just as efficient as SHA-224.
* The security strength can be reduced if a smaller
* entropy length is set with
* mbedtls_hmac_drbg_set_entropy_len().
*
* \note The default entropy length is the security strength
* (converted from bits to bytes). You can override
* it by calling mbedtls_hmac_drbg_set_entropy_len().
*
* \note During the initial seeding, this function calls
* the entropy source to obtain a nonce
* whose length is half the entropy length.
*/
#if defined(MBEDTLS_THREADING_C)
/**
* \note When Mbed TLS is built with threading support,
* after this function returns successfully,
* it is safe to call mbedtls_hmac_drbg_random()
* from multiple threads. Other operations, including
* reseeding, are not thread-safe.
*/
#endif /* MBEDTLS_THREADING_C */
/**
* \param ctx HMAC_DRBG context to be seeded.
* \param md_info MD algorithm to use for HMAC_DRBG.
* \param f_entropy The entropy callback, taking as arguments the
* \p p_entropy context, the buffer to fill, and the
* length of the buffer.
* \p f_entropy is always called with a length that is
* less than or equal to the entropy length.
* \param p_entropy The entropy context to pass to \p f_entropy.
* \param custom The personalization string.
* This can be \c NULL, in which case the personalization
* string is empty regardless of the value of \p len.
* \param len The length of the personalization string.
* This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT
* and also at most
* #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \p entropy_len * 3 / 2
* where \p entropy_len is the entropy length
* described above.
*
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info is
* invalid.
* \return #MBEDTLS_ERR_MD_ALLOC_FAILED if there was not enough
* memory to allocate context data.
* \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
* if the call to \p f_entropy failed.
*/
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 );
/**
* \brief Initilisation of simpified HMAC_DRBG (never reseeds).
*
* This function is meant for use in algorithms that need a pseudorandom
* input such as deterministic ECDSA.
*/
#if defined(MBEDTLS_THREADING_C)
/**
* \note When Mbed TLS is built with threading support,
* after this function returns successfully,
* it is safe to call mbedtls_hmac_drbg_random()
* from multiple threads. Other operations, including
* reseeding, are not thread-safe.
*/
#endif /* MBEDTLS_THREADING_C */
/**
* \param ctx HMAC_DRBG context to be initialised.
* \param md_info MD algorithm to use for HMAC_DRBG.
* \param data Concatenation of the initial entropy string and
* the additional data.
* \param data_len Length of \p data in bytes.
*
* \return \c 0 if successful. or
* \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info is
* invalid.
* \return #MBEDTLS_ERR_MD_ALLOC_FAILED if there was not enough
* memory to allocate context data.
*/
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 );
/**
* \brief This function turns prediction resistance on or off.
* The default value is off.
*
* \note If enabled, entropy is gathered at the beginning of
* every call to mbedtls_hmac_drbg_random_with_add()
* or mbedtls_hmac_drbg_random().
* Only use this if your entropy source has sufficient
* throughput.
*
* \param ctx The HMAC_DRBG context.
* \param resistance #MBEDTLS_HMAC_DRBG_PR_ON or #MBEDTLS_HMAC_DRBG_PR_OFF.
*/
void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
int resistance );
/**
* \brief This function sets the amount of entropy grabbed on each
* seed or reseed.
*
* See the documentation of mbedtls_hmac_drbg_seed() for the default value.
*
* \param ctx The HMAC_DRBG context.
* \param len The amount of entropy to grab, in bytes.
*/
void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx,
size_t len );
/**
* \brief Set the reseed interval.
*
* The reseed interval is the number of calls to mbedtls_hmac_drbg_random()
* or mbedtls_hmac_drbg_random_with_add() after which the entropy function
* is called again.
*
* The default value is #MBEDTLS_HMAC_DRBG_RESEED_INTERVAL.
*
* \param ctx The HMAC_DRBG context.
* \param interval The reseed interval.
*/
void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx,
int interval );
/**
* \brief This function updates the state of the HMAC_DRBG context.
*
* \note This function is not thread-safe. It is not safe
* to call this function if another thread might be
* concurrently obtaining random numbers from the same
* context or updating or reseeding the same context.
*
* \param ctx The HMAC_DRBG context.
* \param additional The data to update the state with.
* If this is \c NULL, there is no additional data.
* \param add_len Length of \p additional in bytes.
* Unused if \p additional is \c NULL.
*
* \return \c 0 on success, or an error from the underlying
* hash calculation.
*/
int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx,
const unsigned char *additional, size_t add_len );
/**
* \brief This function reseeds the HMAC_DRBG context, that is
* extracts data from the entropy source.
*
* \note This function is not thread-safe. It is not safe
* to call this function if another thread might be
* concurrently obtaining random numbers from the same
* context or updating or reseeding the same context.
*
* \param ctx The HMAC_DRBG context.
* \param additional Additional data to add to the state.
* If this is \c NULL, there is no additional data
* and \p len should be \c 0.
* \param len The length of the additional data.
* This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT
* and also at most
* #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \p entropy_len
* where \p entropy_len is the entropy length
* (see mbedtls_hmac_drbg_set_entropy_len()).
*
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
* if a call to the entropy function failed.
*/
int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
const unsigned char *additional, size_t len );
/**
* \brief This function updates an HMAC_DRBG instance with additional
* data and uses it to generate random data.
*
* This function automatically reseeds if the reseed counter is exceeded
* or prediction resistance is enabled.
*
* \note This function is not thread-safe. It is not safe
* to call this function if another thread might be
* concurrently obtaining random numbers from the same
* context or updating or reseeding the same context.
*
* \param p_rng The HMAC_DRBG context. This must be a pointer to a
* #mbedtls_hmac_drbg_context structure.
* \param output The buffer to fill.
* \param output_len The length of the buffer in bytes.
* This must be at most #MBEDTLS_HMAC_DRBG_MAX_REQUEST.
* \param additional Additional data to update with.
* If this is \c NULL, there is no additional data
* and \p add_len should be \c 0.
* \param add_len The length of the additional data.
* This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT.
*
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
* if a call to the entropy source failed.
* \return #MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG if
* \p output_len > #MBEDTLS_HMAC_DRBG_MAX_REQUEST.
* \return #MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG if
* \p add_len > #MBEDTLS_HMAC_DRBG_MAX_INPUT.
*/
int mbedtls_hmac_drbg_random_with_add( void *p_rng,
unsigned char *output, size_t output_len,
const unsigned char *additional,
size_t add_len );
/**
* \brief This function uses HMAC_DRBG to generate random data.
*
* This function automatically reseeds if the reseed counter is exceeded
* or prediction resistance is enabled.
*/
#if defined(MBEDTLS_THREADING_C)
/**
* \note When Mbed TLS is built with threading support,
* it is safe to call mbedtls_ctr_drbg_random()
* from multiple threads. Other operations, including
* reseeding, are not thread-safe.
*/
#endif /* MBEDTLS_THREADING_C */
/**
* \param p_rng The HMAC_DRBG context. This must be a pointer to a
* #mbedtls_hmac_drbg_context structure.
* \param output The buffer to fill.
* \param out_len The length of the buffer in bytes.
* This must be at most #MBEDTLS_HMAC_DRBG_MAX_REQUEST.
*
* \return \c 0 if successful.
* \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
* if a call to the entropy source failed.
* \return #MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG if
* \p out_len > #MBEDTLS_HMAC_DRBG_MAX_REQUEST.
*/
int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len );
/**
* \brief This function resets HMAC_DRBG context to the state immediately
* after initial call of mbedtls_hmac_drbg_init().
*
* \param ctx The HMAC_DRBG context to free.
*/
void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx );
#if ! defined(MBEDTLS_DEPRECATED_REMOVED)
#if defined(MBEDTLS_DEPRECATED_WARNING)
#define MBEDTLS_DEPRECATED __attribute__((deprecated))
#else
#define MBEDTLS_DEPRECATED
#endif
/**
* \brief This function updates the state of the HMAC_DRBG context.
*
* \deprecated Superseded by mbedtls_hmac_drbg_update_ret()
* in 2.16.0.
*
* \param ctx The HMAC_DRBG context.
* \param additional The data to update the state with.
* If this is \c NULL, there is no additional data.
* \param add_len Length of \p additional in bytes.
* Unused if \p additional is \c NULL.
*/
MBEDTLS_DEPRECATED void mbedtls_hmac_drbg_update(
mbedtls_hmac_drbg_context *ctx,
const unsigned char *additional, size_t add_len );
#undef MBEDTLS_DEPRECATED
#endif /* !MBEDTLS_DEPRECATED_REMOVED */
#if defined(MBEDTLS_FS_IO)
/**
* \brief This function writes a seed file.
*
* \param ctx The HMAC_DRBG context.
* \param path The name of the file.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR on file error.
* \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED on reseed
* failure.
*/
int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path );
/**
* \brief This function reads and updates a seed file. The seed
* is added to this instance.
*
* \param ctx The HMAC_DRBG context.
* \param path The name of the file.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR on file error.
* \return #MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED on
* reseed failure.
* \return #MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG if the existing
* seed file is too large.
*/
int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path );
#endif /* MBEDTLS_FS_IO */
#if defined(MBEDTLS_SELF_TEST)
/**
* \brief The HMAC_DRBG Checkup routine.
*
* \return \c 0 if successful.
* \return \c 1 if the test failed.
*/
int mbedtls_hmac_drbg_self_test( int verbose );
#endif
#ifdef __cplusplus
}
#endif
#endif /* hmac_drbg.h */

File diff suppressed because it is too large Load Diff

View File

@@ -1,29 +1,25 @@
/** /**
* \file md.h * \file md.h
* *
* \brief This file contains the generic message-digest wrapper. * \brief This file contains the generic message-digest wrapper.
* *
* \author Adriaan de Jong <dejong@fox-it.com> * \author Adriaan de Jong <dejong@fox-it.com>
*/ */
/* /*
* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of Mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
#ifndef MBEDTLS_MD_H #ifndef MBEDTLS_MD_H
@@ -32,7 +28,7 @@
#include <stddef.h> #include <stddef.h>
#if !defined(MBEDTLS_CONFIG_FILE) #if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h" #include "mbedtls/config.h"
#else #else
#include MBEDTLS_CONFIG_FILE #include MBEDTLS_CONFIG_FILE
#endif #endif
@@ -41,6 +37,8 @@
#define MBEDTLS_ERR_MD_BAD_INPUT_DATA -0x5100 /**< Bad input parameters to function. */ #define MBEDTLS_ERR_MD_BAD_INPUT_DATA -0x5100 /**< Bad input parameters to function. */
#define MBEDTLS_ERR_MD_ALLOC_FAILED -0x5180 /**< Failed to allocate memory. */ #define MBEDTLS_ERR_MD_ALLOC_FAILED -0x5180 /**< Failed to allocate memory. */
#define MBEDTLS_ERR_MD_FILE_IO_ERROR -0x5200 /**< Opening or reading of file failed. */ #define MBEDTLS_ERR_MD_FILE_IO_ERROR -0x5200 /**< Opening or reading of file failed. */
/* MBEDTLS_ERR_MD_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_MD_HW_ACCEL_FAILED -0x5280 /**< MD hardware accelerator failed. */ #define MBEDTLS_ERR_MD_HW_ACCEL_FAILED -0x5280 /**< MD hardware accelerator failed. */
#ifdef __cplusplus #ifdef __cplusplus
@@ -56,7 +54,7 @@ extern "C" {
* *
*/ */
typedef enum { typedef enum {
MBEDTLS_MD_NONE = 0, /**< None. */ MBEDTLS_MD_NONE=0, /**< None. */
MBEDTLS_MD_MD2, /**< The MD2 message digest. */ MBEDTLS_MD_MD2, /**< The MD2 message digest. */
MBEDTLS_MD_MD4, /**< The MD4 message digest. */ MBEDTLS_MD_MD4, /**< The MD4 message digest. */
MBEDTLS_MD_MD5, /**< The MD5 message digest. */ MBEDTLS_MD_MD5, /**< The MD5 message digest. */
@@ -74,6 +72,12 @@ typedef enum {
#define MBEDTLS_MD_MAX_SIZE 32 /* longest known is SHA256 or less */ #define MBEDTLS_MD_MAX_SIZE 32 /* longest known is SHA256 or less */
#endif #endif
#if defined(MBEDTLS_SHA512_C)
#define MBEDTLS_MD_MAX_BLOCK_SIZE 128
#else
#define MBEDTLS_MD_MAX_BLOCK_SIZE 64
#endif
/** /**
* Opaque struct defined in md_internal.h. * Opaque struct defined in md_internal.h.
*/ */
@@ -82,7 +86,8 @@ typedef struct mbedtls_md_info_t mbedtls_md_info_t;
/** /**
* The generic message-digest context. * The generic message-digest context.
*/ */
typedef struct mbedtls_md_context_t { typedef struct mbedtls_md_context_t
{
/** Information about the associated message digest. */ /** Information about the associated message digest. */
const mbedtls_md_info_t *md_info; const mbedtls_md_info_t *md_info;
@@ -97,12 +102,14 @@ typedef struct mbedtls_md_context_t {
* \brief This function returns the list of digests supported by the * \brief This function returns the list of digests supported by the
* generic digest module. * generic digest module.
* *
* \note The list starts with the strongest available hashes.
*
* \return A statically allocated array of digests. Each element * \return A statically allocated array of digests. Each element
* in the returned list is an integer belonging to the * in the returned list is an integer belonging to the
* message-digest enumeration #mbedtls_md_type_t. * message-digest enumeration #mbedtls_md_type_t.
* The last entry is 0. * The last entry is 0.
*/ */
const int *mbedtls_md_list(void); const int *mbedtls_md_list( void );
/** /**
* \brief This function returns the message-digest information * \brief This function returns the message-digest information
@@ -113,7 +120,7 @@ const int *mbedtls_md_list(void);
* \return The message-digest information associated with \p md_name. * \return The message-digest information associated with \p md_name.
* \return NULL if the associated message-digest information is not found. * \return NULL if the associated message-digest information is not found.
*/ */
const mbedtls_md_info_t *mbedtls_md_info_from_string(const char *md_name); const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name );
/** /**
* \brief This function returns the message-digest information * \brief This function returns the message-digest information
@@ -124,7 +131,7 @@ const mbedtls_md_info_t *mbedtls_md_info_from_string(const char *md_name);
* \return The message-digest information associated with \p md_type. * \return The message-digest information associated with \p md_type.
* \return NULL if the associated message-digest information is not found. * \return NULL if the associated message-digest information is not found.
*/ */
const mbedtls_md_info_t *mbedtls_md_info_from_type(mbedtls_md_type_t md_type); const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type );
/** /**
* \brief This function initializes a message-digest context without * \brief This function initializes a message-digest context without
@@ -134,7 +141,7 @@ const mbedtls_md_info_t *mbedtls_md_info_from_type(mbedtls_md_type_t md_type);
* context for mbedtls_md_setup() for binding it to a * context for mbedtls_md_setup() for binding it to a
* message-digest algorithm. * message-digest algorithm.
*/ */
void mbedtls_md_init(mbedtls_md_context_t *ctx); void mbedtls_md_init( mbedtls_md_context_t *ctx );
/** /**
* \brief This function clears the internal structure of \p ctx and * \brief This function clears the internal structure of \p ctx and
@@ -149,7 +156,7 @@ void mbedtls_md_init(mbedtls_md_context_t *ctx);
* You must not call this function if you have not called * You must not call this function if you have not called
* mbedtls_md_init(). * mbedtls_md_init().
*/ */
void mbedtls_md_free(mbedtls_md_context_t *ctx); void mbedtls_md_free( mbedtls_md_context_t *ctx );
#if ! defined(MBEDTLS_DEPRECATED_REMOVED) #if ! defined(MBEDTLS_DEPRECATED_REMOVED)
#if defined(MBEDTLS_DEPRECATED_WARNING) #if defined(MBEDTLS_DEPRECATED_WARNING)
@@ -175,7 +182,7 @@ void mbedtls_md_free(mbedtls_md_context_t *ctx);
* failure. * failure.
* \return #MBEDTLS_ERR_MD_ALLOC_FAILED on memory-allocation failure. * \return #MBEDTLS_ERR_MD_ALLOC_FAILED on memory-allocation failure.
*/ */
int mbedtls_md_init_ctx(mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info) MBEDTLS_DEPRECATED; int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info ) MBEDTLS_DEPRECATED;
#undef MBEDTLS_DEPRECATED #undef MBEDTLS_DEPRECATED
#endif /* MBEDTLS_DEPRECATED_REMOVED */ #endif /* MBEDTLS_DEPRECATED_REMOVED */
@@ -198,7 +205,7 @@ int mbedtls_md_init_ctx(mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_i
* failure. * failure.
* \return #MBEDTLS_ERR_MD_ALLOC_FAILED on memory-allocation failure. * \return #MBEDTLS_ERR_MD_ALLOC_FAILED on memory-allocation failure.
*/ */
int mbedtls_md_setup(mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac); int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac );
/** /**
* \brief This function clones the state of an message-digest * \brief This function clones the state of an message-digest
@@ -219,8 +226,8 @@ int mbedtls_md_setup(mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info
* \return \c 0 on success. * \return \c 0 on success.
* \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification failure. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification failure.
*/ */
int mbedtls_md_clone(mbedtls_md_context_t *dst, int mbedtls_md_clone( mbedtls_md_context_t *dst,
const mbedtls_md_context_t *src); const mbedtls_md_context_t *src );
/** /**
* \brief This function extracts the message-digest size from the * \brief This function extracts the message-digest size from the
@@ -231,7 +238,7 @@ int mbedtls_md_clone(mbedtls_md_context_t *dst,
* *
* \return The size of the message-digest output in Bytes. * \return The size of the message-digest output in Bytes.
*/ */
unsigned char mbedtls_md_get_size(const mbedtls_md_info_t *md_info); unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info );
/** /**
* \brief This function extracts the message-digest type from the * \brief This function extracts the message-digest type from the
@@ -242,7 +249,7 @@ unsigned char mbedtls_md_get_size(const mbedtls_md_info_t *md_info);
* *
* \return The type of the message digest. * \return The type of the message digest.
*/ */
mbedtls_md_type_t mbedtls_md_get_type(const mbedtls_md_info_t *md_info); mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info );
/** /**
* \brief This function extracts the message-digest name from the * \brief This function extracts the message-digest name from the
@@ -253,7 +260,7 @@ mbedtls_md_type_t mbedtls_md_get_type(const mbedtls_md_info_t *md_info);
* *
* \return The name of the message digest. * \return The name of the message digest.
*/ */
const char *mbedtls_md_get_name(const mbedtls_md_info_t *md_info); const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info );
/** /**
* \brief This function starts a message-digest computation. * \brief This function starts a message-digest computation.
@@ -268,7 +275,7 @@ const char *mbedtls_md_get_name(const mbedtls_md_info_t *md_info);
* \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification
* failure. * failure.
*/ */
int mbedtls_md_starts(mbedtls_md_context_t *ctx); int mbedtls_md_starts( mbedtls_md_context_t *ctx );
/** /**
* \brief This function feeds an input buffer into an ongoing * \brief This function feeds an input buffer into an ongoing
@@ -286,7 +293,7 @@ int mbedtls_md_starts(mbedtls_md_context_t *ctx);
* \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification
* failure. * failure.
*/ */
int mbedtls_md_update(mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen); int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen );
/** /**
* \brief This function finishes the digest operation, * \brief This function finishes the digest operation,
@@ -306,7 +313,7 @@ int mbedtls_md_update(mbedtls_md_context_t *ctx, const unsigned char *input, siz
* \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification
* failure. * failure.
*/ */
int mbedtls_md_finish(mbedtls_md_context_t *ctx, unsigned char *output); int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output );
/** /**
* \brief This function calculates the message-digest of a buffer, * \brief This function calculates the message-digest of a buffer,
@@ -326,8 +333,8 @@ int mbedtls_md_finish(mbedtls_md_context_t *ctx, unsigned char *output);
* \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification
* failure. * failure.
*/ */
int mbedtls_md(const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen,
unsigned char *output); unsigned char *output );
#if defined(MBEDTLS_FS_IO) #if defined(MBEDTLS_FS_IO)
/** /**
@@ -347,8 +354,8 @@ int mbedtls_md(const mbedtls_md_info_t *md_info, const unsigned char *input, siz
* the file pointed by \p path. * the file pointed by \p path.
* \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info was NULL. * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info was NULL.
*/ */
int mbedtls_md_file(const mbedtls_md_info_t *md_info, const char *path, int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path,
unsigned char *output); unsigned char *output );
#endif /* MBEDTLS_FS_IO */ #endif /* MBEDTLS_FS_IO */
/** /**
@@ -369,8 +376,8 @@ int mbedtls_md_file(const mbedtls_md_info_t *md_info, const char *path,
* \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification
* failure. * failure.
*/ */
int mbedtls_md_hmac_starts(mbedtls_md_context_t *ctx, const unsigned char *key, int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key,
size_t keylen); size_t keylen );
/** /**
* \brief This function feeds an input buffer into an ongoing HMAC * \brief This function feeds an input buffer into an ongoing HMAC
@@ -391,8 +398,8 @@ int mbedtls_md_hmac_starts(mbedtls_md_context_t *ctx, const unsigned char *key,
* \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification
* failure. * failure.
*/ */
int mbedtls_md_hmac_update(mbedtls_md_context_t *ctx, const unsigned char *input, int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input,
size_t ilen); size_t ilen );
/** /**
* \brief This function finishes the HMAC operation, and writes * \brief This function finishes the HMAC operation, and writes
@@ -412,7 +419,7 @@ int mbedtls_md_hmac_update(mbedtls_md_context_t *ctx, const unsigned char *input
* \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification
* failure. * failure.
*/ */
int mbedtls_md_hmac_finish(mbedtls_md_context_t *ctx, unsigned char *output); int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output);
/** /**
* \brief This function prepares to authenticate a new message with * \brief This function prepares to authenticate a new message with
@@ -429,7 +436,7 @@ int mbedtls_md_hmac_finish(mbedtls_md_context_t *ctx, unsigned char *output);
* \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification
* failure. * failure.
*/ */
int mbedtls_md_hmac_reset(mbedtls_md_context_t *ctx); int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx );
/** /**
* \brief This function calculates the full generic HMAC * \brief This function calculates the full generic HMAC
@@ -453,12 +460,12 @@ int mbedtls_md_hmac_reset(mbedtls_md_context_t *ctx);
* \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification
* failure. * failure.
*/ */
int mbedtls_md_hmac(const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen, int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen,
const unsigned char *input, size_t ilen, const unsigned char *input, size_t ilen,
unsigned char *output); unsigned char *output );
/* Internal use */ /* Internal use */
int mbedtls_md_process(mbedtls_md_context_t *ctx, const unsigned char *data); int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data );
#ifdef __cplusplus #ifdef __cplusplus
} }

360
common/mbedtls/md2.c Normal file
View File

@@ -0,0 +1,360 @@
/*
* RFC 1115/1319 compliant MD2 implementation
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* The MD2 algorithm was designed by Ron Rivest in 1989.
*
* http://www.ietf.org/rfc/rfc1115.txt
* http://www.ietf.org/rfc/rfc1319.txt
*/
#include "common.h"
#if defined(MBEDTLS_MD2_C)
#include "mbedtls/md2.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#include <string.h>
#if defined(MBEDTLS_SELF_TEST)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */
#if !defined(MBEDTLS_MD2_ALT)
static const unsigned char PI_SUBST[256] =
{
0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36,
0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3,
0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C,
0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16,
0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, 0xBE, 0x4E,
0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E,
0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2,
0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21,
0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E,
0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, 0xFF, 0x19, 0x30, 0xB3,
0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56,
0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6,
0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D,
0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65,
0xE6, 0x2D, 0xA8, 0x02, 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0,
0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F,
0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C,
0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E,
0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81,
0x4D, 0x52, 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA,
0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88,
0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE,
0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58,
0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A,
0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99,
0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14
};
void mbedtls_md2_init( mbedtls_md2_context *ctx )
{
memset( ctx, 0, sizeof( mbedtls_md2_context ) );
}
void mbedtls_md2_free( mbedtls_md2_context *ctx )
{
if( ctx == NULL )
return;
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md2_context ) );
}
void mbedtls_md2_clone( mbedtls_md2_context *dst,
const mbedtls_md2_context *src )
{
*dst = *src;
}
/*
* MD2 context setup
*/
int mbedtls_md2_starts_ret( mbedtls_md2_context *ctx )
{
memset( ctx->cksum, 0, 16 );
memset( ctx->state, 0, 46 );
memset( ctx->buffer, 0, 16 );
ctx->left = 0;
return( 0 );
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_md2_starts( mbedtls_md2_context *ctx )
{
mbedtls_md2_starts_ret( ctx );
}
#endif
#if !defined(MBEDTLS_MD2_PROCESS_ALT)
int mbedtls_internal_md2_process( mbedtls_md2_context *ctx )
{
int i, j;
unsigned char t = 0;
for( i = 0; i < 16; i++ )
{
ctx->state[i + 16] = ctx->buffer[i];
ctx->state[i + 32] =
(unsigned char)( ctx->buffer[i] ^ ctx->state[i]);
}
for( i = 0; i < 18; i++ )
{
for( j = 0; j < 48; j++ )
{
ctx->state[j] = (unsigned char)
( ctx->state[j] ^ PI_SUBST[t] );
t = ctx->state[j];
}
t = (unsigned char)( t + i );
}
t = ctx->cksum[15];
for( i = 0; i < 16; i++ )
{
ctx->cksum[i] = (unsigned char)
( ctx->cksum[i] ^ PI_SUBST[ctx->buffer[i] ^ t] );
t = ctx->cksum[i];
}
/* Zeroise variables to clear sensitive data from memory. */
mbedtls_platform_zeroize( &t, sizeof( t ) );
return( 0 );
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_md2_process( mbedtls_md2_context *ctx )
{
mbedtls_internal_md2_process( ctx );
}
#endif
#endif /* !MBEDTLS_MD2_PROCESS_ALT */
/*
* MD2 process buffer
*/
int mbedtls_md2_update_ret( mbedtls_md2_context *ctx,
const unsigned char *input,
size_t ilen )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t fill;
while( ilen > 0 )
{
if( ilen > 16 - ctx->left )
fill = 16 - ctx->left;
else
fill = ilen;
memcpy( ctx->buffer + ctx->left, input, fill );
ctx->left += fill;
input += fill;
ilen -= fill;
if( ctx->left == 16 )
{
ctx->left = 0;
if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 )
return( ret );
}
}
return( 0 );
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_md2_update( mbedtls_md2_context *ctx,
const unsigned char *input,
size_t ilen )
{
mbedtls_md2_update_ret( ctx, input, ilen );
}
#endif
/*
* MD2 final digest
*/
int mbedtls_md2_finish_ret( mbedtls_md2_context *ctx,
unsigned char output[16] )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i;
unsigned char x;
x = (unsigned char)( 16 - ctx->left );
for( i = ctx->left; i < 16; i++ )
ctx->buffer[i] = x;
if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 )
return( ret );
memcpy( ctx->buffer, ctx->cksum, 16 );
if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 )
return( ret );
memcpy( output, ctx->state, 16 );
return( 0 );
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_md2_finish( mbedtls_md2_context *ctx,
unsigned char output[16] )
{
mbedtls_md2_finish_ret( ctx, output );
}
#endif
#endif /* !MBEDTLS_MD2_ALT */
/*
* output = MD2( input buffer )
*/
int mbedtls_md2_ret( const unsigned char *input,
size_t ilen,
unsigned char output[16] )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_md2_context ctx;
mbedtls_md2_init( &ctx );
if( ( ret = mbedtls_md2_starts_ret( &ctx ) ) != 0 )
goto exit;
if( ( ret = mbedtls_md2_update_ret( &ctx, input, ilen ) ) != 0 )
goto exit;
if( ( ret = mbedtls_md2_finish_ret( &ctx, output ) ) != 0 )
goto exit;
exit:
mbedtls_md2_free( &ctx );
return( ret );
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_md2( const unsigned char *input,
size_t ilen,
unsigned char output[16] )
{
mbedtls_md2_ret( input, ilen, output );
}
#endif
#if defined(MBEDTLS_SELF_TEST)
/*
* RFC 1319 test vectors
*/
static const unsigned char md2_test_str[7][81] =
{
{ "" },
{ "a" },
{ "abc" },
{ "message digest" },
{ "abcdefghijklmnopqrstuvwxyz" },
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
{ "12345678901234567890123456789012345678901234567890123456789012345678901234567890" }
};
static const size_t md2_test_strlen[7] =
{
0, 1, 3, 14, 26, 62, 80
};
static const unsigned char md2_test_sum[7][16] =
{
{ 0x83, 0x50, 0xE5, 0xA3, 0xE2, 0x4C, 0x15, 0x3D,
0xF2, 0x27, 0x5C, 0x9F, 0x80, 0x69, 0x27, 0x73 },
{ 0x32, 0xEC, 0x01, 0xEC, 0x4A, 0x6D, 0xAC, 0x72,
0xC0, 0xAB, 0x96, 0xFB, 0x34, 0xC0, 0xB5, 0xD1 },
{ 0xDA, 0x85, 0x3B, 0x0D, 0x3F, 0x88, 0xD9, 0x9B,
0x30, 0x28, 0x3A, 0x69, 0xE6, 0xDE, 0xD6, 0xBB },
{ 0xAB, 0x4F, 0x49, 0x6B, 0xFB, 0x2A, 0x53, 0x0B,
0x21, 0x9F, 0xF3, 0x30, 0x31, 0xFE, 0x06, 0xB0 },
{ 0x4E, 0x8D, 0xDF, 0xF3, 0x65, 0x02, 0x92, 0xAB,
0x5A, 0x41, 0x08, 0xC3, 0xAA, 0x47, 0x94, 0x0B },
{ 0xDA, 0x33, 0xDE, 0xF2, 0xA4, 0x2D, 0xF1, 0x39,
0x75, 0x35, 0x28, 0x46, 0xC3, 0x03, 0x38, 0xCD },
{ 0xD5, 0x97, 0x6F, 0x79, 0xD8, 0x3D, 0x3A, 0x0D,
0xC9, 0x80, 0x6C, 0x3C, 0x66, 0xF3, 0xEF, 0xD8 }
};
/*
* Checkup routine
*/
int mbedtls_md2_self_test( int verbose )
{
int i, ret = 0;
unsigned char md2sum[16];
for( i = 0; i < 7; i++ )
{
if( verbose != 0 )
mbedtls_printf( " MD2 test #%d: ", i + 1 );
ret = mbedtls_md2_ret( md2_test_str[i], md2_test_strlen[i], md2sum );
if( ret != 0 )
goto fail;
if( memcmp( md2sum, md2_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_MD2_C */

304
common/mbedtls/md2.h Normal file
View File

@@ -0,0 +1,304 @@
/**
* \file md2.h
*
* \brief MD2 message digest algorithm (hash function)
*
* \warning MD2 is considered a weak message digest and its use constitutes a
* security risk. We recommend considering stronger message digests
* instead.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef MBEDTLS_MD2_H
#define MBEDTLS_MD2_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include <stddef.h>
/* MBEDTLS_ERR_MD2_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_MD2_HW_ACCEL_FAILED -0x002B /**< MD2 hardware accelerator failed */
#ifdef __cplusplus
extern "C" {
#endif
#if !defined(MBEDTLS_MD2_ALT)
// Regular implementation
//
/**
* \brief MD2 context structure
*
* \warning MD2 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
typedef struct mbedtls_md2_context
{
unsigned char cksum[16]; /*!< checksum of the data block */
unsigned char state[48]; /*!< intermediate digest state */
unsigned char buffer[16]; /*!< data block being processed */
size_t left; /*!< amount of data in buffer */
}
mbedtls_md2_context;
#else /* MBEDTLS_MD2_ALT */
#include "md2_alt.h"
#endif /* MBEDTLS_MD2_ALT */
/**
* \brief Initialize MD2 context
*
* \param ctx MD2 context to be initialized
*
* \warning MD2 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
void mbedtls_md2_init( mbedtls_md2_context *ctx );
/**
* \brief Clear MD2 context
*
* \param ctx MD2 context to be cleared
*
* \warning MD2 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
void mbedtls_md2_free( mbedtls_md2_context *ctx );
/**
* \brief Clone (the state of) an MD2 context
*
* \param dst The destination context
* \param src The context to be cloned
*
* \warning MD2 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
void mbedtls_md2_clone( mbedtls_md2_context *dst,
const mbedtls_md2_context *src );
/**
* \brief MD2 context setup
*
* \param ctx context to be initialized
*
* \return 0 if successful
*
* \warning MD2 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
int mbedtls_md2_starts_ret( mbedtls_md2_context *ctx );
/**
* \brief MD2 process buffer
*
* \param ctx MD2 context
* \param input buffer holding the data
* \param ilen length of the input data
*
* \return 0 if successful
*
* \warning MD2 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
int mbedtls_md2_update_ret( mbedtls_md2_context *ctx,
const unsigned char *input,
size_t ilen );
/**
* \brief MD2 final digest
*
* \param ctx MD2 context
* \param output MD2 checksum result
*
* \return 0 if successful
*
* \warning MD2 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
int mbedtls_md2_finish_ret( mbedtls_md2_context *ctx,
unsigned char output[16] );
/**
* \brief MD2 process data block (internal use only)
*
* \param ctx MD2 context
*
* \return 0 if successful
*
* \warning MD2 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
int mbedtls_internal_md2_process( mbedtls_md2_context *ctx );
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
#if defined(MBEDTLS_DEPRECATED_WARNING)
#define MBEDTLS_DEPRECATED __attribute__((deprecated))
#else
#define MBEDTLS_DEPRECATED
#endif
/**
* \brief MD2 context setup
*
* \deprecated Superseded by mbedtls_md2_starts_ret() in 2.7.0
*
* \param ctx context to be initialized
*
* \warning MD2 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
MBEDTLS_DEPRECATED void mbedtls_md2_starts( mbedtls_md2_context *ctx );
/**
* \brief MD2 process buffer
*
* \deprecated Superseded by mbedtls_md2_update_ret() in 2.7.0
*
* \param ctx MD2 context
* \param input buffer holding the data
* \param ilen length of the input data
*
* \warning MD2 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
MBEDTLS_DEPRECATED void mbedtls_md2_update( mbedtls_md2_context *ctx,
const unsigned char *input,
size_t ilen );
/**
* \brief MD2 final digest
*
* \deprecated Superseded by mbedtls_md2_finish_ret() in 2.7.0
*
* \param ctx MD2 context
* \param output MD2 checksum result
*
* \warning MD2 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
MBEDTLS_DEPRECATED void mbedtls_md2_finish( mbedtls_md2_context *ctx,
unsigned char output[16] );
/**
* \brief MD2 process data block (internal use only)
*
* \deprecated Superseded by mbedtls_internal_md2_process() in 2.7.0
*
* \param ctx MD2 context
*
* \warning MD2 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
MBEDTLS_DEPRECATED void mbedtls_md2_process( mbedtls_md2_context *ctx );
#undef MBEDTLS_DEPRECATED
#endif /* !MBEDTLS_DEPRECATED_REMOVED */
/**
* \brief Output = MD2( input buffer )
*
* \param input buffer holding the data
* \param ilen length of the input data
* \param output MD2 checksum result
*
* \warning MD2 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
int mbedtls_md2_ret( const unsigned char *input,
size_t ilen,
unsigned char output[16] );
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
#if defined(MBEDTLS_DEPRECATED_WARNING)
#define MBEDTLS_DEPRECATED __attribute__((deprecated))
#else
#define MBEDTLS_DEPRECATED
#endif
/**
* \brief Output = MD2( input buffer )
*
* \deprecated Superseded by mbedtls_md2_ret() in 2.7.0
*
* \param input buffer holding the data
* \param ilen length of the input data
* \param output MD2 checksum result
*
* \warning MD2 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
MBEDTLS_DEPRECATED void mbedtls_md2( const unsigned char *input,
size_t ilen,
unsigned char output[16] );
#undef MBEDTLS_DEPRECATED
#endif /* !MBEDTLS_DEPRECATED_REMOVED */
#if defined(MBEDTLS_SELF_TEST)
/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if the test failed
*
* \warning MD2 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
int mbedtls_md2_self_test( int verbose );
#endif /* MBEDTLS_SELF_TEST */
#ifdef __cplusplus
}
#endif
#endif /* mbedtls_md2.h */

484
common/mbedtls/md4.c Normal file
View File

@@ -0,0 +1,484 @@
/*
* RFC 1186/1320 compliant MD4 implementation
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* The MD4 algorithm was designed by Ron Rivest in 1990.
*
* http://www.ietf.org/rfc/rfc1186.txt
* http://www.ietf.org/rfc/rfc1320.txt
*/
#include "common.h"
#if defined(MBEDTLS_MD4_C)
#include "mbedtls/md4.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#include <string.h>
#if defined(MBEDTLS_SELF_TEST)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */
#if !defined(MBEDTLS_MD4_ALT)
/*
* 32-bit integer manipulation macros (little endian)
*/
#ifndef GET_UINT32_LE
#define GET_UINT32_LE(n,b,i) \
{ \
(n) = ( (uint32_t) (b)[(i) ] ) \
| ( (uint32_t) (b)[(i) + 1] << 8 ) \
| ( (uint32_t) (b)[(i) + 2] << 16 ) \
| ( (uint32_t) (b)[(i) + 3] << 24 ); \
}
#endif
#ifndef PUT_UINT32_LE
#define PUT_UINT32_LE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
(b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
(b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
(b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
}
#endif
void mbedtls_md4_init( mbedtls_md4_context *ctx )
{
memset( ctx, 0, sizeof( mbedtls_md4_context ) );
}
void mbedtls_md4_free( mbedtls_md4_context *ctx )
{
if( ctx == NULL )
return;
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md4_context ) );
}
void mbedtls_md4_clone( mbedtls_md4_context *dst,
const mbedtls_md4_context *src )
{
*dst = *src;
}
/*
* MD4 context setup
*/
int mbedtls_md4_starts_ret( mbedtls_md4_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_DEPRECATED_REMOVED)
void mbedtls_md4_starts( mbedtls_md4_context *ctx )
{
mbedtls_md4_starts_ret( ctx );
}
#endif
#if !defined(MBEDTLS_MD4_PROCESS_ALT)
int mbedtls_internal_md4_process( mbedtls_md4_context *ctx,
const unsigned char data[64] )
{
struct
{
uint32_t X[16], A, B, C, D;
} local;
GET_UINT32_LE( local.X[ 0], data, 0 );
GET_UINT32_LE( local.X[ 1], data, 4 );
GET_UINT32_LE( local.X[ 2], data, 8 );
GET_UINT32_LE( local.X[ 3], data, 12 );
GET_UINT32_LE( local.X[ 4], data, 16 );
GET_UINT32_LE( local.X[ 5], data, 20 );
GET_UINT32_LE( local.X[ 6], data, 24 );
GET_UINT32_LE( local.X[ 7], data, 28 );
GET_UINT32_LE( local.X[ 8], data, 32 );
GET_UINT32_LE( local.X[ 9], data, 36 );
GET_UINT32_LE( local.X[10], data, 40 );
GET_UINT32_LE( local.X[11], data, 44 );
GET_UINT32_LE( local.X[12], data, 48 );
GET_UINT32_LE( local.X[13], data, 52 );
GET_UINT32_LE( local.X[14], data, 56 );
GET_UINT32_LE( local.X[15], data, 60 );
#define S(x,n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n))))
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) (((x) & (y)) | ((~(x)) & (z)))
#define P(a,b,c,d,x,s) \
do \
{ \
(a) += F((b),(c),(d)) + (x); \
(a) = S((a),(s)); \
} while( 0 )
P( local.A, local.B, local.C, local.D, local.X[ 0], 3 );
P( local.D, local.A, local.B, local.C, local.X[ 1], 7 );
P( local.C, local.D, local.A, local.B, local.X[ 2], 11 );
P( local.B, local.C, local.D, local.A, local.X[ 3], 19 );
P( local.A, local.B, local.C, local.D, local.X[ 4], 3 );
P( local.D, local.A, local.B, local.C, local.X[ 5], 7 );
P( local.C, local.D, local.A, local.B, local.X[ 6], 11 );
P( local.B, local.C, local.D, local.A, local.X[ 7], 19 );
P( local.A, local.B, local.C, local.D, local.X[ 8], 3 );
P( local.D, local.A, local.B, local.C, local.X[ 9], 7 );
P( local.C, local.D, local.A, local.B, local.X[10], 11 );
P( local.B, local.C, local.D, local.A, local.X[11], 19 );
P( local.A, local.B, local.C, local.D, local.X[12], 3 );
P( local.D, local.A, local.B, local.C, local.X[13], 7 );
P( local.C, local.D, local.A, local.B, local.X[14], 11 );
P( local.B, local.C, local.D, local.A, local.X[15], 19 );
#undef P
#undef F
#define F(x,y,z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
#define P(a,b,c,d,x,s) \
do \
{ \
(a) += F((b),(c),(d)) + (x) + 0x5A827999; \
(a) = S((a),(s)); \
} while( 0 )
P( local.A, local.B, local.C, local.D, local.X[ 0], 3 );
P( local.D, local.A, local.B, local.C, local.X[ 4], 5 );
P( local.C, local.D, local.A, local.B, local.X[ 8], 9 );
P( local.B, local.C, local.D, local.A, local.X[12], 13 );
P( local.A, local.B, local.C, local.D, local.X[ 1], 3 );
P( local.D, local.A, local.B, local.C, local.X[ 5], 5 );
P( local.C, local.D, local.A, local.B, local.X[ 9], 9 );
P( local.B, local.C, local.D, local.A, local.X[13], 13 );
P( local.A, local.B, local.C, local.D, local.X[ 2], 3 );
P( local.D, local.A, local.B, local.C, local.X[ 6], 5 );
P( local.C, local.D, local.A, local.B, local.X[10], 9 );
P( local.B, local.C, local.D, local.A, local.X[14], 13 );
P( local.A, local.B, local.C, local.D, local.X[ 3], 3 );
P( local.D, local.A, local.B, local.C, local.X[ 7], 5 );
P( local.C, local.D, local.A, local.B, local.X[11], 9 );
P( local.B, local.C, local.D, local.A, local.X[15], 13 );
#undef P
#undef F
#define F(x,y,z) ((x) ^ (y) ^ (z))
#define P(a,b,c,d,x,s) \
do \
{ \
(a) += F((b),(c),(d)) + (x) + 0x6ED9EBA1; \
(a) = S((a),(s)); \
} while( 0 )
P( local.A, local.B, local.C, local.D, local.X[ 0], 3 );
P( local.D, local.A, local.B, local.C, local.X[ 8], 9 );
P( local.C, local.D, local.A, local.B, local.X[ 4], 11 );
P( local.B, local.C, local.D, local.A, local.X[12], 15 );
P( local.A, local.B, local.C, local.D, local.X[ 2], 3 );
P( local.D, local.A, local.B, local.C, local.X[10], 9 );
P( local.C, local.D, local.A, local.B, local.X[ 6], 11 );
P( local.B, local.C, local.D, local.A, local.X[14], 15 );
P( local.A, local.B, local.C, local.D, local.X[ 1], 3 );
P( local.D, local.A, local.B, local.C, local.X[ 9], 9 );
P( local.C, local.D, local.A, local.B, local.X[ 5], 11 );
P( local.B, local.C, local.D, local.A, local.X[13], 15 );
P( local.A, local.B, local.C, local.D, local.X[ 3], 3 );
P( local.D, local.A, local.B, local.C, local.X[11], 9 );
P( local.C, local.D, local.A, local.B, local.X[ 7], 11 );
P( local.B, local.C, local.D, local.A, local.X[15], 15 );
#undef F
#undef P
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 );
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_md4_process( mbedtls_md4_context *ctx,
const unsigned char data[64] )
{
mbedtls_internal_md4_process( ctx, data );
}
#endif
#endif /* !MBEDTLS_MD4_PROCESS_ALT */
/*
* MD4 process buffer
*/
int mbedtls_md4_update_ret( mbedtls_md4_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),
(void *) input, fill );
if( ( ret = mbedtls_internal_md4_process( ctx, ctx->buffer ) ) != 0 )
return( ret );
input += fill;
ilen -= fill;
left = 0;
}
while( ilen >= 64 )
{
if( ( ret = mbedtls_internal_md4_process( ctx, input ) ) != 0 )
return( ret );
input += 64;
ilen -= 64;
}
if( ilen > 0 )
{
memcpy( (void *) (ctx->buffer + left),
(void *) input, ilen );
}
return( 0 );
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_md4_update( mbedtls_md4_context *ctx,
const unsigned char *input,
size_t ilen )
{
mbedtls_md4_update_ret( ctx, input, ilen );
}
#endif
static const unsigned char md4_padding[64] =
{
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* MD4 final digest
*/
int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx,
unsigned char output[16] )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
uint32_t last, padn;
uint32_t high, low;
unsigned char msglen[8];
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT32_LE( low, msglen, 0 );
PUT_UINT32_LE( high, msglen, 4 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
ret = mbedtls_md4_update_ret( ctx, (unsigned char *)md4_padding, padn );
if( ret != 0 )
return( ret );
if( ( ret = mbedtls_md4_update_ret( ctx, msglen, 8 ) ) != 0 )
return( ret );
PUT_UINT32_LE( ctx->state[0], output, 0 );
PUT_UINT32_LE( ctx->state[1], output, 4 );
PUT_UINT32_LE( ctx->state[2], output, 8 );
PUT_UINT32_LE( ctx->state[3], output, 12 );
return( 0 );
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_md4_finish( mbedtls_md4_context *ctx,
unsigned char output[16] )
{
mbedtls_md4_finish_ret( ctx, output );
}
#endif
#endif /* !MBEDTLS_MD4_ALT */
/*
* output = MD4( input buffer )
*/
int mbedtls_md4_ret( const unsigned char *input,
size_t ilen,
unsigned char output[16] )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_md4_context ctx;
mbedtls_md4_init( &ctx );
if( ( ret = mbedtls_md4_starts_ret( &ctx ) ) != 0 )
goto exit;
if( ( ret = mbedtls_md4_update_ret( &ctx, input, ilen ) ) != 0 )
goto exit;
if( ( ret = mbedtls_md4_finish_ret( &ctx, output ) ) != 0 )
goto exit;
exit:
mbedtls_md4_free( &ctx );
return( ret );
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_md4( const unsigned char *input,
size_t ilen,
unsigned char output[16] )
{
mbedtls_md4_ret( input, ilen, output );
}
#endif
#if defined(MBEDTLS_SELF_TEST)
/*
* RFC 1320 test vectors
*/
static const unsigned char md4_test_str[7][81] =
{
{ "" },
{ "a" },
{ "abc" },
{ "message digest" },
{ "abcdefghijklmnopqrstuvwxyz" },
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
{ "12345678901234567890123456789012345678901234567890123456789012345678901234567890" }
};
static const size_t md4_test_strlen[7] =
{
0, 1, 3, 14, 26, 62, 80
};
static const unsigned char md4_test_sum[7][16] =
{
{ 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
{ 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
{ 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
{ 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
{ 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
{ 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
{ 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
};
/*
* Checkup routine
*/
int mbedtls_md4_self_test( int verbose )
{
int i, ret = 0;
unsigned char md4sum[16];
for( i = 0; i < 7; i++ )
{
if( verbose != 0 )
mbedtls_printf( " MD4 test #%d: ", i + 1 );
ret = mbedtls_md4_ret( md4_test_str[i], md4_test_strlen[i], md4sum );
if( ret != 0 )
goto fail;
if( memcmp( md4sum, md4_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_MD4_C */

309
common/mbedtls/md4.h Normal file
View File

@@ -0,0 +1,309 @@
/**
* \file md4.h
*
* \brief MD4 message digest algorithm (hash function)
*
* \warning MD4 is considered a weak message digest and its use constitutes a
* security risk. We recommend considering stronger message digests
* instead.
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef MBEDTLS_MD4_H
#define MBEDTLS_MD4_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include <stddef.h>
#include <stdint.h>
/* MBEDTLS_ERR_MD4_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_MD4_HW_ACCEL_FAILED -0x002D /**< MD4 hardware accelerator failed */
#ifdef __cplusplus
extern "C" {
#endif
#if !defined(MBEDTLS_MD4_ALT)
// Regular implementation
//
/**
* \brief MD4 context structure
*
* \warning MD4 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
typedef struct mbedtls_md4_context
{
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[4]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
}
mbedtls_md4_context;
#else /* MBEDTLS_MD4_ALT */
#include "md4_alt.h"
#endif /* MBEDTLS_MD4_ALT */
/**
* \brief Initialize MD4 context
*
* \param ctx MD4 context to be initialized
*
* \warning MD4 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
void mbedtls_md4_init( mbedtls_md4_context *ctx );
/**
* \brief Clear MD4 context
*
* \param ctx MD4 context to be cleared
*
* \warning MD4 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
void mbedtls_md4_free( mbedtls_md4_context *ctx );
/**
* \brief Clone (the state of) an MD4 context
*
* \param dst The destination context
* \param src The context to be cloned
*
* \warning MD4 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
void mbedtls_md4_clone( mbedtls_md4_context *dst,
const mbedtls_md4_context *src );
/**
* \brief MD4 context setup
*
* \param ctx context to be initialized
*
* \return 0 if successful
*
* \warning MD4 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*/
int mbedtls_md4_starts_ret( mbedtls_md4_context *ctx );
/**
* \brief MD4 process buffer
*
* \param ctx MD4 context
* \param input buffer holding the data
* \param ilen length of the input data
*
* \return 0 if successful
*
* \warning MD4 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
int mbedtls_md4_update_ret( mbedtls_md4_context *ctx,
const unsigned char *input,
size_t ilen );
/**
* \brief MD4 final digest
*
* \param ctx MD4 context
* \param output MD4 checksum result
*
* \return 0 if successful
*
* \warning MD4 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx,
unsigned char output[16] );
/**
* \brief MD4 process data block (internal use only)
*
* \param ctx MD4 context
* \param data buffer holding one block of data
*
* \return 0 if successful
*
* \warning MD4 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
int mbedtls_internal_md4_process( mbedtls_md4_context *ctx,
const unsigned char data[64] );
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
#if defined(MBEDTLS_DEPRECATED_WARNING)
#define MBEDTLS_DEPRECATED __attribute__((deprecated))
#else
#define MBEDTLS_DEPRECATED
#endif
/**
* \brief MD4 context setup
*
* \deprecated Superseded by mbedtls_md4_starts_ret() in 2.7.0
*
* \param ctx context to be initialized
*
* \warning MD4 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
MBEDTLS_DEPRECATED void mbedtls_md4_starts( mbedtls_md4_context *ctx );
/**
* \brief MD4 process buffer
*
* \deprecated Superseded by mbedtls_md4_update_ret() in 2.7.0
*
* \param ctx MD4 context
* \param input buffer holding the data
* \param ilen length of the input data
*
* \warning MD4 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
MBEDTLS_DEPRECATED void mbedtls_md4_update( mbedtls_md4_context *ctx,
const unsigned char *input,
size_t ilen );
/**
* \brief MD4 final digest
*
* \deprecated Superseded by mbedtls_md4_finish_ret() in 2.7.0
*
* \param ctx MD4 context
* \param output MD4 checksum result
*
* \warning MD4 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
MBEDTLS_DEPRECATED void mbedtls_md4_finish( mbedtls_md4_context *ctx,
unsigned char output[16] );
/**
* \brief MD4 process data block (internal use only)
*
* \deprecated Superseded by mbedtls_internal_md4_process() in 2.7.0
*
* \param ctx MD4 context
* \param data buffer holding one block of data
*
* \warning MD4 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
MBEDTLS_DEPRECATED void mbedtls_md4_process( mbedtls_md4_context *ctx,
const unsigned char data[64] );
#undef MBEDTLS_DEPRECATED
#endif /* !MBEDTLS_DEPRECATED_REMOVED */
/**
* \brief Output = MD4( input buffer )
*
* \param input buffer holding the data
* \param ilen length of the input data
* \param output MD4 checksum result
*
* \return 0 if successful
*
* \warning MD4 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
int mbedtls_md4_ret( const unsigned char *input,
size_t ilen,
unsigned char output[16] );
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
#if defined(MBEDTLS_DEPRECATED_WARNING)
#define MBEDTLS_DEPRECATED __attribute__((deprecated))
#else
#define MBEDTLS_DEPRECATED
#endif
/**
* \brief Output = MD4( input buffer )
*
* \deprecated Superseded by mbedtls_md4_ret() in 2.7.0
*
* \param input buffer holding the data
* \param ilen length of the input data
* \param output MD4 checksum result
*
* \warning MD4 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
MBEDTLS_DEPRECATED void mbedtls_md4( const unsigned char *input,
size_t ilen,
unsigned char output[16] );
#undef MBEDTLS_DEPRECATED
#endif /* !MBEDTLS_DEPRECATED_REMOVED */
#if defined(MBEDTLS_SELF_TEST)
/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if the test failed
*
* \warning MD4 is considered a weak message digest and its use
* constitutes a security risk. We recommend considering
* stronger message digests instead.
*
*/
int mbedtls_md4_self_test( int verbose );
#endif /* MBEDTLS_SELF_TEST */
#ifdef __cplusplus
}
#endif
#endif /* mbedtls_md4.h */

View File

@@ -1,24 +1,20 @@
/* /*
* RFC 1321 compliant MD5 implementation * RFC 1321 compliant MD5 implementation
* *
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
/* /*
* The MD5 algorithm was designed by Ron Rivest in 1991. * The MD5 algorithm was designed by Ron Rivest in 1991.
@@ -26,16 +22,13 @@
* http://www.ietf.org/rfc/rfc1321.txt * http://www.ietf.org/rfc/rfc1321.txt
*/ */
#if !defined(MBEDTLS_CONFIG_FILE) #include "common.h"
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_MD5_C) #if defined(MBEDTLS_MD5_C)
#include "mbedtls/md5.h" #include "mbedtls/md5.h"
#include "mbedtls/platform_util.h" #include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#include <string.h> #include <string.h>
@@ -55,44 +48,48 @@
*/ */
#ifndef GET_UINT32_LE #ifndef GET_UINT32_LE
#define GET_UINT32_LE(n,b,i) \ #define GET_UINT32_LE(n,b,i) \
{ \ { \
(n) = ( (uint32_t) (b)[(i) ] ) \ (n) = ( (uint32_t) (b)[(i) ] ) \
| ( (uint32_t) (b)[(i) + 1] << 8 ) \ | ( (uint32_t) (b)[(i) + 1] << 8 ) \
| ( (uint32_t) (b)[(i) + 2] << 16 ) \ | ( (uint32_t) (b)[(i) + 2] << 16 ) \
| ( (uint32_t) (b)[(i) + 3] << 24 ); \ | ( (uint32_t) (b)[(i) + 3] << 24 ); \
} }
#endif #endif
#ifndef PUT_UINT32_LE #ifndef PUT_UINT32_LE
#define PUT_UINT32_LE(n,b,i) \ #define PUT_UINT32_LE(n,b,i) \
{ \ { \
(b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
(b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
(b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
(b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
} }
#endif #endif
void mbedtls_md5_init(mbedtls_md5_context *ctx) { void mbedtls_md5_init( mbedtls_md5_context *ctx )
memset(ctx, 0, sizeof(mbedtls_md5_context)); {
memset( ctx, 0, sizeof( mbedtls_md5_context ) );
} }
void mbedtls_md5_free(mbedtls_md5_context *ctx) { void mbedtls_md5_free( mbedtls_md5_context *ctx )
if (ctx == NULL) {
if( ctx == NULL )
return; return;
mbedtls_platform_zeroize(ctx, sizeof(mbedtls_md5_context)); mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md5_context ) );
} }
void mbedtls_md5_clone(mbedtls_md5_context *dst, void mbedtls_md5_clone( mbedtls_md5_context *dst,
const mbedtls_md5_context *src) { const mbedtls_md5_context *src )
{
*dst = *src; *dst = *src;
} }
/* /*
* MD5 context setup * MD5 context setup
*/ */
int mbedtls_md5_starts_ret(mbedtls_md5_context *ctx) { int mbedtls_md5_starts_ret( mbedtls_md5_context *ctx )
{
ctx->total[0] = 0; ctx->total[0] = 0;
ctx->total[1] = 0; ctx->total[1] = 0;
@@ -101,145 +98,157 @@ int mbedtls_md5_starts_ret(mbedtls_md5_context *ctx) {
ctx->state[2] = 0x98BADCFE; ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476; ctx->state[3] = 0x10325476;
return (0); return( 0 );
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED) #if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_md5_starts(mbedtls_md5_context *ctx) { void mbedtls_md5_starts( mbedtls_md5_context *ctx )
mbedtls_md5_starts_ret(ctx); {
mbedtls_md5_starts_ret( ctx );
} }
#endif #endif
#if !defined(MBEDTLS_MD5_PROCESS_ALT) #if !defined(MBEDTLS_MD5_PROCESS_ALT)
int mbedtls_internal_md5_process(mbedtls_md5_context *ctx, int mbedtls_internal_md5_process( mbedtls_md5_context *ctx,
const unsigned char data[64]) { const unsigned char data[64] )
uint32_t X[16], A, B, C, D; {
struct
{
uint32_t X[16], A, B, C, D;
} local;
GET_UINT32_LE(X[ 0], data, 0); GET_UINT32_LE( local.X[ 0], data, 0 );
GET_UINT32_LE(X[ 1], data, 4); GET_UINT32_LE( local.X[ 1], data, 4 );
GET_UINT32_LE(X[ 2], data, 8); GET_UINT32_LE( local.X[ 2], data, 8 );
GET_UINT32_LE(X[ 3], data, 12); GET_UINT32_LE( local.X[ 3], data, 12 );
GET_UINT32_LE(X[ 4], data, 16); GET_UINT32_LE( local.X[ 4], data, 16 );
GET_UINT32_LE(X[ 5], data, 20); GET_UINT32_LE( local.X[ 5], data, 20 );
GET_UINT32_LE(X[ 6], data, 24); GET_UINT32_LE( local.X[ 6], data, 24 );
GET_UINT32_LE(X[ 7], data, 28); GET_UINT32_LE( local.X[ 7], data, 28 );
GET_UINT32_LE(X[ 8], data, 32); GET_UINT32_LE( local.X[ 8], data, 32 );
GET_UINT32_LE(X[ 9], data, 36); GET_UINT32_LE( local.X[ 9], data, 36 );
GET_UINT32_LE(X[10], data, 40); GET_UINT32_LE( local.X[10], data, 40 );
GET_UINT32_LE(X[11], data, 44); GET_UINT32_LE( local.X[11], data, 44 );
GET_UINT32_LE(X[12], data, 48); GET_UINT32_LE( local.X[12], data, 48 );
GET_UINT32_LE(X[13], data, 52); GET_UINT32_LE( local.X[13], data, 52 );
GET_UINT32_LE(X[14], data, 56); GET_UINT32_LE( local.X[14], data, 56 );
GET_UINT32_LE(X[15], data, 60); GET_UINT32_LE( local.X[15], data, 60 );
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) #define S(x,n) \
( ( (x) << (n) ) | ( ( (x) & 0xFFFFFFFF) >> ( 32 - (n) ) ) )
#define P(a,b,c,d,k,s,t) \ #define P(a,b,c,d,k,s,t) \
{ \ do \
a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \ { \
} (a) += F((b),(c),(d)) + local.X[(k)] + (t); \
(a) = S((a),(s)) + (b); \
} while( 0 )
A = ctx->state[0]; local.A = ctx->state[0];
B = ctx->state[1]; local.B = ctx->state[1];
C = ctx->state[2]; local.C = ctx->state[2];
D = ctx->state[3]; local.D = ctx->state[3];
#define F(x,y,z) (z ^ (x & (y ^ z))) #define F(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
P(A, B, C, D, 0, 7, 0xD76AA478); P( local.A, local.B, local.C, local.D, 0, 7, 0xD76AA478 );
P(D, A, B, C, 1, 12, 0xE8C7B756); P( local.D, local.A, local.B, local.C, 1, 12, 0xE8C7B756 );
P(C, D, A, B, 2, 17, 0x242070DB); P( local.C, local.D, local.A, local.B, 2, 17, 0x242070DB );
P(B, C, D, A, 3, 22, 0xC1BDCEEE); P( local.B, local.C, local.D, local.A, 3, 22, 0xC1BDCEEE );
P(A, B, C, D, 4, 7, 0xF57C0FAF); P( local.A, local.B, local.C, local.D, 4, 7, 0xF57C0FAF );
P(D, A, B, C, 5, 12, 0x4787C62A); P( local.D, local.A, local.B, local.C, 5, 12, 0x4787C62A );
P(C, D, A, B, 6, 17, 0xA8304613); P( local.C, local.D, local.A, local.B, 6, 17, 0xA8304613 );
P(B, C, D, A, 7, 22, 0xFD469501); P( local.B, local.C, local.D, local.A, 7, 22, 0xFD469501 );
P(A, B, C, D, 8, 7, 0x698098D8); P( local.A, local.B, local.C, local.D, 8, 7, 0x698098D8 );
P(D, A, B, C, 9, 12, 0x8B44F7AF); P( local.D, local.A, local.B, local.C, 9, 12, 0x8B44F7AF );
P(C, D, A, B, 10, 17, 0xFFFF5BB1); P( local.C, local.D, local.A, local.B, 10, 17, 0xFFFF5BB1 );
P(B, C, D, A, 11, 22, 0x895CD7BE); P( local.B, local.C, local.D, local.A, 11, 22, 0x895CD7BE );
P(A, B, C, D, 12, 7, 0x6B901122); P( local.A, local.B, local.C, local.D, 12, 7, 0x6B901122 );
P(D, A, B, C, 13, 12, 0xFD987193); P( local.D, local.A, local.B, local.C, 13, 12, 0xFD987193 );
P(C, D, A, B, 14, 17, 0xA679438E); P( local.C, local.D, local.A, local.B, 14, 17, 0xA679438E );
P(B, C, D, A, 15, 22, 0x49B40821); P( local.B, local.C, local.D, local.A, 15, 22, 0x49B40821 );
#undef F #undef F
#define F(x,y,z) (y ^ (z & (x ^ y))) #define F(x,y,z) ((y) ^ ((z) & ((x) ^ (y))))
P(A, B, C, D, 1, 5, 0xF61E2562); P( local.A, local.B, local.C, local.D, 1, 5, 0xF61E2562 );
P(D, A, B, C, 6, 9, 0xC040B340); P( local.D, local.A, local.B, local.C, 6, 9, 0xC040B340 );
P(C, D, A, B, 11, 14, 0x265E5A51); P( local.C, local.D, local.A, local.B, 11, 14, 0x265E5A51 );
P(B, C, D, A, 0, 20, 0xE9B6C7AA); P( local.B, local.C, local.D, local.A, 0, 20, 0xE9B6C7AA );
P(A, B, C, D, 5, 5, 0xD62F105D); P( local.A, local.B, local.C, local.D, 5, 5, 0xD62F105D );
P(D, A, B, C, 10, 9, 0x02441453); P( local.D, local.A, local.B, local.C, 10, 9, 0x02441453 );
P(C, D, A, B, 15, 14, 0xD8A1E681); P( local.C, local.D, local.A, local.B, 15, 14, 0xD8A1E681 );
P(B, C, D, A, 4, 20, 0xE7D3FBC8); P( local.B, local.C, local.D, local.A, 4, 20, 0xE7D3FBC8 );
P(A, B, C, D, 9, 5, 0x21E1CDE6); P( local.A, local.B, local.C, local.D, 9, 5, 0x21E1CDE6 );
P(D, A, B, C, 14, 9, 0xC33707D6); P( local.D, local.A, local.B, local.C, 14, 9, 0xC33707D6 );
P(C, D, A, B, 3, 14, 0xF4D50D87); P( local.C, local.D, local.A, local.B, 3, 14, 0xF4D50D87 );
P(B, C, D, A, 8, 20, 0x455A14ED); P( local.B, local.C, local.D, local.A, 8, 20, 0x455A14ED );
P(A, B, C, D, 13, 5, 0xA9E3E905); P( local.A, local.B, local.C, local.D, 13, 5, 0xA9E3E905 );
P(D, A, B, C, 2, 9, 0xFCEFA3F8); P( local.D, local.A, local.B, local.C, 2, 9, 0xFCEFA3F8 );
P(C, D, A, B, 7, 14, 0x676F02D9); P( local.C, local.D, local.A, local.B, 7, 14, 0x676F02D9 );
P(B, C, D, A, 12, 20, 0x8D2A4C8A); P( local.B, local.C, local.D, local.A, 12, 20, 0x8D2A4C8A );
#undef F #undef F
#define F(x,y,z) (x ^ y ^ z) #define F(x,y,z) ((x) ^ (y) ^ (z))
P(A, B, C, D, 5, 4, 0xFFFA3942); P( local.A, local.B, local.C, local.D, 5, 4, 0xFFFA3942 );
P(D, A, B, C, 8, 11, 0x8771F681); P( local.D, local.A, local.B, local.C, 8, 11, 0x8771F681 );
P(C, D, A, B, 11, 16, 0x6D9D6122); P( local.C, local.D, local.A, local.B, 11, 16, 0x6D9D6122 );
P(B, C, D, A, 14, 23, 0xFDE5380C); P( local.B, local.C, local.D, local.A, 14, 23, 0xFDE5380C );
P(A, B, C, D, 1, 4, 0xA4BEEA44); P( local.A, local.B, local.C, local.D, 1, 4, 0xA4BEEA44 );
P(D, A, B, C, 4, 11, 0x4BDECFA9); P( local.D, local.A, local.B, local.C, 4, 11, 0x4BDECFA9 );
P(C, D, A, B, 7, 16, 0xF6BB4B60); P( local.C, local.D, local.A, local.B, 7, 16, 0xF6BB4B60 );
P(B, C, D, A, 10, 23, 0xBEBFBC70); P( local.B, local.C, local.D, local.A, 10, 23, 0xBEBFBC70 );
P(A, B, C, D, 13, 4, 0x289B7EC6); P( local.A, local.B, local.C, local.D, 13, 4, 0x289B7EC6 );
P(D, A, B, C, 0, 11, 0xEAA127FA); P( local.D, local.A, local.B, local.C, 0, 11, 0xEAA127FA );
P(C, D, A, B, 3, 16, 0xD4EF3085); P( local.C, local.D, local.A, local.B, 3, 16, 0xD4EF3085 );
P(B, C, D, A, 6, 23, 0x04881D05); P( local.B, local.C, local.D, local.A, 6, 23, 0x04881D05 );
P(A, B, C, D, 9, 4, 0xD9D4D039); P( local.A, local.B, local.C, local.D, 9, 4, 0xD9D4D039 );
P(D, A, B, C, 12, 11, 0xE6DB99E5); P( local.D, local.A, local.B, local.C, 12, 11, 0xE6DB99E5 );
P(C, D, A, B, 15, 16, 0x1FA27CF8); P( local.C, local.D, local.A, local.B, 15, 16, 0x1FA27CF8 );
P(B, C, D, A, 2, 23, 0xC4AC5665); P( local.B, local.C, local.D, local.A, 2, 23, 0xC4AC5665 );
#undef F #undef F
#define F(x,y,z) (y ^ (x | ~z)) #define F(x,y,z) ((y) ^ ((x) | ~(z)))
P(A, B, C, D, 0, 6, 0xF4292244); P( local.A, local.B, local.C, local.D, 0, 6, 0xF4292244 );
P(D, A, B, C, 7, 10, 0x432AFF97); P( local.D, local.A, local.B, local.C, 7, 10, 0x432AFF97 );
P(C, D, A, B, 14, 15, 0xAB9423A7); P( local.C, local.D, local.A, local.B, 14, 15, 0xAB9423A7 );
P(B, C, D, A, 5, 21, 0xFC93A039); P( local.B, local.C, local.D, local.A, 5, 21, 0xFC93A039 );
P(A, B, C, D, 12, 6, 0x655B59C3); P( local.A, local.B, local.C, local.D, 12, 6, 0x655B59C3 );
P(D, A, B, C, 3, 10, 0x8F0CCC92); P( local.D, local.A, local.B, local.C, 3, 10, 0x8F0CCC92 );
P(C, D, A, B, 10, 15, 0xFFEFF47D); P( local.C, local.D, local.A, local.B, 10, 15, 0xFFEFF47D );
P(B, C, D, A, 1, 21, 0x85845DD1); P( local.B, local.C, local.D, local.A, 1, 21, 0x85845DD1 );
P(A, B, C, D, 8, 6, 0x6FA87E4F); P( local.A, local.B, local.C, local.D, 8, 6, 0x6FA87E4F );
P(D, A, B, C, 15, 10, 0xFE2CE6E0); P( local.D, local.A, local.B, local.C, 15, 10, 0xFE2CE6E0 );
P(C, D, A, B, 6, 15, 0xA3014314); P( local.C, local.D, local.A, local.B, 6, 15, 0xA3014314 );
P(B, C, D, A, 13, 21, 0x4E0811A1); P( local.B, local.C, local.D, local.A, 13, 21, 0x4E0811A1 );
P(A, B, C, D, 4, 6, 0xF7537E82); P( local.A, local.B, local.C, local.D, 4, 6, 0xF7537E82 );
P(D, A, B, C, 11, 10, 0xBD3AF235); P( local.D, local.A, local.B, local.C, 11, 10, 0xBD3AF235 );
P(C, D, A, B, 2, 15, 0x2AD7D2BB); P( local.C, local.D, local.A, local.B, 2, 15, 0x2AD7D2BB );
P(B, C, D, A, 9, 21, 0xEB86D391); P( local.B, local.C, local.D, local.A, 9, 21, 0xEB86D391 );
#undef F #undef F
ctx->state[0] += A; ctx->state[0] += local.A;
ctx->state[1] += B; ctx->state[1] += local.B;
ctx->state[2] += C; ctx->state[2] += local.C;
ctx->state[3] += D; ctx->state[3] += local.D;
return (0); /* Zeroise variables to clear sensitive data from memory. */
mbedtls_platform_zeroize( &local, sizeof( local ) );
return( 0 );
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED) #if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_md5_process(mbedtls_md5_context *ctx, void mbedtls_md5_process( mbedtls_md5_context *ctx,
const unsigned char data[64]) { const unsigned char data[64] )
mbedtls_internal_md5_process(ctx, data); {
mbedtls_internal_md5_process( ctx, data );
} }
#endif #endif
#endif /* !MBEDTLS_MD5_PROCESS_ALT */ #endif /* !MBEDTLS_MD5_PROCESS_ALT */
@@ -247,15 +256,16 @@ void mbedtls_md5_process(mbedtls_md5_context *ctx,
/* /*
* MD5 process buffer * MD5 process buffer
*/ */
int mbedtls_md5_update_ret(mbedtls_md5_context *ctx, int mbedtls_md5_update_ret( mbedtls_md5_context *ctx,
const unsigned char *input, const unsigned char *input,
size_t ilen) { size_t ilen )
int ret; {
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t fill; size_t fill;
uint32_t left; uint32_t left;
if (ilen == 0) if( ilen == 0 )
return (0); return( 0 );
left = ctx->total[0] & 0x3F; left = ctx->total[0] & 0x3F;
fill = 64 - left; fill = 64 - left;
@@ -263,48 +273,53 @@ int mbedtls_md5_update_ret(mbedtls_md5_context *ctx,
ctx->total[0] += (uint32_t) ilen; ctx->total[0] += (uint32_t) ilen;
ctx->total[0] &= 0xFFFFFFFF; ctx->total[0] &= 0xFFFFFFFF;
if (ctx->total[0] < (uint32_t) ilen) if( ctx->total[0] < (uint32_t) ilen )
ctx->total[1]++; ctx->total[1]++;
if (left && ilen >= fill) { if( left && ilen >= fill )
memcpy((void *)(ctx->buffer + left), input, fill); {
if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0) memcpy( (void *) (ctx->buffer + left), input, fill );
return (ret); if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 )
return( ret );
input += fill; input += fill;
ilen -= fill; ilen -= fill;
left = 0; left = 0;
} }
while (ilen >= 64) { while( ilen >= 64 )
if ((ret = mbedtls_internal_md5_process(ctx, input)) != 0) {
return (ret); if( ( ret = mbedtls_internal_md5_process( ctx, input ) ) != 0 )
return( ret );
input += 64; input += 64;
ilen -= 64; ilen -= 64;
} }
if (ilen > 0) { if( ilen > 0 )
memcpy((void *)(ctx->buffer + left), input, ilen); {
memcpy( (void *) (ctx->buffer + left), input, ilen );
} }
return (0); return( 0 );
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED) #if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_md5_update(mbedtls_md5_context *ctx, void mbedtls_md5_update( mbedtls_md5_context *ctx,
const unsigned char *input, const unsigned char *input,
size_t ilen) { size_t ilen )
mbedtls_md5_update_ret(ctx, input, ilen); {
mbedtls_md5_update_ret( ctx, input, ilen );
} }
#endif #endif
/* /*
* MD5 final digest * MD5 final digest
*/ */
int mbedtls_md5_finish_ret(mbedtls_md5_context *ctx, int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx,
unsigned char output[16]) { unsigned char output[16] )
int ret; {
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
uint32_t used; uint32_t used;
uint32_t high, low; uint32_t high, low;
@@ -315,47 +330,51 @@ int mbedtls_md5_finish_ret(mbedtls_md5_context *ctx,
ctx->buffer[used++] = 0x80; ctx->buffer[used++] = 0x80;
if (used <= 56) { if( used <= 56 )
{
/* Enough room for padding + length in current block */ /* Enough room for padding + length in current block */
memset(ctx->buffer + used, 0, 56 - used); memset( ctx->buffer + used, 0, 56 - used );
} else { }
else
{
/* We'll need an extra block */ /* We'll need an extra block */
memset(ctx->buffer + used, 0, 64 - used); memset( ctx->buffer + used, 0, 64 - used );
if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0) if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 )
return (ret); return( ret );
memset(ctx->buffer, 0, 56); memset( ctx->buffer, 0, 56 );
} }
/* /*
* Add message length * Add message length
*/ */
high = (ctx->total[0] >> 29) high = ( ctx->total[0] >> 29 )
| (ctx->total[1] << 3); | ( ctx->total[1] << 3 );
low = (ctx->total[0] << 3); low = ( ctx->total[0] << 3 );
PUT_UINT32_LE(low, ctx->buffer, 56); PUT_UINT32_LE( low, ctx->buffer, 56 );
PUT_UINT32_LE(high, ctx->buffer, 60); PUT_UINT32_LE( high, ctx->buffer, 60 );
if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0) if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 )
return (ret); return( ret );
/* /*
* Output final state * Output final state
*/ */
PUT_UINT32_LE(ctx->state[0], output, 0); PUT_UINT32_LE( ctx->state[0], output, 0 );
PUT_UINT32_LE(ctx->state[1], output, 4); PUT_UINT32_LE( ctx->state[1], output, 4 );
PUT_UINT32_LE(ctx->state[2], output, 8); PUT_UINT32_LE( ctx->state[2], output, 8 );
PUT_UINT32_LE(ctx->state[3], output, 12); PUT_UINT32_LE( ctx->state[3], output, 12 );
return (0); return( 0 );
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED) #if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_md5_finish(mbedtls_md5_context *ctx, void mbedtls_md5_finish( mbedtls_md5_context *ctx,
unsigned char output[16]) { unsigned char output[16] )
mbedtls_md5_finish_ret(ctx, output); {
mbedtls_md5_finish_ret( ctx, output );
} }
#endif #endif
@@ -364,34 +383,36 @@ void mbedtls_md5_finish(mbedtls_md5_context *ctx,
/* /*
* output = MD5( input buffer ) * output = MD5( input buffer )
*/ */
int mbedtls_md5_ret(const unsigned char *input, int mbedtls_md5_ret( const unsigned char *input,
size_t ilen, size_t ilen,
unsigned char output[16]) { unsigned char output[16] )
int ret; {
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_md5_context ctx; mbedtls_md5_context ctx;
mbedtls_md5_init(&ctx); mbedtls_md5_init( &ctx );
if ((ret = mbedtls_md5_starts_ret(&ctx)) != 0) if( ( ret = mbedtls_md5_starts_ret( &ctx ) ) != 0 )
goto exit; goto exit;
if ((ret = mbedtls_md5_update_ret(&ctx, input, ilen)) != 0) if( ( ret = mbedtls_md5_update_ret( &ctx, input, ilen ) ) != 0 )
goto exit; goto exit;
if ((ret = mbedtls_md5_finish_ret(&ctx, output)) != 0) if( ( ret = mbedtls_md5_finish_ret( &ctx, output ) ) != 0 )
goto exit; goto exit;
exit: exit:
mbedtls_md5_free(&ctx); mbedtls_md5_free( &ctx );
return (ret); return( ret );
} }
#if !defined(MBEDTLS_DEPRECATED_REMOVED) #if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_md5(const unsigned char *input, void mbedtls_md5( const unsigned char *input,
size_t ilen, size_t ilen,
unsigned char output[16]) { unsigned char output[16] )
mbedtls_md5_ret(input, ilen, output); {
mbedtls_md5_ret( input, ilen, output );
} }
#endif #endif
@@ -399,88 +420,77 @@ void mbedtls_md5(const unsigned char *input,
/* /*
* RFC 1321 test vectors * RFC 1321 test vectors
*/ */
static const unsigned char md5_test_buf[7][81] = { static const unsigned char md5_test_buf[7][81] =
{
{ "" }, { "" },
{ "a" }, { "a" },
{ "abc" }, { "abc" },
{ "message digest" }, { "message digest" },
{ "abcdefghijklmnopqrstuvwxyz" }, { "abcdefghijklmnopqrstuvwxyz" },
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
{ { "12345678901234567890123456789012345678901234567890123456789012345678901234567890" }
"12345678901234567890123456789012345678901234567890123456789012"
"345678901234567890"
}
}; };
static const size_t md5_test_buflen[7] = { static const size_t md5_test_buflen[7] =
{
0, 1, 3, 14, 26, 62, 80 0, 1, 3, 14, 26, 62, 80
}; };
static const unsigned char md5_test_sum[7][16] = { static const unsigned char md5_test_sum[7][16] =
{ {
0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04, { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,
0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E },
}, { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8,
{ 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 },
0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8, { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0,
0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 },
}, { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D,
{ 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 },
0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0, { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00,
0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B },
}, { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5,
{ 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F },
0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D, { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55,
0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A }
},
{
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 * Checkup routine
*/ */
int mbedtls_md5_self_test(int verbose) { int mbedtls_md5_self_test( int verbose )
{
int i, ret = 0; int i, ret = 0;
unsigned char md5sum[16]; unsigned char md5sum[16];
for (i = 0; i < 7; i++) { for( i = 0; i < 7; i++ )
if (verbose != 0) {
mbedtls_printf(" MD5 test #%d: ", i + 1); if( verbose != 0 )
mbedtls_printf( " MD5 test #%d: ", i + 1 );
ret = mbedtls_md5_ret(md5_test_buf[i], md5_test_buflen[i], md5sum); ret = mbedtls_md5_ret( md5_test_buf[i], md5_test_buflen[i], md5sum );
if (ret != 0) if( ret != 0 )
goto fail; goto fail;
if (memcmp(md5sum, md5_test_sum[i], 16) != 0) { if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 )
{
ret = 1; ret = 1;
goto fail; goto fail;
} }
if (verbose != 0) if( verbose != 0 )
mbedtls_printf("passed\n"); mbedtls_printf( "passed\n" );
} }
if (verbose != 0) if( verbose != 0 )
mbedtls_printf("\n"); mbedtls_printf( "\n" );
return (0); return( 0 );
fail: fail:
if (verbose != 0) if( verbose != 0 )
mbedtls_printf("failed\n"); mbedtls_printf( "failed\n" );
return (ret); return( ret );
} }
#endif /* MBEDTLS_SELF_TEST */ #endif /* MBEDTLS_SELF_TEST */

View File

@@ -8,30 +8,26 @@
* digests instead. * digests instead.
*/ */
/* /*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
#ifndef MBEDTLS_MD5_H #ifndef MBEDTLS_MD5_H
#define MBEDTLS_MD5_H #define MBEDTLS_MD5_H
#if !defined(MBEDTLS_CONFIG_FILE) #if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h" #include "mbedtls/config.h"
#else #else
#include MBEDTLS_CONFIG_FILE #include MBEDTLS_CONFIG_FILE
#endif #endif
@@ -39,6 +35,7 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
/* MBEDTLS_ERR_MD5_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_MD5_HW_ACCEL_FAILED -0x002F /**< MD5 hardware accelerator failed */ #define MBEDTLS_ERR_MD5_HW_ACCEL_FAILED -0x002F /**< MD5 hardware accelerator failed */
#ifdef __cplusplus #ifdef __cplusplus
@@ -57,7 +54,8 @@ extern "C" {
* stronger message digests instead. * stronger message digests instead.
* *
*/ */
typedef struct mbedtls_md5_context { typedef struct mbedtls_md5_context
{
uint32_t total[2]; /*!< number of bytes processed */ uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[4]; /*!< intermediate digest state */ uint32_t state[4]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */ unsigned char buffer[64]; /*!< data block being processed */
@@ -78,7 +76,7 @@ mbedtls_md5_context;
* stronger message digests instead. * stronger message digests instead.
* *
*/ */
void mbedtls_md5_init(mbedtls_md5_context *ctx); void mbedtls_md5_init( mbedtls_md5_context *ctx );
/** /**
* \brief Clear MD5 context * \brief Clear MD5 context
@@ -90,7 +88,7 @@ void mbedtls_md5_init(mbedtls_md5_context *ctx);
* stronger message digests instead. * stronger message digests instead.
* *
*/ */
void mbedtls_md5_free(mbedtls_md5_context *ctx); void mbedtls_md5_free( mbedtls_md5_context *ctx );
/** /**
* \brief Clone (the state of) an MD5 context * \brief Clone (the state of) an MD5 context
@@ -103,8 +101,8 @@ void mbedtls_md5_free(mbedtls_md5_context *ctx);
* stronger message digests instead. * stronger message digests instead.
* *
*/ */
void mbedtls_md5_clone(mbedtls_md5_context *dst, void mbedtls_md5_clone( mbedtls_md5_context *dst,
const mbedtls_md5_context *src); const mbedtls_md5_context *src );
/** /**
* \brief MD5 context setup * \brief MD5 context setup
@@ -118,7 +116,7 @@ void mbedtls_md5_clone(mbedtls_md5_context *dst,
* stronger message digests instead. * stronger message digests instead.
* *
*/ */
int mbedtls_md5_starts_ret(mbedtls_md5_context *ctx); int mbedtls_md5_starts_ret( mbedtls_md5_context *ctx );
/** /**
* \brief MD5 process buffer * \brief MD5 process buffer
@@ -134,9 +132,9 @@ int mbedtls_md5_starts_ret(mbedtls_md5_context *ctx);
* stronger message digests instead. * stronger message digests instead.
* *
*/ */
int mbedtls_md5_update_ret(mbedtls_md5_context *ctx, int mbedtls_md5_update_ret( mbedtls_md5_context *ctx,
const unsigned char *input, const unsigned char *input,
size_t ilen); size_t ilen );
/** /**
* \brief MD5 final digest * \brief MD5 final digest
@@ -151,8 +149,8 @@ int mbedtls_md5_update_ret(mbedtls_md5_context *ctx,
* stronger message digests instead. * stronger message digests instead.
* *
*/ */
int mbedtls_md5_finish_ret(mbedtls_md5_context *ctx, int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx,
unsigned char output[16]); unsigned char output[16] );
/** /**
* \brief MD5 process data block (internal use only) * \brief MD5 process data block (internal use only)
@@ -167,8 +165,8 @@ int mbedtls_md5_finish_ret(mbedtls_md5_context *ctx,
* stronger message digests instead. * stronger message digests instead.
* *
*/ */
int mbedtls_internal_md5_process(mbedtls_md5_context *ctx, int mbedtls_internal_md5_process( mbedtls_md5_context *ctx,
const unsigned char data[64]); const unsigned char data[64] );
#if !defined(MBEDTLS_DEPRECATED_REMOVED) #if !defined(MBEDTLS_DEPRECATED_REMOVED)
#if defined(MBEDTLS_DEPRECATED_WARNING) #if defined(MBEDTLS_DEPRECATED_WARNING)
@@ -188,7 +186,7 @@ int mbedtls_internal_md5_process(mbedtls_md5_context *ctx,
* stronger message digests instead. * stronger message digests instead.
* *
*/ */
MBEDTLS_DEPRECATED void mbedtls_md5_starts(mbedtls_md5_context *ctx); MBEDTLS_DEPRECATED void mbedtls_md5_starts( mbedtls_md5_context *ctx );
/** /**
* \brief MD5 process buffer * \brief MD5 process buffer
@@ -204,9 +202,9 @@ MBEDTLS_DEPRECATED void mbedtls_md5_starts(mbedtls_md5_context *ctx);
* stronger message digests instead. * stronger message digests instead.
* *
*/ */
MBEDTLS_DEPRECATED void mbedtls_md5_update(mbedtls_md5_context *ctx, MBEDTLS_DEPRECATED void mbedtls_md5_update( mbedtls_md5_context *ctx,
const unsigned char *input, const unsigned char *input,
size_t ilen); size_t ilen );
/** /**
* \brief MD5 final digest * \brief MD5 final digest
@@ -221,8 +219,8 @@ MBEDTLS_DEPRECATED void mbedtls_md5_update(mbedtls_md5_context *ctx,
* stronger message digests instead. * stronger message digests instead.
* *
*/ */
MBEDTLS_DEPRECATED void mbedtls_md5_finish(mbedtls_md5_context *ctx, MBEDTLS_DEPRECATED void mbedtls_md5_finish( mbedtls_md5_context *ctx,
unsigned char output[16]); unsigned char output[16] );
/** /**
* \brief MD5 process data block (internal use only) * \brief MD5 process data block (internal use only)
@@ -237,8 +235,8 @@ MBEDTLS_DEPRECATED void mbedtls_md5_finish(mbedtls_md5_context *ctx,
* stronger message digests instead. * stronger message digests instead.
* *
*/ */
MBEDTLS_DEPRECATED void mbedtls_md5_process(mbedtls_md5_context *ctx, MBEDTLS_DEPRECATED void mbedtls_md5_process( mbedtls_md5_context *ctx,
const unsigned char data[64]); const unsigned char data[64] );
#undef MBEDTLS_DEPRECATED #undef MBEDTLS_DEPRECATED
#endif /* !MBEDTLS_DEPRECATED_REMOVED */ #endif /* !MBEDTLS_DEPRECATED_REMOVED */
@@ -257,9 +255,9 @@ MBEDTLS_DEPRECATED void mbedtls_md5_process(mbedtls_md5_context *ctx,
* stronger message digests instead. * stronger message digests instead.
* *
*/ */
int mbedtls_md5_ret(const unsigned char *input, int mbedtls_md5_ret( const unsigned char *input,
size_t ilen, size_t ilen,
unsigned char output[16]); unsigned char output[16] );
#if !defined(MBEDTLS_DEPRECATED_REMOVED) #if !defined(MBEDTLS_DEPRECATED_REMOVED)
#if defined(MBEDTLS_DEPRECATED_WARNING) #if defined(MBEDTLS_DEPRECATED_WARNING)
@@ -281,13 +279,15 @@ int mbedtls_md5_ret(const unsigned char *input,
* stronger message digests instead. * stronger message digests instead.
* *
*/ */
MBEDTLS_DEPRECATED void mbedtls_md5(const unsigned char *input, MBEDTLS_DEPRECATED void mbedtls_md5( const unsigned char *input,
size_t ilen, size_t ilen,
unsigned char output[16]); unsigned char output[16] );
#undef MBEDTLS_DEPRECATED #undef MBEDTLS_DEPRECATED
#endif /* !MBEDTLS_DEPRECATED_REMOVED */ #endif /* !MBEDTLS_DEPRECATED_REMOVED */
#if defined(MBEDTLS_SELF_TEST)
/** /**
* \brief Checkup routine * \brief Checkup routine
* *
@@ -298,7 +298,9 @@ MBEDTLS_DEPRECATED void mbedtls_md5(const unsigned char *input,
* stronger message digests instead. * stronger message digests instead.
* *
*/ */
int mbedtls_md5_self_test(int verbose); int mbedtls_md5_self_test( int verbose );
#endif /* MBEDTLS_SELF_TEST */
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -8,35 +8,31 @@
* \author Adriaan de Jong <dejong@fox-it.com> * \author Adriaan de Jong <dejong@fox-it.com>
*/ */
/* /*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
#ifndef MBEDTLS_MD_WRAP_H #ifndef MBEDTLS_MD_WRAP_H
#define MBEDTLS_MD_WRAP_H #define MBEDTLS_MD_WRAP_H
#if !defined(MBEDTLS_CONFIG_FILE) #if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h" #include "mbedtls/config.h"
#else #else
#include MBEDTLS_CONFIG_FILE #include MBEDTLS_CONFIG_FILE
#endif #endif
#include "md.h" #include "mbedtls/md.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@@ -46,43 +42,19 @@ extern "C" {
* Message digest information. * Message digest information.
* Allows message digest functions to be called in a generic way. * Allows message digest functions to be called in a generic way.
*/ */
struct mbedtls_md_info_t { struct mbedtls_md_info_t
{
/** Name of the message digest */
const char * name;
/** Digest identifier */ /** Digest identifier */
mbedtls_md_type_t type; mbedtls_md_type_t type;
/** Name of the message digest */
const char *name;
/** Output length of the digest function in bytes */ /** Output length of the digest function in bytes */
int size; unsigned char size;
/** Block length of the digest function in bytes */ /** Block length of the digest function in bytes */
int block_size; unsigned char block_size;
/** Digest initialisation function */
int (*starts_func)(void *ctx);
/** Digest update function */
int (*update_func)(void *ctx, const unsigned char *input, size_t ilen);
/** Digest finalisation function */
int (*finish_func)(void *ctx, unsigned char *output);
/** Generic digest function */
int (*digest_func)(const unsigned char *input, size_t ilen,
unsigned char *output);
/** Allocate a new context */
void *(*ctx_alloc_func)(void);
/** Free the given context */
void (*ctx_free_func)(void *ctx);
/** Clone state from a context */
void (*clone_func)(void *dst, const void *src);
/** Internal use only */
int (*process_func)(void *ctx, const unsigned char *input);
}; };
#if defined(MBEDTLS_MD2_C) #if defined(MBEDTLS_MD2_C)
@@ -105,7 +77,9 @@ extern const mbedtls_md_info_t mbedtls_sha224_info;
extern const mbedtls_md_info_t mbedtls_sha256_info; extern const mbedtls_md_info_t mbedtls_sha256_info;
#endif #endif
#if defined(MBEDTLS_SHA512_C) #if defined(MBEDTLS_SHA512_C)
#if !defined(MBEDTLS_SHA512_NO_SHA384)
extern const mbedtls_md_info_t mbedtls_sha384_info; extern const mbedtls_md_info_t mbedtls_sha384_info;
#endif
extern const mbedtls_md_info_t mbedtls_sha512_info; extern const mbedtls_md_info_t mbedtls_sha512_info;
#endif #endif

View File

@@ -1,533 +0,0 @@
/**
* \file md_wrap.c
*
* \brief Generic message digest wrapper for mbed TLS
*
* \author Adriaan de Jong <dejong@fox-it.com>
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: GPL-2.0
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This file is part of mbed TLS (https://tls.mbed.org)
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_MD_C)
#include "mbedtls/md_internal.h"
#if defined(MBEDTLS_MD2_C)
#include "mbedtls/md2.h"
#endif
#if defined(MBEDTLS_MD4_C)
#include "mbedtls/md4.h"
#endif
#if defined(MBEDTLS_MD5_C)
#include "mbedtls/md5.h"
#endif
#if defined(MBEDTLS_RIPEMD160_C)
#include "mbedtls/ripemd160.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_SHA512_C)
#include "mbedtls/sha512.h"
#endif
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdlib.h>
#define mbedtls_calloc calloc
#define mbedtls_free free
#endif
#if defined(MBEDTLS_MD2_C)
static int md2_starts_wrap(void *ctx) {
return (mbedtls_md2_starts_ret((mbedtls_md2_context *) ctx));
}
static int md2_update_wrap(void *ctx, const unsigned char *input,
size_t ilen) {
return (mbedtls_md2_update_ret((mbedtls_md2_context *) ctx, input, ilen));
}
static int md2_finish_wrap(void *ctx, unsigned char *output) {
return (mbedtls_md2_finish_ret((mbedtls_md2_context *) ctx, output));
}
static void *md2_ctx_alloc(void) {
void *ctx = mbedtls_calloc(1, sizeof(mbedtls_md2_context));
if (ctx != NULL)
mbedtls_md2_init((mbedtls_md2_context *) ctx);
return (ctx);
}
static void md2_ctx_free(void *ctx) {
mbedtls_md2_free((mbedtls_md2_context *) ctx);
mbedtls_free(ctx);
}
static void md2_clone_wrap(void *dst, const void *src) {
mbedtls_md2_clone((mbedtls_md2_context *) dst,
(const mbedtls_md2_context *) src);
}
static int md2_process_wrap(void *ctx, const unsigned char *data) {
((void) data);
return (mbedtls_internal_md2_process((mbedtls_md2_context *) ctx));
}
const mbedtls_md_info_t mbedtls_md2_info = {
MBEDTLS_MD_MD2,
"MD2",
16,
16,
md2_starts_wrap,
md2_update_wrap,
md2_finish_wrap,
mbedtls_md2_ret,
md2_ctx_alloc,
md2_ctx_free,
md2_clone_wrap,
md2_process_wrap,
};
#endif /* MBEDTLS_MD2_C */
#if defined(MBEDTLS_MD4_C)
static int md4_starts_wrap(void *ctx) {
return (mbedtls_md4_starts_ret((mbedtls_md4_context *) ctx));
}
static int md4_update_wrap(void *ctx, const unsigned char *input,
size_t ilen) {
return (mbedtls_md4_update_ret((mbedtls_md4_context *) ctx, input, ilen));
}
static int md4_finish_wrap(void *ctx, unsigned char *output) {
return (mbedtls_md4_finish_ret((mbedtls_md4_context *) ctx, output));
}
static void *md4_ctx_alloc(void) {
void *ctx = mbedtls_calloc(1, sizeof(mbedtls_md4_context));
if (ctx != NULL)
mbedtls_md4_init((mbedtls_md4_context *) ctx);
return (ctx);
}
static void md4_ctx_free(void *ctx) {
mbedtls_md4_free((mbedtls_md4_context *) ctx);
mbedtls_free(ctx);
}
static void md4_clone_wrap(void *dst, const void *src) {
mbedtls_md4_clone((mbedtls_md4_context *) dst,
(const mbedtls_md4_context *) src);
}
static int md4_process_wrap(void *ctx, const unsigned char *data) {
return (mbedtls_internal_md4_process((mbedtls_md4_context *) ctx, data));
}
const mbedtls_md_info_t mbedtls_md4_info = {
MBEDTLS_MD_MD4,
"MD4",
16,
64,
md4_starts_wrap,
md4_update_wrap,
md4_finish_wrap,
mbedtls_md4_ret,
md4_ctx_alloc,
md4_ctx_free,
md4_clone_wrap,
md4_process_wrap,
};
#endif /* MBEDTLS_MD4_C */
#if defined(MBEDTLS_MD5_C)
static int md5_starts_wrap(void *ctx) {
return (mbedtls_md5_starts_ret((mbedtls_md5_context *) ctx));
}
static int md5_update_wrap(void *ctx, const unsigned char *input,
size_t ilen) {
return (mbedtls_md5_update_ret((mbedtls_md5_context *) ctx, input, ilen));
}
static int md5_finish_wrap(void *ctx, unsigned char *output) {
return (mbedtls_md5_finish_ret((mbedtls_md5_context *) ctx, output));
}
static void *md5_ctx_alloc(void) {
void *ctx = mbedtls_calloc(1, sizeof(mbedtls_md5_context));
if (ctx != NULL)
mbedtls_md5_init((mbedtls_md5_context *) ctx);
return (ctx);
}
static void md5_ctx_free(void *ctx) {
mbedtls_md5_free((mbedtls_md5_context *) ctx);
mbedtls_free(ctx);
}
static void md5_clone_wrap(void *dst, const void *src) {
mbedtls_md5_clone((mbedtls_md5_context *) dst,
(const mbedtls_md5_context *) src);
}
static int md5_process_wrap(void *ctx, const unsigned char *data) {
return (mbedtls_internal_md5_process((mbedtls_md5_context *) ctx, data));
}
const mbedtls_md_info_t mbedtls_md5_info = {
MBEDTLS_MD_MD5,
"MD5",
16,
64,
md5_starts_wrap,
md5_update_wrap,
md5_finish_wrap,
mbedtls_md5_ret,
md5_ctx_alloc,
md5_ctx_free,
md5_clone_wrap,
md5_process_wrap,
};
#endif /* MBEDTLS_MD5_C */
#if defined(MBEDTLS_RIPEMD160_C)
static int ripemd160_starts_wrap(void *ctx) {
return (mbedtls_ripemd160_starts_ret((mbedtls_ripemd160_context *) ctx));
}
static int ripemd160_update_wrap(void *ctx, const unsigned char *input,
size_t ilen) {
return (mbedtls_ripemd160_update_ret((mbedtls_ripemd160_context *) ctx,
input, ilen));
}
static int ripemd160_finish_wrap(void *ctx, unsigned char *output) {
return (mbedtls_ripemd160_finish_ret((mbedtls_ripemd160_context *) ctx,
output));
}
static void *ripemd160_ctx_alloc(void) {
void *ctx = mbedtls_calloc(1, sizeof(mbedtls_ripemd160_context));
if (ctx != NULL)
mbedtls_ripemd160_init((mbedtls_ripemd160_context *) ctx);
return (ctx);
}
static void ripemd160_ctx_free(void *ctx) {
mbedtls_ripemd160_free((mbedtls_ripemd160_context *) ctx);
mbedtls_free(ctx);
}
static void ripemd160_clone_wrap(void *dst, const void *src) {
mbedtls_ripemd160_clone((mbedtls_ripemd160_context *) dst,
(const mbedtls_ripemd160_context *) src);
}
static int ripemd160_process_wrap(void *ctx, const unsigned char *data) {
return (mbedtls_internal_ripemd160_process(
(mbedtls_ripemd160_context *) ctx, data));
}
const mbedtls_md_info_t mbedtls_ripemd160_info = {
MBEDTLS_MD_RIPEMD160,
"RIPEMD160",
20,
64,
ripemd160_starts_wrap,
ripemd160_update_wrap,
ripemd160_finish_wrap,
mbedtls_ripemd160_ret,
ripemd160_ctx_alloc,
ripemd160_ctx_free,
ripemd160_clone_wrap,
ripemd160_process_wrap,
};
#endif /* MBEDTLS_RIPEMD160_C */
#if defined(MBEDTLS_SHA1_C)
static int sha1_starts_wrap(void *ctx) {
return (mbedtls_sha1_starts_ret((mbedtls_sha1_context *) ctx));
}
static int sha1_update_wrap(void *ctx, const unsigned char *input,
size_t ilen) {
return (mbedtls_sha1_update_ret((mbedtls_sha1_context *) ctx,
input, ilen));
}
static int sha1_finish_wrap(void *ctx, unsigned char *output) {
return (mbedtls_sha1_finish_ret((mbedtls_sha1_context *) ctx, output));
}
static void *sha1_ctx_alloc(void) {
void *ctx = mbedtls_calloc(1, sizeof(mbedtls_sha1_context));
if (ctx != NULL)
mbedtls_sha1_init((mbedtls_sha1_context *) ctx);
return (ctx);
}
static void sha1_clone_wrap(void *dst, const void *src) {
mbedtls_sha1_clone((mbedtls_sha1_context *) dst,
(const mbedtls_sha1_context *) src);
}
static void sha1_ctx_free(void *ctx) {
mbedtls_sha1_free((mbedtls_sha1_context *) ctx);
mbedtls_free(ctx);
}
static int sha1_process_wrap(void *ctx, const unsigned char *data) {
return (mbedtls_internal_sha1_process((mbedtls_sha1_context *) ctx,
data));
}
const mbedtls_md_info_t mbedtls_sha1_info = {
MBEDTLS_MD_SHA1,
"SHA1",
20,
64,
sha1_starts_wrap,
sha1_update_wrap,
sha1_finish_wrap,
mbedtls_sha1_ret,
sha1_ctx_alloc,
sha1_ctx_free,
sha1_clone_wrap,
sha1_process_wrap,
};
#endif /* MBEDTLS_SHA1_C */
/*
* Wrappers for generic message digests
*/
#if defined(MBEDTLS_SHA256_C)
static int sha224_starts_wrap(void *ctx) {
return (mbedtls_sha256_starts_ret((mbedtls_sha256_context *) ctx, 1));
}
static int sha224_update_wrap(void *ctx, const unsigned char *input,
size_t ilen) {
return (mbedtls_sha256_update_ret((mbedtls_sha256_context *) ctx,
input, ilen));
}
static int sha224_finish_wrap(void *ctx, unsigned char *output) {
return (mbedtls_sha256_finish_ret((mbedtls_sha256_context *) ctx,
output));
}
static int sha224_wrap(const unsigned char *input, size_t ilen,
unsigned char *output) {
return (mbedtls_sha256_ret(input, ilen, output, 1));
}
static void *sha224_ctx_alloc(void) {
void *ctx = mbedtls_calloc(1, sizeof(mbedtls_sha256_context));
if (ctx != NULL)
mbedtls_sha256_init((mbedtls_sha256_context *) ctx);
return (ctx);
}
static void sha224_ctx_free(void *ctx) {
mbedtls_sha256_free((mbedtls_sha256_context *) ctx);
mbedtls_free(ctx);
}
static void sha224_clone_wrap(void *dst, const void *src) {
mbedtls_sha256_clone((mbedtls_sha256_context *) dst,
(const mbedtls_sha256_context *) src);
}
static int sha224_process_wrap(void *ctx, const unsigned char *data) {
return (mbedtls_internal_sha256_process((mbedtls_sha256_context *) ctx,
data));
}
const mbedtls_md_info_t mbedtls_sha224_info = {
MBEDTLS_MD_SHA224,
"SHA224",
28,
64,
sha224_starts_wrap,
sha224_update_wrap,
sha224_finish_wrap,
sha224_wrap,
sha224_ctx_alloc,
sha224_ctx_free,
sha224_clone_wrap,
sha224_process_wrap,
};
static int sha256_starts_wrap(void *ctx) {
return (mbedtls_sha256_starts_ret((mbedtls_sha256_context *) ctx, 0));
}
static int sha256_wrap(const unsigned char *input, size_t ilen,
unsigned char *output) {
return (mbedtls_sha256_ret(input, ilen, output, 0));
}
const mbedtls_md_info_t mbedtls_sha256_info = {
MBEDTLS_MD_SHA256,
"SHA256",
32,
64,
sha256_starts_wrap,
sha224_update_wrap,
sha224_finish_wrap,
sha256_wrap,
sha224_ctx_alloc,
sha224_ctx_free,
sha224_clone_wrap,
sha224_process_wrap,
};
#endif /* MBEDTLS_SHA256_C */
#if defined(MBEDTLS_SHA512_C)
static int sha384_starts_wrap(void *ctx) {
return (mbedtls_sha512_starts_ret((mbedtls_sha512_context *) ctx, 1));
}
static int sha384_update_wrap(void *ctx, const unsigned char *input,
size_t ilen) {
return (mbedtls_sha512_update_ret((mbedtls_sha512_context *) ctx,
input, ilen));
}
static int sha384_finish_wrap(void *ctx, unsigned char *output) {
return (mbedtls_sha512_finish_ret((mbedtls_sha512_context *) ctx,
output));
}
static int sha384_wrap(const unsigned char *input, size_t ilen,
unsigned char *output) {
return (mbedtls_sha512_ret(input, ilen, output, 1));
}
static void *sha384_ctx_alloc(void) {
void *ctx = mbedtls_calloc(1, sizeof(mbedtls_sha512_context));
if (ctx != NULL)
mbedtls_sha512_init((mbedtls_sha512_context *) ctx);
return (ctx);
}
static void sha384_ctx_free(void *ctx) {
mbedtls_sha512_free((mbedtls_sha512_context *) ctx);
mbedtls_free(ctx);
}
static void sha384_clone_wrap(void *dst, const void *src) {
mbedtls_sha512_clone((mbedtls_sha512_context *) dst,
(const mbedtls_sha512_context *) src);
}
static int sha384_process_wrap(void *ctx, const unsigned char *data) {
return (mbedtls_internal_sha512_process((mbedtls_sha512_context *) ctx,
data));
}
const mbedtls_md_info_t mbedtls_sha384_info = {
MBEDTLS_MD_SHA384,
"SHA384",
48,
128,
sha384_starts_wrap,
sha384_update_wrap,
sha384_finish_wrap,
sha384_wrap,
sha384_ctx_alloc,
sha384_ctx_free,
sha384_clone_wrap,
sha384_process_wrap,
};
static int sha512_starts_wrap(void *ctx) {
return (mbedtls_sha512_starts_ret((mbedtls_sha512_context *) ctx, 0));
}
static int sha512_wrap(const unsigned char *input, size_t ilen,
unsigned char *output) {
return (mbedtls_sha512_ret(input, ilen, output, 0));
}
const mbedtls_md_info_t mbedtls_sha512_info = {
MBEDTLS_MD_SHA512,
"SHA512",
64,
128,
sha512_starts_wrap,
sha384_update_wrap,
sha384_finish_wrap,
sha512_wrap,
sha384_ctx_alloc,
sha384_ctx_free,
sha384_clone_wrap,
sha384_process_wrap,
};
#endif /* MBEDTLS_SHA512_C */
#endif /* MBEDTLS_MD_C */

View File

@@ -0,0 +1,744 @@
/*
* Buffer-based memory allocator
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#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_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 to good option here, but corrupting the heap seems
* worse than loosing 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 */

View File

@@ -0,0 +1,149 @@
/**
* \file memory_buffer_alloc.h
*
* \brief Buffer-based memory allocator
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBEDTLS_MEMORY_BUFFER_ALLOC_H
#define MBEDTLS_MEMORY_BUFFER_ALLOC_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include <stddef.h>
/**
* \name SECTION: Module settings
*
* The configuration options you can set for this module are in this section.
* Either change them in config.h or define them on the compiler command line.
* \{
*/
#if !defined(MBEDTLS_MEMORY_ALIGN_MULTIPLE)
#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */
#endif
/* \} name SECTION: Module settings */
#define MBEDTLS_MEMORY_VERIFY_NONE 0
#define MBEDTLS_MEMORY_VERIFY_ALLOC (1 << 0)
#define MBEDTLS_MEMORY_VERIFY_FREE (1 << 1)
#define MBEDTLS_MEMORY_VERIFY_ALWAYS (MBEDTLS_MEMORY_VERIFY_ALLOC | MBEDTLS_MEMORY_VERIFY_FREE)
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief Initialize use of stack-based memory allocator.
* The stack-based allocator does memory management inside the
* presented buffer and does not call calloc() and free().
* It sets the global mbedtls_calloc() and mbedtls_free() pointers
* to its own functions.
* (Provided mbedtls_calloc() and mbedtls_free() are thread-safe if
* MBEDTLS_THREADING_C is defined)
*
* \note This code is not optimized and provides a straight-forward
* implementation of a stack-based memory allocator.
*
* \param buf buffer to use as heap
* \param len size of the buffer
*/
void mbedtls_memory_buffer_alloc_init( unsigned char *buf, size_t len );
/**
* \brief Free the mutex for thread-safety and clear remaining memory
*/
void mbedtls_memory_buffer_alloc_free( void );
/**
* \brief Determine when the allocator should automatically verify the state
* of the entire chain of headers / meta-data.
* (Default: MBEDTLS_MEMORY_VERIFY_NONE)
*
* \param verify One of MBEDTLS_MEMORY_VERIFY_NONE, MBEDTLS_MEMORY_VERIFY_ALLOC,
* MBEDTLS_MEMORY_VERIFY_FREE or MBEDTLS_MEMORY_VERIFY_ALWAYS
*/
void mbedtls_memory_buffer_set_verify( int verify );
#if defined(MBEDTLS_MEMORY_DEBUG)
/**
* \brief Print out the status of the allocated memory (primarily for use
* after a program should have de-allocated all memory)
* Prints out a list of 'still allocated' blocks and their stack
* trace if MBEDTLS_MEMORY_BACKTRACE is defined.
*/
void mbedtls_memory_buffer_alloc_status( void );
/**
* \brief Get the peak heap usage so far
*
* \param max_used Peak number of bytes in use or committed. This
* includes bytes in allocated blocks too small to split
* into smaller blocks but larger than the requested size.
* \param max_blocks Peak number of blocks in use, including free and used
*/
void mbedtls_memory_buffer_alloc_max_get( size_t *max_used, size_t *max_blocks );
/**
* \brief Reset peak statistics
*/
void mbedtls_memory_buffer_alloc_max_reset( void );
/**
* \brief Get the current heap usage
*
* \param cur_used Current number of bytes in use or committed. This
* includes bytes in allocated blocks too small to split
* into smaller blocks but larger than the requested size.
* \param cur_blocks Current number of blocks in use, including free and used
*/
void mbedtls_memory_buffer_alloc_cur_get( size_t *cur_used, size_t *cur_blocks );
#endif /* MBEDTLS_MEMORY_DEBUG */
/**
* \brief Verifies that all headers in the memory buffer are correct
* and contain sane values. Helps debug buffer-overflow errors.
*
* Prints out first failure if MBEDTLS_MEMORY_DEBUG is defined.
* Prints out full header information if MBEDTLS_MEMORY_DEBUG
* is defined. (Includes stack trace information for each block if
* MBEDTLS_MEMORY_BACKTRACE is defined as well).
*
* \return 0 if verified, 1 otherwise
*/
int mbedtls_memory_buffer_alloc_verify( void );
#if defined(MBEDTLS_SELF_TEST)
/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if a test failed
*/
int mbedtls_memory_buffer_alloc_self_test( int verbose );
#endif
#ifdef __cplusplus
}
#endif
#endif /* memory_buffer_alloc.h */

35
common/mbedtls/net.h Normal file
View File

@@ -0,0 +1,35 @@
/**
* \file net.h
*
* \brief Deprecated header file that includes net_sockets.h
*
* \deprecated Superseded by mbedtls/net_sockets.h
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
#include "mbedtls/net_sockets.h"
#if defined(MBEDTLS_DEPRECATED_WARNING)
#warning "Deprecated header file: Superseded by mbedtls/net_sockets.h"
#endif /* MBEDTLS_DEPRECATED_WARNING */
#endif /* !MBEDTLS_DEPRECATED_REMOVED */

View File

@@ -0,0 +1,694 @@
/*
* TCP/IP or UDP/IP networking functions
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Enable definition of getaddrinfo() even when compiling with -std=c99. Must
* be set before config.h, which pulls in glibc's features.h indirectly.
* Harmless on other platforms. */
#define _POSIX_C_SOURCE 200112L
#define _XOPEN_SOURCE 600 /* sockaddr_storage */
#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 config.h"
#endif
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdlib.h>
#endif
#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 )
#if !defined(_WIN32_WINNT)
/* Enables getaddrinfo() & Co */
#define _WIN32_WINNT 0x0501
#endif
#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 )
#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>
#include <time.h>
#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 );
}
/*
* 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;
}
close( ctx->fd );
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 )
{
close( ctx->fd );
ret = MBEDTLS_ERR_NET_SOCKET_FAILED;
continue;
}
if( bind( ctx->fd, cur->ai_addr, MSVC_INT_CAST cur->ai_addrlen ) != 0 )
{
close( ctx->fd );
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 )
{
close( ctx->fd );
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 *ip_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;
*ip_len = sizeof( addr4->sin_addr.s_addr );
if( buf_size < *ip_len )
return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL );
memcpy( client_ip, &addr4->sin_addr.s_addr, *ip_len );
}
else
{
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr;
*ip_len = sizeof( addr6->sin6_addr.s6_addr );
if( buf_size < *ip_len )
return( MBEDTLS_ERR_NET_BUFFER_TOO_SMALL );
memcpy( client_ip, &addr6->sin6_addr.s6_addr, *ip_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;
if( fd < 0 )
return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
/* 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( fd >= FD_SETSIZE )
return( MBEDTLS_ERR_NET_POLL_FAILED );
#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( fd, &read_fds );
}
FD_ZERO( &write_fds );
if( rw & MBEDTLS_NET_POLL_WRITE )
{
rw &= ~MBEDTLS_NET_POLL_WRITE;
FD_SET( 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__) )
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;
if( fd < 0 )
return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
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;
if( fd < 0 )
return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
/* 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( fd >= FD_SETSIZE )
return( MBEDTLS_ERR_NET_POLL_FAILED );
FD_ZERO( &read_fds );
FD_SET( 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;
if( fd < 0 )
return( MBEDTLS_ERR_NET_INVALID_CONTEXT );
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->fd == -1 )
return;
shutdown( ctx->fd, 2 );
close( ctx->fd );
ctx->fd = -1;
}
#endif /* MBEDTLS_NET_C */

View File

@@ -0,0 +1,288 @@
/**
* \file net_sockets.h
*
* \brief Network sockets abstraction layer to integrate Mbed TLS into a
* BSD-style sockets API.
*
* The network sockets module provides an example integration of the
* Mbed TLS library into a BSD sockets implementation. The module is
* intended to be an example of how Mbed TLS can be integrated into a
* networking stack, as well as to be Mbed TLS's network integration
* for its supported platforms.
*
* The module is intended only to be used with the Mbed TLS library and
* is not intended to be used by third party application software
* directly.
*
* The supported platforms are as follows:
* * Microsoft Windows and Windows CE
* * POSIX/Unix platforms including Linux, OS X
*
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBEDTLS_NET_SOCKETS_H
#define MBEDTLS_NET_SOCKETS_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include "mbedtls/ssl.h"
#include <stddef.h>
#include <stdint.h>
#define MBEDTLS_ERR_NET_SOCKET_FAILED -0x0042 /**< Failed to open a socket. */
#define MBEDTLS_ERR_NET_CONNECT_FAILED -0x0044 /**< The connection to the given server / port failed. */
#define MBEDTLS_ERR_NET_BIND_FAILED -0x0046 /**< Binding of the socket failed. */
#define MBEDTLS_ERR_NET_LISTEN_FAILED -0x0048 /**< Could not listen on the socket. */
#define MBEDTLS_ERR_NET_ACCEPT_FAILED -0x004A /**< Could not accept the incoming connection. */
#define MBEDTLS_ERR_NET_RECV_FAILED -0x004C /**< Reading information from the socket failed. */
#define MBEDTLS_ERR_NET_SEND_FAILED -0x004E /**< Sending information through the socket failed. */
#define MBEDTLS_ERR_NET_CONN_RESET -0x0050 /**< Connection was reset by peer. */
#define MBEDTLS_ERR_NET_UNKNOWN_HOST -0x0052 /**< Failed to get an IP address for the given hostname. */
#define MBEDTLS_ERR_NET_BUFFER_TOO_SMALL -0x0043 /**< Buffer is too small to hold the data. */
#define MBEDTLS_ERR_NET_INVALID_CONTEXT -0x0045 /**< The context is invalid, eg because it was free()ed. */
#define MBEDTLS_ERR_NET_POLL_FAILED -0x0047 /**< Polling the net context failed. */
#define MBEDTLS_ERR_NET_BAD_INPUT_DATA -0x0049 /**< Input invalid. */
#define MBEDTLS_NET_LISTEN_BACKLOG 10 /**< The backlog that listen() should use. */
#define MBEDTLS_NET_PROTO_TCP 0 /**< The TCP transport protocol */
#define MBEDTLS_NET_PROTO_UDP 1 /**< The UDP transport protocol */
#define MBEDTLS_NET_POLL_READ 1 /**< Used in \c mbedtls_net_poll to check for pending data */
#define MBEDTLS_NET_POLL_WRITE 2 /**< Used in \c mbedtls_net_poll to check if write possible */
#ifdef __cplusplus
extern "C" {
#endif
/**
* Wrapper type for sockets.
*
* Currently backed by just a file descriptor, but might be more in the future
* (eg two file descriptors for combined IPv4 + IPv6 support, or additional
* structures for hand-made UDP demultiplexing).
*/
typedef struct mbedtls_net_context
{
int fd; /**< The underlying file descriptor */
}
mbedtls_net_context;
/**
* \brief Initialize a context
* Just makes the context ready to be used or freed safely.
*
* \param ctx Context to initialize
*/
void mbedtls_net_init( mbedtls_net_context *ctx );
/**
* \brief Initiate a connection with host:port in the given protocol
*
* \param ctx Socket to use
* \param host Host to connect to
* \param port Port to connect to
* \param proto Protocol: MBEDTLS_NET_PROTO_TCP or MBEDTLS_NET_PROTO_UDP
*
* \return 0 if successful, or one of:
* MBEDTLS_ERR_NET_SOCKET_FAILED,
* MBEDTLS_ERR_NET_UNKNOWN_HOST,
* MBEDTLS_ERR_NET_CONNECT_FAILED
*
* \note Sets the socket in connected mode even with UDP.
*/
int mbedtls_net_connect( mbedtls_net_context *ctx, const char *host, const char *port, int proto );
/**
* \brief Create a receiving socket on bind_ip:port in the chosen
* protocol. If bind_ip == NULL, all interfaces are bound.
*
* \param ctx Socket to use
* \param bind_ip IP to bind to, can be NULL
* \param port Port number to use
* \param proto Protocol: MBEDTLS_NET_PROTO_TCP or MBEDTLS_NET_PROTO_UDP
*
* \return 0 if successful, or one of:
* MBEDTLS_ERR_NET_SOCKET_FAILED,
* MBEDTLS_ERR_NET_UNKNOWN_HOST,
* MBEDTLS_ERR_NET_BIND_FAILED,
* MBEDTLS_ERR_NET_LISTEN_FAILED
*
* \note Regardless of the protocol, opens the sockets and binds it.
* In addition, make the socket listening if protocol is TCP.
*/
int mbedtls_net_bind( mbedtls_net_context *ctx, const char *bind_ip, const char *port, int proto );
/**
* \brief Accept a connection from a remote client
*
* \param bind_ctx Relevant socket
* \param client_ctx Will contain the connected client socket
* \param client_ip Will contain the client IP address, can be NULL
* \param buf_size Size of the client_ip buffer
* \param ip_len Will receive the size of the client IP written,
* can be NULL if client_ip is null
*
* \return 0 if successful, or
* MBEDTLS_ERR_NET_SOCKET_FAILED,
* MBEDTLS_ERR_NET_BIND_FAILED,
* MBEDTLS_ERR_NET_ACCEPT_FAILED, or
* MBEDTLS_ERR_NET_BUFFER_TOO_SMALL if buf_size is too small,
* MBEDTLS_ERR_SSL_WANT_READ if bind_fd was set to
* non-blocking and accept() would block.
*/
int mbedtls_net_accept( mbedtls_net_context *bind_ctx,
mbedtls_net_context *client_ctx,
void *client_ip, size_t buf_size, size_t *ip_len );
/**
* \brief Check and wait for the context to be ready for read/write
*
* \note The current implementation of this function uses
* select() and returns an error if the file descriptor
* is \c FD_SETSIZE or greater.
*
* \param ctx Socket to check
* \param rw Bitflag composed of MBEDTLS_NET_POLL_READ and
* MBEDTLS_NET_POLL_WRITE specifying the events
* to wait for:
* - If MBEDTLS_NET_POLL_READ is set, the function
* will return as soon as the net context is available
* for reading.
* - If MBEDTLS_NET_POLL_WRITE is set, the function
* will return as soon as the net context is available
* for writing.
* \param timeout Maximal amount of time to wait before returning,
* in milliseconds. If \c timeout is zero, the
* function returns immediately. If \c timeout is
* -1u, the function blocks potentially indefinitely.
*
* \return Bitmask composed of MBEDTLS_NET_POLL_READ/WRITE
* on success or timeout, or a negative return code otherwise.
*/
int mbedtls_net_poll( mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout );
/**
* \brief Set the socket blocking
*
* \param ctx Socket to set
*
* \return 0 if successful, or a non-zero error code
*/
int mbedtls_net_set_block( mbedtls_net_context *ctx );
/**
* \brief Set the socket non-blocking
*
* \param ctx Socket to set
*
* \return 0 if successful, or a non-zero error code
*/
int mbedtls_net_set_nonblock( mbedtls_net_context *ctx );
/**
* \brief Portable usleep helper
*
* \param usec Amount of microseconds to sleep
*
* \note Real amount of time slept will not be less than
* select()'s timeout granularity (typically, 10ms).
*/
void mbedtls_net_usleep( unsigned long usec );
/**
* \brief Read at most 'len' characters. If no error occurs,
* the actual amount read is returned.
*
* \param ctx Socket
* \param buf The buffer to write to
* \param len Maximum length of the buffer
*
* \return the number of bytes received,
* or a non-zero error code; with a non-blocking socket,
* MBEDTLS_ERR_SSL_WANT_READ indicates read() would block.
*/
int mbedtls_net_recv( void *ctx, unsigned char *buf, size_t len );
/**
* \brief Write at most 'len' characters. If no error occurs,
* the actual amount read is returned.
*
* \param ctx Socket
* \param buf The buffer to read from
* \param len The length of the buffer
*
* \return the number of bytes sent,
* or a non-zero error code; with a non-blocking socket,
* MBEDTLS_ERR_SSL_WANT_WRITE indicates write() would block.
*/
int mbedtls_net_send( void *ctx, const unsigned char *buf, size_t len );
/**
* \brief Read at most 'len' characters, blocking for at most
* 'timeout' seconds. If no error occurs, the actual amount
* read is returned.
*
* \note The current implementation of this function uses
* select() and returns an error if the file descriptor
* is \c FD_SETSIZE or greater.
*
* \param ctx Socket
* \param buf The buffer to write to
* \param len Maximum length of the buffer
* \param timeout Maximum number of milliseconds to wait for data
* 0 means no timeout (wait forever)
*
* \return The number of bytes received if successful.
* MBEDTLS_ERR_SSL_TIMEOUT if the operation timed out.
* MBEDTLS_ERR_SSL_WANT_READ if interrupted by a signal.
* Another negative error code (MBEDTLS_ERR_NET_xxx)
* for other failures.
*
* \note This function will block (until data becomes available or
* timeout is reached) even if the socket is set to
* non-blocking. Handling timeouts with non-blocking reads
* requires a different strategy.
*/
int mbedtls_net_recv_timeout( void *ctx, unsigned char *buf, size_t len,
uint32_t timeout );
/**
* \brief Closes down the connection and free associated data
*
* \param ctx The context to close
*/
void mbedtls_net_close( mbedtls_net_context *ctx );
/**
* \brief Gracefully shutdown the connection and free associated data
*
* \param ctx The context to free
*/
void mbedtls_net_free( mbedtls_net_context *ctx );
#ifdef __cplusplus
}
#endif
#endif /* net_sockets.h */

750
common/mbedtls/nist_kw.c Normal file
View File

@@ -0,0 +1,750 @@
/*
* 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
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* 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 <stdint.h>
#include <string.h>
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
#if !defined(MBEDTLS_NIST_KW_ALT)
#define KW_SEMIBLOCK_LENGTH 8
#define MIN_SEMIBLOCKS_COUNT 3
/* constant-time buffer comparison */
static inline unsigned char mbedtls_nist_kw_safer_memcmp( const void *a, const void *b, size_t n )
{
size_t i;
volatile const unsigned char *A = (volatile const unsigned char *) a;
volatile const unsigned char *B = (volatile const unsigned char *) b;
volatile unsigned char diff = 0;
for( i = 0; 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;
}
return( diff );
}
/*! 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};
#ifndef GET_UINT32_BE
#define GET_UINT32_BE(n,b,i) \
do { \
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
| ( (uint32_t) (b)[(i) + 3] ); \
} while( 0 )
#endif
#ifndef PUT_UINT32_BE
#define PUT_UINT32_BE(n,b,i) \
do { \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 3] = (unsigned char) ( (n) ); \
} while( 0 )
#endif
/*
* 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( cipher_info->block_size != 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 )
{
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];
unsigned char *R2 = output + KW_SEMIBLOCK_LENGTH;
unsigned char *A = output;
*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 );
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
{
/*
* 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 = output + ( semiblocks - 2 ) * KW_SEMIBLOCK_LENGTH;
*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 );
/* 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 i, olen;
unsigned char A[KW_SEMIBLOCK_LENGTH];
unsigned char diff, bad_padding = 0;
*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_nist_kw_safer_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_nist_kw_safer_memcmp( NIST_KW_ICV2, A, KW_SEMIBLOCK_LENGTH / 2 );
if( diff != 0 )
{
ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
}
GET_UINT32_BE( Plen, 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;
if ( padlen > 7 )
{
padlen &= 7;
ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
}
/* 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];
}
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( &bad_padding, sizeof( bad_padding) );
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)
#define KW_TESTS 3
/*
* 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[KW_TESTS] = { 16, 24, 32 };
static const unsigned char kw_key[KW_TESTS][32] = {
{ 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2,
0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 },
{ 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 }
};
static const unsigned char kw_msg[KW_TESTS][40] = {
{ 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea,
0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f },
{ 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 }
};
static const size_t kw_msg_len[KW_TESTS] = { 16, 40, 24 };
static const size_t kw_out_len[KW_TESTS] = { 24, 48, 32 };
static const unsigned char kw_res[KW_TESTS][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 },
{ 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 }
};
static const unsigned char kwp_key[KW_TESTS][32] = {
{ 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a,
0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 },
{ 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 }
};
static const unsigned char kwp_msg[KW_TESTS][31] = {
{ 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8,
0x96 },
{ 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 }
};
static const size_t kwp_msg_len[KW_TESTS] = { 9, 31, 1 };
static const unsigned char kwp_res[KW_TESTS][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 },
{ 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 }
};
static const size_t kwp_out_len[KW_TESTS] = { 24, 40, 16 };
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 );
for( i = 0; i < KW_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" );
}
for( i = 0; i < KW_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 */

182
common/mbedtls/nist_kw.h Normal file
View File

@@ -0,0 +1,182 @@
/**
* \file nist_kw.h
*
* \brief This file provides an API for key wrapping (KW) and key wrapping with
* padding (KWP) as defined in NIST SP 800-38F.
* https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38F.pdf
*
* Key wrapping specifies a deterministic authenticated-encryption mode
* of operation, according to <em>NIST SP 800-38F: Recommendation for
* Block Cipher Modes of Operation: Methods for Key Wrapping</em>. Its
* purpose is to protect cryptographic keys.
*
* Its equivalent is RFC 3394 for KW, and RFC 5649 for KWP.
* https://tools.ietf.org/html/rfc3394
* https://tools.ietf.org/html/rfc5649
*
*/
/*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBEDTLS_NIST_KW_H
#define MBEDTLS_NIST_KW_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include "mbedtls/cipher.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef enum
{
MBEDTLS_KW_MODE_KW = 0,
MBEDTLS_KW_MODE_KWP = 1
} mbedtls_nist_kw_mode_t;
#if !defined(MBEDTLS_NIST_KW_ALT)
// Regular implementation
//
/**
* \brief The key wrapping context-type definition. The key wrapping context is passed
* to the APIs called.
*
* \note The definition of this type may change in future library versions.
* Don't make any assumptions on this context!
*/
typedef struct {
mbedtls_cipher_context_t cipher_ctx; /*!< The cipher context used. */
} mbedtls_nist_kw_context;
#else /* MBEDTLS_NIST_key wrapping_ALT */
#include "nist_kw_alt.h"
#endif /* MBEDTLS_NIST_KW_ALT */
/**
* \brief This function initializes the specified key wrapping context
* to make references valid and prepare the context
* for mbedtls_nist_kw_setkey() or mbedtls_nist_kw_free().
*
* \param ctx The key wrapping context to initialize.
*
*/
void mbedtls_nist_kw_init( mbedtls_nist_kw_context *ctx );
/**
* \brief This function initializes the key wrapping context set in the
* \p ctx parameter and sets the encryption key.
*
* \param ctx The key wrapping context.
* \param cipher The 128-bit block cipher to use. Only AES is supported.
* \param key The Key Encryption Key (KEK).
* \param keybits The KEK size in bits. This must be acceptable by the cipher.
* \param is_wrap Specify whether the operation within the context is wrapping or unwrapping
*
* \return \c 0 on success.
* \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for any invalid input.
* \return \c MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE for 128-bit block ciphers
* which are not supported.
* \return cipher-specific error code on failure of the underlying cipher.
*/
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 );
/**
* \brief This function releases and clears the specified key wrapping context
* and underlying cipher sub-context.
*
* \param ctx The key wrapping context to clear.
*/
void mbedtls_nist_kw_free( mbedtls_nist_kw_context *ctx );
/**
* \brief This function encrypts a buffer using key wrapping.
*
* \param ctx The key wrapping context to use for encryption.
* \param mode The key wrapping mode to use (MBEDTLS_KW_MODE_KW or MBEDTLS_KW_MODE_KWP)
* \param input The buffer holding the input data.
* \param in_len The length of the input data in Bytes.
* The input uses units of 8 Bytes called semiblocks.
* <ul><li>For KW mode: a multiple of 8 bytes between 16 and 2^57-8 inclusive. </li>
* <li>For KWP mode: any length between 1 and 2^32-1 inclusive.</li></ul>
* \param[out] output The buffer holding the output data.
* <ul><li>For KW mode: Must be at least 8 bytes larger than \p in_len.</li>
* <li>For KWP mode: Must be at least 8 bytes larger rounded up to a multiple of
* 8 bytes for KWP (15 bytes at most).</li></ul>
* \param[out] out_len The number of bytes written to the output buffer. \c 0 on failure.
* \param[in] out_size The capacity of the output buffer.
*
* \return \c 0 on success.
* \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for invalid input length.
* \return cipher-specific error code on failure of the underlying cipher.
*/
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 );
/**
* \brief This function decrypts a buffer using key wrapping.
*
* \param ctx The key wrapping context to use for decryption.
* \param mode The key wrapping mode to use (MBEDTLS_KW_MODE_KW or MBEDTLS_KW_MODE_KWP)
* \param input The buffer holding the input data.
* \param in_len The length of the input data in Bytes.
* The input uses units of 8 Bytes called semiblocks.
* The input must be a multiple of semiblocks.
* <ul><li>For KW mode: a multiple of 8 bytes between 24 and 2^57 inclusive. </li>
* <li>For KWP mode: a multiple of 8 bytes between 16 and 2^32 inclusive.</li></ul>
* \param[out] output The buffer holding the output data.
* The output buffer's minimal length is 8 bytes shorter than \p in_len.
* \param[out] out_len The number of bytes written to the output buffer. \c 0 on failure.
* For KWP mode, the length could be up to 15 bytes shorter than \p in_len,
* depending on how much padding was added to the data.
* \param[in] out_size The capacity of the output buffer.
*
* \return \c 0 on success.
* \return \c MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA for invalid input length.
* \return \c MBEDTLS_ERR_CIPHER_AUTH_FAILED for verification failure of the ciphertext.
* \return cipher-specific error code on failure of the underlying cipher.
*/
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);
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
/**
* \brief The key wrapping checkup routine.
*
* \return \c 0 on success.
* \return \c 1 on failure.
*/
int mbedtls_nist_kw_self_test( int verbose );
#endif /* MBEDTLS_SELF_TEST && MBEDTLS_AES_C */
#ifdef __cplusplus
}
#endif
#endif /* MBEDTLS_NIST_KW_H */

View File

@@ -3,36 +3,29 @@
* *
* \brief Object Identifier (OID) database * \brief Object Identifier (OID) database
* *
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
#if !defined(MBEDTLS_CONFIG_FILE) #include "common.h"
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_OID_C) #if defined(MBEDTLS_OID_C)
#include "mbedtls/oid.h" #include "mbedtls/oid.h"
#include "mbedtls/rsa.h" #include "mbedtls/rsa.h"
#include "mbedtls/error.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@@ -43,10 +36,6 @@
#define mbedtls_snprintf snprintf #define mbedtls_snprintf snprintf
#endif #endif
#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
#include "mbedtls/x509.h"
#endif
/* /*
* Macro to automatically add the size of #define'd OIDs * Macro to automatically add the size of #define'd OIDs
*/ */
@@ -56,21 +45,23 @@
* Macro to generate an internal function for oid_XXX_from_asn1() (used by * Macro to generate an internal function for oid_XXX_from_asn1() (used by
* the other functions) * the other functions)
*/ */
#define FN_OID_TYPED_FROM_ASN1( TYPE_T, NAME, LIST ) \ #define FN_OID_TYPED_FROM_ASN1( TYPE_T, NAME, LIST ) \
static const TYPE_T * oid_ ## NAME ## _from_asn1( const mbedtls_asn1_buf *oid ) \ static const TYPE_T * oid_ ## NAME ## _from_asn1( \
{ \ const mbedtls_asn1_buf *oid ) \
const TYPE_T *p = LIST; \ { \
const mbedtls_oid_descriptor_t *cur = (const mbedtls_oid_descriptor_t *) p; \ const TYPE_T *p = (LIST); \
if( p == NULL || oid == NULL ) return( NULL ); \ const mbedtls_oid_descriptor_t *cur = \
while( cur->asn1 != NULL ) { \ (const mbedtls_oid_descriptor_t *) p; \
if( cur->asn1_len == oid->len && \ if( p == NULL || oid == NULL ) return( NULL ); \
memcmp( cur->asn1, oid->p, oid->len ) == 0 ) { \ while( cur->asn1 != NULL ) { \
return( p ); \ if( cur->asn1_len == oid->len && \
} \ memcmp( cur->asn1, oid->p, oid->len ) == 0 ) { \
p++; \ return( p ); \
cur = (const mbedtls_oid_descriptor_t *) p; \ } \
} \ p++; \
return( NULL ); \ cur = (const mbedtls_oid_descriptor_t *) p; \
} \
return( NULL ); \
} }
/* /*
@@ -78,26 +69,26 @@
* descriptor of an mbedtls_oid_descriptor_t wrapper. * descriptor of an mbedtls_oid_descriptor_t wrapper.
*/ */
#define FN_OID_GET_DESCRIPTOR_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ #define FN_OID_GET_DESCRIPTOR_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \
int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \
{ \ { \
const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \
if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \
*ATTR1 = data->descriptor.ATTR1; \ *ATTR1 = data->descriptor.ATTR1; \
return( 0 ); \ return( 0 ); \
} }
/* /*
* Macro to generate a function for retrieving a single attribute from an * Macro to generate a function for retrieving a single attribute from an
* mbedtls_oid_descriptor_t wrapper. * mbedtls_oid_descriptor_t wrapper.
*/ */
#define FN_OID_GET_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ #define FN_OID_GET_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \
int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \
{ \ { \
const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \
if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \
*ATTR1 = data->ATTR1; \ *ATTR1 = data->ATTR1; \
return( 0 ); \ return( 0 ); \
} }
/* /*
* Macro to generate a function for retrieving two attributes from an * Macro to generate a function for retrieving two attributes from an
@@ -105,12 +96,13 @@
*/ */
#define FN_OID_GET_ATTR2(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1, \ #define FN_OID_GET_ATTR2(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1, \
ATTR2_TYPE, ATTR2) \ ATTR2_TYPE, ATTR2) \
int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1, ATTR2_TYPE * ATTR2 ) \ int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1, \
ATTR2_TYPE * ATTR2 ) \
{ \ { \
const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \
if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \
*ATTR1 = data->ATTR1; \ *(ATTR1) = data->ATTR1; \
*ATTR2 = data->ATTR2; \ *(ATTR2) = data->ATTR2; \
return( 0 ); \ return( 0 ); \
} }
@@ -119,19 +111,19 @@ int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1, ATTR2_TYPE * ATTR2
* attribute from a mbedtls_oid_descriptor_t wrapper. * attribute from a mbedtls_oid_descriptor_t wrapper.
*/ */
#define FN_OID_GET_OID_BY_ATTR1(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1) \ #define FN_OID_GET_OID_BY_ATTR1(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1) \
int FN_NAME( ATTR1_TYPE ATTR1, const char **oid, size_t *olen ) \ int FN_NAME( ATTR1_TYPE ATTR1, const char **oid, size_t *olen ) \
{ \ { \
const TYPE_T *cur = LIST; \ const TYPE_T *cur = (LIST); \
while( cur->descriptor.asn1 != NULL ) { \ while( cur->descriptor.asn1 != NULL ) { \
if( cur->ATTR1 == ATTR1 ) { \ if( cur->ATTR1 == (ATTR1) ) { \
*oid = cur->descriptor.asn1; \ *oid = cur->descriptor.asn1; \
*olen = cur->descriptor.asn1_len; \ *olen = cur->descriptor.asn1_len; \
return( 0 ); \ return( 0 ); \
} \ } \
cur++; \ cur++; \
} \ } \
return( MBEDTLS_ERR_OID_NOT_FOUND ); \ return( MBEDTLS_ERR_OID_NOT_FOUND ); \
} }
/* /*
* Macro to generate a function for retrieving the OID based on two * Macro to generate a function for retrieving the OID based on two
@@ -142,9 +134,9 @@ int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1, ATTR2_TYPE * ATTR2
int FN_NAME( ATTR1_TYPE ATTR1, ATTR2_TYPE ATTR2, const char **oid , \ int FN_NAME( ATTR1_TYPE ATTR1, ATTR2_TYPE ATTR2, const char **oid , \
size_t *olen ) \ size_t *olen ) \
{ \ { \
const TYPE_T *cur = LIST; \ const TYPE_T *cur = (LIST); \
while( cur->descriptor.asn1 != NULL ) { \ while( cur->descriptor.asn1 != NULL ) { \
if( cur->ATTR1 == ATTR1 && cur->ATTR2 == ATTR2 ) { \ if( cur->ATTR1 == (ATTR1) && cur->ATTR2 == (ATTR2) ) { \
*oid = cur->descriptor.asn1; \ *oid = cur->descriptor.asn1; \
*olen = cur->descriptor.asn1_len; \ *olen = cur->descriptor.asn1_len; \
return( 0 ); \ return( 0 ); \
@@ -154,7 +146,6 @@ int FN_NAME( ATTR1_TYPE ATTR1, ATTR2_TYPE ATTR2, const char **oid , \
return( MBEDTLS_ERR_OID_NOT_FOUND ); \ return( MBEDTLS_ERR_OID_NOT_FOUND ); \
} }
#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
/* /*
* For X520 attribute types * For X520 attribute types
*/ */
@@ -163,81 +154,82 @@ typedef struct {
const char *short_name; const char *short_name;
} oid_x520_attr_t; } oid_x520_attr_t;
static const oid_x520_attr_t oid_x520_attr_type[] = { static const oid_x520_attr_t oid_x520_attr_type[] =
{
{ {
{ ADD_LEN(MBEDTLS_OID_AT_CN), "id-at-commonName", "Common Name" }, { ADD_LEN( MBEDTLS_OID_AT_CN ), "id-at-commonName", "Common Name" },
"CN", "CN",
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_AT_COUNTRY), "id-at-countryName", "Country" }, { ADD_LEN( MBEDTLS_OID_AT_COUNTRY ), "id-at-countryName", "Country" },
"C", "C",
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_AT_LOCALITY), "id-at-locality", "Locality" }, { ADD_LEN( MBEDTLS_OID_AT_LOCALITY ), "id-at-locality", "Locality" },
"L", "L",
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_AT_STATE), "id-at-state", "State" }, { ADD_LEN( MBEDTLS_OID_AT_STATE ), "id-at-state", "State" },
"ST", "ST",
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_AT_ORGANIZATION), "id-at-organizationName", "Organization" }, { ADD_LEN( MBEDTLS_OID_AT_ORGANIZATION ),"id-at-organizationName", "Organization" },
"O", "O",
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_AT_ORG_UNIT), "id-at-organizationalUnitName", "Org Unit" }, { ADD_LEN( MBEDTLS_OID_AT_ORG_UNIT ), "id-at-organizationalUnitName", "Org Unit" },
"OU", "OU",
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_PKCS9_EMAIL), "emailAddress", "E-mail address" }, { ADD_LEN( MBEDTLS_OID_PKCS9_EMAIL ), "emailAddress", "E-mail address" },
"emailAddress", "emailAddress",
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_AT_SERIAL_NUMBER), "id-at-serialNumber", "Serial number" }, { ADD_LEN( MBEDTLS_OID_AT_SERIAL_NUMBER ),"id-at-serialNumber", "Serial number" },
"serialNumber", "serialNumber",
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_AT_POSTAL_ADDRESS), "id-at-postalAddress", "Postal address" }, { ADD_LEN( MBEDTLS_OID_AT_POSTAL_ADDRESS ),"id-at-postalAddress", "Postal address" },
"postalAddress", "postalAddress",
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_AT_POSTAL_CODE), "id-at-postalCode", "Postal code" }, { ADD_LEN( MBEDTLS_OID_AT_POSTAL_CODE ), "id-at-postalCode", "Postal code" },
"postalCode", "postalCode",
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_AT_SUR_NAME), "id-at-surName", "Surname" }, { ADD_LEN( MBEDTLS_OID_AT_SUR_NAME ), "id-at-surName", "Surname" },
"SN", "SN",
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_AT_GIVEN_NAME), "id-at-givenName", "Given name" }, { ADD_LEN( MBEDTLS_OID_AT_GIVEN_NAME ), "id-at-givenName", "Given name" },
"GN", "GN",
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_AT_INITIALS), "id-at-initials", "Initials" }, { ADD_LEN( MBEDTLS_OID_AT_INITIALS ), "id-at-initials", "Initials" },
"initials", "initials",
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_AT_GENERATION_QUALIFIER), "id-at-generationQualifier", "Generation qualifier" }, { ADD_LEN( MBEDTLS_OID_AT_GENERATION_QUALIFIER ), "id-at-generationQualifier", "Generation qualifier" },
"generationQualifier", "generationQualifier",
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_AT_TITLE), "id-at-title", "Title" }, { ADD_LEN( MBEDTLS_OID_AT_TITLE ), "id-at-title", "Title" },
"title", "title",
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_AT_DN_QUALIFIER), "id-at-dnQualifier", "Distinguished Name qualifier" }, { ADD_LEN( MBEDTLS_OID_AT_DN_QUALIFIER ),"id-at-dnQualifier", "Distinguished Name qualifier" },
"dnQualifier", "dnQualifier",
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_AT_PSEUDONYM), "id-at-pseudonym", "Pseudonym" }, { ADD_LEN( MBEDTLS_OID_AT_PSEUDONYM ), "id-at-pseudonym", "Pseudonym" },
"pseudonym", "pseudonym",
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_DOMAIN_COMPONENT), "id-domainComponent", "Domain component" }, { ADD_LEN( MBEDTLS_OID_DOMAIN_COMPONENT ), "id-domainComponent", "Domain component" },
"DC", "DC",
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_AT_UNIQUE_IDENTIFIER), "id-at-uniqueIdentifier", "Unique Identifier" }, { ADD_LEN( MBEDTLS_OID_AT_UNIQUE_IDENTIFIER ), "id-at-uniqueIdentifier", "Unique Identifier" },
"uniqueIdentifier", "uniqueIdentifier",
}, },
{ {
@@ -257,26 +249,31 @@ typedef struct {
int ext_type; int ext_type;
} oid_x509_ext_t; } oid_x509_ext_t;
static const oid_x509_ext_t oid_x509_ext[] = { static const oid_x509_ext_t oid_x509_ext[] =
{
{ {
{ ADD_LEN(MBEDTLS_OID_BASIC_CONSTRAINTS), "id-ce-basicConstraints", "Basic Constraints" }, { ADD_LEN( MBEDTLS_OID_BASIC_CONSTRAINTS ), "id-ce-basicConstraints", "Basic Constraints" },
MBEDTLS_X509_EXT_BASIC_CONSTRAINTS, MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS,
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_KEY_USAGE), "id-ce-keyUsage", "Key Usage" }, { ADD_LEN( MBEDTLS_OID_KEY_USAGE ), "id-ce-keyUsage", "Key Usage" },
MBEDTLS_X509_EXT_KEY_USAGE, MBEDTLS_OID_X509_EXT_KEY_USAGE,
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_EXTENDED_KEY_USAGE), "id-ce-extKeyUsage", "Extended Key Usage" }, { ADD_LEN( MBEDTLS_OID_EXTENDED_KEY_USAGE ), "id-ce-extKeyUsage", "Extended Key Usage" },
MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE, MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE,
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_SUBJECT_ALT_NAME), "id-ce-subjectAltName", "Subject Alt Name" }, { ADD_LEN( MBEDTLS_OID_SUBJECT_ALT_NAME ), "id-ce-subjectAltName", "Subject Alt Name" },
MBEDTLS_X509_EXT_SUBJECT_ALT_NAME, MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME,
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_NS_CERT_TYPE), "id-netscape-certtype", "Netscape Certificate Type" }, { ADD_LEN( MBEDTLS_OID_NS_CERT_TYPE ), "id-netscape-certtype", "Netscape Certificate Type" },
MBEDTLS_X509_EXT_NS_CERT_TYPE, MBEDTLS_OID_X509_EXT_NS_CERT_TYPE,
},
{
{ ADD_LEN( MBEDTLS_OID_CERTIFICATE_POLICIES ), "id-ce-certificatePolicies", "Certificate Policies" },
MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES,
}, },
{ {
{ NULL, 0, NULL, NULL }, { NULL, 0, NULL, NULL },
@@ -287,19 +284,29 @@ static const oid_x509_ext_t oid_x509_ext[] = {
FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext) FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext)
FN_OID_GET_ATTR1(mbedtls_oid_get_x509_ext_type, oid_x509_ext_t, x509_ext, int, ext_type) FN_OID_GET_ATTR1(mbedtls_oid_get_x509_ext_type, oid_x509_ext_t, x509_ext, int, ext_type)
static const mbedtls_oid_descriptor_t oid_ext_key_usage[] = { static const mbedtls_oid_descriptor_t oid_ext_key_usage[] =
{ ADD_LEN(MBEDTLS_OID_SERVER_AUTH), "id-kp-serverAuth", "TLS Web Server Authentication" }, {
{ ADD_LEN(MBEDTLS_OID_CLIENT_AUTH), "id-kp-clientAuth", "TLS Web Client Authentication" }, { ADD_LEN( MBEDTLS_OID_SERVER_AUTH ), "id-kp-serverAuth", "TLS Web Server Authentication" },
{ ADD_LEN(MBEDTLS_OID_CODE_SIGNING), "id-kp-codeSigning", "Code Signing" }, { ADD_LEN( MBEDTLS_OID_CLIENT_AUTH ), "id-kp-clientAuth", "TLS Web Client Authentication" },
{ ADD_LEN(MBEDTLS_OID_EMAIL_PROTECTION), "id-kp-emailProtection", "E-mail Protection" }, { ADD_LEN( MBEDTLS_OID_CODE_SIGNING ), "id-kp-codeSigning", "Code Signing" },
{ ADD_LEN(MBEDTLS_OID_TIME_STAMPING), "id-kp-timeStamping", "Time Stamping" }, { ADD_LEN( MBEDTLS_OID_EMAIL_PROTECTION ), "id-kp-emailProtection", "E-mail Protection" },
{ ADD_LEN(MBEDTLS_OID_OCSP_SIGNING), "id-kp-OCSPSigning", "OCSP Signing" }, { ADD_LEN( MBEDTLS_OID_TIME_STAMPING ), "id-kp-timeStamping", "Time Stamping" },
{ ADD_LEN( MBEDTLS_OID_OCSP_SIGNING ), "id-kp-OCSPSigning", "OCSP Signing" },
{ ADD_LEN( MBEDTLS_OID_WISUN_FAN ), "id-kp-wisun-fan-device", "Wi-SUN Alliance Field Area Network (FAN)" },
{ NULL, 0, NULL, NULL }, { NULL, 0, NULL, NULL },
}; };
FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, ext_key_usage, oid_ext_key_usage) FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, ext_key_usage, oid_ext_key_usage)
FN_OID_GET_ATTR1(mbedtls_oid_get_extended_key_usage, mbedtls_oid_descriptor_t, ext_key_usage, const char *, description) FN_OID_GET_ATTR1(mbedtls_oid_get_extended_key_usage, mbedtls_oid_descriptor_t, ext_key_usage, const char *, description)
#endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */
static const mbedtls_oid_descriptor_t oid_certificate_policies[] =
{
{ ADD_LEN( MBEDTLS_OID_ANY_POLICY ), "anyPolicy", "Any Policy" },
{ NULL, 0, NULL, NULL },
};
FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, certificate_policies, oid_certificate_policies)
FN_OID_GET_ATTR1(mbedtls_oid_get_certificate_policies, mbedtls_oid_descriptor_t, certificate_policies, const char *, description)
#if defined(MBEDTLS_MD_C) #if defined(MBEDTLS_MD_C)
/* /*
@@ -311,55 +318,56 @@ typedef struct {
mbedtls_pk_type_t pk_alg; mbedtls_pk_type_t pk_alg;
} oid_sig_alg_t; } oid_sig_alg_t;
static const oid_sig_alg_t oid_sig_alg[] = { static const oid_sig_alg_t oid_sig_alg[] =
{
#if defined(MBEDTLS_RSA_C) #if defined(MBEDTLS_RSA_C)
#if defined(MBEDTLS_MD2_C) #if defined(MBEDTLS_MD2_C)
{ {
{ ADD_LEN(MBEDTLS_OID_PKCS1_MD2), "md2WithRSAEncryption", "RSA with MD2" }, { ADD_LEN( MBEDTLS_OID_PKCS1_MD2 ), "md2WithRSAEncryption", "RSA with MD2" },
MBEDTLS_MD_MD2, MBEDTLS_PK_RSA, MBEDTLS_MD_MD2, MBEDTLS_PK_RSA,
}, },
#endif /* MBEDTLS_MD2_C */ #endif /* MBEDTLS_MD2_C */
#if defined(MBEDTLS_MD4_C) #if defined(MBEDTLS_MD4_C)
{ {
{ ADD_LEN(MBEDTLS_OID_PKCS1_MD4), "md4WithRSAEncryption", "RSA with MD4" }, { ADD_LEN( MBEDTLS_OID_PKCS1_MD4 ), "md4WithRSAEncryption", "RSA with MD4" },
MBEDTLS_MD_MD4, MBEDTLS_PK_RSA, MBEDTLS_MD_MD4, MBEDTLS_PK_RSA,
}, },
#endif /* MBEDTLS_MD4_C */ #endif /* MBEDTLS_MD4_C */
#if defined(MBEDTLS_MD5_C) #if defined(MBEDTLS_MD5_C)
{ {
{ ADD_LEN(MBEDTLS_OID_PKCS1_MD5), "md5WithRSAEncryption", "RSA with MD5" }, { ADD_LEN( MBEDTLS_OID_PKCS1_MD5 ), "md5WithRSAEncryption", "RSA with MD5" },
MBEDTLS_MD_MD5, MBEDTLS_PK_RSA, MBEDTLS_MD_MD5, MBEDTLS_PK_RSA,
}, },
#endif /* MBEDTLS_MD5_C */ #endif /* MBEDTLS_MD5_C */
#if defined(MBEDTLS_SHA1_C) #if defined(MBEDTLS_SHA1_C)
{ {
{ ADD_LEN(MBEDTLS_OID_PKCS1_SHA1), "sha-1WithRSAEncryption", "RSA with SHA1" }, { ADD_LEN( MBEDTLS_OID_PKCS1_SHA1 ), "sha-1WithRSAEncryption", "RSA with SHA1" },
MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA,
}, },
#endif /* MBEDTLS_SHA1_C */ #endif /* MBEDTLS_SHA1_C */
#if defined(MBEDTLS_SHA256_C) #if defined(MBEDTLS_SHA256_C)
{ {
{ ADD_LEN(MBEDTLS_OID_PKCS1_SHA224), "sha224WithRSAEncryption", "RSA with SHA-224" }, { ADD_LEN( MBEDTLS_OID_PKCS1_SHA224 ), "sha224WithRSAEncryption", "RSA with SHA-224" },
MBEDTLS_MD_SHA224, MBEDTLS_PK_RSA, MBEDTLS_MD_SHA224, MBEDTLS_PK_RSA,
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_PKCS1_SHA256), "sha256WithRSAEncryption", "RSA with SHA-256" }, { ADD_LEN( MBEDTLS_OID_PKCS1_SHA256 ), "sha256WithRSAEncryption", "RSA with SHA-256" },
MBEDTLS_MD_SHA256, MBEDTLS_PK_RSA, MBEDTLS_MD_SHA256, MBEDTLS_PK_RSA,
}, },
#endif /* MBEDTLS_SHA256_C */ #endif /* MBEDTLS_SHA256_C */
#if defined(MBEDTLS_SHA512_C) #if defined(MBEDTLS_SHA512_C)
{ {
{ ADD_LEN(MBEDTLS_OID_PKCS1_SHA384), "sha384WithRSAEncryption", "RSA with SHA-384" }, { ADD_LEN( MBEDTLS_OID_PKCS1_SHA384 ), "sha384WithRSAEncryption", "RSA with SHA-384" },
MBEDTLS_MD_SHA384, MBEDTLS_PK_RSA, MBEDTLS_MD_SHA384, MBEDTLS_PK_RSA,
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_PKCS1_SHA512), "sha512WithRSAEncryption", "RSA with SHA-512" }, { ADD_LEN( MBEDTLS_OID_PKCS1_SHA512 ), "sha512WithRSAEncryption", "RSA with SHA-512" },
MBEDTLS_MD_SHA512, MBEDTLS_PK_RSA, MBEDTLS_MD_SHA512, MBEDTLS_PK_RSA,
}, },
#endif /* MBEDTLS_SHA512_C */ #endif /* MBEDTLS_SHA512_C */
#if defined(MBEDTLS_SHA1_C) #if defined(MBEDTLS_SHA1_C)
{ {
{ ADD_LEN(MBEDTLS_OID_RSA_SHA_OBS), "sha-1WithRSAEncryption", "RSA with SHA1" }, { ADD_LEN( MBEDTLS_OID_RSA_SHA_OBS ), "sha-1WithRSAEncryption", "RSA with SHA1" },
MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA,
}, },
#endif /* MBEDTLS_SHA1_C */ #endif /* MBEDTLS_SHA1_C */
@@ -367,34 +375,34 @@ static const oid_sig_alg_t oid_sig_alg[] = {
#if defined(MBEDTLS_ECDSA_C) #if defined(MBEDTLS_ECDSA_C)
#if defined(MBEDTLS_SHA1_C) #if defined(MBEDTLS_SHA1_C)
{ {
{ ADD_LEN(MBEDTLS_OID_ECDSA_SHA1), "ecdsa-with-SHA1", "ECDSA with SHA1" }, { ADD_LEN( MBEDTLS_OID_ECDSA_SHA1 ), "ecdsa-with-SHA1", "ECDSA with SHA1" },
MBEDTLS_MD_SHA1, MBEDTLS_PK_ECDSA, MBEDTLS_MD_SHA1, MBEDTLS_PK_ECDSA,
}, },
#endif /* MBEDTLS_SHA1_C */ #endif /* MBEDTLS_SHA1_C */
#if defined(MBEDTLS_SHA256_C) #if defined(MBEDTLS_SHA256_C)
{ {
{ ADD_LEN(MBEDTLS_OID_ECDSA_SHA224), "ecdsa-with-SHA224", "ECDSA with SHA224" }, { ADD_LEN( MBEDTLS_OID_ECDSA_SHA224 ), "ecdsa-with-SHA224", "ECDSA with SHA224" },
MBEDTLS_MD_SHA224, MBEDTLS_PK_ECDSA, MBEDTLS_MD_SHA224, MBEDTLS_PK_ECDSA,
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_ECDSA_SHA256), "ecdsa-with-SHA256", "ECDSA with SHA256" }, { ADD_LEN( MBEDTLS_OID_ECDSA_SHA256 ), "ecdsa-with-SHA256", "ECDSA with SHA256" },
MBEDTLS_MD_SHA256, MBEDTLS_PK_ECDSA, MBEDTLS_MD_SHA256, MBEDTLS_PK_ECDSA,
}, },
#endif /* MBEDTLS_SHA256_C */ #endif /* MBEDTLS_SHA256_C */
#if defined(MBEDTLS_SHA512_C) #if defined(MBEDTLS_SHA512_C)
{ {
{ ADD_LEN(MBEDTLS_OID_ECDSA_SHA384), "ecdsa-with-SHA384", "ECDSA with SHA384" }, { ADD_LEN( MBEDTLS_OID_ECDSA_SHA384 ), "ecdsa-with-SHA384", "ECDSA with SHA384" },
MBEDTLS_MD_SHA384, MBEDTLS_PK_ECDSA, MBEDTLS_MD_SHA384, MBEDTLS_PK_ECDSA,
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_ECDSA_SHA512), "ecdsa-with-SHA512", "ECDSA with SHA512" }, { ADD_LEN( MBEDTLS_OID_ECDSA_SHA512 ), "ecdsa-with-SHA512", "ECDSA with SHA512" },
MBEDTLS_MD_SHA512, MBEDTLS_PK_ECDSA, MBEDTLS_MD_SHA512, MBEDTLS_PK_ECDSA,
}, },
#endif /* MBEDTLS_SHA512_C */ #endif /* MBEDTLS_SHA512_C */
#endif /* MBEDTLS_ECDSA_C */ #endif /* MBEDTLS_ECDSA_C */
#if defined(MBEDTLS_RSA_C) #if defined(MBEDTLS_RSA_C)
{ {
{ ADD_LEN(MBEDTLS_OID_RSASSA_PSS), "RSASSA-PSS", "RSASSA-PSS" }, { ADD_LEN( MBEDTLS_OID_RSASSA_PSS ), "RSASSA-PSS", "RSASSA-PSS" },
MBEDTLS_MD_NONE, MBEDTLS_PK_RSASSA_PSS, MBEDTLS_MD_NONE, MBEDTLS_PK_RSASSA_PSS,
}, },
#endif /* MBEDTLS_RSA_C */ #endif /* MBEDTLS_RSA_C */
@@ -418,17 +426,18 @@ typedef struct {
mbedtls_pk_type_t pk_alg; mbedtls_pk_type_t pk_alg;
} oid_pk_alg_t; } oid_pk_alg_t;
static const oid_pk_alg_t oid_pk_alg[] = { static const oid_pk_alg_t oid_pk_alg[] =
{
{ {
{ ADD_LEN(MBEDTLS_OID_PKCS1_RSA), "rsaEncryption", "RSA" }, { ADD_LEN( MBEDTLS_OID_PKCS1_RSA ), "rsaEncryption", "RSA" },
MBEDTLS_PK_RSA, MBEDTLS_PK_RSA,
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_EC_ALG_UNRESTRICTED), "id-ecPublicKey", "Generic EC key" }, { ADD_LEN( MBEDTLS_OID_EC_ALG_UNRESTRICTED ), "id-ecPublicKey", "Generic EC key" },
MBEDTLS_PK_ECKEY, MBEDTLS_PK_ECKEY,
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_EC_ALG_ECDH), "id-ecDH", "EC key for ECDH" }, { ADD_LEN( MBEDTLS_OID_EC_ALG_ECDH ), "id-ecDH", "EC key for ECDH" },
MBEDTLS_PK_ECKEY_DH, MBEDTLS_PK_ECKEY_DH,
}, },
{ {
@@ -450,70 +459,71 @@ typedef struct {
mbedtls_ecp_group_id grp_id; mbedtls_ecp_group_id grp_id;
} oid_ecp_grp_t; } oid_ecp_grp_t;
static const oid_ecp_grp_t oid_ecp_grp[] = { static const oid_ecp_grp_t oid_ecp_grp[] =
{
#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
{ {
{ ADD_LEN(MBEDTLS_OID_EC_GRP_SECP192R1), "secp192r1", "secp192r1" }, { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP192R1 ), "secp192r1", "secp192r1" },
MBEDTLS_ECP_DP_SECP192R1, MBEDTLS_ECP_DP_SECP192R1,
}, },
#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */
#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
{ {
{ ADD_LEN(MBEDTLS_OID_EC_GRP_SECP224R1), "secp224r1", "secp224r1" }, { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP224R1 ), "secp224r1", "secp224r1" },
MBEDTLS_ECP_DP_SECP224R1, MBEDTLS_ECP_DP_SECP224R1,
}, },
#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ #endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */
#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
{ {
{ ADD_LEN(MBEDTLS_OID_EC_GRP_SECP256R1), "secp256r1", "secp256r1" }, { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP256R1 ), "secp256r1", "secp256r1" },
MBEDTLS_ECP_DP_SECP256R1, MBEDTLS_ECP_DP_SECP256R1,
}, },
#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */
#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
{ {
{ ADD_LEN(MBEDTLS_OID_EC_GRP_SECP384R1), "secp384r1", "secp384r1" }, { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP384R1 ), "secp384r1", "secp384r1" },
MBEDTLS_ECP_DP_SECP384R1, MBEDTLS_ECP_DP_SECP384R1,
}, },
#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ #endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */
#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
{ {
{ ADD_LEN(MBEDTLS_OID_EC_GRP_SECP521R1), "secp521r1", "secp521r1" }, { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP521R1 ), "secp521r1", "secp521r1" },
MBEDTLS_ECP_DP_SECP521R1, MBEDTLS_ECP_DP_SECP521R1,
}, },
#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ #endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */
#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
{ {
{ ADD_LEN(MBEDTLS_OID_EC_GRP_SECP192K1), "secp192k1", "secp192k1" }, { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP192K1 ), "secp192k1", "secp192k1" },
MBEDTLS_ECP_DP_SECP192K1, MBEDTLS_ECP_DP_SECP192K1,
}, },
#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */
#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
{ {
{ ADD_LEN(MBEDTLS_OID_EC_GRP_SECP224K1), "secp224k1", "secp224k1" }, { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP224K1 ), "secp224k1", "secp224k1" },
MBEDTLS_ECP_DP_SECP224K1, MBEDTLS_ECP_DP_SECP224K1,
}, },
#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ #endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */
#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
{ {
{ ADD_LEN(MBEDTLS_OID_EC_GRP_SECP256K1), "secp256k1", "secp256k1" }, { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP256K1 ), "secp256k1", "secp256k1" },
MBEDTLS_ECP_DP_SECP256K1, MBEDTLS_ECP_DP_SECP256K1,
}, },
#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */
#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) #if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
{ {
{ ADD_LEN(MBEDTLS_OID_EC_GRP_BP256R1), "brainpoolP256r1", "brainpool256r1" }, { ADD_LEN( MBEDTLS_OID_EC_GRP_BP256R1 ), "brainpoolP256r1","brainpool256r1" },
MBEDTLS_ECP_DP_BP256R1, MBEDTLS_ECP_DP_BP256R1,
}, },
#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ #endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */
#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) #if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
{ {
{ ADD_LEN(MBEDTLS_OID_EC_GRP_BP384R1), "brainpoolP384r1", "brainpool384r1" }, { ADD_LEN( MBEDTLS_OID_EC_GRP_BP384R1 ), "brainpoolP384r1","brainpool384r1" },
MBEDTLS_ECP_DP_BP384R1, MBEDTLS_ECP_DP_BP384R1,
}, },
#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ #endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */
#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) #if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
{ {
{ ADD_LEN(MBEDTLS_OID_EC_GRP_BP512R1), "brainpoolP512r1", "brainpool512r1" }, { ADD_LEN( MBEDTLS_OID_EC_GRP_BP512R1 ), "brainpoolP512r1","brainpool512r1" },
MBEDTLS_ECP_DP_BP512R1, MBEDTLS_ECP_DP_BP512R1,
}, },
#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ #endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */
@@ -537,13 +547,14 @@ typedef struct {
mbedtls_cipher_type_t cipher_alg; mbedtls_cipher_type_t cipher_alg;
} oid_cipher_alg_t; } oid_cipher_alg_t;
static const oid_cipher_alg_t oid_cipher_alg[] = { static const oid_cipher_alg_t oid_cipher_alg[] =
{
{ {
{ ADD_LEN(MBEDTLS_OID_DES_CBC), "desCBC", "DES-CBC" }, { ADD_LEN( MBEDTLS_OID_DES_CBC ), "desCBC", "DES-CBC" },
MBEDTLS_CIPHER_DES_CBC, MBEDTLS_CIPHER_DES_CBC,
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_DES_EDE3_CBC), "des-ede3-cbc", "DES-EDE3-CBC" }, { ADD_LEN( MBEDTLS_OID_DES_EDE3_CBC ), "des-ede3-cbc", "DES-EDE3-CBC" },
MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_CIPHER_DES_EDE3_CBC,
}, },
{ {
@@ -565,51 +576,58 @@ typedef struct {
mbedtls_md_type_t md_alg; mbedtls_md_type_t md_alg;
} oid_md_alg_t; } oid_md_alg_t;
static const oid_md_alg_t oid_md_alg[] = { static const oid_md_alg_t oid_md_alg[] =
{
#if defined(MBEDTLS_MD2_C) #if defined(MBEDTLS_MD2_C)
{ {
{ ADD_LEN(MBEDTLS_OID_DIGEST_ALG_MD2), "id-md2", "MD2" }, { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD2 ), "id-md2", "MD2" },
MBEDTLS_MD_MD2, MBEDTLS_MD_MD2,
}, },
#endif /* MBEDTLS_MD2_C */ #endif /* MBEDTLS_MD2_C */
#if defined(MBEDTLS_MD4_C) #if defined(MBEDTLS_MD4_C)
{ {
{ ADD_LEN(MBEDTLS_OID_DIGEST_ALG_MD4), "id-md4", "MD4" }, { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD4 ), "id-md4", "MD4" },
MBEDTLS_MD_MD4, MBEDTLS_MD_MD4,
}, },
#endif /* MBEDTLS_MD4_C */ #endif /* MBEDTLS_MD4_C */
#if defined(MBEDTLS_MD5_C) #if defined(MBEDTLS_MD5_C)
{ {
{ ADD_LEN(MBEDTLS_OID_DIGEST_ALG_MD5), "id-md5", "MD5" }, { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD5 ), "id-md5", "MD5" },
MBEDTLS_MD_MD5, MBEDTLS_MD_MD5,
}, },
#endif /* MBEDTLS_MD5_C */ #endif /* MBEDTLS_MD5_C */
#if defined(MBEDTLS_SHA1_C) #if defined(MBEDTLS_SHA1_C)
{ {
{ ADD_LEN(MBEDTLS_OID_DIGEST_ALG_SHA1), "id-sha1", "SHA-1" }, { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA1 ), "id-sha1", "SHA-1" },
MBEDTLS_MD_SHA1, MBEDTLS_MD_SHA1,
}, },
#endif /* MBEDTLS_SHA1_C */ #endif /* MBEDTLS_SHA1_C */
#if defined(MBEDTLS_SHA256_C) #if defined(MBEDTLS_SHA256_C)
{ {
{ ADD_LEN(MBEDTLS_OID_DIGEST_ALG_SHA224), "id-sha224", "SHA-224" }, { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA224 ), "id-sha224", "SHA-224" },
MBEDTLS_MD_SHA224, MBEDTLS_MD_SHA224,
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_DIGEST_ALG_SHA256), "id-sha256", "SHA-256" }, { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA256 ), "id-sha256", "SHA-256" },
MBEDTLS_MD_SHA256, MBEDTLS_MD_SHA256,
}, },
#endif /* MBEDTLS_SHA256_C */ #endif /* MBEDTLS_SHA256_C */
#if defined(MBEDTLS_SHA512_C) #if defined(MBEDTLS_SHA512_C)
{ {
{ ADD_LEN(MBEDTLS_OID_DIGEST_ALG_SHA384), "id-sha384", "SHA-384" }, { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA384 ), "id-sha384", "SHA-384" },
MBEDTLS_MD_SHA384, MBEDTLS_MD_SHA384,
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_DIGEST_ALG_SHA512), "id-sha512", "SHA-512" }, { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA512 ), "id-sha512", "SHA-512" },
MBEDTLS_MD_SHA512, MBEDTLS_MD_SHA512,
}, },
#endif /* MBEDTLS_SHA512_C */ #endif /* MBEDTLS_SHA512_C */
#if defined(MBEDTLS_RIPEMD160_C)
{
{ ADD_LEN( MBEDTLS_OID_DIGEST_ALG_RIPEMD160 ), "id-ripemd160", "RIPEMD-160" },
MBEDTLS_MD_RIPEMD160,
},
#endif /* MBEDTLS_RIPEMD160_C */
{ {
{ NULL, 0, NULL, NULL }, { NULL, 0, NULL, NULL },
MBEDTLS_MD_NONE, MBEDTLS_MD_NONE,
@@ -628,30 +646,31 @@ typedef struct {
mbedtls_md_type_t md_hmac; mbedtls_md_type_t md_hmac;
} oid_md_hmac_t; } oid_md_hmac_t;
static const oid_md_hmac_t oid_md_hmac[] = { static const oid_md_hmac_t oid_md_hmac[] =
{
#if defined(MBEDTLS_SHA1_C) #if defined(MBEDTLS_SHA1_C)
{ {
{ ADD_LEN(MBEDTLS_OID_HMAC_SHA1), "hmacSHA1", "HMAC-SHA-1" }, { ADD_LEN( MBEDTLS_OID_HMAC_SHA1 ), "hmacSHA1", "HMAC-SHA-1" },
MBEDTLS_MD_SHA1, MBEDTLS_MD_SHA1,
}, },
#endif /* MBEDTLS_SHA1_C */ #endif /* MBEDTLS_SHA1_C */
#if defined(MBEDTLS_SHA256_C) #if defined(MBEDTLS_SHA256_C)
{ {
{ ADD_LEN(MBEDTLS_OID_HMAC_SHA224), "hmacSHA224", "HMAC-SHA-224" }, { ADD_LEN( MBEDTLS_OID_HMAC_SHA224 ), "hmacSHA224", "HMAC-SHA-224" },
MBEDTLS_MD_SHA224, MBEDTLS_MD_SHA224,
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_HMAC_SHA256), "hmacSHA256", "HMAC-SHA-256" }, { ADD_LEN( MBEDTLS_OID_HMAC_SHA256 ), "hmacSHA256", "HMAC-SHA-256" },
MBEDTLS_MD_SHA256, MBEDTLS_MD_SHA256,
}, },
#endif /* MBEDTLS_SHA256_C */ #endif /* MBEDTLS_SHA256_C */
#if defined(MBEDTLS_SHA512_C) #if defined(MBEDTLS_SHA512_C)
{ {
{ ADD_LEN(MBEDTLS_OID_HMAC_SHA384), "hmacSHA384", "HMAC-SHA-384" }, { ADD_LEN( MBEDTLS_OID_HMAC_SHA384 ), "hmacSHA384", "HMAC-SHA-384" },
MBEDTLS_MD_SHA384, MBEDTLS_MD_SHA384,
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_HMAC_SHA512), "hmacSHA512", "HMAC-SHA-512" }, { ADD_LEN( MBEDTLS_OID_HMAC_SHA512 ), "hmacSHA512", "HMAC-SHA-512" },
MBEDTLS_MD_SHA512, MBEDTLS_MD_SHA512,
}, },
#endif /* MBEDTLS_SHA512_C */ #endif /* MBEDTLS_SHA512_C */
@@ -675,13 +694,14 @@ typedef struct {
mbedtls_cipher_type_t cipher_alg; mbedtls_cipher_type_t cipher_alg;
} oid_pkcs12_pbe_alg_t; } oid_pkcs12_pbe_alg_t;
static const oid_pkcs12_pbe_alg_t oid_pkcs12_pbe_alg[] = { static const oid_pkcs12_pbe_alg_t oid_pkcs12_pbe_alg[] =
{
{ {
{ ADD_LEN(MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC), "pbeWithSHAAnd3-KeyTripleDES-CBC", "PBE with SHA1 and 3-Key 3DES" }, { ADD_LEN( MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC ), "pbeWithSHAAnd3-KeyTripleDES-CBC", "PBE with SHA1 and 3-Key 3DES" },
MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE3_CBC, MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE3_CBC,
}, },
{ {
{ ADD_LEN(MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC), "pbeWithSHAAnd2-KeyTripleDES-CBC", "PBE with SHA1 and 2-Key 3DES" }, { ADD_LEN( MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC ), "pbeWithSHAAnd2-KeyTripleDES-CBC", "PBE with SHA1 and 2-Key 3DES" },
MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE_CBC, MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE_CBC,
}, },
{ {
@@ -698,15 +718,16 @@ FN_OID_GET_ATTR2(mbedtls_oid_get_pkcs12_pbe_alg, oid_pkcs12_pbe_alg_t, pkcs12_pb
do { \ do { \
if( ret < 0 || (size_t) ret >= n ) \ if( ret < 0 || (size_t) ret >= n ) \
return( MBEDTLS_ERR_OID_BUF_TOO_SMALL ); \ return( MBEDTLS_ERR_OID_BUF_TOO_SMALL ); \
\ \
n -= (size_t) ret; \ n -= (size_t) ret; \
p += (size_t) ret; \ p += (size_t) ret; \
} while( 0 ) } while( 0 )
/* Return the x.y.z.... style numeric string for the given OID */ /* Return the x.y.z.... style numeric string for the given OID */
int mbedtls_oid_get_numeric_string(char *buf, size_t size, int mbedtls_oid_get_numeric_string( char *buf, size_t size,
const mbedtls_asn1_buf *oid) { const mbedtls_asn1_buf *oid )
int ret; {
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t i, n; size_t i, n;
unsigned int value; unsigned int value;
char *p; char *p;
@@ -715,29 +736,32 @@ int mbedtls_oid_get_numeric_string(char *buf, size_t size,
n = size; n = size;
/* First byte contains first two dots */ /* First byte contains first two dots */
if (oid->len > 0) { if( oid->len > 0 )
ret = mbedtls_snprintf(p, n, "%d.%d", oid->p[0] / 40, oid->p[0] % 40); {
ret = mbedtls_snprintf( p, n, "%d.%d", oid->p[0] / 40, oid->p[0] % 40 );
OID_SAFE_SNPRINTF; OID_SAFE_SNPRINTF;
} }
value = 0; value = 0;
for (i = 1; i < oid->len; i++) { for( i = 1; i < oid->len; i++ )
{
/* Prevent overflow in value. */ /* Prevent overflow in value. */
if (((value << 7) >> 7) != value) if( ( ( value << 7 ) >> 7 ) != value )
return (MBEDTLS_ERR_OID_BUF_TOO_SMALL); return( MBEDTLS_ERR_OID_BUF_TOO_SMALL );
value <<= 7; value <<= 7;
value += oid->p[i] & 0x7F; value += oid->p[i] & 0x7F;
if (!(oid->p[i] & 0x80)) { if( !( oid->p[i] & 0x80 ) )
{
/* Last byte */ /* Last byte */
ret = mbedtls_snprintf(p, n, ".%d", value); ret = mbedtls_snprintf( p, n, ".%u", value );
OID_SAFE_SNPRINTF; OID_SAFE_SNPRINTF;
value = 0; value = 0;
} }
} }
return ((int)(size - n)); return( (int) ( size - n ) );
} }
#endif /* MBEDTLS_OID_C */ #endif /* MBEDTLS_OID_C */

View File

@@ -4,54 +4,68 @@
* \brief Object Identifier (OID) database * \brief Object Identifier (OID) database
*/ */
/* /*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
#ifndef MBEDTLS_OID_H #ifndef MBEDTLS_OID_H
#define MBEDTLS_OID_H #define MBEDTLS_OID_H
#if !defined(MBEDTLS_CONFIG_FILE) #if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h" #include "mbedtls/config.h"
#else #else
#include MBEDTLS_CONFIG_FILE #include MBEDTLS_CONFIG_FILE
#endif #endif
#include "asn1.h" #include "mbedtls/asn1.h"
#include "pk.h" #include "mbedtls/pk.h"
#include <stddef.h> #include <stddef.h>
#if defined(MBEDTLS_CIPHER_C) #if defined(MBEDTLS_CIPHER_C)
#include "cipher.h" #include "mbedtls/cipher.h"
#endif #endif
#if defined(MBEDTLS_MD_C) #if defined(MBEDTLS_MD_C)
#include "md.h" #include "mbedtls/md.h"
#endif
#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
#include "x509.h"
#endif #endif
#define MBEDTLS_ERR_OID_NOT_FOUND -0x002E /**< OID is not found. */ #define MBEDTLS_ERR_OID_NOT_FOUND -0x002E /**< OID is not found. */
#define MBEDTLS_ERR_OID_BUF_TOO_SMALL -0x000B /**< output buffer is too small */ #define MBEDTLS_ERR_OID_BUF_TOO_SMALL -0x000B /**< output buffer is too small */
/* This is for the benefit of X.509, but defined here in order to avoid
* having a "backwards" include of x.509.h here */
/*
* X.509 extension types (internal, arbitrary values for bitsets)
*/
#define MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER (1 << 0)
#define MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER (1 << 1)
#define MBEDTLS_OID_X509_EXT_KEY_USAGE (1 << 2)
#define MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES (1 << 3)
#define MBEDTLS_OID_X509_EXT_POLICY_MAPPINGS (1 << 4)
#define MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME (1 << 5)
#define MBEDTLS_OID_X509_EXT_ISSUER_ALT_NAME (1 << 6)
#define MBEDTLS_OID_X509_EXT_SUBJECT_DIRECTORY_ATTRS (1 << 7)
#define MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS (1 << 8)
#define MBEDTLS_OID_X509_EXT_NAME_CONSTRAINTS (1 << 9)
#define MBEDTLS_OID_X509_EXT_POLICY_CONSTRAINTS (1 << 10)
#define MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE (1 << 11)
#define MBEDTLS_OID_X509_EXT_CRL_DISTRIBUTION_POINTS (1 << 12)
#define MBEDTLS_OID_X509_EXT_INIHIBIT_ANYPOLICY (1 << 13)
#define MBEDTLS_OID_X509_EXT_FRESHEST_CRL (1 << 14)
#define MBEDTLS_OID_X509_EXT_NS_CERT_TYPE (1 << 16)
/* /*
* Top level OID tuples * Top level OID tuples
*/ */
@@ -66,10 +80,10 @@
#define MBEDTLS_OID_COUNTRY_US "\x86\x48" /* {us(840)} */ #define MBEDTLS_OID_COUNTRY_US "\x86\x48" /* {us(840)} */
#define MBEDTLS_OID_ORG_RSA_DATA_SECURITY "\x86\xf7\x0d" /* {rsadsi(113549)} */ #define MBEDTLS_OID_ORG_RSA_DATA_SECURITY "\x86\xf7\x0d" /* {rsadsi(113549)} */
#define MBEDTLS_OID_RSA_COMPANY MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ #define MBEDTLS_OID_RSA_COMPANY MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \
MBEDTLS_OID_ORG_RSA_DATA_SECURITY /* {iso(1) member-body(2) us(840) rsadsi(113549)} */ MBEDTLS_OID_ORG_RSA_DATA_SECURITY /* {iso(1) member-body(2) us(840) rsadsi(113549)} */
#define MBEDTLS_OID_ORG_ANSI_X9_62 "\xce\x3d" /* ansi-X9-62(10045) */ #define MBEDTLS_OID_ORG_ANSI_X9_62 "\xce\x3d" /* ansi-X9-62(10045) */
#define MBEDTLS_OID_ANSI_X9_62 MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ #define MBEDTLS_OID_ANSI_X9_62 MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \
MBEDTLS_OID_ORG_ANSI_X9_62 MBEDTLS_OID_ORG_ANSI_X9_62
/* /*
* ISO Identified organization OID parts * ISO Identified organization OID parts
@@ -106,7 +120,8 @@
* { iso(1) identified-organization(3) dod(6) internet(1) * { iso(1) identified-organization(3) dod(6) internet(1)
* security(5) mechanisms(5) pkix(7) } * security(5) mechanisms(5) pkix(7) }
*/ */
#define MBEDTLS_OID_PKIX MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_DOD "\x01\x05\x05\x07" #define MBEDTLS_OID_INTERNET MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_DOD "\x01"
#define MBEDTLS_OID_PKIX MBEDTLS_OID_INTERNET "\x05\x05\x07"
/* /*
* Arc for standard naming attributes * Arc for standard naming attributes
@@ -151,6 +166,11 @@
#define MBEDTLS_OID_INIHIBIT_ANYPOLICY MBEDTLS_OID_ID_CE "\x36" /**< id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 } */ #define MBEDTLS_OID_INIHIBIT_ANYPOLICY MBEDTLS_OID_ID_CE "\x36" /**< id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 } */
#define MBEDTLS_OID_FRESHEST_CRL MBEDTLS_OID_ID_CE "\x2E" /**< id-ce-freshestCRL OBJECT IDENTIFIER ::= { id-ce 46 } */ #define MBEDTLS_OID_FRESHEST_CRL MBEDTLS_OID_ID_CE "\x2E" /**< id-ce-freshestCRL OBJECT IDENTIFIER ::= { id-ce 46 } */
/*
* Certificate policies
*/
#define MBEDTLS_OID_ANY_POLICY MBEDTLS_OID_CERTIFICATE_POLICIES "\x00" /**< anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificatePolicies 0 } */
/* /*
* Netscape certificate extensions * Netscape certificate extensions
*/ */
@@ -185,6 +205,16 @@
#define MBEDTLS_OID_TIME_STAMPING MBEDTLS_OID_KP "\x08" /**< id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } */ #define MBEDTLS_OID_TIME_STAMPING MBEDTLS_OID_KP "\x08" /**< id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } */
#define MBEDTLS_OID_OCSP_SIGNING MBEDTLS_OID_KP "\x09" /**< id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } */ #define MBEDTLS_OID_OCSP_SIGNING MBEDTLS_OID_KP "\x09" /**< id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } */
/**
* Wi-SUN Alliance Field Area Network
* { iso(1) identified-organization(3) dod(6) internet(1)
* private(4) enterprise(1) WiSUN(45605) FieldAreaNetwork(1) }
*/
#define MBEDTLS_OID_WISUN_FAN MBEDTLS_OID_INTERNET "\x04\x01\x82\xe4\x25\x01"
#define MBEDTLS_OID_ON MBEDTLS_OID_PKIX "\x08" /**< id-on OBJECT IDENTIFIER ::= { id-pkix 8 } */
#define MBEDTLS_OID_ON_HW_MODULE_NAME MBEDTLS_OID_ON "\x04" /**< id-on-hardwareModuleName OBJECT IDENTIFIER ::= { id-on 4 } */
/* /*
* PKCS definition OIDs * PKCS definition OIDs
*/ */
@@ -230,6 +260,8 @@
#define MBEDTLS_OID_DIGEST_ALG_SHA512 MBEDTLS_OID_NIST_ALG "\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */ #define MBEDTLS_OID_DIGEST_ALG_SHA512 MBEDTLS_OID_NIST_ALG "\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */
#define MBEDTLS_OID_DIGEST_ALG_RIPEMD160 MBEDTLS_OID_TELETRUST "\x03\x02\x01" /**< id-ripemd160 OBJECT IDENTIFIER :: { iso(1) identified-organization(3) teletrust(36) algorithm(3) hashAlgorithm(2) ripemd160(1) } */
#define MBEDTLS_OID_HMAC_SHA1 MBEDTLS_OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */ #define MBEDTLS_OID_HMAC_SHA1 MBEDTLS_OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */
#define MBEDTLS_OID_HMAC_SHA224 MBEDTLS_OID_RSA_COMPANY "\x02\x08" /**< id-hmacWithSHA224 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 8 } */ #define MBEDTLS_OID_HMAC_SHA224 MBEDTLS_OID_RSA_COMPANY "\x02\x08" /**< id-hmacWithSHA224 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 8 } */
@@ -405,7 +437,8 @@ extern "C" {
/** /**
* \brief Base OID descriptor structure * \brief Base OID descriptor structure
*/ */
typedef struct mbedtls_oid_descriptor_t { typedef struct mbedtls_oid_descriptor_t
{
const char *asn1; /*!< OID ASN.1 representation */ const char *asn1; /*!< OID ASN.1 representation */
size_t asn1_len; /*!< length of asn1 */ size_t asn1_len; /*!< length of asn1 */
const char *name; /*!< official name (e.g. from RFC) */ const char *name; /*!< official name (e.g. from RFC) */
@@ -423,9 +456,8 @@ typedef struct mbedtls_oid_descriptor_t {
* \return Length of the string written (excluding final NULL) or * \return Length of the string written (excluding final NULL) or
* MBEDTLS_ERR_OID_BUF_TOO_SMALL in case of error * MBEDTLS_ERR_OID_BUF_TOO_SMALL in case of error
*/ */
int mbedtls_oid_get_numeric_string(char *buf, size_t size, const mbedtls_asn1_buf *oid); int mbedtls_oid_get_numeric_string( char *buf, size_t size, const mbedtls_asn1_buf *oid );
#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)
/** /**
* \brief Translate an X.509 extension OID into local values * \brief Translate an X.509 extension OID into local values
* *
@@ -434,8 +466,7 @@ int mbedtls_oid_get_numeric_string(char *buf, size_t size, const mbedtls_asn1_bu
* *
* \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND
*/ */
int mbedtls_oid_get_x509_ext_type(const mbedtls_asn1_buf *oid, int *ext_type); int mbedtls_oid_get_x509_ext_type( const mbedtls_asn1_buf *oid, int *ext_type );
#endif
/** /**
* \brief Translate an X.509 attribute type OID into the short name * \brief Translate an X.509 attribute type OID into the short name
@@ -446,7 +477,7 @@ int mbedtls_oid_get_x509_ext_type(const mbedtls_asn1_buf *oid, int *ext_type);
* *
* \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND
*/ */
int mbedtls_oid_get_attr_short_name(const mbedtls_asn1_buf *oid, const char **short_name); int mbedtls_oid_get_attr_short_name( const mbedtls_asn1_buf *oid, const char **short_name );
/** /**
* \brief Translate PublicKeyAlgorithm OID into pk_type * \brief Translate PublicKeyAlgorithm OID into pk_type
@@ -456,7 +487,7 @@ int mbedtls_oid_get_attr_short_name(const mbedtls_asn1_buf *oid, const char **sh
* *
* \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND
*/ */
int mbedtls_oid_get_pk_alg(const mbedtls_asn1_buf *oid, mbedtls_pk_type_t *pk_alg); int mbedtls_oid_get_pk_alg( const mbedtls_asn1_buf *oid, mbedtls_pk_type_t *pk_alg );
/** /**
* \brief Translate pk_type into PublicKeyAlgorithm OID * \brief Translate pk_type into PublicKeyAlgorithm OID
@@ -467,8 +498,8 @@ int mbedtls_oid_get_pk_alg(const mbedtls_asn1_buf *oid, mbedtls_pk_type_t *pk_al
* *
* \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND
*/ */
int mbedtls_oid_get_oid_by_pk_alg(mbedtls_pk_type_t pk_alg, int mbedtls_oid_get_oid_by_pk_alg( mbedtls_pk_type_t pk_alg,
const char **oid, size_t *olen); const char **oid, size_t *olen );
#if defined(MBEDTLS_ECP_C) #if defined(MBEDTLS_ECP_C)
/** /**
@@ -479,7 +510,7 @@ int mbedtls_oid_get_oid_by_pk_alg(mbedtls_pk_type_t pk_alg,
* *
* \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND
*/ */
int mbedtls_oid_get_ec_grp(const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *grp_id); int mbedtls_oid_get_ec_grp( const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *grp_id );
/** /**
* \brief Translate EC group identifier into NamedCurve OID * \brief Translate EC group identifier into NamedCurve OID
@@ -490,8 +521,8 @@ int mbedtls_oid_get_ec_grp(const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *gr
* *
* \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND
*/ */
int mbedtls_oid_get_oid_by_ec_grp(mbedtls_ecp_group_id grp_id, int mbedtls_oid_get_oid_by_ec_grp( mbedtls_ecp_group_id grp_id,
const char **oid, size_t *olen); const char **oid, size_t *olen );
#endif /* MBEDTLS_ECP_C */ #endif /* MBEDTLS_ECP_C */
#if defined(MBEDTLS_MD_C) #if defined(MBEDTLS_MD_C)
@@ -504,8 +535,8 @@ int mbedtls_oid_get_oid_by_ec_grp(mbedtls_ecp_group_id grp_id,
* *
* \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND
*/ */
int mbedtls_oid_get_sig_alg(const mbedtls_asn1_buf *oid, int mbedtls_oid_get_sig_alg( const mbedtls_asn1_buf *oid,
mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg); mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg );
/** /**
* \brief Translate SignatureAlgorithm OID into description * \brief Translate SignatureAlgorithm OID into description
@@ -515,7 +546,7 @@ int mbedtls_oid_get_sig_alg(const mbedtls_asn1_buf *oid,
* *
* \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND
*/ */
int mbedtls_oid_get_sig_alg_desc(const mbedtls_asn1_buf *oid, const char **desc); int mbedtls_oid_get_sig_alg_desc( const mbedtls_asn1_buf *oid, const char **desc );
/** /**
* \brief Translate md_type and pk_type into SignatureAlgorithm OID * \brief Translate md_type and pk_type into SignatureAlgorithm OID
@@ -527,8 +558,8 @@ int mbedtls_oid_get_sig_alg_desc(const mbedtls_asn1_buf *oid, const char **desc)
* *
* \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND
*/ */
int mbedtls_oid_get_oid_by_sig_alg(mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, int mbedtls_oid_get_oid_by_sig_alg( mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg,
const char **oid, size_t *olen); const char **oid, size_t *olen );
/** /**
* \brief Translate hash algorithm OID into md_type * \brief Translate hash algorithm OID into md_type
@@ -538,7 +569,7 @@ int mbedtls_oid_get_oid_by_sig_alg(mbedtls_pk_type_t pk_alg, mbedtls_md_type_t m
* *
* \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND
*/ */
int mbedtls_oid_get_md_alg(const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg); int mbedtls_oid_get_md_alg( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg );
/** /**
* \brief Translate hmac algorithm OID into md_type * \brief Translate hmac algorithm OID into md_type
@@ -548,7 +579,7 @@ int mbedtls_oid_get_md_alg(const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_al
* *
* \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND
*/ */
int mbedtls_oid_get_md_hmac(const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_hmac); int mbedtls_oid_get_md_hmac( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_hmac );
#endif /* MBEDTLS_MD_C */ #endif /* MBEDTLS_MD_C */
/** /**
@@ -559,7 +590,17 @@ int mbedtls_oid_get_md_hmac(const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_h
* *
* \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND
*/ */
int mbedtls_oid_get_extended_key_usage(const mbedtls_asn1_buf *oid, const char **desc); int mbedtls_oid_get_extended_key_usage( const mbedtls_asn1_buf *oid, const char **desc );
/**
* \brief Translate certificate policies OID into description
*
* \param oid OID to use
* \param desc place to store string pointer
*
* \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND
*/
int mbedtls_oid_get_certificate_policies( const mbedtls_asn1_buf *oid, const char **desc );
/** /**
* \brief Translate md_type into hash algorithm OID * \brief Translate md_type into hash algorithm OID
@@ -570,7 +611,7 @@ int mbedtls_oid_get_extended_key_usage(const mbedtls_asn1_buf *oid, const char *
* *
* \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND
*/ */
int mbedtls_oid_get_oid_by_md(mbedtls_md_type_t md_alg, const char **oid, size_t *olen); int mbedtls_oid_get_oid_by_md( mbedtls_md_type_t md_alg, const char **oid, size_t *olen );
#if defined(MBEDTLS_CIPHER_C) #if defined(MBEDTLS_CIPHER_C)
/** /**
@@ -581,7 +622,7 @@ int mbedtls_oid_get_oid_by_md(mbedtls_md_type_t md_alg, const char **oid, size_t
* *
* \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND
*/ */
int mbedtls_oid_get_cipher_alg(const mbedtls_asn1_buf *oid, mbedtls_cipher_type_t *cipher_alg); int mbedtls_oid_get_cipher_alg( const mbedtls_asn1_buf *oid, mbedtls_cipher_type_t *cipher_alg );
#endif /* MBEDTLS_CIPHER_C */ #endif /* MBEDTLS_CIPHER_C */
#if defined(MBEDTLS_PKCS12_C) #if defined(MBEDTLS_PKCS12_C)
@@ -595,8 +636,8 @@ int mbedtls_oid_get_cipher_alg(const mbedtls_asn1_buf *oid, mbedtls_cipher_type_
* *
* \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND
*/ */
int mbedtls_oid_get_pkcs12_pbe_alg(const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg, int mbedtls_oid_get_pkcs12_pbe_alg( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg,
mbedtls_cipher_type_t *cipher_alg); mbedtls_cipher_type_t *cipher_alg );
#endif /* MBEDTLS_PKCS12_C */ #endif /* MBEDTLS_PKCS12_C */
#ifdef __cplusplus #ifdef __cplusplus

164
common/mbedtls/padlock.c Normal file
View File

@@ -0,0 +1,164 @@
/*
* VIA PadLock support functions
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* 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 "mbedtls/padlock.h"
#include <string.h>
#ifndef asm
#define asm __asm
#endif
#if defined(MBEDTLS_HAVE_X86)
/*
* 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->rk;
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 );
}
/*
* 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];
if( ( (long) input & 15 ) != 0 ||
( (long) output & 15 ) != 0 )
return( MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED );
rk = ctx->rk;
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_HAVE_X86 */
#endif /* MBEDTLS_PADLOCK_C */

124
common/mbedtls/padlock.h Normal file
View File

@@ -0,0 +1,124 @@
/**
* \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
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBEDTLS_PADLOCK_H
#define MBEDTLS_PADLOCK_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#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
/* Some versions of ASan result in errors about not enough registers */
#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && defined(__i386__) && \
!defined(MBEDTLS_HAVE_ASAN)
#ifndef MBEDTLS_HAVE_X86
#define MBEDTLS_HAVE_X86
#endif
#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 1 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 */

View File

@@ -1,31 +1,23 @@
/* /*
* Privacy Enhanced Mail (PEM) decoding * Privacy Enhanced Mail (PEM) decoding
* *
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
#if !defined(MBEDTLS_CONFIG_FILE) #include "common.h"
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) #if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C)
@@ -36,6 +28,7 @@
#include "mbedtls/md5.h" #include "mbedtls/md5.h"
#include "mbedtls/cipher.h" #include "mbedtls/cipher.h"
#include "mbedtls/platform_util.h" #include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#include <string.h> #include <string.h>
@@ -48,8 +41,9 @@
#endif #endif
#if defined(MBEDTLS_PEM_PARSE_C) #if defined(MBEDTLS_PEM_PARSE_C)
void mbedtls_pem_init(mbedtls_pem_context *ctx) { void mbedtls_pem_init( mbedtls_pem_context *ctx )
memset(ctx, 0, sizeof(mbedtls_pem_context)); {
memset( ctx, 0, sizeof( mbedtls_pem_context ) );
} }
#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ #if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \
@@ -57,136 +51,141 @@ void mbedtls_pem_init(mbedtls_pem_context *ctx) {
/* /*
* Read a 16-byte hex string and convert it to binary * Read a 16-byte hex string and convert it to binary
*/ */
static int pem_get_iv(const unsigned char *s, unsigned char *iv, static int pem_get_iv( const unsigned char *s, unsigned char *iv,
size_t iv_len) { size_t iv_len )
{
size_t i, j, k; size_t i, j, k;
memset(iv, 0, iv_len); memset( iv, 0, iv_len );
for (i = 0; i < iv_len * 2; i++, s++) { 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'; if( *s >= '0' && *s <= '9' ) j = *s - '0'; else
else if (*s >= 'a' && *s <= 'f') j = *s - 'W'; if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else
else if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else
return (MBEDTLS_ERR_PEM_INVALID_ENC_IV); return( MBEDTLS_ERR_PEM_INVALID_ENC_IV );
k = ((i & 1) != 0) ? j : j << 4; k = ( ( i & 1 ) != 0 ) ? j : j << 4;
iv[i >> 1] = (unsigned char)(iv[i >> 1] | k); iv[i >> 1] = (unsigned char)( iv[i >> 1] | k );
} }
return (0); return( 0 );
} }
static int pem_pbkdf1(unsigned char *key, size_t keylen, static int pem_pbkdf1( unsigned char *key, size_t keylen,
unsigned char *iv, unsigned char *iv,
const unsigned char *pwd, size_t pwdlen) { const unsigned char *pwd, size_t pwdlen )
{
mbedtls_md5_context md5_ctx; mbedtls_md5_context md5_ctx;
unsigned char md5sum[16]; unsigned char md5sum[16];
size_t use_len; size_t use_len;
int ret; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_md5_init(&md5_ctx); mbedtls_md5_init( &md5_ctx );
/* /*
* key[ 0..15] = MD5(pwd || IV) * key[ 0..15] = MD5(pwd || IV)
*/ */
if ((ret = mbedtls_md5_starts_ret(&md5_ctx)) != 0) if( ( ret = mbedtls_md5_starts_ret( &md5_ctx ) ) != 0 )
goto exit; goto exit;
if ((ret = mbedtls_md5_update_ret(&md5_ctx, pwd, pwdlen)) != 0) if( ( ret = mbedtls_md5_update_ret( &md5_ctx, pwd, pwdlen ) ) != 0 )
goto exit; goto exit;
if ((ret = mbedtls_md5_update_ret(&md5_ctx, iv, 8)) != 0) if( ( ret = mbedtls_md5_update_ret( &md5_ctx, iv, 8 ) ) != 0 )
goto exit; goto exit;
if ((ret = mbedtls_md5_finish_ret(&md5_ctx, md5sum)) != 0) if( ( ret = mbedtls_md5_finish_ret( &md5_ctx, md5sum ) ) != 0 )
goto exit; goto exit;
if (keylen <= 16) { if( keylen <= 16 )
memcpy(key, md5sum, keylen); {
memcpy( key, md5sum, keylen );
goto exit; goto exit;
} }
memcpy(key, md5sum, 16); memcpy( key, md5sum, 16 );
/* /*
* key[16..23] = MD5(key[ 0..15] || pwd || IV]) * key[16..23] = MD5(key[ 0..15] || pwd || IV])
*/ */
if ((ret = mbedtls_md5_starts_ret(&md5_ctx)) != 0) if( ( ret = mbedtls_md5_starts_ret( &md5_ctx ) ) != 0 )
goto exit; goto exit;
if ((ret = mbedtls_md5_update_ret(&md5_ctx, md5sum, 16)) != 0) if( ( ret = mbedtls_md5_update_ret( &md5_ctx, md5sum, 16 ) ) != 0 )
goto exit; goto exit;
if ((ret = mbedtls_md5_update_ret(&md5_ctx, pwd, pwdlen)) != 0) if( ( ret = mbedtls_md5_update_ret( &md5_ctx, pwd, pwdlen ) ) != 0 )
goto exit; goto exit;
if ((ret = mbedtls_md5_update_ret(&md5_ctx, iv, 8)) != 0) if( ( ret = mbedtls_md5_update_ret( &md5_ctx, iv, 8 ) ) != 0 )
goto exit; goto exit;
if ((ret = mbedtls_md5_finish_ret(&md5_ctx, md5sum)) != 0) if( ( ret = mbedtls_md5_finish_ret( &md5_ctx, md5sum ) ) != 0 )
goto exit; goto exit;
use_len = 16; use_len = 16;
if (keylen < 32) if( keylen < 32 )
use_len = keylen - 16; use_len = keylen - 16;
memcpy(key + 16, md5sum, use_len); memcpy( key + 16, md5sum, use_len );
exit: exit:
mbedtls_md5_free(&md5_ctx); mbedtls_md5_free( &md5_ctx );
mbedtls_platform_zeroize(md5sum, 16); mbedtls_platform_zeroize( md5sum, 16 );
return (ret); return( ret );
} }
#if defined(MBEDTLS_DES_C) #if defined(MBEDTLS_DES_C)
/* /*
* Decrypt with DES-CBC, using PBKDF1 for key derivation * Decrypt with DES-CBC, using PBKDF1 for key derivation
*/ */
static int pem_des_decrypt(unsigned char des_iv[8], static int pem_des_decrypt( unsigned char des_iv[8],
unsigned char *buf, size_t buflen, unsigned char *buf, size_t buflen,
const unsigned char *pwd, size_t pwdlen) { const unsigned char *pwd, size_t pwdlen )
{
mbedtls_des_context des_ctx; mbedtls_des_context des_ctx;
unsigned char des_key[8]; unsigned char des_key[8];
int ret; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_des_init(&des_ctx); mbedtls_des_init( &des_ctx );
if ((ret = pem_pbkdf1(des_key, 8, des_iv, pwd, pwdlen)) != 0) if( ( ret = pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen ) ) != 0 )
goto exit; goto exit;
if ((ret = mbedtls_des_setkey_dec(&des_ctx, des_key)) != 0) if( ( ret = mbedtls_des_setkey_dec( &des_ctx, des_key ) ) != 0 )
goto exit; goto exit;
ret = mbedtls_des_crypt_cbc(&des_ctx, MBEDTLS_DES_DECRYPT, buflen, ret = mbedtls_des_crypt_cbc( &des_ctx, MBEDTLS_DES_DECRYPT, buflen,
des_iv, buf, buf); des_iv, buf, buf );
exit: exit:
mbedtls_des_free(&des_ctx); mbedtls_des_free( &des_ctx );
mbedtls_platform_zeroize(des_key, 8); mbedtls_platform_zeroize( des_key, 8 );
return (ret); return( ret );
} }
/* /*
* Decrypt with 3DES-CBC, using PBKDF1 for key derivation * Decrypt with 3DES-CBC, using PBKDF1 for key derivation
*/ */
static int pem_des3_decrypt(unsigned char des3_iv[8], static int pem_des3_decrypt( unsigned char des3_iv[8],
unsigned char *buf, size_t buflen, unsigned char *buf, size_t buflen,
const unsigned char *pwd, size_t pwdlen) { const unsigned char *pwd, size_t pwdlen )
{
mbedtls_des3_context des3_ctx; mbedtls_des3_context des3_ctx;
unsigned char des3_key[24]; unsigned char des3_key[24];
int ret; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_des3_init(&des3_ctx); mbedtls_des3_init( &des3_ctx );
if ((ret = pem_pbkdf1(des3_key, 24, des3_iv, pwd, pwdlen)) != 0) if( ( ret = pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen ) ) != 0 )
goto exit; goto exit;
if ((ret = mbedtls_des3_set3key_dec(&des3_ctx, des3_key)) != 0) if( ( ret = mbedtls_des3_set3key_dec( &des3_ctx, des3_key ) ) != 0 )
goto exit; goto exit;
ret = mbedtls_des3_crypt_cbc(&des3_ctx, MBEDTLS_DES_DECRYPT, buflen, ret = mbedtls_des3_crypt_cbc( &des3_ctx, MBEDTLS_DES_DECRYPT, buflen,
des3_iv, buf, buf); des3_iv, buf, buf );
exit: exit:
mbedtls_des3_free(&des3_ctx); mbedtls_des3_free( &des3_ctx );
mbedtls_platform_zeroize(des3_key, 24); mbedtls_platform_zeroize( des3_key, 24 );
return (ret); return( ret );
} }
#endif /* MBEDTLS_DES_C */ #endif /* MBEDTLS_DES_C */
@@ -194,37 +193,39 @@ exit:
/* /*
* Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation
*/ */
static int pem_aes_decrypt(unsigned char aes_iv[16], unsigned int keylen, static int pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen,
unsigned char *buf, size_t buflen, unsigned char *buf, size_t buflen,
const unsigned char *pwd, size_t pwdlen) { const unsigned char *pwd, size_t pwdlen )
{
mbedtls_aes_context aes_ctx; mbedtls_aes_context aes_ctx;
unsigned char aes_key[32]; unsigned char aes_key[32];
int ret; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
mbedtls_aes_init(&aes_ctx); mbedtls_aes_init( &aes_ctx );
if ((ret = pem_pbkdf1(aes_key, keylen, aes_iv, pwd, pwdlen)) != 0) if( ( ret = pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen ) ) != 0 )
goto exit; goto exit;
if ((ret = mbedtls_aes_setkey_dec(&aes_ctx, aes_key, keylen * 8)) != 0) if( ( ret = mbedtls_aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 ) ) != 0 )
goto exit; goto exit;
ret = mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_DECRYPT, buflen, ret = mbedtls_aes_crypt_cbc( &aes_ctx, MBEDTLS_AES_DECRYPT, buflen,
aes_iv, buf, buf); aes_iv, buf, buf );
exit: exit:
mbedtls_aes_free(&aes_ctx); mbedtls_aes_free( &aes_ctx );
mbedtls_platform_zeroize(aes_key, keylen); mbedtls_platform_zeroize( aes_key, keylen );
return (ret); return( ret );
} }
#endif /* MBEDTLS_AES_C */ #endif /* MBEDTLS_AES_C */
#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && #endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC &&
( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */
int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const char *footer, int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const char *footer,
const unsigned char *data, const unsigned char *pwd, const unsigned char *data, const unsigned char *pwd,
size_t pwdlen, size_t *use_len) { size_t pwdlen, size_t *use_len )
{
int ret, enc; int ret, enc;
size_t len; size_t len;
unsigned char *buf; unsigned char *buf;
@@ -239,145 +240,154 @@ int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const
#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && #endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC &&
( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */
if (ctx == NULL) if( ctx == NULL )
return (MBEDTLS_ERR_PEM_BAD_INPUT_DATA); return( MBEDTLS_ERR_PEM_BAD_INPUT_DATA );
s1 = (unsigned char *) strstr((const char *) data, header); s1 = (unsigned char *) strstr( (const char *) data, header );
if (s1 == NULL) if( s1 == NULL )
return (MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT); return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT );
s2 = (unsigned char *) strstr((const char *) data, footer); s2 = (unsigned char *) strstr( (const char *) data, footer );
if (s2 == NULL || s2 <= s1) if( s2 == NULL || s2 <= s1 )
return (MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT); return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT );
s1 += strlen(header); s1 += strlen( header );
if (*s1 == ' ') s1++; if( *s1 == ' ' ) s1++;
if (*s1 == '\r') s1++; if( *s1 == '\r' ) s1++;
if (*s1 == '\n') s1++; if( *s1 == '\n' ) s1++;
else return (MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT); else return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT );
end = s2; end = s2;
end += strlen(footer); end += strlen( footer );
if (*end == ' ') end++; if( *end == ' ' ) end++;
if (*end == '\r') end++; if( *end == '\r' ) end++;
if (*end == '\n') end++; if( *end == '\n' ) end++;
*use_len = end - data; *use_len = end - data;
enc = 0; enc = 0;
if (s2 - s1 >= 22 && memcmp(s1, "Proc-Type: 4,ENCRYPTED", 22) == 0) { if( s2 - s1 >= 22 && memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 )
{
#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ #if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \
( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) )
enc++; enc++;
s1 += 22; s1 += 22;
if (*s1 == '\r') s1++; if( *s1 == '\r' ) s1++;
if (*s1 == '\n') s1++; if( *s1 == '\n' ) s1++;
else return (MBEDTLS_ERR_PEM_INVALID_DATA); else return( MBEDTLS_ERR_PEM_INVALID_DATA );
#if defined(MBEDTLS_DES_C) #if defined(MBEDTLS_DES_C)
if (s2 - s1 >= 23 && memcmp(s1, "DEK-Info: DES-EDE3-CBC,", 23) == 0) { if( s2 - s1 >= 23 && memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) == 0 )
{
enc_alg = MBEDTLS_CIPHER_DES_EDE3_CBC; enc_alg = MBEDTLS_CIPHER_DES_EDE3_CBC;
s1 += 23; s1 += 23;
if (s2 - s1 < 16 || pem_get_iv(s1, pem_iv, 8) != 0) if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8 ) != 0 )
return (MBEDTLS_ERR_PEM_INVALID_ENC_IV); return( MBEDTLS_ERR_PEM_INVALID_ENC_IV );
s1 += 16; s1 += 16;
} else if (s2 - s1 >= 18 && memcmp(s1, "DEK-Info: DES-CBC,", 18) == 0) { }
else if( s2 - s1 >= 18 && memcmp( s1, "DEK-Info: DES-CBC,", 18 ) == 0 )
{
enc_alg = MBEDTLS_CIPHER_DES_CBC; enc_alg = MBEDTLS_CIPHER_DES_CBC;
s1 += 18; s1 += 18;
if (s2 - s1 < 16 || pem_get_iv(s1, pem_iv, 8) != 0) if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8) != 0 )
return (MBEDTLS_ERR_PEM_INVALID_ENC_IV); return( MBEDTLS_ERR_PEM_INVALID_ENC_IV );
s1 += 16; s1 += 16;
} }
#endif /* MBEDTLS_DES_C */ #endif /* MBEDTLS_DES_C */
#if defined(MBEDTLS_AES_C) #if defined(MBEDTLS_AES_C)
if (s2 - s1 >= 14 && memcmp(s1, "DEK-Info: AES-", 14) == 0) { if( s2 - s1 >= 14 && memcmp( s1, "DEK-Info: AES-", 14 ) == 0 )
if (s2 - s1 < 22) {
return (MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG); if( s2 - s1 < 22 )
else if (memcmp(s1, "DEK-Info: AES-128-CBC,", 22) == 0) 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; enc_alg = MBEDTLS_CIPHER_AES_128_CBC;
else if (memcmp(s1, "DEK-Info: AES-192-CBC,", 22) == 0) else if( memcmp( s1, "DEK-Info: AES-192-CBC,", 22 ) == 0 )
enc_alg = MBEDTLS_CIPHER_AES_192_CBC; enc_alg = MBEDTLS_CIPHER_AES_192_CBC;
else if (memcmp(s1, "DEK-Info: AES-256-CBC,", 22) == 0) else if( memcmp( s1, "DEK-Info: AES-256-CBC,", 22 ) == 0 )
enc_alg = MBEDTLS_CIPHER_AES_256_CBC; enc_alg = MBEDTLS_CIPHER_AES_256_CBC;
else else
return (MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG); return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG );
s1 += 22; s1 += 22;
if (s2 - s1 < 32 || pem_get_iv(s1, pem_iv, 16) != 0) if( s2 - s1 < 32 || pem_get_iv( s1, pem_iv, 16 ) != 0 )
return (MBEDTLS_ERR_PEM_INVALID_ENC_IV); return( MBEDTLS_ERR_PEM_INVALID_ENC_IV );
s1 += 32; s1 += 32;
} }
#endif /* MBEDTLS_AES_C */ #endif /* MBEDTLS_AES_C */
if (enc_alg == MBEDTLS_CIPHER_NONE) if( enc_alg == MBEDTLS_CIPHER_NONE )
return (MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG); return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG );
if (*s1 == '\r') s1++; if( *s1 == '\r' ) s1++;
if (*s1 == '\n') s1++; if( *s1 == '\n' ) s1++;
else return (MBEDTLS_ERR_PEM_INVALID_DATA); else return( MBEDTLS_ERR_PEM_INVALID_DATA );
#else #else
return (MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE); return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE );
#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && #endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC &&
( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */
} }
if (s1 >= s2) if( s1 >= s2 )
return (MBEDTLS_ERR_PEM_INVALID_DATA); return( MBEDTLS_ERR_PEM_INVALID_DATA );
ret = mbedtls_base64_decode(NULL, 0, &len, s1, s2 - s1); ret = mbedtls_base64_decode( NULL, 0, &len, s1, s2 - s1 );
if (ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER) if( ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER )
return (MBEDTLS_ERR_PEM_INVALID_DATA + ret); return( MBEDTLS_ERR_PEM_INVALID_DATA + ret );
if ((buf = mbedtls_calloc(1, len)) == NULL) if( ( buf = mbedtls_calloc( 1, len ) ) == NULL )
return (MBEDTLS_ERR_PEM_ALLOC_FAILED); return( MBEDTLS_ERR_PEM_ALLOC_FAILED );
if ((ret = mbedtls_base64_decode(buf, len, &len, s1, s2 - s1)) != 0) { if( ( ret = mbedtls_base64_decode( buf, len, &len, s1, s2 - s1 ) ) != 0 )
mbedtls_platform_zeroize(buf, len); {
mbedtls_free(buf); mbedtls_platform_zeroize( buf, len );
return (MBEDTLS_ERR_PEM_INVALID_DATA + ret); mbedtls_free( buf );
return( MBEDTLS_ERR_PEM_INVALID_DATA + ret );
} }
if (enc != 0) { if( enc != 0 )
{
#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ #if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \
( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) )
if (pwd == NULL) { if( pwd == NULL )
mbedtls_platform_zeroize(buf, len); {
mbedtls_free(buf); mbedtls_platform_zeroize( buf, len );
return (MBEDTLS_ERR_PEM_PASSWORD_REQUIRED); mbedtls_free( buf );
return( MBEDTLS_ERR_PEM_PASSWORD_REQUIRED );
} }
ret = 0; ret = 0;
#if defined(MBEDTLS_DES_C) #if defined(MBEDTLS_DES_C)
if (enc_alg == MBEDTLS_CIPHER_DES_EDE3_CBC) if( enc_alg == MBEDTLS_CIPHER_DES_EDE3_CBC )
ret = pem_des3_decrypt(pem_iv, buf, len, pwd, pwdlen); ret = pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen );
else if (enc_alg == MBEDTLS_CIPHER_DES_CBC) else if( enc_alg == MBEDTLS_CIPHER_DES_CBC )
ret = pem_des_decrypt(pem_iv, buf, len, pwd, pwdlen); ret = pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen );
#endif /* MBEDTLS_DES_C */ #endif /* MBEDTLS_DES_C */
#if defined(MBEDTLS_AES_C) #if defined(MBEDTLS_AES_C)
if (enc_alg == MBEDTLS_CIPHER_AES_128_CBC) if( enc_alg == MBEDTLS_CIPHER_AES_128_CBC )
ret = pem_aes_decrypt(pem_iv, 16, buf, len, pwd, pwdlen); ret = pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen );
else if (enc_alg == MBEDTLS_CIPHER_AES_192_CBC) else if( enc_alg == MBEDTLS_CIPHER_AES_192_CBC )
ret = pem_aes_decrypt(pem_iv, 24, buf, len, pwd, pwdlen); ret = pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen );
else if (enc_alg == MBEDTLS_CIPHER_AES_256_CBC) else if( enc_alg == MBEDTLS_CIPHER_AES_256_CBC )
ret = pem_aes_decrypt(pem_iv, 32, buf, len, pwd, pwdlen); ret = pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen );
#endif /* MBEDTLS_AES_C */ #endif /* MBEDTLS_AES_C */
if (ret != 0) { if( ret != 0 )
mbedtls_free(buf); {
return (ret); mbedtls_free( buf );
return( ret );
} }
/* /*
@@ -386,15 +396,16 @@ int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const
* *
* Use that as a heuristic to try to detect password mismatches. * Use that as a heuristic to try to detect password mismatches.
*/ */
if (len <= 2 || buf[0] != 0x30 || buf[1] > 0x83) { if( len <= 2 || buf[0] != 0x30 || buf[1] > 0x83 )
mbedtls_platform_zeroize(buf, len); {
mbedtls_free(buf); mbedtls_platform_zeroize( buf, len );
return (MBEDTLS_ERR_PEM_PASSWORD_MISMATCH); mbedtls_free( buf );
return( MBEDTLS_ERR_PEM_PASSWORD_MISMATCH );
} }
#else #else
mbedtls_platform_zeroize(buf, len); mbedtls_platform_zeroize( buf, len );
mbedtls_free(buf); mbedtls_free( buf );
return (MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE); return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE );
#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && #endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC &&
( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */
} }
@@ -402,66 +413,77 @@ int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const
ctx->buf = buf; ctx->buf = buf;
ctx->buflen = len; ctx->buflen = len;
return (0); return( 0 );
} }
void mbedtls_pem_free(mbedtls_pem_context *ctx) { void mbedtls_pem_free( mbedtls_pem_context *ctx )
if (ctx->buf != NULL) {
mbedtls_platform_zeroize(ctx->buf, ctx->buflen); if ( ctx->buf != NULL )
mbedtls_free(ctx->buf); {
mbedtls_free(ctx->info); mbedtls_platform_zeroize( ctx->buf, ctx->buflen );
mbedtls_free( ctx->buf );
}
mbedtls_free( ctx->info );
mbedtls_platform_zeroize(ctx, sizeof(mbedtls_pem_context)); mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pem_context ) );
} }
#endif /* MBEDTLS_PEM_PARSE_C */ #endif /* MBEDTLS_PEM_PARSE_C */
#if defined(MBEDTLS_PEM_WRITE_C) #if defined(MBEDTLS_PEM_WRITE_C)
int mbedtls_pem_write_buffer(const char *header, const char *footer, int mbedtls_pem_write_buffer( const char *header, const char *footer,
const unsigned char *der_data, size_t der_len, const unsigned char *der_data, size_t der_len,
unsigned char *buf, size_t buf_len, size_t *olen) { unsigned char *buf, size_t buf_len, size_t *olen )
int ret; {
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char *encode_buf = NULL, *c, *p = buf; unsigned char *encode_buf = NULL, *c, *p = buf;
size_t len = 0, use_len, add_len = 0; size_t len = 0, use_len, add_len = 0;
mbedtls_base64_encode(NULL, 0, &use_len, der_data, der_len); mbedtls_base64_encode( NULL, 0, &use_len, der_data, der_len );
add_len = strlen(header) + strlen(footer) + (use_len / 64) + 1; add_len = strlen( header ) + strlen( footer ) + ( use_len / 64 ) + 1;
if (use_len + add_len > buf_len) { if( use_len + add_len > buf_len )
{
*olen = use_len + add_len; *olen = use_len + add_len;
return (MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL); return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
} }
if (use_len != 0 && if( use_len != 0 &&
((encode_buf = mbedtls_calloc(1, use_len)) == NULL)) ( ( encode_buf = mbedtls_calloc( 1, use_len ) ) == NULL ) )
return (MBEDTLS_ERR_PEM_ALLOC_FAILED); return( MBEDTLS_ERR_PEM_ALLOC_FAILED );
if ((ret = mbedtls_base64_encode(encode_buf, use_len, &use_len, der_data, if( ( ret = mbedtls_base64_encode( encode_buf, use_len, &use_len, der_data,
der_len)) != 0) { der_len ) ) != 0 )
mbedtls_free(encode_buf); {
return (ret); mbedtls_free( encode_buf );
return( ret );
} }
memcpy(p, header, strlen(header)); memcpy( p, header, strlen( header ) );
p += strlen(header); p += strlen( header );
c = encode_buf; c = encode_buf;
while (use_len) { while( use_len )
len = (use_len > 64) ? 64 : use_len; {
memcpy(p, c, len); len = ( use_len > 64 ) ? 64 : use_len;
memcpy( p, c, len );
use_len -= len; use_len -= len;
p += len; p += len;
c += len; c += len;
*p++ = '\n'; *p++ = '\n';
} }
memcpy(p, footer, strlen(footer)); memcpy( p, footer, strlen( footer ) );
p += strlen(footer); p += strlen( footer );
*p++ = '\0'; *p++ = '\0';
*olen = p - buf; *olen = p - buf;
mbedtls_free(encode_buf); /* Clean any remaining data previously written to the buffer */
return (0); memset( buf + *olen, 0, buf_len - *olen );
mbedtls_free( encode_buf );
return( 0 );
} }
#endif /* MBEDTLS_PEM_WRITE_C */ #endif /* MBEDTLS_PEM_WRITE_C */
#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ #endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */

View File

@@ -4,28 +4,30 @@
* \brief Privacy Enhanced Mail (PEM) decoding * \brief Privacy Enhanced Mail (PEM) decoding
*/ */
/* /*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
#ifndef MBEDTLS_PEM_H #ifndef MBEDTLS_PEM_H
#define MBEDTLS_PEM_H #define MBEDTLS_PEM_H
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#include <stddef.h> #include <stddef.h>
/** /**
@@ -53,7 +55,8 @@ extern "C" {
/** /**
* \brief PEM context structure * \brief PEM context structure
*/ */
typedef struct mbedtls_pem_context { typedef struct mbedtls_pem_context
{
unsigned char *buf; /*!< buffer for decoded data */ unsigned char *buf; /*!< buffer for decoded data */
size_t buflen; /*!< length of the buffer */ size_t buflen; /*!< length of the buffer */
unsigned char *info; /*!< buffer for extra header information */ unsigned char *info; /*!< buffer for extra header information */
@@ -65,7 +68,7 @@ mbedtls_pem_context;
* *
* \param ctx context to be initialized * \param ctx context to be initialized
*/ */
void mbedtls_pem_init(mbedtls_pem_context *ctx); void mbedtls_pem_init( mbedtls_pem_context *ctx );
/** /**
* \brief Read a buffer for PEM information and store the resulting * \brief Read a buffer for PEM information and store the resulting
@@ -89,17 +92,17 @@ void mbedtls_pem_init(mbedtls_pem_context *ctx);
* *
* \return 0 on success, or a specific PEM error code * \return 0 on success, or a specific PEM error code
*/ */
int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const char *footer, int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const char *footer,
const unsigned char *data, const unsigned char *data,
const unsigned char *pwd, const unsigned char *pwd,
size_t pwdlen, size_t *use_len); size_t pwdlen, size_t *use_len );
/** /**
* \brief PEM context memory freeing * \brief PEM context memory freeing
* *
* \param ctx context to be freed * \param ctx context to be freed
*/ */
void mbedtls_pem_free(mbedtls_pem_context *ctx); void mbedtls_pem_free( mbedtls_pem_context *ctx );
#endif /* MBEDTLS_PEM_PARSE_C */ #endif /* MBEDTLS_PEM_PARSE_C */
#if defined(MBEDTLS_PEM_WRITE_C) #if defined(MBEDTLS_PEM_WRITE_C)
@@ -107,21 +110,31 @@ void mbedtls_pem_free(mbedtls_pem_context *ctx);
* \brief Write a buffer of PEM information from a DER encoded * \brief Write a buffer of PEM information from a DER encoded
* buffer. * buffer.
* *
* \param header header string to write * \param header The header string to write.
* \param footer footer string to write * \param footer The footer string to write.
* \param der_data DER data to write * \param der_data The DER data to encode.
* \param der_len length of the DER data * \param der_len The length of the DER data \p der_data in Bytes.
* \param buf buffer to write to * \param buf The buffer to write to.
* \param buf_len length of output buffer * \param buf_len The length of the output buffer \p buf in Bytes.
* \param olen total length written / required (if buf_len is not enough) * \param olen The address at which to store the total length written
* or required (if \p buf_len is not enough).
* *
* \return 0 on success, or a specific PEM or BASE64 error code. On * \note You may pass \c NULL for \p buf and \c 0 for \p buf_len
* MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL olen is the required * to request the length of the resulting PEM buffer in
* size. * `*olen`.
*
* \note This function may be called with overlapping \p der_data
* and \p buf buffers.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL if \p buf isn't large
* enough to hold the PEM buffer. In this case, `*olen` holds
* the required minimum size of \p buf.
* \return Another PEM or BASE64 error code on other kinds of failure.
*/ */
int mbedtls_pem_write_buffer(const char *header, const char *footer, int mbedtls_pem_write_buffer( const char *header, const char *footer,
const unsigned char *der_data, size_t der_len, const unsigned char *der_data, size_t der_len,
unsigned char *buf, size_t buf_len, size_t *olen); unsigned char *buf, size_t buf_len, size_t *olen );
#endif /* MBEDTLS_PEM_WRITE_C */ #endif /* MBEDTLS_PEM_WRITE_C */
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -1,37 +1,30 @@
/* /*
* Public Key abstraction layer * Public Key abstraction layer
* *
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
#if !defined(MBEDTLS_CONFIG_FILE) #include "common.h"
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_PK_C) #if defined(MBEDTLS_PK_C)
#include "mbedtls/pk.h" #include "mbedtls/pk.h"
#include "mbedtls/pk_internal.h" #include "mbedtls/pk_internal.h"
#include "mbedtls/platform_util.h" #include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#if defined(MBEDTLS_RSA_C) #if defined(MBEDTLS_RSA_C)
#include "mbedtls/rsa.h" #include "mbedtls/rsa.h"
@@ -43,15 +36,25 @@
#include "mbedtls/ecdsa.h" #include "mbedtls/ecdsa.h"
#endif #endif
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#include "mbedtls/psa_util.h"
#endif
#include <limits.h> #include <limits.h>
#include <stdint.h> #include <stdint.h>
/* Parameter validation macros based on platform_util.h */
#define PK_VALIDATE_RET( cond ) \
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA )
#define PK_VALIDATE( cond ) \
MBEDTLS_INTERNAL_VALIDATE( cond )
/* /*
* Initialise a mbedtls_pk_context * Initialise a mbedtls_pk_context
*/ */
void mbedtls_pk_init(mbedtls_pk_context *ctx) { void mbedtls_pk_init( mbedtls_pk_context *ctx )
if (ctx == NULL) {
return; PK_VALIDATE( ctx != NULL );
ctx->pk_info = NULL; ctx->pk_info = NULL;
ctx->pk_ctx = NULL; ctx->pk_ctx = NULL;
@@ -60,71 +63,143 @@ void mbedtls_pk_init(mbedtls_pk_context *ctx) {
/* /*
* Free (the components of) a mbedtls_pk_context * Free (the components of) a mbedtls_pk_context
*/ */
void mbedtls_pk_free(mbedtls_pk_context *ctx) { void mbedtls_pk_free( mbedtls_pk_context *ctx )
if (ctx == NULL || ctx->pk_info == NULL) {
if( ctx == NULL )
return; return;
ctx->pk_info->ctx_free_func(ctx->pk_ctx); if ( ctx->pk_info != NULL )
ctx->pk_info->ctx_free_func( ctx->pk_ctx );
mbedtls_platform_zeroize(ctx, sizeof(mbedtls_pk_context)); mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pk_context ) );
} }
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
/*
* Initialize a restart context
*/
void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx )
{
PK_VALIDATE( ctx != NULL );
ctx->pk_info = NULL;
ctx->rs_ctx = NULL;
}
/*
* Free the components of a restart context
*/
void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx )
{
if( ctx == NULL || ctx->pk_info == NULL ||
ctx->pk_info->rs_free_func == NULL )
{
return;
}
ctx->pk_info->rs_free_func( ctx->rs_ctx );
ctx->pk_info = NULL;
ctx->rs_ctx = NULL;
}
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
/* /*
* Get pk_info structure from type * Get pk_info structure from type
*/ */
const mbedtls_pk_info_t *mbedtls_pk_info_from_type(mbedtls_pk_type_t pk_type) { const mbedtls_pk_info_t * mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type )
switch (pk_type) { {
switch( pk_type ) {
#if defined(MBEDTLS_RSA_C) #if defined(MBEDTLS_RSA_C)
case MBEDTLS_PK_RSA: case MBEDTLS_PK_RSA:
return (&mbedtls_rsa_info); return( &mbedtls_rsa_info );
#endif #endif
#if defined(MBEDTLS_ECP_C) #if defined(MBEDTLS_ECP_C)
case MBEDTLS_PK_ECKEY: case MBEDTLS_PK_ECKEY:
return (&mbedtls_eckey_info); return( &mbedtls_eckey_info );
case MBEDTLS_PK_ECKEY_DH: case MBEDTLS_PK_ECKEY_DH:
return (&mbedtls_eckeydh_info); return( &mbedtls_eckeydh_info );
#endif #endif
#if defined(MBEDTLS_ECDSA_C) #if defined(MBEDTLS_ECDSA_C)
case MBEDTLS_PK_ECDSA: case MBEDTLS_PK_ECDSA:
return (&mbedtls_ecdsa_info); return( &mbedtls_ecdsa_info );
#endif #endif
/* MBEDTLS_PK_RSA_ALT omitted on purpose */ /* MBEDTLS_PK_RSA_ALT omitted on purpose */
default: default:
return (NULL); return( NULL );
} }
} }
/* /*
* Initialise context * Initialise context
*/ */
int mbedtls_pk_setup(mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info) { int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info )
if (ctx == NULL || info == NULL || ctx->pk_info != NULL) {
return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); PK_VALIDATE_RET( ctx != NULL );
if( info == NULL || ctx->pk_info != NULL )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
if ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL) if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL )
return (MBEDTLS_ERR_PK_ALLOC_FAILED); return( MBEDTLS_ERR_PK_ALLOC_FAILED );
ctx->pk_info = info; ctx->pk_info = info;
return (0); return( 0 );
} }
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/*
* Initialise a PSA-wrapping context
*/
int mbedtls_pk_setup_opaque( mbedtls_pk_context *ctx,
const psa_key_id_t key )
{
const mbedtls_pk_info_t * const info = &mbedtls_pk_opaque_info;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t *pk_ctx;
psa_key_type_t type;
if( ctx == NULL || ctx->pk_info != NULL )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
if( PSA_SUCCESS != psa_get_key_attributes( key, &attributes ) )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
type = psa_get_key_type( &attributes );
psa_reset_key_attributes( &attributes );
/* Current implementation of can_do() relies on this. */
if( ! PSA_KEY_TYPE_IS_ECC_KEY_PAIR( type ) )
return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE) ;
if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL )
return( MBEDTLS_ERR_PK_ALLOC_FAILED );
ctx->pk_info = info;
pk_ctx = (psa_key_id_t *) ctx->pk_ctx;
*pk_ctx = key;
return( 0 );
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
/* /*
* Initialize an RSA-alt context * Initialize an RSA-alt context
*/ */
int mbedtls_pk_setup_rsa_alt(mbedtls_pk_context *ctx, void *key, int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key,
mbedtls_pk_rsa_alt_decrypt_func decrypt_func, mbedtls_pk_rsa_alt_decrypt_func decrypt_func,
mbedtls_pk_rsa_alt_sign_func sign_func, mbedtls_pk_rsa_alt_sign_func sign_func,
mbedtls_pk_rsa_alt_key_len_func key_len_func) { mbedtls_pk_rsa_alt_key_len_func key_len_func )
{
mbedtls_rsa_alt_context *rsa_alt; mbedtls_rsa_alt_context *rsa_alt;
const mbedtls_pk_info_t *info = &mbedtls_rsa_alt_info; const mbedtls_pk_info_t *info = &mbedtls_rsa_alt_info;
if (ctx == NULL || ctx->pk_info != NULL) PK_VALIDATE_RET( ctx != NULL );
return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); if( ctx->pk_info != NULL )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
if ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL) if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL )
return (MBEDTLS_ERR_PK_ALLOC_FAILED); return( MBEDTLS_ERR_PK_ALLOC_FAILED );
ctx->pk_info = info; ctx->pk_info = info;
@@ -135,225 +210,430 @@ int mbedtls_pk_setup_rsa_alt(mbedtls_pk_context *ctx, void *key,
rsa_alt->sign_func = sign_func; rsa_alt->sign_func = sign_func;
rsa_alt->key_len_func = key_len_func; rsa_alt->key_len_func = key_len_func;
return (0); return( 0 );
} }
#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */
/* /*
* Tell if a PK can do the operations of the given type * Tell if a PK can do the operations of the given type
*/ */
int mbedtls_pk_can_do(const mbedtls_pk_context *ctx, mbedtls_pk_type_t type) { int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type )
/* null or NONE context can't do anything */ {
if (ctx == NULL || ctx->pk_info == NULL) /* A context with null pk_info is not set up yet and can't do anything.
return (0); * For backward compatibility, also accept NULL instead of a context
* pointer. */
if( ctx == NULL || ctx->pk_info == NULL )
return( 0 );
return (ctx->pk_info->can_do(type)); return( ctx->pk_info->can_do( type ) );
} }
/* /*
* Helper for mbedtls_pk_sign and mbedtls_pk_verify * Helper for mbedtls_pk_sign and mbedtls_pk_verify
*/ */
static inline int pk_hashlen_helper(mbedtls_md_type_t md_alg, size_t *hash_len) { static inline int pk_hashlen_helper( mbedtls_md_type_t md_alg, size_t *hash_len )
{
const mbedtls_md_info_t *md_info; const mbedtls_md_info_t *md_info;
if (*hash_len != 0) if( *hash_len != 0 )
return (0); return( 0 );
if ((md_info = mbedtls_md_info_from_type(md_alg)) == NULL) if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL )
return (-1); return( -1 );
*hash_len = mbedtls_md_get_size(md_info); *hash_len = mbedtls_md_get_size( md_info );
return (0); return( 0 );
}
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
/*
* Helper to set up a restart context if needed
*/
static int pk_restart_setup( mbedtls_pk_restart_ctx *ctx,
const mbedtls_pk_info_t *info )
{
/* Don't do anything if already set up or invalid */
if( ctx == NULL || ctx->pk_info != NULL )
return( 0 );
/* Should never happen when we're called */
if( info->rs_alloc_func == NULL || info->rs_free_func == NULL )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
if( ( ctx->rs_ctx = info->rs_alloc_func() ) == NULL )
return( MBEDTLS_ERR_PK_ALLOC_FAILED );
ctx->pk_info = info;
return( 0 );
}
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
/*
* Verify a signature (restartable)
*/
int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx,
mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len,
mbedtls_pk_restart_ctx *rs_ctx )
{
PK_VALIDATE_RET( ctx != NULL );
PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) ||
hash != NULL );
PK_VALIDATE_RET( sig != NULL );
if( ctx->pk_info == NULL ||
pk_hashlen_helper( md_alg, &hash_len ) != 0 )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
/* optimization: use non-restartable version if restart disabled */
if( rs_ctx != NULL &&
mbedtls_ecp_restart_is_enabled() &&
ctx->pk_info->verify_rs_func != NULL )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 )
return( ret );
ret = ctx->pk_info->verify_rs_func( ctx->pk_ctx,
md_alg, hash, hash_len, sig, sig_len, rs_ctx->rs_ctx );
if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
mbedtls_pk_restart_free( rs_ctx );
return( ret );
}
#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
(void) rs_ctx;
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
if( ctx->pk_info->verify_func == NULL )
return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg, hash, hash_len,
sig, sig_len ) );
} }
/* /*
* Verify a signature * Verify a signature
*/ */
int mbedtls_pk_verify(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len, const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len) { const unsigned char *sig, size_t sig_len )
if (ctx == NULL || ctx->pk_info == NULL || {
pk_hashlen_helper(md_alg, &hash_len) != 0) return( mbedtls_pk_verify_restartable( ctx, md_alg, hash, hash_len,
return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); sig, sig_len, NULL ) );
if (ctx->pk_info->verify_func == NULL)
return (MBEDTLS_ERR_PK_TYPE_MISMATCH);
return (ctx->pk_info->verify_func(ctx->pk_ctx, md_alg, hash, hash_len,
sig, sig_len));
} }
/* /*
* Verify a signature with options * Verify a signature with options
*/ */
int mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options, int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options,
mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len, const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len) { const unsigned char *sig, size_t sig_len )
if (ctx == NULL || ctx->pk_info == NULL) {
return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); PK_VALIDATE_RET( ctx != NULL );
PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) ||
hash != NULL );
PK_VALIDATE_RET( sig != NULL );
if (! mbedtls_pk_can_do(ctx, type)) if( ctx->pk_info == NULL )
return (MBEDTLS_ERR_PK_TYPE_MISMATCH); return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
if (type == MBEDTLS_PK_RSASSA_PSS) { if( ! mbedtls_pk_can_do( ctx, type ) )
return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
if( type == MBEDTLS_PK_RSASSA_PSS )
{
#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) #if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21)
int ret; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
const mbedtls_pk_rsassa_pss_options *pss_opts; const mbedtls_pk_rsassa_pss_options *pss_opts;
#if SIZE_MAX > UINT_MAX #if SIZE_MAX > UINT_MAX
if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len )
return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
#endif /* SIZE_MAX > UINT_MAX */ #endif /* SIZE_MAX > UINT_MAX */
if (options == NULL) if( options == NULL )
return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
pss_opts = (const mbedtls_pk_rsassa_pss_options *) options; pss_opts = (const mbedtls_pk_rsassa_pss_options *) options;
if (sig_len < mbedtls_pk_get_len(ctx)) if( sig_len < mbedtls_pk_get_len( ctx ) )
return (MBEDTLS_ERR_RSA_VERIFY_FAILED); return( MBEDTLS_ERR_RSA_VERIFY_FAILED );
ret = mbedtls_rsa_rsassa_pss_verify_ext(mbedtls_pk_rsa(*ctx), ret = mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_pk_rsa( *ctx ),
NULL, NULL, MBEDTLS_RSA_PUBLIC, NULL, NULL, MBEDTLS_RSA_PUBLIC,
md_alg, (unsigned int) hash_len, hash, md_alg, (unsigned int) hash_len, hash,
pss_opts->mgf1_hash_id, pss_opts->mgf1_hash_id,
pss_opts->expected_salt_len, pss_opts->expected_salt_len,
sig); sig );
if (ret != 0) if( ret != 0 )
return (ret); return( ret );
if (sig_len > mbedtls_pk_get_len(ctx)) if( sig_len > mbedtls_pk_get_len( ctx ) )
return (MBEDTLS_ERR_PK_SIG_LEN_MISMATCH); return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH );
return (0); return( 0 );
#else #else
return (MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE); return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
#endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */ #endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */
} }
/* General case: no options */ /* General case: no options */
if (options != NULL) if( options != NULL )
return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
return (mbedtls_pk_verify(ctx, md_alg, hash, hash_len, sig, sig_len)); return( mbedtls_pk_verify( ctx, md_alg, hash, hash_len, sig, sig_len ) );
}
/*
* Make a signature (restartable)
*/
int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx,
mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
unsigned char *sig, size_t *sig_len,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
mbedtls_pk_restart_ctx *rs_ctx )
{
PK_VALIDATE_RET( ctx != NULL );
PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) ||
hash != NULL );
PK_VALIDATE_RET( sig != NULL );
if( ctx->pk_info == NULL ||
pk_hashlen_helper( md_alg, &hash_len ) != 0 )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
/* optimization: use non-restartable version if restart disabled */
if( rs_ctx != NULL &&
mbedtls_ecp_restart_is_enabled() &&
ctx->pk_info->sign_rs_func != NULL )
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 )
return( ret );
ret = ctx->pk_info->sign_rs_func( ctx->pk_ctx, md_alg,
hash, hash_len, sig, sig_len, f_rng, p_rng, rs_ctx->rs_ctx );
if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS )
mbedtls_pk_restart_free( rs_ctx );
return( ret );
}
#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
(void) rs_ctx;
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
if( ctx->pk_info->sign_func == NULL )
return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg, hash, hash_len,
sig, sig_len, f_rng, p_rng ) );
} }
/* /*
* Make a signature * Make a signature
*/ */
int mbedtls_pk_sign(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len, const unsigned char *hash, size_t hash_len,
unsigned char *sig, size_t *sig_len, unsigned char *sig, size_t *sig_len,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
if (ctx == NULL || ctx->pk_info == NULL || {
pk_hashlen_helper(md_alg, &hash_len) != 0) return( mbedtls_pk_sign_restartable( ctx, md_alg, hash, hash_len,
return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); sig, sig_len, f_rng, p_rng, NULL ) );
if (ctx->pk_info->sign_func == NULL)
return (MBEDTLS_ERR_PK_TYPE_MISMATCH);
return (ctx->pk_info->sign_func(ctx->pk_ctx, md_alg, hash, hash_len,
sig, sig_len, f_rng, p_rng));
} }
/* /*
* Decrypt message * Decrypt message
*/ */
int mbedtls_pk_decrypt(mbedtls_pk_context *ctx, int mbedtls_pk_decrypt( mbedtls_pk_context *ctx,
const unsigned char *input, size_t ilen, const unsigned char *input, size_t ilen,
unsigned char *output, size_t *olen, size_t osize, unsigned char *output, size_t *olen, size_t osize,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
if (ctx == NULL || ctx->pk_info == NULL) {
return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); PK_VALIDATE_RET( ctx != NULL );
PK_VALIDATE_RET( input != NULL || ilen == 0 );
PK_VALIDATE_RET( output != NULL || osize == 0 );
PK_VALIDATE_RET( olen != NULL );
if (ctx->pk_info->decrypt_func == NULL) if( ctx->pk_info == NULL )
return (MBEDTLS_ERR_PK_TYPE_MISMATCH); return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
return (ctx->pk_info->decrypt_func(ctx->pk_ctx, input, ilen, if( ctx->pk_info->decrypt_func == NULL )
output, olen, osize, f_rng, p_rng)); return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
return( ctx->pk_info->decrypt_func( ctx->pk_ctx, input, ilen,
output, olen, osize, f_rng, p_rng ) );
} }
/* /*
* Encrypt message * Encrypt message
*/ */
int mbedtls_pk_encrypt(mbedtls_pk_context *ctx, int mbedtls_pk_encrypt( mbedtls_pk_context *ctx,
const unsigned char *input, size_t ilen, const unsigned char *input, size_t ilen,
unsigned char *output, size_t *olen, size_t osize, unsigned char *output, size_t *olen, size_t osize,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng) { int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
if (ctx == NULL || ctx->pk_info == NULL) {
return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); PK_VALIDATE_RET( ctx != NULL );
PK_VALIDATE_RET( input != NULL || ilen == 0 );
PK_VALIDATE_RET( output != NULL || osize == 0 );
PK_VALIDATE_RET( olen != NULL );
if (ctx->pk_info->encrypt_func == NULL) if( ctx->pk_info == NULL )
return (MBEDTLS_ERR_PK_TYPE_MISMATCH); return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
return (ctx->pk_info->encrypt_func(ctx->pk_ctx, input, ilen, if( ctx->pk_info->encrypt_func == NULL )
output, olen, osize, f_rng, p_rng)); return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
return( ctx->pk_info->encrypt_func( ctx->pk_ctx, input, ilen,
output, olen, osize, f_rng, p_rng ) );
} }
/* /*
* Check public-private key pair * Check public-private key pair
*/ */
int mbedtls_pk_check_pair(const mbedtls_pk_context *pub, const mbedtls_pk_context *prv) { int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv )
if (pub == NULL || pub->pk_info == NULL || {
prv == NULL || prv->pk_info == NULL || PK_VALIDATE_RET( pub != NULL );
prv->pk_info->check_pair_func == NULL) { PK_VALIDATE_RET( prv != NULL );
return (MBEDTLS_ERR_PK_BAD_INPUT_DATA);
if( pub->pk_info == NULL ||
prv->pk_info == NULL )
{
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
} }
if (prv->pk_info->type == MBEDTLS_PK_RSA_ALT) { if( prv->pk_info->check_pair_func == NULL )
if (pub->pk_info->type != MBEDTLS_PK_RSA) return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
return (MBEDTLS_ERR_PK_TYPE_MISMATCH);
} else { if( prv->pk_info->type == MBEDTLS_PK_RSA_ALT )
if (pub->pk_info != prv->pk_info) {
return (MBEDTLS_ERR_PK_TYPE_MISMATCH); if( pub->pk_info->type != MBEDTLS_PK_RSA )
return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
}
else
{
if( pub->pk_info != prv->pk_info )
return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
} }
return (prv->pk_info->check_pair_func(pub->pk_ctx, prv->pk_ctx)); return( prv->pk_info->check_pair_func( pub->pk_ctx, prv->pk_ctx ) );
} }
/* /*
* Get key size in bits * Get key size in bits
*/ */
size_t mbedtls_pk_get_bitlen(const mbedtls_pk_context *ctx) { size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx )
if (ctx == NULL || ctx->pk_info == NULL) {
return (0); /* For backward compatibility, accept NULL or a context that
* isn't set up yet, and return a fake value that should be safe. */
if( ctx == NULL || ctx->pk_info == NULL )
return( 0 );
return (ctx->pk_info->get_bitlen(ctx->pk_ctx)); return( ctx->pk_info->get_bitlen( ctx->pk_ctx ) );
} }
/* /*
* Export debug information * Export debug information
*/ */
int mbedtls_pk_debug(const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items) { int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items )
if (ctx == NULL || ctx->pk_info == NULL) {
return (MBEDTLS_ERR_PK_BAD_INPUT_DATA); PK_VALIDATE_RET( ctx != NULL );
if( ctx->pk_info == NULL )
return( MBEDTLS_ERR_PK_BAD_INPUT_DATA );
if (ctx->pk_info->debug_func == NULL) if( ctx->pk_info->debug_func == NULL )
return (MBEDTLS_ERR_PK_TYPE_MISMATCH); return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
ctx->pk_info->debug_func(ctx->pk_ctx, items); ctx->pk_info->debug_func( ctx->pk_ctx, items );
return (0); return( 0 );
} }
/* /*
* Access the PK type name * Access the PK type name
*/ */
const char *mbedtls_pk_get_name(const mbedtls_pk_context *ctx) { const char *mbedtls_pk_get_name( const mbedtls_pk_context *ctx )
if (ctx == NULL || ctx->pk_info == NULL) {
return ("invalid PK"); if( ctx == NULL || ctx->pk_info == NULL )
return( "invalid PK" );
return (ctx->pk_info->name); return( ctx->pk_info->name );
} }
/* /*
* Access the PK type * Access the PK type
*/ */
mbedtls_pk_type_t mbedtls_pk_get_type(const mbedtls_pk_context *ctx) { mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx )
if (ctx == NULL || ctx->pk_info == NULL) {
return (MBEDTLS_PK_NONE); if( ctx == NULL || ctx->pk_info == NULL )
return( MBEDTLS_PK_NONE );
return (ctx->pk_info->type); return( ctx->pk_info->type );
} }
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/*
* Load the key to a PSA key slot,
* then turn the PK context into a wrapper for that key slot.
*
* Currently only works for EC private keys.
*/
int mbedtls_pk_wrap_as_opaque( mbedtls_pk_context *pk,
psa_key_id_t *key,
psa_algorithm_t hash_alg )
{
#if !defined(MBEDTLS_ECP_C)
((void) pk);
((void) key);
((void) hash_alg);
return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
#else
const mbedtls_ecp_keypair *ec;
unsigned char d[MBEDTLS_ECP_MAX_BYTES];
size_t d_len;
psa_ecc_family_t curve_id;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_type_t key_type;
size_t bits;
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
/* export the private key material in the format PSA wants */
if( mbedtls_pk_get_type( pk ) != MBEDTLS_PK_ECKEY )
return( MBEDTLS_ERR_PK_TYPE_MISMATCH );
ec = mbedtls_pk_ec( *pk );
d_len = ( ec->grp.nbits + 7 ) / 8;
if( ( ret = mbedtls_mpi_write_binary( &ec->d, d, d_len ) ) != 0 )
return( ret );
curve_id = mbedtls_ecc_group_to_psa( ec->grp.id, &bits );
key_type = PSA_KEY_TYPE_ECC_KEY_PAIR( curve_id );
/* prepare the key attributes */
psa_set_key_type( &attributes, key_type );
psa_set_key_bits( &attributes, bits );
psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_HASH );
psa_set_key_algorithm( &attributes, PSA_ALG_ECDSA(hash_alg) );
/* import private key into PSA */
if( PSA_SUCCESS != psa_import_key( &attributes, d, d_len, key ) )
return( MBEDTLS_ERR_PK_HW_ACCEL_FAILED );
/* make PK context wrap the key slot */
mbedtls_pk_free( pk );
mbedtls_pk_init( pk );
return( mbedtls_pk_setup_opaque( pk, *key ) );
#endif /* MBEDTLS_ECP_C */
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#endif /* MBEDTLS_PK_C */ #endif /* MBEDTLS_PK_C */

View File

@@ -4,47 +4,47 @@
* \brief Public Key abstraction layer * \brief Public Key abstraction layer
*/ */
/* /*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: GPL-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* This program is free software; you can redistribute it and/or modify * Licensed under the Apache License, Version 2.0 (the "License"); you may
* it under the terms of the GNU General Public License as published by * not use this file except in compliance with the License.
* the Free Software Foundation; either version 2 of the License, or * You may obtain a copy of the License at
* (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * http://www.apache.org/licenses/LICENSE-2.0
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License along * Unless required by applicable law or agreed to in writing, software
* with this program; if not, write to the Free Software Foundation, Inc., * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* This file is part of mbed TLS (https://tls.mbed.org) * limitations under the License.
*/ */
#ifndef MBEDTLS_PK_H #ifndef MBEDTLS_PK_H
#define MBEDTLS_PK_H #define MBEDTLS_PK_H
#if !defined(MBEDTLS_CONFIG_FILE) #if !defined(MBEDTLS_CONFIG_FILE)
#include "config.h" #include "mbedtls/config.h"
#else #else
#include MBEDTLS_CONFIG_FILE #include MBEDTLS_CONFIG_FILE
#endif #endif
#include "md.h" #include "mbedtls/md.h"
#if defined(MBEDTLS_RSA_C) #if defined(MBEDTLS_RSA_C)
#include "rsa.h" #include "mbedtls/rsa.h"
#endif #endif
#if defined(MBEDTLS_ECP_C) #if defined(MBEDTLS_ECP_C)
#include "ecp.h" #include "mbedtls/ecp.h"
#endif #endif
#if defined(MBEDTLS_ECDSA_C) #if defined(MBEDTLS_ECDSA_C)
#include "ecdsa.h" #include "mbedtls/ecdsa.h"
#endif
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#include "psa/crypto.h"
#endif #endif
#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ #if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \
@@ -66,6 +66,8 @@
#define MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE -0x3A00 /**< Elliptic curve is unsupported (only NIST curves are supported). */ #define MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE -0x3A00 /**< Elliptic curve is unsupported (only NIST curves are supported). */
#define MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -0x3980 /**< Unavailable feature, e.g. RSA disabled for RSA key. */ #define MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -0x3980 /**< Unavailable feature, e.g. RSA disabled for RSA key. */
#define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH -0x3900 /**< The buffer contains a valid signature followed by more data. */ #define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH -0x3900 /**< The buffer contains a valid signature followed by more data. */
/* MBEDTLS_ERR_PK_HW_ACCEL_FAILED is deprecated and should not be used. */
#define MBEDTLS_ERR_PK_HW_ACCEL_FAILED -0x3880 /**< PK hardware accelerator failed. */ #define MBEDTLS_ERR_PK_HW_ACCEL_FAILED -0x3880 /**< PK hardware accelerator failed. */
#ifdef __cplusplus #ifdef __cplusplus
@@ -76,29 +78,84 @@ extern "C" {
* \brief Public key types * \brief Public key types
*/ */
typedef enum { typedef enum {
MBEDTLS_PK_NONE = 0, MBEDTLS_PK_NONE=0,
MBEDTLS_PK_RSA, MBEDTLS_PK_RSA,
MBEDTLS_PK_ECKEY, MBEDTLS_PK_ECKEY,
MBEDTLS_PK_ECKEY_DH, MBEDTLS_PK_ECKEY_DH,
MBEDTLS_PK_ECDSA, MBEDTLS_PK_ECDSA,
MBEDTLS_PK_RSA_ALT, MBEDTLS_PK_RSA_ALT,
MBEDTLS_PK_RSASSA_PSS, MBEDTLS_PK_RSASSA_PSS,
MBEDTLS_PK_OPAQUE,
} mbedtls_pk_type_t; } mbedtls_pk_type_t;
/** /**
* \brief Options for RSASSA-PSS signature verification. * \brief Options for RSASSA-PSS signature verification.
* See \c mbedtls_rsa_rsassa_pss_verify_ext() * See \c mbedtls_rsa_rsassa_pss_verify_ext()
*/ */
typedef struct mbedtls_pk_rsassa_pss_options { typedef struct mbedtls_pk_rsassa_pss_options
{
mbedtls_md_type_t mgf1_hash_id; mbedtls_md_type_t mgf1_hash_id;
int expected_salt_len; int expected_salt_len;
} mbedtls_pk_rsassa_pss_options; } mbedtls_pk_rsassa_pss_options;
/**
* \brief Maximum size of a signature made by mbedtls_pk_sign().
*/
/* We need to set MBEDTLS_PK_SIGNATURE_MAX_SIZE to the maximum signature
* size among the supported signature types. Do it by starting at 0,
* then incrementally increasing to be large enough for each supported
* signature mechanism.
*
* The resulting value can be 0, for example if MBEDTLS_ECDH_C is enabled
* (which allows the pk module to be included) but neither MBEDTLS_ECDSA_C
* nor MBEDTLS_RSA_C nor any opaque signature mechanism (PSA or RSA_ALT).
*/
#define MBEDTLS_PK_SIGNATURE_MAX_SIZE 0
#if ( defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_RSA_ALT_SUPPORT) ) && \
MBEDTLS_MPI_MAX_SIZE > MBEDTLS_PK_SIGNATURE_MAX_SIZE
/* For RSA, the signature can be as large as the bignum module allows.
* For RSA_ALT, the signature size is not necessarily tied to what the
* bignum module can do, but in the absence of any specific setting,
* we use that (rsa_alt_sign_wrap in pk_wrap will check). */
#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE
#define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE
#endif
#if defined(MBEDTLS_ECDSA_C) && \
MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_PK_SIGNATURE_MAX_SIZE
/* For ECDSA, the ecdsa module exports a constant for the maximum
* signature size. */
#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE
#define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN
#endif
#if defined(MBEDTLS_USE_PSA_CRYPTO)
#if PSA_SIGNATURE_MAX_SIZE > MBEDTLS_PK_SIGNATURE_MAX_SIZE
/* PSA_SIGNATURE_MAX_SIZE is the maximum size of a signature made
* through the PSA API in the PSA representation. */
#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE
#define MBEDTLS_PK_SIGNATURE_MAX_SIZE PSA_SIGNATURE_MAX_SIZE
#endif
#if PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE + 11 > MBEDTLS_PK_SIGNATURE_MAX_SIZE
/* The Mbed TLS representation is different for ECDSA signatures:
* PSA uses the raw concatenation of r and s,
* whereas Mbed TLS uses the ASN.1 representation (SEQUENCE of two INTEGERs).
* Add the overhead of ASN.1: up to (1+2) + 2 * (1+2+1) for the
* types, lengths (represented by up to 2 bytes), and potential leading
* zeros of the INTEGERs and the SEQUENCE. */
#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE
#define MBEDTLS_PK_SIGNATURE_MAX_SIZE ( PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE + 11 )
#endif
#endif /* defined(MBEDTLS_USE_PSA_CRYPTO) */
/** /**
* \brief Types for interfacing with the debug module * \brief Types for interfacing with the debug module
*/ */
typedef enum { typedef enum
{
MBEDTLS_PK_DEBUG_NONE = 0, MBEDTLS_PK_DEBUG_NONE = 0,
MBEDTLS_PK_DEBUG_MPI, MBEDTLS_PK_DEBUG_MPI,
MBEDTLS_PK_DEBUG_ECP, MBEDTLS_PK_DEBUG_ECP,
@@ -107,7 +164,8 @@ typedef enum {
/** /**
* \brief Item to send to the debug module * \brief Item to send to the debug module
*/ */
typedef struct mbedtls_pk_debug_item { typedef struct mbedtls_pk_debug_item
{
mbedtls_pk_debug_type type; mbedtls_pk_debug_type type;
const char *name; const char *name;
void *value; void *value;
@@ -124,11 +182,26 @@ typedef struct mbedtls_pk_info_t mbedtls_pk_info_t;
/** /**
* \brief Public key container * \brief Public key container
*/ */
typedef struct mbedtls_pk_context { typedef struct mbedtls_pk_context
const mbedtls_pk_info_t *pk_info; /**< Public key informations */ {
void *pk_ctx; /**< Underlying public key context */ const mbedtls_pk_info_t * pk_info; /**< Public key information */
void * pk_ctx; /**< Underlying public key context */
} mbedtls_pk_context; } mbedtls_pk_context;
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
/**
* \brief Context for resuming operations
*/
typedef struct
{
const mbedtls_pk_info_t * pk_info; /**< Public key information */
void * rs_ctx; /**< Underlying restart context */
} mbedtls_pk_restart_ctx;
#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
/* Now we can declare functions that take a pointer to that */
typedef void mbedtls_pk_restart_ctx;
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
#if defined(MBEDTLS_RSA_C) #if defined(MBEDTLS_RSA_C)
/** /**
* Quick access to an RSA context inside a PK context. * Quick access to an RSA context inside a PK context.
@@ -136,8 +209,9 @@ typedef struct mbedtls_pk_context {
* \warning You must make sure the PK context actually holds an RSA context * \warning You must make sure the PK context actually holds an RSA context
* before using this function! * before using this function!
*/ */
static inline mbedtls_rsa_context *mbedtls_pk_rsa(const mbedtls_pk_context pk) { static inline mbedtls_rsa_context *mbedtls_pk_rsa( const mbedtls_pk_context pk )
return ((mbedtls_rsa_context *)(pk).pk_ctx); {
return( (mbedtls_rsa_context *) (pk).pk_ctx );
} }
#endif /* MBEDTLS_RSA_C */ #endif /* MBEDTLS_RSA_C */
@@ -148,8 +222,9 @@ static inline mbedtls_rsa_context *mbedtls_pk_rsa(const mbedtls_pk_context pk) {
* \warning You must make sure the PK context actually holds an EC context * \warning You must make sure the PK context actually holds an EC context
* before using this function! * before using this function!
*/ */
static inline mbedtls_ecp_keypair *mbedtls_pk_ec(const mbedtls_pk_context pk) { static inline mbedtls_ecp_keypair *mbedtls_pk_ec( const mbedtls_pk_context pk )
return ((mbedtls_ecp_keypair *)(pk).pk_ctx); {
return( (mbedtls_ecp_keypair *) (pk).pk_ctx );
} }
#endif /* MBEDTLS_ECP_C */ #endif /* MBEDTLS_ECP_C */
@@ -157,14 +232,14 @@ static inline mbedtls_ecp_keypair *mbedtls_pk_ec(const mbedtls_pk_context pk) {
/** /**
* \brief Types for RSA-alt abstraction * \brief Types for RSA-alt abstraction
*/ */
typedef int (*mbedtls_pk_rsa_alt_decrypt_func)(void *ctx, int mode, size_t *olen, typedef int (*mbedtls_pk_rsa_alt_decrypt_func)( void *ctx, int mode, size_t *olen,
const unsigned char *input, unsigned char *output, const unsigned char *input, unsigned char *output,
size_t output_max_len); size_t output_max_len );
typedef int (*mbedtls_pk_rsa_alt_sign_func)(void *ctx, typedef int (*mbedtls_pk_rsa_alt_sign_func)( void *ctx,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, int mode, mbedtls_md_type_t md_alg, unsigned int hashlen,
const unsigned char *hash, unsigned char *sig); const unsigned char *hash, unsigned char *sig );
typedef size_t (*mbedtls_pk_rsa_alt_key_len_func)(void *ctx); typedef size_t (*mbedtls_pk_rsa_alt_key_len_func)( void *ctx );
#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */
/** /**
@@ -174,23 +249,53 @@ typedef size_t (*mbedtls_pk_rsa_alt_key_len_func)(void *ctx);
* *
* \return The PK info associated with the type or NULL if not found. * \return The PK info associated with the type or NULL if not found.
*/ */
const mbedtls_pk_info_t *mbedtls_pk_info_from_type(mbedtls_pk_type_t pk_type); const mbedtls_pk_info_t *mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type );
/** /**
* \brief Initialize a mbedtls_pk_context (as NONE) * \brief Initialize a #mbedtls_pk_context (as NONE).
*
* \param ctx The context to initialize.
* This must not be \c NULL.
*/ */
void mbedtls_pk_init(mbedtls_pk_context *ctx); void mbedtls_pk_init( mbedtls_pk_context *ctx );
/** /**
* \brief Free a mbedtls_pk_context * \brief Free the components of a #mbedtls_pk_context.
*
* \param ctx The context to clear. It must have been initialized.
* If this is \c NULL, this function does nothing.
*
* \note For contexts that have been set up with
* mbedtls_pk_setup_opaque(), this does not free the underlying
* PSA key and you still need to call psa_destroy_key()
* independently if you want to destroy that key.
*/ */
void mbedtls_pk_free(mbedtls_pk_context *ctx); void mbedtls_pk_free( mbedtls_pk_context *ctx );
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
/**
* \brief Initialize a restart context
*
* \param ctx The context to initialize.
* This must not be \c NULL.
*/
void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx );
/**
* \brief Free the components of a restart context
*
* \param ctx The context to clear. It must have been initialized.
* If this is \c NULL, this function does nothing.
*/
void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx );
#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
/** /**
* \brief Initialize a PK context with the information given * \brief Initialize a PK context with the information given
* and allocates the type-specific PK subcontext. * and allocates the type-specific PK subcontext.
* *
* \param ctx Context to initialize. Must be empty (type NONE). * \param ctx Context to initialize. It must not have been set
* up yet (type #MBEDTLS_PK_NONE).
* \param info Information to use * \param info Information to use
* *
* \return 0 on success, * \return 0 on success,
@@ -200,13 +305,47 @@ void mbedtls_pk_free(mbedtls_pk_context *ctx);
* \note For contexts holding an RSA-alt key, use * \note For contexts holding an RSA-alt key, use
* \c mbedtls_pk_setup_rsa_alt() instead. * \c mbedtls_pk_setup_rsa_alt() instead.
*/ */
int mbedtls_pk_setup(mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info); int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info );
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/**
* \brief Initialize a PK context to wrap a PSA key.
*
* \note This function replaces mbedtls_pk_setup() for contexts
* that wrap a (possibly opaque) PSA key instead of
* storing and manipulating the key material directly.
*
* \param ctx The context to initialize. It must be empty (type NONE).
* \param key The PSA key to wrap, which must hold an ECC key pair
* (see notes below).
*
* \note The wrapped key must remain valid as long as the
* wrapping PK context is in use, that is at least between
* the point this function is called and the point
* mbedtls_pk_free() is called on this context. The wrapped
* key might then be independently used or destroyed.
*
* \note This function is currently only available for ECC key
* pairs (that is, ECC keys containing private key material).
* Support for other key types may be added later.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input
* (context already used, invalid key identifier).
* \return #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the key is not an
* ECC key pair.
* \return #MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure.
*/
int mbedtls_pk_setup_opaque( mbedtls_pk_context *ctx,
const psa_key_id_t key );
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
/** /**
* \brief Initialize an RSA-alt context * \brief Initialize an RSA-alt context
* *
* \param ctx Context to initialize. Must be empty (type NONE). * \param ctx Context to initialize. It must not have been set
* up yet (type #MBEDTLS_PK_NONE).
* \param key RSA key pointer * \param key RSA key pointer
* \param decrypt_func Decryption function * \param decrypt_func Decryption function
* \param sign_func Signing function * \param sign_func Signing function
@@ -217,46 +356,51 @@ int mbedtls_pk_setup(mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info);
* *
* \note This function replaces \c mbedtls_pk_setup() for RSA-alt. * \note This function replaces \c mbedtls_pk_setup() for RSA-alt.
*/ */
int mbedtls_pk_setup_rsa_alt(mbedtls_pk_context *ctx, void *key, int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key,
mbedtls_pk_rsa_alt_decrypt_func decrypt_func, mbedtls_pk_rsa_alt_decrypt_func decrypt_func,
mbedtls_pk_rsa_alt_sign_func sign_func, mbedtls_pk_rsa_alt_sign_func sign_func,
mbedtls_pk_rsa_alt_key_len_func key_len_func); mbedtls_pk_rsa_alt_key_len_func key_len_func );
#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */
/** /**
* \brief Get the size in bits of the underlying key * \brief Get the size in bits of the underlying key
* *
* \param ctx Context to use * \param ctx The context to query. It must have been initialized.
* *
* \return Key size in bits, or 0 on error * \return Key size in bits, or 0 on error
*/ */
size_t mbedtls_pk_get_bitlen(const mbedtls_pk_context *ctx); size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx );
/** /**
* \brief Get the length in bytes of the underlying key * \brief Get the length in bytes of the underlying key
* \param ctx Context to use *
* \param ctx The context to query. It must have been initialized.
* *
* \return Key length in bytes, or 0 on error * \return Key length in bytes, or 0 on error
*/ */
static inline size_t mbedtls_pk_get_len(const mbedtls_pk_context *ctx) { static inline size_t mbedtls_pk_get_len( const mbedtls_pk_context *ctx )
return ((mbedtls_pk_get_bitlen(ctx) + 7) / 8); {
return( ( mbedtls_pk_get_bitlen( ctx ) + 7 ) / 8 );
} }
/** /**
* \brief Tell if a context can do the operation given by type * \brief Tell if a context can do the operation given by type
* *
* \param ctx Context to test * \param ctx The context to query. It must have been initialized.
* \param type Target type * \param type The desired type.
* *
* \return 0 if context can't do the operations, * \return 1 if the context can do operations on the given type.
* 1 otherwise. * \return 0 if the context cannot do the operations on the given
* type. This is always the case for a context that has
* been initialized but not set up, or that has been
* cleared with mbedtls_pk_free().
*/ */
int mbedtls_pk_can_do(const mbedtls_pk_context *ctx, mbedtls_pk_type_t type); int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type );
/** /**
* \brief Verify signature (including padding if relevant). * \brief Verify signature (including padding if relevant).
* *
* \param ctx PK context to use * \param ctx The PK context to use. It must have been set up.
* \param md_alg Hash algorithm used (see notes) * \param md_alg Hash algorithm used (see notes)
* \param hash Hash of the message to sign * \param hash Hash of the message to sign
* \param hash_len Hash length or 0 (see notes) * \param hash_len Hash length or 0 (see notes)
@@ -277,9 +421,35 @@ int mbedtls_pk_can_do(const mbedtls_pk_context *ctx, mbedtls_pk_type_t type);
* *
* \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0 * \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0
*/ */
int mbedtls_pk_verify(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len, const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len); const unsigned char *sig, size_t sig_len );
/**
* \brief Restartable version of \c mbedtls_pk_verify()
*
* \note Performs the same job as \c mbedtls_pk_verify(), but can
* return early and restart according to the limit set with
* \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC
* operations. For RSA, same as \c mbedtls_pk_verify().
*
* \param ctx The PK context to use. It must have been set up.
* \param md_alg Hash algorithm used (see notes)
* \param hash Hash of the message to sign
* \param hash_len Hash length or 0 (see notes)
* \param sig Signature to verify
* \param sig_len Signature length
* \param rs_ctx Restart context (NULL to disable restart)
*
* \return See \c mbedtls_pk_verify(), or
* \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
* operations was reached: see \c mbedtls_ecp_set_max_ops().
*/
int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx,
mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len,
mbedtls_pk_restart_ctx *rs_ctx );
/** /**
* \brief Verify signature, with options. * \brief Verify signature, with options.
@@ -287,7 +457,7 @@ int mbedtls_pk_verify(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
* *
* \param type Signature type (inc. possible padding type) to verify * \param type Signature type (inc. possible padding type) to verify
* \param options Pointer to type-specific options, or NULL * \param options Pointer to type-specific options, or NULL
* \param ctx PK context to use * \param ctx The PK context to use. It must have been set up.
* \param md_alg Hash algorithm used (see notes) * \param md_alg Hash algorithm used (see notes)
* \param hash Hash of the message to sign * \param hash Hash of the message to sign
* \param hash_len Hash length or 0 (see notes) * \param hash_len Hash length or 0 (see notes)
@@ -310,20 +480,26 @@ int mbedtls_pk_verify(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
* to a mbedtls_pk_rsassa_pss_options structure, * to a mbedtls_pk_rsassa_pss_options structure,
* otherwise it must be NULL. * otherwise it must be NULL.
*/ */
int mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options, int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options,
mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len, const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len); const unsigned char *sig, size_t sig_len );
/** /**
* \brief Make signature, including padding if relevant. * \brief Make signature, including padding if relevant.
* *
* \param ctx PK context to use - must hold a private key * \param ctx The PK context to use. It must have been set up
* with a private key.
* \param md_alg Hash algorithm used (see notes) * \param md_alg Hash algorithm used (see notes)
* \param hash Hash of the message to sign * \param hash Hash of the message to sign
* \param hash_len Hash length or 0 (see notes) * \param hash_len Hash length or 0 (see notes)
* \param sig Place to write the signature * \param sig Place to write the signature.
* \param sig_len Number of bytes written * It must have enough room for the signature.
* #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough.
* You may use a smaller buffer if it is large enough
* given the key type.
* \param sig_len On successful return,
* the number of bytes written to \p sig.
* \param f_rng RNG function * \param f_rng RNG function
* \param p_rng RNG parameter * \param p_rng RNG parameter
* *
@@ -339,15 +515,51 @@ int mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options,
* \note For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0. * \note For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0.
* For ECDSA, md_alg may never be MBEDTLS_MD_NONE. * For ECDSA, md_alg may never be MBEDTLS_MD_NONE.
*/ */
int mbedtls_pk_sign(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len, const unsigned char *hash, size_t hash_len,
unsigned char *sig, size_t *sig_len, unsigned char *sig, size_t *sig_len,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
/**
* \brief Restartable version of \c mbedtls_pk_sign()
*
* \note Performs the same job as \c mbedtls_pk_sign(), but can
* return early and restart according to the limit set with
* \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC
* operations. For RSA, same as \c mbedtls_pk_sign().
*
* \param ctx The PK context to use. It must have been set up
* with a private key.
* \param md_alg Hash algorithm used (see notes for mbedtls_pk_sign())
* \param hash Hash of the message to sign
* \param hash_len Hash length or 0 (see notes for mbedtls_pk_sign())
* \param sig Place to write the signature.
* It must have enough room for the signature.
* #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough.
* You may use a smaller buffer if it is large enough
* given the key type.
* \param sig_len On successful return,
* the number of bytes written to \p sig.
* \param f_rng RNG function
* \param p_rng RNG parameter
* \param rs_ctx Restart context (NULL to disable restart)
*
* \return See \c mbedtls_pk_sign().
* \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
* operations was reached: see \c mbedtls_ecp_set_max_ops().
*/
int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx,
mbedtls_md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
unsigned char *sig, size_t *sig_len,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
mbedtls_pk_restart_ctx *rs_ctx );
/** /**
* \brief Decrypt message (including padding if relevant). * \brief Decrypt message (including padding if relevant).
* *
* \param ctx PK context to use - must hold a private key * \param ctx The PK context to use. It must have been set up
* with a private key.
* \param input Input to decrypt * \param input Input to decrypt
* \param ilen Input size * \param ilen Input size
* \param output Decrypted output * \param output Decrypted output
@@ -360,15 +572,15 @@ int mbedtls_pk_sign(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
* *
* \return 0 on success, or a specific error code. * \return 0 on success, or a specific error code.
*/ */
int mbedtls_pk_decrypt(mbedtls_pk_context *ctx, int mbedtls_pk_decrypt( mbedtls_pk_context *ctx,
const unsigned char *input, size_t ilen, const unsigned char *input, size_t ilen,
unsigned char *output, size_t *olen, size_t osize, unsigned char *output, size_t *olen, size_t osize,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
/** /**
* \brief Encrypt message (including padding if relevant). * \brief Encrypt message (including padding if relevant).
* *
* \param ctx PK context to use * \param ctx The PK context to use. It must have been set up.
* \param input Message to encrypt * \param input Message to encrypt
* \param ilen Message size * \param ilen Message size
* \param output Encrypted output * \param output Encrypted output
@@ -381,10 +593,10 @@ int mbedtls_pk_decrypt(mbedtls_pk_context *ctx,
* *
* \return 0 on success, or a specific error code. * \return 0 on success, or a specific error code.
*/ */
int mbedtls_pk_encrypt(mbedtls_pk_context *ctx, int mbedtls_pk_encrypt( mbedtls_pk_context *ctx,
const unsigned char *input, size_t ilen, const unsigned char *input, size_t ilen,
unsigned char *output, size_t *olen, size_t osize, unsigned char *output, size_t *olen, size_t osize,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng); int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
/** /**
* \brief Check if a public-private pair of keys matches. * \brief Check if a public-private pair of keys matches.
@@ -392,49 +604,64 @@ int mbedtls_pk_encrypt(mbedtls_pk_context *ctx,
* \param pub Context holding a public key. * \param pub Context holding a public key.
* \param prv Context holding a private (and public) key. * \param prv Context holding a private (and public) key.
* *
* \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA * \return \c 0 on success (keys were checked and match each other).
* \return #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the keys could not
* be checked - in that case they may or may not match.
* \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA if a context is invalid.
* \return Another non-zero value if the keys do not match.
*/ */
int mbedtls_pk_check_pair(const mbedtls_pk_context *pub, const mbedtls_pk_context *prv); int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv );
/** /**
* \brief Export debug information * \brief Export debug information
* *
* \param ctx Context to use * \param ctx The PK context to use. It must have been initialized.
* \param items Place to write debug items * \param items Place to write debug items
* *
* \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA * \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA
*/ */
int mbedtls_pk_debug(const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items); int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items );
/** /**
* \brief Access the type name * \brief Access the type name
* *
* \param ctx Context to use * \param ctx The PK context to use. It must have been initialized.
* *
* \return Type name on success, or "invalid PK" * \return Type name on success, or "invalid PK"
*/ */
const char *mbedtls_pk_get_name(const mbedtls_pk_context *ctx); const char * mbedtls_pk_get_name( const mbedtls_pk_context *ctx );
/** /**
* \brief Get the key type * \brief Get the key type
* *
* \param ctx Context to use * \param ctx The PK context to use. It must have been initialized.
* *
* \return Type on success, or MBEDTLS_PK_NONE * \return Type on success.
* \return #MBEDTLS_PK_NONE for a context that has not been set up.
*/ */
mbedtls_pk_type_t mbedtls_pk_get_type(const mbedtls_pk_context *ctx); mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx );
#if defined(MBEDTLS_PK_PARSE_C) #if defined(MBEDTLS_PK_PARSE_C)
/** \ingroup pk_module */ /** \ingroup pk_module */
/** /**
* \brief Parse a private key in PEM or DER format * \brief Parse a private key in PEM or DER format
* *
* \param ctx key to be initialized * \param ctx The PK context to fill. It must have been initialized
* \param key input buffer * but not set up.
* \param keylen size of the buffer * \param key Input buffer to parse.
* (including the terminating null byte for PEM data) * The buffer must contain the input exactly, with no
* \param pwd password for decryption (optional) * extra trailing material. For PEM, the buffer must
* \param pwdlen size of the password * contain a null-terminated string.
* \param keylen Size of \b key in bytes.
* For PEM data, this includes the terminating null byte,
* so \p keylen must be equal to `strlen(key) + 1`.
* \param pwd Optional password for decryption.
* Pass \c NULL if expecting a non-encrypted key.
* Pass a string of \p pwdlen bytes if expecting an encrypted
* key; a non-encrypted key will also be accepted.
* The empty password is not supported.
* \param pwdlen Size of the password in bytes.
* Ignored if \p pwd is \c NULL.
* *
* \note On entry, ctx must be empty, either freshly initialised * \note On entry, ctx must be empty, either freshly initialised
* with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a
@@ -444,18 +671,23 @@ mbedtls_pk_type_t mbedtls_pk_get_type(const mbedtls_pk_context *ctx);
* *
* \return 0 if successful, or a specific PK or PEM error code * \return 0 if successful, or a specific PK or PEM error code
*/ */
int mbedtls_pk_parse_key(mbedtls_pk_context *ctx, int mbedtls_pk_parse_key( mbedtls_pk_context *ctx,
const unsigned char *key, size_t keylen, const unsigned char *key, size_t keylen,
const unsigned char *pwd, size_t pwdlen); const unsigned char *pwd, size_t pwdlen );
/** \ingroup pk_module */ /** \ingroup pk_module */
/** /**
* \brief Parse a public key in PEM or DER format * \brief Parse a public key in PEM or DER format
* *
* \param ctx key to be initialized * \param ctx The PK context to fill. It must have been initialized
* \param key input buffer * but not set up.
* \param keylen size of the buffer * \param key Input buffer to parse.
* (including the terminating null byte for PEM data) * The buffer must contain the input exactly, with no
* extra trailing material. For PEM, the buffer must
* contain a null-terminated string.
* \param keylen Size of \b key in bytes.
* For PEM data, this includes the terminating null byte,
* so \p keylen must be equal to `strlen(key) + 1`.
* *
* \note On entry, ctx must be empty, either freshly initialised * \note On entry, ctx must be empty, either freshly initialised
* with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a
@@ -465,17 +697,22 @@ int mbedtls_pk_parse_key(mbedtls_pk_context *ctx,
* *
* \return 0 if successful, or a specific PK or PEM error code * \return 0 if successful, or a specific PK or PEM error code
*/ */
int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx, int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx,
const unsigned char *key, size_t keylen); const unsigned char *key, size_t keylen );
#if defined(MBEDTLS_FS_IO) #if defined(MBEDTLS_FS_IO)
/** \ingroup pk_module */ /** \ingroup pk_module */
/** /**
* \brief Load and parse a private key * \brief Load and parse a private key
* *
* \param ctx key to be initialized * \param ctx The PK context to fill. It must have been initialized
* but not set up.
* \param path filename to read the private key from * \param path filename to read the private key from
* \param password password to decrypt the file (can be NULL) * \param password Optional password to decrypt the file.
* Pass \c NULL if expecting a non-encrypted key.
* Pass a null-terminated string if expecting an encrypted
* key; a non-encrypted key will also be accepted.
* The empty password is not supported.
* *
* \note On entry, ctx must be empty, either freshly initialised * \note On entry, ctx must be empty, either freshly initialised
* with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a
@@ -485,14 +722,15 @@ int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx,
* *
* \return 0 if successful, or a specific PK or PEM error code * \return 0 if successful, or a specific PK or PEM error code
*/ */
int mbedtls_pk_parse_keyfile(mbedtls_pk_context *ctx, int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx,
const char *path, const char *password); const char *path, const char *password );
/** \ingroup pk_module */ /** \ingroup pk_module */
/** /**
* \brief Load and parse a public key * \brief Load and parse a public key
* *
* \param ctx key to be initialized * \param ctx The PK context to fill. It must have been initialized
* but not set up.
* \param path filename to read the public key from * \param path filename to read the public key from
* *
* \note On entry, ctx must be empty, either freshly initialised * \note On entry, ctx must be empty, either freshly initialised
@@ -504,7 +742,7 @@ int mbedtls_pk_parse_keyfile(mbedtls_pk_context *ctx,
* *
* \return 0 if successful, or a specific PK or PEM error code * \return 0 if successful, or a specific PK or PEM error code
*/ */
int mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path); int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path );
#endif /* MBEDTLS_FS_IO */ #endif /* MBEDTLS_FS_IO */
#endif /* MBEDTLS_PK_PARSE_C */ #endif /* MBEDTLS_PK_PARSE_C */
@@ -515,14 +753,14 @@ int mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path);
* return value to determine where you should start * return value to determine where you should start
* using the buffer * using the buffer
* *
* \param ctx private to write away * \param ctx PK context which must contain a valid private key.
* \param buf buffer to write to * \param buf buffer to write to
* \param size size of the buffer * \param size size of the buffer
* *
* \return length of data written if successful, or a specific * \return length of data written if successful, or a specific
* error code * error code
*/ */
int mbedtls_pk_write_key_der(mbedtls_pk_context *ctx, unsigned char *buf, size_t size); int mbedtls_pk_write_key_der( mbedtls_pk_context *ctx, unsigned char *buf, size_t size );
/** /**
* \brief Write a public key to a SubjectPublicKeyInfo DER structure * \brief Write a public key to a SubjectPublicKeyInfo DER structure
@@ -530,37 +768,39 @@ int mbedtls_pk_write_key_der(mbedtls_pk_context *ctx, unsigned char *buf, size_t
* return value to determine where you should start * return value to determine where you should start
* using the buffer * using the buffer
* *
* \param ctx public key to write away * \param ctx PK context which must contain a valid public or private key.
* \param buf buffer to write to * \param buf buffer to write to
* \param size size of the buffer * \param size size of the buffer
* *
* \return length of data written if successful, or a specific * \return length of data written if successful, or a specific
* error code * error code
*/ */
int mbedtls_pk_write_pubkey_der(mbedtls_pk_context *ctx, unsigned char *buf, size_t size); int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *ctx, unsigned char *buf, size_t size );
#if defined(MBEDTLS_PEM_WRITE_C) #if defined(MBEDTLS_PEM_WRITE_C)
/** /**
* \brief Write a public key to a PEM string * \brief Write a public key to a PEM string
* *
* \param ctx public key to write away * \param ctx PK context which must contain a valid public or private key.
* \param buf buffer to write to * \param buf Buffer to write to. The output includes a
* \param size size of the buffer * terminating null byte.
* \param size Size of the buffer in bytes.
* *
* \return 0 if successful, or a specific error code * \return 0 if successful, or a specific error code
*/ */
int mbedtls_pk_write_pubkey_pem(mbedtls_pk_context *ctx, unsigned char *buf, size_t size); int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *ctx, unsigned char *buf, size_t size );
/** /**
* \brief Write a private key to a PKCS#1 or SEC1 PEM string * \brief Write a private key to a PKCS#1 or SEC1 PEM string
* *
* \param ctx private to write away * \param ctx PK context which must contain a valid private key.
* \param buf buffer to write to * \param buf Buffer to write to. The output includes a
* \param size size of the buffer * terminating null byte.
* \param size Size of the buffer in bytes.
* *
* \return 0 if successful, or a specific error code * \return 0 if successful, or a specific error code
*/ */
int mbedtls_pk_write_key_pem(mbedtls_pk_context *ctx, unsigned char *buf, size_t size); int mbedtls_pk_write_key_pem( mbedtls_pk_context *ctx, unsigned char *buf, size_t size );
#endif /* MBEDTLS_PEM_WRITE_C */ #endif /* MBEDTLS_PEM_WRITE_C */
#endif /* MBEDTLS_PK_WRITE_C */ #endif /* MBEDTLS_PK_WRITE_C */
@@ -575,12 +815,13 @@ int mbedtls_pk_write_key_pem(mbedtls_pk_context *ctx, unsigned char *buf, size_t
* *
* \param p the position in the ASN.1 data * \param p the position in the ASN.1 data
* \param end end of the buffer * \param end end of the buffer
* \param pk the key to fill * \param pk The PK context to fill. It must have been initialized
* but not set up.
* *
* \return 0 if successful, or a specific PK error code * \return 0 if successful, or a specific PK error code
*/ */
int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end, int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end,
mbedtls_pk_context *pk); mbedtls_pk_context *pk );
#endif /* MBEDTLS_PK_PARSE_C */ #endif /* MBEDTLS_PK_PARSE_C */
#if defined(MBEDTLS_PK_WRITE_C) #if defined(MBEDTLS_PK_WRITE_C)
@@ -590,12 +831,12 @@ int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end,
* *
* \param p reference to current position pointer * \param p reference to current position pointer
* \param start start of the buffer (for bounds-checking) * \param start start of the buffer (for bounds-checking)
* \param key public key to write away * \param key PK context which must contain a valid public or private key.
* *
* \return the length written or a negative error code * \return the length written or a negative error code
*/ */
int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start, int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start,
const mbedtls_pk_context *key); const mbedtls_pk_context *key );
#endif /* MBEDTLS_PK_WRITE_C */ #endif /* MBEDTLS_PK_WRITE_C */
/* /*
@@ -603,9 +844,35 @@ int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start,
* know you do. * know you do.
*/ */
#if defined(MBEDTLS_FS_IO) #if defined(MBEDTLS_FS_IO)
int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n); int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n );
#endif #endif
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/**
* \brief Turn an EC key into an opaque one.
*
* \warning This is a temporary utility function for tests. It might
* change or be removed at any time without notice.
*
* \note Only ECDSA keys are supported so far. Signing with the
* specified hash is the only allowed use of that key.
*
* \param pk Input: the EC key to import to a PSA key.
* Output: a PK context wrapping that PSA key.
* \param key Output: a PSA key identifier.
* It's the caller's responsibility to call
* psa_destroy_key() on that key identifier after calling
* mbedtls_pk_free() on the PK context.
* \param hash_alg The hash algorithm to allow for use with that key.
*
* \return \c 0 if successful.
* \return An Mbed TLS error code otherwise.
*/
int mbedtls_pk_wrap_as_opaque( mbedtls_pk_context *pk,
psa_key_id_t *key,
psa_algorithm_t hash_alg );
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

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