// SPDX-License-Identifier: BSD-2-Clause /* * Copyright 2018-2020 NXP * * RSA Mask Generation function implementation. */ #include #include #include #include #include "local.h" TEE_Result drvcrypt_rsa_mgf1(struct drvcrypt_rsa_mgf *mgf_data) { TEE_Result ret = TEE_ERROR_GENERIC; void *ctx = NULL; size_t lastBlock_size = 0; size_t nbBlock = 0; uint32_t counter = 0; uint32_t swapcount = 0; uint8_t *cur_mask = mgf_data->mask.data; uint8_t *tmpdigest = NULL; CRYPTO_TRACE("Generate Mask (%zu bytes) with seed of %zu bytes", mgf_data->mask.length, mgf_data->seed.length); /* Calculate the number of complet hash digest */ lastBlock_size = mgf_data->mask.length % mgf_data->digest_size; if (lastBlock_size) { /* Allocate a digest buffer for the last block */ tmpdigest = malloc(mgf_data->digest_size); if (!tmpdigest) return TEE_ERROR_OUT_OF_MEMORY; } /* Allocate the Hash Context */ ret = crypto_hash_alloc_ctx(&ctx, mgf_data->hash_algo); if (ret != TEE_SUCCESS) goto exit_mgf; nbBlock = (mgf_data->mask.length - lastBlock_size) / mgf_data->digest_size; CRYPTO_TRACE("Nb Loop (%zu bytes) = %zu, last Block = %zu bytes", mgf_data->digest_size, nbBlock, lastBlock_size); for (; counter < nbBlock; counter++, cur_mask += mgf_data->digest_size) { swapcount = TEE_U32_TO_BIG_ENDIAN(counter); ret = crypto_hash_init(ctx); if (ret != TEE_SUCCESS) goto exit_mgf; ret = crypto_hash_update(ctx, mgf_data->seed.data, mgf_data->seed.length); if (ret != TEE_SUCCESS) goto exit_mgf; ret = crypto_hash_update(ctx, (uint8_t *)&swapcount, sizeof(swapcount)); if (ret != TEE_SUCCESS) goto exit_mgf; ret = crypto_hash_final(ctx, cur_mask, mgf_data->digest_size); if (ret != TEE_SUCCESS) goto exit_mgf; } if (lastBlock_size) { CRYPTO_TRACE("Last Block = %zu bytes", lastBlock_size); swapcount = TEE_U32_TO_BIG_ENDIAN(counter); ret = crypto_hash_init(ctx); if (ret != TEE_SUCCESS) goto exit_mgf; ret = crypto_hash_update(ctx, mgf_data->seed.data, mgf_data->seed.length); if (ret != TEE_SUCCESS) goto exit_mgf; ret = crypto_hash_update(ctx, (uint8_t *)&swapcount, sizeof(swapcount)); if (ret != TEE_SUCCESS) goto exit_mgf; ret = crypto_hash_final(ctx, tmpdigest, mgf_data->digest_size); if (ret != TEE_SUCCESS) goto exit_mgf; memcpy(cur_mask, tmpdigest, lastBlock_size); } ret = TEE_SUCCESS; exit_mgf: crypto_hash_free_ctx(ctx); free(tmpdigest); CRYPTO_TRACE("return 0x%08" PRIx32, ret); return ret; }