<commit_before>/*
 *  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};

/*
 * 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] ^= BYTE_0( t >> ( ( sizeof( t ) - 1 - i ) * 8 ) );
    }
}

/*
 * KW-AE as defined in SP 800-38F section 6.2
 * KWP-AE as defined in SP 800-38F section 6.3
 */
int mbedtls_nist_kw_wrap( mbedtls_nist_kw_context *ctx,
                          mbedtls_nist_kw_mode_t mode,
                          const unsigned char *input, size_t in_len,
                          unsigned char *output, size_t *out_len, size_t out_size )
{
    int ret = 0;
    size_t semiblocks = 0;
    size_t s;
    size_t olen, padlen = 0;
    uint64_t t = 0;
    unsigned char outbuff[KW_SEMIBLOCK_LENGTH * 2];
    unsigned char inbuff[KW_SEMIBLOCK_LENGTH * 2];

    *out_len = 0;
    /*
     * Generate the String to work on
     */
    if( mode == MBEDTLS_KW_MODE_KW )
    {
        if( out_size < in_len + KW_SEMIBLOCK_LENGTH )
        {<commit_msg>Undo use of BYTE_x macro<commit_after>/*
 *  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};

/*
 * 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];

    *out_len = 0;
    /*
     * Generate the String to work on
     */
    if( mode == MBEDTLS_KW_MODE_KW )
    {
        if( out_size < in_len + KW_SEMIBLOCK_LENGTH )
        {
{'fraction_non_alphanumeric': 0.08978040540540541, 'fraction_numerical': 0.022635135135135136, 'mean_word_length': 2.4795768439612105, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 23, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 22, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5477751', 'n_tokens_mistral': 4212, 'n_tokens_neox': 3900, 'n_words': 1174}