<commit_before>/*
 *  PSA cipher driver entry points
 */
/*
 *  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_PSA_CRYPTO_C)

#include <psa_crypto_cipher.h>
#include "psa_crypto_core.h"
#include "psa_crypto_random_impl.h"

#include "mbedtls/cipher.h"
#include "mbedtls/error.h"

#include <string.h>

#if ( defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) || \
      ( defined(PSA_CRYPTO_DRIVER_TEST) && \
        defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DES) ) )
#define BUILTIN_KEY_TYPE_DES  1
#endif

#if ( defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \
      ( defined(PSA_CRYPTO_DRIVER_TEST) && \
        defined(MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING) ) )
#define BUILTIN_ALG_CBC_NO_PADDING  1
#endif

#if ( defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7) || \
      ( defined(PSA_CRYPTO_DRIVER_TEST) && \
        defined(MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7) ) )
#define BUILTIN_ALG_CBC_PKCS7  1
#endif

#if ( defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20) || \
      ( defined(PSA_CRYPTO_DRIVER_TEST) && \
        defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_CHACHA20) ) )
#define BUILTIN_KEY_TYPE_CHACHA20  1
#endif

const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa(
    psa_algorithm_t alg,
    psa_key_type_t key_type,
    size_t key_bits,
    mbedtls_cipher_id_t* cipher_id )
{
    mbedtls_cipher_mode_t mode;
    mbedtls_cipher_id_t cipher_id_tmp;

    if( PSA_ALG_IS_AEAD( alg ) )
        alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, 0 );

    if( PSA_ALG_IS_CIPHER( alg ) || PSA_ALG_IS_AEAD( alg ) )
    {
        switch( alg )
        {
            case PSA_ALG_STREAM_CIPHER:
                mode = MBEDTLS_MODE_STREAM;
                break;
            case PSA_ALG_CTR:
                mode = MBEDTLS_MODE_CTR;
                break;
            case PSA_ALG_CFB:
                mode = MBEDTLS_MODE_CFB;
                break;
            case PSA_ALG_OFB:
                mode = MBEDTLS_MODE_OFB;
                break;
            case PSA_ALG_ECB_NO_PADDING:
                mode = MBEDTLS_MODE_ECB;
                break;
            case PSA_ALG_CBC_NO_PADDING:
                mode = MBEDTLS_MODE_CBC;
                break;
            case PSA_ALG_CBC_PKCS7:
                mode = MBEDTLS_MODE_CBC;
                break;
            case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 0 ):
                mode = MBEDTLS_MODE_CCM;
                break;
            case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 0 ):
                mode = MBEDTLS_MODE_GCM;
                break;
            case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CHACHA20_POLY1305, 0 ):
                mode = MBEDTLS_MODE_CHACHAPOLY;
                break;
            default:
                return( NULL );
        }
    }
    else if( alg == PSA_ALG_CMAC )
        mode = MBEDTLS_MODE_ECB;
    else
        return( NULL );

    switch( key_type )
    {
        case PSA_KEY_TYPE_AES:
            cipher_id_tmp = MBEDTLS_CIPHER_ID_AES;
            break;
        case PSA_KEY_TYPE_DES:
            /* key_bits is 64 for Single-DES, 128 for two-key Triple-DES,
             * and 192 for three-key Triple-DES. */
            if( key_bits == 64 )
                cipher_id_tmp = MBEDTLS_CIPHER_ID_DES;
            else
                cipher_id_tmp = MBEDTLS_CIPHER_ID_3DES;
            /* mbedtls doesn't recognize two-key Triple-DES as an algorithm,
             * but two-key Triple-DES is functionally three-key Triple-DES
             * with K1=K3, so that's how we present it to mbedtls. */
            if( key_bits == 128 )
                key_bits = 192;
            break;
        case PSA_KEY_TYPE_CAMELLIA:
            cipher_id_tmp = MBEDTLS_CIPHER_ID_CAMELLIA;
            break;
        case PSA_KEY_TYPE_ARC4:
            cipher_id_tmp = MBEDTLS_CIPHER_ID_ARC4;
            break;
        case PSA_KEY_TYPE_CHACHA20:
            cipher_id_tmp = MBEDTLS_CIPHER_ID_CHACHA20;
            break;
        default:
            return( NULL );
    }
    if( cipher_id != NULL )
        *cipher_id = cipher_id_tmp;

    return( mbedtls_cipher_info_from_values( cipher_id_tmp,
                                             (int) key_bits, mode ) );
}

