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_bitops.h"
9 #include "cc_pal_types_plat.h"
10 #include "cc_pal_types.h"
11 #include "cc_pal_mem.h"
12 #include "cc_error.h"
13 #include "cc_common.h"
14 #include "cc_common_math.h"
15 #include "cc_rnd_common.h"
16 #include "cc_rnd_error.h"
17 #include "cc_rnd_local.h"
18 #include "cc_hash_defs.h"
19 #include "cc_general_defs.h"
20 #include "mbedtls/md.h"
21 #include "mbedtls_cc_hkdf.h"
22 #include "cc_ffcdh_error.h"
23 #include "cc_ffcdh.h"
24 #include "cc_ffc_domain.h"
25 #include "cc_ffcdh.h"
26 #include "cc_ffcdh_local.h"
27 #include "cc_fips_defs.h"
28 #include "pki.h"
29 
30 /************************ Defines *******************************/
31 
32 /************************ Enums *********************************/
33 
34 /************************ macros ********************************/
35 
36 /************************ global data ***********************************/
37 
38 extern CCError_t FfcGetHashMode(
39                     CCHashOperationMode_t *pHashMode, /* optional */
40                     mbedtls_hkdf_hashmode_t *pHkdfHashMode, /* optional */
41                     uint32_t *pBlockSize,              /* optional */
42                     uint32_t *pDigestSize,             /* optional */
43                     CCFfcHashOpMode_t ffcHashMode);    /* ffc HASH mode */
44 
45 
46 extern CCError_t FfcGetDomainSizes(
47                     uint32_t *pMaxSecurStrength,        /* Maximum security strength supported, in bits. */
48                     uint32_t *pPrimeLen,                /* Field (prime P) length in bytes. */
49                     uint32_t *pOrderLen,                /* Subgroup order Q length in bytes. */
50                     uint32_t *pMinHashLen,              /* Minimum length of HASH output in bytes. */
51                     CCFfcParamSetId_t  ffcParamSetId);  /* Enum. defining set of lengths of domain parameters, approved
52                                                          by SP 800-56A and FIPS 186-4 standards */
53 
54 /************************ Private Functions ******************************/
55 
56 #ifdef FFC_FURTHER_USING
57 /* The function converts little endianness bytes array to big endianness without leading zeros.
58  * Note: The function is not constant-time and intended for work with non secure data.
59  *       Overlapping of buffers is not allowed.  */
LeBytesArrayToBeBytesWithoutZeros(uint8_t * pBeDst,uint8_t * pLeSrc,size_t * pSizeBytes)60 static CCError_t LeBytesArrayToBeBytesWithoutZeros (
61                                 uint8_t *pBeDst,   /* LE destination */
62                                 uint8_t *pLeSrc,   /* BE source */
63                                 size_t *pSizeBytes /* pointer to size: in - buffer size,
64                                                        out -  actual size without leading zeros */
65 )
66 {
67     CCError_t err = CC_OK;
68     int32_t i, j;
69 
70     CHECK_AND_SET_ERROR((*pSizeBytes == 0), CC_FFCDH_INVALID_ARGUMENT_SIZE_ERROR);
71 
72         j = 0;
73         i = *pSizeBytes-1;
74         while (pLeSrc[i] == 0) {  /* remove leading zeros */
75             i--;
76         }
77 
78         /* copy actual data */
79         for (; i>=0; i--) {
80             pBeDst[j++] = pLeSrc[i];
81         }
82 
83         *pSizeBytes = j; /* output actual size */
84 End:
85         return err;
86 }
87 #endif
88 
89 #ifdef FFC_FURTHER_USING
90 /* The function converts big endianness bytes array to little endianness without leading zeros.
91  * Note: The function is not constant-time and intended for work with non secure data */
BeBytesArrayToLeEBytes(uint8_t * pLeDst,uint8_t * pBeSrc,uint32_t * pSizeBytes)92 static void BeBytesArrayToLeEBytes (
93                                 uint8_t  *pLeDst, /* LE destination */
94                                 uint8_t  *pBeSrc, /* BE source */
95                                 uint32_t *pSizeBytes) /* pointer to size: in - buffer size,
96                                                          out -  actual size without leading zeros */
97 {
98         int32_t i, j;
99         int32_t count0 = 0;
100 
101         j = 0;
102 
103         if(*pSizeBytes == 0)
104             return;
105 
106         /* remove leading zeros */
107     while (pBeSrc[count0] == 0) {
108         count0++;
109     }
110 
111     /* copy actual data */
112     for (i = *pSizeBytes - 1; i >= count0; i--) {
113             pLeDst[j++] = pBeSrc[i];
114     }
115     *pSizeBytes = *pSizeBytes -count0;
116 
117     return;
118 }
119 #endif
120 
121 
122 #ifdef FFC_FURTHER_USING
123 /*******************************************************************************
124  *             CC_CommonGetBytesCounterEffectiveSizeInBits                  *
125  *******************************************************************************
126  *
127  * @brief This function returns the effective number of bits in the byte stream counter
128  *        ( searching the highest '1' in the counter )
129  *
130  *        Assumed, that MSB of the counter is stored in the first cell in the
131  *         array. For example, the value of the 8-Bytes numberer B is :
132  *             B[0]<<56 | B[1]<<48 ............ B[6]<<8 | B[7] .
133  *
134  * @param[in] pCounter -  The counter buffer.
135  * @param[in] CounterSize -  the counter size in bytes.
136  *
137  * @return result - The effective counters size in bits.
138  */
139 
FfcDhGetBeCounterEffectiveSizeInBits(const uint8_t * pCounterBuffp,uint32_t * pCountLeadingZeros,uint32_t counterSize)140 static uint32_t FfcDhGetBeCounterEffectiveSizeInBits(const uint8_t *pCounterBuffp,
141                                                      uint32_t *pCountLeadingZeros,
142                                                      uint32_t counterSize)
143 {
144     /* FUNCTION LOCAL DECLARATIONS */
145 
146     /* loop variable */
147     int32_t i;
148 
149     /* the effective size in bits */
150     uint32_t effectSizeInBits;
151 
152     /* the effective MS byte (the one that is not zero) */
153     uint8_t effectMsByteVal;
154 
155     /* FUNCTION LOGIC */
156 
157     /* STEP1 : a loop for adjusting the counter size by neglecting the MSB zeros */
158         *pCountLeadingZeros = 0
159     while (i < counterSize) {
160         if (pCounterBuff[i] != 0)
161             break;
162         else
163             *pCountLeadingZeros++;
164     }
165 
166     /* STEP2 : if counter size is 0 - return 0 */
167     if (CounterSize == 0)
168         return 0;
169 
170     /* set the effective MS byte */
171     effectMsByteVal = pCounterBuff[i];
172 
173     /* initialize the effective size as the counters size (with MSB zeros) */
174     counterEffectSizeInBits = counterSize * 8;
175 
176     /* STEP 3 : adjusting the effective size in bits */
177     for (i = 0; i < 8; i++) {
178         if (effectMsByteVal & 0x80)
179             break;
180 
181         counterEffectSizeInBits--;
182         effectMsByteVal <<= 1;
183 
184     }/* end of adjusting the effective size in bits loop */
185 
186     return counterEffectSizeInBits;
187 
188 }/* END OF CC_DhGetBeCounterEffectiveSizeInBits */
189 #endif
190 
191 /* The function writes the separate bytes-array (Src) into the Dst buffer.
192  *
193  * Of first, he function sets the string length as first 2-bytes big endianness counter,
194  * then writes the data, promote the pointer to next after the data position. If
195  * pointer to FullLen != NULL, then add the size of written source to FullLen value.
196  *
197  * \note: Assumed that all parameters, including possible buffers overflow, are
198  * checked and correct.
199  * \note: Dst buffer should be given by allocated pointer to pointer and not by
200  *  address of the buffer address.
201  */
FfcDhWriteBufferBeToBe(uint8_t ** ppDst,uint8_t * pSrc,uint32_t curLen,uint32_t * pFullLen)202 static void FfcDhWriteBufferBeToBe(
203                 uint8_t **ppDst,      /* [in/out] pointer to pointer to destination buffer:
204                                          in - start address, out - next address after writing data. */
205                 uint8_t  *pSrc,       /* [in] pointer to source buffer */
206                 uint32_t  curLen,     /* [in] size of source buffer in bytes. */
207                 uint32_t *pFullLen)   /* [in/out] pointer to accumulated full length of
208                                           written data. */
209 {
210     /* set length and data */
211     (*ppDst)[0] = (uint8_t)((curLen>>8) & 0xFF); (*ppDst)[1] = (uint8_t)(curLen & 0xFF);
212     *ppDst += CC_FFCDH_LENGTH_COUNTER_SIZE_IN_BYTES;
213     CC_PalMemCopy(*ppDst, pSrc, curLen);
214 
215     /* update the Dst pointer */
216     *ppDst += curLen;
217     if(pFullLen != NULL){
218         *pFullLen += (curLen + CC_FFCDH_LENGTH_COUNTER_SIZE_IN_BYTES);
219     }
220 
221     return;
222 }
223 
224 
225 /* The function writes the separate LE words Src array into the Dst BE bytes buffer.
226  *
227  * Of first, the function sets the Src length as 2-bytes big endianness length-counter,
228  * then writes the data, converted to BE bytes and promote the pointer to next position
229  * after the data . If pointer to FullLen != NULL, then the function adds the size of
230  * source to FullLen value.
231  *
232  * \note: Assumed that all parameters, including possible buffers overflow, are
233  * checked and correct.
234  * \note: Dst buffer should be given by allocated pointer to pointer and not by
235  *  address of the buffer address.
236  */
FfcDhWriteBufferLeToBe(uint8_t ** ppDst,uint32_t * pSrc,uint32_t curLen,uint32_t * pFullLen)237 static void FfcDhWriteBufferLeToBe(
238                 uint8_t **ppDst,      /* [in/out] pointer to pointer to destination buffer:
239                                          in - start address, out - next address after writing data. */
240                 uint32_t *pSrc,       /* [in] pointer to source buffer, given as LE words array. */
241                 uint32_t  curLen,     /* [in] size of source in words. */
242                 uint32_t *pFullLen)   /* [in/out] pointer to accumulated full length (in bytes) of
243                                           all written data. */
244 {
245     int32_t i, j;
246     curLen = curLen << 2; /* now size is in bytes*/
247     /* set length and data */
248     (*ppDst)[0] = (uint8_t)((curLen>>8) & 0xFF); (*ppDst)[1] = (uint8_t)(curLen & 0xFF);
249     *ppDst += CC_FFCDH_LENGTH_COUNTER_SIZE_IN_BYTES;
250 //  CHECK_AND_SET_ERROR(CC_CommonConvertLswMswWordsToMsbLsbBytes(*ppDst, curLen, pSrc, curLen));
251 
252     for (i = curLen - 1, j = 0; i >= 0; i--, j++) {
253         (*ppDst)[i] = (uint8_t)(pSrc[j / CC_32BIT_WORD_SIZE] >> ((j % CC_32BIT_WORD_SIZE) << 3));
254     }
255 
256     /* update the Dst pointer */
257     *ppDst += curLen;
258     if(pFullLen != NULL){
259         *pFullLen += (curLen + CC_FFCDH_LENGTH_COUNTER_SIZE_IN_BYTES);
260     }
261 
262     return;
263 }
264 
265 
266 #ifdef FFC_FURTHER_USING
267 /* The function writes the byte-string Src into the Dst buffer with
268  * setting the length as first 2-bytes counter and control of remaining
269  * size of destination buffer.
270  * \note: The function promotes the destination pointer by written bytes and
271  * decreases the remaining size */
FfcDhWriteBuffers(uint8_t ** ppDst,uint8_t * pSrc,size_t len,size_t * pRemainLen)272 static CCError_t FfcDhWriteBuffers(uint8_t **ppDst, uint8_t *pSrc,
273                            size_t len, size_t *pRemainLen)
274 {
275     if(ppDst == NULL || *ppDst == NULL)
276         return CC_FFCDH_INVALID_ARGUMENT_POINTER_ERROR;
277     if(len + 2 > *pRemainLen)
278         return CC_FFCDH_BUFFER_OVERFLOW_ERROR;
279     /* set length and data */
280     (*ppDst)[0] = (uint8_t)((len>>1) & 0xFF); (*ppDst)[1] = (uint8_t)(len & 0xFF);
281     *ppDst += CC_FFCDH_LENGTH_COUNTER_SIZE_IN_BYTES;
282 
283     if(pSrc != NULL && len != 0) {
284         CC_PalMemCopy(*ppDst, pSrc, len);
285     }
286     /* update the Dst pointer and Remaining length */
287     *ppDst += len;
288     *pRemainLen -= (len + CC_FFCDH_LENGTH_COUNTER_SIZE_IN_BYTES);
289 
290     return CC_OK;
291 }
292 
293 
294 /*! The function copies "len" bytes from pSrc to pDst buffer and sets
295  *  offset of pDst buffer from base address to pCurrOffset. */
FfcDhWriteBufferAndOffset(uint8_t ** ppDst,uint8_t * pSrc,size_t len,uint16_t * pCurrOffset,uint8_t * pBaseAddr)296 static void FfcDhWriteBufferAndOffset(uint8_t **ppDst, uint8_t *pSrc,
297                               size_t len, uint16_t *pCurrOffset, uint8_t *pBaseAddr)
298 {
299     *pCurrOffset = (uint16_t)((*ppDst - pBaseAddr)&0xFFFF);
300     /* set length and data */
301     (*ppDst)[0] = (uint8_t)((len>>1) & 0xFF); (*ppDst)[1] = (uint8_t)(len & 0xFF);
302     *ppDst += CC_FFCDH_LENGTH_COUNTER_SIZE_IN_BYTES;
303 
304     if(len != 0) {
305         CC_PalMemCopy(*ppDst, pSrc, len);
306     }
307     /* update the Dst pointer and Offset of next buffer */
308     *ppDst += len;
309 
310     return;
311 }
312 #endif
313 
314 #ifdef FFC_FURTHER_USING
FfcGetBufferSize(uint8_t ** ppSrc,size_t * pLen,size_t * pRemainLen)315 static CCError_t FfcGetBufferSize(uint8_t **ppSrc, size_t *pLen, size_t *pRemainLen)
316 {
317     size_t len;
318     len = (((size_t)((*ppSrc)[0])) << 8) | (*ppSrc)[1];
319     if(len > 0) {
320         if((*pRemainLen < CC_FFCDH_LENGTH_COUNTER_SIZE_IN_BYTES) ||
321            (*pRemainLen - CC_FFCDH_LENGTH_COUNTER_SIZE_IN_BYTES < len)) {
322             return CC_FFCDH_BUFFER_OVERFLOW_ERROR;
323         }
324     }
325     *pRemainLen -= CC_FFCDH_LENGTH_COUNTER_SIZE_IN_BYTES;
326     *ppSrc += CC_FFCDH_LENGTH_COUNTER_SIZE_IN_BYTES;
327     *pLen = len;
328 
329     return CC_OK;
330 }
331 #endif
332 
333 /************************ Public Functions ******************************/
334 
335 /*******************************************************************************************/
336 /*! The functions initializes the DH Context structure:
337 <li> zeroes context buffers, initializes 3 MS bytes of validation tag by context ID and sets LS byte
338 to zero to prepare it for further indications of setting appropriate parts of data into context
339 */
CC_FfcDhInitCtx(CCFfcDhUserContext_t * pDhUserCtx)340 CEXPORT_C CCError_t  CC_FfcDhInitCtx( CCFfcDhUserContext_t *pDhUserCtx)
341 {
342        /* FUNCTION DECLARATIONS */
343 
344         /* The return error identifier */
345         CCError_t err = CC_OK;
346 
347     CHECK_AND_RETURN_ERR_UPON_FIPS_ERROR();
348 
349         /* check contexts pointers */
350     CHECK_AND_SET_ERROR(pDhUserCtx == NULL, CC_FFCDH_INVALID_CONTEXT_PTR_ERROR);
351 
352         /* zeroing the Context */
353         CC_PalMemSetZero((uint8_t*)pDhUserCtx, sizeof(CCFfcDhUserContext_t));
354 
355         /* check that DhCtx is initialized to zero */
356         pDhUserCtx->validTag = FFCDH_CTX_VALID_TAG_INIT_VAL;
357 
358 End:
359         return err;
360 }
361 
362 
363 /*******************************************************************************************/
364 /*! The functions destroys (zeroes) the DH Context structure.
365 
366 @return CC_OK on success.
367 @return A non-zero value on failure as defined cc_dh_error.h.
368 
369 */
CC_FfcDhFreeCtx(CCFfcDhUserContext_t * pDhUserCtx)370 CEXPORT_C CCError_t  CC_FfcDhFreeCtx( CCFfcDhUserContext_t *pDhUserCtx)
371 {
372        /* FUNCTION DECLARATIONS */
373 
374         /* The return error identifier */
375         CCError_t err = CC_OK;
376 
377     CHECK_AND_RETURN_ERR_UPON_FIPS_ERROR();
378 
379         /* check contexts pointers */
380     CHECK_AND_SET_ERROR(pDhUserCtx == NULL, CC_FFCDH_INVALID_CONTEXT_PTR_ERROR);
381 
382         /* zeroing the Context */
383         CC_PalMemSetZero((uint8_t*)pDhUserCtx, sizeof(CCFfcDhUserContext_t));
384 
385 End:
386         return err;
387 }
388 
389 
390 
391 /**************************************************************/
392 /* The function calculates internal structures FfcDhSchemeInfo_t and FfcDhSchemeDataOffsets_t,
393  * describing which parameters and data are used in the scheme and where appropriate  entries of
394  * the data are saved in the Context.
395  *
396  * When some member of the structure FfcDhSchemeInfo_t in the context is equal to 1,
397  * then appropriate parameter is needed for the Scheme and if it is 0 - not.
398  * The places of the data entries are given by offsets in FfcDhSchemeDataOffsets_t structure.
399  * Assumed: all input parameters are checked and set correctly.
400  *
401  * Note: Offsets of OtherInfo Sub-Entries given from base address = &pDhCth->extendDataBuffer[0];
402  */
FfcDhSchemeInfo(DhContext_t * pDhCtx,uint8_t * pAlgId,size_t algIdSize,uint8_t * pUserId,size_t userIdSize,uint8_t * pPartnId,size_t partnIdSize)403 static CCError_t FfcDhSchemeInfo(
404             DhContext_t *pDhCtx,   /*!< [in/out] pointer to internal DH context structure */
405             uint8_t *pAlgId,       /*!< [in] pointer to Algorithm ID agreed by both parties. */
406             size_t algIdSize,      /*!< [in] size of Algorithm ID in bytes. Should be less than
407                             CC_FFCDH_MAX_SIZE_OF_ALG_ID_SUB_ENTRY. */
408             uint8_t *pUserId,      /*!< [in] pointer to the user ID - a distinct identifier of the user. */
409             size_t userIdSize,     /*!< [in] size of the user ID in bytes. */
410             uint8_t *pPartnId,     /*!< [in] pointer to the partner ID - a distinct identifier of the party. */
411             size_t partnIdSize)     /*!< [in] size of the partner ID in bytes. */
412 {
413 
414     /* FUNCTION DECLARATIONS */
415 
416     uint32_t publKeySize;
417 //  uint32_t nonceSize;
418     /* pointer to structure, containing information about input
419      * parameters needed, for chosen Scheme, party role (U,V) and
420      * confirmation role (provider, recipient). */
421     FfcDhSchemeInfo_t *schemeInfo = &pDhCtx->schemeInfo;
422     /* Structure, containing offsets and sizes of  parties Info */
423     FfcDhSchemeDataOffsets_t *pDataOffsets = &pDhCtx->dataOffsets;
424     CCFfcDhSchemeId_t dhSchemeId = pDhCtx->dhSchemeId;
425         CCFfcDhUserPartyIs_t userParty = pDhCtx->userParty;
426         CCFfcDhUserConfirmMode_t confirmMode = pDhCtx->confirmMode;
427         uint8_t *pBaseAddr = (uint8_t*)&pDhCtx->extendDataBuffer;
428 
429 
430     publKeySize = pDhCtx->ffcDomain.modLenWords*CC_32BIT_WORD_SIZE;
431     pDhCtx->nonceSize = pDhCtx->ffcDomain.ordLenWords*CC_32BIT_WORD_SIZE;
432 //  pDhCtx->macTagSize = DH_SHA_PARAMETERS_SIZES_IN_BYTES[pDhCtx->];
433 
434     /* FUNCTION  logic */
435 
436     /* zeroing of schemeInfo */
437     CC_PalMemSetZero(schemeInfo, sizeof(FfcDhSchemeInfo_t));
438 
439     /* calculate buffers offsets, dependent on user and partner roles. */
440     /* Note: these offsets points directly on data (no length counter before) */
441     pDataOffsets->kdfCounterOffset = 0; /*!< KDF counter offset: is a base=0 for counting other offsets */
442     /* set shared secret value size for Hybrid modes = 2*primeSize and for other modes = 1*primeSize. */
443     pDataOffsets->sharedSecrSize = publKeySize*(1 + ((dhSchemeId == CC_FFCDH_SCHEM_HYBRID_ONE_FLOW) || \
444                                                  (dhSchemeId == CC_FFCDH_SCHEM_HYBRID1)));
445     pDataOffsets->sharedSecrOffset = pDataOffsets->kdfCounterOffset + CC_FFCDH_KDF_COUNTER_SIZE_IN_BYTES;
446     /* The following offsets points on the length counters of OtherInfo entries */
447     pDataOffsets->algIdOffset = FFCDH_SET_OFFSET(pDataOffsets->sharedSecrOffset, pDataOffsets->sharedSecrSize);
448 
449     /*-------------------------------------------------------------*/
450     /* set Scheme Info indication values about required parameters */
451     /*-------------------------------------------------------------*/
452     if(userParty == CC_FFCDH_PARTY_U) {
453         switch(dhSchemeId) {
454         case CC_FFCDH_SCHEM_HYBRID1: /* user: stat=1,ephem=1,nonce=0;  partn: stat=1,ephem=1,nonce=0; */
455             /* set keys used info */
456             schemeInfo->doUserStatKey = 1;
457             schemeInfo->doUserEphemKey = 1;
458             schemeInfo->doPartnerStatKey = 1;
459             schemeInfo->doPartnerEphemKey = 1;
460 
461             /* set confirmation roles and nonces info */
462             if(confirmMode == CC_FFCDH_CONFIRM_NOT_USED)
463                 break;
464             schemeInfo->doConfirmProvid = /* = bilateral||VtoU */
465                 ((confirmMode == CC_FFCDH_CONFIRM_U_TO_V) || (confirmMode == CC_FFCDH_CONFIRM_BILATERAL));
466             schemeInfo->doConfirmRecip =  /* = bilateral||UtoV */
467                 ((confirmMode == CC_FFCDH_CONFIRM_V_TO_U) || (confirmMode == CC_FFCDH_CONFIRM_BILATERAL));
468             break;
469 
470         case CC_FFCDH_SCHEM_EPHEM: /* user: stat=0,ephem=1,nonce=0; partn: stat=0,ephem=1,nonce=0; */
471             /* set keys used info */
472             schemeInfo->doUserEphemKey = 1;
473             schemeInfo->doPartnerEphemKey = 1;
474             /* no confirmation */
475             break;
476 
477         case CC_FFCDH_SCHEM_HYBRID_ONE_FLOW: /* user: stat=1,ephem=1,nonce=0;  partn: stat=1,ephem=0,nonce=(confirm==VtoU); */
478             /* set keys used info */
479             schemeInfo->doUserStatKey = 1;
480             schemeInfo->doUserEphemKey = 1;
481             schemeInfo->doPartnerStatKey = 1;
482 
483             /* set confirmation roles and nonces info */
484             if(confirmMode == CC_FFCDH_CONFIRM_NOT_USED)
485                 break;
486             schemeInfo->doConfirmProvid = /* = bilateral||VtoU */
487                 ((confirmMode == CC_FFCDH_CONFIRM_U_TO_V) || (confirmMode == CC_FFCDH_CONFIRM_BILATERAL));
488             schemeInfo->doConfirmRecip =  /* = bilateral||UtoV */
489                 ((confirmMode == CC_FFCDH_CONFIRM_V_TO_U) || (confirmMode == CC_FFCDH_CONFIRM_BILATERAL));
490             schemeInfo->doPartnerNonce = schemeInfo->doConfirmProvid;
491             break;
492 
493         case CC_FFCDH_SCHEM_ONE_FLOW: /* user: stat=0,ephem=1,nonce=0;  partn: stat=1,ephem=0,nonce=0 */
494             /* set keys used info */
495             schemeInfo->doUserEphemKey = 1;
496             schemeInfo->doPartnerStatKey = 1;
497 
498             /* set confirmation roles and nonces info */
499             if(confirmMode == CC_FFCDH_CONFIRM_NOT_USED)
500                 break;
501             if(confirmMode != CC_FFCDH_CONFIRM_V_TO_U) {
502                 return CC_FFCDH_INVALID_CONFIRM_MODE_ERROR;
503             } else {
504                 schemeInfo->doConfirmRecip = 1;  /*user is recipient*/
505                 schemeInfo->doPartnerNonce = 1;
506             }
507             break;
508 
509         case CC_FFCDH_SCHEM_STATIC: /* user: stat=1,ephem=1,nonce=0;  partn: stat=1,ephem=0,nonce=(confirm?); */
510             /* set keys used info */
511             schemeInfo->doUserStatKey = 1;
512             schemeInfo->doPartnerStatKey = 1;
513 
514             /* set confirmation roles and nonces info */
515             if(confirmMode == CC_FFCDH_CONFIRM_NOT_USED)
516                 break;
517             schemeInfo->doConfirmProvid = /* = bilateral||UtoV */
518                 ((confirmMode == CC_FFCDH_CONFIRM_U_TO_V) || (confirmMode == CC_FFCDH_CONFIRM_BILATERAL));
519             schemeInfo->doConfirmRecip =  /* = bilateral||UtoV */
520                 ((confirmMode == CC_FFCDH_CONFIRM_V_TO_U) || (confirmMode == CC_FFCDH_CONFIRM_BILATERAL));
521             schemeInfo->doUserNonce = 1; /* always = 1: see sec.6.3.3.1*/
522             schemeInfo->doPartnerNonce = schemeInfo->doConfirmProvid;
523             break;
524 
525         default:
526             return CC_FFCDH_INVALID_SCHEM_ID_ERROR;
527 
528             /* calculate user and partner Info data offsets (starts from Party ID). */
529 //          pDataOffsets->userIdOffset = FFCDH_SET_OFFSET(pDataOffsets->algIdOffset, algIdSize);
530 //          pDataOffsets->partnIdOffset= FFCDH_SET_OFFSET(pDataOffsets->algIdOffset, CC_FFCDH_MAX_SIZE_OF_PARTY_INFO_BYTES);
531         }
532     } else { /* userParty == CC_FFCDH_PARTY_V */
533         switch(dhSchemeId) {
534         case CC_FFCDH_SCHEM_HYBRID1:
535             /* set keys used info */
536             schemeInfo->doUserStatKey = 1;
537             schemeInfo->doUserEphemKey = 1;
538             schemeInfo->doPartnerStatKey = 1;
539             schemeInfo->doPartnerEphemKey = 1;
540 
541             /* set confirmation roles and nonce info */
542             if(confirmMode == CC_FFCDH_CONFIRM_NOT_USED)
543                 break;
544             schemeInfo->doConfirmProvid =
545                 ((confirmMode == CC_FFCDH_CONFIRM_V_TO_U) || (confirmMode == CC_FFCDH_CONFIRM_BILATERAL));
546             schemeInfo->doConfirmRecip =
547                 ((confirmMode == CC_FFCDH_CONFIRM_U_TO_V) || (confirmMode == CC_FFCDH_CONFIRM_BILATERAL));
548             break;
549 
550         case CC_FFCDH_SCHEM_EPHEM:
551             /* set keys used info */
552             schemeInfo->doUserEphemKey = 1;
553             schemeInfo->doPartnerEphemKey = 1;
554             /* no confirmation */
555             break;
556 
557         case CC_FFCDH_SCHEM_HYBRID_ONE_FLOW:
558             /* set keys used info */
559             schemeInfo->doUserStatKey = 1; /* ephem=0*/
560             schemeInfo->doPartnerStatKey = 1;
561             schemeInfo->doPartnerEphemKey = 1;
562 
563             /* set confirmation roles and nonces info */
564             if(confirmMode == CC_FFCDH_CONFIRM_NOT_USED)
565                 break;
566             schemeInfo->doConfirmProvid = /* = bilateral||VtoU */
567                 ((confirmMode == CC_FFCDH_CONFIRM_V_TO_U) || (confirmMode == CC_FFCDH_CONFIRM_BILATERAL));
568             schemeInfo->doConfirmRecip =  /* = bilateral||UtoV */
569                 ((confirmMode == CC_FFCDH_CONFIRM_U_TO_V) || (confirmMode == CC_FFCDH_CONFIRM_BILATERAL));
570             schemeInfo->doUserNonce = schemeInfo->doConfirmRecip;
571             break;
572 
573         case CC_FFCDH_SCHEM_ONE_FLOW: /* user: stat=1,ephem=0,nonce=0;  partn: stat=0,ephem=1,nonce=0 */
574             /* set keys used info */
575             schemeInfo->doUserStatKey = 1;
576             schemeInfo->doPartnerEphemKey = 1;
577 
578             /* set confirmation roles and nonces info */
579             if(confirmMode == CC_FFCDH_CONFIRM_NOT_USED)
580                 break;
581             if((confirmMode != CC_FFCDH_CONFIRM_V_TO_U)) {
582                 return CC_FFCDH_INVALID_CONFIRM_MODE_ERROR;
583             } else {
584                 schemeInfo->doConfirmProvid = 1; /*user is provider*/
585                 schemeInfo->doUserNonce = 1;
586             }
587             break;
588 
589         case CC_FFCDH_SCHEM_STATIC: /* user: stat=1,ephem=1,nonce=0;  partn: stat=1,ephem=0,nonce=(confirm?); */
590             /* set keys used info */
591             schemeInfo->doUserStatKey = 1;
592             schemeInfo->doPartnerStatKey = 1;
593 
594             /* set confirmation roles and nonces info */
595             if(confirmMode == CC_FFCDH_CONFIRM_NOT_USED)
596                 break;
597             schemeInfo->doConfirmProvid = /* = bilateral||VtoU */
598                 ((confirmMode == CC_FFCDH_CONFIRM_V_TO_U) || (confirmMode == CC_FFCDH_CONFIRM_BILATERAL));
599             schemeInfo->doConfirmRecip =  /* = bilateral||UtoV */
600                 ((confirmMode == CC_FFCDH_CONFIRM_U_TO_V) || (confirmMode == CC_FFCDH_CONFIRM_BILATERAL));
601             schemeInfo->doUserNonce = schemeInfo->doConfirmRecip;
602             schemeInfo->doPartnerNonce = schemeInfo->doConfirmProvid;
603             break;
604 
605         default:
606             return CC_FFCDH_INVALID_SCHEM_ID_ERROR;
607         }
608 
609         /* calculate user and partner PartyInfo data offsets (starts from Party ID). */
610 //      pDataOffsets->userIdOffset = FFCDH_SET_OFFSET(pDataOffsets->algIdOffset, CC_FFCDH_MAX_SIZE_OF_PARTY_INFO_BYTES);
611 //      pDataOffsets->partnIdOffset = FFCDH_SET_OFFSET(pDataOffsets->algIdOffset, algIdSize);
612     }
613 
614     /* calculate user Info data sub-entries offsets */
615 //  pDataOffsets->userStatPublKeyOffset = FFCDH_SET_OFFSET(pDataOffsets->userIdOffset, userIdSize);
616 //  pDataOffsets->userEphemPublKeyOffset = FFCDH_COND_SET_OFFSET(pDataOffsets->userStatPublKeyOffset, publKeySize, schemeInfo->doUserStatKey);
617 //  pDataOffsets->userNonceOffset = FFCDH_COND_SET_OFFSET(pDataOffsets->userEphemPublKeyOffset, publKeySize, schemeInfo->doUserEphemKey);
618 //  pDataOffsets->userOtherDataOffset = FFCDH_COND_SET_OFFSET(pDataOffsets->userNonceOffset, nonceSize, schemeInfo->doUserNonce);
619 //
620 //  /* calculate partner Info data sub-entries offsets */
621 //  pDataOffsets->partnStatPublKeyOffset = FFCDH_SET_OFFSET(pDataOffsets->partnIdOffset, partnIdSize);
622 //  pDataOffsets->partnEphemPublKeyOffset = FFCDH_COND_SET_OFFSET(pDataOffsets->partnStatPublKeyOffset, publKeySize, schemeInfo->doPartnerStatKey);
623 //  pDataOffsets->partnNonceOffset = FFCDH_COND_SET_OFFSET(pDataOffsets->partnEphemPublKeyOffset, publKeySize, schemeInfo->doPartnerEphemKey);
624 //  pDataOffsets->partnOtherDataOffset = FFCDH_COND_SET_OFFSET(pDataOffsets->partnNonceOffset, nonceSize, schemeInfo->doPartnerNonce); ;
625 //
626 //  pDataOffsets->suppPublInfoOffset = FFCDH_SET_OFFSET(pDataOffsets->algIdOffset, algIdSize + 2*CC_FFCDH_MAX_SIZE_OF_PARTY_INFO_BYTES);
627 //  pDataOffsets->suppPrivInfoOffset = FFCDH_SET_OFFSET(pDataOffsets->suppPublInfoOffset, CC_FFCDH_MAX_SIZE_OF_OTHER_INFO_SUPPL_ENTRY_BYTES);
628 
629     /* copy AlgId, User ID and Partner ID into Context */
630     CC_PalMemCopy(pBaseAddr + pDataOffsets->algIdOffset, pAlgId, algIdSize);
631     CC_PalMemCopy(pDhCtx->userId, pUserId, userIdSize);
632     pDhCtx->userIdSizeBytes = userIdSize;
633     CC_PalMemCopy(pDhCtx->partnerId, pPartnId, partnIdSize);
634     pDhCtx->partnerIdSizeBytes = partnIdSize;
635 
636 //  pDataOffsets->userInfoSize;            /*!< full size of Party U data */
637 //  pDataOffsets->partnInfoSize;           /*!< full size of partner data */
638 //  pDataOffsets->suppPublInfoSize;
639 //  pDataOffsets->suppPublInfoSize;
640 //
641 //End:
642 
643     return CC_OK;
644 }
645 
646 
647 
648 /*******************************************************************************************/
649 /*! The function sets into DH context FFCDH Scheme agreed parameters: SchemeId, User role, Confirmation mode etc.
650 \note The context is used in DH Agreement functions, implementing NIST SP 800-56A rev.2 standard.
651 \note Assumed, that input FFC Domain is properly generated or imported and validated according to
652 NIST SP 800-56A and FIPS 186-4 standards.
653 
654 @return CC_OK on success.
655 @return A non-zero value on failure as defined cc_dh_error.h.
656 */
CC_FfcDhCtxSetSchemeParams(CCFfcDhUserContext_t * pDhUserCtx,CCFfcDomain_t * pDomain,uint8_t * pAlgId,size_t algIdSize,size_t secretKeyingDataSize,uint8_t * pUserId,size_t userIdSize,uint8_t * pPartnId,size_t partnIdSize,CCFfcDhUserPartyIs_t userParty,CCFfcDhSchemeId_t dhSchemeId,CCFfcParamSetId_t ffcParamSetId,CCFfcDhKdfModeSp56A_t kdfMode,CCFfcHashOpMode_t ffcHashMode,CCFfcDhUserConfirmMode_t confirmMode,uint8_t * pHmacSalt,size_t hmacSaltSize,size_t macTagSize)657 CEXPORT_C CCError_t  CC_FfcDhCtxSetSchemeParams(
658                             CCFfcDhUserContext_t *pDhUserCtx, /*!< [in/out] pointer to context structure, containing all parameters and data,
659                                                                         defining DH Key Agreement Scheme */
660                             CCFfcDomain_t *pDomain,           /*!< [in] pointer to DH FFC Domain structure. */
661                             uint8_t *pAlgId,                  /*!< [in] pointer to Algorithm ID agreed by both parties and indicates how the derived
662                                                                         secret keying material will be parsed and for which algorithms (sec.5.8.1.2).
663                                                                         In partial, Algorithm ID should indicate also how much bits are intended for
664                                                                         internal confirmation MAC algorithm and how much remaining bits will be
665                                                                         returned to the user for external applications/algorithms (the total size should
666                                                                         be equal to chosen secretKeyDataSize). */
667                             size_t algIdSize,                 /*!< [in] size of Algorithm ID in bytes, should be less than
668                                                         CC_FFCDH_MAX_SIZE_OF_ALG_ID_SUB_ENTRY. */
669                             size_t secretKeyingDataSize,      /*!< [in] size in bytes of shared secret keying data, which will be extracted and in
670                                                                                     the next steps and passed to the user for using in  external algorithm(s).
671                                                                                     It is used for calculation of Derived Keying material size =
672                                                                                     key size of the used HMAC function + secretKeyingDataSize. */
673                             uint8_t *pUserId,                 /*!< [in] pointer to the user ID - a distinct identifier of the user. */
674                             size_t userIdSize,                /*!< [in] size of the user ID in bytes. */
675                             uint8_t *pPartnId,                /*!< [in] pointer to the partner ID - a distinct identifier of the party. */
676                             size_t partnIdSize,               /*!< [in] size of the partner ID in bytes. */
677                             CCFfcDhUserPartyIs_t userParty,   /*!< [in] enumerator, defining role of the user (function's caller) in the
678                                                                         DH Agreement Scheme: partyU or partyV. */
679                             CCFfcDhSchemeId_t dhSchemeId,     /*!< [in] enumerator ID of used FFC DH Key Agreement Scheme, as defined
680                                                                 in sec. 6, tab. 12. */
681                             CCFfcParamSetId_t ffcParamSetId,  /*!< [in] enumerator, defining the set of FFC domain parameters
682                                                                                     according to SP 56A rev.2 section 5.5.1.1, tab.1. */
683                             CCFfcDhKdfModeSp56A_t kdfMode,    /*!< [in] enumerator ID of used KDF function, based on HASH or HMAC algorithms. In current
684                                                                         implementation is allowed only KDF HMAC_RFC5869 mode, according to KDF_HMAC_RFC-5869. */
685                             CCFfcHashOpMode_t ffcHashMode,    /*!< [in] enumerator ID of used SHAXXX HASH mode, supported by the product.
686                                                                         Note: HASH SHA1 function may be used only with SA set of domain parameters
687                                                                         (sec. 5.8.1, tab.6); with other sets the function returns an error. */
688                             CCFfcDhUserConfirmMode_t confirmMode, /*!< enumerator, defining confirmation mode of each party: provider
689                                                                         or/and recipient, according to sec. 5.9. */
690                             uint8_t *pHmacSalt,               /*!< [in] optional, pointer to the Salt, used as key in HMAC-KDF function on appropriate modes.
691                                                                         If HMAC-KDF mode is set, and the pointer and size are zero, then the Salt is
692                                                                         treated as full-zero bytes array of size equalled to block-size of used HMAC function.
693                                                                         If HMAC-KDF mode is HMAC_RFC5869_MODE, then the Salt is treated as HMAC Key.
694                                                                         If only one of parameters (pointer and size) is zero, but other not, then the
695                                                                         function returns an error. */
696                             size_t  hmacSaltSize,             /*!< [in] optional, size of Salt in bytes, should be equalled to the HMAC block size if
697                                                                         salt is used. */
698                             size_t  macTagSize                /*!< [in] optional, size in bytes of confirmation MacTag. Should be in range:
699                                                                         [CC_FFCDH_MIN_SIZE_OF_CONFIRM_MAC_TAG_BYTES, CC_FFCDH_MAX_SIZE_OF_CONFIRM_MAC_TAG_BYTES]. */
700 )
701 {
702 
703         /* FUNCTION DECLARATIONS */
704 
705         /* the return error identifier */
706         CCError_t err = CC_OK;
707         /* pointer to internal DH context structure */
708         DhContext_t *pDhCtx;
709         uint32_t hashSize, minHashSize;
710         uint32_t ffcPrimeSize, ffcOrderSize;
711         CCHashOperationMode_t hashMode;
712 //        FfcDhSchemeDataOffsets_t *pOffsets;
713 //        uint32_t ffcOrderSizeBytes;
714 //        uint8_t *pTmp, *pBaseAddr;
715 //        uint16_t zzSize; /* size of shared secret ZZ, depended on Scheme */
716 //        uint16_t remainLen; /* remaining size of buffers to write */
717 //        uint32_t ffcOrderSize;
718 
719     CHECK_AND_RETURN_ERR_UPON_FIPS_ERROR();
720 
721 
722         /* ...... checking the parameters validity ........ */
723         /* ------------------------------------------------ */
724 
725         /* check contexts pointers and tags */
726     CHECK_AND_RETURN_ERROR(pDhUserCtx == NULL, CC_FFCDH_INVALID_CONTEXT_PTR_ERROR);
727         /* check that DhCtx is valid */
728     CHECK_AND_RETURN_ERROR(pDhUserCtx == NULL, CC_FFCDH_INVALID_CONTEXT_PTR_ERROR);
729     CHECK_AND_SET_ERROR(FFCDH_CHECK_CTX_VALID_TAG_BITS(pDhUserCtx->validTag, FFCDH_CTX_VALID_TAG_INIT_VAL),
730                 CC_FFCDH_CONTEXT_VALIDATION_TAG_ERROR);
731     /* Check FFC Domain pointer and validation tag */
732     CHECK_AND_RETURN_ERROR(pDomain == NULL, CC_FFCDH_INVALID_DOMAIN_PTR_ERROR);
733     CHECK_AND_SET_ERROR(pDomain->validTag != CC_FFC_DOMAIN_VALIDATION_TAG,
734                 CC_FFCDH_INVALID_DOMAIN_VALIDAT_TAG_ERROR);
735 
736     /* check user and algorithm IDs pointers and sizes */
737     CHECK_AND_RETURN_ERROR((pUserId == NULL || userIdSize == 0 || userIdSize > CC_FFCDH_MAX_SIZE_OF_PARTY_ID_BYTES),
738                 CC_FFCDH_INVALID_USER_PARTY_ID_ERROR);
739     CHECK_AND_RETURN_ERROR((pAlgId == NULL) || (algIdSize == 0) || (algIdSize > CC_FFCDH_MAX_SIZE_OF_ALG_ID_ENTRY_BYTES),
740                     CC_FFCDH_ALGORITHM_ID_ERROR);
741         /* check optional Salt data */
742     CHECK_AND_RETURN_ERROR((pHmacSalt == NULL) != (hmacSaltSize == 0) ||
743                     (hmacSaltSize > CC_FFCDH_MAX_SIZE_OF_ALG_ID_ENTRY_BYTES), CC_FFCDH_ALGORITHM_ID_ERROR);
744 
745          /* check all enumerators */
746     CHECK_AND_RETURN_ERROR(dhSchemeId    >= CC_FFCDH_SCHEM_NUM_OFF_MODE, CC_FFCDH_INVALID_SCHEM_ID_ERROR);
747     CHECK_AND_RETURN_ERROR(ffcParamSetId >= CC_FFC_PARAMS_SET_FC, CC_FFCDH_INVALID_DOMAIN_SIZES_SET_ID_ERROR);
748     CHECK_AND_RETURN_ERROR(kdfMode       >= CC_FFCDH_KDF_NUM_OFF_MODE, CC_FFCDH_INVALID_KDF_MODE_ERROR);
749     CHECK_AND_RETURN_ERROR(ffcHashMode   >= CC_FFC_HASH_NUM_OFF_MODE, CC_FFCDH_INVALID_HASH_MODE_ERROR);
750     CHECK_AND_RETURN_ERROR(userParty     >= CC_FFCDH_PARTY_NUM_OFF_MODE, CC_FFCDH_INVALID_USER_PARTY_ID_ERROR);
751     CHECK_AND_RETURN_ERROR(confirmMode   >= CC_FFCDH_CONFIRM_NUM_OFF_MODE, CC_FFCDH_INVALID_CONFIRM_MODE_ERROR);
752 
753         /* Get internal context structure */
754         pDhCtx = (DhContext_t*)&pDhUserCtx->contextBuff;
755 
756         /* check that FFC params Set in Domain meets to given by input value. */
757         CHECK_AND_SET_ERROR(pDomain->ffcParamSetId != ffcParamSetId, CC_FFCDH_INVALID_DOMAIN_DATA_ERROR);
758 
759         /* get HASH related parameters */
760         CHECK_ERROR(FfcGetHashMode(&hashMode, NULL/*pHkdfHashMode*/, NULL/*pBlockSize*/, &hashSize, ffcHashMode/*in*/));
761 
762         /* get DH Domain related parameters */
763         CHECK_ERROR(FfcGetDomainSizes(NULL/*pMaxSecurStrengthBytes*/, &ffcPrimeSize/*pPrimeLenBytes*/,
764                 &ffcOrderSize/*pOrderLenBytes*/, &minHashSize, ffcParamSetId));
765 
766         /* check that Domain generation parameters are meets to given Domain sizes set ffcParamSetId. */
767         CHECK_AND_SET_ERROR((pDomain->modLenWords * CC_32BIT_WORD_SIZE != ffcPrimeSize) ||
768                     (pDomain->ordLenWords * CC_32BIT_WORD_SIZE != ffcOrderSize) ||
769                     (pDomain->ffcHashMode != ffcHashMode), CC_FFCDH_INVALID_DOMAIN_DATA_ERROR);
770 
771         /* check HASH mode (size) according to standard security for FFC Sizes Set:
772          * SP 800-56A rev.2, tab.6,8 */
773         CHECK_AND_SET_ERROR(hashSize < minHashSize, CC_FFCDH_INVALID_LOW_HASH_SIZE_ERROR);
774 
775         /* check confirmation mode according to Scheme and user party (U,V).
776            Note: in other schemes allowed all modes */
777         if(confirmMode != CC_FFCDH_CONFIRM_NOT_USED) {
778             /* check Scheme and Confirmation accordance */
779             CHECK_AND_SET_ERROR(
780                (dhSchemeId == CC_FFCDH_SCHEM_EPHEM)         ||
781            ((dhSchemeId == CC_FFCDH_SCHEM_ONE_FLOW) &&
782             (confirmMode != CC_FFCDH_CONFIRM_V_TO_U))   ||
783            ((dhSchemeId == CC_FFCDH_SCHEM_HYBRID_ONE_FLOW) &&
784             (confirmMode != CC_FFCDH_CONFIRM_U_TO_V)),
785             CC_FFCDH_INVALID_CONFIRM_MODE_ERROR);
786 
787                 /* if confirmation is used, then check MacTag size */
788                 CHECK_AND_SET_ERROR((macTagSize > CC_FFCDH_MAX_SIZE_OF_CONFIRM_MAC_TAG_BYTES) ||
789                                 (macTagSize < CC_FFCDH_MIN_SIZE_OF_CONFIRM_MAC_TAG_BYTES),
790                                 CC_FFCDH_MAC_TAG_SIZE_INVALID_ERROR);
791                 /* set MacTag size */
792                 pDhCtx->macTagSize = macTagSize;
793         }
794 
795         /* check the optional HMAC salt, used in key derivation on HMAC mode */
796         CHECK_AND_SET_ERROR((pHmacSalt != NULL) != (hmacSaltSize != 0),
797                     CC_FFCDH_INVALID_HMAC_SALT_PARAMS_ERROR);
798 
799 
800         /*------------------------------------------*/
801         /*            set DH Scheme parameters      */
802         /*------------------------------------------*/
803 
804         /* HMAC KDF parameters */
805         if(kdfMode == CC_FFCDH_KDF_HMAC_RFC5869_MODE) {
806         /* check that the user not trying to pass redundant HMAC salt */
807         CHECK_AND_SET_ERROR((pHmacSalt == NULL) || (hmacSaltSize == 0), CC_FFCDH_INVALID_HMAC_SALT_PARAMS_ERROR);
808         }
809 #ifdef CC_FFCDH_KDF_HMAC_ONE_STEP_MODE
810         else if(kdfMode == CC_FFCDH_KDF_HMAC_SINGLE_STEP_MODE) {
811             CHECK_AND_SET_ERROR((pHmacSalt == NULL) ||
812                         (hmacSaltSize != DhHashBlockAndDigestSizes[hashMode].blockSizeInBytes),
813                             CC_FFCDH_INVALID_HMAC_SALT_PARAMS_ERROR);
814         }
815         else {
816             err = CC_FFCDH_INVALID_KDF_MODE_ERROR;
817             goto End;
818         }
819 #endif
820 
821         /* copy FFC Domain into DH context */
822         CC_PalMemCopy(&pDhCtx->ffcDomain, pDomain, sizeof(pDhCtx->ffcDomain));
823 
824         /* copy given Salt into DH context */
825         if(pHmacSalt != NULL) {
826             pDhCtx->hmacSaltSizeBytes = hmacSaltSize;
827                 CC_PalMemCopy(pDhCtx->hmacSalt, pHmacSalt, hmacSaltSize);
828                 pDhCtx->hmacSaltSizeBytes = hmacSaltSize;
829         }
830 
831         /* set DH Scheme parameters into Context */
832         pDhCtx->dhSchemeId   = dhSchemeId;
833         pDhCtx->ffcHashMode  = ffcHashMode;
834         pDhCtx->kdfMode      = kdfMode;
835         pDhCtx->userParty    = userParty;
836         pDhCtx->confirmMode  = confirmMode;
837         pDhCtx->ffcParamSet  = ffcParamSetId;
838         pDhCtx->nonceSize    = ffcOrderSize;
839         pDhCtx->secretKeyingDataSize = secretKeyingDataSize;
840         pDhCtx->macTagSize = macTagSize;
841 
842         /* set required size of keying material to be derived according to confirmation mode and HMAC size */
843         if(confirmMode < CC_FFCDH_CONFIRM_NOT_USED) {
844             pDhCtx->derivedKeyingMaterialSize = secretKeyingDataSize + CC_FFCDH_SIZE_OF_CONFIRM_MAC_KEY_IN_BYTES;
845         }
846 
847         err = FfcDhSchemeInfo(pDhCtx, pAlgId, algIdSize, pUserId, userIdSize, pPartnId, partnIdSize);
848         if(err)
849             goto End;
850 
851 //        ffcOrderSize = pDhCtx->ffcDomain.ordLenBytes;
852 //
853 //        /* size of shared secret ZZ */
854 //        zzSize = pDhCtx->ffcDomain.modLenBytes;
855 //        if((dhSchemeId == CC_FFCDH_SCHEM_HYBRID1) || (dhSchemeId == CC_FFCDH_SCHEM_HYBRID_ONE_FLOW)) {
856 //          zzSize += pDhCtx->ffcDomain.modLenBytes;
857 //        }
858 
859          /* set validation tag */
860         pDhUserCtx->validTag |= FFCDH_CTX_VALID_TAG_SCHEM_PARAM_BIT;
861 
862 End:
863         if (err != CC_OK) {
864                 /* delete secure sensitive data */
865                 CC_PalMemSetZero((uint8_t*)pDhUserCtx, sizeof(CCFfcDhUserContext_t));
866     }
867 
868         return err;
869 
870 }/* END OF CC_FfcDhCtxSetSchemeParams function */
871 
872 
873 
874 /*******************************************************************************************/
875 /*! The function generates public/private FFC Key pair according to
876  *  NIST SP 800-56A rev.2 standard.
877  *  Assumed: all in/out pointers and contexts content are correct;
878  *           all arrays are set with little endianness order of bytes and words;
879  *           size of output private key = FFC generator order size;
880  *           size of output public key = FFC prime (module) size;
881  *           leading zeros are given, if existing.
882  */
FfcDhGenKeyPair(CCFfcDomain_t * pFfcDomain,CCRndContext_t * pRndContext,uint32_t * pPrivKey,uint32_t * pPublKey)883 static CCError_t FfcDhGenKeyPair ( // RL check, that result keys are put out in CC only on end of generation
884             CCFfcDomain_t *pFfcDomain,    /*!< [in] pointer to DH FFC Domain structure. */
885             CCRndContext_t *pRndContext,    /*!< [in] random generation function context. */
886             uint32_t *pPrivKey,             /*!< [out] pointer to private key buffer. */
887             uint32_t *pPublKey)             /*!< [out] pointer to public key buffer. */
888 {
889     CCError_t err = CC_OK;
890 
891     uint32_t primeModSize = pFfcDomain->modLenWords*CC_32BIT_WORD_SIZE;
892     uint32_t ffcOrderSize = pFfcDomain->ordLenWords*CC_32BIT_WORD_SIZE;
893 
894     /* generate random in range [1, q-1]- little endianness  */
895     err = CC_RndGenerateVectorInRange(
896             pRndContext,                             /*in*/
897             pFfcDomain->ordLenWords*CC_BITS_IN_32BIT_WORD, /*rndSizeInBits*/
898             (uint8_t*)&pFfcDomain->order[0],         /*maxVect*/
899             (uint8_t*)pPrivKey);                     /*out*/
900 
901     if (err != CC_OK) {
902         goto End;
903     }
904 
905 // RL convert bytes to words only for #ifdef BIG__ENDIAN
906     /* convert key to big endianness bytes */
907 //  CC_CommonReverseMemcpy(pPrivKey, pPrivKey, ffcOrderSize);
908 
909 
910     /* ----------------------------------------------------------- */
911     /*           Create the public key                             */
912     /* ----------------------------------------------------------- */
913     err = PkiExecModExpLeW(
914         pPublKey,                       /*public key - out*/
915         pFfcDomain->genG,               /*generator G*/
916         primeModSize,                   /*generator size in words*/
917         pFfcDomain->prime,              /*prime P*/
918         primeModSize*CC_BITS_IN_BYTE,   /*P size in bits*/
919         pPrivKey,                       /*priv.key - exponent*/
920         ffcOrderSize);                   /*priv.key size in word*/
921 
922     /* check error */
923     if (err != CC_OK) {
924         goto End;
925     }
926 
927 
928 End:
929     return err;
930 
931 }
932 
933 
934 /*******************************************************************************************/
935 /*!
936 @brief The function generates FFC DH key pairs according to DH Scheme and NIST SP 800-56A rev.2 standard:
937 <ol><li> - count of required key pairs (one or two is dependent on DH Scheme and user Party (U or V),
938 inserted into Context. For each of key pair the function performs the following steps: </li>
939 <li> - randomly generates the private key X according to section 5.6.1.1 and FIPS 184-4, B.1.1; </li>
940 <li> - the sizes of primes P,Q should be taken from DH FFC sizes set previously inserted into Context;  </li>
941 <li> - calculates the associated public key  Y = G^X mod P; </li>
942 <li> - sets private and public keys in appropriate place in the Context according to user party (U,V) and keys
943 status (static, ephemeral); </li>
944 <li> - exports the public key as big endianness order of bytes. </li></ol>
945 \note Before calling of this function, DH context should be initialized, DH Scheme parameters and
946 DH Domain are inserted by calling appropriate functions, else the function returns an error.
947 
948 @return CC_OK on success.
949 @return A non-zero value on failure as defined cc_dh_error.h, cc_rnd_error.h.
950 */
CC_FfcDhGeneratePublPrivKeys(CCFfcDhUserContext_t * pDhUserCtx,CCRndContext_t * pRndContext)951 CEXPORT_C CCError_t CC_FfcDhGeneratePublPrivKeys(
952                                 CCFfcDhUserContext_t *pDhUserCtx,/*!< [in/out] pointer to DH FFC User Context structure. */
953                                 CCRndContext_t *pRndContext )     /*!< [in] random generation function context. */
954 {
955         /* FUNCTION DECLARATIONS */
956 
957         /* The return error identifier */
958         CCError_t err = CC_OK;
959         /* temp pointers */
960         uint32_t *pPrivKey, *pPublKey;
961 //        uint8_t *pprime;
962 //        uint32_t nonceSize;
963         DhContext_t *pDhCtx; /* pointer to the internal DH context structure */
964         /* RND state and function pointers */
965         CCRndState_t   *pRndState;
966         CCRndGenerateVectWorkFunc_t RndGenerateVectFunc;
967 
968     CHECK_AND_RETURN_ERR_UPON_FIPS_ERROR();
969 
970 
971         /* ............... checking the parameters validity ................... */
972         /* -------------------------------------------------------------------- */
973 
974         /* check contexts pointers and tags */
975     CHECK_AND_RETURN_ERROR(pDhUserCtx == NULL, CC_FFCDH_INVALID_CONTEXT_PTR_ERROR);
976         /* check that DhCtx is valid for user keys generation step: *
977         *  DH Scheme and Domain are set.                           */
978     CHECK_AND_RETURN_ERROR(FFCDH_CHECK_CTX_VALID_TAG_BITS(pDhUserCtx->validTag, FFCDH_CTX_VALID_TAG_INIT_VAL),
979                                                    CC_FFCDH_CONTEXT_VALIDATION_TAG_ERROR);
980 
981         /* Check RND context pointer. Note: full check of context will be  *
982         *  performed in the called CC_RndGenerateVectorInRange function */
983     CHECK_AND_RETURN_ERROR(pRndContext == NULL, CC_RND_CONTEXT_PTR_INVALID_ERROR);
984         pRndState = (CCRndState_t*)&(pRndContext->rndState);
985         RndGenerateVectFunc = pRndContext->rndGenerateVectFunc;
986         CHECK_AND_RETURN_ERROR(RndGenerateVectFunc == NULL, CC_RND_GEN_VECTOR_FUNC_ERROR);
987 
988         pDhCtx = (DhContext_t*)&pDhUserCtx->contextBuff; /* get internal DH context */
989 //        pBaseAddr = &pDhCtx->extendDataBuffer[0];
990 
991         /* get FFC domain parameters */
992 //        ffcOrderSize = pDhCtx->ffcDomain.modLenBytes;
993 //        ffcOrderSize = pDhCtx->ffcDomain.ordLenBytes;
994 //        pprime = &pDhCtx->ffcDomain.prime[0];
995 
996 //        nonceSize = pDhCtx->ffcDomain.ordLenBytes;
997 
998 
999         /* ------------------------------------------------------------  *
1000          *  Generate user private and public keys using method, defined  *
1001          *  in FIPS 186-4 B.1.2 (by testing candidates)                  *
1002          * ------------------------------------------------------------  */
1003 
1004         /* static key pair */
1005     if(pDhCtx->schemeInfo.doUserStatKey == 1) {
1006         /* set static key */
1007         pPrivKey = &pDhCtx->statPrivKey[0];
1008         pPublKey = &pDhCtx->userStatPublKey[0];
1009         /* generate static private and public keys */
1010         err = FfcDhGenKeyPair(&pDhCtx->ffcDomain, pRndContext, pPrivKey, pPublKey);
1011         if (err != CC_OK) {
1012             goto End;
1013         }
1014         pDhCtx->validTag |= FFCDH_CTX_VALID_TAG_USER_STAT_KEY_BIT;
1015 
1016     }
1017     /* ephemeral key pair */
1018     if(pDhCtx->schemeInfo.doUserEphemKey == 1){
1019         pPrivKey = &pDhCtx->ephemPrivKey[0];
1020         pPublKey = &pDhCtx->userEphemPublKey[0];
1021         /* generate static private and public keys */
1022         err = FfcDhGenKeyPair(&pDhCtx->ffcDomain, pRndContext, pPrivKey, pPublKey);
1023         if (err != CC_OK) {
1024             goto End;
1025         }
1026         pDhCtx->validTag |= FFCDH_CTX_VALID_TAG_USER_EPHEM_KEY_BIT;
1027     } else if(pDhCtx->schemeInfo.doUserNonce == 1) {
1028         /* generate random nonce */
1029         CHECK_ERROR(RndGenerateVectFunc(pRndState, pDhCtx->userNonce, pDhCtx->nonceSize));
1030         pDhCtx->validTag |= FFCDH_CTX_VALID_TAG_USER_NONCE_BIT;
1031     }
1032 
1033 End:
1034         if (err != CC_OK) {
1035                 /* delete secure sensitive data */
1036                 CC_PalMemSetZero((uint8_t*)pDhUserCtx, sizeof(CCFfcDhUserContext_t));
1037     }
1038 
1039         return err;
1040 
1041 }/* END OF CC_FfcDhGeneratePublPrivKeys function */
1042 
1043 
1044 
1045 
1046 /*******************************************************************************************/
1047 /*!
1048 @brief This function validates the FFC DH public key according to NIST SP 800-56A rev.2,
1049        sec.5.6.2.3.1 and checking mode:
1050 
1051 <ul><li> - on "partial" mode - checks the pointers and high/low limits of key value;</li>
1052 <li> - on "full" mode - checks also that the the key belongs to the FFC subgroup; </li></ul>
1053 \note Before calling of this function, appropriate FFC Domain parameters should be obtained and validated,
1054 else the function returns an error.
1055 @return CC_OK on success.
1056 @return A non-zero value on failure as defined cc_dh_error.h.
1057 */
CC_FfcDhValidatePublKey(CCFfcDomain_t * pDomain,uint8_t * pPublKeyData,size_t publKeyDataSize,CCFfcDhKeyValidMode_t validatMode,uint32_t * pTmpBuff)1058 CEXPORT_C CCError_t CC_FfcDhValidatePublKey(
1059             CCFfcDomain_t *pDomain,          /*!< [in/out] pointer to DH FFC Context structure. */
1060             uint8_t *pPublKeyData,             /*!< [in] pointer to given DH FFC public key formatted as big endianness array;
1061                                      it should be in range [2, P-2], where P is the Domain Prime P. */
1062             size_t publKeyDataSize,            /*!< [in] pointer to public key size, in bytes: should be not great than Prime size. */
1063 
1064             CCFfcDhKeyValidMode_t validatMode, /*!< [in] enumerator ID defining the validation mode:
1065                                      CC_FFCDH_CHECK_FULL_MODE - full validation (sec. 5.6.2.3.1);
1066                                      CC_FFCDH_CHECK_PARTIAL_MODE - check pointers, sizes and range of values. */
1067             uint32_t *pTmpBuff)                 /*!< [in] temporary buffer of size not less Prime size. */
1068 {
1069         /* FUNCTION DECLARATIONS */
1070 
1071         /* The return error identifier */
1072         CCError_t err = CC_OK;
1073     uint32_t *pPrime;
1074     uint32_t *pPublKey32;
1075         size_t  primeSizeBytes;
1076         size_t  primeSizeWords, orderSizeWords;
1077         uint32_t  one;
1078         CCCommonCmpCounter_t cmp;
1079 
1080         CHECK_AND_RETURN_ERR_UPON_FIPS_ERROR();
1081 
1082 
1083         /* ............... check parameters validity ................... */
1084         /* ------------------------------------------------------------- */
1085 
1086         CHECK_AND_RETURN_ERROR(pDomain == NULL, CC_FFCDH_INVALID_DOMAIN_PTR_ERROR);
1087         CHECK_AND_RETURN_ERROR(pDomain->validTag != CC_FFC_DOMAIN_VALIDATION_TAG,
1088                            CC_FFCDH_INVALID_DOMAIN_DATA_ERROR);
1089         CHECK_AND_RETURN_ERROR((pPublKeyData == NULL) || (pTmpBuff == NULL),
1090                     CC_FFCDH_INVALID_PUBL_KEY_PTR_ERROR);
1091         CHECK_AND_RETURN_ERROR(publKeyDataSize == 0, CC_FFCDH_INVALID_PUBLIC_KEY_SIZE_ERROR);
1092 
1093         /* get FFC domain parameters */
1094         primeSizeWords = pDomain->modLenWords;
1095     orderSizeWords = pDomain->ordLenWords;
1096         primeSizeBytes = primeSizeWords*CC_32BIT_WORD_SIZE;
1097 
1098         pPrime = &pDomain->prime[0];
1099         pPublKey32 = pTmpBuff;
1100 
1101 
1102         /* check input enumerators */
1103         CHECK_AND_RETURN_ERROR(validatMode >= CC_FFCDH_KEY_VALIDAT_NUM_OFF_MODE,
1104                        CC_FFCDH_INVALID_VALIDAT_MODE_ERROR);
1105 
1106     /* convert pPublKeyData to LE words array */
1107         CHECK_ERROR(CC_CommonConvertMsbLsbBytesToLswMswWords(pPublKey32/*out32*/, primeSizeBytes,
1108                                      pPublKeyData/*in8*/, publKeyDataSize));
1109 
1110         /*----------------------------------------------------------------------*/
1111         /*   Public Key Validation: sec.5.6.2.3.1, step.1 (partial validation)  */
1112         /*----------------------------------------------------------------------*/
1113         /* preliminary check the key size */
1114 //        CHECK_AND_SET_ERROR(publKeyDataSize != ffcPrimeSize, CC_FFCDH_INVALID_PUBLIC_KEY_SIZE_ERROR);
1115 
1116     /* check public key value range [2,P-2]:  1 < publKey < P-1; */
1117         pPrime[0] -= 1; /*temporary set P = P-1*/
1118     cmp = CC_CommonCmpLsWordsUnsignedCounters(pPrime, primeSizeWords, pPublKey32, primeSizeWords);
1119     CHECK_AND_SET_ERROR(cmp != CC_COMMON_CmpCounter1GreaterThenCounter2, CC_FFCDH_INVALID_PUBLIC_KEY_VALUE_ERROR);
1120     pPrime[0] += 1; /*repair P */
1121     /* compare to 1 */
1122     one = 1;
1123     cmp = CC_CommonCmpLsWordsUnsignedCounters(pPublKey32, primeSizeWords, &one, 1);
1124     CHECK_AND_SET_ERROR(cmp != CC_COMMON_CmpCounter1GreaterThenCounter2,
1125                 CC_FFCDH_INVALID_PUBLIC_KEY_VALUE_ERROR);
1126 
1127 
1128         /*--------------------------------------------------------------------*/
1129         /*         For Full Validation perform step.2 of sec.5.6.2.3.1:       */
1130     /*               check, that 1 = (PublKey ^ FfcOrder) mod P.                   */
1131         /*--------------------------------------------------------------------*/
1132     if(validatMode == CC_FFCDH_KEY_VALIDAT_FULL_MODE) {
1133 
1134         err = PkiExecModExpLeW(
1135             pPublKey32,                       /*result - out*/
1136             pPublKey32,                       /*public key - in*/
1137             primeSizeWords,                   /*public key size - in*/
1138             pPrime,                           /*prime P - modulus*/
1139             primeSizeWords*CC_BITS_IN_32BIT_WORD, /*P size in bits*/
1140             &pDomain->order[0],  /* sub-group order Q*/
1141             orderSizeWords);                  /* Q size in words*/
1142 
1143         /* check error */
1144         if (err != CC_OK) {
1145             goto End;
1146         }
1147 
1148         cmp = CC_CommonCmpLsWordsUnsignedCounters(pPublKey32, primeSizeWords, &one, 1);
1149         CHECK_AND_SET_ERROR(cmp != CC_COMMON_CmpCounter1AndCounter2AreIdentical,
1150                     CC_FFCDH_INVALID_PUBLIC_KEY_VALUE_ERROR);
1151     }
1152 
1153 End:
1154 
1155     CC_PalMemSetZero((uint8_t*)pTmpBuff, primeSizeBytes);
1156 
1157     return err;
1158 
1159 } /* CC_FfcDhValidatePublKey */
1160 
1161 
1162 
1163 /*******************************************************************************************/
1164 /*!
1165 @brief The function checks and sets the FFC DH partner's public key into DH Context
1166 according to NIST SP 800-56A rev.2 sec.5.6.2.3.1 and checking mode:
1167 
1168 <ul><li> - if the key belongs to user's party, then the function returns an error, meaning
1169 that the user should use other function to import both public and private keys together;</li>.
1170 <li> - on "partial" mode - checks the pointers and high/low limits of key value;</li>
1171 <li> - on "full" mode - checks also that the the key belongs to the FFC subgroup; </li>
1172 <li> - sets the key data into DH Context according to party's role and key status. </li></ul>
1173 \note Before calling of this function, DH context should be initialized and Scheme and FFC Domain
1174 parameters are inserted by calling appropriate functions, else the function returns an error.
1175 @return CC_OK on success.
1176 @return A non-zero value on failure as defined cc_dh_error.h.
1177 */
CC_FfcDhValidateAndImportPublKey(CCFfcDhUserContext_t * pDhUserCtx,uint8_t * pPublKeyData,size_t publKeyDataSize,CCFfcDhKeyValidMode_t validatMode,CCFfcDhKeyStatus_t keyStatus)1178 CEXPORT_C CCError_t CC_FfcDhValidateAndImportPublKey(
1179                                 CCFfcDhUserContext_t *pDhUserCtx,  /*!< [in/out] pointer to DH FFC Context structure. */
1180                                 uint8_t *pPublKeyData,             /*!< [in] pointer to given DH FFC public key or Nonce in big endianness;
1181                                                                           it should be in range [2, P-2], where P is the Domain Prime. */
1182                                 size_t publKeyDataSize,            /*!< [in] public key size, in bytes: should be not great than Domain Prime size. */
1183                                 CCFfcDhKeyValidMode_t validatMode, /*!< [in] enumerator ID defining the validation mode:
1184                                                                            CC_FFCDH_CHECK_FULL_MODE - full validation (sec. 5.6.2.3.1);
1185                                                                            CC_FFCDH_CHECK_PARTIAL_MODE - check pointers, sizes and range of values. */
1186                                 CCFfcDhKeyStatus_t keyStatus       /*!< [in] enumerator, defining the key status according to its life time
1187                                                                           or purpose: static/ephemeral */
1188 )
1189 {
1190         /* FUNCTION DECLARATIONS */
1191 
1192         /* The return error identifier */
1193         CCError_t err = CC_OK;
1194         DhContext_t *pDhCtx; /* internal DH context */
1195         CCFfcDomain_t *pFfcDomain;
1196         uint32_t *pPublKey32, *pPublKeySizeBytes;
1197         uint32_t  primeSizeBytes, primeSizeWords, previousKeySize;
1198         uint32_t testBit = 0;
1199 
1200 
1201         CHECK_AND_RETURN_ERR_UPON_FIPS_ERROR();
1202 
1203         /* check contexts pointers and tags */
1204         CHECK_AND_RETURN_ERROR(pDhUserCtx == NULL, CC_FFCDH_INVALID_CONTEXT_PTR_ERROR);
1205         /* check that DhCtx is valid for user keys generation step: *
1206         *  DH Scheme and Domain are set.                           */
1207         CHECK_AND_SET_ERROR(FFCDH_CHECK_CTX_VALID_TAG_BITS(pDhUserCtx->validTag,
1208                    FFCDH_CTX_VALID_TAG_SCHEM_PARAM_SET), CC_FFCDH_CONTEXT_VALIDATION_TAG_ERROR);
1209 
1210         /* Get internal context structure */
1211         pDhCtx = (DhContext_t*)&pDhUserCtx->contextBuff;
1212         pFfcDomain = &pDhCtx->ffcDomain;
1213         /* check domain validation tag */
1214         CHECK_AND_SET_ERROR(pFfcDomain->validTag != CC_FFC_DOMAIN_VALIDATION_TAG,
1215                     CC_FFCDH_INVALID_DOMAIN_DATA_ERROR);
1216 
1217         /* get FFC domain parameters */
1218         primeSizeWords = pFfcDomain->modLenWords;
1219         primeSizeBytes = primeSizeWords*CC_32BIT_WORD_SIZE;
1220 
1221         CHECK_AND_SET_ERROR(pPublKeyData == NULL, CC_FFCDH_INVALID_ARGUMENT_POINTER_ERROR);
1222         /* check input enumerators */
1223         CHECK_AND_SET_ERROR(keyStatus >= CC_FFCDH_KEY_STATUS_NUM_OFF_MODE, CC_FFCDH_INVALID_KEY_STATUS_ERROR);
1224         CHECK_AND_SET_ERROR(validatMode >= CC_FFCDH_KEY_VALIDAT_NUM_OFF_MODE, CC_FFCDH_INVALID_VALIDAT_MODE_ERROR);
1225         /* preliminary check of public key size */
1226         CHECK_AND_SET_ERROR(publKeyDataSize == 0, CC_FFCDH_INVALID_PUBLIC_KEY_SIZE_ERROR);
1227 
1228         /* check that the key meets to scheme requirements and set the pointer to
1229          * the appropriate place in the context */
1230     if(keyStatus == CC_FFCDH_KEY_STATIC) {
1231         previousKeySize = pDhCtx->partnerStatPublKeySizeBytes; /*size of previous inserted key*/
1232         if(pDhCtx->schemeInfo.doPartnerStatKey == 1) {
1233             pPublKey32 = pDhCtx->partnerStatPublKey;
1234             pPublKeySizeBytes = &pDhCtx->partnerStatPublKeySizeBytes;
1235             testBit = FFCDH_CTX_VALID_TAG_PARTN_STAT_KEY_BIT;
1236 
1237         } else {
1238             err = CC_FFCDH_THE_KEY_IS_NOT_REQUIRED_ERROR;
1239             goto End;
1240         }
1241     } else if(keyStatus == CC_FFCDH_KEY_EPHEMER) {
1242         previousKeySize = pDhCtx->partnerEphemPublKeySizeBytes; /*size of previous inserted key*/
1243         if(pDhCtx->schemeInfo.doPartnerEphemKey == 1) {
1244             pPublKey32 = pDhCtx->partnerEphemPublKey;
1245             pPublKeySizeBytes = &pDhCtx->partnerEphemPublKeySizeBytes;
1246             testBit = FFCDH_CTX_VALID_TAG_PARTN_EPHEM_KEY_BIT;
1247         } else {
1248             err = CC_FFCDH_THE_KEY_IS_NOT_REQUIRED_ERROR;
1249             goto End;
1250         }
1251     }
1252 
1253     /* check that other key wasn't inserted previously on this place */
1254         CHECK_AND_SET_ERROR(previousKeySize != 0, CC_FFCDH_ILLEGAL_TRY_REWRITE_PARAM_ERROR);
1255 
1256        /* Check Public Key Data validity */
1257         err = CC_FfcDhValidatePublKey(
1258                 &pDhCtx->ffcDomain,
1259                 pPublKeyData,
1260                         publKeyDataSize, /*size with leading zeros*/
1261                         validatMode,
1262                         (uint32_t*)&pDhCtx->tmpBuff);
1263 
1264         if (err != CC_OK) {
1265                 goto End;
1266         }
1267 
1268         /* copy the public key into context as LE words array. */
1269         CHECK_ERROR(CC_CommonConvertMsbLsbBytesToLswMswWords(pPublKey32/*out32*/, primeSizeBytes,
1270                                      pPublKeyData/*in8*/, publKeyDataSize));
1271 
1272         *pPublKeySizeBytes = primeSizeBytes;
1273 
1274         /* set valid tag bit according to key status */
1275         pDhCtx->validTag |= testBit;
1276 
1277 End:
1278         if (err != CC_OK) {
1279                 /* delete secure sensitive data */
1280                 CC_PalMemSetZero((uint8_t*)pDhUserCtx, sizeof(CCFfcDhUserContext_t));
1281     }
1282 
1283         return err;
1284 }
1285 
1286 /*******************************************************************************************/
1287 /*!
1288 @brief The function checks and sets the FFC DH user's private/public key pair into DH Context
1289 according to NIST SP 800-56A rev.2 sec.5.6.2.3.1 and checking mode:
1290 
1291 <ul><li> - if the key belongs to partner's party, then the function returns an error, meaning
1292 that the user should use other function to import only public key;</li>.
1293 <li> - on "partial" mode - checks the pointers and high/low limits of key value;</li>
1294 <li> - on "full" mode - checks also that the the public key meets to private key; </li>
1295 <li> - sets the key data into DH Context according to party's role and key status. </li></ul>
1296 \note Before calling of this function, DH context should be initialized and Scheme and FFC Domain
1297 parameters are inserted by calling appropriate functions, else the function returns an error.
1298 @return CC_OK on success.
1299 @return A non-zero value on failure as defined cc_dh_error.h.
1300 */
CC_FfcDhValidateAndImportKeyPair(CCFfcDhUserContext_t * pDhUserCtx,uint8_t * pPrivKeyData,size_t privKeyDataSize,uint8_t * pPublKeyData,size_t publKeyDataSize,CCFfcDhKeyValidMode_t validatMode,CCFfcDhKeyStatus_t keyStatus)1301 CEXPORT_C CCError_t CC_FfcDhValidateAndImportKeyPair(
1302                                 CCFfcDhUserContext_t *pDhUserCtx,  /*!< [in/out] pointer to DH FFC Context structure. */
1303                                 uint8_t *pPrivKeyData,             /*!< [in] pointer to given DH FFC private key in big endianness;
1304                                                                              it should be in range [1, n-1], where n is the Domain generator order. */
1305                                 size_t privKeyDataSize,            /*!< [in] private key size, in bytes: should be equaled Domain
1306                                                                              generator order size. */
1307                                 uint8_t *pPublKeyData,             /*!< [in] pointer to given DH FFC public key in big endianness;
1308                                                                           it should be in range [2, P-2], where P is the Domain Prime. */
1309                                 size_t publKeyDataSize,            /*!< [in] public key size, in bytes: should be equaled to Domain Prime size,
1310                                                                              including leading zeros. */
1311                                 CCFfcDhKeyValidMode_t validatMode, /*!< [in] enumerator ID defining the validation mode:
1312                                                                              CC_FFCDH_CHECK_FULL_MODE - full validation (sec. 5.6.2.3.1);
1313                                                                              CC_FFCDH_CHECK_PARTIAL_MODE - check pointers, sizes and range of values. */
1314                                 CCFfcDhKeyStatus_t keyStatus       /*!< [in] enumerator, defining the key status according to its life time
1315                                                                              or purpose: static/ephemeral/nonce */
1316 )
1317 {
1318         /* FUNCTION DECLARATIONS */
1319 
1320         /* The return error identifier */
1321         CCError_t err = CC_OK;
1322         DhContext_t *pDhCtx; /* internal DH context */
1323         CCFfcDomain_t *pFfcDomain;
1324         uint32_t *pPublKey32, *pPrivKey32;
1325 //        uint16_t   *pPublKey32Size;
1326         uint32_t  *pPrime, *pOrder, one = 0;
1327         size_t  primeSizeBytes, orderSizeBytes;
1328         size_t  primeSizeWords, orderSizeWords;
1329         uint32_t  testBit;
1330         uint32_t  *pPrivKeySize, *pPublKeySize;
1331 //        uint8_t  *pBaseAddr; /* start address for offsets counting */
1332 //        CCFfcDhCtxPublKeys_t *pPublKey32s;
1333         CCCommonCmpCounter_t cmp;
1334 //        bool isKeyRequested;
1335         uint32_t *pTmpBuff; /* used size = Prime size */
1336 
1337 
1338         CHECK_AND_RETURN_ERR_UPON_FIPS_ERROR();
1339 
1340         /* check contexts pointers and tags */
1341         CHECK_AND_RETURN_ERROR(pDhUserCtx == NULL, CC_FFCDH_INVALID_CONTEXT_PTR_ERROR);
1342         /* check that DhCtx is valid for user keys generation step: *
1343         *  DH Scheme and Domain are set.                           */
1344         CHECK_AND_SET_ERROR(FFCDH_CHECK_CTX_VALID_TAG_BITS(pDhUserCtx->validTag,
1345                 FFCDH_CTX_VALID_TAG_DOMAIN_SET), CC_FFCDH_CONTEXT_VALIDATION_TAG_ERROR );
1346 
1347         /* preliminary check of private/public key pointers and sizes */
1348         CHECK_AND_SET_ERROR(pPrivKeyData == NULL, CC_FFCDH_INVALID_ARGUMENT_POINTER_ERROR);
1349         CHECK_AND_SET_ERROR(pPublKeyData == NULL, CC_FFCDH_INVALID_ARGUMENT_POINTER_ERROR);
1350         CHECK_AND_SET_ERROR(privKeyDataSize == 0, CC_FFCDH_INVALID_PRIVATE_KEY_SIZE_ERROR);
1351         CHECK_AND_SET_ERROR(publKeyDataSize == 0, CC_FFCDH_INVALID_PUBLIC_KEY_SIZE_ERROR);
1352 
1353         /* check input enumerators */
1354         CHECK_AND_SET_ERROR(keyStatus >= CC_FFCDH_KEY_STATUS_NUM_OFF_MODE, CC_FFCDH_INVALID_KEY_STATUS_ERROR);
1355         CHECK_AND_SET_ERROR(validatMode >= CC_FFCDH_KEY_VALIDAT_NUM_OFF_MODE, CC_FFCDH_INVALID_VALIDAT_MODE_ERROR);
1356 
1357         /* Get internal context structure */
1358         pDhCtx = (DhContext_t*)&pDhUserCtx->contextBuff;
1359         pFfcDomain = &pDhCtx->ffcDomain;
1360         /* check domain validation tag */
1361         CHECK_AND_SET_ERROR(pFfcDomain->validTag != CC_FFC_DOMAIN_VALIDATION_TAG, CC_FFCDH_INVALID_DOMAIN_DATA_ERROR);
1362 
1363         /* get FFC domain parameters */
1364         primeSizeWords = pFfcDomain->modLenWords;
1365         orderSizeWords = pFfcDomain->ordLenWords;
1366         primeSizeBytes = primeSizeWords*CC_32BIT_WORD_SIZE;
1367         orderSizeBytes = orderSizeWords*CC_32BIT_WORD_SIZE;
1368 
1369         pPrime = &pDhCtx->ffcDomain.prime[0]; /* Prime p */
1370         pOrder = &pDhCtx->ffcDomain.order[0]; /* Order q */
1371         pTmpBuff = &pDhCtx->tmpBuff.TempBuff[0]; /* used size = Prime size */
1372 
1373         /* set base address for offsets counting */
1374 //        pBaseAddr = &pDhCtx->extendDataBuffer[0];
1375 
1376         /* check that the key meets to scheme requirements and set the pointers to
1377          * appropriate place in the context */
1378     if(keyStatus == CC_FFCDH_KEY_STATIC) {
1379         if(pDhCtx->schemeInfo.doUserStatKey == 1) {
1380             pPrivKey32 = &pDhCtx->statPrivKey[0];
1381             pPublKey32 = &pDhCtx->userStatPublKey[0];
1382             testBit = FFCDH_CTX_VALID_TAG_USER_STAT_KEY_BIT;
1383             pPrivKeySize = &pDhCtx->statPrivKeySizeBytes;
1384             pPublKeySize = &pDhCtx->userStatPublKeySizeBytes;
1385         } else {
1386             err = CC_FFCDH_INVALID_KEY_STATUS_ERROR;
1387             goto End;
1388         }
1389     } else if(keyStatus == CC_FFCDH_KEY_EPHEMER) {
1390         if(pDhCtx->schemeInfo.doUserEphemKey == 1) {
1391             pPrivKey32 = &pDhCtx->ephemPrivKey[0];
1392             pPublKey32 = &pDhCtx->userEphemPublKey[0];
1393             testBit = FFCDH_CTX_VALID_TAG_USER_EPHEM_KEY_BIT;
1394             pPrivKeySize = &pDhCtx->ephemPrivKeySizeBytes;
1395             pPublKeySize = &pDhCtx->userEphemPublKeySizeBytes;
1396         } else {
1397             err = CC_FFCDH_INVALID_KEY_STATUS_ERROR;
1398             goto End;
1399         }
1400     }
1401 
1402     /* check that the key is not inserted previously */
1403     CHECK_AND_SET_ERROR((*pPrivKeySize != 0) || (*pPublKeySize != 0),
1404                 CC_FFCDH_ILLEGAL_TRY_REWRITE_PARAM_ERROR);
1405 
1406     /* convert the keys to LE words array and set into Context */
1407         CHECK_ERROR(CC_CommonConvertMsbLsbBytesToLswMswWords(pPublKey32/*out32*/, primeSizeBytes,
1408                                      pPublKeyData/*in8*/, publKeyDataSize));
1409         CHECK_ERROR(CC_CommonConvertMsbLsbBytesToLswMswWords(pPrivKey32/*out32*/, orderSizeBytes,
1410                                      pPrivKeyData/*in8*/, privKeyDataSize));
1411 
1412     /* check private key value range [1,q-1]:  1 <= privlKey <= q-1; */
1413     cmp = CC_CommonCmpLsWordsUnsignedCounters(pOrder, orderSizeWords, pPrivKey32, orderSizeWords);
1414     CHECK_AND_SET_ERROR(cmp != CC_COMMON_CmpCounter1GreaterThenCounter2, CC_FFCDH_INVALID_PRIVATE_KEY_VALUE_ERROR);
1415     one = 0;
1416     cmp = CC_CommonCmpLsWordsUnsignedCounters(pPrivKey32, orderSizeWords, &one, 1);
1417     CHECK_AND_SET_ERROR(cmp != CC_COMMON_CmpCounter1GreaterThenCounter2, CC_FFCDH_INVALID_PRIVATE_KEY_VALUE_ERROR);
1418 
1419     /* check public key value range [2,p-2]:  1 < privlKey < p-1; */
1420     pPrime[0] -= 1;
1421     cmp = CC_CommonCmpLsWordsUnsignedCounters(pPrime, primeSizeWords, pPublKey32, primeSizeWords);
1422     CHECK_AND_SET_ERROR(cmp != CC_COMMON_CmpCounter1GreaterThenCounter2, CC_FFCDH_INVALID_PUBLIC_KEY_VALUE_ERROR);
1423     pPrime[0] += 1; /*reset p*/
1424     one = 1;
1425     cmp = CC_CommonCmpLsWordsUnsignedCounters(pPublKey32, primeSizeWords, &one, 1);
1426     CHECK_AND_SET_ERROR(cmp != CC_COMMON_CmpCounter1GreaterThenCounter2, CC_FFCDH_INVALID_PUBLIC_KEY_VALUE_ERROR);
1427 
1428 
1429         /* copy private and public key data into context and set leading zeros */
1430 //        CC_PalMemCopy(pPrivKey32 + (ffcOrderSize - privKeyDataSize), pPrivKeyData, privKeyDataSize);
1431 //        CC_PalMemSet(pPrivKey32, 0, (ffcOrderSize - privKeyDataSize)); /*zeroing leading zeros*/
1432 //        CC_PalMemCopy(pPublKey32 + (ffcPrimeSize - publKeyDataSize), pPublKeyData, publKeyDataSize);
1433 //        CC_PalMemSet(pPublKey32, 0, (ffcPrimeSize - publKeyDataSize)); /*zeroing leading zeros*/
1434 
1435 
1436         /* Full check of Public Key Data validity by recomputing the public key from private:
1437          * (SP 56A rev.2, sec.5.6.2.1.4).  */
1438     if(validatMode == CC_FFCDH_KEY_VALIDAT_FULL_MODE) {
1439         /* calculate PublKey as LE words array */
1440         err = PkiExecModExpLeW(
1441             pTmpBuff,               /*exp.result - out*/
1442             &pFfcDomain->genG[0],   /*FFC generator - in*/
1443             primeSizeWords,         /*generator size - in*/
1444             pPrime,                 /*prime P - modulus*/
1445             primeSizeWords*CC_BITS_IN_32BIT_WORD, /*P size in bits*/
1446             pPrivKey32,             /* private key */
1447             orderSizeWords);        /* private key full size in bytes */
1448 
1449         /* check error */
1450         if (err != CC_OK) {
1451             goto End;
1452         }
1453 
1454         /* check that recalculated publ. key is equaled to input key. */
1455         cmp = CC_CommonCmpLsWordsUnsignedCounters(pTmpBuff, primeSizeWords, pPublKey32, primeSizeWords);
1456         CHECK_AND_SET_ERROR(cmp != CC_COMMON_CmpCounter1AndCounter2AreIdentical, CC_FFCDH_INVALID_PUBLIC_KEY_VALUE_ERROR);
1457     }
1458 
1459 
1460         /* set valid tag bit according to key status */
1461     pDhCtx->validTag |= testBit;
1462 
1463 End:
1464         if (err != CC_OK) {
1465                 /* delete secure sensitive data */
1466                 CC_PalMemSetZero((uint8_t*)pDhUserCtx, sizeof(CCFfcDhUserContext_t));
1467     }
1468 
1469         return err;
1470 }
1471 
1472 
1473 /*******************************************************************************************/
1474 /*!
1475 @brief This function generates random Nonce, used in appropriate DH Schemes (NIST SP 56A rev.2 sec.5.9, 6).
1476 <li> The function generates random vector of given size, sets it into DH context according. </li>
1477 \note Before calling of this function, DH context should be initialized and Scheme parameters and
1478 DH Domain are inserted by calling appropriate functions, else the function returns an error.
1479 \note The Nonce should be generated and the function called only if it is required by DH scheme, and
1480 the Nonce is not inserted previously, else the function returns an error.
1481 \note The function is used when the user not generates an ephemeral key, but requires key confirmation and
1482 therefore Nonce generation.
1483 @return CC_OK on success.
1484 @return A non-zero value on failure as defined cc_dh_error.h.
1485 */
CC_FfcDhGenerateRandomNonce(CCFfcDhUserContext_t * pDhUserCtx,CCRndContext_t * pRndContext)1486 CEXPORT_C CCError_t CC_FfcDhGenerateRandomNonce(
1487                                 CCFfcDhUserContext_t *pDhUserCtx, /*!< [in/out] pointer to DH FFC Context structure. */
1488                                 CCRndContext_t *pRndContext)      /*!< [in] random generation function context. */
1489 {
1490     CCError_t err = CC_OK;
1491     DhContext_t *pDhCtx;
1492 //  uint8_t *pNonce;
1493 
1494         /* RND state and function pointers */
1495         CCRndState_t   *pRndState;
1496         CCRndGenerateVectWorkFunc_t RndGenerateVectFunc;
1497 
1498 
1499         CHECK_AND_RETURN_ERR_UPON_FIPS_ERROR();
1500 
1501         /* check context pointer and tag */
1502         CHECK_AND_RETURN_ERROR(pDhUserCtx == NULL, CC_FFCDH_INVALID_CONTEXT_PTR_ERROR);
1503         /* check that DhCtx is valid for user keys generation step: */
1504         CHECK_AND_SET_ERROR(pDhUserCtx->validTag != FFCDH_CTX_VALID_TAG_DOMAIN_SET, CC_FFCDH_CONTEXT_VALIDATION_TAG_ERROR);
1505 
1506         /* Get internal context structure */
1507         pDhCtx = (DhContext_t*)&pDhUserCtx->contextBuff;
1508 
1509         /* check that Nonce is required according to DH Scheme */
1510         CHECK_AND_SET_ERROR(pDhCtx->schemeInfo.doUserNonce == 0, CC_FFCDH_NONCE_IS_NOT_REQUIRED_ERROR);
1511 
1512 //       /* check userParty enumerator. */
1513 //        CHECK_AND_SET_ERROR(userParty >= CC_FFCDH_PARTY_NUM_OFF_MODE, CC_FFCDH_INVALID_USER_PARTY_ID_ERROR);
1514 //
1515         /* Check RND context pointer. Note: full check of RND context will be  *
1516         *  performed in the called CC_RndGenerateVectorInRange function */
1517     CHECK_AND_SET_ERROR(pRndContext == NULL, CC_RND_CONTEXT_PTR_INVALID_ERROR);
1518         RndGenerateVectFunc = pRndContext->rndGenerateVectFunc;
1519         CHECK_AND_SET_ERROR(RndGenerateVectFunc == NULL, CC_RND_GEN_VECTOR_FUNC_ERROR);
1520         pRndState = (CCRndState_t*)&(pRndContext->rndState);
1521 
1522           /* check that this Nonce is not inserted previously */
1523         CHECK_AND_SET_ERROR(pDhCtx->userNonceSizeBytes != 0, CC_FFCDH_ILLEGAL_TRY_REWRITE_PARAM_ERROR);
1524 
1525         /* generate random Nonce and set it into Context. Note: Nonce is not an integer. */
1526         CHECK_ERROR(RndGenerateVectFunc(pRndState, &pDhCtx->userNonce[0], pDhCtx->nonceSize));
1527 
1528 End:
1529     if (err != CC_OK) {
1530         /* delete secure sensitive data */
1531         CC_PalMemSetZero((uint8_t*)pDhUserCtx, sizeof(CCFfcDhUserContext_t));
1532     }
1533 
1534     return err;
1535 }
1536 
1537 
1538 /*******************************************************************************************/
1539 /*!
1540 @brief This function formats the UserInfo according to the user role (PartyU or PartyV) and NIST SP 56A rev.2,
1541        sec. 5.8.1.2, 5.8.1.2.1.
1542 
1543 <ul><li>  Input and previously inserted data is concatenated as defined in the CCFfcDhPartyInfo_t structure and
1544  sets it into the Context:  UserInfo = UserId||UserStatPublKey||UserStatPublKey||UserNonce}{||UserOtherData}, where: </li>
1545 <li> - UserInfo and each its sub-entry are formatted as length (Len) and then appropriate data: Len||Data,
1546 where each length is a 2-bytes big endianness counter; </li>
1547 <li> - If any sub-entry is not used in chosen DH Scheme, than its lengths should be set 0 and the data is empty. </li>
1548 <li> - total size of PartyInfo, including said lengths, should be not great, than the size of CCDhPartyInfo_t. </li></ul>
1549 \note Before calling of this function the User should initialize DH Context, insert FFC Domain, DH Scheme parameters and
1550 all his Private/Public Keys (or Nonce) using appropriate CC functions.
1551 \note The output from this function will be exported to the other party of the Agreement and vice versa, UserInfo, received
1552 from other party, will be used as input to DhCtxSetSchemeData() function.
1553 
1554 @return CC_OK on success.
1555 @return A non-zero value on failure as defined cc_dh_error.h.
1556 */
CC_FfcDhCreateUserInfo(CCFfcDhUserContext_t * pDhUserCtx,uint8_t * pUserOtherData,size_t userOtherDataSize,uint8_t * pUserConfirmText,size_t userConfirmTextSize,CCFfcDhPartyInfo_t * pUserInfo,size_t * pUserInfoSize)1557 CEXPORT_C CCError_t CC_FfcDhCreateUserInfo(
1558                         CCFfcDhUserContext_t *pDhUserCtx, /*!< [in/out] pointer to context structure, containing all data,
1559                                                                used in DH Key Agreement Scheme. */
1560                         uint8_t *pUserOtherData,          /*!< [in] optional, pointer to other data, which the user will
1561                                                                     insert in addition to its ID, keys and Nonce. */
1562                         size_t userOtherDataSize,         /*!< [in] optional, size of additional data (in bytes), which the
1563                                                                     user will include into the UserInfo. */
1564                         uint8_t *pUserConfirmText,        /*!< [in] optional, pointer to confirmation Text of the User. */
1565                         size_t  userConfirmTextSize,      /*!< [in] optional size of Text data of partyU, in bytes. */
1566                         CCFfcDhPartyInfo_t *pUserInfo,    /*!< [out] pointer to the concatenated UserInfo (i.e. PartyU or PartyV Info). */
1567                         size_t *pUserInfoSize             /*!< [in/out] pointer to the size of UserInfo, in bytes:
1568                                                                 in -  given buffer size (should be not less than CC_FFCDH_MAX_SIZE_OF_OTHER_INFO_ENTRY;
1569                                                                 out - actual size of UserInfo, including length counters */
1570 )
1571 {
1572     /* FUNCTION DECLARATIONS */
1573 
1574         CCError_t err = CC_OK; /* return error identifier */
1575         DhContext_t  *pDhCtx;
1576         /* actual size of UserInfo data */
1577         uint8_t *pTmp; /* temp pointer */
1578         uint8_t *pBaseAddr;
1579         uint32_t fullLen = 0;
1580 
1581         CHECK_AND_RETURN_ERR_UPON_FIPS_ERROR();
1582 
1583         /* check contexts pointers and tags */
1584         if(pDhUserCtx == NULL) {
1585             return CC_FFCDH_INVALID_CONTEXT_PTR_ERROR;
1586         }
1587         /* check that DhCtx is valid for user keys generation step: *
1588         *  DH Scheme, Domain and Keys are set.                      */
1589         CHECK_AND_SET_ERROR(pDhUserCtx->validTag != FFCDH_CTX_VALID_TAG_ALL_KEYS_SET, CC_FFCDH_CONTEXT_VALIDATION_TAG_ERROR);
1590         /*  check the mandatory data pointers  */
1591         CHECK_AND_SET_ERROR(pUserInfo == NULL || pUserInfoSize == NULL, CC_FFCDH_INVALID_ARGUMENT_POINTER_ERROR);
1592     /* check the optional data pointers and sizes */
1593         CHECK_AND_SET_ERROR((pUserOtherData == NULL) != (userOtherDataSize == 0), CC_FFCDH_OPTIONAL_DATA_ERROR);
1594         CHECK_AND_SET_ERROR((pUserConfirmText == NULL) != (userConfirmTextSize == 0), CC_FFCDH_OPTIONAL_DATA_ERROR);
1595 
1596     /* check sizes */
1597         CHECK_AND_SET_ERROR(userOtherDataSize > CC_FFCDH_MAX_SIZE_OF_PARTY_INFO_OTHER_DATA_BYTES, CC_FFCDH_PARTY_INFO_SUB_ENTRY_SIZE_ERROR);
1598         CHECK_AND_SET_ERROR(userConfirmTextSize > CC_FFCDH_MAX_SIZE_OF_CONFIRM_TEXT_DATA_BYTES, CC_FFCDH_PARTY_INFO_SUB_ENTRY_SIZE_ERROR);
1599 
1600         /* Get internal context structure */
1601     pDhCtx = (DhContext_t*)&pDhUserCtx->contextBuff;
1602 
1603     /* address of extended data buffer */
1604     pBaseAddr = &pDhCtx->extendDataBuffer[0];
1605 
1606     /* set temp pointer and save userOtherData in the Context */
1607     pTmp = pBaseAddr + pDhCtx->dataOffsets.userIdOffset;
1608 
1609     /* concatenate generated previously user data into context extendDataBuffer */
1610     FfcDhWriteBufferBeToBe(&pTmp, pDhCtx->userId, pDhCtx->userIdSizeBytes, &fullLen);
1611     FfcDhWriteBufferLeToBe(&pTmp, pDhCtx->userStatPublKey, pDhCtx->userStatPublKeySizeBytes, &fullLen);
1612     FfcDhWriteBufferLeToBe(&pTmp, pDhCtx->userEphemPublKey, pDhCtx->userEphemPublKeySizeBytes, &fullLen);
1613     FfcDhWriteBufferBeToBe(&pTmp, pDhCtx->userNonce, pDhCtx->userNonceSizeBytes, &fullLen);
1614     FfcDhWriteBufferBeToBe(&pTmp, pUserOtherData, userOtherDataSize, &fullLen);
1615 
1616 
1617     CHECK_AND_SET_ERROR(fullLen > *pUserInfoSize, CC_FFCDH_LOW_OUTPUT_BUFF_SIZE_ERROR);
1618 
1619     /* output concatenated UserInfo data */
1620     pDhCtx->currInsertedDataSize = fullLen;
1621     pDhCtx->dataOffsets.userInfoSize = fullLen;
1622     CC_PalMemCopy(pUserInfo, pBaseAddr + pDhCtx->dataOffsets.userIdOffset, fullLen);
1623     /* concatenate user's Confirmation Text */
1624     pTmp = (uint8_t*)&pUserInfo + fullLen;
1625     FfcDhWriteBufferBeToBe(&pTmp, pUserConfirmText, userConfirmTextSize, &fullLen);
1626     *pUserInfoSize = fullLen;
1627 
1628     /* update validation tag */
1629     pDhUserCtx->validTag |= FFCDH_CTX_VALID_TAG_USER_INFO_BIT;
1630 
1631 
1632 End:
1633     if(err != CC_OK) {
1634         CC_PalMemSetZero((uint8_t*)pDhUserCtx, sizeof(CCFfcDhUserContext_t));
1635     }
1636 
1637     return err;
1638 
1639 }
1640 
1641 
FfcDhValidatePartnInfoPublKey(DhContext_t * pDhCtx,CCFfcDhKeyValidMode_t keyValidatMode,uint8_t ** ppCtxKey,uint8_t ** ppInKey)1642 static CCError_t FfcDhValidatePartnInfoPublKey(
1643                 DhContext_t  *pDhCtx,                 /*!< [in/out] pointer to internal DH Context structure. */
1644                 CCFfcDhKeyValidMode_t keyValidatMode, /*!< [in] enum. key validation mode */
1645                 uint8_t **ppCtxKey,                   /*!< [in/out] pointer to pointer to context publ.key buffer */
1646                 uint8_t **ppInKey)                    /*!< [in/out] pointer to pointer to partnerInfo publ.keydata */
1647 {
1648         CCError_t err = CC_OK; /* return error identifier */
1649     uint32_t size1;  /*key size in Context*/
1650     uint32_t size2;  /*size received*/
1651     uint8_t *pKey = *ppCtxKey;
1652 
1653 
1654     /* get key sizes from Context and from the PartnerInfo */
1655     size1 = FFCDH_GET_LENGTH(*ppCtxKey); /*in ctx*/
1656     size2 = FFCDH_GET_LENGTH(*ppInKey);  /*in partner Info*/
1657 
1658     /* if the key was inserted previously, compare the data, else check and import the key */
1659     if(size1 == pDhCtx->ffcDomain.modLenWords*CC_32BIT_WORD_SIZE) {
1660         CHECK_AND_SET_ERROR(size1 != size2,  CC_FFCDH_PARTN_INFO_PARSING_SIZE_ERROR);
1661         CHECK_AND_SET_ERROR(CC_PalMemCmp(*ppCtxKey, *ppInKey, size1), CC_FFCDH_PARTN_INFO_PARSING_DATA_ERROR);
1662 
1663     } else if(size1 == 0){
1664         /* check and import the partner's key */
1665         err = CC_FfcDhValidatePublKey(
1666             &pDhCtx->ffcDomain,
1667             *ppInKey,  size2, /*received PublKey*/
1668             keyValidatMode,
1669             &pDhCtx->tmpBuff.TempBuff[0]);
1670         CHECK_ERROR(err);
1671 
1672         /* copy the key into Context and set size */
1673         FfcDhWriteBufferBeToBe(&pKey, *ppInKey, size2, &pDhCtx->currInsertedDataSize);
1674     } else {
1675         err = CC_FFCDH_PARTN_INFO_PARSING_DATA_ERROR;
1676     }
1677 
1678     /* promote pointers to next Info entries */
1679     *ppCtxKey += size1;
1680     *ppInKey  += size2;
1681 
1682 End:
1683     return err;
1684 
1685 }
1686 
1687 
1688 /*******************************************************************************************/
1689 /*!
1690 @brief This function implements FFC DH primitive according to section 5.7.1.1 of NIST SP 56A rev.2 standard.
1691        The function computes and concatenates the shared secret values according to DH Scheme:
1692         - on all schemes:  SharedSecretVal = partnerPublKey1 ^ userPrivKey1 modulo Prime;
1693         - on hybrid schemes: SharedSecretVal2 = partnerPublKey2 ^ userPrivKey2 modulo Prime, and then
1694           concatenates them:  SharedSecretVal = SharedSecretVal || SharedSecretVal2;
1695 
1696 \note Before calling of this function the user should obtain assurance of public and private keys, involved in the key
1697 agreement, using one of methods, described in section 5.6.2 of above named standard.
1698 \note For assurance of keys validity the user can use appropriate APIs for generating or building and validation,
1699 of keys, described in CC_dh.h file.
1700 \note The function intended for internal using in Keying Material derivation inside CC DH functions.
1701 Assumed, that all required data is inserted properly in the DH Context.
1702 @return CC_OK on success.
1703 @return A non-zero value on failure as defined in cc_dh_error.h or cc_rnd_error.h.
1704 */
FfcDhCalcSharedSecretVal(DhContext_t * pDhCtx)1705 static CCError_t FfcDhCalcSharedSecretVal(DhContext_t *pDhCtx) /*!< [in/out] pointer to context structure, containing all data,
1706                                                                        and buffers, used in DH Key Agreement Scheme. */
1707 
1708 {
1709     CCError_t err = CC_OK;
1710     CCFfcDomain_t *pFfcDomain = &pDhCtx->ffcDomain;
1711     FfcDhSchemeInfo_t *schemeInfo = &pDhCtx->schemeInfo;
1712 //  FfcDhSchemeDataOffsets_t *pDataOffsets = &pDhCtx->dataOffsets;
1713     uint32_t *userPrivKey1 = NULL, *partnPublKey1 = NULL;
1714     uint32_t *userPrivKey2 = NULL, *partnPublKey2 = NULL;
1715     uint8_t *pSharedSecretVal1 = NULL, *pSharedSecretVal2 = NULL;
1716 //  uint32_t publKeyDataSize = 0; //, privKeySize;
1717     uint32_t primeSizeBytes, orderSizeBytes;
1718     uint32_t primeSizeWords, orderSizeWords;
1719     uint32_t *pZ; /* aligned pointer to Shared Secret */
1720 
1721         /* get FFC domain parameters */
1722         primeSizeWords = pFfcDomain->modLenWords;
1723     orderSizeWords = pFfcDomain->ordLenWords;
1724         primeSizeBytes = pFfcDomain->modLenWords*CC_32BIT_WORD_SIZE;
1725     orderSizeBytes = pFfcDomain->ordLenWords*CC_32BIT_WORD_SIZE;
1726 
1727     /* set pointers to shared secret value according to user and partner roles (U,V). */
1728     if(pDhCtx->userParty == CC_FFCDH_PARTY_U) {
1729         pSharedSecretVal1 = &pDhCtx->extendDataBuffer[0] + CC_FFCDH_KDF_COUNTER_SIZE_IN_BYTES;
1730         pSharedSecretVal2 = pSharedSecretVal1 + primeSizeBytes;
1731     } else if(pDhCtx->userParty == CC_FFCDH_PARTY_V){
1732         pSharedSecretVal2 = &pDhCtx->extendDataBuffer[0] + CC_FFCDH_KDF_COUNTER_SIZE_IN_BYTES;
1733         pSharedSecretVal1 = pSharedSecretVal2 + primeSizeBytes;
1734     }
1735 
1736     /* set first pointers to appropriate keys for all DH Schemes */
1737     if(schemeInfo->doUserStatKey) {
1738         userPrivKey1 = &pDhCtx->statPrivKey[0];
1739         pDhCtx->statPrivKeySizeBytes = orderSizeBytes;
1740     } else {
1741         userPrivKey1 = &pDhCtx->ephemPrivKey[0];
1742         pDhCtx->ephemPrivKeySizeBytes = orderSizeBytes;
1743     }
1744 
1745     if(schemeInfo->doPartnerStatKey) {
1746         partnPublKey1 = &pDhCtx->partnerStatPublKey[0];
1747         pDhCtx->partnerStatPublKeySizeBytes = primeSizeBytes;
1748     } else {
1749         partnPublKey1 = &pDhCtx->partnerEphemPublKey[0];
1750         pDhCtx->partnerEphemPublKeySizeBytes = primeSizeBytes;
1751     }
1752 
1753 //  publKeyDataSize = primeSizeBytes;
1754     /* align pointer to address */
1755     pZ = (uint32_t*)((uint32_t)pSharedSecretVal1 & (~(uint32_t)3));
1756 // !!!  pDhCtx-> ???
1757 
1758     /* calculate first shared secret */
1759     err = PkiExecModExpLeW(
1760         pZ,              /*exp.result - out*/
1761         partnPublKey1,   /*public key - in*/
1762         primeSizeWords,  /*public key size - in*/
1763         &pDhCtx->ffcDomain.prime[0], /*prime P - modulus*/
1764         primeSizeWords*CC_BITS_IN_32BIT_WORD,  /*P size in bits*/
1765         userPrivKey1,    /* sub-group order Q*/
1766         orderSizeWords); /* Q size in words*/
1767 
1768     /* check error */
1769     if (err != CC_OK) {
1770         goto End;
1771     }
1772     /* convert Z to BE bytes */
1773     CC_CommonInPlaceConvertBytesWordsAndArrayEndianness(pZ, primeSizeWords);
1774 
1775     /* calculation of second shared secret, if needed */
1776     if(pDhCtx->dhSchemeId == CC_FFCDH_SCHEM_HYBRID1 ||
1777        pDhCtx->dhSchemeId == CC_FFCDH_SCHEM_HYBRID_ONE_FLOW) {
1778 
1779         /* set second pointers to appropriate keys for all DH Schemes */
1780         if(schemeInfo->doUserEphemKey) {
1781             userPrivKey2 = &pDhCtx->ephemPrivKey[0];
1782             pDhCtx->ephemPrivKeySizeBytes = orderSizeBytes;
1783         } else {
1784             userPrivKey2 = &pDhCtx->statPrivKey[0];
1785             pDhCtx->statPrivKeySizeBytes = orderSizeBytes;
1786         }
1787 
1788         if(schemeInfo->doPartnerEphemKey) {
1789             partnPublKey2 = &pDhCtx->partnerEphemPublKey[0];
1790             pDhCtx->partnerEphemPublKeySizeBytes = primeSizeBytes;
1791         } else  {
1792             partnPublKey2 = &pDhCtx->partnerStatPublKey[0];
1793             pDhCtx->partnerStatPublKeySizeBytes = primeSizeBytes;
1794         }
1795 
1796         /* calculate second shared secret */
1797         pZ = (uint32_t*)((uint32_t)pSharedSecretVal2 & (~(uint32_t)3));
1798         err = PkiExecModExpLeW(
1799             pZ,            /*exp.result - out*/
1800             partnPublKey2, /*public key - in*/
1801             primeSizeWords, /*public key size - in*/
1802             &pDhCtx->ffcDomain.prime[0],             /*prime P - modulus*/
1803             primeSizeWords*CC_BITS_IN_BYTE, /*P size in bits*/
1804             userPrivKey2,       /* sub-group order Q*/
1805             orderSizeWords); /* Q size in words*/
1806 
1807         /* check error */
1808         if (err != CC_OK) {
1809             goto End;
1810         }
1811 
1812         /* convert Z to BE bytes */
1813         CC_CommonInPlaceConvertBytesWordsAndArrayEndianness(pZ, primeSizeWords);
1814 
1815     }
1816 
1817 End:
1818     if (err != CC_OK) {
1819         /* delete secure sensitive data */
1820         CC_PalMemSetZero((uint8_t*)pDhCtx, sizeof(DhContext_t));
1821     }
1822 
1823     return err;
1824 
1825 }
1826 
1827 #ifdef FFC_FURTHER_USING
1828 
1829 /* The function updates offsets for further using */
FfcDhUpdateOffsets(DhContext_t * pDhCtx,CCFfcDhUserPartyIs_t userParty)1830 static void FfcDhUpdateOffsets(DhContext_t *pDhCtx,
1831                    CCFfcDhUserPartyIs_t userParty)
1832 {
1833     uint8_t *pTmp1;
1834     uint16_t size1, partnerInfoNewOffset;
1835     FfcDhSchemeDataOffsets_t *dataOffsets = &pDhCtx->dataOffsets;
1836     int32_t diffOffsets;
1837 
1838     if(userParty == CC_FFCDH_PARTY_U) {
1839 
1840         pTmp1 = &pDhCtx->extendDataBuffer[0] + pDhCtx->dataOffsets.userOtherDataOffset;
1841         size1 = FFCDH_GET_LENGTH(pTmp1); /* size of user Other data*/
1842         partnerInfoNewOffset = pDhCtx->dataOffsets.userOtherDataOffset + size1 +
1843                            CC_FFCDH_LENGTH_COUNTER_SIZE_IN_BYTES;
1844         /* difference between new and old offsets */
1845         diffOffsets = pDhCtx->dataOffsets.partnIdOffset - partnerInfoNewOffset;
1846 
1847         /* move partner info to new position */
1848         pTmp1 = &pDhCtx->extendDataBuffer[0] + partnerInfoNewOffset;
1849         FfcDhWriteBufferBeToBe(&pTmp1, &pDhCtx->extendDataBuffer[0] + pDhCtx->dataOffsets.partnIdOffset,
1850                              pDhCtx->dataOffsets.partnInfoSize + pDhCtx->dataOffsets.suppPublInfoSize +
1851                              pDhCtx->dataOffsets.suppPrivInfoSize);
1852         /* update */
1853         dataOffsets->partnIdOffset -= diffOffsets;
1854         dataOffsets->partnStatPublKeyOffset -= diffOffsets;
1855         dataOffsets->partnEphemPublKeyOffset -= diffOffsets;
1856         dataOffsets->partnNonceOffset -= diffOffsets;
1857         dataOffsets->partnOtherDataOffset -= diffOffsets;
1858 
1859         dataOffsets->suppPublInfoOffset = dataOffsets->partnIdOffset + CC_FFCDH_LENGTH_COUNTER_SIZE_IN_BYTES +
1860                           pDhCtx->dataOffsets.partnInfoSize;
1861         dataOffsets->suppPrivInfoOffset = dataOffsets->suppPublInfoOffset + CC_FFCDH_LENGTH_COUNTER_SIZE_IN_BYTES +
1862                                       dataOffsets->suppPublInfoSize;
1863     } else {
1864         pTmp1 = &pDhCtx->extendDataBuffer[0] + pDhCtx->dataOffsets.partnOtherDataOffset;
1865         size1 = FFCDH_GET_LENGTH(pTmp1); /* size of user Other data*/
1866         partnerInfoNewOffset = pDhCtx->dataOffsets.userOtherDataOffset + size1 +
1867                            CC_FFCDH_LENGTH_COUNTER_SIZE_IN_BYTES;
1868         /* difference between new and old offsets */
1869         diffOffsets = pDhCtx->dataOffsets.userOtherDataOffset - partnerInfoNewOffset;
1870         /* move user info to new position */
1871         FfcDhWriteBufferBeToBe(&pDhCtx->extendDataBuffer[0] + partnerInfoNewOffset,
1872                              &pDhCtx->extendDataBuffer[0] + pDhCtx->dataOffsets.partnIdOffset,
1873                              pDhCtx->dataOffsets.partnInfoSize + pDhCtx->dataOffsets.suppPublInfoSize +
1874                              pDhCtx->dataOffsets.suppPrivInfoSize);
1875 
1876         dataOffsets->userIdOffset -= diffOffsets;
1877         dataOffsets->userStatPublKeyOffset -= diffOffsets;
1878         dataOffsets->userEphemPublKeyOffset -= diffOffsets;
1879         dataOffsets->userNonceOffset -= diffOffsets;
1880         dataOffsets->userOtherDataOffset -= diffOffsets;
1881 
1882         dataOffsets->suppPublInfoOffset = dataOffsets->userIdOffset + CC_FFCDH_LENGTH_COUNTER_SIZE_IN_BYTES +
1883                           pDhCtx->dataOffsets.userInfoSize;
1884         dataOffsets->suppPrivInfoOffset = dataOffsets->suppPublInfoOffset + CC_FFCDH_LENGTH_COUNTER_SIZE_IN_BYTES +
1885                                       dataOffsets->suppPublInfoSize;
1886     }
1887 
1888     return;
1889 }
1890 #endif
1891 
1892 
1893 /* The function compares party Info entries, inserted into DH context and
1894  * given by the partner in the PartnerInfo buffer.
1895  * If the data is not equaled, then the function returns an error. After the data
1896  * checking the function promotes the data pointers to the next Info entry.
1897  *
1898  */
FfcDhCmpInfoEntries(uint8_t ** ppCtxEntry,uint8_t ** ppPartnEntry)1899 static CCError_t  FfcDhCmpInfoEntries(uint8_t **ppCtxEntry, uint8_t **ppPartnEntry)
1900 {
1901         CCError_t err = CC_OK; /* return error identifier */
1902         uint32_t calcSize, partnSize;
1903 
1904         calcSize = FFCDH_GET_LENGTH(*ppCtxEntry); /* size of PartnerId from Ctx; & pTmp1 += 2 */
1905         partnSize = FFCDH_GET_LENGTH(*ppPartnEntry); /*  -- " -- from Partner's data */
1906     CHECK_AND_SET_ERROR(calcSize != partnSize,  CC_FFCDH_PARTN_INFO_PARSING_SIZE_ERROR);
1907     CHECK_AND_SET_ERROR(CC_PalMemCmp(*ppCtxEntry, *ppPartnEntry, partnSize), CC_FFCDH_PARTN_INFO_PARSING_DATA_ERROR);
1908     /* promote pointers to next entry (partnStatPublKey) */
1909     *ppCtxEntry += calcSize;
1910     *ppPartnEntry += partnSize;
1911 
1912 End:
1913     return err;
1914 }
1915 
1916 
1917 /******************************************************************************************/
1918 /*!
1919 @brief The function calculates user's confirmation MacTags for FFC DH Schemes according to NIST SP 56A rev.2 standard.
1920 
1921 \note Before calling of this function the user should obtain assurance of used FFC Domain and public, private keys,
1922 involved in the key agreement, using one of the methods, described in sec. 5.6.2 of above named standard.
1923 <ul><li> - depending on DH Scheme, calculates confirmation HMAC MacTag, which is intended to be provided to the partner
1924 (sec. 5.2, 5.9, 6); in this case the secret keying material is parsed to MacKey of size, equaled to HMAC key size. </li>
1925 <li> - in our implementation HMAC key size defined equal to FFC sub-group order (meets to sec.5.9.3). </li>
1926 <li> - if in the chosen DH Scheme the user is not Confirmation provider, then both the pointer and the size of
1927 appropriate MacTag should be set to NULL. </li>
1928 <li>  - for detailed description of Confirmation "MacData" see CCFfcDhConfirmMacData_t structure definition. </li></ul>
1929 
1930 @return CC_OK on success.
1931 @return A non-zero value on failure as defined in cc_dh_error.h, cc_kdf_error.h or cc_hash_error.h.
1932 */
1933 
FfcDhCalcConfirmMacTags(DhContext_t * pDhCtx,uint8_t * pUserConfirmText,uint32_t userConfirmTextSize,uint8_t * pPartnerConfirmText,uint32_t partnerConfirmTextSize)1934 static CCError_t FfcDhCalcConfirmMacTags(
1935                         DhContext_t *pDhCtx,               /*!< [in] pointer to the user's DH context structure, containing all data, defining
1936                                                                    DH Key Agreement Scheme. The context shall be initialized for user's roles
1937                                                                    (U or V; Provider or Receiver) using CC_FfcDhSetCtx function. */
1938                         uint8_t  *pUserConfirmText,        /*!< [in] optional, pointer to confirmation Text of the User. */
1939                         uint32_t  userConfirmTextSize,     /*!< [in] optional size of Text data of partyU, in bytes. */
1940                         uint8_t  *pPartnerConfirmText,     /*!< [in] optional, pointer to confirmation Text of the Partner. */
1941                         uint32_t  partnerConfirmTextSize)  /*!< [in] optional, size of Text data of partyV, in bytes. */
1942 
1943 {
1944     /* Function Declarations    */
1945 
1946         CCError_t err = CC_OK; /* return error identifier */
1947         uint8_t messStr1[] = "KS_1_U", messStr2[] = "KS_2_U", strV[] = "V";
1948         uint8_t *pMessStr; /*a pointer to messageString*/
1949         uint8_t *pTmp;
1950     /* address of extended data buffer */
1951         uint8_t *pBaseAddr = &pDhCtx->extendDataBuffer[0];
1952         uint32_t fullLen = 0;
1953 
1954         CCHashOperationMode_t hashMode;
1955     const mbedtls_md_info_t *mdInfo = NULL;
1956 
1957 
1958 
1959 #define MESSAGE_STR_SIZE 6
1960 
1961 
1962     /* if confirmation is required, then set formatted MacData string according
1963      * to scheme and user roles in confirmation (U,V and Provider - P, Recipient - R):
1964      *   MacData = messageString||IdP||IdR||EphemDataP||EphemDataR{||TextP}
1965      *   SP 800-56A sec. 5.9. */
1966 
1967 /* set messageString according to Hybrid (or not) confirm. mode  */
1968     if((pDhCtx->dhSchemeId == CC_FFCDH_SCHEM_HYBRID1) ||
1969             (pDhCtx->dhSchemeId == CC_FFCDH_SCHEM_HYBRID_ONE_FLOW)) {
1970         pMessStr = &messStr2[0];
1971     } else {
1972         pMessStr = &messStr1[0];
1973     }
1974 
1975     /* get HASH mode and op. size */
1976     CHECK_ERROR(FfcGetHashMode(&hashMode, NULL, NULL/*pBlockSize*/,
1977                      NULL/*pDigestSize*/, pDhCtx->ffcHashMode));
1978 
1979         /* calculate MacTag for user as provider */
1980     if(pDhCtx->schemeInfo.doConfirmProvid == 1) {
1981         if(pDhCtx->userParty == CC_FFCDH_PARTY_V) {
1982             CC_PalMemCopy(&pMessStr[5], strV, 1); /*set user V letter*/
1983         }
1984 
1985         /* copy all required confirmation data to context buffer */
1986         pTmp = pBaseAddr + pDhCtx->dataOffsets.algIdOffset;
1987         FfcDhWriteBufferBeToBe(&pTmp, pMessStr, MESSAGE_STR_SIZE, &fullLen);
1988         FfcDhWriteBufferBeToBe(&pTmp, pDhCtx->userId, pDhCtx->userIdSizeBytes, &fullLen);
1989         FfcDhWriteBufferBeToBe(&pTmp, pDhCtx->partnerId, pDhCtx->partnerIdSizeBytes, &fullLen);
1990         FfcDhWriteBufferLeToBe(&pTmp, &pDhCtx->userEphemPublKey[0], pDhCtx->userStatPublKeySizeBytes>>2, &fullLen);
1991         FfcDhWriteBufferBeToBe(&pTmp, pDhCtx->userNonce, pDhCtx->userNonceSizeBytes, &fullLen);
1992         FfcDhWriteBufferLeToBe(&pTmp, &pDhCtx->partnerEphemPublKey[0], pDhCtx->partnerStatPublKeySizeBytes>>2, &fullLen);
1993         FfcDhWriteBufferBeToBe(&pTmp, pDhCtx->partnerNonce, pDhCtx->partnerNonceSizeBytes, &fullLen);
1994         FfcDhWriteBufferBeToBe(&pTmp, pUserConfirmText, userConfirmTextSize, &fullLen);
1995 
1996         /* call HMAC function with Key derived from pDhCtx->derivedKeyingMaterial  */
1997         mdInfo = mbedtls_md_info_from_string( HashAlgMode2mbedtlsString[hashMode] );
1998         if( mdInfo == NULL ){
1999             return CC_FFCDH_INVALID_HASH_MODE_ERROR;
2000         }
2001         err = mbedtls_md_hmac( mdInfo,
2002                             &pDhCtx->derivedKeyingMaterial[0]/*HmacKey*/,
2003                             CC_FFCDH_SIZE_OF_CONFIRM_MAC_KEY_IN_BYTES/*HmacKeySize*/,
2004                             pBaseAddr + pDhCtx->dataOffsets.algIdOffset/*data*/,
2005                             fullLen/*dataInSize*/,
2006                             (unsigned char*)pDhCtx->userMacTag/*result*/ );
2007         if (err != CC_OK){
2008             goto End;
2009         }
2010     }
2011 
2012 
2013 
2014     /* calculate MacTag for partner as provider */
2015     if(pDhCtx->schemeInfo.doConfirmRecip == 1) {
2016         if(pDhCtx->userParty == CC_FFCDH_PARTY_U) {
2017             CC_PalMemCopy(&pMessStr[5], strV, 1); /*set partner V letter*/
2018         }
2019 
2020         /* copy all required confirmation data to context buffer */
2021         pTmp = pBaseAddr + pDhCtx->dataOffsets.algIdOffset;
2022         FfcDhWriteBufferBeToBe(&pTmp, pMessStr, MESSAGE_STR_SIZE, &fullLen);
2023         FfcDhWriteBufferBeToBe(&pTmp, pDhCtx->partnerId, pDhCtx->partnerIdSizeBytes, &fullLen);
2024         FfcDhWriteBufferBeToBe(&pTmp, pDhCtx->userId, pDhCtx->userIdSizeBytes, &fullLen);
2025         FfcDhWriteBufferLeToBe(&pTmp, pDhCtx->partnerEphemPublKey, pDhCtx->partnerStatPublKeySizeBytes>>2, &fullLen);
2026         FfcDhWriteBufferBeToBe(&pTmp, pDhCtx->partnerNonce, pDhCtx->partnerNonceSizeBytes, &fullLen);
2027         FfcDhWriteBufferLeToBe(&pTmp, pDhCtx->userEphemPublKey, pDhCtx->userStatPublKeySizeBytes>>2, &fullLen);
2028         FfcDhWriteBufferBeToBe(&pTmp, pDhCtx->userNonce, pDhCtx->userNonceSizeBytes, &fullLen);
2029         FfcDhWriteBufferBeToBe(&pTmp, pPartnerConfirmText, partnerConfirmTextSize, &fullLen);
2030 
2031 
2032         err = mbedtls_md_hmac( mdInfo,
2033                             &pDhCtx->derivedKeyingMaterial[0]/*HmacKey*/,
2034                             CC_FFCDH_SIZE_OF_CONFIRM_MAC_KEY_IN_BYTES/*KeySize*/,
2035                             pBaseAddr + pDhCtx->dataOffsets.algIdOffset/*data*/,
2036                             fullLen/*dataInSize*/,
2037                             (unsigned char*)pDhCtx->partnerMacTag/*result*/);
2038         if (err != CC_OK){
2039             goto End;
2040 
2041         }
2042     }
2043 
2044 
2045 End:
2046     return err;
2047 
2048 }
2049 
2050 
2051 
2052 
2053 /*******************************************************************************************/
2054 /*!
2055 @brief This function checks and sets given "OtherInfo" entries, calculates shared secret value and
2056        derives the "secret keying material".
2057        The function's implementation meets to NIST SP 56A rev.2 standard requirements.
2058 \note Before calling of this function, DH Context should be initialized, DH Scheme, Domain parameters and all
2059 required user's Private, Public keys or nonces are inserted by calling appropriate CC functions.
2060 <ul><li>  The function sets input data into the Context to form the "OtherInfo" (sec. 5.8.1) according to
2061 said standard and the implementation requirements:
2062 <li>  - OtherInfo = AlgorithmId||PartyUInfo||PartyVInfo {||SuppPubInfo}{||SuppPrivInfo}, where each PartyInfo is
2063 formatted as : </li>
2064 <li>  - Remark: AlgorithmId includes information about length in bits of derived Keying Material and its
2065  parsing between internal using for confirmation HMAC algorithm and output Secret Keying Data
2066  and algorithm, which it is intended for. </li>
2067 <li>  - PartyInfo = PartyId||PartyStatPublKey||PartyEphemKey||PartyNonce{||PartyOtherData}. </li>
2068 <li>  - for detailed description of "OtherInfo" construction and concatenation its sub-entries, see
2069 CCFfcDhOtherInfo_t structure definition; </li></ul>
2070 \note - the function performs the following calculations:
2071 <ul><li> - calculates shared secret value according to DH Scheme:
2072    -  SharedSecretVal = (PublKey1 ^ PrivKey1)  modulo Prime  or
2073    -  SharedSecretVal = (PartnPublKey1 ^ UserPrivKey1) || (PartnPublKey2 ^ UserPrivKey2)  modulo Prime; </li>
2074 <li> - derives the secret keying material of required size from the shared secret value by calling KDF function
2075 with shared OtherInfo data: DerivedKeyingMaterial = KDF(ZZ, OtherInfo, keyingMaterialSize); </li></ul>
2076 <ul><li> - If DH Scheme includes Key Confirmation, then the function calculates confirmation HMAC MacTag, which is
2077 intended to be provided to the partner (sec. 5.2, 5.9, 6); in this case the secret keying material is parsed to MacKey
2078 of size, equaled to HMAC key size. </li>
2079 <li> - in our implementation HMAC key size is defined to be equaled to FFC sub-group order (meets to sec.5.9.3). </li>
2080 <li> - if in the chosen DH Scheme the user is not a Confirmation Provider, then both the pointer and the size of
2081 appropriate MacTag should be set to NULL. </li>
2082 <li>  - for detailed description of Confirmation "MacData" see CCFfcDhConfirmMacData_t structure definition. </li></ul>
2083 
2084 @return CC_OK on success.
2085 @return A non-zero value on failure as defined cc_dh_error.h.
2086 */
2087 
CC_FfcDhSetAndCalculateSchemeData(CCFfcDhUserContext_t * pDhUserCtx,uint8_t * pPartnerInfo,size_t sizeOfPartnerInfo,CCFfcDhPartyInfoValidMode_t partnInfoValidMode,uint8_t * pSuppPubInfo,size_t suppPubInfoSize,uint8_t * pSuppPrivInfo,size_t suppPrivInfoSize,uint8_t * pUserMacTag,size_t macTagSize)2088 CEXPORT_C CCError_t CC_FfcDhSetAndCalculateSchemeData(
2089                         CCFfcDhUserContext_t *pDhUserCtx, /*!< [in/out] pointer to context structure, containing all data, used in DH Key
2090                                                                 Agreement Scheme, required for implementation of said standard. */
2091                         /*! Partner's Data to be included into OtherInfo entry. Detailed description see in CCFfcDhOtherInfo_t. */
2092                         uint8_t *pPartnerInfo,            /*!< [in] pointer to the concatenated PartnerInfo. Detailed description see in CCFfcDhOtherInfo_t. */
2093                         size_t sizeOfPartnerInfo,         /*!< [in] size of PartnerInfo, in bytes, should be <= CC_FFCDH_MAX_SIZE_OF_PARTY_INFO_BYTES. */
2094                         CCFfcDhPartyInfoValidMode_t partnInfoValidMode, /*!< enumerator, defining which of public keys (static, ephemeral),
2095                                                                 included in the PartnerInfo, should be full validated and which partial only. */
2096                         uint8_t *pSuppPubInfo,            /*!< [in] pointer to optional shared public data to be included into SuppPubInfo entry */
2097                         size_t suppPubInfoSize,           /*!< [in] size of SuppPubInfo data, in bytes. */
2098                         uint8_t *pSuppPrivInfo,           /*!< [in] pointer to optional shared private data to be included into SuppPrivInfo entry */
2099                         size_t suppPrivInfoSize,          /*!< [in] size of other SuppPrivInfo data, in bytes (should be not great than
2100                                                                     CC_FFCDH_MAX_SIZE_OF_OTHER_INFO_SUPPL_ENTRY_BYTES */
2101                         uint8_t *pUserMacTag,             /*!< [out] optional, pointer to the user-provider confirmation MacTag depending
2102                                                                    on used Key Agreement Scheme. The tag is calculated by HMAC with given
2103                                                                    hashMode, as described in SP800-56A sec. 5.9. */
2104                         size_t  macTagSize                /*!< [in] optional, required size in bytes of confirmation MacTag. */
2105 )
2106 {
2107     /* FUNCTION DECLARATIONS */
2108 
2109     CCError_t err = CC_OK; /* return error identifier */
2110     DhContext_t  *pDhCtx = NULL;
2111     uint8_t *pBaseAddr = NULL;
2112     uint8_t *pTmp1 = NULL/* Context data pointer */;
2113     uint8_t *pTmp2 = NULL/* Partner given data pointer */;
2114     uint32_t size1 = 0, size2 = 0, ffcOrderSize;
2115     CCFfcDhKeyValidMode_t partnStatKeyValidMode, partnEphemKeyValidMode;
2116     /* pointer and size of shared secret value. */
2117     uint8_t *pZZ;
2118     uint32_t zzSize;
2119     uint8_t *pOtherInfo;
2120     mbedtls_hkdf_hashmode_t hkdfHashMode;
2121 
2122 //        CCFfcDhKeyValidMode_t validatMode;
2123 
2124     CHECK_AND_RETURN_ERR_UPON_FIPS_ERROR();
2125 
2126     /* check contexts pointers and tags */
2127     if (pDhUserCtx == NULL) {
2128     return CC_FFCDH_INVALID_CONTEXT_PTR_ERROR;
2129     }
2130 
2131     /* check that DhCtx is valid for user keys generation step: *
2132     *  DH Scheme, Domain and Keys are set.                      */
2133     CHECK_AND_SET_ERROR((pDhUserCtx->validTag != FFCDH_CTX_VALID_TAG_USER_INFO_SET),
2134                      CC_FFCDH_CONTEXT_VALIDATION_TAG_ERROR);
2135     /*  check the mandatory data pointers and sizes */
2136     CHECK_AND_SET_ERROR((pPartnerInfo == NULL), CC_FFCDH_INVALID_ARGUMENT_POINTER_ERROR);
2137     CHECK_AND_SET_ERROR(((sizeOfPartnerInfo == 0) || (sizeOfPartnerInfo > CC_FFCDH_MAX_SIZE_OF_PARTY_INFO_BYTES)),
2138                               CC_FFCDH_INVALID_ARGUMENT_SIZE_ERROR);
2139     /*  check the optional data pointers and sizes */
2140     CHECK_AND_SET_ERROR(((pSuppPubInfo == NULL) != (suppPubInfoSize == 0)) ||
2141                         (suppPubInfoSize > CC_FFCDH_MAX_SIZE_OF_OTHER_INFO_SUPPL_ENTRY_BYTES),
2142                               CC_FFCDH_OPTIONAL_DATA_ERROR);
2143     CHECK_AND_SET_ERROR(((pSuppPrivInfo == NULL) != (suppPrivInfoSize == 0)) ||
2144                         (suppPrivInfoSize > CC_FFCDH_MAX_SIZE_OF_OTHER_INFO_SUPPL_ENTRY_BYTES),
2145                               CC_FFCDH_OPTIONAL_DATA_ERROR);
2146     CHECK_AND_SET_ERROR(partnInfoValidMode >= CC_FFCDH_NO_FULL_VALIDAT_MODE, CC_FFCDH_INVALID_VALIDAT_MODE_ERROR);
2147     /*  check optional confirmation data pointers and sizes */
2148     CHECK_AND_SET_ERROR((pUserMacTag == NULL) != (macTagSize == 0), CC_FFCDH_OPTIONAL_DATA_ERROR);
2149 //        CHECK_AND_SET_ERROR(((pUserConfirmText == NULL) != (userConfirmTextSize == 0)) ||
2150 //                                 (userConfirmTextSize > CC_FFCDH_MAX_SIZE_OF_CONFIRM_TEXT_DATA_BYTES),
2151 //                CC_FFCDH_OPTIONAL_DATA_ERROR);
2152 //        CHECK_AND_SET_ERROR(((pPartnerConfirmText == NULL) != (partnerConfirmTextSize == 0)) ||
2153 //                                 (partnerConfirmTextSize > CC_FFCDH_MAX_SIZE_OF_CONFIRM_TEXT_DATA_BYTES),
2154 //                                  CC_FFCDH_OPTIONAL_DATA_ERROR);
2155 
2156 
2157         /* Get internal context structure */
2158     pDhCtx = (DhContext_t*)&pDhUserCtx->contextBuff;
2159 
2160     if(pDhCtx->schemeInfo.doConfirmProvid == 1) {
2161         CHECK_AND_SET_ERROR((pUserMacTag == NULL) || (macTagSize != pDhCtx->macTagSize),
2162                              CC_FFCDH_OPTIONAL_DATA_ERROR);
2163     }
2164 
2165     /* set base address to partner info = PartnerId in the DH Context. */
2166     pBaseAddr = &pDhCtx->extendDataBuffer[0] + pDhCtx->dataOffsets.partnIdOffset;
2167     pTmp1 = pBaseAddr;        /* in ctx */
2168     pTmp2 = &pPartnerInfo[0]; /* in received data */
2169 
2170         /* get FFC domain parameters */
2171     ffcOrderSize = pDhCtx->ffcDomain.ordLenWords*CC_32BIT_WORD_SIZE;
2172 
2173     /*-----------------------------------*/
2174     /* Check and import PartnerInfo data */
2175     /*-----------------------------------*/
2176 
2177     /* set validation mode for each of keys */
2178     if(partnInfoValidMode == CC_FFCDH_BOTH_KEYS_FULL_VALIDAT_MODE) {
2179         partnStatKeyValidMode = CC_FFCDH_KEY_VALIDAT_FULL_MODE;
2180         partnEphemKeyValidMode = CC_FFCDH_KEY_VALIDAT_FULL_MODE;
2181     } else {
2182         partnStatKeyValidMode  = CC_FFCDH_KEY_VALIDAT_PARTIAL_MODE;
2183         partnEphemKeyValidMode = CC_FFCDH_KEY_VALIDAT_PARTIAL_MODE;
2184     }
2185     if (partnInfoValidMode == CC_FFCDH_STAT_KEY_FULL_VALIDAT_MODE) {
2186         partnStatKeyValidMode = CC_FFCDH_KEY_VALIDAT_FULL_MODE;
2187     }
2188     if(partnInfoValidMode == CC_FFCDH_EPHEM_KEY_FULL_VALIDAT_MODE) {
2189         partnEphemKeyValidMode = CC_FFCDH_KEY_VALIDAT_FULL_MODE;
2190     }
2191 
2192     /* check partner ID data */
2193     CHECK_ERROR(FfcDhCmpInfoEntries(&pTmp1, &pTmp2));
2194 
2195 //  size1 = FFCDH_GET_LENGTH(pTmp1); /* size of PartnerId from Ctx; & pTmp1 += 2 */
2196 //  size2 = FFCDH_GET_LENGTH(pTmp2); /*  -- " -- from Partner's data */
2197 //  CHECK_AND_SET_ERROR(size1 != size2,  CC_FFCDH_PARTN_INFO_PARSING_SIZE_ERROR);
2198 //  CHECK_AND_SET_ERROR(CC_PalMemCmp(pTmp1, pTmp2, size2), CC_FFCDH_PARTN_INFO_PARSING_DATA_ERROR);
2199 //  /* promote pointers to next entry (partnStatPublKey) */
2200 //  pTmp1 += size1;
2201 //  pTmp2 += size2;
2202 
2203 
2204 
2205 /* ????? should be revised:  check that inserted = passeD  */
2206 
2207     /* check and (if needed) import the partner`s static PublKey.
2208      * note: the pointers will be updated to next buffer */
2209     if(pDhCtx->schemeInfo.doPartnerStatKey) {
2210         /* check and import the Key, promote pointers to next Info entries */
2211         err = FfcDhValidatePartnInfoPublKey(
2212             pDhCtx,
2213             partnStatKeyValidMode,
2214             &pTmp1   /* in context*/,
2215             &pTmp2); /* in PartnerInfo */
2216         CHECK_ERROR(err);
2217     } else {
2218         /* get sizes and promote pointers to next entry */
2219         size1 = FFCDH_GET_LENGTH(pTmp1);
2220         size2 = FFCDH_GET_LENGTH(pTmp2);
2221         /* check that given key size == 0, i.e. that partner not passes redundant key */
2222         CHECK_AND_SET_ERROR((size1 != 0) || (size2 != 0), CC_FFCDH_PARTN_INFO_PARSING_SIZE_ERROR);
2223     }
2224 
2225     /* check and (if needed) import the partner`s static PublKey.
2226      * note: the pointers will be updated to next buffer */
2227     if(pDhCtx->schemeInfo.doPartnerEphemKey) {
2228         /* check and import (if needed) the Key */
2229         err = FfcDhValidatePartnInfoPublKey(
2230             pDhCtx,
2231             partnEphemKeyValidMode,
2232             &pTmp1 /* in context*/,
2233             &pTmp2 /* in PartnerInfo */);
2234         CHECK_ERROR(err);
2235 // ????
2236     } else if (pDhCtx->schemeInfo.doPartnerNonce){
2237         /* check and import nonce */
2238         size1 = FFCDH_GET_LENGTH(pTmp1); /* size of Partner's nonce from Ctx; & pTmp1 += 2 */
2239         size2 = FFCDH_GET_LENGTH(pTmp2); /*  -- " -- from Partner's data */
2240         if(size1 != 0) {
2241             CHECK_AND_SET_ERROR(size1 != size2, CC_FFCDH_PARTN_INFO_PARSING_SIZE_ERROR);
2242             CHECK_AND_SET_ERROR(CC_PalMemCmp(pTmp1, pTmp2, size1), CC_FFCDH_PARTN_INFO_PARSING_DATA_ERROR);
2243         } else {
2244             CHECK_AND_SET_ERROR(size2 != ffcOrderSize, CC_FFCDH_PARTN_INFO_PARSING_SIZE_ERROR);
2245             /* copy nonce into context */
2246             FfcDhWriteBufferBeToBe(&pTmp1, pTmp2,  size2, &pDhCtx->currInsertedDataSize);
2247         }
2248     } else {
2249         /* check that key size, given by Partner == 0, i.e. that partner not passes redundant key */
2250         CHECK_AND_SET_ERROR(size2 != 0, CC_FFCDH_PARTN_INFO_PARSING_SIZE_ERROR);
2251     }
2252 
2253     /* import Partner's Other data */
2254     size1 = FFCDH_GET_LENGTH(pTmp1); /* size of Partner Other data from Ctx; & pTmp1 += 2 */
2255     size2 = FFCDH_GET_LENGTH(pTmp2); /*  -- " -- from Partner's data */
2256     CHECK_AND_SET_ERROR(size1 != 0, CC_FFCDH_PARTN_INFO_PARSING_SIZE_ERROR);
2257     CHECK_AND_SET_ERROR(size2 > CC_FFCDH_MAX_SIZE_OF_PARTY_INFO_OTHER_DATA_BYTES, CC_FFCDH_PARTN_INFO_PARSING_SIZE_ERROR);
2258     FfcDhWriteBufferBeToBe(&pTmp1, pTmp2, size2, &pDhCtx->currInsertedDataSize); /* copy to Context */
2259     /* import Supplied public and private data */
2260     CHECK_AND_SET_ERROR(suppPubInfoSize > CC_FFCDH_MAX_SIZE_OF_OTHER_INFO_SUPPL_ENTRY_BYTES, CC_FFCDH_PARTN_INFO_PARSING_SIZE_ERROR);
2261     CHECK_AND_SET_ERROR(suppPrivInfoSize > CC_FFCDH_MAX_SIZE_OF_OTHER_INFO_SUPPL_ENTRY_BYTES, CC_FFCDH_PARTN_INFO_PARSING_SIZE_ERROR);
2262     FfcDhWriteBufferBeToBe(&pTmp1, pSuppPubInfo, suppPubInfoSize, &pDhCtx->currInsertedDataSize);
2263     FfcDhWriteBufferBeToBe(&pTmp1, pSuppPrivInfo, suppPrivInfoSize, &pDhCtx->currInsertedDataSize);
2264 
2265     /*--------------------------------------------------*/
2266     /* Calculate Shared Secret Value using DH primitive */
2267     /*--------------------------------------------------*/
2268     FfcDhCalcSharedSecretVal(pDhCtx);
2269 
2270     /*----------------------------------------------------------------------
2271     * Calculate Shared Secret Keying Data using HASH KDF using HMAC KDF.
2272     * Derivation method meets to requirements of SP 800-56A sec. 5.8, refer
2273     * to SP 800-56C. Note, that these standards allowing implementation
2274     * with application specified formatting of concatenated OtherInfo entries
2275     * and used HMAC modes. In partial, is allowed using RFC 5869 mode of HMAC
2276     * (SP 800-56C sec.4) with formatting, described below.
2277     *----------------------------------------------------------------------*/
2278 
2279     if(pDhCtx->kdfMode == CC_FFCDH_KDF_HMAC_RFC5869_MODE) {
2280         /* on this RFC 5869 mode is used the following format of input data to
2281          * key derivation function: on randomness extraction step are used: Salt (s)
2282          * and ShredSecretValue ZZ as message to generate pseudo random key (PRK);
2283          * on expansion step the function concatenates input DhOtherInfo and 1-byte counter
2284          * to derive the KeyingMaterial */
2285 
2286         /* get pointer and size of shared secret value */
2287         pZZ = &pDhCtx->extendDataBuffer[0] + (size_t)pDhCtx->dataOffsets.sharedSecrOffset;
2288         zzSize = FFCDH_GET_LENGTH(pZZ); /*get size and promote the pointer*/
2289         pOtherInfo = pZZ + zzSize; /*get OtherInfo*/
2290 
2291         /* get HKDF Hash mode ID */
2292         CHECK_ERROR(FfcGetHashMode(NULL/*pHashMode*/, &hkdfHashMode, NULL/*pBlockSize*/,
2293                          NULL/*pDigestSize*/, pDhCtx->ffcHashMode));
2294 
2295         /* call HKDF RFC5869 function */
2296         err = mbedtls_hkdf_key_derivation(
2297                 hkdfHashMode,
2298                 (uint8_t*)&pDhCtx->hmacSalt[0],
2299                 (size_t)pDhCtx->hmacSaltSizeBytes,
2300                 pZZ/*shared secret value - Ikm*/,
2301                 zzSize/*shared secret size - IkmLen*/,
2302                 pOtherInfo /*OtherInfo - Info*/,
2303                 pDhCtx->currInsertedDataSize/*InfoLen*/,
2304                 pDhCtx->derivedKeyingMaterial/*Okm*/,
2305                 pDhCtx->derivedKeyingMaterialSize/*OkmLen*/,
2306                 CC_FALSE/*IsStrongKkey*/);
2307     }
2308 
2309     /* if confirmation is required, then set formatted MacData string according
2310      * to scheme and user roles in confirmation (U,V and Provider - P, Recipient - R):
2311      *   MacData = messageString||IdP||IdR||EphemDataP||EphemDataR{||TextP}
2312      * (see SP 800-56A sec. 5.9). */
2313     if(pDhCtx->schemeInfo.doConfirmProvid) {
2314         err = FfcDhCalcConfirmMacTags(pDhCtx, pDhCtx->userConfirmText, pDhCtx->userConfirmTextSize,
2315                 pDhCtx->partnerConfirmText, pDhCtx->partnerConfirmTextSize);
2316         CHECK_ERROR(err);
2317 
2318         /* output the user MacTag */
2319         CC_PalMemCopy(pUserMacTag, pDhCtx->userMacTag, macTagSize);
2320     }
2321 
2322     /* update validation tag  */
2323         pDhCtx->validTag |= FFCDH_CTX_VALID_TAG_SCHEM_DATA_BIT;
2324 
2325 End:
2326     if(err != CC_OK) {
2327         CC_PalMemSetZero(pDhUserCtx, sizeof(CCFfcDhUserContext_t));
2328     }
2329 
2330         return err;
2331 
2332 }
2333 
2334 
2335 /*******************************************************************************************/
2336 /*!
2337 @brief This function performs DH Key Agreement Confirmation and, on success, outputs the shared keying data.
2338 The function calculates expected partner's confirmation MacTag' and compares it to value,
2339 received from the partner.
2340 <li> If the tags are not equaled, then the function returns an error and zeroes the secure
2341 sensitive data. </li>
2342 <li> If no errors, the function puts the derived secret keying data into output buffer. </li>
2343 \note Assumed, that the user yet have obtained assurance of public and private keys,
2344 involved in the key agreement.
2345 \note Before calling this function the user should perform all required DH Key Agreement
2346 operations, including calculation of shared secret keying material by calling
2347 CC_FfcDhCalcUserConfirmMacTag function.
2348 \note If according to chosen Scheme the user is not a Confirmation Recipient,
2349 then all, the pointer and the size of MacTag should be
2350 set to zero, else the function returns an error.
2351 
2352 @return CC_OK on success.
2353 @return A non-zero value on failure as defined in cc_dh_error.h
2354 */
CC_FfcDhGetSharedSecretKeyingData(CCFfcDhUserContext_t * pDhUserCtx,uint8_t * pSecretKeyData,size_t * pSecretKeyDataSize,uint8_t * pPartnerMacTag,size_t macTagSize)2355 CEXPORT_C CCError_t CC_FfcDhGetSharedSecretKeyingData(
2356                         CCFfcDhUserContext_t *pDhUserCtx, /*!< [in] pointer to the user's DH context structure, containing all data,
2357                                                                defining DH Key Agreement Scheme and its results.  */
2358                         uint8_t *pSecretKeyData,          /*!< [out] pointer to the shared secret keying data, extracted
2359                                                                 from keying material after parsing to . */
2360                         size_t  *pSecretKeyDataSize,      /*!< [in/out] the pointer to the size of shared secret key data:
2361                                                                in - size of the given output buffer, out - actual size of extracted
2362                                                                key data */
2363                         uint8_t *pPartnerMacTag,          /*!< [in] optional, pointer to the confirmation MacTag, provided by the partner */
2364                         size_t   macTagSize)              /*!< [in] optional, size of partner's MacTag, in bytes */
2365 {
2366     CCError_t err = CC_OK; /* return error identifier */
2367     DhContext_t *pDhCtx;
2368     uint8_t *pKeyData;
2369     uint32_t hashBlockSize;
2370 
2371     CHECK_AND_RETURN_ERR_UPON_FIPS_ERROR();
2372 
2373     /* check contexts pointers and tags */
2374     if (pDhUserCtx == NULL) {
2375     return CC_FFCDH_INVALID_CONTEXT_PTR_ERROR;
2376     }
2377     /* check that DhCtx is valid for user keys generation step: *
2378     *  DH Scheme, Domain and Keys are set.                      */
2379     CHECK_AND_SET_ERROR((pDhUserCtx->validTag != FFCDH_CTX_VALID_TAG_SCHEM_DATA_SET),
2380                     CC_FFCDH_CONTEXT_VALIDATION_TAG_ERROR);
2381     /* check output keying data parameters */
2382     CHECK_AND_SET_ERROR(pSecretKeyData == NULL, CC_FFCDH_KEYING_DATA_PTR_INVALID_ERROR);
2383     CHECK_AND_SET_ERROR(pSecretKeyDataSize == NULL, CC_FFCDH_KEYING_DATA_SIZE_PTR_INVALID_ERROR);
2384 
2385     /* Get internal context structure */
2386     pDhCtx = (DhContext_t*)&pDhUserCtx->contextBuff;
2387 
2388     /* get HMAC key size in bytes */
2389     CHECK_ERROR(FfcGetHashMode(NULL/*pHashMode*/, NULL/*hkdfHashMode*/, &hashBlockSize,
2390                    NULL/*pDigestSize*/, pDhCtx->ffcHashMode));
2391 
2392     /* check that given output buffer is enough for the keying data */
2393     CHECK_AND_SET_ERROR(*pSecretKeyDataSize < pDhCtx->secretKeyingDataSize,
2394                    CC_FFCDH_KEYING_DATA_SIZE_INVALID_ERROR);
2395     /*  check optional confirmation data pointers and sizes */
2396     CHECK_AND_SET_ERROR((pPartnerMacTag == NULL) != (macTagSize == 0), CC_FFCDH_OPTIONAL_DATA_ERROR);
2397 
2398     /* if confirmation is needed check appropriate parameters */
2399     if(pDhCtx->schemeInfo.doConfirmRecip == 1) {
2400         CHECK_AND_SET_ERROR(pPartnerMacTag == NULL, CC_FFCDH_MAC_TAG_PTR_INVALID_ERROR);
2401         CHECK_AND_SET_ERROR(macTagSize != pDhCtx->macTagSize, CC_FFCDH_MAC_TAG_SIZE_INVALID_ERROR);
2402 
2403     /* compare calculated partner's MacTag with received value and return error,
2404      * if they are not equaled  */
2405     CHECK_AND_SET_ERROR(CC_PalMemCmp(pPartnerMacTag, pDhCtx->partnerMacTag, macTagSize),
2406                     CC_FFCDH_MAC_TAG_DATA_INVALID_ERROR);
2407     }
2408 
2409     /* set pointer to the second part of keying material, and output the
2410      * Secret Keying Data */
2411     pKeyData = &pDhCtx->extendDataBuffer[0] + pDhCtx->dataOffsets.sharedSecrOffset + hashBlockSize;
2412     *pSecretKeyDataSize = pDhCtx->secretKeyingDataSize;
2413     CC_PalMemCopy(pSecretKeyData, pKeyData, pDhCtx->secretKeyingDataSize);
2414 
2415 End:
2416     CC_PalMemSetZero((uint8_t*)pDhUserCtx, sizeof(CCFfcDhUserContext_t));
2417 
2418 
2419     return err;
2420 
2421 }
2422 
2423 
2424 
2425 /*******************************************************************************************/
2426 /*!
2427 @brief This function implements FFC DH primitive according to section 5.7.1.1 of NIST SP 56A rev.2 standard.
2428        The function computes the shared secret value:  SharedSecretVal = partnerPublKey ^ userPrivKey modulo Prime.
2429 \note Before calling of this function the user should obtain assurance of FFC Domain, public and private keys,
2430 involved in the key agreement, using one of methods, described in section 5.6.2 of above named standard.
2431 \note For assurance of keys validity the user can use appropriate APIs for generating or building and validation,
2432 of keys, described in cc_ffcdh.h file.
2433 @return CC_OK on success.
2434 @return A non-zero value on failure as defined in cc_dh_error.h or cc_rnd_error.h.
2435 */
CC_FfcDhGetSharedSecretVal(CCFfcDomain_t * pDomain,uint8_t * pSharedSecretVal,size_t * pSharedSecretValSize,uint8_t * pPrivKeyData,size_t privKeyDataSize,uint8_t * pPublKeyData,size_t publKeyDataSize,uint32_t * pTmpBuff)2436 CEXPORT_C CCError_t CC_FfcDhGetSharedSecretVal(
2437                     CCFfcDomain_t *pDomain,         /*!< [in/out] pointer to DH FFC Context structure. */
2438                     uint8_t *pSharedSecretVal,      /*!< [out] pointer to the shared secret value in big endianness order
2439                                                               of bytes in the array (MS-byte is a most left one). This
2440                                                               buffer should be at least of prime (modulus) size in bytes. */
2441                     size_t *pSharedSecretValSize,   /*!< [in/out] pointer to the shared secret value size:
2442                                                               input - size of the given buffer, it should be at least
2443                                                               prime (modulus) size bytes; output - actual size. */
2444                     uint8_t *pPrivKeyData,          /*!< [in] pointer to given DH FFC private key in big endianness;
2445                                                               the Key should be in range [1, n-1], where n is the Domain
2446                                                               generator order. */
2447                     size_t privKeyDataSize,         /*!< [in] private key size, in bytes: should be not great than Domain
2448                                                               generator order size. */
2449                     uint8_t *pPublKeyData,          /*!< [in] pointer to given DH FFC public key in big endianness;
2450                                                               the key should be in range [2, P-2], where P is the Domain Prime. */
2451                     size_t publKeyDataSize,         /*!< [in] public key size, in bytes: should be not great than Domain Prime size. */
2452                     uint32_t *pTmpBuff              /*!< [in] pointer to temporary buffer of size = (Prime size + Order size). */
2453 )
2454 {
2455 
2456     CCError_t err = CC_OK; /* return error identifier */
2457     size_t primeSizeBytes, orderSizeBytes;
2458     size_t primeSizeWords, orderSizeWords;
2459     size_t sharSecrSizeBits;
2460     uint32_t *pPublKey32, *pPrivKey32;
2461     uint32_t word = 1; /* buffer = 1*/
2462     CCCommonCmpCounter_t cmp1, cmp2;
2463 
2464     CHECK_AND_RETURN_ERR_UPON_FIPS_ERROR();
2465 
2466     primeSizeWords = pDomain->modLenWords;
2467     orderSizeWords = pDomain->ordLenWords;
2468     primeSizeBytes = primeSizeWords * CC_32BIT_WORD_SIZE;
2469     orderSizeBytes = orderSizeWords * CC_32BIT_WORD_SIZE;
2470 
2471     /* check FFC Domain pointer and validation tag */
2472     CHECK_AND_RETURN_ERROR(pDomain == NULL, CC_FFCDH_INVALID_DOMAIN_PTR_ERROR);
2473     CHECK_AND_RETURN_ERROR((pDomain->validTag != CC_FFC_DOMAIN_VALIDATION_TAG),
2474                 CC_FFCDH_INVALID_DOMAIN_DATA_ERROR);
2475 
2476     /* check in/out data pointers */
2477     CHECK_AND_SET_ERROR((pSharedSecretVal == NULL) || (pSharedSecretValSize == NULL),
2478                  CC_FFCDH_INVALID_SHARED_SECR_VAL_PTR_ERROR);
2479     CHECK_AND_SET_ERROR(pPrivKeyData == NULL, CC_FFCDH_INVALID_PRIV_KEY_PTR_ERROR);
2480     CHECK_AND_SET_ERROR(pPublKeyData == NULL, CC_FFCDH_INVALID_PUBL_KEY_PTR_ERROR);
2481 
2482     /* check that in/out sizes meets to DH Domain parameters and buffers sizes. */
2483     CHECK_AND_SET_ERROR(*pSharedSecretValSize < primeSizeBytes, CC_FFCDH_LOW_OUTPUT_BUFF_SIZE_ERROR);
2484 
2485     /* convert public/private keys to LE words */
2486     pPublKey32 = pTmpBuff;
2487     pPrivKey32 = pPublKey32 + pDomain->modLenWords;
2488     CHECK_AND_SET_ERROR(CC_CommonConvertMsbLsbBytesToLswMswWords(
2489                      pPublKey32, primeSizeBytes, pPublKeyData, publKeyDataSize),
2490                          CC_FFCDH_INVALID_PUBLIC_KEY_SIZE_ERROR);
2491     CHECK_AND_SET_ERROR(CC_CommonConvertMsbLsbBytesToLswMswWords(
2492                      pPrivKey32, orderSizeBytes, pPrivKeyData, privKeyDataSize),
2493                          CC_FFCDH_INVALID_PRIVATE_KEY_SIZE_ERROR);
2494 
2495     /* check public key 1 < publKey < prime-1 */
2496         word = 1;
2497         pDomain->prime[pDomain->modLenWords-1] ^= 1UL; /* temporary prime -= 1; */
2498     cmp1 = CC_CommonCmpLsWordsUnsignedCounters(pPublKey32, primeSizeWords, &word, 1);
2499     cmp2 = CC_CommonCmpLsWordsUnsignedCounters(pPublKey32, primeSizeWords, pDomain->prime, primeSizeWords);
2500     pDomain->prime[primeSizeWords-1] ^= 1UL; /* reset prime */
2501     CHECK_AND_SET_ERROR((cmp1 != CC_COMMON_CmpCounter1GreaterThenCounter2) ||
2502                 (cmp2 != CC_COMMON_CmpCounter2GreaterThenCounter1),
2503                 CC_FFCDH_INVALID_PUBLIC_KEY_VALUE_ERROR );
2504 
2505     /* check private key 0 < privlKey < order */
2506     word = 0;
2507     cmp1 = CC_CommonCmpLsWordsUnsignedCounters(pPrivKey32, primeSizeWords, &word, 1);
2508     cmp2 = CC_CommonCmpLsWordsUnsignedCounters(pPrivKey32, primeSizeWords, pDomain->order, orderSizeWords);
2509     CHECK_AND_SET_ERROR((cmp1 != CC_COMMON_CmpCounter1GreaterThenCounter2) ||
2510                 (cmp2 != CC_COMMON_CmpCounter2GreaterThenCounter1),
2511                 CC_FFCDH_INVALID_PRIVATE_KEY_VALUE_ERROR);
2512 
2513     /* calc. shared secret value */
2514     CHECK_ERROR(PkiExecModExpLeW(
2515             pPublKey32/*pOut*/, pPublKey32/*pIn data*/, primeSizeWords/*inSizeWords*/,
2516                     pDomain->prime/**pMod*/, primeSizeBytes*CC_BITS_IN_BYTE /*modSizeBits*/,
2517                     pPrivKey32/*pExp*/,  orderSizeWords/*expSizeWords*/));
2518 
2519     /* get actual size of shared secret value */
2520     sharSecrSizeBits = CC_CommonGetWordsCounterEffectiveSizeInBits(pPublKey32, primeSizeWords);
2521     *pSharedSecretValSize = ROUNDUP_BITS_TO_BYTES(sharSecrSizeBits);
2522 
2523     /* output result as BE bytes array without leading zeros */
2524     CHECK_ERROR(CC_CommonConvertLswMswWordsToMsbLsbBytes(pSharedSecretVal, *pSharedSecretValSize,
2525                                                  pPublKey32, primeSizeWords));
2526 
2527 End:
2528     /* zero secret data */
2529     CC_PalMemSetZero(pTmpBuff, primeSizeBytes + orderSizeBytes);
2530     if(err) {
2531         CC_PalMemSetZero(pPrivKeyData, privKeyDataSize);
2532         CC_PalMemSetZero(pSharedSecretVal, primeSizeBytes);
2533     }
2534 
2535 
2536     return err;
2537 }
2538 
2539 
2540 
2541