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