#if defined(MBEDTLS_PSA_BUILTIN_CIPHER) || defined(PSA_CRYPTO_DRIVER_TEST)

static psa_status_t cipher_setup(
    mbedtls_psa_cipher_operation_t *operation,
    const psa_key_attributes_t *attributes,
    const uint8_t *key_buffer, size_t key_buffer_size,
    psa_algorithm_t alg,
    mbedtls_operation_t cipher_operation )
{
    int ret = 0;
    size_t key_bits;
    const mbedtls_cipher_info_t *cipher_info = NULL;
    psa_key_type_t key_type = attributes->core.type;

    (void)key_buffer_size;

    /* Proceed with initializing an mbed TLS cipher context if no driver is
     * available for the given algorithm & key. */
    mbedtls_cipher_init( &operation->cipher );

    operation->alg = alg;
    key_bits = attributes->core.bits;
    cipher_info = mbedtls_cipher_info_from_psa( alg, key_type,
                                                key_bits, NULL );
    if( cipher_info == NULL )
        return( PSA_ERROR_NOT_SUPPORTED );

    ret = mbedtls_cipher_setup( &operation->cipher, cipher_info );
    if( ret != 0 )
        goto exit;

#if defined(BUILTIN_KEY_TYPE_DES)
    if( key_type == PSA_KEY_TYPE_DES && key_bits == 128 )
    {
        /* Two-key Triple-DES is 3-key Triple-DES with K1=K3 */
        uint8_t keys[24];
        memcpy( keys, key_buffer, 16 );
        memcpy( keys + 16, key_buffer, 8 );
        ret = mbedtls_cipher_setkey( &operation->cipher,
                                     keys,
                                     192, cipher_operation );
    }
    else
#endif
    {
        ret = mbedtls_cipher_setkey( &operation->cipher, key_buffer,
                                     (int) key_bits, cipher_operation );
    }
    if( ret != 0 )
        goto exit;

#if defined(BUILTIN_ALG_CBC_NO_PADDING) || \
    defined(BUILTIN_ALG_CBC_PKCS7)
    switch( alg )
    {
        case PSA_ALG_CBC_NO_PADDING:
            ret = mbedtls_cipher_set_padding_mode( &operation->cipher,
                                                   MBEDTLS_PADDING_NONE );
            break;
        case PSA_ALG_CBC_PKCS7:
            ret = mbedtls_cipher_set_padding_mode( &operation->cipher,
                                                   MBEDTLS_PADDING_PKCS7 );
            break;
        default:
            /* The algorithm doesn't involve padding. */
            ret = 0;
            break;
    }
    if( ret != 0 )
        goto exit;
#endif /* BUILTIN_ALG_CBC_NO_PADDING || BUILTIN_ALG_CBC_PKCS7 */

    operation->block_size = ( PSA_ALG_IS_STREAM_CIPHER( alg ) ? 1 :
                              PSA_BLOCK_CIPHER_BLOCK_LENGTH( key_type ) );
    if( ( alg & PSA_ALG_CIPHER_FROM_BLOCK_FLAG ) != 0 &&
        alg != PSA_ALG_ECB_NO_PADDING )
    {
        operation->iv_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH( key_type );
    }
#if defined(BUILTIN_KEY_TYPE_CHACHA20)
    else
    if( ( alg == PSA_ALG_STREAM_CIPHER ) &&
        ( key_type == PSA_KEY_TYPE_CHACHA20 ) )
        operation->iv_size = 12;
#endif

exit:
    return( mbedtls_to_psa_error( ret ) );
}

