1 /*
2 * Copyright (c) 2001-2020, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #define CC_PAL_LOG_CUR_COMPONENT CC_LOG_MASK_ASYM_ECC
8
9 /************* Include Files ****************/
10
11 #include "cc_pal_mem.h"
12 #include "cc_ecpki_error.h"
13 #include "cc_ecpki_local.h"
14 #include "cc_common.h"
15 #include "cc_rsa_types.h"
16 #include "cc_fips_defs.h"
17 #include "ec_wrst.h"
18 #ifdef USE_MBEDTLS_CRYPTOCELL
19 #include "cc_general_defs.h"
20 #include "mbedtls/md.h"
21 #endif
22
23 /************************ Defines *****************************************/
24 #if ( CC_HASH_USER_CTX_SIZE_IN_WORDS > CC_PKA_RSA_HASH_CTX_SIZE_IN_WORDS )
25 #error CC_PKA_RSA_HASH_CTX_SIZE_IN_WORDS or CC_HASH_USER_CTX_SIZE_IN_WORDS defined not correctly.
26 #endif
27
28 /************************ Enums *******************************************/
29 /************************ Typedefs ****************************************/
30 /************************ Global Data *************************************/
31 extern const CCEcpkiHash_t ecpki_hash_info[CC_ECPKI_HASH_NumOfModes];
32 extern const uint8_t ecpki_supported_hash_modes[CC_ECPKI_HASH_NumOfModes];
33 /************* Private function prototype *********************************/
34
35 /************************ Public Functions ********************************/
36
37 /**************************************************************************
38 * EcdsaVerifyInit function
39 **************************************************************************/
40 /**
41 @brief Prepares a context that is used by the Update and Finish functions
42 but does not perform elliptic curve cryptographic processing
43
44 The function:
45 - Receives and decrypts user data (working context).
46 - Checks input parameters of ECDSA Vrifying primitive.
47 - Calls hash init function.
48 - Initializes variables and structures for calling next functions.
49 - Encrypts and releases working context.
50
51 NOTE: Using of HASH functions with HASH size great, than EC modulus size,
52 is not recommended!
53
54 @param[in,out] pVerifyUserContext - A pointer to the user buffer for verifying database.
55 @param[in] pSignerPublKey - A pointer to a Signer public key structure.
56 @param[in] hashMode - The enumerator variable defines the hash function to be used.
57
58 @return <b>CCError_t</b>: <br>
59 CC_OK<br>
60 CC_ECDSA_VERIFY_INVALID_USER_CONTEXT_PTR_ERROR <br>
61 CC_ECDSA_VERIFY_INVALID_SIGNER_PUBL_KEY_PTR_ERROR <br>
62 CC_ECDSA_VERIFY_SIGNER_PUBL_KEY_VALIDATION_TAG_ERROR <br>
63 CC_ECDSA_VERIFY_INVALID_DOMAIN_ID_ERROR <br>
64 CC_ECDSA_VERIFY_ILLEGAL_HASH_OP_MODE_ERROR <br>
65 **/
EcdsaVerifyInit(CCEcdsaVerifyUserContext_t * pVerifyUserContext,CCEcpkiUserPublKey_t * pSignerPublKey,CCEcpkiHashOpMode_t hashMode)66 CEXPORT_C CCError_t EcdsaVerifyInit(
67 CCEcdsaVerifyUserContext_t *pVerifyUserContext, /*in/out*/
68 CCEcpkiUserPublKey_t *pSignerPublKey, /*in*/
69 CCEcpkiHashOpMode_t hashMode /*in*/ )
70 {
71 /* FUNCTION DECLERATIONS */
72
73 /* The return error identifier */
74 CCError_t err = CC_OK;
75 /* defining a pointer to the active context allcated by the CCM */
76 EcdsaVerifyContext_t *pWorkingContext;
77 #ifdef USE_MBEDTLS_CRYPTOCELL
78 const mbedtls_md_info_t *md_info=NULL;
79 #endif
80
81 /* FUNCTION LOGIC */
82
83 pWorkingContext = (EcdsaVerifyContext_t*)&pVerifyUserContext->context_buff;
84
85 /* ............... checking the parameters validity ................... */
86 /* -------------------------------------------------------------------- */
87
88 /* if the users context ID pointer is NULL return an error */
89 if (pVerifyUserContext == NULL){
90 return CC_ECDSA_VERIFY_INVALID_USER_CONTEXT_PTR_ERROR;
91 }
92
93 /*if the private key object is NULL return an error*/
94 if (pSignerPublKey == NULL){
95 err = CC_ECDSA_VERIFY_INVALID_SIGNER_PUBL_KEY_PTR_ERROR;
96 goto End;
97 }
98
99 /* check if the hash operation mode is legal */
100 if (hashMode >= CC_ECPKI_HASH_NumOfModes){
101 err = CC_ECDSA_VERIFY_ILLEGAL_HASH_OP_MODE_ERROR;
102 goto End;
103 }
104
105 if (pSignerPublKey->valid_tag != CC_ECPKI_PUBL_KEY_VALIDATION_TAG){
106 err = CC_ECDSA_VERIFY_SIGNER_PUBL_KEY_VALIDATION_TAG_ERROR;
107 goto End;
108 }
109
110 /* reset the Context handler for improper previous values initialized */
111 CC_PalMemSet(pWorkingContext, 0, sizeof(EcdsaVerifyContext_t));
112
113 /* ................. loading the context .................................. */
114 /* ------------------------------------------------------------------------ */
115
116 /*Initializing the Hash operation mode in the ECDSA Context */
117
118
119 if (ecpki_supported_hash_modes[hashMode] == CC_FALSE) {
120 err = CC_ECDSA_VERIFY_ILLEGAL_HASH_OP_MODE_ERROR;
121 goto End;
122 }
123
124 pWorkingContext->hashMode = hashMode;
125 pWorkingContext->hashResultSizeWords = ecpki_hash_info[pWorkingContext->hashMode].hashResultSize;
126
127 if (ecpki_hash_info[pWorkingContext->hashMode].hashMode < CC_HASH_NumOfModes) {
128 #ifdef USE_MBEDTLS_CRYPTOCELL
129 md_info = mbedtls_md_info_from_string( HashAlgMode2mbedtlsString[ecpki_hash_info[pWorkingContext->hashMode].hashMode] );
130 if (NULL == md_info) {
131 err = CC_ECDSA_SIGN_ILLEGAL_HASH_OP_MODE_ERROR;
132 goto End;
133 }
134 mbedtls_md_init(&(pWorkingContext->hash_ctx));
135 err = mbedtls_md_setup(&(pWorkingContext->hash_ctx), md_info, 0); // 0 = HASH, not HMAC
136 if (err != 0) {
137 goto End;
138 }
139 err = mbedtls_md_starts(&(pWorkingContext->hash_ctx));
140 #else
141 err = CC_HashInit(&(pWorkingContext->hashUserCtxBuff), ecpki_hash_info[pWorkingContext->hashMode].hashMode);
142 #endif
143 if (err != CC_OK)
144 goto End;
145 }
146
147 /* copy the ECPKI Public key to the context*/
148 CC_PalMemCopy(&pWorkingContext->ECDSA_SignerPublKey, pSignerPublKey, sizeof(CCEcpkiUserPublKey_t));
149
150 /* set the ECDSA validation tag */
151 pVerifyUserContext->valid_tag = CC_ECDSA_VERIFY_CONTEXT_VALIDATION_TAG;
152
153 End:
154 /* clear the users context in case of error */
155 if (err != CC_OK) {
156 #ifdef USE_MBEDTLS_CRYPTOCELL
157 if(md_info!=NULL){
158 mbedtls_md_free(&(pWorkingContext->hash_ctx));
159 }
160 #endif
161 CC_PalMemSetZero(pVerifyUserContext, sizeof(CCEcdsaVerifyUserContext_t));
162 }
163
164 return err;
165
166 }/* EcdsaVerifyInit */
167
168
169 /**************************************************************************
170 * EcdsaVerifyUpdate function
171 **************************************************************************/
172 /**
173 @brief Performs a hash operation on data allocated by the user
174 before finally verifying its signature.
175
176 In case user divides signing data by block, he must call the Update function
177 continuously a number of times until processing of the entire data block is complete.
178
179 NOTE: Using of HASH functions with HASH size greater, than EC modulus size,
180 is not recommended.
181
182 @param [in,out] pVerifyUserContext - The pointer to the user buffer for verifying database.
183 @param [in] pMessageDataIn - The message data for calculating Hash.
184 @param [in]dataInSize - The size of the message data block, in bytes. The data size,
185 passed on each call of the function, besides the last call, must be
186 a multiple of the HASH block size according to used HASH mode.
187
188 @return <b>CCError_t</b>: <br>
189 CC_OK<br>
190 CC_ECDSA_VERIFY_INVALID_USER_CONTEXT_PTR_ERROR <br>
191 CC_ECDSA_VERIFY_USER_CONTEXT_VALIDATION_TAG_ERROR <br>
192 CC_ECDSA_VERIFY_INVALID_MESSAGE_DATA_IN_PTR_ERROR <br>
193 CC_ECDSA_VERIFY_INVALID_MESSAGE_DATA_IN_SIZE_ERROR <br>
194 CC_ECDSA_VERIFY_ILLEGAL_HASH_OP_MODE_ERROR <br>
195 **/
EcdsaVerifyUpdate(CCEcdsaVerifyUserContext_t * pVerifyUserContext,uint8_t * pMessageDataIn,size_t dataInSize)196 CEXPORT_C CCError_t EcdsaVerifyUpdate(
197 CCEcdsaVerifyUserContext_t *pVerifyUserContext, /*in/out*/
198 uint8_t *pMessageDataIn, /* in */
199 size_t dataInSize /* in */ )
200 {
201 /* FUNCTION DECLARATIONS */
202
203 /* The return error identifier */
204 CCError_t err = CC_OK;
205 /* defining a pointer to the active context allcated by the CCM */
206 EcdsaVerifyContext_t *pWorkingContext;
207
208 /* FUNCTION LOGIC */
209
210 /* sign working context */
211 pWorkingContext = (EcdsaVerifyContext_t*)&pVerifyUserContext->context_buff;
212
213 /* ............... checking the parameters validity ................... */
214 /* -------------------------------------------------------------------- */
215
216 /* if the users context pointer is NULL return an error */
217 if (pVerifyUserContext == NULL){
218 return CC_ECDSA_VERIFY_INVALID_USER_CONTEXT_PTR_ERROR;
219 }
220
221 /* if the users context TAG is illegal return an error - the context is invalid */
222 if (pVerifyUserContext->valid_tag != CC_ECDSA_VERIFY_CONTEXT_VALIDATION_TAG){
223 err = CC_ECDSA_VERIFY_USER_CONTEXT_VALIDATION_TAG_ERROR;
224 goto End;
225 }
226
227 /* if the users MessageDataIn pointer is illegal return an error */
228 if (pMessageDataIn == NULL && dataInSize){
229 err = CC_ECDSA_VERIFY_INVALID_MESSAGE_DATA_IN_PTR_ERROR;
230 goto End;
231 }
232
233 /* check that the data size < 2^29 (to prevent an overflow on the
234 transition to bits ) */
235 if (dataInSize >= (1UL << 29)){
236 err = CC_ECDSA_VERIFY_INVALID_MESSAGE_DATA_IN_SIZE_ERROR;
237 goto End;
238 }
239
240
241 /* HASH update operations */
242 if (ecpki_hash_info[pWorkingContext->hashMode].hashMode < CC_HASH_NumOfModes) {
243 /*Operate the Hash update function for relevant version */
244 #ifdef USE_MBEDTLS_CRYPTOCELL
245 err = mbedtls_md_update(&(pWorkingContext->hash_ctx), pMessageDataIn, dataInSize);
246 #else
247 err = CC_HashUpdate( &(pWorkingContext->hashUserCtxBuff), pMessageDataIn, dataInSize );
248 #endif
249 if (err != CC_OK) {
250 goto End;
251 }
252 } else {
253 if (dataInSize != ecpki_hash_info[pWorkingContext->hashMode].hashResultSize*CC_32BIT_WORD_SIZE) {
254 /* DataInSize must fit exactly to the size of Hash output that we support */
255 err = CC_ECDSA_VERIFY_INVALID_MESSAGE_DATA_IN_SIZE_ERROR;
256 goto End;
257 }
258 /* Copy the DataIn_ptr to the HASH_Result */
259 CC_PalMemCopy((uint8_t *)pWorkingContext->hashResult,pMessageDataIn,dataInSize);
260 }
261
262 End:
263 /* clear the users context in case of error */
264 if (err != CC_OK) {
265 #ifdef USE_MBEDTLS_CRYPTOCELL
266 mbedtls_md_free(&(pWorkingContext->hash_ctx));
267 #endif
268 CC_PalMemSetZero(pVerifyUserContext, sizeof(CCEcdsaVerifyUserContext_t));
269 }
270
271 return err;
272
273 }/* EcdsaVerifyUpdate */
274
275
276
277 /**************************************************************************
278 * EcdsaVerifyFinish function
279 **************************************************************************/
280 /**
281 @brief Performs initialization of variables and structures,
282 calls the hash function for the last block of data (if necessary),
283 than calls EcWrstDsaVerify function for verifying signature
284 according to EC DSA algorithm.
285
286 NOTE: Using of HASH functions with HASH size greater, than EC modulus size,
287 is not recommended!
288 Algorithm according ANS X9.62 standard
289
290 @param[in] pVerifyUserContext - A pointer to the user buffer for verifying the database.
291 @param[in] pSignatureIn - A pointer to a buffer for the signature to be compared
292 @param[in] SignatureSizeBytes - The size of a user passed signature (must be 2*orderSizeInBytes).
293
294 @return <b>CCError_t</b>: <br>
295 CC_OK <br>
296 CC_ECDSA_VERIFY_INVALID_USER_CONTEXT_PTR_ERROR <br>
297 CC_ECDSA_VERIFY_USER_CONTEXT_VALIDATION_TAG_ERROR <br>
298 CC_ECDSA_VERIFY_INVALID_SIGNATURE_IN_PTR_ERROR <br>
299 CC_ECDSA_VERIFY_ILLEGAL_HASH_OP_MODE_ERROR <br>
300 CC_ECDSA_VERIFY_INVALID_SIGNATURE_SIZE_ERROR <br>
301 CC_ECDSA_VERIFY_INCONSISTENT_VERIFY_ERROR <br>
302 **/
EcdsaVerifyFinish(CCEcdsaVerifyUserContext_t * pVerifyUserContext,uint8_t * pSignatureIn,size_t SignatureSizeBytes)303 CEXPORT_C CCError_t EcdsaVerifyFinish(
304 CCEcdsaVerifyUserContext_t *pVerifyUserContext, /*in*/
305 uint8_t *pSignatureIn, /*in*/
306 size_t SignatureSizeBytes /*in*/)
307 {
308 /* FUNCTION DECLARATIONS */
309
310 /* The return error identifier */
311 CCError_t err = CC_OK;
312
313 /* pointer to the active context */
314 EcdsaVerifyContext_t *pWorkingContext;
315 /* pointer to public key structure in ccmWorkingContext */
316 CCEcpkiPublKey_t *PublKey_ptr;
317 /* EC domain ID and pointer to the current domain */
318 /* pointer to the current domain */
319 CCEcpkiDomain_t *pDomain;
320
321 uint32_t *pMessRepres, *pSignatureC, *pSignatureD;
322 uint32_t hashSizeWords;
323 uint32_t orderSizeInBytes, orderSizeInWords;
324
325 /* FUNCTION LOGIC */
326
327 /* the pointer to the internal Verify context */
328 pWorkingContext = (EcdsaVerifyContext_t*)&pVerifyUserContext->context_buff;
329
330 /* ............... checking the parameters validity ................... */
331 /* -------------------------------------------------------------------- */
332
333 /* if the users context pointer is NULL return an error */
334 if (pVerifyUserContext == NULL){
335 return CC_ECDSA_VERIFY_INVALID_USER_CONTEXT_PTR_ERROR;
336 }
337
338 /* if the users context TAG is illegal return an error - the context is invalid */
339 if (pVerifyUserContext->valid_tag != CC_ECDSA_VERIFY_CONTEXT_VALIDATION_TAG){
340 err = CC_ECDSA_VERIFY_USER_CONTEXT_VALIDATION_TAG_ERROR;
341 goto End;
342 }
343
344 /* if the users Signature pointer is illegal then return an error */
345 if (pSignatureIn == NULL){
346 err = CC_ECDSA_VERIFY_INVALID_SIGNATURE_IN_PTR_ERROR;
347 goto End;
348 }
349
350
351 /* ............. checking the validity of context ........ */
352 /* ------------------------------------------------------- */
353
354 /* check Hash mode */
355 if (pWorkingContext->hashMode >= CC_ECPKI_HASH_NumOfModes){
356 err = CC_ECDSA_VERIFY_ILLEGAL_HASH_OP_MODE_ERROR;
357 goto End;
358 }
359
360 PublKey_ptr = (CCEcpkiPublKey_t *)&pWorkingContext->ECDSA_SignerPublKey.PublKeyDbBuff;
361
362 /* Initializing domain parameters */
363 pDomain = &PublKey_ptr->domain;
364 orderSizeInBytes = CALC_FULL_BYTES(pDomain->ordSizeInBits);
365 orderSizeInWords = CALC_FULL_32BIT_WORDS(pDomain->ordSizeInBits);
366
367 /* if the user signature size is not equal to 2*ModSizeInBytes, then return an error */
368 if (SignatureSizeBytes != 2*orderSizeInBytes){
369 err = CC_ECDSA_VERIFY_INVALID_SIGNATURE_SIZE_ERROR;
370 goto End;
371 }
372
373 /*Operating the HASH Finish function only in case that Hash operation is needed*/
374 if (pWorkingContext->hashMode <= CC_ECPKI_HASH_SHA512_mode) {
375 #ifdef USE_MBEDTLS_CRYPTOCELL
376 err = mbedtls_md_finish(&(pWorkingContext->hash_ctx), (unsigned char *)pWorkingContext->hashResult);
377 #else
378 err = CC_HashFinish(&(pWorkingContext->hashUserCtxBuff), pWorkingContext->hashResult);
379 #endif
380 if (err != CC_OK)
381 goto End;
382 }
383
384 /* Initialization of EcWrstDsaVerify arguments */
385 hashSizeWords = pWorkingContext->hashResultSizeWords;
386 /* Temp buffers */
387 pSignatureC = ((EcWrstDsaVerifyDb_t*)(pWorkingContext->ccEcdsaVerIntBuff))->tempBuff;
388 pSignatureD = pSignatureC + orderSizeInWords; /* Max lengths of C in whole words */
389 pMessRepres = pSignatureD + orderSizeInWords;
390
391 // Check shortened cleaning
392 /* Clean memory */
393 CC_PalMemSetZero(pSignatureC, 2*4*orderSizeInWords); //-> pSignatureC[orderSizeInWords-1] = 0;
394 //-> pSignatureD[orderSizeInWords-1] = 0;
395 CC_PalMemSetZero(pMessRepres, 4*orderSizeInWords); //-> pMessRepres[orderSizeInWords-1] = 0;
396
397 /* Derive message representative = leftmost OrderSizeInBits bits of HASH_Result */
398 if (pDomain->ordSizeInBits >= 32*hashSizeWords) {
399 CC_CommonReverseMemcpy((uint8_t*)pMessRepres,
400 (uint8_t*)(pWorkingContext->hashResult), 4*hashSizeWords);
401 } else {
402 EcWrstDsaTruncateMsg(pMessRepres,
403 (uint8_t*)(pWorkingContext->hashResult), pDomain->ordSizeInBits);
404
405 }
406
407 /* Convert signature data to words array with little entian order of *
408 * words */
409 pSignatureC[orderSizeInWords-1] = 0;
410 CC_CommonReverseMemcpy((uint8_t*)pSignatureC, pSignatureIn, orderSizeInBytes);
411 pSignatureD[orderSizeInWords-1] = 0;
412 CC_CommonReverseMemcpy((uint8_t*)pSignatureD, pSignatureIn + orderSizeInBytes, orderSizeInBytes);
413
414 /*------------------------------*/
415 /* Verifying operation */
416 /*------------------------------*/
417 err = EcWrstDsaVerify(PublKey_ptr, pMessRepres, orderSizeInWords, pSignatureC, pSignatureD);
418 if (err != CC_OK) {
419 err = CC_ECDSA_VERIFY_INCONSISTENT_VERIFY_ERROR;
420 }
421
422 End:
423 #ifdef USE_MBEDTLS_CRYPTOCELL
424 mbedtls_md_free(&(pWorkingContext->hash_ctx));
425 #endif
426
427 /* clear the users context */
428 CC_PalMemSetZero(pVerifyUserContext, sizeof(CCEcdsaVerifyUserContext_t));
429
430 return err;
431
432
433 }/* End EcdsaVerifyFinish */
434
435
436 /**************************************************************************
437 * CC_EcdsaVerify integrated function
438 **************************************************************************/
439 /**
440 @brief Performs all ECDSA verifying operations simultaneously.
441
442 This function simply calls the Init, Update and Finish functions continuously.
443
444 NOTE: Using of HASH functions with HASH size great, than EC modulus size,
445 is not recommended!
446 Algorithm according ANS X9.62 standard
447
448
449 @param[in] pVerifyUserContext - A pointer to the user buffer for verifying database.
450 @param[in] pUserPublKey - A pointer to a user public key structure.
451 @param[in] hashMode - The enumerator variable defines the hash function to be used.
452 @param[in] pMessageDataIn - Message data for calculating hash.
453 @param[in] messageSizeInBytes - Size of block of message data in bytes.
454 @param[in] pSignatureIn - A pointer to a buffer for output of signature.
455 @param[in] SignatureSizeBytes - Size of signature, in bytes (must be 2*orderSizeInBytes).
456
457 @return <b>CCError_t</b>: <br>
458 CC_OK <br>
459 CC_ECDSA_VERIFY_INVALID_USER_CONTEXT_PTR_ERROR <br>
460 CC_ECDSA_VERIFY_USER_CONTEXT_VALIDATION_TAG_ERROR <br>
461 CC_ECDSA_VERIFY_INVALID_DOMAIN_ID_ERROR <br>
462 CC_ECDSA_VERIFY_INVALID_SIGNER_PUBL_KEY_PTR_ERROR <br>
463 CC_ECDSA_VERIFY_SIGNER_PUBL_KEY_VALIDATION_TAG_ERROR <br>
464 CC_ECDSA_VERIFY_ILLEGAL_HASH_OP_MODE_ERROR <br>
465 CC_ECDSA_VERIFY_INVALID_MESSAGE_DATA_IN_PTR_ERROR <br>
466 CC_ECDSA_VERIFY_INVALID_MESSAGE_DATA_IN_SIZE_ERROR <br>
467 CC_ECDSA_VERIFY_INVALID_SIGNATURE_IN_PTR_ERROR <br>
468 CC_ECDSA_VERIFY_INVALID_SIGNATURE_SIZE_ERROR <br>
469 CC_ECDSA_VERIFY_INCONSISTENT_VERIFY_ERROR <br>
470 **/
CC_EcdsaVerify(CCEcdsaVerifyUserContext_t * pVerifyUserContext,CCEcpkiUserPublKey_t * pUserPublKey,CCEcpkiHashOpMode_t hashMode,uint8_t * pSignatureIn,size_t SignatureSizeBytes,uint8_t * pMessageDataIn,size_t messageSizeInBytes)471 CEXPORT_C CCError_t CC_EcdsaVerify (
472 CCEcdsaVerifyUserContext_t *pVerifyUserContext, /*in/out*/
473 CCEcpkiUserPublKey_t *pUserPublKey, /*in*/
474 CCEcpkiHashOpMode_t hashMode, /*in*/
475 uint8_t *pSignatureIn, /*in*/
476 size_t SignatureSizeBytes, /*in*/
477 uint8_t *pMessageDataIn, /*in*/
478 size_t messageSizeInBytes /*in*/)
479 {
480 /* FUNCTION DECLERATIONS */
481
482 CCError_t err = CC_OK;
483
484 /* FUNCTION LOGIC */
485 CHECK_AND_RETURN_ERR_UPON_FIPS_ERROR();
486
487
488 err = EcdsaVerifyInit(pVerifyUserContext, pUserPublKey, hashMode);
489
490 if (err!=CC_OK)
491 return err;
492
493 err = EcdsaVerifyUpdate(pVerifyUserContext, pMessageDataIn, messageSizeInBytes);
494 if (err!=CC_OK)
495 return err;
496
497 err = EcdsaVerifyFinish(pVerifyUserContext, pSignatureIn,
498 SignatureSizeBytes);
499 return err;
500
501 }/* END OF CC_EcdsaVerify */
502
503