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_bitops.h"
10 #include "cc_pal_types.h"
11 #include "cc_pal_mem.h"
12 #include "cc_common.h"
13 #include "mbedtls_cc_srp.h"
14 #include "srp_driver.h"
15 #include "srp.h"
16 #include "mbedtls_cc_srp_error.h"
17
18
19 /************************ private Functions **********************/
isSrpVerValid(mbedtls_srp_version_t srpVer)20 bool isSrpVerValid(mbedtls_srp_version_t srpVer)
21 {
22 if ((srpVer != CC_SRP_VER_3) &&
23 (srpVer != CC_SRP_VER_6) &&
24 (srpVer != CC_SRP_VER_6A) &&
25 (srpVer != CC_SRP_VER_HK)) {
26 return false;
27 }
28 return true;
29 }
30
isSrpModulusSizeValid(size_t modSizeInBits)31 bool isSrpModulusSizeValid(size_t modSizeInBits)
32 {
33 if ((modSizeInBits != CC_SRP_MODULUS_SIZE_1024_BITS) &&
34 (modSizeInBits != CC_SRP_MODULUS_SIZE_1536_BITS) &&
35 (modSizeInBits != CC_SRP_MODULUS_SIZE_2048_BITS) &&
36 (modSizeInBits != CC_SRP_MODULUS_SIZE_3072_BITS)) {
37 return false;
38 }
39 return true;
40 }
41
getHashDigestSize(CCHashOperationMode_t hashMode)42 uint32_t getHashDigestSize(CCHashOperationMode_t hashMode)
43 {
44 switch(hashMode) {
45 case CC_HASH_SHA1_mode:
46 return CC_HASH_SHA1_DIGEST_SIZE_IN_BYTES;
47 case CC_HASH_SHA224_mode:
48 return CC_HASH_SHA224_DIGEST_SIZE_IN_BYTES;
49 case CC_HASH_SHA256_mode:
50 return CC_HASH_SHA256_DIGEST_SIZE_IN_BYTES;
51 case CC_HASH_SHA384_mode:
52 return CC_HASH_SHA384_DIGEST_SIZE_IN_BYTES;
53 case CC_HASH_SHA512_mode:
54 return CC_HASH_SHA512_DIGEST_SIZE_IN_BYTES;
55 case CC_HASH_MD5_mode:
56 return CC_HASH_MD5_DIGEST_SIZE_IN_BYTES;
57 default:
58 return 0;
59 }
60 }
61
62 /************************ SRP common Functions **********************/
mbedtls_srp_init(mbedtls_srp_entity_t srpType,mbedtls_srp_version_t srpVer,mbedtls_srp_modulus srpModulus,uint8_t srpGen,size_t modSizeInBits,CCHashOperationMode_t hashMode,uint8_t * pUserName,size_t userNameSize,uint8_t * pPwd,size_t pwdSize,CCRndContext_t * pRndCtx,mbedtls_srp_context * pCtx)63 CIMPORT_C CCError_t mbedtls_srp_init(
64 mbedtls_srp_entity_t srpType,
65 mbedtls_srp_version_t srpVer,
66 mbedtls_srp_modulus srpModulus,
67 uint8_t srpGen,
68 size_t modSizeInBits,
69 CCHashOperationMode_t hashMode,
70 uint8_t *pUserName,
71 size_t userNameSize,
72 uint8_t *pPwd,
73 size_t pwdSize,
74 CCRndContext_t *pRndCtx,
75 mbedtls_srp_context *pCtx)
76 {
77 CCError_t rc = 0;
78 uint32_t hashDigestSize = 0;
79
80 // Verify inputs
81 hashDigestSize = getHashDigestSize(hashMode);
82 if (((srpType != CC_SRP_HOST) && (srpType != CC_SRP_USER)) ||
83 (isSrpVerValid(srpVer) == false) ||
84 (srpModulus == NULL) ||
85 (isSrpModulusSizeValid(modSizeInBits) == false) ||
86 (pUserName == NULL) || (userNameSize == 0) ||
87 ((srpType == CC_SRP_USER) && ((pPwd == NULL) || (pwdSize == 0))) ||
88 (pRndCtx == NULL) ||
89 (pCtx == NULL)) {
90 return CC_SRP_PARAM_INVALID_ERROR;
91 }
92
93 // clear SRP ctx
94 CC_PalMemSetZero(pCtx, sizeof(*pCtx));
95
96 // Keep inputs in context
97 pCtx->srpType = srpType;
98 pCtx->srpVer = srpVer;
99 pCtx->groupParam.gen = srpGen;
100 pCtx->groupParam.modSizeInBits = modSizeInBits;
101 CC_PalMemCopy(pCtx->groupParam.modulus, srpModulus, CALC_FULL_BYTES(modSizeInBits));
102 pCtx->hashMode = hashMode;
103 pCtx->hashDigestSize = hashDigestSize;
104 pCtx->pRndCtx = pRndCtx;
105
106 //calculate multiplier k and keep it in SRP context
107 rc = SRP_InitAndkMultiplierCalc(pCtx);
108 if (rc != 0) {
109 rc = CC_SRP_INTERNAL_ERROR;
110 goto end_with_error;
111 }
112
113 //calculate user credential Digest, if exists, and keep it in SRP context
114 if ((pPwd != NULL) && (pwdSize != 0)) {
115 rc = SRP_UserCredDigCalc(pUserName, userNameSize,
116 pPwd, pwdSize,
117 pCtx);
118 if (rc != 0) {
119 goto end_with_error;
120 }
121 }
122
123 // start calculating the proof with existing values
124 rc = SRP_UserNameDigCalc(pUserName,
125 userNameSize,
126 pCtx);
127 if (rc != 0) {
128 goto end_with_error;
129 }
130
131 return CC_OK;
132
133 end_with_error:
134 CC_PalMemSetZero(pCtx, sizeof(*pCtx));
135 return rc;
136
137 }
138
139
mbedtls_srp_pwd_ver_create(size_t saltSize,uint8_t * pSalt,mbedtls_srp_modulus pwdVerifier,mbedtls_srp_context * pCtx)140 CIMPORT_C CCError_t mbedtls_srp_pwd_ver_create(
141 size_t saltSize,
142 uint8_t *pSalt,
143 mbedtls_srp_modulus pwdVerifier,
144 mbedtls_srp_context *pCtx)
145 {
146 CCError_t rc = 0;
147 mbedtls_srp_digest xBuff;
148 CCRndContext_t *pRndCtx;
149
150 // verify input
151 if ((saltSize < CC_SRP_MIN_SALT_SIZE) || (saltSize > CC_SRP_MAX_SALT_SIZE) ||
152 (pSalt == NULL) ||
153 (pwdVerifier == NULL) ||
154 (pCtx == NULL) || (pCtx->pRndCtx->rndGenerateVectFunc == NULL)) {
155 return CC_SRP_PARAM_INVALID_ERROR;
156 }
157 pRndCtx = pCtx->pRndCtx;
158
159 // generate random pSalt
160 rc = pRndCtx->rndGenerateVectFunc(pRndCtx->rndState, (unsigned char *)pSalt, saltSize);
161 if (rc != CC_OK) {
162 goto end_with_error;
163 }
164 // calc x = SHA(pSalt | pCtx->credDigest)
165 rc = SRP_xBuffCalc(pSalt,
166 saltSize,
167 xBuff,
168 pCtx);
169 if (rc != 0) {
170 goto end_with_error;
171 }
172
173 // Use PKA to calculate v=g^x%N
174 rc = SrpPwdVerifierCalc(xBuff, pwdVerifier, pCtx);
175 if (rc != 0) {
176 rc = CC_SRP_INTERNAL_ERROR;
177 goto end_with_error;
178 }
179 return CC_OK;
180
181 end_with_error:
182 CC_PalMemSetZero(pSalt, saltSize);
183 CC_PalMemSetZero(pwdVerifier, sizeof(mbedtls_srp_modulus));
184 CC_PalMemSetZero(pCtx, sizeof(mbedtls_srp_context));
185 return rc;
186 }
187
188
mbedtls_srp_clear(mbedtls_srp_context * pCtx)189 CIMPORT_C CCError_t mbedtls_srp_clear(
190 mbedtls_srp_context *pCtx)
191 {
192 if (pCtx == NULL) {
193 return CC_SRP_PARAM_INVALID_ERROR;
194 }
195 CC_PalMemSetZero(pCtx, sizeof(*pCtx));
196 return CC_OK;
197 }
198
199
200 /************************ SRP Host Functions **********************/
mbedtls_srp_host_pub_key_create(size_t ephemPrivSize,mbedtls_srp_modulus pwdVerifier,mbedtls_srp_modulus hostPubKeyB,mbedtls_srp_context * pCtx)201 CIMPORT_C CCError_t mbedtls_srp_host_pub_key_create(
202 size_t ephemPrivSize,
203 mbedtls_srp_modulus pwdVerifier,
204 mbedtls_srp_modulus hostPubKeyB,
205 mbedtls_srp_context *pCtx)
206 {
207 CCError_t rc = 0;
208 CCRndContext_t *pRndCtx;
209
210 // verify input
211 if ((ephemPrivSize < CC_SRP_PRIV_NUM_MIN_SIZE) ||
212 (ephemPrivSize > CC_SRP_PRIV_NUM_MAX_SIZE) ||
213 (ephemPrivSize % CC_32BIT_WORD_SIZE) ||
214 (pwdVerifier == NULL) ||
215 (hostPubKeyB == NULL) ||
216 (pCtx == NULL) || (pCtx->pRndCtx->rndGenerateVectFunc == NULL)) {
217 return CC_SRP_PARAM_INVALID_ERROR;
218 }
219 pRndCtx = pCtx->pRndCtx;
220 // generate ephemeral private key b
221 rc = pRndCtx->rndGenerateVectFunc(pRndCtx->rndState, (unsigned char *)pCtx->ephemPriv, ephemPrivSize);
222 if (rc != CC_OK) {
223 goto end_with_error;
224 }
225 pCtx->ephemPrivSize = ephemPrivSize;
226
227 // Use PKA to calculate B=(k*v+g^b)%N
228 rc = SrpHostPublicKeyCalc(pwdVerifier, hostPubKeyB, pCtx);
229 if (rc != 0) {
230 rc = CC_SRP_INTERNAL_ERROR;
231 goto end_with_error;
232 }
233 return CC_OK;
234
235 end_with_error:
236 CC_PalMemSetZero(hostPubKeyB, sizeof(mbedtls_srp_modulus));
237 CC_PalMemSetZero(pCtx, sizeof(mbedtls_srp_context));
238 return rc;
239 }
240
241
mbedtls_srp_host_proof_verify_and_calc(size_t saltSize,uint8_t * pSalt,mbedtls_srp_modulus pwdVerifier,mbedtls_srp_modulus userPubKeyA,mbedtls_srp_modulus hostPubKeyB,mbedtls_srp_digest userProof,mbedtls_srp_digest hostProof,mbedtls_srp_sessionKey sessionKey,mbedtls_srp_context * pCtx)242 CIMPORT_C CCError_t mbedtls_srp_host_proof_verify_and_calc(
243 size_t saltSize,
244 uint8_t *pSalt,
245 mbedtls_srp_modulus pwdVerifier,
246 mbedtls_srp_modulus userPubKeyA,
247 mbedtls_srp_modulus hostPubKeyB,
248 mbedtls_srp_digest userProof,
249 mbedtls_srp_digest hostProof,
250 mbedtls_srp_sessionKey sessionKey,
251 mbedtls_srp_context *pCtx)
252 {
253 CCError_t rc = 0;
254 mbedtls_srp_digest digBuff; // used for uScramble and expected user proof
255 mbedtls_srp_modulus sharedSecret;
256
257 // Verify input
258 if ((saltSize < CC_SRP_MIN_SALT_SIZE) || (saltSize > CC_SRP_MAX_SALT_SIZE) ||
259 (pSalt == NULL) ||
260 (pwdVerifier == NULL) ||
261 (userPubKeyA == NULL) ||
262 (hostPubKeyB == NULL) ||
263 (userProof == NULL) ||
264 (hostProof == NULL) ||
265 (sessionKey == NULL) ||
266 (pCtx == NULL) ) {
267 return CC_SRP_PARAM_INVALID_ERROR;
268 }
269
270 // Generate u
271 rc = SRP_uScrambleCalc(userPubKeyA,
272 hostPubKeyB,
273 digBuff,
274 pCtx);
275 if (rc != 0) {
276 goto end_with_error;
277 }
278
279 // Use PKA to calculate shared secret S=(((A*v^u)^b)%N
280 rc = SrpHostSharedSecretCalc(userPubKeyA,
281 pwdVerifier,
282 digBuff,
283 sharedSecret,
284 pCtx);
285 if (rc != 0) {
286 rc = CC_SRP_INTERNAL_ERROR;
287 goto end_with_error;
288 }
289
290 // Generate session key K
291 rc = SRP_SessionKeyCalc((uint8_t *)sharedSecret,
292 CALC_FULL_BYTES(pCtx->groupParam.modSizeInBits),
293 sessionKey, pCtx);
294 if (rc != 0) {
295 goto end_with_error;
296 }
297
298 CC_PalMemSetZero(digBuff, sizeof(digBuff));
299 // generate the expected user proof
300 rc = SRP_UserProofCalc2(pSalt, saltSize,
301 userPubKeyA, hostPubKeyB,
302 sessionKey,
303 digBuff,
304 pCtx);
305 if (rc != 0) {
306 goto end_with_error;
307 }
308 rc = SRP_SecureMemCmp(digBuff, userProof, pCtx->hashDigestSize);
309 if (rc != 0) {
310 rc = CC_SRP_RESULT_ERROR;
311 goto end_with_error;
312 }
313
314 // generate the host proof
315 rc = SRP_HostProofCalc(userPubKeyA,
316 userProof,
317 sessionKey,
318 hostProof,
319 pCtx);
320 if (rc != 0) {
321 goto end_with_error;
322 }
323 return CC_OK;
324
325 end_with_error:
326 CC_PalMemSetZero(hostProof, sizeof(mbedtls_srp_digest));
327 CC_PalMemSetZero(sessionKey, sizeof(mbedtls_srp_sessionKey));
328 CC_PalMemSetZero(pCtx, sizeof(mbedtls_srp_context));
329 return rc;
330 }
331
332
333 /************************ SRP User Functions **********************/
mbedtls_srp_user_pub_key_create(size_t ephemPrivSize,mbedtls_srp_modulus userPubKeyA,mbedtls_srp_context * pCtx)334 CIMPORT_C CCError_t mbedtls_srp_user_pub_key_create(
335 size_t ephemPrivSize,
336 mbedtls_srp_modulus userPubKeyA,
337 mbedtls_srp_context *pCtx)
338 {
339 CCError_t rc = 0;
340 CCRndContext_t *pRndCtx;
341
342 // verify input
343 if ((ephemPrivSize < CC_SRP_PRIV_NUM_MIN_SIZE) ||
344 (ephemPrivSize > CC_SRP_PRIV_NUM_MAX_SIZE) ||
345 (ephemPrivSize % CC_32BIT_WORD_SIZE) ||
346 (userPubKeyA == NULL) ||
347 (pCtx == NULL) || (pCtx->pRndCtx->rndGenerateVectFunc == NULL)) {
348 return CC_SRP_PARAM_INVALID_ERROR;
349 }
350 pRndCtx = pCtx->pRndCtx;
351 // generate ephemeral private key a
352 rc = pRndCtx->rndGenerateVectFunc(pRndCtx->rndState, (unsigned char *)pCtx->ephemPriv, ephemPrivSize);
353 if (rc != CC_OK) {
354 goto end_with_error;
355 }
356 pCtx->ephemPrivSize = ephemPrivSize;
357
358 // Use PKA to calculate A=(g^a)%N
359 rc = SrpUserPublicKeyCalc(userPubKeyA, pCtx);
360 if (rc != 0) {
361 rc = CC_SRP_INTERNAL_ERROR;
362 goto end_with_error;
363 }
364 return CC_OK;
365
366 end_with_error:
367 CC_PalMemSetZero(userPubKeyA, sizeof(mbedtls_srp_modulus));
368 CC_PalMemSetZero(pCtx, sizeof(mbedtls_srp_context));
369 return rc;
370 }
371
372
mbedtls_srp_user_proof_calc(size_t saltSize,uint8_t * pSalt,mbedtls_srp_modulus userPubKeyA,mbedtls_srp_modulus hostPubKeyB,mbedtls_srp_digest userProof,mbedtls_srp_sessionKey sessionKey,mbedtls_srp_context * pCtx)373 CIMPORT_C CCError_t mbedtls_srp_user_proof_calc(
374 size_t saltSize,
375 uint8_t *pSalt,
376 mbedtls_srp_modulus userPubKeyA,
377 mbedtls_srp_modulus hostPubKeyB,
378 mbedtls_srp_digest userProof,
379 mbedtls_srp_sessionKey sessionKey,
380 mbedtls_srp_context *pCtx)
381 {
382 CCError_t rc = 0;
383 mbedtls_srp_digest uScramble;
384 mbedtls_srp_modulus sharedSecret;
385 mbedtls_srp_digest xBuff;
386
387 // Verify input
388 if ((saltSize < CC_SRP_MIN_SALT_SIZE) || (saltSize > CC_SRP_MAX_SALT_SIZE) ||
389 (pSalt == NULL) ||
390 (userPubKeyA == NULL) ||
391 (hostPubKeyB == NULL) ||
392 (userProof == NULL) ||
393 (sessionKey == NULL) ||
394 (pCtx == NULL) ) {
395 return CC_SRP_PARAM_INVALID_ERROR;
396 }
397
398 // Generate u
399 rc = SRP_uScrambleCalc(userPubKeyA,
400 hostPubKeyB,
401 uScramble,
402 pCtx);
403 if (rc != 0) {
404 goto end_with_error;
405 }
406
407 // calc x = SHA(pSalt | pCtx->credDigest)
408 rc = SRP_xBuffCalc(pSalt, saltSize, xBuff, pCtx);
409 if (rc != 0) {
410 goto end_with_error;
411 }
412
413 // Use PKA to calculate S=((B-k*g^x)^(a+u*x))%N
414 rc = SrpUserSharedSecretCalc(hostPubKeyB,
415 xBuff,
416 uScramble,
417 sharedSecret,
418 pCtx);
419 if (rc != 0) {
420 rc = CC_SRP_INTERNAL_ERROR;
421 goto end_with_error;
422 }
423
424 // generate shared secret K
425 rc = SRP_SessionKeyCalc((uint8_t *)sharedSecret,
426 CALC_FULL_BYTES(pCtx->groupParam.modSizeInBits),
427 sessionKey,
428 pCtx);
429 if (rc != 0) {
430 goto end_with_error;
431 }
432
433 // generate the expected user proof
434 rc = SRP_UserProofCalc2(pSalt, saltSize,
435 userPubKeyA, hostPubKeyB,
436 sessionKey,
437 userProof,
438 pCtx);
439 if (rc != 0) {
440 goto end_with_error;
441 }
442 return CC_OK;
443
444 end_with_error:
445 CC_PalMemSetZero(userProof, sizeof(mbedtls_srp_digest));
446 CC_PalMemSetZero(sessionKey, sizeof(mbedtls_srp_sessionKey));
447 CC_PalMemSetZero(pCtx, sizeof(mbedtls_srp_context));
448 return rc;
449 }
450
451
mbedtls_srp_user_proof_verify(mbedtls_srp_sessionKey sessionKey,mbedtls_srp_modulus userPubKeyA,mbedtls_srp_digest userProof,mbedtls_srp_digest hostProof,mbedtls_srp_context * pCtx)452 CIMPORT_C CCError_t mbedtls_srp_user_proof_verify(
453 mbedtls_srp_sessionKey sessionKey,
454 mbedtls_srp_modulus userPubKeyA,
455 mbedtls_srp_digest userProof,
456 mbedtls_srp_digest hostProof,
457 mbedtls_srp_context *pCtx)
458 {
459 CCError_t rc = 0;
460 mbedtls_srp_digest expHostProof = {0};
461
462 // verify input
463 if ((sessionKey == NULL) ||
464 (userPubKeyA == NULL) ||
465 (userProof == NULL) ||
466 (hostProof == NULL) ||
467 (pCtx == NULL)) {
468 return CC_SRP_PARAM_INVALID_ERROR;
469 }
470
471 // generate the expected proof
472 rc = SRP_HostProofCalc(userPubKeyA,
473 userProof,
474 sessionKey,
475 expHostProof,
476 pCtx);
477 if (rc != 0) {
478 goto end_with_error;
479 }
480
481 // compare the expected proof to the actual one
482 rc = SRP_SecureMemCmp(expHostProof, hostProof, pCtx->hashDigestSize);
483 if (rc != 0) {
484 rc = CC_SRP_RESULT_ERROR;
485 goto end_with_error;
486 }
487 return CC_OK;
488
489 end_with_error:
490 CC_PalMemSetZero(pCtx, sizeof(mbedtls_srp_context));
491 return rc;
492
493 }
494
495