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