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