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