1 /*
2  * Copyright (c) 2001-2019, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #define CC_PAL_LOG_CUR_COMPONENT CC_LOG_MASK_CC_API
8 
9 #include "cc_pal_types.h"
10 #include "cc_pal_mem.h"
11 #include "mbedtls_cc_srp.h"
12 #include "mbedtls_cc_srp_error.h"
13 #include "pka.h"
14 
15 
16 extern const int8_t regTemps[PKA_MAX_COUNT_OF_PHYS_MEM_REGS];
17 
18 #define SRP_NP_VALID 1
19 
20 // v=g^x%N
SrpPwdVerifierCalc(mbedtls_srp_digest xBuff,mbedtls_srp_modulus pwdVerifier,mbedtls_srp_context * pCtx)21 uint32_t  SrpPwdVerifierCalc(mbedtls_srp_digest xBuff,
22                              mbedtls_srp_modulus    pwdVerifier,
23                              mbedtls_srp_context    *pCtx)
24 {
25     CCError_t   rc = 0;
26     uint32_t    genWord;
27     uint32_t    pkaRegCount = 7; // adding 2 for HW temp regs PKA_REG_T0 & PKA_REG_T1
28     /* usage of PKA registers */
29     int8_t  rN = PKA_REG_N;
30     int8_t  rNp = PKA_REG_NP;
31     int8_t  rT2 = regTemps[2];
32     int8_t  rT3 = regTemps[3];
33     int8_t  rT4 = regTemps[4];
34 
35     // Verify input
36     if ((pCtx == NULL) ||
37             (xBuff == NULL) ||
38             (pwdVerifier == NULL)) {
39         return CC_SRP_PARAM_INVALID_ERROR;
40     }
41 
42     genWord = pCtx->groupParam.gen;
43     rc = PkaInitAndMutexLock(pCtx->groupParam.modSizeInBits, &pkaRegCount);
44     if (rc != 0) {
45         return rc;
46     }
47     // first copy N and calculate Np
48     PkaCopyBeByteBuffIntoPkaReg(rN, LEN_ID_MAX_BITS, pCtx->groupParam.modulus, CALC_FULL_32BIT_WORDS(pCtx->groupParam.modSizeInBits));
49     rc = PkaCalcNpIntoPkaReg(LEN_ID_N_BITS, pCtx->groupParam.modSizeInBits, rN, rNp, rT2, rT3);
50     if (rc != 0) {
51         goto end;
52     }
53     pCtx->groupParam.validNp = SRP_NP_VALID;
54     // save Np into pCtx
55     PkaCopyDataFromPkaReg(pCtx->groupParam.Np, CALC_32BIT_WORDS_FROM_BYTES(sizeof(pCtx->groupParam.Np)), rNp);
56 
57     // calculate v=g^x%N
58     PkaCopyDataIntoPkaReg(rT2, LEN_ID_MAX_BITS, &genWord, CALC_32BIT_WORDS_FROM_BYTES(sizeof(genWord)));
59     PkaCopyBeByteBuffIntoPkaReg(rT3, LEN_ID_MAX_BITS, xBuff, CALC_32BIT_WORDS_FROM_BYTES(pCtx->hashDigestSize));
60     PKA_MOD_EXP(LEN_ID_N_BITS, rT4, rT2/*g*/, rT3 /*x*/);
61     // copy the verifier
62     PkaCopyPkaRegIntoBeByteBuff(pwdVerifier, CALC_FULL_32BIT_WORDS(pCtx->groupParam.modSizeInBits), rT4);
63 
64     end:
65     PkaFinishAndMutexUnlock(pkaRegCount);
66     return rc;
67 }
68 
69 /* calculates S=(((A*v^u)^b)%N */
SrpHostSharedSecretCalc(mbedtls_srp_modulus userPubKeyA,mbedtls_srp_modulus pwdVerifier,mbedtls_srp_digest uScramble,mbedtls_srp_modulus sharedSecret,mbedtls_srp_context * pCtx)70 uint32_t   SrpHostSharedSecretCalc(mbedtls_srp_modulus   userPubKeyA,
71                                    mbedtls_srp_modulus pwdVerifier,
72                                    mbedtls_srp_digest uScramble,
73                                    mbedtls_srp_modulus  sharedSecret,
74                                    mbedtls_srp_context  *pCtx)
75 {
76     CCError_t   rc = 0;
77     uint32_t    status;
78     uint32_t    pkaRegCount = 8; // adding 2 for HW temp regs PKA_REG_T0 & PKA_REG_T1
79     /* usage of PKA registers */
80     int8_t  rN = PKA_REG_N;
81     int8_t  rNp = PKA_REG_NP;
82     int8_t  rT2 = regTemps[2];
83     int8_t  rT3 = regTemps[3];
84     int8_t  rT4 = regTemps[4];
85     int8_t  rT5 = regTemps[5];
86 
87     // Verify input
88     if ((pCtx == NULL) ||
89             (pwdVerifier == NULL) ||
90             (userPubKeyA == NULL) ||
91             (uScramble == NULL) ||
92             (sharedSecret == NULL)) {
93         return CC_SRP_PARAM_INVALID_ERROR;
94     }
95 
96     if (pCtx->groupParam.validNp != SRP_NP_VALID) {
97         return CC_SRP_STATE_UNINITIALIZED_ERROR;
98     }
99     rc = PkaInitAndMutexLock(pCtx->groupParam.modSizeInBits, &pkaRegCount);
100     if (rc != 0) {
101         return rc;
102     }
103     // firt copy buffers into PKA reg
104     PkaCopyBeByteBuffIntoPkaReg(rN, LEN_ID_MAX_BITS, pCtx->groupParam.modulus, CALC_FULL_32BIT_WORDS(pCtx->groupParam.modSizeInBits));
105     PkaCopyDataIntoPkaReg(rNp, LEN_ID_MAX_BITS, pCtx->groupParam.Np, CC_PKA_BARRETT_MOD_TAG_BUFF_SIZE_IN_WORDS);
106     PkaCopyBeByteBuffIntoPkaReg(rT2, LEN_ID_MAX_BITS, pwdVerifier, CALC_FULL_32BIT_WORDS(pCtx->groupParam.modSizeInBits));
107     PkaCopyBeByteBuffIntoPkaReg(rT3, LEN_ID_MAX_BITS, uScramble, CALC_32BIT_WORDS_FROM_BYTES(pCtx->hashDigestSize));
108     PkaCopyBeByteBuffIntoPkaReg(rT4, LEN_ID_MAX_BITS, userPubKeyA, CALC_FULL_32BIT_WORDS(pCtx->groupParam.modSizeInBits));
109     PkaCopyBeByteBuffIntoPkaReg(rT5, LEN_ID_MAX_BITS, pCtx->ephemPriv, CALC_32BIT_WORDS_FROM_BYTES(pCtx->ephemPrivSize));
110 
111     // verify 0 < userPubKeyA < N
112     /* if userPubKeyA == 0, return with error */
113     PKA_COMPARE_IM_STATUS(LEN_ID_N_PKA_REG_BITS, rT4, 0, status);
114     if (status == 1) {
115         rc = CC_SRP_PARAM_ERROR;
116         goto end;
117     }
118     /* if userPubKeyA > N, return with error */
119     PKA_SUB(LEN_ID_N_PKA_REG_BITS, RES_DISCARD, rT4, rN);
120     PKA_GET_STATUS_CARRY(status);
121     if (status == 1) {
122         rc = CC_SRP_PARAM_ERROR;
123         goto end;
124     }
125 
126     // calculate rT2 = (v^u)%N
127     PKA_MOD_EXP(LEN_ID_N_BITS, rT2, rT2/*v*/, rT3 /*u*/);
128     // calculate rT4 = (A*(v^u))%N
129     PKA_MOD_MUL(LEN_ID_N_BITS, rT4, rT4/*A*/, rT2 /*v^u*/);
130 
131     // verify (A*(v^u)) != 0
132     PKA_COMPARE_IM_STATUS(LEN_ID_N_PKA_REG_BITS, rT4, 0, status);
133     if (status == 1) {
134         rc = CC_SRP_PARAM_ERROR;
135         goto end;
136     }
137     // verify (A*(v^u)) != 1
138     PKA_COMPARE_IM_STATUS(LEN_ID_N_PKA_REG_BITS, rT4, 1, status);
139     if (status == 1) {
140         rc = CC_SRP_PARAM_ERROR;
141         goto end;
142     }
143     // verify (A*(v^u)) != -1
144     PKA_ADD_IM(LEN_ID_N_BITS, rT2, rT4, 1);
145     PKA_COMPARE_IM_STATUS(LEN_ID_N_PKA_REG_BITS, rT2, 0, status);
146     if (status == 1) {
147         rc = CC_SRP_PARAM_ERROR;
148         goto end;
149     }
150 
151     // calculate rT4 = (rT4 ^ b)%N
152     PKA_MOD_EXP(LEN_ID_N_BITS, rT4, rT4/*(A*(v^u))*/, rT5 /*(b)*/);
153     // copy the generated shared secret
154     PkaCopyPkaRegIntoBeByteBuff(sharedSecret, CALC_FULL_32BIT_WORDS(pCtx->groupParam.modSizeInBits), rT4);
155     end:
156     PkaFinishAndMutexUnlock(pkaRegCount);
157     return rc;
158 }
159 
160 
161 // Use PKA to calculate S=((B-g^x)^(a+u*x))%N
SrpUserSharedSecretCalc(mbedtls_srp_modulus hostPubKeyB,mbedtls_srp_digest xBuff,mbedtls_srp_digest uScramble,mbedtls_srp_modulus sharedSecret,mbedtls_srp_context * pCtx)162 uint32_t   SrpUserSharedSecretCalc(mbedtls_srp_modulus   hostPubKeyB,
163                                    mbedtls_srp_digest   xBuff,
164                                    mbedtls_srp_digest   uScramble,
165                                    mbedtls_srp_modulus  sharedSecret,
166                                    mbedtls_srp_context  *pCtx)
167 {
168     CCError_t   rc = 0;
169     uint32_t    status;
170     uint32_t    genWord;
171     // For 4KBytes PKA we have 10 PKA registers that supports 3072 bit modulus
172     uint32_t    pkaRegCount = 10; // adding 2 for HW temp regs PKA_REG_T0 & PKA_REG_T1
173     /* usage of PKA registers */
174     int8_t  rN = PKA_REG_N;
175     int8_t  rNp = PKA_REG_NP;
176     int8_t  rT2 = regTemps[2];
177     int8_t  rT3 = regTemps[3];
178     int8_t  rT4 = regTemps[4];
179     int8_t  rT5 = regTemps[5];
180     int8_t  rT6 = regTemps[6];
181     int8_t  rT7 = regTemps[7];
182 
183     // Verify input
184     if ((pCtx == NULL) ||
185             (hostPubKeyB == NULL) ||
186             (xBuff == NULL) ||
187             (uScramble == NULL) ||
188             (sharedSecret == NULL)) {
189         return CC_SRP_PARAM_INVALID_ERROR;
190     }
191 
192     if (pCtx->groupParam.validNp != SRP_NP_VALID) {
193         return CC_SRP_STATE_UNINITIALIZED_ERROR;
194     }
195 
196     genWord = pCtx->groupParam.gen;
197     rc = PkaInitAndMutexLock(pCtx->groupParam.modSizeInBits, &pkaRegCount);
198     if (rc != 0) {
199         return rc;
200     }
201     // firt copy buffers into PKA reg
202     PkaCopyBeByteBuffIntoPkaReg(rN, LEN_ID_MAX_BITS, pCtx->groupParam.modulus, CALC_FULL_32BIT_WORDS(pCtx->groupParam.modSizeInBits));
203     PkaCopyDataIntoPkaReg(rNp, LEN_ID_MAX_BITS, pCtx->groupParam.Np, CALC_32BIT_WORDS_FROM_BYTES(sizeof(pCtx->groupParam.Np)));
204     PkaCopyDataIntoPkaReg(rT2, LEN_ID_MAX_BITS, &genWord, CALC_FULL_32BIT_WORDS(sizeof(genWord)));
205     PkaCopyBeByteBuffIntoPkaReg(rT3, LEN_ID_MAX_BITS, xBuff, CALC_32BIT_WORDS_FROM_BYTES(pCtx->hashDigestSize));
206     PkaCopyBeByteBuffIntoPkaReg(rT4, LEN_ID_MAX_BITS, hostPubKeyB, CALC_FULL_32BIT_WORDS(pCtx->groupParam.modSizeInBits));
207     PkaCopyBeByteBuffIntoPkaReg(rT5, LEN_ID_MAX_BITS, uScramble, CALC_32BIT_WORDS_FROM_BYTES(pCtx->hashDigestSize));
208     PkaCopyBeByteBuffIntoPkaReg(rT6, LEN_ID_MAX_BITS, pCtx->ephemPriv, CALC_32BIT_WORDS_FROM_BYTES(pCtx->ephemPrivSize));
209 
210     // verify 0 < hostPubKeyB < N
211     /* if hostPubKeyB % N == 0, return with error */
212     PKA_COMPARE_IM_STATUS(LEN_ID_N_PKA_REG_BITS, rT4, 0, status);
213     if (status == 1) {
214         rc = CC_SRP_PARAM_ERROR;
215         goto end;
216     }
217     /* if hostPubKeyB > N, return with error */
218     PKA_SUB(LEN_ID_N_PKA_REG_BITS, RES_DISCARD, rT4, rN);
219     PKA_GET_STATUS_CARRY(status);
220     if (status == 1) {
221         rc = CC_SRP_PARAM_ERROR;
222         goto end;
223     }
224     PkaCopyBeByteBuffIntoPkaReg(rT7, LEN_ID_MAX_BITS, pCtx->kMult, CALC_32BIT_WORDS_FROM_BYTES(pCtx->hashDigestSize));
225 
226     // calculate rT2 = (g^x)%N
227     PKA_MOD_EXP(LEN_ID_N_BITS, rT2, rT2/*g*/, rT3 /*x*/);
228     // calculate rT2 = (k*rT2)%N
229     PKA_MOD_MUL(LEN_ID_N_BITS, rT2, rT7/*k*/, rT2 /*g^x*/);
230     // calculate rT2 = (B-rT2)%N
231     PKA_MOD_SUB(LEN_ID_N_BITS, rT2, rT4/*B*/, rT2 /*g^x*/);
232     // calculate rT5 = (u*x)%N
233     PKA_MOD_MUL(LEN_ID_N_BITS, rT5, rT5/*u*/, rT3 /*x*/);
234     // calculate rT5 = (a + rT5)%N
235     PKA_MOD_ADD(LEN_ID_N_BITS, rT5, rT6/*(a)*/, rT5 /*(u*x)*/);
236     // calculate rT5 = (rT2^rT5)%N
237     PKA_MOD_EXP(LEN_ID_N_BITS, rT5, rT2/*(B-k*g^x)*/, rT5 /*(a+u*x)*/);
238     // copy the generated session key
239     PkaCopyPkaRegIntoBeByteBuff(sharedSecret, CALC_FULL_32BIT_WORDS(pCtx->groupParam.modSizeInBits), rT5);
240     end:
241     PkaFinishAndMutexUnlock(pkaRegCount);
242     return rc;
243 }
244 
245 
246 /* calculates B = (k*v+ g^b)%N */
SrpHostPublicKeyCalc(mbedtls_srp_modulus pwdVerifier,mbedtls_srp_modulus hostPubKeyB,mbedtls_srp_context * pCtx)247 uint32_t  SrpHostPublicKeyCalc(mbedtls_srp_modulus  pwdVerifier,    // in
248                                mbedtls_srp_modulus  hostPubKeyB,    // out
249                                mbedtls_srp_context  *pCtx)      // in
250 {
251     CCError_t   rc = 0;
252     uint32_t    status;
253     uint32_t    genWord;
254     uint32_t    pkaRegCount = 8; // adding 2 for HW temp regs PKA_REG_T0 & PKA_REG_T1
255     /* usage of PKA registers */
256     int8_t  rN = PKA_REG_N;
257     int8_t  rNp = PKA_REG_NP;
258     int8_t  rT2 = regTemps[2];
259     int8_t  rT3 = regTemps[3];
260     int8_t  rT4 = regTemps[4];
261     int8_t  rT5 = regTemps[5];
262 
263     // Verify input
264     if ((pCtx == NULL) ||
265             (pwdVerifier == NULL) ||
266             (hostPubKeyB == NULL)) {
267         return CC_SRP_PARAM_INVALID_ERROR;
268     }
269     genWord = pCtx->groupParam.gen;
270     rc = PkaInitAndMutexLock(pCtx->groupParam.modSizeInBits, &pkaRegCount);
271     if (rc != 0) {
272         return rc;
273     }
274     // firt copy buffers into PKA reg
275     PkaCopyBeByteBuffIntoPkaReg(rN, LEN_ID_MAX_BITS, pCtx->groupParam.modulus, CALC_FULL_32BIT_WORDS(pCtx->groupParam.modSizeInBits));
276     if (pCtx->groupParam.validNp != SRP_NP_VALID) {
277         rc = PkaCalcNpIntoPkaReg(LEN_ID_N_BITS, pCtx->groupParam.modSizeInBits, rN, rNp, rT2, rT3);
278         if (rc != 0) {
279             goto end;
280         }
281         // save Np into pCtx
282         PkaCopyDataFromPkaReg(pCtx->groupParam.Np, CALC_32BIT_WORDS_FROM_BYTES(sizeof(pCtx->groupParam.Np)), rNp);
283         pCtx->groupParam.validNp = SRP_NP_VALID;
284     } else {
285         PkaCopyDataIntoPkaReg(rNp, LEN_ID_MAX_BITS, pCtx->groupParam.Np, CALC_32BIT_WORDS_FROM_BYTES(sizeof(pCtx->groupParam.Np)));
286     }
287     PkaCopyBeByteBuffIntoPkaReg(rT2, LEN_ID_MAX_BITS, pCtx->kMult, CALC_32BIT_WORDS_FROM_BYTES(pCtx->hashDigestSize));
288     PkaCopyBeByteBuffIntoPkaReg(rT3, LEN_ID_MAX_BITS, pwdVerifier, CALC_FULL_32BIT_WORDS(pCtx->groupParam.modSizeInBits));
289     PkaCopyDataIntoPkaReg(rT4, LEN_ID_MAX_BITS, &genWord, CALC_FULL_32BIT_WORDS(sizeof(genWord)));
290     PkaCopyBeByteBuffIntoPkaReg(rT5, LEN_ID_MAX_BITS, pCtx->ephemPriv, CALC_32BIT_WORDS_FROM_BYTES(pCtx->ephemPrivSize));
291 
292     // calculate rT2 = (k*v)%N
293     PKA_MOD_MUL(LEN_ID_N_BITS, rT2, rT2/*k*/, rT3 /*v*/);
294     // calculate rT4 = (g^b)%N
295     PKA_MOD_EXP(LEN_ID_N_BITS, rT4, rT4/*g*/, rT5 /*b*/);
296     // calculate rT4 = (rT2 + rT4)%N
297     PKA_MOD_ADD(LEN_ID_N_BITS, rT4, rT2/*(k*v)*/, rT4 /*(g^b)*/);
298 
299     // verify hostPubKeyB
300     /* if hostPubKeyB % N == 0, return with error */
301     PKA_MOD_ADD_IM(LEN_ID_N_BITS, rT5, rT4, 0);
302     PKA_COMPARE_IM_STATUS(LEN_ID_N_PKA_REG_BITS, rT5, 0, status);
303     if (status == 1) {
304         rc = CC_SRP_PARAM_ERROR;
305         goto end;
306     }
307 
308     // copy the generated Host public key
309     PkaCopyPkaRegIntoBeByteBuff(hostPubKeyB, CALC_FULL_32BIT_WORDS(pCtx->groupParam.modSizeInBits), rT4);
310     end:
311     PkaFinishAndMutexUnlock(pkaRegCount);
312     return rc;
313 }
314 
315 /* calculates A = (g^a)%N */
SrpUserPublicKeyCalc(mbedtls_srp_modulus userPubKeyA,mbedtls_srp_context * pCtx)316 uint32_t  SrpUserPublicKeyCalc(mbedtls_srp_modulus  userPubKeyA,    // out
317                                mbedtls_srp_context  *pCtx)      // in
318 {
319     CCError_t   rc = 0;
320     uint32_t    status;
321     uint32_t    genWord;
322     uint32_t    pkaRegCount = 6; // adding 2 for HW temp regs PKA_REG_T0 & PKA_REG_T1
323     /* usage of PKA registers */
324     int8_t  rN = PKA_REG_N;
325     int8_t  rNp = PKA_REG_NP;
326     int8_t  rT2 = regTemps[2];
327     int8_t  rT3 = regTemps[3];
328 
329     // Verify input
330     if ((userPubKeyA == NULL) ||
331             (pCtx == NULL)) {
332         return CC_SRP_PARAM_INVALID_ERROR;
333     }
334 
335     genWord = pCtx->groupParam.gen;
336     rc = PkaInitAndMutexLock(pCtx->groupParam.modSizeInBits, &pkaRegCount);
337     if (rc != 0) {
338         return rc;
339     }
340     // firt copy buffers into PKA reg
341     PkaCopyBeByteBuffIntoPkaReg(rN, LEN_ID_MAX_BITS, pCtx->groupParam.modulus, CALC_FULL_32BIT_WORDS(pCtx->groupParam.modSizeInBits));
342     if (pCtx->groupParam.validNp != SRP_NP_VALID) {
343         rc = PkaCalcNpIntoPkaReg(LEN_ID_N_BITS, pCtx->groupParam.modSizeInBits, rN, rNp, rT2, rT3);
344         if (rc != 0) {
345             goto end;
346         }
347         // save Np into pCtx
348         PkaCopyDataFromPkaReg(pCtx->groupParam.Np, CALC_32BIT_WORDS_FROM_BYTES(sizeof(pCtx->groupParam.Np)), rNp);
349         pCtx->groupParam.validNp = SRP_NP_VALID;
350     } else {
351         PkaCopyDataIntoPkaReg(rNp, LEN_ID_MAX_BITS, pCtx->groupParam.Np, CALC_32BIT_WORDS_FROM_BYTES(sizeof(pCtx->groupParam.Np)));
352     }
353     PkaCopyDataIntoPkaReg(rT2, LEN_ID_MAX_BITS, &genWord, CALC_FULL_32BIT_WORDS(sizeof(genWord)));
354     PkaCopyBeByteBuffIntoPkaReg(rT3, LEN_ID_MAX_BITS, pCtx->ephemPriv, CALC_32BIT_WORDS_FROM_BYTES(pCtx->ephemPrivSize));
355 
356     // calculate rT4 = (g^b)%N
357     PKA_MOD_EXP(LEN_ID_N_BITS, rT2, rT2/*g*/, rT3 /*a*/);
358 
359     // verify userPubKeyA
360     /* if userPubKeyA % N == 0, return with error */
361     PKA_MOD_ADD_IM(LEN_ID_N_BITS, rT3, rT2, 0);
362     PKA_COMPARE_IM_STATUS(LEN_ID_N_PKA_REG_BITS, rT3, 0, status);
363     if (status == 1) {
364         rc = CC_SRP_PARAM_ERROR;
365         goto end;
366     }
367     // copy the generated User public key
368     PkaCopyPkaRegIntoBeByteBuff(userPubKeyA, CALC_FULL_32BIT_WORDS(pCtx->groupParam.modSizeInBits), rT2);
369     end:
370     PkaFinishAndMutexUnlock(pkaRegCount);
371     return rc;
372 }
373