1 /*
2  * Copyright (c) 2001-2022, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifdef CC_IOT
8 #include "mbedtls/build_info.h"
9 #endif
10 
11 #if !defined(CC_IOT) || ( defined(CC_IOT) && defined(MBEDTLS_RSA_C))
12 
13 
14 /************* Include Files ****************/
15 
16 #include "cc_rsa_error.h"
17 #include "cc_rsa_types.h"
18 #include "pka.h"
19 #include "pki.h"
20 #include "cc_pal_mutex.h"
21 #include "pka_error.h"
22 #include "rsa.h"
23 #include "rsa_private.h"
24 
25 extern const int8_t regTemps[PKA_MAX_COUNT_OF_PHYS_MEM_REGS];
26 
27 
28 /***********     RsaExecPrivKeyExpNonCrt  function      **********************/
29 /**
30  * @brief Executes the RSA primitive: private key CRT exponent
31  *
32  *    Algorithm [PKCS #1 v2.1]:
33  *
34  *     1. If NonCRT exponent, then  M  =  C^D  mod N.
35  *
36  *     Where: M- message representative, C- ciphertext, D- priv.exponent, N- modulus,
37  *            ^ - exponentiation symbol.
38  *
39  *     Note: PKA registers used: r0,r1,r2,r3,r4,  r30,r31.
40  *
41  * @return  CC_OK On success, otherwise indicates failure
42  */
RsaExecPrivKeyExpNonCrt(CCRsaPrivKey_t * pPrivKey,CCRsaPrimeData_t * pPrivData)43 static CCError_t RsaExecPrivKeyExpNonCrt(CCRsaPrivKey_t    *pPrivKey , /*!< [in]  Private key database. */
44                      CCRsaPrimeData_t *pPrivData)       /*!< [in/out]  Containing DataIn and DataOut buffers. */
45 {
46     CCError_t error = CC_OK;
47     uint32_t modSizeWords, dSizeInWords;
48     uint32_t pkaReqRegs = 7;
49     /* set virtual registers pointers  */
50     uint8_t rT2= regTemps[2]; /*2*/
51     uint8_t rT3 = regTemps[3]; /*3*/
52     uint8_t rT4 = regTemps[4]; /*4*/
53 
54     /* modulus N size in bytes */
55     modSizeWords = CALC_FULL_32BIT_WORDS(pPrivKey->nSizeInBits);
56     if (modSizeWords > CALC_FULL_32BIT_WORDS(CC_RSA_MAX_VALID_KEY_SIZE_VALUE_IN_BITS)) {
57         return CC_RSA_INVALID_MODULUS_SIZE;
58     }
59 
60     /* priv. exponent size in bytes */
61     dSizeInWords = CALC_FULL_32BIT_WORDS(pPrivKey->PriveKeyDb.NonCrt.dSizeInBits);
62 
63     error = PkaInitAndMutexLock(pPrivKey->nSizeInBits,&pkaReqRegs);
64     if (error != CC_OK) {
65         return error;
66     }
67 
68     /*      copy the N, Np DataIn and D into PKA registers                  */
69     /* N => r0 */
70     /* copy modulus N into PKA register: N=>r0 */
71     PkaCopyDataIntoPkaReg(PKA_REG_N/*dstReg*/, LEN_ID_MAX_BITS/*LenID*/, pPrivKey->n/*srcPtr*/,modSizeWords);
72 
73     /* copy the NP into r1 register NP */
74     PkaCopyDataIntoPkaReg(PKA_REG_NP/*dstReg*/, LEN_ID_MAX_BITS/*LenID*/,
75                    ((RsaPrivKeyDb_t*)(pPrivKey->ccRSAPrivKeyIntBuff))->NonCrt.NP/*srcPtr*/,
76                    CC_PKA_BARRETT_MOD_TAG_BUFF_SIZE_IN_WORDS);
77 
78     /* copy input data into PKI register: DataIn=>r2 */
79     PkaCopyDataIntoPkaReg( rT2/*dstReg*/, LEN_ID_MAX_BITS/*LenID*/, pPrivData->DataIn, modSizeWords);
80 
81     /* copy input data into PKI register: DataIn=>r2 */
82     PkaCopyDataIntoPkaReg( rT3/*dstReg*/, LEN_ID_MAX_BITS/*LenID*/, pPrivKey->PriveKeyDb.NonCrt.d, dSizeInWords);
83 
84 
85     /* .. calculate the exponent Res = DataIn^D mod N;                  ... */
86     PKA_MOD_EXP(LEN_ID_N_BITS/*LenID*/, rT4/*Res*/, rT2/*OpA*/, rT3/*OpB*/);
87 
88 
89     /*  Finish PKA and copy result */
90     /* copy result into output buffer */
91     /* copy result into output: r4 =>DataOut */
92     PkaCopyDataFromPkaReg(pPrivData->DataOut, modSizeWords, rT4/*srcReg*/);
93 
94     PkaFinishAndMutexUnlock(pkaReqRegs);
95 
96     return error;
97 
98 }
99 
100 
101 /***********    RsaExecPrivKeyExpCrt   function      **********************/
102 /**
103  * @brief This function executes the RSA primitive: private key CRT exponent.
104  *        adapted for Keys up to 2K bits size.
105  *
106  *    Algorithm [PKCS #1 v2.1]:
107  *
108  *   CRT exponentiation algorithm:
109  *        1. Mq  =  C^dQ mod Q;
110  *        2. Mp  =  C ^dP mod P,
111  *        3  h = (Mp-Mq)*qInv mod P;
112  *        4. M = Mq + Q * h.
113  *
114  *     Where: M- message representative, C- ciphertext, D- priv.exponent, N- modulus,
115  *            P,Q,dP,dQ, qInv - CRT private key parameters;
116  *            ^ - exponentiation symbol.
117  *
118  *     Note: 9 PKA registers are used: r0-r6,  r30,r31.
119  *
120  * @return  CC_OK On success, otherwise indicates failure
121  */
RsaExecPrivKeyExpCrt(CCRsaPrivKey_t * pPrivKey,CCRsaPrimeData_t * pPrivData)122 static CCError_t RsaExecPrivKeyExpCrt(CCRsaPrivKey_t    *pPrivKey , /*!< [in]  Private key database. */
123                   CCRsaPrimeData_t *pPrivData)        /*!< [in/out]  Containing DataIn and DataOut buffers. */
124 
125 {
126     CCError_t error = CC_OK;
127     uint32_t  modSizeWords, pqSizeInWords;
128     uint32_t pkaReqRegs = 10;
129 
130     /* virtual registers pointers
131        Note: don't change rQ = 6  */
132     int8_t  rN  = PKA_REG_N;
133     int8_t  rNP = PKA_REG_NP;
134     int8_t  rD  = regTemps[2];
135     int8_t  rT  = regTemps[3];
136     int8_t  rT1 = regTemps[4];
137     int8_t  rMq = regTemps[5];
138     int8_t  rQ  = regTemps[6];
139     int8_t  rqInv = regTemps[7];
140 
141 
142     /* modulus N size in bytes */
143     modSizeWords = CALC_FULL_32BIT_WORDS(pPrivKey->nSizeInBits);
144     if (modSizeWords > CALC_FULL_32BIT_WORDS(CC_RSA_MAX_VALID_KEY_SIZE_VALUE_IN_BITS)) {
145         return CC_RSA_INVALID_MODULUS_SIZE;
146     }
147 
148     error = PkaInitAndMutexLock(pPrivKey->nSizeInBits, &pkaReqRegs);
149     if (error != CC_OK) {
150         return error;
151     }
152 
153     /*  set Sizes table: 0- Nsize, 1- Nsize+1w (is done), 2- Psize  */
154     PkaSetLenIds(pPrivKey->PriveKeyDb.Crt.PSizeInBits, LEN_ID_PQ_BITS);
155 
156     /* P and Q size in bytes */
157     pqSizeInWords = CALC_FULL_32BIT_WORDS(pPrivKey->PriveKeyDb.Crt.PSizeInBits);
158 
159     /* PKA modular operations  according to modulus Q:              */
160 
161     /* copy CRT parametersrs Q, dQ, QP into PKA registers */
162     PkaCopyDataIntoPkaReg( rN/*0 dstReg*/, LEN_ID_MAX_BITS/*LenID*/, pPrivKey->PriveKeyDb.Crt.Q/*src_ptr*/, pqSizeInWords);
163 
164     PkaCopyDataIntoPkaReg( rD/*2 dstReg*/, LEN_ID_MAX_BITS/*LenID*/, pPrivKey->PriveKeyDb.Crt.dQ/*src_ptr*/, pqSizeInWords);
165 
166     PkaCopyDataIntoPkaReg( rNP/*1 dstReg*/, LEN_ID_MAX_BITS/*LenID*/, ((RsaPrivKeyDb_t*)(pPrivKey->ccRSAPrivKeyIntBuff))->Crt.QP/*src_ptr*/,
167                 CC_PKA_BARRETT_MOD_TAG_BUFF_SIZE_IN_WORDS );
168     /* copy DataIn into rT and rT! */
169     PkaCopyDataIntoPkaReg(rT/*3 dstReg*/, LEN_ID_MAX_BITS/*LenID*/, pPrivData->DataIn/*src_ptr*/, modSizeWords );
170     PKA_COPY(LEN_ID_MAX_BITS/*LenID*/, rT1/*4 dest*/, rT/*3 src*/);
171 
172     /*  Calculation of Mq          */
173     /* reduction of the input data by modulus Q  rT = rT mod Q */
174     PKA_DIV(LEN_ID_N_PKA_REG_BITS/*LenID*/, rQ/*6 Res not used*/, rT/*3 OpA*/, rN/*0 OpB=rN=Q*/);
175 
176     /* operation changes from p/q size to N size, need clearing rT high bits */
177 
178     /*  calculate of Mq = DataIn^dQ mod Q: Mq = rT^rD mod rN        */
179     PKA_MOD_EXP(LEN_ID_PQ_BITS/*LenID*/, rMq/*5 Res*/, rT/*3 OpA*/, rD/*2 OpB*/);
180 
181     /* PKA modular operations  according to modulus P:              */
182     /* copy prime factor P into rQ for swapping with rN */
183     PkaCopyDataIntoPkaReg(rQ/*6 dstReg*/, LEN_ID_MAX_BITS/*LenID*/, pPrivKey->PriveKeyDb.Crt.P/*src_ptr*/, pqSizeInWords);
184     /* swap rQ <-> rN so that Q->rQ and P->rN */
185     rQ = PKA_REG_N; rN = 6;
186 
187     /* set new value to N_NP_TO_T1 register according N->6, Np->1,T0->30,T1->31: 0x000FF826*/
188     PKA_SET_N_NP_T0_T1_REG(rN, PKA_REG_NP, PKA_REG_T0, PKA_REG_T1);
189 
190 
191     /* copy Barrett tag PP: PP=>NP */
192     PkaCopyDataIntoPkaReg(rNP/*1 dstReg*/, LEN_ID_MAX_BITS/*LenID*/, ((RsaPrivKeyDb_t*)(pPrivKey->ccRSAPrivKeyIntBuff))->Crt.PP/*src_ptr*/,
193                    CC_PKA_BARRETT_MOD_TAG_BUFF_SIZE_IN_WORDS);
194 
195     /* copy priv. exponent factor dP: dP=>rD */
196     PkaCopyDataIntoPkaReg(rD/*2 dstReg*/, LEN_ID_MAX_BITS/*LenID*/, pPrivKey->PriveKeyDb.Crt.dP/*src_ptr*/, pqSizeInWords);
197 
198     /* copy qInv coefficient: qInv=>rqInv   */
199     PkaCopyDataIntoPkaReg(rqInv/*7 dstReg*/, LEN_ID_MAX_BITS/*LenID*/, pPrivKey->PriveKeyDb.Crt.qInv/*src_ptr*/, pqSizeInWords );
200 
201     /*  Calculation of Mp          */
202     /* reduction of input data by modulus P:  rT = rT1 mod P  */
203     PKA_DIV(LEN_ID_N_PKA_REG_BITS/*LenID*/, rT/*3 res not used*/, rT1/*4 OpA and remainder*/, rN/*0 OpB*/);
204 
205     /* operation changes from p/q size to N size, need clearing registers high bits */
206 
207     /* calculate exponent Mp = DataIn^dP mod P , i.e: rT = rT1^rD mod rP  */
208     PKA_MOD_EXP(LEN_ID_PQ_BITS/*LenID*/, rT/*3 Res*/, rT1/*4 OpA*/, rD/*2 exp*/);
209 
210     /* Calculation of  h = (Mp-Mq)*qInv mod P    */
211     /* rT1 = Mq mod P - needed for right calculating in next operation if Mq>P */
212     PKA_MOD_ADD_IM(LEN_ID_PQ_BITS/*LenID*/, rT1/*Res*/, rMq/*5 OpA*/, 0/*immed OpB*/);
213 
214     /* rT = Mp - Mq mod P */
215     PKA_MOD_SUB(LEN_ID_PQ_BITS/*LenID*/, rT/*Res*/, rT/*OpA*/, rT1/*OpB*/);
216 
217     /* rT1 = h = (Mp - Mq)*qInv mod P */
218     PKA_MOD_MUL(LEN_ID_PQ_BITS/*LenID*/, rT1/*Res*/, rT/*OpA*/, rqInv/*rqInv*/);
219 
220     /*       M = Mq + Q*h;         */
221     /*  OpSize according Nsize     */
222     /* operation changes from p/q size to N size, need clearing rT high bits */
223     PkaClearPkaRegWords(rT1, pqSizeInWords);
224     PkaClearPkaRegWords(rT, pqSizeInWords);
225     PkaClearPkaRegWords(rQ, pqSizeInWords);
226     PkaClearPkaRegWords(rMq, pqSizeInWords);
227 
228     /* copy rT1 and Mq in other registers for clearing junk from registers high part  */
229     PKA_2CLEAR(LEN_ID_MAX_BITS/*LenID*/, PKA_REG_T0/*dest*/);
230     PKA_COPY(LEN_ID_MAX_BITS/*LenID*/, rT/*dest*/, rT1/*src*/);
231     PKA_2CLEAR(LEN_ID_MAX_BITS/*LenID*/, PKA_REG_T0/*dest*/);
232     PKA_COPY(LEN_ID_MAX_BITS/*LenID*/, rT1/*dest*/, rMq/*src*/);
233 
234     /* Q*h => rT = rQ*rT */
235     PKA_MUL_LOW(LEN_ID_N_PKA_REG_BITS/*LenID*/, rT/*Res*/, rT/*OpA*/, rQ/*OpB*/);
236 
237     PkaClearPkaRegWords(rT, pPrivKey->nSizeInBits);
238 
239     /* M = rT1 = rMq + rT */
240     PKA_ADD(LEN_ID_N_BITS/*LenID*/, rT/*Res*/, rT1/*OpA*/, rT/*OpB*/);
241 
242     /*  Finish PKA and copy result */
243     PkaCopyDataFromPkaReg(pPrivData->DataOut,  modSizeWords, rT/*srcReg*/);
244 
245     PkaFinishAndMutexUnlock(pkaReqRegs);
246 
247     return error;
248 
249 }
250 
251 
252 /***********     RsaInitPrivKeyDb  function      **********************/
253 /**
254  * @brief This function initializes the low level key database private structure.
255  *        On the HW platform the Barrett tag is initialized
256  *
257  *
258  * @return  CC_OK On success, otherwise indicates failure
259  */
RsaInitPrivKeyDb(CCRsaPrivKey_t * pPrivKey)260 CCError_t RsaInitPrivKeyDb( CCRsaPrivKey_t *pPrivKey )  /*!< [in]  Private key database. */
261 {
262     CCError_t error = CC_OK;
263 
264     /* calculate NP on NonCRT mode  */
265     if (pPrivKey->OperationMode == CC_RSA_NoCrt) {
266         /* check key size */
267         if (pPrivKey->nSizeInBits > CC_RSA_MAX_VALID_KEY_SIZE_VALUE_IN_BITS) {
268             error = PKA_KEY_ILLEGAL_SIZE_ERROR;
269             goto END;
270         }
271 
272         /* calculate Barrett tag NP by initialization PKA for modular operations.
273            Default settings: N=PKA_REG_N, NP=PKA_REG_NP, T0=30, T1=31.
274            Our settings for temps: rT0=2, rT1=3, rT2=4 */
275         error = PkiCalcNp( ((RsaPrivKeyDb_t *)(pPrivKey->ccRSAPrivKeyIntBuff))->NonCrt.NP,   /*out*/
276                     pPrivKey->n,     /*in*/
277                     pPrivKey->nSizeInBits); /*in*/
278 
279 
280     } else {
281         /* on CRT mode calculate the Barrett tags  */
282         /*    PP and PQ for P and Q factors        */
283         /* check key sizes */
284         if (pPrivKey->PriveKeyDb.Crt.PSizeInBits > CC_RSA_MAX_VALID_KEY_SIZE_VALUE_IN_BITS/2 ||
285             pPrivKey->PriveKeyDb.Crt.QSizeInBits > CC_RSA_MAX_VALID_KEY_SIZE_VALUE_IN_BITS/2) {
286             error = PKA_KEY_ILLEGAL_SIZE_ERROR;
287             goto END;
288         }
289         /* calculate Barrett tag PP by initialization PKA for modular operations */
290         error = PkiCalcNp( ((RsaPrivKeyDb_t *)(pPrivKey->ccRSAPrivKeyIntBuff))->Crt.PP,   /*out*/
291                     pPrivKey->PriveKeyDb.Crt.P, /*in*/
292                     pPrivKey->PriveKeyDb.Crt.PSizeInBits);
293         if (error != CC_SUCCESS) {
294             goto END;
295         }
296 
297         /* calculate Barrett tag PP by initialization PKA for modular operations */
298         error = PkiCalcNp( ((RsaPrivKeyDb_t *)(pPrivKey->ccRSAPrivKeyIntBuff))->Crt.QP,   /*out*/
299                     pPrivKey->PriveKeyDb.Crt.Q, /*in*/
300                     pPrivKey->PriveKeyDb.Crt.QSizeInBits);
301         if (error != CC_SUCCESS) {
302             goto END;
303         }
304 
305 
306     }/* end of CRT case */
307 
308     END:
309     return error;
310 }
311 
312 
313 
314 /***********     RsaExecPrivKeyExp  function      **********************/
315 /**
316  * @brief This function executes the RSA private key exponentiation
317  *
318  *    Algorithm [PKCS #1 v2.1]:
319  *
320  *     1. If NonCRT exponent, then  M  =  C^D  mod N.
321  *
322  *     2. If CRT exponent, then:
323  *        2.1. M1  =  C^dP mod P,
324  *        2.2. M2  =  C^dQ mod Q;
325  *        2.3  h = (M1-M2)*qInv mod P;
326  *        2.4. M = M2 + Q * h.
327  *
328  *     Where: M- message representative, C- ciphertext, N- modulus,
329  *            P,Q,dP,dQ, qInv - CRT private key parameters;
330  *            ^ - exponentiation symbol.
331  *
332  *     Note: PKA registers used: NonCrt: r0-r4,   r30,r31, size of registers - Nsize;
333  *                               Crt:    r0-r10,  r30,r31, size of registers - Nsize;
334  *
335  * @return  CC_OK On success, otherwise indicates failure
336  */
RsaExecPrivKeyExp(CCRsaPrivKey_t * pPrivKey,CCRsaPrimeData_t * pPrivData)337 CCError_t RsaExecPrivKeyExp( CCRsaPrivKey_t    *pPrivKey ,   /*!< [in]  Private key database. */
338                     CCRsaPrimeData_t *pPrivData )   /*!< [in/out]  Containing DataIn and DataOut buffers. */
339 {
340     CCError_t error = CC_OK;
341 
342     /*         1.  NonCRT  case                     */
343     if (pPrivKey->OperationMode == CC_RSA_NoCrt) {
344         error = RsaExecPrivKeyExpNonCrt(pPrivKey, pPrivData );
345     } else {
346         /*         2.  CRT  case                         */
347         error = RsaExecPrivKeyExpCrt(pPrivKey, pPrivData );
348     }
349 
350     return error;
351 }
352 
353 #endif/* !defined(CC_IOT) || ( defined(CC_IOT) && defined(MBEDTLS_RSA_C)) */
354 
355 
356