1 /*
2 * Copyright (c) 2001-2019, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7
8 /************* Include Files ****************/
9
10 #include "cc_pal_mem.h"
11 #include "cc_ecpki_types.h"
12 #include "cc_common.h"
13 #include "cc_common_math.h"
14 #include "cc_ecpki_error.h"
15 #include "cc_ecpki_local.h"
16 #include "cc_fips_defs.h"
17 #include "ec_wrst.h"
18
19 /************************ Defines ***************************************/
20
21
22 /************************ Enums *****************************************/
23
24 /************************ Typedefs **************************************/
25
26 /************************ Global Data ***********************************/
27
28 /************* Private function prototype *******************************/
29
30 /************************ Public Functions ******************************/
31
CC_EcpkiPublKeyBuildAndCheck(const CCEcpkiDomain_t * pDomain,uint8_t * pPubKeyIn,size_t publKeySizeInBytes,ECPublKeyCheckMode_t checkMode,CCEcpkiUserPublKey_t * pUserPublKey,CCEcpkiBuildTempData_t * tempBuff)32 CEXPORT_C CCError_t CC_EcpkiPublKeyBuildAndCheck(
33 const CCEcpkiDomain_t *pDomain, /*in*/
34 uint8_t *pPubKeyIn, /*in*/
35 size_t publKeySizeInBytes, /*in*/
36 ECPublKeyCheckMode_t checkMode, /*in*/
37 CCEcpkiUserPublKey_t *pUserPublKey, /*out*/
38 CCEcpkiBuildTempData_t *tempBuff /*in*/)
39
40 {
41 /* FUNCTION DECLARATIONS */
42
43 /* the private key structure pointer */
44 CCEcpkiPublKey_t *pPublKey;
45 /* EC modulus size in bytes*/
46 uint32_t modSizeInBytes, modSizeInWords;
47 /* Point control pc pc and pc1 = pc&6*/
48 uint32_t pc, pc1;
49 /* the err return code identifier */
50 CCError_t err = CC_OK;
51 CCCommonCmpCounter_t cmp;
52
53 /* FUNCTION LOGIC */
54 CHECK_AND_RETURN_ERR_UPON_FIPS_ERROR();
55
56 /* ...... checking the validity of the User given pointers ......... */
57 if (pUserPublKey == NULL)
58 return CC_ECPKI_BUILD_KEY_INVALID_USER_PUBL_KEY_PTR_ERROR;
59 if (pPubKeyIn == NULL)
60 return CC_ECPKI_BUILD_KEY_INVALID_PUBL_KEY_IN_PTR_ERROR;
61 if (pDomain == NULL)
62 return CC_ECPKI_DOMAIN_PTR_ERROR;
63 /* check input values */
64 if (checkMode >= PublKeyChecingOffMode)
65 return CC_ECPKI_BUILD_KEY_INVALID_CHECK_MODE_ERROR;
66 if ((checkMode != CheckPointersAndSizesOnly) && (tempBuff == NULL))
67 return CC_ECPKI_BUILD_KEY_INVALID_TEMP_BUFF_PTR_ERROR;
68
69 /* check EC domain parameters sizes */
70 if ((pDomain->modSizeInBits > (CC_ECPKI_MODUL_MAX_LENGTH_IN_WORDS * 32)) ||
71 (pDomain->ordSizeInBits > (pDomain->modSizeInBits + 1))) {
72 return CC_ECPKI_INVALID_DATA_IN_PASSED_STRUCT_ERROR;
73 }
74
75
76 /* ...... Initializations ............... */
77
78 pPublKey = (CCEcpkiPublKey_t*)((void*)pUserPublKey->PublKeyDbBuff);
79 modSizeInBytes = CALC_FULL_BYTES(pDomain->modSizeInBits);
80 modSizeInWords = CALC_32BIT_WORDS_FROM_BYTES(modSizeInBytes);
81
82 if(modSizeInWords>=CC_ECPKI_MODUL_MAX_LENGTH_IN_WORDS){ /*To remove static analyzer warning*/
83 return CC_ECPKI_INVALID_DATA_IN_PASSED_STRUCT_ERROR;
84 }
85
86 /* point control */
87 pc = pPubKeyIn[0];
88 if (pc >= CC_EC_PointCompresOffMode || pc == CC_EC_PointContWrong)
89 return CC_ECPKI_BUILD_KEY_INVALID_COMPRESSION_MODE_ERROR;
90 pc1 = pc & 0x6; /*compression. mode*/
91
92 /* preliminary check key size */
93 if (pc1 == CC_EC_PointCompressed) {
94 if (publKeySizeInBytes != modSizeInBytes + 1)
95 return CC_ECPKI_BUILD_KEY_INVALID_PUBL_KEY_SIZE_ERROR;
96 } else {
97 if (publKeySizeInBytes != 2*modSizeInBytes + 1)
98 return CC_ECPKI_BUILD_KEY_INVALID_PUBL_KEY_SIZE_ERROR;
99 }
100
101 /* ...... copy the buffers to the key handle structure ................ */
102 /* -------------------------------------------------------------------- */
103
104 /* RL ? clear the public key db */
105 CC_PalMemSetZero((uint8_t*)pUserPublKey, sizeof(CCEcpkiUserPublKey_t));
106
107 /* copy public key Xin to X, Yin to Y */
108 err = CC_CommonConvertMsbLsbBytesToLswMswWords(pPublKey->x, sizeof(pPublKey->x),
109 pPubKeyIn + 1, modSizeInBytes);
110 if (err != CC_OK) {
111 err = CC_ECPKI_BUILD_KEY_INVALID_PUBL_KEY_DATA_ERROR;
112 goto End;
113 }
114
115 /* check public key X value */
116 cmp = CC_CommonCmpLsWordsUnsignedCounters(pPublKey->x, modSizeInWords,
117 pDomain->ecP, modSizeInWords);
118 if(cmp != CC_COMMON_CmpCounter2GreaterThenCounter1) {
119 return CC_ECPKI_BUILD_KEY_INVALID_PUBL_KEY_DATA_ERROR;
120 }
121
122 if (pc1 == CC_EC_PointUncompressed || pc1 == CC_EC_PointHybrid) {
123 /* PC1 = 4 or PC1 = 6 */
124 err = CC_CommonConvertMsbLsbBytesToLswMswWords(
125 pPublKey->y, sizeof(pPublKey->y),
126 pPubKeyIn + 1 + modSizeInBytes, modSizeInBytes);
127 if (err != CC_OK) {
128 err = CC_ECPKI_BUILD_KEY_INVALID_PUBL_KEY_DATA_ERROR;
129 goto End;
130 }
131
132 /* check public key Y value */
133 cmp = CC_CommonCmpLsWordsUnsignedCounters(pPublKey->y, modSizeInWords,
134 pDomain->ecP, modSizeInWords);
135 if(cmp != CC_COMMON_CmpCounter2GreaterThenCounter1) {
136 return CC_ECPKI_BUILD_KEY_INVALID_PUBL_KEY_DATA_ERROR;
137 }
138
139 }
140
141 /* initialize LLF public key */
142 /*-----------------------------*/
143 /* copy EC domain */
144 CC_PalMemCopy(&pPublKey->domain, pDomain, sizeof(CCEcpkiDomain_t));
145
146 /* Initialization, partly checking and uncompressing (if needed) of the public key */
147 err = EcWrstInitPubKey(pPublKey, pc);
148 if (err != CC_OK) {
149 err = CC_ECPKI_INTERNAL_ERROR;
150 goto End;
151 }
152
153
154 /* additional (full) checking of public key */
155 /*--------------------------------------------*/
156 if (checkMode == ECpublKeyFullCheck) {
157 err = EcWrstFullCheckPublKey(pPublKey, (uint32_t*)tempBuff);
158 if (err != CC_OK) {
159 goto End;
160 }
161 }
162
163
164 /* ................ set the private key validation tag ................... */
165 pUserPublKey->valid_tag = CC_ECPKI_PUBL_KEY_VALIDATION_TAG;
166
167 End:
168 /* if the created structure is not valid - clear it */
169 if (err != CC_OK) {
170 CC_PalMemSetZero(pUserPublKey, sizeof(CCEcpkiUserPublKey_t));
171 }
172 if (tempBuff != NULL) {
173 CC_PalMemSetZero(tempBuff, sizeof(CCEcpkiBuildTempData_t));
174 }
175
176 return err;
177
178
179 } /* End of CC_EcpkiPublKeyBuildAndCheck() */
180
181
182 /***********************************************************************************
183 * CC_EcpkiPubKeyExport function *
184 ***********************************************************************************/
185 /**
186 @brief The function converts an existed public key into the big endian and outputs it.
187
188 The function performs the following steps:
189 - checks input parameters,
190 - Converts the X,Y coordinates of public key EC point to big endianness.
191 - Sets the public key as follows:
192 In case "Uncompressed" point: PubKey = PC||X||Y, PC = 0x4 - single byte;
193 In other cases returns an error.
194 - Exits.
195
196 NOTE: - At this stage supported only uncompressed point form,
197 - Size of output X and Y coordinates is equal to ModSizeInBytes.
198
199 @param[in] pUserPublKey - A pointer to the public key structure initialized by CC.
200 @param[in] compression - An enumerator parameter, defines point compression.
201 @param[out] pExportPublKey - A pointer to the buffer for export the public key bytes
202 array in big endian order of bytes. Size of buffer must be
203 not less than 2*ModSiseInBytes+1 bytes.
204 @param[in/out] pPublKeySizeBytes - A pointer to size of the user passed
205 public key buffer (in) and the actual size of exported
206 public key (out).
207
208 @return CCError_t - CC_OK,
209 CC_ECPKI_EXPORT_PUBL_KEY_INVALID_USER_PUBL_KEY_PTR_ERROR
210 CC_ECPKI_EXPORT_PUBL_KEY_ILLEGAL_COMPRESSION_MODE_ERROR
211 CC_ECPKI_EXPORT_PUBL_KEY_INVALID_EXTERN_PUBL_KEY_PTR_ERROR
212 CC_ECPKI_EXPORT_PUBL_KEY_INVALID_PUBL_KEY_SIZE_PTR_ERROR
213 CC_ECPKI_EXPORT_PUBL_KEY_INVALID_PUBL_KEY_SIZE_ERROR
214 CC_ECPKI_EXPORT_PUBL_KEY_ILLEGAL_DOMAIN_ID_ERROR
215 */
CC_EcpkiPubKeyExport(CCEcpkiUserPublKey_t * pUserPublKey,CCEcpkiPointCompression_t compression,uint8_t * pExportPublKey,size_t * pPublKeySizeBytes)216 CEXPORT_C CCError_t CC_EcpkiPubKeyExport(
217 CCEcpkiUserPublKey_t *pUserPublKey, /*in*/
218 CCEcpkiPointCompression_t compression, /*in*/
219 uint8_t *pExportPublKey, /*in*/
220 size_t *pPublKeySizeBytes /*in/out*/)
221 {
222 /*-------------------- FUNCTION DECLARATIONS ------------------------*/
223
224 /* the private key structure pointer */
225 CCEcpkiPublKey_t *publKey;
226
227 /* EC modulus size in words and in bytes*/
228 uint32_t modSizeInBytes, modSizeInWords;
229 uint8_t yBit;
230
231 /* the err return code identifier */
232 CCError_t err = CC_OK;
233
234 /*............. Checking input parameters ..............................*/
235 CHECK_AND_RETURN_ERR_UPON_FIPS_ERROR();
236
237 if (pUserPublKey == NULL)
238 return CC_ECPKI_EXPORT_PUBL_KEY_INVALID_USER_PUBL_KEY_PTR_ERROR;
239
240 if (pExportPublKey == NULL)
241 return CC_ECPKI_EXPORT_PUBL_KEY_INVALID_EXTERN_PUBL_KEY_PTR_ERROR;
242
243 if (pUserPublKey->valid_tag != CC_ECPKI_PUBL_KEY_VALIDATION_TAG)
244 return CC_ECPKI_EXPORT_PUBL_KEY_ILLEGAL_VALIDATION_TAG_ERROR;
245
246 if (pPublKeySizeBytes == NULL)
247 return CC_ECPKI_EXPORT_PUBL_KEY_INVALID_PUBL_KEY_SIZE_PTR_ERROR;
248
249 if (compression == CC_EC_PointContWrong || compression >= CC_EC_PointCompresOffMode)
250 return CC_ECPKI_EXPORT_PUBL_KEY_ILLEGAL_COMPRESSION_MODE_ERROR;
251
252
253 /* FUNCTION LOGIC */
254
255 publKey = (CCEcpkiPublKey_t *)((void*)pUserPublKey->PublKeyDbBuff);
256
257 /* EC modulus size */
258 modSizeInBytes = CALC_FULL_BYTES(publKey->domain.modSizeInBits);
259 modSizeInWords = CALC_FULL_32BIT_WORDS(publKey->domain.modSizeInBits);
260
261 /* calc. MS Bit of Y */
262 yBit = (uint8_t)(publKey->y[0] & 1);
263
264 /* Convert public key to big endianness export form */
265 switch (compression) {
266 case CC_EC_PointCompressed:
267
268 if (*pPublKeySizeBytes < modSizeInBytes + 1)
269 return CC_ECPKI_EXPORT_PUBL_KEY_INVALID_PUBL_KEY_SIZE_ERROR;
270
271 /* point control byte */
272 pExportPublKey[0] = 0x02 | yBit;
273
274 err = CC_CommonConvertLswMswWordsToMsbLsbBytes(
275 pExportPublKey + 1, 4*modSizeInWords,
276 publKey->x, modSizeInBytes);
277 if (err != CC_OK) {
278 err = CC_ECPKI_EXPORT_PUBL_KEY_INVALID_PUBL_KEY_DATA_ERROR;
279 goto End;
280 }
281
282 *pPublKeySizeBytes = modSizeInBytes + 1;
283 break;
284
285 case CC_EC_PointUncompressed:
286 case CC_EC_PointHybrid:
287
288 if (*pPublKeySizeBytes < 2*modSizeInBytes + 1)
289 return CC_ECPKI_EXPORT_PUBL_KEY_INVALID_PUBL_KEY_SIZE_ERROR;
290
291 /* Point control byte */
292 if (compression == CC_EC_PointUncompressed)
293 pExportPublKey[0] = 0x04;
294 else
295 pExportPublKey[0] = (0x06 | yBit);
296
297 err = CC_CommonConvertLswMswWordsToMsbLsbBytes(
298 pExportPublKey + 1, 4*((modSizeInBytes+3)/4),
299 publKey->x, modSizeInBytes );
300 if (err != CC_OK) {
301 err = CC_ECPKI_EXPORT_PUBL_KEY_INVALID_PUBL_KEY_DATA_ERROR;
302 goto End;
303 }
304 err = CC_CommonConvertLswMswWordsToMsbLsbBytes(
305 pExportPublKey + 1 + modSizeInBytes, 4*((modSizeInBytes+3)/4),
306 publKey->y, modSizeInBytes );
307 if (err != CC_OK) {
308 err = CC_ECPKI_EXPORT_PUBL_KEY_INVALID_PUBL_KEY_DATA_ERROR;
309 goto End;
310 }
311
312 /* Set publKeySizeInBytes */
313 *pPublKeySizeBytes = 2*modSizeInBytes + 1;
314 break;
315
316 default:
317 return CC_ECPKI_EXPORT_PUBL_KEY_ILLEGAL_COMPRESSION_MODE_ERROR;
318 }
319 End:
320 if (err != CC_OK) {
321 CC_PalMemSetZero(pExportPublKey, *pPublKeySizeBytes);
322 *pPublKeySizeBytes = 0;
323 }
324 return err;
325
326 } /* End of CC_EcpkiPubKeyExport */
327
328
329
330