1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright 2018-2020 NXP
4 *
5 * RSA Mask Generation function implementation.
6 */
7 #include <drvcrypt.h>
8 #include <malloc.h>
9 #include <string.h>
10 #include <utee_defines.h>
11
12 #include "local.h"
13
drvcrypt_rsa_mgf1(struct drvcrypt_rsa_mgf * mgf_data)14 TEE_Result drvcrypt_rsa_mgf1(struct drvcrypt_rsa_mgf *mgf_data)
15 {
16 TEE_Result ret = TEE_ERROR_GENERIC;
17 void *ctx = NULL;
18 size_t lastBlock_size = 0;
19 size_t nbBlock = 0;
20 uint32_t counter = 0;
21 uint32_t swapcount = 0;
22 uint8_t *cur_mask = mgf_data->mask.data;
23 uint8_t *tmpdigest = NULL;
24
25 CRYPTO_TRACE("Generate Mask (%zu bytes) with seed of %zu bytes",
26 mgf_data->mask.length, mgf_data->seed.length);
27
28 /* Calculate the number of complet hash digest */
29 lastBlock_size = mgf_data->mask.length % mgf_data->digest_size;
30 if (lastBlock_size) {
31 /* Allocate a digest buffer for the last block */
32 tmpdigest = malloc(mgf_data->digest_size);
33 if (!tmpdigest)
34 return TEE_ERROR_OUT_OF_MEMORY;
35 }
36
37 /* Allocate the Hash Context */
38 ret = crypto_hash_alloc_ctx(&ctx, mgf_data->hash_algo);
39 if (ret != TEE_SUCCESS)
40 goto exit_mgf;
41
42 nbBlock = (mgf_data->mask.length - lastBlock_size) /
43 mgf_data->digest_size;
44
45 CRYPTO_TRACE("Nb Loop (%zu bytes) = %zu, last Block = %zu bytes",
46 mgf_data->digest_size, nbBlock, lastBlock_size);
47
48 for (; counter < nbBlock;
49 counter++, cur_mask += mgf_data->digest_size) {
50 swapcount = TEE_U32_TO_BIG_ENDIAN(counter);
51
52 ret = crypto_hash_init(ctx);
53 if (ret != TEE_SUCCESS)
54 goto exit_mgf;
55
56 ret = crypto_hash_update(ctx, mgf_data->seed.data,
57 mgf_data->seed.length);
58 if (ret != TEE_SUCCESS)
59 goto exit_mgf;
60
61 ret = crypto_hash_update(ctx, (uint8_t *)&swapcount,
62 sizeof(swapcount));
63 if (ret != TEE_SUCCESS)
64 goto exit_mgf;
65
66 ret = crypto_hash_final(ctx, cur_mask, mgf_data->digest_size);
67 if (ret != TEE_SUCCESS)
68 goto exit_mgf;
69 }
70
71 if (lastBlock_size) {
72 CRYPTO_TRACE("Last Block = %zu bytes", lastBlock_size);
73
74 swapcount = TEE_U32_TO_BIG_ENDIAN(counter);
75
76 ret = crypto_hash_init(ctx);
77 if (ret != TEE_SUCCESS)
78 goto exit_mgf;
79
80 ret = crypto_hash_update(ctx, mgf_data->seed.data,
81 mgf_data->seed.length);
82 if (ret != TEE_SUCCESS)
83 goto exit_mgf;
84
85 ret = crypto_hash_update(ctx, (uint8_t *)&swapcount,
86 sizeof(swapcount));
87 if (ret != TEE_SUCCESS)
88 goto exit_mgf;
89
90 ret = crypto_hash_final(ctx, tmpdigest, mgf_data->digest_size);
91 if (ret != TEE_SUCCESS)
92 goto exit_mgf;
93
94 memcpy(cur_mask, tmpdigest, lastBlock_size);
95 }
96
97 ret = TEE_SUCCESS;
98
99 exit_mgf:
100 crypto_hash_free_ctx(ctx);
101 free(tmpdigest);
102
103 CRYPTO_TRACE("return 0x%08" PRIx32, ret);
104 return ret;
105 }
106