/* * PSA hashing layer on top of Mbed TLS software crypto */ /* * 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 #include "psa_crypto_core.h" #include "psa_crypto_hash.h" #include #include /* Use builtin defines specific to this compilation unit, since the test driver * relies on the software driver. */ #if (defined(MBEDTLS_PSA_BUILTIN_ALG_MD2) || \ (defined(PSA_CRYPTO_DRIVER_TEST) && defined(MBEDTLS_PSA_ACCEL_ALG_MD2))) #define BUILTIN_ALG_MD2 1 #endif #if (defined(MBEDTLS_PSA_BUILTIN_ALG_MD4) || \ (defined(PSA_CRYPTO_DRIVER_TEST) && defined(MBEDTLS_PSA_ACCEL_ALG_MD4))) #define BUILTIN_ALG_MD4 1 #endif #if (defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) || \ (defined(PSA_CRYPTO_DRIVER_TEST) && defined(MBEDTLS_PSA_ACCEL_ALG_MD5))) #define BUILTIN_ALG_MD5 1 #endif #if (defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) || \ (defined(PSA_CRYPTO_DRIVER_TEST) && defined(MBEDTLS_PSA_ACCEL_ALG_RIPEMD160))) #define BUILTIN_ALG_RIPEMD160 1 #endif #if (defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1) || \ (defined(PSA_CRYPTO_DRIVER_TEST) && defined(MBEDTLS_PSA_ACCEL_ALG_SHA_1))) #define BUILTIN_ALG_SHA_1 1 #endif #if (defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) || \ (defined(PSA_CRYPTO_DRIVER_TEST) && defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224))) #define BUILTIN_ALG_SHA_224 1 #endif #if (defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) || \ (defined(PSA_CRYPTO_DRIVER_TEST) && defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256))) #define BUILTIN_ALG_SHA_256 1 #endif #if (defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) || \ (defined(PSA_CRYPTO_DRIVER_TEST) && defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384))) #define BUILTIN_ALG_SHA_384 1 #endif #if (defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) || \ (defined(PSA_CRYPTO_DRIVER_TEST) && defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512))) #define BUILTIN_ALG_SHA_512 1 #endif #if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || \ defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) const mbedtls_md_info_t *mbedtls_md_info_from_psa(psa_algorithm_t alg) { switch (alg) { #if defined(MBEDTLS_MD2_C) case PSA_ALG_MD2: return (&mbedtls_md2_info); #endif #if defined(MBEDTLS_MD4_C) case PSA_ALG_MD4: return (&mbedtls_md4_info); #endif #if defined(MBEDTLS_MD5_C) case PSA_ALG_MD5: return (&mbedtls_md5_info); #endif #if defined(MBEDTLS_RIPEMD160_C) case PSA_ALG_RIPEMD160: return (&mbedtls_ripemd160_info); #endif #if defined(MBEDTLS_SHA1_C) case PSA_ALG_SHA_1: return (&mbedtls_sha1_info); #endif #if defined(MBEDTLS_SHA224_C) case PSA_ALG_SHA_224: return (&mbedtls_sha224_info); #endif #if defined(MBEDTLS_SHA256_C) case PSA_ALG_SHA_256: return (&mbedtls_sha256_info); #endif #if defined(MBEDTLS_SHA384_C) case PSA_ALG_SHA_384: return (&mbedtls_sha384_info); #endif #if defined(MBEDTLS_SHA512_C) case PSA_ALG_SHA_512: return (&mbedtls_sha512_info); #endif default: return (NULL); } } #endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */ /* Implement the PSA driver hash interface on top of mbed TLS if either the * software driver or the test driver requires it. */ #if defined(MBEDTLS_PSA_BUILTIN_HASH) || defined(PSA_CRYPTO_DRIVER_TEST) static psa_status_t hash_abort( mbedtls_psa_hash_operation_t *operation) { switch (operation->alg) { case 0: /* The object has (apparently) been initialized but it is not * in use. It's ok to call abort on such an object, and there's * nothing to do. */ break; #if defined(BUILTIN_ALG_MD2) case PSA_ALG_MD2: mbedtls_md2_free(&operation->ctx.md2); break; #endif #if defined(BUILTIN_ALG_MD4) case PSA_ALG_MD4: mbedtls_md4_free(&operation->ctx.md4); break; #endif #if defined(BUILTIN_ALG_MD5) case PSA_ALG_MD5: mbedtls_md5_free(&operation->ctx.md5); break; #endif #if defined(BUILTIN_ALG_RIPEMD160) case PSA_ALG_RIPEMD160: mbedtls_ripemd160_free(&operation->ctx.ripemd160); break; #endif #if defined(BUILTIN_ALG_SHA_1) case PSA_ALG_SHA_1: mbedtls_sha1_free(&operation->ctx.sha1); break; #endif #if defined(BUILTIN_ALG_SHA_224) case PSA_ALG_SHA_224: mbedtls_sha256_free(&operation->ctx.sha256); break; #endif #if defined(BUILTIN_ALG_SHA_256) case PSA_ALG_SHA_256: mbedtls_sha256_free(&operation->ctx.sha256); break; #endif #if defined(BUILTIN_ALG_SHA_384) case PSA_ALG_SHA_384: mbedtls_sha512_free(&operation->ctx.sha512); break; #endif #if defined(BUILTIN_ALG_SHA_512) case PSA_ALG_SHA_512: mbedtls_sha512_free(&operation->ctx.sha512); break; #endif default: return (PSA_ERROR_BAD_STATE); } operation->alg = 0; return (PSA_SUCCESS); } static psa_status_t hash_setup( mbedtls_psa_hash_operation_t *operation, psa_algorithm_t alg) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; /* A context must be freshly initialized before it can be set up. */ if (operation->alg != 0) { return (PSA_ERROR_BAD_STATE); } switch (alg) { #if defined(BUILTIN_ALG_MD2) case PSA_ALG_MD2: mbedtls_md2_init(&operation->ctx.md2); ret = mbedtls_md2_starts_ret(&operation->ctx.md2); break; #endif #if defined(BUILTIN_ALG_MD4) case PSA_ALG_MD4: mbedtls_md4_init(&operation->ctx.md4); ret = mbedtls_md4_starts_ret(&operation->ctx.md4); break; #endif #if defined(BUILTIN_ALG_MD5) case PSA_ALG_MD5: mbedtls_md5_init(&operation->ctx.md5); ret = mbedtls_md5_starts_ret(&operation->ctx.md5); break; #endif #if defined(BUILTIN_ALG_RIPEMD160) case PSA_ALG_RIPEMD160: mbedtls_ripemd160_init(&operation->ctx.ripemd160); ret = mbedtls_ripemd160_starts_ret(&operation->ctx.ripemd160); break; #endif #if defined(BUILTIN_ALG_SHA_1) case PSA_ALG_SHA_1: mbedtls_sha1_init(&operation->ctx.sha1); ret = mbedtls_sha1_starts_ret(&operation->ctx.sha1); break; #endif #if defined(BUILTIN_ALG_SHA_224) case PSA_ALG_SHA_224: mbedtls_sha256_init(&operation->ctx.sha256); ret = mbedtls_sha256_starts_ret(&operation->ctx.sha256, 1); break; #endif #if defined(BUILTIN_ALG_SHA_256) case PSA_ALG_SHA_256: mbedtls_sha256_init(&operation->ctx.sha256); ret = mbedtls_sha256_starts_ret(&operation->ctx.sha256, 0); break; #endif #if defined(BUILTIN_ALG_SHA_384) case PSA_ALG_SHA_384: mbedtls_sha512_init(&operation->ctx.sha512); ret = mbedtls_sha512_starts_ret(&operation->ctx.sha512, 1); break; #endif #if defined(BUILTIN_ALG_SHA_512) case PSA_ALG_SHA_512: mbedtls_sha512_init(&operation->ctx.sha512); ret = mbedtls_sha512_starts_ret(&operation->ctx.sha512, 0); break; #endif default: return (PSA_ALG_IS_HASH(alg) ? PSA_ERROR_NOT_SUPPORTED : PSA_ERROR_INVALID_ARGUMENT); } if (ret == 0) { operation->alg = alg; } else { hash_abort(operation); } return (mbedtls_to_psa_error(ret)); } static psa_status_t hash_clone( const mbedtls_psa_hash_operation_t *source_operation, mbedtls_psa_hash_operation_t *target_operation) { switch (source_operation->alg) { case 0: return (PSA_ERROR_BAD_STATE); #if defined(BUILTIN_ALG_MD2) case PSA_ALG_MD2: mbedtls_md2_clone(&target_operation->ctx.md2, &source_operation->ctx.md2); break; #endif #if defined(BUILTIN_ALG_MD4) case PSA_ALG_MD4: mbedtls_md4_clone(&target_operation->ctx.md4, &source_operation->ctx.md4); break; #endif #if defined(BUILTIN_ALG_MD5) case PSA_ALG_MD5: mbedtls_md5_clone(&target_operation->ctx.md5, &source_operation->ctx.md5); break; #endif #if defined(BUILTIN_ALG_RIPEMD160) case PSA_ALG_RIPEMD160: mbedtls_ripemd160_clone(&target_operation->ctx.ripemd160, &source_operation->ctx.ripemd160); break; #endif #if defined(BUILTIN_ALG_SHA_1) case PSA_ALG_SHA_1: mbedtls_sha1_clone(&target_operation->ctx.sha1, &source_operation->ctx.sha1); break; #endif #if defined(BUILTIN_ALG_SHA_224) case PSA_ALG_SHA_224: mbedtls_sha256_clone(&target_operation->ctx.sha256, &source_operation->ctx.sha256); break; #endif #if defined(BUILTIN_ALG_SHA_256) case PSA_ALG_SHA_256: mbedtls_sha256_clone(&target_operation->ctx.sha256, &source_operation->ctx.sha256); break; #endif #if defined(BUILTIN_ALG_SHA_384) case PSA_ALG_SHA_384: mbedtls_sha512_clone(&target_operation->ctx.sha512, &source_operation->ctx.sha512); break; #endif #if defined(BUILTIN_ALG_SHA_512) case PSA_ALG_SHA_512: mbedtls_sha512_clone(&target_operation->ctx.sha512, &source_operation->ctx.sha512); break; #endif default: (void)source_operation; (void)target_operation; return (PSA_ERROR_NOT_SUPPORTED); } target_operation->alg = source_operation->alg; return (PSA_SUCCESS); } static psa_status_t hash_update( mbedtls_psa_hash_operation_t *operation, const uint8_t *input, size_t input_length) { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; switch (operation->alg) { #if defined(BUILTIN_ALG_MD2) case PSA_ALG_MD2: ret = mbedtls_md2_update_ret(&operation->ctx.md2, input, input_length); break; #endif #if defined(BUILTIN_ALG_MD4) case PSA_ALG_MD4: ret = mbedtls_md4_update_ret(&operation->ctx.md4, input, input_length); break; #endif #if defined(BUILTIN_ALG_MD5) case PSA_ALG_MD5: ret = mbedtls_md5_update_ret(&operation->ctx.md5, input, input_length); break; #endif #if defined(BUILTIN_ALG_RIPEMD160) case PSA_ALG_RIPEMD160: ret = mbedtls_ripemd160_update_ret(&operation->ctx.ripemd160, input, input_length); break; #endif #if defined(BUILTIN_ALG_SHA_1) case PSA_ALG_SHA_1: ret = mbedtls_sha1_update_ret(&operation->ctx.sha1, input, input_length); break; #endif #if defined(BUILTIN_ALG_SHA_224) case PSA_ALG_SHA_224: ret = mbedtls_sha256_update_ret(&operation->ctx.sha256, input, input_length); break; #endif #if defined(BUILTIN_ALG_SHA_256) case PSA_ALG_SHA_256: ret = mbedtls_sha256_update_ret(&operation->ctx.sha256, input, input_length); break; #endif #if defined(BUILTIN_ALG_SHA_384) case PSA_ALG_SHA_384: ret = mbedtls_sha512_update_ret(&operation->ctx.sha512, input, input_length); break; #endif #if defined(BUILTIN_ALG_SHA_512) case PSA_ALG_SHA_512: ret = mbedtls_sha512_update_ret(&operation->ctx.sha512, input, input_length); break; #endif default: (void)input; (void)input_length; return (PSA_ERROR_BAD_STATE); } return (mbedtls_to_psa_error(ret)); } static psa_status_t hash_finish( mbedtls_psa_hash_operation_t *operation, uint8_t *hash, size_t hash_size, size_t *hash_length) { psa_status_t status; int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t actual_hash_length = PSA_HASH_LENGTH(operation->alg); /* Fill the output buffer with something that isn't a valid hash * (barring an attack on the hash and deliberately-crafted input), * in case the caller doesn't check the return status properly. */ *hash_length = hash_size; /* If hash_size is 0 then hash may be NULL and then the * call to memset would have undefined behavior. */ if (hash_size != 0) { memset(hash, '!', hash_size); } if (hash_size < actual_hash_length) { status = PSA_ERROR_BUFFER_TOO_SMALL; goto exit; } switch (operation->alg) { #if defined(BUILTIN_ALG_MD2) case PSA_ALG_MD2: ret = mbedtls_md2_finish_ret(&operation->ctx.md2, hash); break; #endif #if defined(BUILTIN_ALG_MD4) case PSA_ALG_MD4: ret = mbedtls_md4_finish_ret(&operation->ctx.md4, hash); break; #endif #if defined(BUILTIN_ALG_MD5) case PSA_ALG_MD5: ret = mbedtls_md5_finish_ret(&operation->ctx.md5, hash); break; #endif #if defined(BUILTIN_ALG_RIPEMD160) case PSA_ALG_RIPEMD160: ret = mbedtls_ripemd160_finish_ret(&operation->ctx.ripemd160, hash); break; #endif #if defined(BUILTIN_ALG_SHA_1) case PSA_ALG_SHA_1: ret = mbedtls_sha1_finish_ret(&operation->ctx.sha1, hash); break; #endif #if defined(BUILTIN_ALG_SHA_224) case PSA_ALG_SHA_224: ret = mbedtls_sha256_finish_ret(&operation->ctx.sha256, hash); break; #endif #if defined(BUILTIN_ALG_SHA_256) case PSA_ALG_SHA_256: ret = mbedtls_sha256_finish_ret(&operation->ctx.sha256, hash); break; #endif #if defined(BUILTIN_ALG_SHA_384) case PSA_ALG_SHA_384: ret = mbedtls_sha512_finish_ret(&operation->ctx.sha512, hash); break; #endif #if defined(BUILTIN_ALG_SHA_512) case PSA_ALG_SHA_512: ret = mbedtls_sha512_finish_ret(&operation->ctx.sha512, hash); break; #endif default: (void)hash; return (PSA_ERROR_BAD_STATE); } status = mbedtls_to_psa_error(ret); exit: if (status == PSA_SUCCESS) { *hash_length = actual_hash_length; } return (status); } static psa_status_t hash_compute( psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *hash, size_t hash_size, size_t *hash_length) { mbedtls_psa_hash_operation_t operation = MBEDTLS_PSA_HASH_OPERATION_INIT; psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED; *hash_length = hash_size; status = hash_setup(&operation, alg); if (status != PSA_SUCCESS) { goto exit; } status = hash_update(&operation, input, input_length); if (status != PSA_SUCCESS) { goto exit; } status = hash_finish(&operation, hash, hash_size, hash_length); if (status != PSA_SUCCESS) { goto exit; } exit: abort_status = hash_abort(&operation); if (status == PSA_SUCCESS) { return (abort_status); } else { return (status); } } #endif /* MBEDTLS_PSA_BUILTIN_HASH || PSA_CRYPTO_DRIVER_TEST */ #if defined(MBEDTLS_PSA_BUILTIN_HASH) psa_status_t mbedtls_psa_hash_compute( psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *hash, size_t hash_size, size_t *hash_length) { return (hash_compute(alg, input, input_length, hash, hash_size, hash_length)); } psa_status_t mbedtls_psa_hash_setup( mbedtls_psa_hash_operation_t *operation, psa_algorithm_t alg) { return (hash_setup(operation, alg)); } psa_status_t mbedtls_psa_hash_clone( const mbedtls_psa_hash_operation_t *source_operation, mbedtls_psa_hash_operation_t *target_operation) { return (hash_clone(source_operation, target_operation)); } psa_status_t mbedtls_psa_hash_update( mbedtls_psa_hash_operation_t *operation, const uint8_t *input, size_t input_length) { return (hash_update(operation, input, input_length)); } psa_status_t mbedtls_psa_hash_finish( mbedtls_psa_hash_operation_t *operation, uint8_t *hash, size_t hash_size, size_t *hash_length) { return (hash_finish(operation, hash, hash_size, hash_length)); } psa_status_t mbedtls_psa_hash_abort( mbedtls_psa_hash_operation_t *operation) { return (hash_abort(operation)); } #endif /* MBEDTLS_PSA_BUILTIN_HASH */ /* * BEYOND THIS POINT, TEST DRIVER ENTRY POINTS ONLY. */ #if defined(PSA_CRYPTO_DRIVER_TEST) static int is_hash_accelerated(psa_algorithm_t alg) { switch (alg) { #if defined(MBEDTLS_PSA_ACCEL_ALG_MD2) case PSA_ALG_MD2: return (1); #endif #if defined(MBEDTLS_PSA_ACCEL_ALG_MD4) case PSA_ALG_MD4: return (1); #endif #if defined(MBEDTLS_PSA_ACCEL_ALG_MD5) case PSA_ALG_MD5: return (1); #endif #if defined(MBEDTLS_PSA_ACCEL_ALG_RIPEMD160) case PSA_ALG_RIPEMD160: return (1); #endif #if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_1) case PSA_ALG_SHA_1: return (1); #endif #if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224) case PSA_ALG_SHA_224: return (1); #endif #if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256) case PSA_ALG_SHA_256: return (1); #endif #if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384) case PSA_ALG_SHA_384: return (1); #endif #if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512) case PSA_ALG_SHA_512: return (1); #endif default: return (0); } } psa_status_t mbedtls_transparent_test_driver_hash_compute( psa_algorithm_t alg, const uint8_t *input, size_t input_length, uint8_t *hash, size_t hash_size, size_t *hash_length) { if (is_hash_accelerated(alg)) return (hash_compute(alg, input, input_length, hash, hash_size, hash_length)); else { return (PSA_ERROR_NOT_SUPPORTED); } } psa_status_t mbedtls_transparent_test_driver_hash_setup( mbedtls_transparent_test_driver_hash_operation_t *operation, psa_algorithm_t alg) { if (is_hash_accelerated(alg)) { return (hash_setup(operation, alg)); } else { return (PSA_ERROR_NOT_SUPPORTED); } } psa_status_t mbedtls_transparent_test_driver_hash_clone( const mbedtls_transparent_test_driver_hash_operation_t *source_operation, mbedtls_transparent_test_driver_hash_operation_t *target_operation) { if (is_hash_accelerated(source_operation->alg)) { return (hash_clone(source_operation, target_operation)); } else { return (PSA_ERROR_BAD_STATE); } } psa_status_t mbedtls_transparent_test_driver_hash_update( mbedtls_transparent_test_driver_hash_operation_t *operation, const uint8_t *input, size_t input_length) { if (is_hash_accelerated(operation->alg)) { return (hash_update(operation, input, input_length)); } else { return (PSA_ERROR_BAD_STATE); } } psa_status_t mbedtls_transparent_test_driver_hash_finish( mbedtls_transparent_test_driver_hash_operation_t *operation, uint8_t *hash, size_t hash_size, size_t *hash_length) { if (is_hash_accelerated(operation->alg)) { return (hash_finish(operation, hash, hash_size, hash_length)); } else { return (PSA_ERROR_BAD_STATE); } } psa_status_t mbedtls_transparent_test_driver_hash_abort( mbedtls_transparent_test_driver_hash_operation_t *operation) { return (hash_abort(operation)); } #endif /* PSA_CRYPTO_DRIVER_TEST */ #endif /* MBEDTLS_PSA_CRYPTO_C */