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