1 /*
2  * Copyright (c) 2001-2019, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 #include "cc_pal_mem.h"
7 #include "cc_pal_mutex.h"
8 #include "cc_pal_abort.h"
9 #include "cc_common_math.h"
10 #include "cc_ecpki_types.h"
11 #include "cc_ecpki_error.h"
12 #include "cc_ecpki_local.h"
13 #include "pka_hw_defs.h"
14 #include "cc_ecpki_types.h"
15 #include "pki.h"
16 #include "pka.h"
17 #include "pka_error.h"
18 #include "ec_wrst.h"
19 #include "pka_ec_wrst.h"
20 #include "ec_wrst_error.h"
21 #include "pki_modular_arithmetic.h"
22 #include "pki_dbg.h"
23 #include "cc_common.h"
24 #include "pka_point_compress_regs_def.h"
25 
26 /***********    EcWrstInitPubKey   function      **********************/
27 /**
28  *  @brief Performs uncompression (extracts Y-coordinate) checks
29  *      and inits the public key (ANS X9.62-2005).
30  *
31  * @author reuvenl (22/09/2014)
32  *
33  * @return  - On success CC_OK is returned, on failure an error code.
34  *
35  */
EcWrstInitPubKey(CCEcpkiPublKey_t * pPublKey,uint8_t pointCtl)36 CCError_t  EcWrstInitPubKey(CCEcpkiPublKey_t *pPublKey,  /*!< [in/out] Pointer to the public key structure. */
37                 uint8_t pointCtl)          /*!< [in] EC point control byte = (compression mode | Y-MSbit). */
38 {
39     CCError_t err = CC_OK;
40     uint32_t modSizeInBits, modSizeInWords;
41     CCEcpkiDomain_t *pDomain;
42     uint32_t w;
43     bool  rootExist;
44     uint32_t pkaReqRegs = PKA_MAX_COUNT_OF_PHYS_MEM_REGS;
45 
46     /* EC domain parameters */
47     pDomain = &pPublKey->domain;
48 
49     modSizeInBits = pDomain->modSizeInBits;
50     modSizeInWords = CALC_FULL_32BIT_WORDS(modSizeInBits);
51 
52     if (modSizeInWords > CC_ECPKI_MODUL_MAX_LENGTH_IN_WORDS)
53         return CC_ECPKI_BUILD_KEY_INVALID_PUBL_KEY_SIZE_ERROR;
54 
55     /*       lock mutex and init PKA  */
56     err = PkaInitAndMutexLock(modSizeInBits, &pkaReqRegs);
57     if (err != CC_OK) {
58         return err;
59     }
60 
61     /* set modulus P and Barrett tag NP into PKA registers 0,1 */
62     PkaCopyDataIntoPkaReg(PKA_REG_N/*dstReg*/, 1, pDomain->ecP, modSizeInWords);
63 
64     PkaCopyDataIntoPkaReg(PKA_REG_NP/*dstReg*/, 1, pDomain->llfBuff/*NP*/,
65         CC_PKA_BARRETT_MOD_TAG_BUFF_SIZE_IN_WORDS);
66 
67     /* set public key coordinates into PKA registers  */
68     PkaCopyDataIntoPkaReg(PKA_REG_X/*dstReg*/, 1, pPublKey->x, modSizeInWords);
69 
70     /* set EC params */
71     PkaCopyDataIntoPkaReg(PKA_REG_EC_A/*dstReg*/, 1, pDomain->ecA, modSizeInWords);
72     PkaCopyDataIntoPkaReg(PKA_REG_EC_B/*dstReg*/, 1, pDomain->ecB, modSizeInWords);
73 
74     /* calculate  y^2 for from x */
75     PKA_MOD_MUL(LEN_ID_N_BITS, PKA_REG_T/*Res*/, PKA_REG_X/*OpA*/, PKA_REG_X/*OpB*/);
76     PKA_MOD_ADD(LEN_ID_N_PKA_REG_BITS, PKA_REG_T/*Res*/, PKA_REG_T/*OpA*/, PKA_REG_EC_A/*OpB*/);
77     PKA_MOD_MUL(LEN_ID_N_BITS, PKA_REG_T/*Res*/, PKA_REG_X/*OpA*/, PKA_REG_T/*OpB*/);
78     PKA_MOD_ADD(LEN_ID_N_PKA_REG_BITS, PKA_REG_Y2/*=PKA_REG_EC_A*/, PKA_REG_T/*OpA*/, PKA_REG_EC_B/*OpB*/);
79 
80     if((pointCtl & 6) != 2) {
81         /*   Partly check uncompressed key (is it on curve ?)  */
82         /* calculate y^2 directly */
83         PkaCopyDataIntoPkaReg(PKA_REG_Y/*dstReg*/, 1, pPublKey->y, modSizeInWords);
84         PKA_MOD_MUL(LEN_ID_N_BITS, PKA_REG_T, PKA_REG_Y, PKA_REG_Y);
85         PKA_COMPARE_STATUS(LEN_ID_N_PKA_REG_BITS, PKA_REG_Y2, PKA_REG_T, w/*stat*/);
86         if(w != 1) {
87             err = CC_ECPKI_BUILD_KEY_INVALID_PUBL_KEY_DATA_ERROR;
88             goto End;
89         }
90     }
91     else {
92         /*    Uncompress the Y coordinate if needed            */
93                 /* derive modular square root (in/out registers according to  *
94                 *  included definitions file                                  */
95                 /*implicit parameterss: PKA_REG_Y(PKA_REG_Y1)=3(out), PKA_REG_Y2(PKA_REG_EC_A)=4(in),      *
96                 * PKA_REG_N=0(in)                                                    */
97         rootExist = PkiIsModSquareRootExists();
98 
99                 /* check is the root exists */
100                 if(rootExist != true){
101             err = PKA_MOD_SQUARE_ROOT_NOT_EXIST_ERROR;
102             goto End;
103         }
104 
105                 /* check Y LS-bit and set Y = -Y if need */
106         PKA_READ_WORD_FROM_REG(w, 0, PKA_REG_Y);
107         if((w & 1) != (pointCtl & 1)) {
108             PKA_SUB(LEN_ID_N_PKA_REG_BITS, PKA_REG_Y, PKA_REG_N, PKA_REG_Y);
109         }
110 
111                 /* copy Y-coordinate */
112         PkaCopyDataFromPkaReg(pPublKey->y/*dst*/, modSizeInWords, PKA_REG_Y/*src reg*/);
113     }
114 
115 End:
116     PkaFinishAndMutexUnlock(pkaReqRegs);
117     return err;
118 
119 }
120 
121 
122 /***********     EcWrstFullCheckPublKey  function      **********************/
123 /**
124  * @brief  Checks that the public key is valid point belonging to EC group.
125  *
126  *       Assuming: partly check (sizes, point is on curve) of the public key
127  *                 was done previously.
128  *
129  * @return  - On success CC_OK is returned, on failure an error code.
130  *
131 */
EcWrstFullCheckPublKey(CCEcpkiPublKey_t * pPublKey,uint32_t * pTempBuff)132 CCError_t  EcWrstFullCheckPublKey( CCEcpkiPublKey_t    *pPublKey,    /*!< [in] Pointer to the public key structure. */
133                     uint32_t             *pTempBuff) /*!< [in] Pointer to itemp buffer of size not less 2*modulusSize. */
134 {
135     CCError_t err = CC_OK;
136     uint32_t ordSizeInWords, modSizeInWords, sizeBits;
137         uint32_t *outPointX, *outPointY;
138         uint32_t *pTmpForFunc;
139 
140         modSizeInWords = CALC_FULL_32BIT_WORDS(pPublKey->domain.modSizeInBits);
141         ordSizeInWords = CALC_FULL_32BIT_WORDS(pPublKey->domain.ordSizeInBits);
142 
143         /* scalar mult. resut coordinates  */
144     outPointX = pTempBuff;
145         outPointY = outPointX + modSizeInWords;
146         pTmpForFunc = outPointY + modSizeInWords;
147 
148 
149         /* scalar mult publ.key point by EC generator order ecR */
150         err = PkaEcWrstScalarMult(
151                                 &pPublKey->domain,
152                                 pPublKey->domain.ecR, /*in*/
153                                 ordSizeInWords,       /*in - publ key X*/
154                                 pPublKey->x,          /*in - publ key Y*/
155                                 pPublKey->y,          /*in*/
156                                 outPointX,            /*out*/
157                                 outPointY,            /*out*/
158                                 pTmpForFunc);
159         if(err) {
160                 err = CC_ECPKI_INTERNAL_ERROR;
161                 goto End;
162         }
163 
164         /* check that out point is on infinity, i.e. X=0 && Y=0 */
165         sizeBits = CC_CommonGetWordsCounterEffectiveSizeInBits(outPointY, modSizeInWords);
166         if(sizeBits > 0){
167                 err = CC_ECPKI_BUILD_KEY_INVALID_PUBL_KEY_DATA_ERROR;
168                 goto End;
169         }
170         /* check condition for X */
171         sizeBits = CC_CommonGetWordsCounterEffectiveSizeInBits(outPointX, modSizeInWords);
172         if(sizeBits > 0){
173                 err = CC_ECPKI_BUILD_KEY_INVALID_PUBL_KEY_DATA_ERROR;
174                 goto End;
175         }
176 
177 End:
178     return err;
179 }
180 
181 
182 /***********     EcWrstDhDeriveSharedSecret  function      **********************/
183 /**
184  * @brief  Derives shared secrete value from provided keys. called also SVDP_DH
185  *
186  * @return  - On success CC_OK is returned, on failure an error code.
187  *
188 */
EcWrstDhDeriveSharedSecret(CCEcpkiPublKey_t * pPublKey,CCEcpkiPrivKey_t * pPrivKey,uint8_t * pSharedSecretValue,CCEcdhTempData_t * pTempBuff)189 CCError_t  EcWrstDhDeriveSharedSecret(CCEcpkiPublKey_t    *pPublKey,          /*!< [in] Pointer to the public key structure. */
190                     CCEcpkiPrivKey_t    *pPrivKey,        /*!< [in] Pointer to the private key structure. */
191                     uint8_t                 *pSharedSecretValue,  /*!< [out] Pointer to buffer for Shared Secret Value of size
192                                                  not less than modulusSize in words. */
193                     CCEcdhTempData_t    *pTempBuff)       /*!< [in] Pointer to temp buffer. */
194 {
195     CCError_t err;
196     uint32_t ordSizeInWords, modSizeInWords, modSizeInBytes;
197         uint32_t *outPointX, *outPointY;
198         uint32_t *pTmpForFunc;
199 
200         modSizeInWords = CALC_FULL_32BIT_WORDS(pPublKey->domain.modSizeInBits);
201         ordSizeInWords = CALC_FULL_32BIT_WORDS(pPublKey->domain.ordSizeInBits);
202         modSizeInBytes = CALC_FULL_BYTES(pPublKey->domain.modSizeInBits);
203 
204         /* scalar mult. resut coordinates  */
205     outPointX = (uint32_t*)pTempBuff;
206         outPointY = outPointX + modSizeInWords;
207         pTmpForFunc = outPointY + modSizeInWords;
208 
209         /* scalar mult publ.key point by EC generator order ecR */
210         err = PkaEcWrstScalarMult(
211                                 &pPublKey->domain,
212                                 pPrivKey->PrivKey,    /*in*/
213                                 ordSizeInWords,       /*in - publ key X*/
214                                 pPublKey->x,          /*in - publ key Y*/
215                                 pPublKey->y,          /*in*/
216                                 outPointX,            /*out*/
217                                 outPointY,            /*out*/
218                                 pTmpForFunc);         /*in*/
219         if(err)
220                 goto End;
221 
222         /* Note: Because output of scalar mult result point in affine         *
223         *  form,there no need to check, that coordinates X,Y <= mod-1.        */
224         /* Check that out point is not on infinity, i.e. X,Y != 0             */
225         if(CC_CommonGetWordsCounterEffectiveSizeInBits(outPointY, modSizeInWords) == 0  ||
226            CC_CommonGetWordsCounterEffectiveSizeInBits(outPointX, modSizeInWords) == 0){
227                 err = ECWRST_DH_SHARED_VALUE_IS_ON_INFINITY_ERROR;
228                 goto End;
229         } else {
230                 /* copy X-coordinate of SecrP to output */
231                 CC_CommonReverseMemcpy(pSharedSecretValue, (uint8_t*)outPointX, modSizeInBytes);
232         }
233 
234 End:
235         CC_PalMemSetZero ( pTempBuff, sizeof(CCEcdhTempData_t) );
236     return err;
237 
238 }
239 
240 
241 
242