1 /*
2  * Copyright (c) 2001-2020, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <string.h>
8 #include "cc_pal_types.h"
9 #include "cc_pal_mem.h"
10 #include "cc_hash_defs.h"
11 #include "cc_common.h"
12 #include "cc_rnd_error.h"
13 #include "cc_ec_mont_api.h"
14 #include "mbedtls_cc_ec_mont_edw_error.h"
15 #include "ec_mont_local.h"
16 #include "ec_mont.h"
17 #include "cc_general_defs.h"
18 #include "mbedtls/md.h"
19 
20 // RL Debug
21 #include "pki_dbg.h"
22 
23 /******************************************************************************/
24 /*!
25    The function performs EC Montgomery scalar multiplication:
26          resPoint = scalar * point.<br>
27   <br>
28          Note: all byte arrays have LE order of bytes, i.e. LS byte is on left most place.<br>
29   <br>
30   return CCError_t
31 */
CC_EcMontScalarmult(uint8_t * pResPoint,size_t * pResPointSize,const uint8_t * pScalar,size_t scalarSize,const uint8_t * pInPoint,size_t inPointSize,CCEcMontTempBuff_t * pEcMontTempBuff)32 CEXPORT_C CCError_t CC_EcMontScalarmult(
33                                 uint8_t       *pResPoint,       /*!< [out] Pointer to the public (secret) key. */
34                                 size_t        *pResPointSize,   /*!< [in/out] Pointer to the size of the public key in bytes.
35                                                                        In  - the size of the buffer. must be at least EC modulus
36                                                                              size (for curve25519 - 32 bytes).
37                                                                        Out - the actual size. */
38                                 const uint8_t *pScalar,         /*!< [in] Pointer to the secret (private) key. */
39                                 size_t         scalarSize,      /*!< [in] Pointer to the size of the secret key in bytes;
40                                                                      must be equal to EC order size (for curve25519 - 32 bytes). */
41                                 const uint8_t *pInPoint,        /*!< [in] Pointer to the input point (compressed). */
42                                 size_t         inPointSize,     /*!< [in] Size of the point - must be equal to CC_EC_MONT_MOD_SIZE_IN_BYTES. */
43                                 CCEcMontTempBuff_t *pEcMontTempBuff)  /*!< [in] pointer temp buffer. */
44 {
45         CCError_t err = CC_OK;
46         /* pointers to aligned buffers */
47         uint32_t *pResPoint32, *pScalar32, *pInPoint32;
48         size_t ecOrdSizeBytes, ecModSizeBytes;
49         size_t scalarSizeWords;
50         /* the pointer to EC domain (curve). */
51         const CCEcMontDomain_t *pEcDomain;
52         uint32_t ls, ms;
53 
54 
55         if (pResPoint == NULL || pResPointSize == NULL ||
56             pScalar == NULL || pInPoint == NULL ||
57             pEcMontTempBuff == NULL) {
58                 return CC_EC_MONT_INVALID_INPUT_POINTER_ERROR;
59         }
60 
61         /* get domain */
62         pEcDomain = EcMontGetCurve25519Domain();
63 
64 
65         /* set EC domain parameters sizes */
66         scalarSizeWords = pEcDomain->ecOrdSizeInWords;
67         ecModSizeBytes = pEcDomain->ecModSizeInWords * sizeof(uint32_t);
68         ecOrdSizeBytes = pEcDomain->ecOrdSizeInWords * sizeof(uint32_t);
69 
70         /* check sizes */
71         if (*pResPointSize < ecModSizeBytes ||
72             inPointSize != ecModSizeBytes  ||
73             scalarSize != ecOrdSizeBytes) {
74                 return CC_EC_MONT_INVALID_INPUT_SIZE_ERROR;
75         }
76 
77         /* set pointers to temp buffer */
78         pScalar32 = pEcMontTempBuff->ecMontScalar;
79         pResPoint32 = pEcMontTempBuff->ecMontResPoint;
80         pInPoint32 = pEcMontTempBuff->ecMontInPoint;
81 
82         /* convert input byte arrays to LE word arrays */
83         CC_CommonConvertLsbMsbBytesToLswMswWords(pScalar32, (uint8_t*)pScalar, scalarSize);
84         CC_CommonConvertLsbMsbBytesToLswMswWords(pInPoint32, (uint8_t*)pInPoint, ecModSizeBytes);
85 
86         /* revert changed bytes in the scalar */
87         ls = pScalar32[0]; ms = pScalar32[scalarSizeWords-1];
88 
89         /* set scalar bits according to EC Montgomery curve25519 algorithm:
90            byte[31] = (byte[31] & 127) | 64; byte[0] &= 248; */
91         pScalar32[scalarSizeWords-1] = (pScalar32[scalarSizeWords-1] & 0x7FFFFFFF) | 0x40000000;
92         pScalar32[0] &= 0xFFFFFFF8;
93 
94         /* call llf pScalar multiplication function */
95         err = EcMontScalarmult(
96                               pResPoint32,
97                               pScalar32,
98                               pInPoint32,
99                               pEcDomain);
100         if (err) {
101                 err = CC_ECMONT_INTERNAL_ERROR;
102                 goto EndWithError;
103         }
104 
105         /* revert changed bytes in the scalar */
106         pScalar32[0] = ls; pScalar32[scalarSizeWords-1] = ms;
107 
108         /* output pResPoint to LE bytes array */
109         CC_CommonConvertLswMswWordsToLsbMsbBytes(pResPoint, pResPoint32, pEcDomain->ecModSizeInWords);
110         *pResPointSize = ecModSizeBytes;
111 
112         EndWithError:
113         /* zeroing temp buffers, they are not used as input/output */
114         if ((uint8_t*)pScalar32 != pScalar) {
115                 CC_PalMemSetZero((uint8_t*)pScalar32, ecModSizeBytes);
116         }
117         if ((uint8_t*)pResPoint32 != pResPoint) {
118                 CC_PalMemSetZero((uint8_t*)pResPoint32, ecModSizeBytes);
119         }
120         if ((uint8_t*)pInPoint32 != pInPoint) {
121                 CC_PalMemSetZero((uint8_t*)pInPoint32, ecModSizeBytes);
122         }
123 
124         CC_PalMemSetZero(&pEcMontTempBuff->ecMontScalrMultTempBuff, sizeof(CCEcMontScalrMultTempBuff_t));
125         return err;
126 
127 }
128 
129 /*********************************************************************/
130 /*!
131 @brief The function performs EC Montgomery (Curve25519) scalar multiplication of base point:
132        res = scalar * base_point.
133 
134        Note: all byte arrays have LE order of bytes, i.e. LS byte is on left most place.
135 
136 
137 @return CC_OK on success,
138 @return A non-zero value on failure as defined mbedtls_cc_ec_mont_edw_error.h.
139 */
140 
CC_EcMontScalarmultBase(uint8_t * pResPoint,size_t * pResPointSize,const uint8_t * pScalar,size_t scalarSize,CCEcMontTempBuff_t * pEcMontTempBuff)141 CEXPORT_C CCError_t CC_EcMontScalarmultBase(
142                                 uint8_t       *pResPoint,      /*!< [out] Pointer to the public (secret) key. */
143                                 size_t        *pResPointSize,  /*!< [in/out] Pointer to the size of the public key in bytes.
144                                                                       In  - the size of buffer must be at least EC modulus size
145                                                                           (for curve25519 - 32 bytes);
146                                                                       Out - the actual size. */
147                                 const uint8_t *pScalar,        /*!< [in] Pointer to the secret (private) key. */
148                                 size_t         scalarSize,     /*!< [in] Pointer to the size of the scalar in bytes -
149                                                                     must be equal to EC order size (for curve25519 - 32 bytes). */
150                                 CCEcMontTempBuff_t *pEcMontTempBuff) /*!< [in] pointer to the temp buffer. */
151 {
152         CCError_t err = CC_OK;
153         /* pointers to aligned buffers */
154         uint32_t *pResPoint32, *pScalar32;
155         size_t ecOrdSizeBytes, ecModSizeBytes;
156         size_t scalarSizeWords;
157         const CCEcMontDomain_t *pEcDomain;
158         uint32_t ls, ms;
159 
160         /* check parameters */
161         if (pResPoint  == NULL || pResPointSize == NULL ||
162             pScalar == NULL || pEcMontTempBuff == NULL) {
163                 return CC_EC_MONT_INVALID_INPUT_POINTER_ERROR;
164         }
165 
166         /* get domain */
167         pEcDomain = EcMontGetCurve25519Domain();
168 
169         /* set EC domain parameters sizes */
170         scalarSizeWords = pEcDomain->ecOrdSizeInWords;
171         ecModSizeBytes = pEcDomain->ecModSizeInWords * sizeof(uint32_t);
172         ecOrdSizeBytes = scalarSizeWords * sizeof(uint32_t);
173 
174         /* check sizes */
175         if (*pResPointSize < ecModSizeBytes ||
176             scalarSize != ecOrdSizeBytes) {
177                 return CC_EC_MONT_INVALID_INPUT_SIZE_ERROR;
178         }
179 
180         /* set pointers to temp buffer */
181         pScalar32 = pEcMontTempBuff->ecMontScalar;
182         pResPoint32 = pEcMontTempBuff->ecMontResPoint;
183 
184         /* convert input byte arrays to LE word arrays */
185         CC_CommonConvertLsbMsbBytesToLswMswWords(pScalar32, (uint8_t*)pScalar, scalarSize);
186 
187         /* revert changed bytes in the scalar */
188         ls = pScalar32[0]; ms = pScalar32[scalarSizeWords-1];
189 
190         /* set scalar bits according to EC Montgomery curve25519 algorithm:
191            byte[31] = (byte[31] & 127) | 64; byte[0] &= 248; */
192         pScalar32[scalarSizeWords-1] = (pScalar32[scalarSizeWords-1] & 0x7FFFFFFF) | 0x40000000;
193         pScalar32[0] &= 0xFFFFFFF8;
194 
195         /* call llf pScalar multiplication function */
196         err = EcMontScalarmult(
197                               pResPoint32,
198                               pScalar32,
199                               (uint32_t*)pEcDomain->ecGenX,
200                               pEcDomain);
201         if (err) {
202                 err = CC_ECMONT_INTERNAL_ERROR;
203                 goto EndWithError;
204         }
205 
206         /* revert changed bytes in the scalar */
207         pScalar32[0] = ls; pScalar32[scalarSizeWords-1] = ms;
208 
209         /* output pResPoint to LE bytes array */
210         CC_CommonConvertLswMswWordsToLsbMsbBytes(pResPoint, pResPoint32,
211                                                     pEcDomain->ecModSizeInWords);
212         *pResPointSize = ecModSizeBytes;
213 
214 
215         EndWithError:
216         /* zeroing temp buffers if they are not used as input/output */
217         if ((uint8_t*)pScalar32 != pScalar) {
218                 CC_PalMemSetZero((uint8_t*)pScalar32, ecModSizeBytes);
219         }
220         if ((uint8_t*)pResPoint32 != pResPoint) {
221                 CC_PalMemSetZero((uint8_t*)pResPoint32, ecModSizeBytes);
222         }
223 
224         return err;
225 
226 }
227 /********************************************************************/
228 
ecMontKeyPairBase(uint8_t * pPublKey,size_t * pPublKeySize,uint8_t * pSecrKey,size_t * pSecrKeySize,const uint8_t * pInPoint,CCRndContext_t * pRndContext,CCEcMontTempBuff_t * pEcMontTempBuff)229 static CCError_t ecMontKeyPairBase (
230                               uint8_t *pPublKey,                    /*!< [out] Pointer to the public key. */
231                               size_t  *pPublKeySize,                /*!< [in/out] Pointer to the size of the public key in bytes
232                                                                     In  - the size of the buffer must be at least EC order size
233                                                                    (for curve25519 - 32 bytes);
234                                                                                      Out - the actual size. */
235                               uint8_t *pSecrKey,                    /*!< [out] Pointer to the secret key, including. */
236                               size_t  *pSecrKeySize,                /*!< [in/out] Pointer to the size of buffer for the secret key in bytes -
237                                                                                     must be at least EC order size (for curve25519 - 32 bytes). */
238                               const uint8_t *pInPoint,        /*!< [in] Pointer to the input point (compressed). must be of size CC_EC_MONT_MOD_SIZE_IN_BYTES */
239                               CCRndContext_t *pRndContext,      /*!< [in/out] Pointer to the RND context buffer. */
240                               CCEcMontTempBuff_t *pEcMontTempBuff) /*!< [in] pointer to EC domain (curve). */
241 {
242         /* DEFINITIONS */
243 
244         CCError_t err = CC_OK;
245         uint32_t ecScalarSizeBytes, ecModSizeBytes;
246         CCRndGenerateVectWorkFunc_t RndGenerateVectFunc;
247         /* the pointer to EC domain (curve). */
248         const CCEcMontDomain_t *pEcDomain;
249 
250 
251         /* FUNCTION LOGIC */
252 
253         /* check input parameters */
254         if (pSecrKey  == NULL || pSecrKeySize == NULL ||
255             pPublKey  == NULL || pPublKeySize == NULL ||
256             pRndContext == NULL || pEcMontTempBuff == NULL) {
257                 return CC_EC_MONT_INVALID_INPUT_POINTER_ERROR;
258         }
259 
260         /* get domain */
261         pEcDomain = EcMontGetCurve25519Domain();
262 
263         /* EC pScalar size in bytes */
264         ecScalarSizeBytes = pEcDomain->ecOrdSizeInWords * sizeof(uint32_t);
265         ecModSizeBytes = pEcDomain->ecModSizeInWords * sizeof(uint32_t);
266 
267         if (*pSecrKeySize < ecScalarSizeBytes ||
268             *pPublKeySize < ecScalarSizeBytes) {
269                 return CC_EC_MONT_INVALID_INPUT_SIZE_ERROR;
270         }
271 
272         /* generaate secret key (seed) */
273         RndGenerateVectFunc = pRndContext->rndGenerateVectFunc;
274         if(RndGenerateVectFunc == NULL)
275                 return CC_RND_GEN_VECTOR_FUNC_ERROR;
276 
277         err = RndGenerateVectFunc(
278                         (void *)pRndContext->rndState,
279                         (unsigned char *)pSecrKey,
280                         (size_t)ecScalarSizeBytes);
281         if (err) {
282                 goto End;
283         }
284 
285         *pPublKeySize = ecModSizeBytes;
286 
287         /* calculate public key by pScalar mult. */
288         if (pInPoint != NULL)
289         {
290             err = CC_EcMontScalarmult(
291                                     pPublKey,
292                                     pPublKeySize,
293                                     pSecrKey,
294                                     ecScalarSizeBytes,
295                                     pInPoint,
296                                     CC_EC_MONT_MOD_SIZE_IN_BYTES,
297                                     pEcMontTempBuff);
298         }
299         else /* use the curve base point*/
300         {
301             err = CC_EcMontScalarmultBase(
302                                     pPublKey,
303                                     pPublKeySize,
304                                     pSecrKey,
305                                     ecScalarSizeBytes,
306                                     pEcMontTempBuff);
307         }
308         if (err) {
309                 goto End;
310         }
311 
312         /* output results */
313         *pSecrKeySize = ecScalarSizeBytes;
314 
315         End:
316 
317         CC_PalMemSetZero(pEcMontTempBuff, sizeof(CCEcMontTempBuff_t));
318 
319         if (err) {
320                 CC_PalMemSetZero(pPublKey, ecModSizeBytes);
321                 CC_PalMemSetZero(pSecrKey, ecScalarSizeBytes);
322         }
323         return err;
324 
325 }
326 
327 
328 /*******************************************************************/
329 /*!
330 @brief The function randomly generates  private and public keys for Montgomery
331        Curve25519, with a configurable base point.
332 
333 
334 \note All byte arrays are in LE order of bytes, i.e. LS byte is on the left most place. \par
335 \note LS and MS bits of the Secret key are set according to EC Montgomery scalar mult. algorithm:
336                 secrKey[0] &= 248; secrKey[31] &= 127; secrKey[31] |= 64;
337 
338 @return CC_OK on success,
339 @return A non-zero value on failure as defined mbedtls_cc_ec_mont_edw_error.h.
340 
341 */
CC_EcMontKeyPairBase(uint8_t * pPublKey,size_t * pPublKeySize,uint8_t * pSecrKey,size_t * pSecrKeySize,const uint8_t * pInPoint,size_t inPointSize,CCRndContext_t * pRndContext,CCEcMontTempBuff_t * pEcMontTempBuff)342 CEXPORT_C CCError_t CC_EcMontKeyPairBase(
343                                          uint8_t *pPublKey,                    /*!< [out] Pointer to the public key. */
344                                          size_t  *pPublKeySize,                /*!< [in/out] Pointer to the size of the public key in bytes.
345                                                                                      In  - the size of the buffer must be at least EC order size
346                                                                                            (for curve25519 - 32 bytes);
347                                                                                      Out - the actual size. */
348                                          uint8_t *pSecrKey,                    /*!< [out] Pointer to the secret key, including. */
349                                          size_t  *pSecrKeySize,                /*!< [in/out] Pointer to the size of buffer for the secret key in bytes -
350                                                                                     must be at least EC order size (for curve25519 - 32 bytes). */
351                                          const uint8_t *pInPoint,        /*!< [in] Pointer to the input point (compressed). */
352                                          size_t         inPointSize,     /*!< [in] Size of the point - must be equal to CC_EC_MONT_MOD_SIZE_IN_BYTES. */
353                                          CCRndContext_t *pRndContext,      /*!< [in/out] Pointer to the RND context buffer. */
354                                          CCEcMontTempBuff_t *pEcMontTempBuff) /*!< [in] pointer to EC domain (curve). */
355 {
356     if (inPointSize != CC_EC_MONT_MOD_SIZE_IN_BYTES)
357     {
358         return CC_EC_MONT_INVALID_INPUT_SIZE_ERROR;
359     }
360 
361     return ecMontKeyPairBase(pPublKey, pPublKeySize, pSecrKey, pSecrKeySize, pInPoint, pRndContext, pEcMontTempBuff);
362 }
363 
364 /*******************************************************************/
365 /*!
366 @brief The function randomly generates  private and public keys for Montgomery
367        Curve25519. it uses CC_EcMontKeyPair with the Generator point of the Curve
368 
369 
370 \note All byte arrays are in LE order of bytes, i.e. LS byte is on the left most place. \par
371 \note LS and MS bits of the Secret key are set according to EC Montgomery scalar mult. algorithm:
372                 secrKey[0] &= 248; secrKey[31] &= 127; secrKey[31] |= 64;
373 
374 @return CC_OK on success,
375 @return A non-zero value on failure as defined mbedtls_cc_ec_mont_edw_error.h.
376 
377 */
CC_EcMontKeyPair(uint8_t * pPublKey,size_t * pPublKeySize,uint8_t * pSecrKey,size_t * pSecrKeySize,CCRndContext_t * pRndContext,CCEcMontTempBuff_t * pEcMontTempBuff)378 CEXPORT_C CCError_t CC_EcMontKeyPair(
379                                          uint8_t *pPublKey,                    /*!< [out] Pointer to the public key. */
380                                          size_t  *pPublKeySize,                /*!< [in/out] Pointer to the size of the public key in bytes.
381                                                                                      In  - the size of the buffer must be at least EC order size
382                                                                                           (for curve25519 - 32 bytes);
383                                                                                      Out - the actual size. */
384                                          uint8_t *pSecrKey,                    /*!< [out] Pointer to the secret key, including. */
385                                          size_t  *pSecrKeySize,                /*!< [in/out] Pointer to the size of buffer for the secret key in bytes -
386                                                                                     must be at least EC order size (for curve25519 - 32 bytes). */
387                                          CCRndContext_t *pRndContext,      /*!< [in/out] Pointer to the RND context buffer. */
388                                          CCEcMontTempBuff_t *pEcMontTempBuff) /*!< [in] pointer to EC domain (curve). */
389 {
390 
391     return ecMontKeyPairBase(pPublKey, pPublKeySize, pSecrKey, pSecrKeySize, NULL, pRndContext, pEcMontTempBuff);
392 }
393 
394 /*******************************************************************/
395 /**
396 @brief The function generates private and public keys for Montgomery Curve25519
397        using given seed.
398 
399        Note: all byte arrays have LE order of bytes, i.e. LS byte is on left most place.
400 
401 @return CC_OK on success,
402 @return a non-zero value on failure as defined mbedtls_cc_ec_mont_edw_error.h.
403 */
CC_EcMontSeedKeyPair(uint8_t * pPublKey,size_t * pPublKeySize,uint8_t * pSecrKey,size_t * pSecrKeySize,const uint8_t * pSeed,size_t seedSize,CCEcMontTempBuff_t * pEcMontTempBuff)404 CEXPORT_C CCError_t CC_EcMontSeedKeyPair (
405                       uint8_t       *pPublKey,       /*!< [out] Pointer to the public (secret) key. */
406                       size_t        *pPublKeySize,   /*!< [in/out] Pointer to the size of the public key in bytes.
407                                                              In  - the size of buffer must be at least EC order size
408                                                                 (for curve25519 - 32 bytes);
409                                                              Out - the actual size. */
410                       uint8_t       *pSecrKey,       /*!< [out] Pointer to the secret (private) key. */
411                       size_t        *pSecrKeySize,   /*!< [in/out] Pointer to the size of the secret key in bytes
412                                                               In  - the size of buffer must be at least EC order size
413                                                                 (for curve25519 - 32 bytes);
414                                                               Out - the actual size. */
415                       const uint8_t *pSeed,          /*!< [in] Pointer to the given seed - 32 bytes. */
416                       size_t         seedSize,       /*!< [in/] Size of the seed in bytes (must be equal to CC_EC_MONT_SEEDBYTES). */
417                       CCEcMontTempBuff_t *pEcMontTempBuff)  /*!< [in] pointer temp buffer. */
418 {
419         /* DEFINITIONS */
420 
421         CCError_t err = CC_OK;
422         uint8_t *pScalar, *pRes;
423         CCHashResultBuf_t *pHashResult; /*takes 64 bytes in pEcMontTempBuff*/
424         uint32_t ecOrdSizeBytes, ecMontSizeBytes;
425         /* the pointer to EC domain (curve). */
426         const CCEcMontDomain_t *pEcDomain;
427         const mbedtls_md_info_t *md_info=NULL;
428 
429         /* FUNCTION LOGIC */
430 
431 
432         /* check input parameters */
433         if (pSecrKey  == NULL || pSecrKeySize == NULL ||
434             pPublKey == NULL || pPublKeySize == NULL ||
435             pSeed == NULL || pEcMontTempBuff == NULL) {
436                 return CC_EC_MONT_INVALID_INPUT_POINTER_ERROR;
437         }
438 
439         /* get domain */
440         pEcDomain = EcMontGetCurve25519Domain();
441 
442         ecOrdSizeBytes = pEcDomain->ecOrdSizeInWords*sizeof(uint32_t);
443         ecMontSizeBytes = pEcDomain->ecModSizeInWords*sizeof(uint32_t);
444 
445         if (*pSecrKeySize < ecOrdSizeBytes ||
446              seedSize != ecOrdSizeBytes) {
447                 return CC_EC_MONT_INVALID_INPUT_SIZE_ERROR;
448         }
449 
450         pHashResult = (CCHashResultBuf_t*)pEcMontTempBuff;
451         pScalar = (uint8_t*)&pEcMontTempBuff->ecMontScalar;
452         pRes = (uint8_t*)&pEcMontTempBuff->ecMontResPoint;
453 
454         /* copy seed into buffer with phys. memory (HW HASH requirement) */
455         CC_PalMemCopy(pScalar, pSeed, seedSize);
456 
457         /* calculate secret key; note pScalar points  *
458         *  to the same mem. as pHashResult            */
459         md_info = mbedtls_md_info_from_string( HashAlgMode2mbedtlsString[CC_HASH_SHA512_mode] );
460         if (NULL == md_info) {
461              err = CC_EC_MONT_INVALID_INPUT_SIZE_ERROR;
462              goto End;
463 
464         }
465         err = mbedtls_md(md_info,
466                          pScalar,
467                          seedSize,
468                         (unsigned char *)(*pHashResult));
469         if (err) {
470                 goto End;
471         }
472 
473         /* calculate the public key */
474         err = CC_EcMontScalarmultBase(
475                                 (uint8_t*)&pEcMontTempBuff->ecMontResPoint[0],
476                                 pPublKeySize,
477                                 pScalar,  // check endianness !
478                                 ecOrdSizeBytes,
479                                 pEcMontTempBuff);
480 
481         if (err) {
482                 goto End;
483         }
484 
485         /* set actual sizes of Secr. and publ. keys */
486         *pSecrKeySize = ecOrdSizeBytes;
487         *pPublKeySize = ecMontSizeBytes;
488 
489         /* output secret and publ. keys */
490         CC_PalMemCopy(pSecrKey, (uint8_t*)pScalar, *pSecrKeySize);
491         CC_PalMemCopy(pPublKey, pRes, *pPublKeySize);
492 
493         End:
494         /* clean the temp buffers */
495         CC_PalMemSetZero((uint8_t*)pEcMontTempBuff, sizeof(CCEcMontTempBuff_t));
496         if (err) {
497                 CC_PalMemSetZero(pSecrKey, ecOrdSizeBytes);
498                 CC_PalMemSetZero(pPublKey, ecMontSizeBytes);
499         }
500 
501         return err;
502 }
503 
504