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