static psa_status_t cipher_encrypt_setup(
    mbedtls_psa_cipher_operation_t *operation,
    const psa_key_attributes_t *attributes,
    const uint8_t *key_buffer, size_t key_buffer_size,
    psa_algorithm_t alg )
{
    return( cipher_setup( operation, attributes,
                          key_buffer, key_buffer_size,
                          alg, MBEDTLS_ENCRYPT ) );
}

static psa_status_t cipher_decrypt_setup(
    mbedtls_psa_cipher_operation_t *operation,
    const psa_key_attributes_t *attributes,
    const uint8_t *key_buffer, size_t key_buffer_size,
    psa_algorithm_t alg )
{
    return( cipher_setup( operation, attributes,
                          key_buffer, key_buffer_size,
                          alg, MBEDTLS_DECRYPT ) );
}

static psa_status_t cipher_set_iv( mbedtls_psa_cipher_operation_t *operation,
                            const uint8_t *iv, size_t iv_length )
{
    if( iv_length != operation->iv_size )
        return( PSA_ERROR_INVALID_ARGUMENT );

    return( mbedtls_to_psa_error(
                mbedtls_cipher_set_iv( &operation->cipher,
                                       iv, iv_length ) ) );
}

static psa_status_t cipher_generate_iv(
    mbedtls_psa_cipher_operation_t *operation,
    uint8_t *iv, size_t iv_size, size_t *iv_length )
{
    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;

    if( iv_size < operation->iv_size )
        return( PSA_ERROR_BUFFER_TOO_SMALL );

    ret = mbedtls_psa_get_random( MBEDTLS_PSA_RANDOM_STATE,
                                  iv, operation->iv_size );
    if( ret != 0 )
        return( mbedtls_to_psa_error( ret ) );

    *iv_length = operation->iv_size;

    return( cipher_set_iv( operation, iv, *iv_length ) );
}

/* Process input for which the algorithm is set to ECB mode. This requires<commit_msg>psa: cipher: Use psa_generate_random to generate IVs<commit_after>/*
 *  PSA cipher driver entry points
 */
