1 /*
2 * Copyright (c) 2001-2019, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 /************* Include Files ****************/
8 #include "cc_pal_mem.h"
9 #include "cc_pal_types_plat.h"
10 #include "cc_pal_types.h"
11 #include "cc_rnd_common.h"
12 #include "cc_common.h"
13 #include "cc_common_math.h"
14 #include "cc_rsa_types.h"
15 #include "cc_hash_defs.h"
16 #include "mbedtls_cc_hkdf.h"
17 #include "pki.h"
18 #include "rsa.h"
19 #include "cc_ffc_domain_error.h"
20 #include "cc_ffc_domain.h"
21 #include "cc_rnd_error.h"
22 #include "cc_fips_defs.h"
23 #include "cc_general_defs.h"
24
25
26 /************************ Defines *******************************/
27
28 /************************ Enums *********************************/
29
30 /************************ macros ********************************/
31
32 /** @brief This macro is required to remove compilers warnings if the HASH or PKI is not supported */
33
34
35 /*********************** Global data ***************************/
36
37 //extern CCFfcDomainParamSizes_t ffcDomainParamSizes[CC_FFC_DOMAIN_PARAMS_SET_NUM_OFF_MODE];
38 //extern CCFfcDhHashBlockAndDigestSizes_t FfcDhHashBlockAndDigestSizes[CC_FFCDH_HASH_NUM_OFF_MODE];
39
40 extern CCError_t RsaPrimeTestCall(CCRndContext_t *pRndContext, uint32_t *pPrimeP, int32_t sizeWords,
41 int32_t rabinTestsCount, int8_t *pIsPrime, uint32_t *pTempBuff,
42 CCRsaDhPrimeTestMode_t primeTestMode);
43
44 /************* External functions prototypes *****************************/
45
46 //static
47 CCError_t RndGenerateWordsArrayInRange(CCRndContext_t *pRndContext,
48 uint32_t rndSizeInBits,
49 uint32_t *maxVect_ptr,
50 uint32_t *rndVect_ptr,
51 uint32_t *tmp_ptr);
52
53 /************************ Private Functions ******************************/
54
55 /* This function translates the DH-Hash modes into HASH and KDF-Hash modes
56 * and gives HASH block and digest sizes (in bytes). Note: the function sets on output
57 * only required parameters, which pointers are not NULL.
58 * */
FfcGetHashMode(CCHashOperationMode_t * pHashMode,mbedtls_hkdf_hashmode_t * pHkdfHashMode,uint32_t * pBlockSize,uint32_t * pDigestSize,CCFfcHashOpMode_t ffcHashMode)59 CCError_t FfcGetHashMode(CCHashOperationMode_t *pHashMode, /* optional */
60 mbedtls_hkdf_hashmode_t *pHkdfHashMode, /* optional */
61 uint32_t *pBlockSize, /* optional */
62 uint32_t *pDigestSize, /* optional */
63 CCFfcHashOpMode_t ffcHashMode) /* FFC HASH mode */
64 {
65 CCError_t err = CC_OK;
66 CCHashOperationMode_t hashMode;
67 mbedtls_hkdf_hashmode_t hkdfHashMode;
68 size_t blockize, digestSize;
69
70 blockize = CC_HASH_BLOCK_SIZE_IN_BYTES; /* for all modes besides SHA384, SHA512 */
71 switch (ffcHashMode) {
72 case CC_FFC_HASH_SHA1_MODE:
73 hashMode = CC_HASH_SHA1_mode;
74 hkdfHashMode = CC_HKDF_HASH_SHA1_mode;
75 digestSize = CC_HASH_SHA1_DIGEST_SIZE_IN_BYTES;
76 break;
77 case CC_FFC_HASH_SHA224_MODE:
78 hashMode = CC_HASH_SHA224_mode;
79 hkdfHashMode = CC_HKDF_HASH_SHA224_mode;
80 digestSize = CC_HASH_SHA224_DIGEST_SIZE_IN_BYTES;
81 break;
82 case CC_FFC_HASH_SHA256_MODE:
83 hashMode = CC_HASH_SHA256_mode;
84 hkdfHashMode = CC_HKDF_HASH_SHA256_mode;
85 digestSize = CC_HASH_SHA256_DIGEST_SIZE_IN_BYTES;
86 break;
87 case CC_FFC_HASH_SHA384_MODE:
88 hashMode = CC_HASH_SHA384_mode;
89 hkdfHashMode = CC_HKDF_HASH_SHA384_mode;
90 blockize = CC_HASH_SHA512_BLOCK_SIZE_IN_BYTES;
91 digestSize = CC_HASH_SHA384_DIGEST_SIZE_IN_BYTES;
92 break;
93 case CC_FFC_HASH_SHA512_MODE:
94 hashMode = CC_HASH_SHA512_mode;
95 hkdfHashMode = CC_HKDF_HASH_SHA512_mode;
96 digestSize = CC_HASH_SHA512_DIGEST_SIZE_IN_BYTES;
97 blockize = CC_HASH_SHA512_BLOCK_SIZE_IN_BYTES;
98 break;
99 default:
100 return CC_FFC_DOMAIN_INVALID_HASH_MODE_ERROR;
101 }
102
103 /* output required parameters only */
104 if(pHashMode != NULL)
105 *pHashMode = hashMode;
106 if(pHkdfHashMode != NULL)
107 *pHkdfHashMode = hkdfHashMode;
108 if(pDigestSize != NULL)
109 *pDigestSize = digestSize;
110 if(pBlockSize != NULL)
111 *pBlockSize = blockize;
112
113 return err;
114 }
115
116 /*!
117 * The function returns FFC Domain parameters sizes according to given ID of
118 * approved set of Domain parameters FA,FB or FC (see SP 800-56A and FIPS 186-4 sec.1 standards).
119 *
120 */
FfcGetDomainSizes(uint32_t * pMaxSecurStrength,uint32_t * pPrimeLen,uint32_t * pOrderLen,uint32_t * pMinHashLen,CCFfcParamSetId_t ffcParamSetId)121 CCError_t FfcGetDomainSizes(
122 uint32_t *pMaxSecurStrength, /*!< Maximum security strength supported, in bits. */
123 uint32_t *pPrimeLen, /*!< Field (prime P) length in bytes. */
124 uint32_t *pOrderLen, /*!< Subgroup order Q length in bytes. */
125 uint32_t *pMinHashLen, /*!< Minimum length of HASH output in bytes. */
126 CCFfcParamSetId_t ffcParamSetId) /*!< Enum. defining set of lengths of domain parameters, approved
127 by SP 800-56A and FIPS 186-4 standards */
128 {
129 CCError_t err = CC_OK;
130 CCFfcDomainParamSizes_t *pParamsSet;
131 /*! Define and initialize DH domain parameters sizes array */
132 CCFfcDomainParamSizes_t ffcDomainParamSizes[(uint32_t)CC_FFC_PARAMS_SET_NUM_OFF_MODE] =
133 CC_FFC_DOMAIN_PARAM_SIZES_SET;
134
135 if(ffcParamSetId >= CC_FFC_PARAMS_SET_NUM_OFF_MODE)
136 return CC_FFC_DOMAIN_INVALID_SIZES_SET_ID_ERROR;
137
138 pParamsSet = &ffcDomainParamSizes[ffcParamSetId];
139
140 if(pMaxSecurStrength != NULL)
141 *pMaxSecurStrength = pParamsSet->maxSecurStrength;
142 if(pPrimeLen != NULL)
143 *pPrimeLen = pParamsSet->primeSize >> 3;
144 if(pOrderLen != NULL)
145 *pOrderLen = pParamsSet->orderSize >> 3;
146 if(pMinHashLen != NULL)
147 *pMinHashLen = pParamsSet->minHashLen >> 3;
148
149 return err;
150 }
151
152
153
154
155
156 /******************************************************************************************/
157 /************************ Private Functions ******************************/
158 /******************************************************************************************/
159
160 /********************************************************************************/
161 /**
162 * The function adds value to the number N, presented as bytes array, where MSbyte
163 * is a most left one.
164 *
165 * Algorithm: N = (N + val) mod 2^(8*sizeBytes).
166 * Assumed: The array and its size are aligned to 32-bit words.
167 *
168 * @return carry from last addition
169 */
170 static
FfcAddValueToMsbLsbBytesArray(uint8_t * pArr,uint32_t val,uint32_t sizeBytes)171 uint8_t FfcAddValueToMsbLsbBytesArray(uint8_t *pArr, uint32_t val, uint32_t sizeBytes)
172 {
173 int32_t i;
174 uint32_t word, carry;
175
176 /* check input data */
177 // if(((uint32_t)pArr & 3) || (sizeBytes % 4) || (sizeBytes == 0)) {
178 // return CC_FFC_DOMAIN_BUFFER_ALIGNMENTS_ERROR;
179 // }
180
181 carry = val;
182 for (i = sizeBytes - 1; i >= 0; i -= 4) {
183 /*set input bytes to word */
184 word = pArr[i-3]; word = (word<<8) | pArr[i-2];
185 word = (word<<16) | pArr[i-1]; word = (word<<24) | pArr[i];
186 carry += word;
187 /* set 4 bytes of sum into array */
188 pArr[i] = carry & 0xFF; pArr[i-1] = (carry>>8) & 0xFF;
189 pArr[i-2] = (carry>>16) & 0xFF; pArr[i-3] = (carry>>24) & 0xFF;
190
191 carry = (carry < word);
192 }
193
194 return (uint8_t)(carry & 1);
195 }
196
197 #define FFC_CMP_BE2LE_FIRST_GREAT 1
198 #define FFC_CMP_BE2LE_FIRST_SMALL -1
199 #define FFC_CMP_BE2LE_EQUALLED 0
200
201
202 /** The function compares two big numbers, presented by:
203 * - the first as BE bytes array, the second - as LE 32-bit words array.
204 *
205 * Note: assumed, that sizes in bytes of both arrays are equalled.
206 * in the first buffer
207 */
208 static
FfcCmpBeBytes2LeWordsBigNum(uint8_t * pBeBytes,uint32_t * pLeWords,size_t sizeWords)209 int32_t FfcCmpBeBytes2LeWordsBigNum(uint8_t *pBeBytes, uint32_t *pLeWords, size_t sizeWords)
210 {
211 int32_t i, j, cmp;
212 uint32_t word;
213
214 cmp = FFC_CMP_BE2LE_EQUALLED;
215 i = 0;
216 for (j = sizeWords-1; j >= 0; j--) {
217 /*set 4 input bytes to word */
218 word = pBeBytes[i++]; word = (word<<8) | pBeBytes[i++];
219 word = (word<<8) | pBeBytes[i++]; word = (word<<8) | pBeBytes[i++];
220 if(word > pLeWords[i]) {
221 cmp = FFC_CMP_BE2LE_FIRST_GREAT;
222 } else if(word < pLeWords[i]){
223 cmp = FFC_CMP_BE2LE_FIRST_SMALL;
224 }
225 }
226
227 return cmp;
228 }
229
230
231
232 #ifdef FFC_FURTHER_USING
233 /********************************************************************************/
234 /**
235 * @brief This function returns the effective size in bits of the MSB bytes array.
236 *
237 * Assumed, that MSB > 0 is stored in the most left cell in the array.
238 *
239 * @param[in] arr_ptr - The counter buffer.
240 * @param[in] sizeInBytes - The counter size in bytes.
241 *
242 * @return result - The effective counters size in bits.
243 */
244
245 //static
FfcGetSizeInBitsOfMsbLsbBytesArray(uint8_t * arr_ptr,uint32_t sizeInBytes)246 uint32_t FfcGetSizeInBitsOfMsbLsbBytesArray(uint8_t *arr_ptr,
247 uint32_t sizeInBytes)
248 {
249 /* FUNCTION LOCAL DECLERATIONS */
250
251 /* loop variable */
252 int32_t i;
253
254 /* the effective size in bits */
255 uint32_t sizeInBits = 8 * sizeInBytes;
256
257 /* the effective MS byte */
258 uint8_t msbVal = arr_ptr[0], mask = 0x80;
259
260 /* FUNCTION LOGIC */
261
262 /* adjusting the effective size in bits */
263 for (i = 0; i < 8 ; i++) {
264 /* if the MS bit is set exit the loop */
265 if (msbVal & mask) {
266 break;
267 }
268
269 sizeInBits--;
270
271 mask >>= 1;
272
273 }
274
275 return sizeInBits;
276
277 }/* END OF FfcDhKgGetSizeInBitsOfMsbLsbBytesArray */
278 #endif
279
280
281 /**
282 * The function returns count of Rabin-Miller tests, required for generation
283 * primes in FFC DSA and DH algorithms according to FIPS 186-4, sec. C.3: Tab. C.1.
284 *
285 * If input size not meets one of standard sizes of FFC Prime modulus or Order,
286 * then the function returns an error.
287 */
288 static
FfcGetCountOfRabMilTests(uint32_t * pCountTests,size_t primeSizeBits)289 CCError_t FfcGetCountOfRabMilTests(uint32_t *pCountTests, size_t primeSizeBits)
290 {
291 switch(primeSizeBits) {
292 /* sizes set for FFC Order */
293 case 160:
294 *pCountTests = 19;
295 break;
296 case 224:
297 *pCountTests = 24;
298 break;
299 case 256:
300 *pCountTests = 27;
301 break;
302 /* sizes set for FFC Prime modulus */
303 case 1024:
304 *pCountTests = 3;
305 break;
306 case 2048:
307 *pCountTests = 3;
308 break;
309 case 3072:
310 *pCountTests = 2;
311 break;
312 default:
313 return CC_FFC_DOMAIN_INVALID_ARGUMENT_SIZE_ERROR;
314 }
315
316 return CC_OK;
317 }
318
319
320 /**
321 * The function checks that ptr != NULL and outSize <= buffSize .
322 *
323 * In case the user gives both output pointer and size equal to zero,
324 * then the function ignores any checking and exits with OK
325 */
326 static
FfcCheckPtrAndSize(void * pOut,size_t * pBuffSizeBytes,void * pIn,size_t inSizeBytes)327 CCError_t FfcCheckPtrAndSize(void *pOut, size_t *pBuffSizeBytes, void *pIn, size_t inSizeBytes) {
328
329 CCError_t err = CC_OK;
330
331 if((pOut == NULL) && (pBuffSizeBytes == NULL)) {
332 goto End;
333 }
334
335 if((pOut == NULL) || (pIn == NULL)) {
336 err = CC_FFC_DOMAIN_INVALID_ARGUMENT_PTR_ERROR;
337 goto End; \
338 }
339
340 if(inSizeBytes > *pBuffSizeBytes) {
341 err = CC_FFC_DOMAIN_INVALID_ARGUMENT_SIZE_ERROR;
342 goto End;
343 }
344
345 End:
346 return err;
347 }
348
349
350 /**
351 * The function finds prime Order Q for FFC Domain generation according to FIPS 186-4 sec.A.i.2.
352 *
353 * Note: Sizes in bytes of P, Q, HASH should be multiple of 4.
354 * Size of pTmp buffer = 3*PrimeSizeWords + orderSizeWords + 1.
355 */
356 static
FfcFips186v4FindOrderQ(CCFfcDomain_t * pDomain,CCRndContext_t * pRndContext,CCFfcGenerateSeed_t generateSeed,CCFfcDomainTmpBuff_t * pTmpBuff)357 CCError_t FfcFips186v4FindOrderQ(
358 CCFfcDomain_t *pDomain, /* [in/out] pointer to FFC Domain. */
359 CCRndContext_t *pRndContext, /* [in] context defining used random function and state. */
360 CCFfcGenerateSeed_t generateSeed, /*in*/
361 CCFfcDomainTmpBuff_t *pTmpBuff) /*!< [in] pointer to FFC Domain temp buffer structure. */{
362
363 /* FUNCTION DECLARATIONS */
364
365 /* The return error identifier */
366 CCError_t err = CC_OK;
367
368 /* random function given by the user */
369 CCRndState_t *pRndState;
370 CCRndGenerateVectWorkFunc_t RndGenerateVectFunc;
371 uint32_t *pOrder; /*out, LE words */
372 uint32_t orderSizeWords, orderSizeBytes; /*in*/
373 uint8_t *pSeed; /*BE bytes array */
374 uint32_t seedSizeBytes, hashDigestSize;
375 /* primality flag (if prime, then isPrime = 1, else 0 ) */
376 int8_t isPrime;
377 uint32_t *pHashData, *pTmp1;
378 uint32_t countRabMilTests;
379 CCHashOperationMode_t hashMode;
380 const mbedtls_md_info_t *md_info=NULL;
381
382 /* check some parameters */
383 CHECK_AND_SET_ERROR((pDomain == NULL), CC_FFC_DOMAIN_INVALID_DOMAIN_PTR_ERROR);
384 CHECK_AND_SET_ERROR((pRndContext == NULL), CC_FFC_DOMAIN_INVALID_RND_CTX_PTR_ERROR);
385
386 /* INITIALIZATION */
387
388 pRndState = (CCRndState_t*)&(pRndContext->rndState);
389 RndGenerateVectFunc = pRndContext->rndGenerateVectFunc;
390
391 pOrder = pDomain->order;
392 orderSizeBytes = pDomain->ordLenWords * CC_32BIT_WORD_SIZE;
393 orderSizeWords = pDomain->ordLenWords;
394 pSeed = pDomain->seed;
395 seedSizeBytes = pDomain->seedSizeBytes;
396 hashDigestSize = pDomain->hashDigestSize;
397 /* set temp buffers */
398 pHashData = (uint32_t*)&pTmpBuff->TmpBuff[0]; /*orderSizeWords+1*/
399 pTmp1 = pHashData + orderSizeWords + 1; /*buffer 3*PrimeSizeWords*/
400
401 /* FUNCTION LOGIC */
402
403 /* zeroing word, next after MSWord of Q, for carry, which can occur
404 * in P generation function. */
405 pOrder[orderSizeWords] = 0;
406
407 /* get count of R-M tests */
408 CHECK_ERROR(FfcGetCountOfRabMilTests(&countRabMilTests, orderSizeBytes*CC_BITS_IN_BYTE));
409 /* get HASH related parameters */
410 CHECK_ERROR(FfcGetHashMode(&hashMode, NULL/*pHkdfHashMode*/, NULL/*pBlockSize*/, NULL, pDomain->ffcHashMode/*in*/));
411
412 md_info = mbedtls_md_info_from_string( HashAlgMode2mbedtlsString[hashMode] );
413 if (NULL == md_info) {
414 err = CC_FFC_DOMAIN_GENERATION_FAILURE_ERROR;
415 goto End;
416 }
417
418 /*-------------------------------------------------*/
419 /* FFC prime Order generation loop */
420 /*-------------------------------------------------*/
421 while(1) {
422 /* Create random domain seed sec.A.1.1.2. */
423 if(generateSeed == CC_FFC_GENERATE_NEW_SEED) {
424 CHECK_ERROR(RndGenerateVectFunc(pRndState, pSeed, seedSizeBytes));
425 }
426
427 err = mbedtls_md(md_info, pSeed, seedSizeBytes, (unsigned char *)pHashData);
428 if (err) {
429 goto End;
430 }
431
432 /* copy min(orderSizeBytes, hashDigestSize) bytes from HASH result to order Q buffer:
433 * steps 5,6,7 of sec.A.1.1.2 process: U = HASH(seed) mod 2^(OrdSizeInBits-1) */
434 if(orderSizeBytes >= hashDigestSize) {
435 CC_PalMemCopy((uint8_t*)pOrder + orderSizeBytes - hashDigestSize, (uint8_t*)pHashData, hashDigestSize);
436 } else {
437 CC_PalMemCopy((uint8_t*)pOrder, (uint8_t*)pHashData + hashDigestSize - orderSizeBytes, orderSizeBytes);
438 }
439 /* set MS and LS bits of order Q to 1 */
440 pOrder[0] |= 0x80000000;
441 pOrder[orderSizeWords - 1] |= 0x00000001;
442
443 /* convert pOrder to LE words array for primality testing */
444 CHECK_ERROR(CC_CommonConvertMsbLsbBytesToLswMswWords(
445 pOrder, orderSizeBytes, (uint8_t*)pOrder, orderSizeBytes));
446
447 /* test primality of Order */
448 CHECK_ERROR(RsaPrimeTestCall(pRndContext, pOrder, orderSizeWords,
449 countRabMilTests, &isPrime, pTmp1,
450 (CCFfcPrimeTestMode_t)CC_FFC_PRIME_TEST_MODE));
451 if(isPrime) {
452 goto End;
453 } else {
454 /* if seed is given, but Q is not prime, then return an error */
455 CHECK_AND_SET_ERROR((generateSeed == CC_FFC_USE_GIVEN_SEED) && (isPrime == 0),
456 CC_FFC_DOMAIN_GENERATION_FAILURE_ERROR);
457 }
458 }
459
460
461 /* End of function */
462 End:
463 if(err) {
464 CC_PalMemSetZero(pDomain, sizeof(CCFfcDomain_t));
465 CC_PalMemSetZero(pTmpBuff, sizeof(CCFfcDomainTmpBuff_t));
466 }
467
468 return err;
469
470 } /* End of FfcFips186v4FindOrderQ */
471
472
473 /**
474 * The function finds prime Order Q for FFC Domain generation according to FIPS 186-4 sec.A.i.2.
475 *
476 * Note: Sizes in bytes of P, Q, HASH should be multiple of 4.
477 * Size in words of pTmp buffer should be not less than
478 * (2MaxModSize + MaxHashSize + 2MaxOrdeSize + 2).
479 */
480 static
FfcFips186v4FindPrimeP(CCFfcDomain_t * pDomain,CCRndContext_t * pRndContext,int8_t * pIsPrime,CCFfcDomainTmpBuff_t * pTmpBuff)481 CCError_t FfcFips186v4FindPrimeP(
482 CCFfcDomain_t *pDomain, /* [in/out] pointer to FFC Domain. */
483 CCRndContext_t *pRndContext, /* [in] context defining used random function and state. */
484 int8_t *pIsPrime, /* [out] pointer to indication, that prime is found. */
485 CCFfcDomainTmpBuff_t *pTmpBuff) /*!< [in] pointer to FFC Domain temp buffer structure. */{
486
487 /* FUNCTION DECLARATIONS */
488
489 /* The return error identifier */
490 CCError_t err = CC_OK;
491
492 /* primality flag (if prime, then isPrime = 1, else 0 ) */
493 uint32_t j, offset;
494 uint32_t counter, countBlocks;
495 uint32_t primeSizeBytes, primeSizeWords, remainBytes;
496 uint32_t *pOrder, *pPrimeP; /*LE words */
497 uint32_t *pCurrPtr;
498 uint32_t orderSizeBytes, orderSizeWords;
499 uint8_t *pHashInput; /*BE bytes array*/
500 uint32_t seedSizeBytes, hashDigestSize;
501 uint32_t countRabMilTests; /*count of Rabin-Miller tests*/
502 /* temp buffers */
503 uint32_t *p2Q, *pRemC, *pTmp1;
504 uint32_t addValue;
505 CCHashOperationMode_t hashMode;
506 const mbedtls_md_info_t *md_info=NULL;
507
508 /* minimal check of some parameters */
509 CHECK_AND_SET_ERROR(pDomain == NULL, CC_FFC_DOMAIN_INVALID_DOMAIN_PTR_ERROR);
510 CHECK_AND_SET_ERROR(pRndContext == NULL, CC_FFC_DOMAIN_INVALID_RND_CTX_PTR_ERROR);
511
512 /* INITIALIZATION */
513
514 pPrimeP = pDomain->prime;
515 primeSizeWords = pDomain->modLenWords;
516 primeSizeBytes = primeSizeWords*CC_32BIT_WORD_SIZE;
517 pOrder = pDomain->order;
518 orderSizeBytes = pDomain->ordLenWords*CC_32BIT_WORD_SIZE;
519 orderSizeWords = orderSizeBytes;
520 seedSizeBytes = pDomain->seedSizeBytes;
521 hashDigestSize = pDomain->hashDigestSize;
522
523 /* set pointers to temp buffers. Total max size of pTmp buffer in words:
524 * (2MaxModSize + MaxHashSize + 2MaxOrdeSize + 2) = 194 words for
525 * ModSz=2048bit and OrdSz=256bit, or 258 words for ModSz=3072bit */
526 p2Q = (uint32_t*)&pTmpBuff->TmpBuff[0]; /*buffer for 2*Q, size=orderSizeWords+1. */
527 pRemC = p2Q + orderSizeWords+1; /*buffer for remainder C of size = orderSizeWords+1.*/
528 pHashInput = (uint8_t*)(pRemC + orderSizeWords+1); /*buffer for hash-input data of size = seedSizeWords.*/
529 pTmp1 = pRemC + orderSizeWords+1 + seedSizeBytes/CC_32BIT_WORD_SIZE; /*buffer of size = 3*primeSizeWords.*/
530
531 /* n = count of full HASH blocks in prime P. */
532 countBlocks = primeSizeBytes / hashDigestSize; /* n */
533 remainBytes = primeSizeBytes % hashDigestSize; /*not full block size*/
534
535
536 /* FUNCTION LOGIC */
537
538 *pIsPrime = CC_FALSE;
539 offset = 1;
540
541 /* get count of R-M tests */
542 CHECK_ERROR(FfcGetCountOfRabMilTests(&countRabMilTests, primeSizeBytes*CC_BITS_IN_BYTE));
543
544 /* get HASH related parameters */
545 CHECK_ERROR(FfcGetHashMode(&hashMode, NULL/*pHkdfHashMode*/, NULL/*pBlockSize*/, NULL, pDomain->ffcHashMode/*in*/));
546
547 /* calculate p2Q = 2*Q with setting carry into MS word */
548 p2Q[orderSizeWords] = CC_CommonAdd2vectors(pOrder, pOrder, orderSizeWords, p2Q/*res*/);
549 /* copy seed into hashing buffer */
550 CC_PalMemCopy(pHashInput, pDomain->seed, seedSizeBytes);
551
552 md_info = mbedtls_md_info_from_string( HashAlgMode2mbedtlsString[hashMode] );
553 if (NULL == md_info) {
554 err = CC_FFC_DOMAIN_GENERATION_FAILURE_ERROR;
555 goto End;
556 }
557
558 /* try to generate prime P up to 4*primeSizeInBits times; if not successes,
559 * then return an error (sec. A.1.1.2, process: 11). */
560 for(counter = 0; counter < 4*primeSizeBytes*CC_BITS_IN_BYTE; counter++) {
561 /* Create primeP using HASH and Seed sec.A.1.1.2. */
562 pCurrPtr = pPrimeP;
563
564 for(j = 0; j < countBlocks; j++) {
565 addValue = offset + j;
566 FfcAddValueToMsbLsbBytesArray(pHashInput, addValue, seedSizeBytes/CC_32BIT_WORD_SIZE);
567
568 err = mbedtls_md(md_info, pHashInput, seedSizeBytes, (unsigned char*)pCurrPtr);
569 if (err) {
570 goto End;
571 }
572
573 pCurrPtr += hashDigestSize/CC_32BIT_WORD_SIZE;
574 }
575
576 if(remainBytes > 0) {
577 addValue = offset + j;
578 FfcAddValueToMsbLsbBytesArray(pHashInput, addValue, seedSizeBytes/CC_32BIT_WORD_SIZE);
579
580 err = mbedtls_md(md_info, pHashInput, seedSizeBytes, (unsigned char*)pRemC); /*temporary use pRemC*/
581 if (err) {
582 goto End;
583 }
584
585 CC_PalMemCopy((uint8_t*)pCurrPtr, (uint8_t*)pRemC, remainBytes);
586 }
587
588 /* zero remaining (redundant) last bytes */
589
590 /* set MsBit of prime to 1 */
591 ((uint8_t*)pPrimeP)[0] |= 0x80;
592
593 /*zero additional words for carry */
594 pPrimeP[primeSizeWords] = 0;
595 p2Q[orderSizeWords] = 0;
596
597 /* convert prime to LE words */
598 CC_CommonInPlaceConvertBytesWordsAndArrayEndianness(pPrimeP, primeSizeWords);
599
600 /* calculate P so that P = 1 mod(2*Q) */
601 /*------------------------------------*/
602 /* calculate remainder C = P % 2Q */
603 CHECK_ERROR(PkiLongNumDiv(pPrimeP/*numerator*/, primeSizeWords, p2Q/*divider*/,
604 orderSizeWords+1, pRemC/*remainder C*/, pTmp1/*DivRes - not used*/));
605
606 /* P = P-(C-1): if P odd then C=C-1, else P=P+1 and then P=P-C */
607 if((pPrimeP[0] & 1UL) == 1) {
608 pRemC[0]--;
609 } else {
610 pPrimeP[0]++;
611 }
612 CC_CommonSubtractUintArrays(pPrimeP, pRemC, primeSizeWords, pPrimeP/*res*/);
613
614 /* if P>2^(L-1) then test prime, else increase offset and repeat generation */
615 if((pPrimeP[primeSizeWords-1] & 0x80000000) != 0) {
616 CHECK_ERROR(RsaPrimeTestCall(pRndContext, pPrimeP, primeSizeWords, countRabMilTests,
617 pIsPrime, pTmp1, (CCRsaDhPrimeTestMode_t)CC_FFC_PRIME_TEST_MODE));
618
619 if(*pIsPrime == 1) { /* the prime is found */
620 /* set counter into Domain */
621 pDomain->genCounter = counter;
622 goto End;
623 }
624 }
625
626 /* repeat generation of prime P with new offset*/
627 offset += (countBlocks+1);
628 }
629
630 /* if reached this row, then the function exits for further
631 * continuing generation of new Q and P */
632
633 /* End of function */
634 End:
635
636 if(err) {
637 CC_PalMemSetZero(pDomain, sizeof(CCFfcDomain_t));
638 CC_PalMemSetZero(pTmpBuff, sizeof(CCFfcDomainTmpBuff_t));
639 }
640
641 return err;
642
643 } /* End of FfcFips186v4FindPrimeP */
644
645
646 /**
647 * The function creates FFC sub-group Generator Q according to FIPS 186-4 sec.A.2.3
648 *
649 * Note: Sizes in bytes of P, Q, HASH should be multiple of 4.
650 * Size in words of pTmp buffer should be not less than
651 * (2MaxModSize + MaxHashSize + 2MaxOrdeSize + 2).
652 */
653 static
FfcFips186v4CreateGenerator(CCFfcDomain_t * pDomain,CCRndContext_t * pRndContext,uint8_t index,CCFfcDomainTmpBuff_t * pTmpBuff)654 CCError_t FfcFips186v4CreateGenerator(
655 CCFfcDomain_t *pDomain, /* [in/out] pointer to FFC Domain. */
656 CCRndContext_t *pRndContext, /* [in] context defining used random function and state. */
657 uint8_t index, /* [in] index of FFC Generator, allowing to generate different
658 Generators for the same FFC parameters Prime P and Order Q. */
659 CCFfcDomainTmpBuff_t *pTmpBuff) /*!< [in] pointer to FFC Domain temp buffer structure. */{
660 /* FUNCTION DECLARATIONS */
661
662
663 CCError_t err = CC_OK;
664 uint16_t count = 0; /*loop counter*/
665 size_t primeSizeBytes;
666 uint32_t *pPrimeP; /*LE words */
667 size_t hashDataSizeBytes;
668 uint8_t *pIndex;/* point on index inside the hashData*/
669 uint8_t ggen[4] = {0x67,0x67,0x65,0x6E};
670 uint32_t one = 1;
671 CCCommonCmpCounter_t cmp;
672 CCHashOperationMode_t hashMode;
673 const mbedtls_md_info_t *md_info=NULL;
674
675 /* pointers to temp buffers: for variables E, U, W,
676 * named in the said standard sec; */
677 uint32_t *pDivResE/*e*/, *pHashDataU/*u*/, *pHashResW/*W*/, *pTmp1/*dummy*/;
678
679 CHECK_AND_SET_ERROR((pDomain == NULL), CC_FFC_DOMAIN_INVALID_DOMAIN_PTR_ERROR);
680 CHECK_AND_SET_ERROR((pRndContext == NULL), CC_FFC_DOMAIN_INVALID_RND_CTX_PTR_ERROR);
681 CHECK_AND_SET_ERROR((pDomain->validTag != CC_FFC_DOMAIN_VALIDATION_TAG),
682 CC_FFC_DOMAIN_VALIDATION_TAG_ERROR);
683
684 /* FUNCTION LOGIC */
685
686 primeSizeBytes = pDomain->modLenWords * CC_32BIT_WORD_SIZE;
687 pPrimeP = pDomain->prime;
688
689 /* set pointers and calculate W = HASH of U */
690
691 pHashResW = (uint32_t*)&pTmpBuff->TmpBuff[0]; /* buffer size CC_FFC_DOMAIN_MAX_GENER_ORDER_SIZE_IN_BYTES + 12 */
692 pHashDataU = pHashResW + pDomain->hashDigestSize / CC_32BIT_WORD_SIZE;
693
694
695 /* repeat generation while count != 0 */
696 count = 1;
697
698 while(count != 0) {
699 /*-----------------------------------------*/
700 /* set U data = Seed||"ggen"||index||count */
701 /*-----------------------------------------*/
702 pIndex = (uint8_t*)pHashDataU; /*now used as temporary pointer*/
703 CC_PalMemCopy(pIndex, pDomain->seed, pDomain->seedSizeBytes);
704 pIndex += pDomain->seedSizeBytes;
705 CC_PalMemCopy(pIndex, ggen, sizeof(ggen));
706 pIndex += sizeof(ggen);
707 *pIndex = index;
708 /* copy counter after address, pointed by pIndex*/
709 pIndex[1] = count & 0xFF; pIndex[2] = (count>>8) & 0xFF;
710 hashDataSizeBytes = pDomain->seedSizeBytes + sizeof(ggen) + sizeof(count) + 1/*index*/;
711
712 /* get HASH related parameters */
713 CHECK_ERROR(FfcGetHashMode(&hashMode, NULL/*pHkdfHashMode*/, NULL/*pBlockSize*/, NULL, pDomain->ffcHashMode/*in*/));
714
715 md_info = mbedtls_md_info_from_string( HashAlgMode2mbedtlsString[hashMode] );
716 if (NULL == md_info) {
717 err = CC_FFC_DOMAIN_GENERATION_FAILURE_ERROR;
718 goto End;
719 }
720
721 /* calculate W = HASH(U) */
722 err = mbedtls_md(md_info, (uint8_t*)pHashDataU, hashDataSizeBytes, (unsigned char *)pHashResW);
723 if (err) {
724 goto End;
725 }
726
727 /* convert Hash result to LE words array */
728 CC_CommonConvertMsbLsbBytesToLswMswWords(pHashResW, pDomain->hashDigestSize,
729 (uint8_t*)pHashResW, pDomain->hashDigestSize);
730
731 /*--------------------------*/
732 /* calculate e = P / Q */
733 /*--------------------------*/
734
735 pDomain->prime[primeSizeBytes-1] ^= 1; /* temporary: P = p-1;*/
736 pDivResE = pHashDataU; /* pHashDataU not used now */
737 pTmp1 = pDivResE + pDomain->ordLenWords;
738
739 /* e = (p-1) / q */
740 CHECK_ERROR(PkiLongNumDiv(pPrimeP/*numerator*/, pDomain->modLenWords,
741 pDomain->order/*divider*/, pDomain->ordLenWords,
742 pTmp1/*remainder C*/, pDivResE/*DivRes - not used*/));
743 pDomain->prime[primeSizeBytes-1] ^= 1; /*reset: P = P+1*/
744
745 /* calculate Generator g = W^e mod P */
746 err = PkiExecModExpLeW(
747 pDomain->genG, /*G res*/
748 pHashResW, /*W*/
749 pDomain->ordLenWords, /*W size*/
750 &pDomain->prime[0], /*prime P - modulus*/
751 pDomain->modLenWords*CC_BITS_IN_32BIT_WORD, /*P size in bits*/
752 pDivResE, /*E exponent*/
753 pDomain->ordLenWords); /* Q size in words*/
754
755 /* check error */
756 if (err != CC_OK) {
757 goto End;
758 }
759
760 /* check that g > 1, else repeat generation with count++. */
761 cmp = CC_CommonCmpLsWordsUnsignedCounters(pDomain->genG, pDomain->modLenWords, &one, sizeof(one));
762 if(cmp == CC_COMMON_CmpCounter1GreaterThenCounter2) {
763 /* set results into Domain */
764 pDomain->indexOfGenerator = index;
765 break;
766 }
767 count++;
768 }
769
770 /* End of function */
771 End:
772
773 if(err) {
774 CC_PalMemSetZero(pDomain, sizeof(CCFfcDomain_t));
775 CC_PalMemSetZero((uint8_t*)pTmpBuff, sizeof(CCFfcDomainTmpBuff_t));
776 }
777
778 return err;
779
780 } /* End of FfcFips186v4FindPrimeP */
781
782
783 /** The function performs preliminary checking of Domain generation input parameters.
784 *
785 * This checking is related only to pointers and sizes of input parameters in
786 * accordance with NIST SP 56A rev.2, referring to FIPS 184-4 standards, but not
787 * means standard full validation of them.
788 *
789 */
FfcDomainMinCheckInput(CCFfcDomain_t * pDomain,CCRndContext_t * pRndContext,size_t primeSizeBits,size_t orderSizeBits,uint8_t * pSeed,size_t seedSizeBytes,CCFfcGenerateSeed_t generateSeed,uint32_t genCounter,CCFfcParamSetId_t ffcParamSetId,CCFfcHashOpMode_t ffcHashMode,uint8_t indexOfGener)790 static CCError_t FfcDomainMinCheckInput(
791 CCFfcDomain_t *pDomain, /*!< [out] pointer to FFC Domain structure. */
792 CCRndContext_t *pRndContext, /*!< [in] random generation function context. */
793 size_t primeSizeBits, /*!< [in] size of domain's prime modulus in bits (see requirements above). */
794 size_t orderSizeBits, /*!< [in] size of domain's sub-group order in bits. The size should meet
795 to one of allowed sizes according given. */
796 uint8_t *pSeed, /*!< [in] optional pointer to the seed for domain generation and validation.
797 If Seed should be generated internally, then Seed pointer and size
798 should be zero. */
799 size_t seedSizeBytes, /*!< [in] optional seed size in bytes */
800 CCFfcGenerateSeed_t generateSeed,/*!< [in] enumerator indicates to generate a new domain Seed. */
801 uint32_t genCounter, /*!< [in] optional value of count of iterations, required for generation
802 of FFC Domain from given Seed. If Seed is given, and actually calculated
803 count is not equal to given, then the function returns an error.
804 If a new Seed is required (i.e. the counter is not known), then input
805 genCounter should be set 0. */
806 CCFfcParamSetId_t ffcParamSetId, /*!< [in] enumerator, defining the set of FFC domain parameters
807 according to SP 56A rev.2 section 5.5.1.1, tab.1. */
808 CCFfcHashOpMode_t ffcHashMode, /*!< [in] enumerator ID of used SHAXXX HASH mode, supported by the product.
809 Note: HASH SHA1 function may be used only with SA set of domain parameters
810 (sec. 5.8.1, tab.6); with other sets the function returns an error. */
811 uint8_t indexOfGener /*!< [in] index of FFC Generator, allowing to generate different FFC generators with
812 the same FFC parameters (Prime and Order), existed in the domain. */
813 )
814 {
815 /* The return error identifier */
816 CCError_t err = CC_OK;
817
818 uint32_t hashMinLen;
819 uint32_t primeSizeBytes, orderSizeBytes;
820 CCHashOperationMode_t hashMode;
821
822 /* Step 1. Check input parameters */
823 /*------------------------------- */
824 CHECK_AND_SET_ERROR((pDomain == NULL), CC_FFC_DOMAIN_INVALID_DOMAIN_PTR_ERROR);
825 CHECK_AND_SET_ERROR((pRndContext == NULL), CC_RND_CONTEXT_PTR_INVALID_ERROR);
826 CHECK_AND_SET_ERROR((pRndContext->rndGenerateVectFunc == NULL), CC_FFC_DOMAIN_INVALID_RND_FUNCTION_PTR_ERROR);
827 /* check enumerators */
828 CHECK_AND_SET_ERROR(ffcParamSetId >= CC_FFC_PARAMS_SET_NUM_OFF_MODE, CC_FFC_DOMAIN_INVALID_HASH_MODE_ERROR);
829 CHECK_AND_SET_ERROR(ffcParamSetId >= CC_FFC_PARAMS_SET_NUM_OFF_MODE, CC_FFC_DOMAIN_INVALID_HASH_MODE_ERROR);
830 CHECK_AND_SET_ERROR(ffcParamSetId >= CC_FFC_PARAMS_SET_NUM_OFF_MODE, CC_FFC_DOMAIN_INVALID_SEED_GENERATION_MODE_ERROR);
831
832 /* check seed and generation counter */
833 if((generateSeed == CC_FFC_GENERATE_NEW_SEED) || (generateSeed == CC_FFC_SEED_NOT_USED)) {
834 /* case that the seed and generation counter not known and not given. */
835 CHECK_AND_SET_ERROR(pSeed != NULL, CC_FFC_DOMAIN_SEED_IS_NOT_REQUIRED_ERROR);
836 CHECK_AND_SET_ERROR(genCounter != 0, CC_FFC_DOMAIN_GEN_COUNTER_NOT_VALID_ERROR);
837 } else {
838 /* case of actually used input of seed and counter */
839 CHECK_AND_SET_ERROR(pSeed == NULL, CC_FFC_DOMAIN_INVALID_SEED_PTR_ERROR);
840 CHECK_AND_SET_ERROR(genCounter == 0, CC_FFC_DOMAIN_GEN_COUNTER_NOT_VALID_ERROR);
841 }
842
843 /* get HASH mode and sizes, FFC sizes set and insert them into Domain. */
844 CHECK_AND_SET_ERROR(FfcGetHashMode(&hashMode, NULL/*pHkdfHashMode*/,
845 &pDomain->hashBlockSize, &pDomain->hashDigestSize, ffcHashMode/*in*/),
846 CC_FFC_DOMAIN_INVALID_HASH_MODE_ERROR);
847 CHECK_AND_SET_ERROR(FfcGetDomainSizes(NULL/*pMaxSecurStrength*/, &primeSizeBytes,
848 &orderSizeBytes, &hashMinLen, ffcParamSetId/*in*/),
849 CC_FFC_DOMAIN_INVALID_SIZES_SET_ID_ERROR);
850
851 /* check that FFC Prime and Order sizes are meet to given ffcParamSetId */
852 CHECK_AND_SET_ERROR(primeSizeBits != primeSizeBytes*CC_BITS_IN_BYTE, CC_FFC_DOMAIN_INVALID_PRIME_SIZE_ERROR);
853 CHECK_AND_SET_ERROR(orderSizeBits != orderSizeBytes*CC_BITS_IN_BYTE, CC_FFC_DOMAIN_INVALID_ORDER_SIZE_ERROR);
854
855 /* check Hash and Seed sizes according to required FFC parameters Set ID */
856 CHECK_AND_SET_ERROR(pDomain->hashDigestSize < hashMinLen, CC_FFC_DOMAIN_INVALID_LOW_HASH_SIZE_ERROR);
857 CHECK_AND_SET_ERROR((seedSizeBytes < orderSizeBytes) || (seedSizeBytes > CC_FFC_DOMAIN_SEED_MAX_SIZE_IN_BYTES),
858 CC_FFC_DOMAIN_INVALID_SEED_SIZE_ERROR);
859
860 /* set other parameters into FFC Domain */
861 pDomain->ffcParamSetId = ffcParamSetId;
862 pDomain->ffcHashMode = ffcHashMode;
863 pDomain->indexOfGenerator = indexOfGener;
864 pDomain->seedSizeBytes = seedSizeBytes;
865 pDomain->modLenWords = primeSizeBytes/CC_32BIT_WORD_SIZE;
866 pDomain->ordLenWords = orderSizeBytes/CC_32BIT_WORD_SIZE;
867 pDomain->seedSizeBytes = seedSizeBytes;
868 pDomain->genCounter = genCounter;
869
870 /* End of function */
871 End:
872
873 return err;
874
875 }
876
877
878
879 /***********************************************************************/
880 /*!
881 @brief This function generates FFC domain parameters according to NIST SP 56A rev.2, referring to FIPS 184-4 standard.
882 \par<ol><li>
883 <li> The function generates FFC Domain from given Seed or generates a new random Seed and then the Domain, depending on
884 geneSeedId value: 0,1 (see type definition). </li>
885 <li> The function calculates prime modulus P, subgroup generator G with order Q using Seed and HASH function and
886 parameters and then compares count of performed iterations with given right value. In other words, the function recalculates
887 previously generated FFC domain from given Seed (sections SP 56A rev.2 5.5.1.1 and FIPS 184-4 A.1.1.2, A.1.1.3, A.2.3). </li>
888 <li> The function allows generation domains with approved set of parameters sizes (SP 56A rev.2 5.5.1.1), given by
889 enumerator CCFfcParamSetId_t. </li>
890 <li> The function validates received FFC domain parameters and sets them into Domain structure. </li></ol>
891 @return CC_OK on success.
892 @return A non-zero value on failure as defined cc_dh_error.h, cc_rnd_error.h.
893 */
894 //static
FfcFips186v4GenerateDomain(CCFfcDomain_t * pDomain,CCRndContext_t * pRndContext,size_t primeSizeBits,size_t orderSizeBits,uint8_t * pSeed,size_t seedSizeBytes,CCFfcGenerateSeed_t generateSeed,uint32_t genCounter,CCFfcParamSetId_t ffcParamSetId,CCFfcHashOpMode_t ffcHashMode,uint8_t generIndex,CCFfcDomainTmpBuff_t * pTmpBuff)895 CCError_t FfcFips186v4GenerateDomain(
896 CCFfcDomain_t *pDomain, /*!< [out] pointer to FFC Domain structure. */
897 CCRndContext_t *pRndContext, /*!< [in] random generation function context. */
898 size_t primeSizeBits, /*!< [in] size of domain's prime modulus in bits (see requirements above). */
899 size_t orderSizeBits, /*!< [in] size of domain's sub-group order in bits. The size should meet
900 to one of allowed sizes according given. */
901 uint8_t *pSeed, /*!< [in] optional pointer to the seed for domain generation and validation.
902 If Seed should be generated internally, then Seed pointer and size
903 should be zero, because the Seed will be saved in the domain. */
904 size_t seedSizeBytes, /*!< [in] seed size in bytes, should meets to given ffcParamSetId. */
905 CCFfcGenerateSeed_t generateSeed,/*!< [in] enumerator indicates to generate a new domain Seed. */
906 uint32_t genCounter, /*!< [in] optional value of count of iterations, required for generation
907 of FFC Domain from given Seed. If Seed is given, and actually calculated
908 count is not equal to given, then the function returns an error.
909 If a new Seed is required (i.e. the counter is not known), then input
910 genCounter should be set 0. */
911 CCFfcParamSetId_t ffcParamSetId, /*!< [in] enumerator, defining the set of FFC domain parameters
912 according to SP 56A rev.2 section 5.5.1.1, tab.1. */
913 CCFfcHashOpMode_t ffcHashMode, /*!< [in] enumerator ID of used SHAXXX HASH mode, supported by the product.
914 Note: HASH SHA1 function may be used only with SA set of domain parameters
915 (sec. 5.8.1, tab.6); with other sets the function returns an error. */
916 uint8_t generIndex, /*!< [in] index of FFC Generator, allowing to generate different FFC generators with
917 the same FFC parameters prime P and Order Q, existed in the domain. */
918 CCFfcDomainTmpBuff_t *pTmpBuff /*!< [in] pointer to FFC Domain temp buffer structure. */
919 )
920 {
921
922 /* FUNCTION DECLARATIONS */
923
924 /* The return error identifier */
925 CCError_t err = CC_OK;
926 int8_t isPrime; /* indication, that prime is found (0, 1). */
927
928
929 /* FUNCTION LOGIC */
930
931 /* preliminary checking of input pointers and sizes according to given ffcParamSetId
932 * and ffcHashMode; save checked data into Domain structure */
933 CHECK_ERROR(FfcDomainMinCheckInput(pDomain, pRndContext, primeSizeBits, orderSizeBits,
934 pSeed, seedSizeBytes, generateSeed, genCounter,
935 ffcParamSetId, ffcHashMode, generIndex));
936 /* check temp buffer */
937 CHECK_AND_SET_ERROR((pTmpBuff == NULL), CC_FFC_DOMAIN_INVALID_ARGUMENT_PTR_ERROR);
938
939 /* main loop of FFC domain generation:
940 * !!! Note: the loop, according to Standard algorithm, is not limited
941 * therefore we need insert an WatchDog timer. */
942 while(1) {
943 /* generate FFC Order Q */
944 CHECK_ERROR(FfcFips186v4FindOrderQ(pDomain, pRndContext, generateSeed, pTmpBuff));
945 /* generate FFC Prime modulus P */
946 CHECK_ERROR(FfcFips186v4FindPrimeP(pDomain, pRndContext, &isPrime, pTmpBuff));
947
948 /* check that both P,Q are prime */
949 if(isPrime == 1) {
950 break;
951 }
952 }
953
954 /* if the Seed is given, then check iterations counter */
955 CHECK_AND_SET_ERROR((generateSeed == CC_FFC_USE_GIVEN_SEED) && (pDomain->genCounter != genCounter),
956 CC_FFC_DOMAIN_GENERATION_FAILURE_ERROR);
957
958 /* create FFC Generator with given Index */
959 CHECK_ERROR(FfcFips186v4CreateGenerator(pDomain, pRndContext, generIndex, pTmpBuff));
960
961 /* End of function */
962 End:
963 if(err) {
964 CC_PalMemSetZero(pDomain, sizeof(CCFfcDomain_t));
965 CC_PalMemSetZero(pTmpBuff, sizeof(CCFfcDomainTmpBuff_t));
966 }
967
968 return err;
969
970 }
971
972
973
974
975
976 /*******************************************************************************************/
977 /*!
978 @brief This function generates FFC domain parameters according to NIST SP 56A rev.2, referring to FIPS 184-4 standard.
979 \par<ol><li>
980 <li> The function generates FFC Domain from given Seed and iterations count and sets them into Domain structure.
981 If actual count of iterations is not equalled to given value, then the function returns an error. </li>
982 <li> The function calculates prime modulus P, subgroup generator G with order Q using Seed and given Generator
983 index, allowing to generate different FFC generators with same P and Q, according to SP 56A rev.2 sec.5.5.1.1
984 and FIPS 184-4 A.1.1.2, A.2.3. </li>
985 <li> The function allows generation domains only for approved set of parameters sizes (SP 56A rev.2 5.5.1.1),
986 given by enumerator ID of type CCFfcParamSetId_t. </li></ol>
987 @return CC_OK on success.
988 @return A non-zero value on failure as defined cc_ffc_domain_error.h.
989
990 */
CC_FfcGenerateDomainFromSeed(CCFfcDomain_t * pDomain,CCRndContext_t * pRndContext,size_t primeSizeBits,size_t orderSizeBits,uint8_t * pSeed,size_t seedSizeBytes,uint32_t genCounter,CCFfcParamSetId_t ffcParamSetId,CCFfcHashOpMode_t ffcHashMode,uint8_t generIndex,CCFfcDomainTmpBuff_t * pTmpBuff)991 CEXPORT_C CCError_t CC_FfcGenerateDomainFromSeed(
992 CCFfcDomain_t *pDomain, /*!< [out] pointer to FFC Domain structure. */
993 CCRndContext_t *pRndContext, /*!< [in] random generation function context. */
994 size_t primeSizeBits, /*!< [in] size of domain's prime modulus in bits (see requirements above). */
995 size_t orderSizeBits, /*!< [in] size of domain's sub-group order in bits (see requirements above). */
996 uint8_t *pSeed, /*!< [in] pointer to the seed for domain generation and validation; */
997 size_t seedSizeBytes, /*!< [in] seed size in bytes */
998 uint32_t genCounter, /*!< [in] exact value of count of main loop iterations, required for generation
999 FFC Domain from given Seed. If actual count is not equal to given,
1000 then the function returns an error. */
1001 CCFfcParamSetId_t ffcParamSetId,/*!< [in] enumerator, defining the set of FFC domain parameters
1002 according to SP 56A rev.2 section 5.5.1.1, tab.1. */
1003 CCFfcHashOpMode_t ffcHashMode, /*!< [in] enumerator ID of SHAx HASH mode. Note: HASH SHA1 mode may be
1004 used only with SA set of domain parameters (sec. 5.8.1, tab.6). */
1005 uint8_t generIndex, /*!< [in] an index of FFC Generator, allowing to generate different FFC generators with
1006 the same FFC parameters prime P and Order Q, existed in the domain. */
1007 CCFfcDomainTmpBuff_t *pTmpBuff /*!< [in] pointer to FFC Domain temp buffer structure. */
1008 )
1009 {
1010 /* FUNCTION DECLARATIONS */
1011
1012 /* The return error identifier */
1013 CCError_t err = CC_OK;
1014
1015 /* call generation function */
1016 err = FfcFips186v4GenerateDomain(
1017 pDomain, pRndContext, primeSizeBits, orderSizeBits,
1018 pSeed, seedSizeBytes, CC_FFC_USE_GIVEN_SEED, genCounter,
1019 ffcParamSetId, ffcHashMode, generIndex, pTmpBuff);
1020
1021 if(err == CC_OK) {
1022 pDomain->validTag = CC_FFC_DOMAIN_VALIDATION_TAG;
1023 }
1024
1025 return err;
1026 }
1027
1028
1029 /*******************************************************************************************/
1030 /*!
1031 @brief This function generates FFC Domain parameters including new Seed Seed according to
1032 NIST SP 56A rev.2 with referring to FIPS 184-4 standard.
1033 \par<ol><li>
1034 <li> The function generates a new Seed, calculates FFC Domain parameters and sets them into Domain. </li>
1035 <li> The function calculates prime modulus P, subgroup generator G with order Q using Seed and given Generator
1036 index, allowing to generate different FFC generators with same P and Q, according to SP 56A rev.2 sec.5.5.1.1
1037 and FIPS 184-4 A.1.1.2, A.2.3. </li>
1038 <li> The function allows generation Domain only for approved set of parameters sizes (SP 56A rev.2 5.5.1.1),
1039 given by enumerator ID of type CCFfcParamSetId_t. </li></ol>
1040 @return CC_OK on success.
1041 @return A non-zero value on failure as defined cc_ffc_domain_error.h.
1042
1043 */
CC_FfcGenerateDomainAndSeed(CCFfcDomain_t * pDomain,CCRndContext_t * pRndContext,size_t primeSizeBits,size_t orderSizeBits,size_t seedSizeBytes,CCFfcParamSetId_t ffcParamSetId,CCFfcHashOpMode_t ffcHashMode,uint8_t generIndex,CCFfcDomainTmpBuff_t * pTmpBuff)1044 CEXPORT_C CCError_t CC_FfcGenerateDomainAndSeed(
1045 CCFfcDomain_t *pDomain, /*!< [out] pointer to FFC Domain structure. */
1046 CCRndContext_t *pRndContext, /*!< [in] random generation function context. */
1047 size_t primeSizeBits, /*!< [in] size of domain's prime modulus in bits (see requirements above). */
1048 size_t orderSizeBits, /*!< [in] size of domain's sub-group order in bits (see requirements above). */
1049 size_t seedSizeBytes, /*!< [in] required size of the seed in bytes; it must be not less than
1050 HASH security strength, defined in given ffcParamsSet. */
1051 CCFfcParamSetId_t ffcParamSetId,/*!< [in] enumerator, defining the set of FFC domain parameters
1052 according to SP 56A rev.2 section 5.5.1.1, tab.1. */
1053 CCFfcHashOpMode_t ffcHashMode, /*!< [in] enumerator ID of SHAx HASH mode. Note: HASH SHA1 mode may be
1054 used only with SA set of domain parameters (sec. 5.8.1, tab.6). */
1055 uint8_t generIndex, /*!< [in] an index of FFC Generator, allowing to generate different FFC generators with
1056 the same FFC parameters prime P and Order Q, existed in the domain. */
1057 CCFfcDomainTmpBuff_t *pTmpBuff /*!< [in] pointer to FFC Domain temp buffer structure. */
1058 )
1059 {
1060 /* FUNCTION DECLARATIONS */
1061
1062 /* The return error identifier */
1063 CCError_t err = CC_OK;
1064
1065 /* call generation function */
1066 err = FfcFips186v4GenerateDomain(
1067 pDomain, pRndContext, primeSizeBits, orderSizeBits, NULL/*pSeed*/,
1068 seedSizeBytes, CC_FFC_GENERATE_NEW_SEED, 0/*generCounter*/,
1069 ffcParamSetId, ffcHashMode, generIndex, pTmpBuff);
1070
1071 if(err == CC_OK) {
1072 pDomain->validTag = CC_FFC_DOMAIN_VALIDATION_TAG;
1073 }
1074
1075 return err;
1076 }
1077
1078 //static
1079 //CCError_t
1080
1081 /*******************************************************************************************/
1082 /*!
1083 @brief The function validates received FFC domain parameters and sets them into Domain structure.
1084 <ol><li> Validation of performed according to NIST SP 56A rev.2, sec. 5.5.2 and to FIPS 184-4 standard. </li>
1085 </li> If optional parameters (Seed and pgenCounter) are given, then the function performs full validation by generation
1086 primes P,Q from the given Seed and compares calculated and received parameters according to the FIPS 184-4, A.1.1.3. </li>
1087 </li> Generator G is validated according to sec. A.2.3. </li>
1088 </li> If optional parameters pSeed, seedSize, pgenCounter are zero, and the user explicitly sets validation mode to
1089 "Trusted Data", then the function performs only checking of pointers, sizes and some relations between parameters. <li>.
1090 </li> All input byte-arrays should be set with big endianness order of bytes, i.e. MS Byte is a leftmost one. </li></ol>
1091 @return CC_OK on success.
1092 @return A non-zero value on failure, as defined in cc_dh_error.h, cc_rnd_error.h.
1093 */
CC_FfcValidateAndImportDomain(CCFfcDomain_t * pDomain,CCRndContext_t * pRndContext,uint8_t * pPrime,size_t primeSizeBits,uint8_t * pOrder,size_t orderSizeBits,uint8_t * pGenerator,size_t generSizeBytes,uint8_t * pSeed,size_t seedSizeBytes,CCFfcParamSetId_t ffcParamSetId,CCFfcHashOpMode_t ffcHashMode,uint32_t genCounter,uint8_t generIndex,CCFfcDomainValidMode_t validMode,CCFfcDomainTmpBuff_t * pTmpBuff)1094 CEXPORT_C CCError_t CC_FfcValidateAndImportDomain(
1095 CCFfcDomain_t *pDomain, /*!< [out] optional (used on Full Validation mode only), pointer to FFC Domain. */
1096 CCRndContext_t *pRndContext, /*!< [in] optional (used on Full Validation mode only), random generation
1097 function context. */
1098 uint8_t *pPrime, /*!< [in] pointer to prime modulus of the finite field (P). */
1099 size_t primeSizeBits, /*!< [in] prime P size in bits. */
1100 uint8_t *pOrder, /*!< [in] pointer to the order Q of the generator. */
1101 size_t orderSizeBits, /*!< [in] order size in bits. */
1102 uint8_t *pGenerator, /*!< [in] pointer to generator G of subgroup of FFC. */
1103 size_t generSizeBytes, /*!< [in] generator G size in bytes (see note bellow). */
1104 uint8_t *pSeed, /*!< [in] optional (used on Full Validation mode only), pointer to the Seed,
1105 if the Seed is not given, then should be set to NULL. */
1106 size_t seedSizeBytes, /*!< [in] optional size of Seed in bytes; if Seed not given, then
1107 should be set to 0. */
1108 CCFfcParamSetId_t ffcParamSetId, /*!< [in] enumerator, defining the set of FFC domain parameters
1109 according to SP 56A rev.2 section 5.5.1.1, tab.1. */
1110 CCFfcHashOpMode_t ffcHashMode, /*!< [in] enumerator ID of SHAx HASH mode. Note: HASH SHA1 mode may be
1111 used only with SA set of domain parameters (sec. 5.8.1, tab.6). */
1112 uint32_t genCounter, /*!< [in] optional, counter of main iterations loop, performed during
1113 domain generation with Seed. */
1114 uint8_t generIndex, /*!< [in] an index of FFC Generator, allowing to generate different FFC generators with
1115 the same FFC parameters prime P and Order Q, existed in the domain. */
1116 CCFfcDomainValidMode_t validMode,/*!< [in] enumerator, defining validation mode of of domain parameters:
1117 "full" (approved by FIPS standard), "partial"
1118 and "trusted" (validated previously); using of both second
1119 modes is not approved by standards and is fully on the user
1120 responsibility. */
1121 CCFfcDomainTmpBuff_t *pTmpBuff /*!< [in] optional pointer to FFC Domain temp buffer structure. Used only
1122 on Full validation mode, on Trusted mode may be set to NULL. */
1123
1124 )
1125 {
1126 /* FUNCTION DECLARATIONS */
1127
1128 /* The return error identifier */
1129 CCError_t err = CC_OK;
1130 size_t primeSizeBytes, orderSizeBytes;
1131
1132
1133 /* INITIALIZATIONS */
1134
1135 primeSizeBytes = primeSizeBits/CC_BITS_IN_BYTE;
1136 orderSizeBytes = orderSizeBits/CC_BITS_IN_BYTE;
1137
1138 /* check parameters */
1139 CHECK_AND_SET_ERROR((pGenerator == NULL) != (generSizeBytes == 0), CC_FFC_DOMAIN_INVALID_OPTIONAL_PARAM_ERROR);
1140 CHECK_AND_SET_ERROR(validMode >= CC_FFC_DOMAIN_VALIDAT_NUM_OFF_MODE, CC_FFC_DOMAIN_INVALID_VALIDAT_MODE_ERROR);
1141
1142 /*----------------------------------------------------------------------------*
1143 * case of full validation mode *
1144 *--------------------------------------------------------------------------- */
1145 if(validMode == CC_FFC_DOMAIN_VALIDAT_FULL_MODE) {
1146 CHECK_AND_SET_ERROR(pSeed == NULL, CC_FFC_DOMAIN_INVALID_SEED_PTR_ERROR);
1147
1148 /* generate Domain from given Seed. */
1149 CHECK_ERROR(FfcFips186v4GenerateDomain(
1150 pDomain, pRndContext, primeSizeBits, orderSizeBits, pSeed, seedSizeBytes,
1151 CC_FFC_USE_GIVEN_SEED, genCounter, ffcParamSetId, ffcHashMode, generIndex, pTmpBuff));
1152
1153 /* compare input data with generated parameters */
1154 CHECK_AND_SET_ERROR(FfcCmpBeBytes2LeWordsBigNum(pPrime, pDomain->prime, primeSizeBytes/CC_32BIT_WORD_SIZE),
1155 CC_FFC_DOMAIN_PRIME_NOT_VALID_ERROR);
1156 CHECK_AND_SET_ERROR(FfcCmpBeBytes2LeWordsBigNum(pOrder, pDomain->order, orderSizeBytes/CC_32BIT_WORD_SIZE),
1157 CC_FFC_DOMAIN_ORDER_NOT_VALID_ERROR);
1158 // CHECK_AND_SET_ERROR(CC_PalMemCmp(pSeed, pDomain->seed, orderSizeBytes/CC_32BIT_WORD_SIZE),
1159 // CC_FFC_DOMAIN_SEED_IS_NOT_VALID_ERROR);
1160 CHECK_AND_SET_ERROR(genCounter != pDomain->genCounter, CC_FFC_DOMAIN_GEN_COUNTER_NOT_VALID_ERROR);
1161
1162 /* create FFC sub-group generator G with given index */
1163 if(pGenerator != NULL) {
1164 CHECK_ERROR(FfcFips186v4CreateGenerator(pDomain, pRndContext, generIndex, pTmpBuff));
1165 /* check the generator */
1166 CHECK_AND_SET_ERROR(FfcCmpBeBytes2LeWordsBigNum(pGenerator, &pDomain->genG[0], primeSizeBytes),
1167 CC_FFC_DOMAIN_GENERATOR_NOT_VALID_ERROR);
1168 }
1169 }
1170 /*--------------------------------------------------------------------------------------
1171 * the case, that the user has obtained insurance, that all Domain input data is correct,
1172 * therefore the following checking is minimal and not means validation of the Domain. *
1173 *-------------------------------------------------------------------------------------*/
1174 else if (validMode == CC_FFC_DOMAIN_TRUSTED_DATA_MODE) {
1175
1176 /* check input pointers and sizes according to given ffcParamSetId and ffcHashMode */
1177 CHECK_ERROR(FfcDomainMinCheckInput(pDomain, pRndContext, primeSizeBits, orderSizeBits,
1178 pSeed, seedSizeBytes, CC_FFC_USE_GIVEN_SEED, genCounter,
1179 ffcParamSetId, ffcHashMode, generIndex));
1180
1181 /* check Prime, Order and Generator */
1182 CHECK_AND_SET_ERROR((pPrime == NULL) || (pOrder == NULL) || (pGenerator == NULL),
1183 CC_FFC_DOMAIN_INVALID_ARGUMENT_PTR_ERROR);
1184
1185 /* set data into Domain as LE words array */
1186 CC_CommonConvertMsbLsbBytesToLswMswWords(pDomain->prime, primeSizeBytes, pPrime, primeSizeBytes);
1187 CC_CommonConvertMsbLsbBytesToLswMswWords(pDomain->order, orderSizeBytes, pOrder, primeSizeBytes);
1188 CC_CommonConvertMsbLsbBytesToLswMswWords(pDomain->genG, primeSizeBytes, pGenerator, primeSizeBytes);
1189 if(pSeed != NULL) {/*set data as is */
1190 CC_PalMemCopy(pDomain->seed, pSeed, seedSizeBytes);
1191 }
1192 /* Note: part of settings is done by FfcDomainMinCheckInput() function. */
1193 }
1194
1195 if(err == CC_OK) {
1196 pDomain->validTag = CC_FFC_DOMAIN_VALIDATION_TAG;
1197 }
1198
1199 End:
1200
1201 if(err) {
1202 CC_PalMemSetZero(pDomain, sizeof(CCFfcDomain_t));
1203 if(pTmpBuff != NULL) {
1204 CC_PalMemSetZero((uint8_t*)pTmpBuff, sizeof(CCFfcDomainTmpBuff_t));
1205 }
1206 }
1207
1208 return err;
1209 }
1210
1211
1212
1213 /*******************************************************************************************/
1214 /*!
1215 @brief This function extracts FFC domain parameters from Domain structure for external using.
1216 <ol><li> Assumed, that FFC domain is properly generated or validated according to the FIPS 184-4, standard. </li>
1217 <li> The function checks input/output pointers and buffers sizes, converts the DH Domain parameters
1218 to big endianness output arrays (with leading zeros if exists). </li>
1219 <li> If the user not need any domain parameters, then appropriate pointers (for buffer and size)
1220 should be set to NULL </li>
1221 <li> Note: The sizes of buffers are given by pointers, were the referred [in/out] values are:
1222 [in] - the buffer size, [out] - actual data size. </li></ol>
1223
1224 @return CC_OK on success.
1225 @return A non-zero value on failure as defined cc_dh_error.h, cc_rnd_error.h.
1226 */
CC_FfcExportDomain(CCFfcDomain_t * pDomain,uint8_t * pPrime,size_t * pPrimeSize,uint8_t * pGenerator,size_t * pGeneratorSize,uint8_t * pOrder,size_t * pOrderSize,uint8_t * pSeed,size_t * pSeedSize,CCFfcParamSetId_t * pFfcParamSetId,CCFfcHashOpMode_t * pFfcHashMode,uint32_t * pGenCounter,uint8_t * pIndexOfGenerator)1227 CEXPORT_C CCError_t CC_FfcExportDomain(
1228 CCFfcDomain_t *pDomain, /*!< [in] pointer to FFC Domain to be exported. */
1229 uint8_t *pPrime, /*!< [out] pointer to prime modulus of the finite field (P). */
1230 size_t *pPrimeSize, /*!< [in/out] pointer to prime P size in bytes. */
1231 uint8_t *pGenerator, /*!< [out] pointer to generator of subgroup (G). */
1232 size_t *pGeneratorSize, /*!< [in/out] pointer to generator G size in bytes. */
1233 uint8_t *pOrder, /*!< [out] pointer to the order of the generator G. */
1234 size_t *pOrderSize, /*!< [in/out] pointer to order of generator Q size in bytes. */
1235 uint8_t *pSeed, /*!< [out] pointer to the Seed, used for Domain generation;
1236 if Seed is not required, then the pointer and size should be NULL. */
1237 size_t *pSeedSize, /*!< [in/out] size of the Seed in bytes - if the Seed not exist,
1238 in the Domain, the function sets the size = 0. */
1239 CCFfcParamSetId_t *pFfcParamSetId, /*!< [in] pointer to enumerator ID, defining the set of FFC domain parameters
1240 parameters according to SP 56A rev.2 section 5.5.1.1, tab.1. */
1241 CCFfcHashOpMode_t *pFfcHashMode, /*!< [in] pointer to enumerator ID of SHAx HASH mode. Note: HASH SHA1 mode
1242 may be used only with SA set of domain parameters (sec. 5.8.1, tab.6). */
1243 uint32_t *pGenCounter, /*!< [out] pointer to count of iterations, which were performed
1244 during Domain generation. */
1245 uint8_t *pIndexOfGenerator /*!< pointer to index, of FFC Generator existed in the Domain. */
1246 )
1247 {
1248
1249 /* The return error identifier */
1250 CCError_t err = CC_OK;
1251 size_t primeSizeBytes;
1252 size_t orderSizeBytes;
1253
1254 /* check input Domain */
1255 CHECK_AND_SET_ERROR((pDomain == NULL), CC_FFC_DOMAIN_INVALID_DOMAIN_PTR_ERROR);
1256 CHECK_AND_SET_ERROR((pDomain->validTag != CC_FFC_DOMAIN_VALIDATION_TAG),
1257 CC_FFC_DOMAIN_VALIDATION_TAG_ERROR);
1258
1259 primeSizeBytes = pDomain->modLenWords * CC_32BIT_WORD_SIZE;
1260 orderSizeBytes = pDomain->ordLenWords * CC_32BIT_WORD_SIZE;
1261
1262 /*----------------------------------------------------------------------------------------*
1263 * Check output buffers: ptr != NULL, outSize <= buffSize and set data to output buffers. *
1264 *----------------------------------------------------------------------------------------*/
1265 /* Prime P */
1266 if((pPrime != NULL) && (pPrimeSize != NULL)) {
1267 CHECK_ERROR(FfcCheckPtrAndSize(pPrime, pPrimeSize, pDomain->prime, primeSizeBytes));
1268 CHECK_ERROR(CC_CommonConvertLswMswWordsToMsbLsbBytes(pPrime, primeSizeBytes, pDomain->prime, primeSizeBytes));
1269 *pPrimeSize = primeSizeBytes;
1270 }
1271 /* Order Q */
1272 if((pOrder != NULL) && (pOrderSize != NULL)) {
1273 CHECK_ERROR(FfcCheckPtrAndSize(pOrder, pOrderSize, pDomain->order, orderSizeBytes));
1274 CHECK_ERROR(CC_CommonConvertLswMswWordsToMsbLsbBytes(pOrder, orderSizeBytes, pDomain->order, orderSizeBytes));
1275 *pOrderSize = orderSizeBytes;
1276 }
1277 /* Generator G */
1278 if((pGenerator != NULL) && (pGeneratorSize != NULL)) {
1279 CHECK_ERROR(FfcCheckPtrAndSize(pGenerator, pGeneratorSize, pDomain->genG, primeSizeBytes));
1280 CHECK_ERROR(CC_CommonConvertLswMswWordsToMsbLsbBytes(pGenerator, primeSizeBytes, pDomain->genG, primeSizeBytes));
1281 *pGeneratorSize = primeSizeBytes;
1282 }
1283 /* Seed */
1284 if((pSeed != NULL) && (pSeedSize != NULL)) {
1285 CHECK_ERROR(FfcCheckPtrAndSize(pSeed, pSeedSize, pDomain->seed, pDomain->seedSizeBytes));
1286 CHECK_AND_SET_ERROR(CC_PalMemCopy(pSeed, pDomain->seed, pDomain->seedSizeBytes),
1287 CC_FFC_DOMAIN_INVALID_OPTIONAL_PARAM_ERROR);
1288 *pSeedSize = pDomain->seedSizeBytes;
1289 }
1290
1291 /* Output enumerator and number parameters */
1292 if(pFfcParamSetId != NULL) {
1293 *pFfcParamSetId = pDomain->ffcParamSetId;
1294 }
1295 if(pFfcHashMode != NULL) {
1296 *pFfcHashMode = pDomain->ffcHashMode;
1297 }
1298 if(pGenCounter != NULL) {
1299 *pGenCounter = pDomain->genCounter;
1300 }
1301 if(pIndexOfGenerator != NULL) {
1302 *pIndexOfGenerator = pDomain->indexOfGenerator;
1303 }
1304
1305 End:
1306 /* Note: because the Domain is not secret,
1307 * we don't zeroing buffers in case of in/out errors
1308 */
1309 return err;
1310 }
1311
1312
1313
1314 /*******************************************************************************************/
1315 /*!
1316 @brief The function creates a new FFC subgroup Generator for existed FFC Domain.
1317 <ol><li> Assumed, that FFC domain is properly generated or imported previously and meets
1318 to the FIPS 184-4, sec. A.1.1.2 standard. </li>
1319 <li> The function checks input/output pointers and buffers sizes and creates new Generator
1320 according to sec. A.2.3. and sets it into Domain structure. </li></ol>
1321
1322 @return CC_OK on success.
1323 @return A non-zero value on failure as defined cc_dh_error.h, cc_rnd_error.h.
1324 */
CC_FfcCreateNewGenerator(CCFfcDomain_t * pDomain,CCRndContext_t * pRndContext,uint8_t index,CCFfcDomainTmpBuff_t * pTmpBuff)1325 CEXPORT_C CCError_t CC_FfcCreateNewGenerator(
1326 CCFfcDomain_t *pDomain, /*!< [in/out] pointer to FFC Domain structure. */
1327 CCRndContext_t *pRndContext, /*!< [in] random generation function context. */
1328 uint8_t index, /*!< [in] index allowing to generate some FFC generators with
1329 the same FFC parameters prime P and Order Q, existed in the domain. */
1330 CCFfcDomainTmpBuff_t *pTmpBuff /*!< [in] pointer to FFC Domain temp buffer structure. */
1331 )
1332 {
1333 /* The return error identifier */
1334 CCError_t err = CC_OK;
1335
1336 CHECK_AND_SET_ERROR((pDomain == NULL), CC_FFC_DOMAIN_INVALID_RND_CTX_PTR_ERROR);
1337 CHECK_AND_SET_ERROR((pDomain->validTag != CC_FFC_DOMAIN_VALIDATION_TAG),
1338 CC_FFC_DOMAIN_VALIDATION_TAG_ERROR);
1339
1340 return FfcFips186v4CreateGenerator(pDomain, pRndContext, index, pTmpBuff);
1341
1342 End:
1343 return err;
1344
1345 }
1346
1347
1348