1 /*
2  * Copyright (c) 2001-2022, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 #ifdef CC_IOT
7 #include "mbedtls/build_info.h"
8 #endif
9 
10 #if !defined(CC_IOT) || ( defined(CC_IOT) && defined(MBEDTLS_RSA_C))
11 
12 #define CC_PAL_LOG_CUR_COMPONENT CC_LOG_MASK_ASYM_RSA_DH
13 
14 /************* Include Files ****************/
15 
16 #include "cc_pal_mem.h"
17 #include "cc_common.h"
18 #include "cc_common_math.h"
19 #include "cc_rsa_error.h"
20 #include "cc_rsa_local.h"
21 #include "rsa.h"
22 #include "rsa_public.h"
23 #include "rsa_private.h"
24 #include "cc_fips_defs.h"
25 
26 /************************ Defines ******************************/
27 
28 /************************ Enums ******************************/
29 
30 /************************ Typedefs ******************************/
31 
32 /************************ Global Data ******************************/
33 
34 /************************ Public Functions ******************************/
35 
36 
37 /**********************************************************************************/
38 /**
39 @brief
40 CC_RsaPrimEncrypt implements the RSAEP algorithm as defined in PKCS#1 v2.1 6.1.1
41 
42   @param[in] UserPubKey_ptr - Pointer to the public key data structure.
43   @param[in] PrimeData_ptr - A pointer to a structure containing temp buffers.
44   @param[in] Data_ptr - Pointer to the input data to be encrypted.
45   @param[in] DataSize - The size, in bytes, of the input data.
46             \Note: DataSize <= modulus size is supported, but recommended
47             that size is equal to modulus size. If smaller, the data will be
48             zero-padded on left side up to the modulus size and therefore,
49             after further decrypt operation its result will contain
50             padding zeros also.
51   @param[out] Output_ptr - Pointer to the encrypted data. The size of output data
52             is always equal to size modulus size. The output buffer
53             must be at least of modulus size in bytes.
54 
55   @return CCError_t - CC_OK,
56             CC_RSA_INVALID_PUB_KEY_STRUCT_POINTER_ERROR,
57             CC_RSA_PUB_KEY_VALIDATION_TAG_ERROR,
58             CC_RSA_PRIM_DATA_STRUCT_POINTER_INVALID,
59             CC_RSA_DATA_POINTER_INVALID_ERROR,
60             CC_RSA_INVALID_OUTPUT_POINTER_ERROR,
61             CC_RSA_INVALID_MESSAGE_BUFFER_SIZE,
62             CC_RSA_INVALID_MESSAGE_DATA_SIZE,
63             CC_RSA_INVALID_MESSAGE_VAL
64  */
CC_RsaPrimEncrypt(CCRsaUserPubKey_t * UserPubKey_ptr,CCRsaPrimeData_t * PrimeData_ptr,uint8_t * Data_ptr,size_t DataSize,uint8_t * Output_ptr)65 CEXPORT_C CCError_t CC_RsaPrimEncrypt(CCRsaUserPubKey_t *UserPubKey_ptr,
66                         CCRsaPrimeData_t  *PrimeData_ptr,
67                         uint8_t              *Data_ptr,
68                         size_t                DataSize,
69                         uint8_t              *Output_ptr)
70 {
71     /* FUNCTION LOCAL DECLERATIONS */
72 
73     /* the counter compare result */
74     CCCommonCmpCounter_t CounterCmpResult;
75 
76     /* the public key database pointer */
77     CCRsaPubKey_t *PubKey_ptr;
78 
79     /* the modulus size in bytes */
80     uint32_t nSizeInBytes;
81 
82     /* The return error identifier */
83     CCError_t Error = CC_OK;
84 
85     /* FUNCTION LOGIC */
86 
87 
88     /* ............... checking the parameters pointers validity .......... */
89     /* -------------------------------------------------------------------- */
90 
91     CHECK_AND_RETURN_ERR_UPON_FIPS_ERROR();
92     /* checking the key database handle pointer */
93     if (UserPubKey_ptr == NULL)
94         return CC_RSA_INVALID_PUB_KEY_STRUCT_POINTER_ERROR;
95 
96     /* if the users TAG is illegal return an error - the context is invalid */
97     if (UserPubKey_ptr->valid_tag != CC_RSA_PUB_KEY_VALIDATION_TAG)
98         return CC_RSA_PUB_KEY_VALIDATION_TAG_ERROR;
99 
100     /* checking the Prime Data pointer */
101     if (PrimeData_ptr == NULL)
102         return CC_RSA_PRIM_DATA_STRUCT_POINTER_INVALID;
103 
104     /* if the users Data pointer is illegal return an error */
105     if (Data_ptr == NULL)
106         return CC_RSA_DATA_POINTER_INVALID_ERROR;
107 
108     /* if the users output pointer is illegal return an error */
109     if (Output_ptr == NULL)
110         return CC_RSA_INVALID_OUTPUT_POINTER_ERROR;
111 
112     /* if the data size is larger then the internal buffer return error */
113     if (DataSize > sizeof(PrimeData_ptr->DataIn))
114         return CC_RSA_INVALID_MESSAGE_BUFFER_SIZE;
115 
116     /* setting the pointer to the key database */
117     PubKey_ptr = (CCRsaPubKey_t*)UserPubKey_ptr->PublicKeyDbBuff;
118 
119     /* setting the modulus size in bytes */
120     nSizeInBytes = CALC_FULL_BYTES(PubKey_ptr->nSizeInBits);
121 
122 
123     /* ................ copying the input data to the buffer .............. */
124     /* -------------------------------------------------------------------- */
125 
126     /* clear the input data */
127     CC_PalMemSet(PrimeData_ptr->DataIn, 0, sizeof(PrimeData_ptr->DataIn));
128 
129     /* copy the input data to the aligned buffer on the data handler */
130     Error = CC_CommonConvertMsbLsbBytesToLswMswWords(PrimeData_ptr->DataIn, 4*((nSizeInBytes+3)/4),
131                                 Data_ptr, DataSize);
132     if (Error != CC_OK) {
133         Error = CC_RSA_INVALID_MESSAGE_DATA_SIZE;
134         goto End;
135     }
136 
137         /* ...... checking the the message value it must be less then the modulus ...... */
138     CounterCmpResult = CC_CommonCmpLsWordsUnsignedCounters(
139                                  PrimeData_ptr->DataIn, (uint16_t)(nSizeInBytes+3)/4,
140                                  PubKey_ptr->n, (uint16_t)(nSizeInBytes+3)/4);
141 
142     if (CounterCmpResult != CC_COMMON_CmpCounter2GreaterThenCounter1) {
143         Error = CC_RSA_INVALID_MESSAGE_VAL;
144         goto End;
145     }
146 
147     /* executing the encryption */
148     Error = RsaExecPubKeyExp(PubKey_ptr, PrimeData_ptr);
149 
150     if (Error != CC_OK) {
151         Error = CC_RSA_INTERNAL_ERROR;
152         goto End;
153     }
154 
155     /* copy the output data from the aligned buffer to the users data on big endian format */
156     Error = CC_CommonConvertLswMswWordsToMsbLsbBytes(Output_ptr, 4*((nSizeInBytes+3)/4),
157                                 PrimeData_ptr->DataOut, nSizeInBytes );
158     if (Error != CC_OK) {
159         Error = CC_RSA_INVALID_MESSAGE_VAL;
160         goto End;
161     }
162 
163 End:
164     if (Error != CC_OK) {
165         CC_PalMemSetZero(Output_ptr, nSizeInBytes);
166     }
167     /* clear the data buffer */
168     CC_PalMemSetZero(PrimeData_ptr, sizeof(CCRsaPrimeData_t) );
169 
170     return Error;
171 
172 
173 }/* END OF CC_RsaPrimEncrypt */
174 
175 
176 /**********************************************************************************/
177 /**
178 @brief
179 CC_RsaPrimDecrypt implements the RSADP algorithm as defined in PKCS#1 v2.1 6.1.2
180 
181   @param[in] PrivKey_ptr - Pointer to the private key data
182                structure. \note The RSA key parameters and hence the algorithm (CRT
183                or not) are determined by this structure. Using CC_BuildPrivKey or
184                CC_BuildPrivKeyCRT determines which algorithm will be used.
185 
186   @param[in] PrimeData_ptr - A pointer to a structure containing internal
187                  buffers required for the RSA operation.
188   @param[in] Data_ptr - Pointer to the data to be decrypted.
189   @param[in] DataSize - The size, in bytes, of the input data. To decrypt
190             previously encrypted data its size must be equal to
191             modulus size.
192             \Note: DataSize <= modulus size is supported, but
193             it is recommended that the size is equal to modulus size.
194             If smaller, the data will be zero-padded on left side
195             up to the modulus size and therefore, after further decrypt
196             operation its result will contain padding zeros also.
197   @param[out] Output_ptr - Pointer to the decrypted data. The size of output data
198             is always equal to size modulus size. The output buffer
199             must be at least of modulus size in bytes.
200 
201   @return CCError_t - CC_OK,
202             CC_RSA_INVALID_PRIV_KEY_STRUCT_POINTER_ERROR,
203             CC_RSA_PRIM_DATA_STRUCT_POINTER_INVALID,
204             CC_RSA_PRIV_KEY_VALIDATION_TAG_ERROR,
205             CC_RSA_DATA_POINTER_INVALID_ERROR,
206             CC_RSA_INVALID_OUTPUT_POINTER_ERROR,
207             CC_RSA_INVALID_MESSAGE_DATA_SIZE,
208             CC_RSA_INVALID_MESSAGE_VAL
209  */
210 
CC_RsaPrimDecrypt(CCRsaUserPrivKey_t * UserPrivKey_ptr,CCRsaPrimeData_t * PrimeData_ptr,uint8_t * Data_ptr,size_t DataSize,uint8_t * Output_ptr)211 CEXPORT_C CCError_t CC_RsaPrimDecrypt(
212                        CCRsaUserPrivKey_t *UserPrivKey_ptr,
213                        CCRsaPrimeData_t   *PrimeData_ptr,
214                        uint8_t             *Data_ptr,
215                        size_t               DataSize,
216                        uint8_t             *Output_ptr)
217 {
218     /* FUNCTION LOCAL DECLERATIONS */
219 
220     /* the counter compare result */
221     CCCommonCmpCounter_t CounterCmpResult;
222 
223     /* the private key database pointer */
224     CCRsaPrivKey_t *PrivKey_ptr;
225 
226     /* the modulus size in bytes */
227     uint32_t nSizeInBytes;
228 
229     /* The return error identifier */
230     CCError_t Error = CC_OK;
231 
232     /* FUNCTION LOGIC */
233 
234 
235     /* ............... checking the parameters pointers validity .......... */
236     /* -------------------------------------------------------------------- */
237     CHECK_AND_RETURN_ERR_UPON_FIPS_ERROR();
238 
239     /* ...... checking the key database handle pointer .................... */
240     if (UserPrivKey_ptr == NULL)
241         return CC_RSA_INVALID_PRIV_KEY_STRUCT_POINTER_ERROR;
242 
243     /* ...... checking the Prime Data pointer .................... */
244     if (PrimeData_ptr == NULL)
245         return CC_RSA_PRIM_DATA_STRUCT_POINTER_INVALID;
246 
247     /* if the users TAG is illegal return an error - the context is invalid */
248     if (UserPrivKey_ptr->valid_tag != CC_RSA_PRIV_KEY_VALIDATION_TAG)
249         return CC_RSA_PRIV_KEY_VALIDATION_TAG_ERROR;
250 
251     /* if the users Data pointer is NULL return an error */
252     if (Data_ptr == NULL)
253         return CC_RSA_DATA_POINTER_INVALID_ERROR;
254 
255     /* if the users Output pointer is NULL return an error */
256     if (Output_ptr == NULL)
257         return CC_RSA_INVALID_OUTPUT_POINTER_ERROR;
258 
259 
260     /* setting the pointer to the key database */
261     PrivKey_ptr = (CCRsaPrivKey_t*)UserPrivKey_ptr->PrivateKeyDbBuff;
262 
263     /* setting the modulus size in bytes */
264     nSizeInBytes = CALC_FULL_BYTES(PrivKey_ptr->nSizeInBits);
265 
266     /* if the data size is 0 or great than modulus size - return an error */
267     if (DataSize == 0 || DataSize > nSizeInBytes)
268         return CC_RSA_INVALID_MESSAGE_DATA_SIZE;
269 
270     /* ................ copying the input data to the buffer .............. */
271     /* -------------------------------------------------------------------- */
272 
273     /* clear the input data */
274     CC_PalMemSetZero( PrimeData_ptr->DataIn, sizeof(PrimeData_ptr->DataIn));
275 
276     /* copy the input data to the aligned buffer on the data handler in little endian format */
277     Error = CC_CommonConvertMsbLsbBytesToLswMswWords(
278                                PrimeData_ptr->DataIn, 4*((nSizeInBytes+3)/4), Data_ptr, DataSize);
279     if (Error != CC_OK) {
280         Error = CC_RSA_INVALID_MESSAGE_DATA_SIZE;
281         goto End;
282     }
283 
284     /* .. checking the message value it must be less then the modulus .. */
285     /* ----------------------------------------------------------------- */
286     CounterCmpResult = CC_CommonCmpLsWordsUnsignedCounters(
287                                  PrimeData_ptr->DataIn, (uint16_t)(nSizeInBytes+3)/4,
288                                  PrivKey_ptr->n, (uint16_t)(nSizeInBytes+3)/4);
289 
290     if (CounterCmpResult != CC_COMMON_CmpCounter2GreaterThenCounter1) {
291         Error = CC_RSA_INVALID_MESSAGE_VAL;
292         goto End;
293     }
294 
295     /* ..................... executing the encryption ...................... */
296     /* --------------------------------------------------------------------- */
297 
298     Error = RsaExecPrivKeyExp(PrivKey_ptr, PrimeData_ptr);
299 
300     if (Error != CC_OK) {
301         Error = CC_RSA_INTERNAL_ERROR;
302         goto End;
303     }
304 
305     /* copy the output data from the aligned words-buffer to the users data in MS-LS bytes order */
306     Error = CC_CommonConvertLswMswWordsToMsbLsbBytes(Output_ptr, 4*((nSizeInBytes+3)/4),
307                                 PrimeData_ptr->DataOut, nSizeInBytes);
308     if (Error != CC_OK) {
309         Error = CC_RSA_INVALID_MESSAGE_VAL;
310         goto End;
311     }
312 
313 End:
314     if (Error != CC_OK) {
315         CC_PalMemSetZero(Output_ptr, nSizeInBytes);
316     }
317 
318     /* clear the temp data buffer */
319     CC_PalMemSetZero(PrimeData_ptr, sizeof(CCRsaPrimeData_t));
320 
321     return Error;
322 
323 
324 }/* END OF CC_RsaPrimDecrypt */
325 
326 #endif /* !defined(CC_IOT) || ( defined(CC_IOT) && defined(MBEDTLS_RSA_C)) */
327 
328