/*
 *  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_PSA_CRYPTO_C)

#include <psa_crypto_cipher.h>
#include "psa_crypto_core.h"
#include "psa_crypto_random_impl.h"

#include "mbedtls/cipher.h"
#include "mbedtls/error.h"

#include <string.h>

#if ( defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) || \
      ( defined(PSA_CRYPTO_DRIVER_TEST) && \
        defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DES) ) )
#define BUILTIN_KEY_TYPE_DES  1
#endif

#if ( defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \
      ( defined(PSA_CRYPTO_DRIVER_TEST) && \
        defined(MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING) ) )
#define BUILTIN_ALG_CBC_NO_PADDING  1
#endif

#if ( defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7) || \
      ( defined(PSA_CRYPTO_DRIVER_TEST) && \
        defined(MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7) ) )
#define BUILTIN_ALG_CBC_PKCS7  1
#endif

#if ( defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20) || \
      ( defined(PSA_CRYPTO_DRIVER_TEST) && \
        defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_CHACHA20) ) )
#define BUILTIN_KEY_TYPE_CHACHA20  1
#endif

const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa(
    psa_algorithm_t alg,
    psa_key_type_t key_type,
    size_t key_bits,
    mbedtls_cipher_id_t* cipher_id )
{
    mbedtls_cipher_mode_t mode;
    mbedtls_cipher_id_t cipher_id_tmp;

    if( PSA_ALG_IS_AEAD( alg ) )
        alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG( alg, 0 );

    if( PSA_ALG_IS_CIPHER( alg ) || PSA_ALG_IS_AEAD( alg ) )
    {
        switch( alg )
        {
            case PSA_ALG_STREAM_CIPHER:
                mode = MBEDTLS_MODE_STREAM;
                break;
            case PSA_ALG_CTR:
                mode = MBEDTLS_MODE_CTR;
                break;
            case PSA_ALG_CFB:
                mode = MBEDTLS_MODE_CFB;
                break;
            case PSA_ALG_OFB:
                mode = MBEDTLS_MODE_OFB;
                break;
            case PSA_ALG_ECB_NO_PADDING:
                mode = MBEDTLS_MODE_ECB;
                break;
            case PSA_ALG_CBC_NO_PADDING:
                mode = MBEDTLS_MODE_CBC;
                break;
            case PSA_ALG_CBC_PKCS7:
                mode = MBEDTLS_MODE_CBC;
                break;
            case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CCM, 0 ):
                mode = MBEDTLS_MODE_CCM;
                break;
            case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_GCM, 0 ):
                mode = MBEDTLS_MODE_GCM;
                break;
            case PSA_ALG_AEAD_WITH_SHORTENED_TAG( PSA_ALG_CHACHA20_POLY1305, 0 ):
                mode = MBEDTLS_MODE_CHACHAPOLY;
                break;
            default:
                return( NULL );
        }
    }
    else if( alg == PSA_ALG_CMAC )
        mode = MBEDTLS_MODE_ECB;
    else
        return( NULL );

    switch( key_type )
    {
        case PSA_KEY_TYPE_AES:
            cipher_id_tmp = MBEDTLS_CIPHER_ID_AES;
            break;
        case PSA_KEY_TYPE_DES:
            /* key_bits is 64 for Single-DES, 128 for two-key Triple-DES,
             * and 192 for three-key Triple-DES. */
            if( key_bits == 64 )
                cipher_id_tmp = MBEDTLS_CIPHER_ID_DES;
            else
                cipher_id_tmp = MBEDTLS_CIPHER_ID_3DES;
            /* mbedtls doesn't recognize two-key Triple-DES as an algorithm,
             * but two-key Triple-DES is functionally three-key Triple-DES
             * with K1=K3, so that's how we present it to mbedtls. */
            if( key_bits == 128 )
                key_bits = 192;
            break;
        case PSA_KEY_TYPE_CAMELLIA:
            cipher_id_tmp = MBEDTLS_CIPHER_ID_CAMELLIA;
            break;
        case PSA_KEY_TYPE_ARC4:
            cipher_id_tmp = MBEDTLS_CIPHER_ID_ARC4;
            break;
        case PSA_KEY_TYPE_CHACHA20:
            cipher_id_tmp = MBEDTLS_CIPHER_ID_CHACHA20;
            break;
        default:
            return( NULL );
    }
    if( cipher_id != NULL )
        *cipher_id = cipher_id_tmp;

    return( mbedtls_cipher_info_from_values( cipher_id_tmp,
                                             (int) key_bits, mode ) );
}

#if defined(MBEDTLS_PSA_BUILTIN_CIPHER) || defined(PSA_CRYPTO_DRIVER_TEST)

static psa_status_t cipher_setup(
    mbedtls_psa_cipher_operation_t *operation,
    const psa_key_attributes_t *attributes,
    const uint8_t *key_buffer, size_t key_buffer_size,
    psa_algorithm_t alg,
    mbedtls_operation_t cipher_operation )
{
    int ret = 0;
    size_t key_bits;
    const mbedtls_cipher_info_t *cipher_info = NULL;
    psa_key_type_t key_type = attributes->core.type;

    (void)key_buffer_size;

    /* Proceed with initializing an mbed TLS cipher context if no driver is
     * available for the given algorithm & key. */
    mbedtls_cipher_init( &operation->cipher );

    operation->alg = alg;
    key_bits = attributes->core.bits;
    cipher_info = mbedtls_cipher_info_from_psa( alg, key_type,
                                                key_bits, NULL );
    if( cipher_info == NULL )
        return( PSA_ERROR_NOT_SUPPORTED );

    ret = mbedtls_cipher_setup( &operation->cipher, cipher_info );
    if( ret != 0 )
        goto exit;

#if defined(BUILTIN_KEY_TYPE_DES)
    if( key_type == PSA_KEY_TYPE_DES && key_bits == 128 )
    {
        /* Two-key Triple-DES is 3-key Triple-DES with K1=K3 */
        uint8_t keys[24];
        memcpy( keys, key_buffer, 16 );
        memcpy( keys + 16, key_buffer, 8 );
        ret = mbedtls_cipher_setkey( &operation->cipher,
                                     keys,
                                     192, cipher_operation );
    }
    else
#endif
    {
        ret = mbedtls_cipher_setkey( &operation->cipher, key_buffer,
                                     (int) key_bits, cipher_operation );
    }
    if( ret != 0 )
        goto exit;

#if defined(BUILTIN_ALG_CBC_NO_PADDING) || \
    defined(BUILTIN_ALG_CBC_PKCS7)
    switch( alg )
    {
        case PSA_ALG_CBC_NO_PADDING:
            ret = mbedtls_cipher_set_padding_mode( &operation->cipher,
                                                   MBEDTLS_PADDING_NONE );
            break;
        case PSA_ALG_CBC_PKCS7:
            ret = mbedtls_cipher_set_padding_mode( &operation->cipher,
                                                   MBEDTLS_PADDING_PKCS7 );
            break;
        default:
            /* The algorithm doesn't involve padding. */
            ret = 0;
            break;
    }
    if( ret != 0 )
        goto exit;
#endif /* BUILTIN_ALG_CBC_NO_PADDING || BUILTIN_ALG_CBC_PKCS7 */

    operation->block_size = ( PSA_ALG_IS_STREAM_CIPHER( alg ) ? 1 :
                              PSA_BLOCK_CIPHER_BLOCK_LENGTH( key_type ) );
    if( ( alg & PSA_ALG_CIPHER_FROM_BLOCK_FLAG ) != 0 &&
        alg != PSA_ALG_ECB_NO_PADDING )
    {
        operation->iv_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH( key_type );
    }
#if defined(BUILTIN_KEY_TYPE_CHACHA20)
    else
    if( ( alg == PSA_ALG_STREAM_CIPHER ) &&
        ( key_type == PSA_KEY_TYPE_CHACHA20 ) )
        operation->iv_size = 12;
#endif

exit:
    return( mbedtls_to_psa_error( ret ) );
}

static psa_status_t cipher_encrypt_setup(
    mbedtls_psa_cipher_operation_t *operation,
    const psa_key_attributes_t *attributes,
    const uint8_t *key_buffer, size_t key_buffer_size,
    psa_algorithm_t alg )
{
    return( cipher_setup( operation, attributes,
                          key_buffer, key_buffer_size,
                          alg, MBEDTLS_ENCRYPT ) );
}

static psa_status_t cipher_decrypt_setup(
    mbedtls_psa_cipher_operation_t *operation,
    const psa_key_attributes_t *attributes,
    const uint8_t *key_buffer, size_t key_buffer_size,
    psa_algorithm_t alg )
{
    return( cipher_setup( operation, attributes,
                          key_buffer, key_buffer_size,
                          alg, MBEDTLS_DECRYPT ) );
}

static psa_status_t cipher_set_iv( mbedtls_psa_cipher_operation_t *operation,
                            const uint8_t *iv, size_t iv_length )
{
    if( iv_length != operation->iv_size )
        return( PSA_ERROR_INVALID_ARGUMENT );

    return( mbedtls_to_psa_error(
                mbedtls_cipher_set_iv( &operation->cipher,
                                       iv, iv_length ) ) );
}

static psa_status_t cipher_generate_iv(
    mbedtls_psa_cipher_operation_t *operation,
    uint8_t *iv, size_t iv_size, size_t *iv_length )
{
    int status = PSA_ERROR_CORRUPTION_DETECTED;

    if( iv_size < operation->iv_size )
        return( PSA_ERROR_BUFFER_TOO_SMALL );

    status = psa_generate_random( iv, operation->iv_size );
    if( status != PSA_SUCCESS )
        return( status );

    *iv_length = operation->iv_size;

    return( cipher_set_iv( operation, iv, *iv_length ) );
}

/* Process input for which the algorithm is set to ECB mode. This requires
{'fraction_non_alphanumeric': 0.07642744892613934, 'fraction_numerical': 0.009900471451021478, 'mean_word_length': 2.176539101497504, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 29, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6930774', 'n_tokens_mistral': 7036, 'n_tokens_neox': 6519, 'n_words': 1267}