1 /*
2 * Copyright (c) 2001-2020, 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 "cc_hash_defs.h"
13 #include "hash_driver.h"
14 #include "mbedtls_cc_srp_error.h"
15 #include "cc_general_defs.h"
16 #include "mbedtls/md.h"
17 #include "cc_bitops.h"
18
19
20 #define REMOVE_LEADING_BYTE_ZEROS(origPubKey, origSize, pPubKey, pubKeySize) {\
21 size_t i; \
22 for (i = 0; i < origSize; i++) { \
23 if (((uint8_t *)origPubKey)[i] != 0) { \
24 break;\
25 } \
26 }\
27 pubKeySize = origSize-i; \
28 pPubKey = &(((uint8_t *)origPubKey)[i]); \
29 }
30
31
32
33 CCHashResultBuf_t zeroBuff = {0};
34
35
SRP_kMultiplierCalc(mbedtls_srp_context * pCtx)36 static uint32_t SRP_kMultiplierCalc(mbedtls_srp_context *pCtx)
37 {
38 CCError_t rc = 0;
39 size_t modSize;
40 CCHashResultBuf_t hashResultBuff;
41 const mbedtls_md_info_t *md_info=NULL;
42 mbedtls_md_context_t hash_ctx;
43
44 modSize = CALC_FULL_BYTES(pCtx->groupParam.modSizeInBits);
45
46 md_info = mbedtls_md_info_from_string( HashAlgMode2mbedtlsString[pCtx->hashMode] );
47 if (NULL == md_info) {
48 rc = CC_SRP_PARAM_INVALID_ERROR;
49 goto End;
50 }
51 mbedtls_md_init(&hash_ctx);
52 rc = mbedtls_md_setup(&hash_ctx, md_info, 0); // 0 = HASH, not HMAC
53 if (rc != 0) {
54 goto End;
55 }
56 rc = mbedtls_md_starts(&hash_ctx);
57 if (rc != 0) {
58 goto End;
59 }
60 rc = mbedtls_md_update(&hash_ctx, pCtx->groupParam.modulus, modSize);
61 if (rc != 0) {
62 goto End;
63 }
64 // use ephemPriv as tempopary buffer with paded zeros
65 CC_PalMemSetZero(pCtx->ephemPriv, sizeof(mbedtls_srp_modulus));
66 pCtx->ephemPriv[modSize-1] = pCtx->groupParam.gen;
67 rc = mbedtls_md_update(&hash_ctx, (uint8_t *)pCtx->ephemPriv, modSize);
68 if (rc != 0) {
69 goto End;
70 }
71 rc = mbedtls_md_finish(&hash_ctx, (unsigned char *)hashResultBuff);
72 if (rc != 0) {
73 goto End;
74 }
75 // verify k != 0
76 if (CC_PalMemCmp((uint8_t *)zeroBuff, (uint8_t *)hashResultBuff, pCtx->hashDigestSize) == 0) {
77 rc = CC_SRP_RESULT_ERROR;
78 goto End;
79 }
80 // copy the result to the user
81 CC_PalMemCopy(pCtx->kMult, (uint8_t *)hashResultBuff, pCtx->hashDigestSize);
82
83 End:
84 if (NULL != md_info) {
85 mbedtls_md_free(&hash_ctx);
86 }
87 return rc;
88 }
89
90 // Sha_interleave - from RFC 2945 : Interleaved SHA
SRP_shaInterleave(uint8_t * pInBuff,size_t inBuffSize,mbedtls_srp_sessionKey sessionKey,mbedtls_srp_context * pCtx)91 static uint32_t SRP_shaInterleave(uint8_t *pInBuff, /* in buff to hash*/
92 size_t inBuffSize, /* in buffer size */
93 mbedtls_srp_sessionKey sessionKey, /* out hash interleave buff - shared secret */
94 mbedtls_srp_context *pCtx)
95 {
96 uint32_t rc = CC_OK;
97 uint32_t i = 0;
98 uint32_t j = 0;
99 const mbedtls_md_info_t *md_info=NULL;
100 uint8_t buffEF[CC_SRP_MAX_MODULUS/2] = {0};
101 uint8_t buffG[CC_SRP_MAX_DIGEST] = {0};
102 uint8_t buffH[CC_SRP_MAX_DIGEST] = {0};
103
104 // Remove all leading zero bytes from the input.
105 while ((pInBuff[i] == 0) &&
106 (inBuffSize > 0)) {
107 inBuffSize--;
108 i++;
109 }
110 if (inBuffSize == 0) {
111 /* meaning pInBuff, which is the shared secret is 0 --
112 * not reasonable, since that the think about SRP */
113 return CC_SRP_INTERNAL_ERROR;
114 }
115 // If the length of the resulting string is odd, also remove the first byte
116 if (inBuffSize % 2) {
117 inBuffSize--;
118 i++;
119 }
120 if (inBuffSize == 0) {
121 /* meaning pInBuff, which is the shared secret is 0 --
122 * not reasonable, since that the think about SRP */
123 return CC_SRP_INTERNAL_ERROR;
124 }
125
126
127 md_info = mbedtls_md_info_from_string( HashAlgMode2mbedtlsString[pCtx->hashMode] );
128 if (NULL == md_info) {
129 return CC_SRP_PARAM_INVALID_ERROR;
130 }
131 // E = T[0] | T[2] | T[4] | ...
132 for (j = 0; j < (inBuffSize/2); j++) {
133 buffEF[j] = pInBuff[i+j*2];
134 }
135 //G = SHA(E)
136 rc = mbedtls_md(md_info,
137 buffEF,
138 inBuffSize/2,
139 (unsigned char *)buffG);
140 if (rc != 0) {
141 return rc;
142 }
143
144 // F = T[1] | T[3] | T[5] | ...
145 for (j = 0; j < (inBuffSize/2); j++) {
146 buffEF[j] = pInBuff[i+j*2+1];
147 }
148 //H = SHA(F)
149 rc = mbedtls_md(md_info,
150 buffEF,
151 inBuffSize/2,
152 (unsigned char *)buffH);
153 if (rc != 0) {
154 return rc;
155 }
156
157 // result = G[0] | H[0] | G[1] | H[1] | ... | G[19] | H[19]
158 for (i = 0; (i < pCtx->hashDigestSize) && (2*i+1 < pCtx->sessionKeySize); i++) {
159 sessionKey[2*i] = buffG[i];
160 sessionKey[2*i+1] = buffH[i];
161
162 }
163 return CC_OK;
164 }
165
SRP_shaInterleaveHK(uint8_t * pInBuff,size_t inBuffSize,mbedtls_srp_sessionKey sessionKey,mbedtls_srp_context * pCtx)166 static uint32_t SRP_shaInterleaveHK(uint8_t *pInBuff, /* in buff to hash*/
167 size_t inBuffSize, /* in buffer size */
168 mbedtls_srp_sessionKey sessionKey, /* out hash interleave buff - shared secret */
169 mbedtls_srp_context *pCtx)
170 {
171 uint32_t rc = CC_OK;
172 const mbedtls_md_info_t *md_info=NULL;
173
174 md_info = mbedtls_md_info_from_string( HashAlgMode2mbedtlsString[pCtx->hashMode] );
175 if (NULL == md_info) {
176 return CC_SRP_PARAM_INVALID_ERROR;
177 }
178 rc = mbedtls_md(md_info,
179 pInBuff,
180 inBuffSize,
181 (unsigned char *)sessionKey);
182 if (rc != 0) {
183 return rc;
184 }
185 return CC_OK;
186 }
187
SRP_InitAndkMultiplierCalc(mbedtls_srp_context * pCtx)188 uint32_t SRP_InitAndkMultiplierCalc(mbedtls_srp_context *pCtx)
189 {
190 CCError_t rc = 0;
191 size_t hashDigestSize;
192
193 // verify input
194 if (pCtx == NULL) {
195 return CC_SRP_PARAM_INVALID_ERROR;
196 }
197 hashDigestSize = pCtx->hashDigestSize;
198
199 CC_PalMemSetZero(pCtx->kMult, sizeof(mbedtls_srp_digest));
200 switch(pCtx->srpVer) {
201 case CC_SRP_VER_3:
202 pCtx->sessionKeySize = 2*hashDigestSize;
203 pCtx->kMult[hashDigestSize-1] = 0x1;
204 break;
205 case CC_SRP_VER_6:
206 pCtx->sessionKeySize = 2*hashDigestSize;
207 pCtx->kMult[hashDigestSize-1] = 0x3;
208 break;
209 case CC_SRP_VER_6A:
210 /* Does 6A requires sha-interleave or just sha?
211 * we assume sha-interleave is required, therefore the size of the session key is digest*2
212 * see details in Cerberus confluence */
213 pCtx->sessionKeySize = 2*hashDigestSize;
214 rc = SRP_kMultiplierCalc(pCtx);
215 break;
216 case CC_SRP_VER_HK:
217 pCtx->sessionKeySize = hashDigestSize;
218 rc = SRP_kMultiplierCalc(pCtx);
219 break;
220 default: // should not reach here
221 return CC_SRP_PARAM_INVALID_ERROR;
222 }
223
224 return rc;
225 }
226
SRP_uScrambleCalc(mbedtls_srp_modulus ephemPubA,mbedtls_srp_modulus ephemPubB,mbedtls_srp_digest uScramble,mbedtls_srp_context * pCtx)227 uint32_t SRP_uScrambleCalc(
228 mbedtls_srp_modulus ephemPubA,
229 mbedtls_srp_modulus ephemPubB,
230 mbedtls_srp_digest uScramble,
231 mbedtls_srp_context *pCtx)
232 {
233 CCError_t rc = 0;
234 CCHashResultBuf_t hashResultBuff;
235 size_t modSize;
236 uint32_t bytesToCopy = 0;
237 mbedtls_md_context_t hash_ctx;
238
239 const mbedtls_md_info_t *md_info=NULL;
240 mbedtls_md_context_t *md_ctx=NULL;
241
242 // verify input
243 if ((ephemPubA == NULL) ||
244 (ephemPubB == NULL) ||
245 (uScramble == NULL) ||
246 (pCtx == NULL)) {
247 rc = CC_SRP_PARAM_INVALID_ERROR;
248 goto End;
249 }
250
251 modSize = CALC_FULL_BYTES(pCtx->groupParam.modSizeInBits);
252
253 CC_PalMemSetZero(uScramble, sizeof(mbedtls_srp_digest));
254 switch(pCtx->srpVer) {
255 case CC_SRP_VER_3:
256 md_info = mbedtls_md_info_from_string( HashAlgMode2mbedtlsString[pCtx->hashMode] );
257 if (NULL == md_info) {
258 rc = CC_SRP_PARAM_INVALID_ERROR;
259 goto End;
260 }
261 rc = mbedtls_md(md_info,
262 (uint8_t *)ephemPubB,
263 modSize,
264 (unsigned char *)hashResultBuff);
265 if (rc != 0) {
266 goto End;
267 }
268 // The parameter u is a 32-bit unsigned integer which takes its value
269 // from the first 32 bits of the SHA1 hash of B, MSB first.
270 bytesToCopy = CC_32BIT_WORD_SIZE;
271 break;
272 case CC_SRP_VER_6:
273 case CC_SRP_VER_6A:
274 case CC_SRP_VER_HK:
275 md_ctx = &hash_ctx;
276 md_info = mbedtls_md_info_from_string( HashAlgMode2mbedtlsString[pCtx->hashMode] );
277 if (NULL == md_info) {
278 rc = CC_SRP_PARAM_INVALID_ERROR;
279 goto End;
280 }
281 mbedtls_md_init(md_ctx);
282 rc = mbedtls_md_setup(md_ctx, md_info, 0); // 0 = HASH, not HMAC
283 if (rc != 0) {
284 goto End;
285 }
286 rc = mbedtls_md_starts(md_ctx);
287 if (rc != 0) {
288 goto End;
289 }
290 rc = mbedtls_md_update(md_ctx, ephemPubA, modSize);
291 if (rc != 0) {
292 goto End;
293 }
294 rc = mbedtls_md_update(md_ctx, ephemPubB, modSize);
295 if (rc != 0) {
296 goto End;
297 }
298
299 rc = mbedtls_md_finish(md_ctx, (unsigned char *)hashResultBuff);
300 if (rc != 0) {
301 goto End;
302 }
303 bytesToCopy = pCtx->hashDigestSize;
304 break;
305 default: // should not reach here
306 rc = CC_SRP_PARAM_INVALID_ERROR;
307 goto End;
308 }
309 // verify u != 0
310 if (CC_PalMemCmp((uint8_t *)zeroBuff, (uint8_t *)hashResultBuff, bytesToCopy) == 0) {
311 rc = CC_SRP_RESULT_ERROR;
312 goto End;
313 }
314 // copy uScramble
315 CC_PalMemCopy(uScramble, (uint8_t *)hashResultBuff, bytesToCopy);
316
317 End:
318 if((md_info!=NULL) && (md_ctx!=NULL)) {
319 mbedtls_md_free(md_ctx);
320 }
321
322 return rc;
323 }
324
325
326 // credDigest = SHA(U|:|P)
SRP_UserCredDigCalc(uint8_t * pUserName,size_t userNameSize,uint8_t * pPwd,size_t pwdSize,mbedtls_srp_context * pCtx)327 uint32_t SRP_UserCredDigCalc(uint8_t *pUserName,
328 size_t userNameSize,
329 uint8_t *pPwd,
330 size_t pwdSize,
331 mbedtls_srp_context *pCtx)
332 {
333 CCError_t rc = 0;
334 char colonChar = ':';
335 CCHashResultBuf_t hashResultBuff;
336 const mbedtls_md_info_t *md_info=NULL;
337 mbedtls_md_context_t hash_ctx;
338
339 // verify input
340 if ((pUserName == NULL) || (userNameSize == 0) ||
341 (pPwd == NULL) || (pwdSize == 0) ||
342 (pCtx == NULL)) {
343 rc = CC_SRP_PARAM_INVALID_ERROR;
344 goto End;
345 }
346
347 CC_PalMemSetZero(pCtx->credDigest, sizeof(mbedtls_srp_digest));
348
349 md_info = mbedtls_md_info_from_string( HashAlgMode2mbedtlsString[pCtx->hashMode] );
350 if (NULL == md_info) {
351 rc = CC_SRP_PARAM_INVALID_ERROR;
352 goto End;
353 }
354 mbedtls_md_init(&hash_ctx);
355 rc = mbedtls_md_setup(&hash_ctx, md_info, 0); // 0 = HASH, not HMAC
356 if (rc != 0) {
357 goto End;
358 }
359 rc = mbedtls_md_starts(&hash_ctx);
360 if (rc != 0) {
361 goto End;
362 }
363 rc = mbedtls_md_update(&hash_ctx, pUserName, userNameSize);
364 if (rc != 0) {
365 goto End;
366 }
367 rc = mbedtls_md_update(&hash_ctx, (uint8_t *)&colonChar, sizeof(colonChar));
368 if (rc != 0) {
369 goto End;
370 }
371 rc = mbedtls_md_update(&hash_ctx, pPwd, pwdSize);
372 if (rc != 0) {
373 goto End;
374 }
375 rc = mbedtls_md_finish(&hash_ctx, (unsigned char *)hashResultBuff);
376 if (rc != 0) {
377 goto End;
378 }
379 CC_PalMemCopy(pCtx->credDigest, (uint8_t *)hashResultBuff, pCtx->hashDigestSize);
380
381 End:
382 if (NULL != md_info) {
383 mbedtls_md_free(&hash_ctx);
384 }
385
386 return rc;
387 }
388
389 // calc x = SHA(pSalt | pCtx->credDigest)
SRP_xBuffCalc(uint8_t * pSalt,size_t saltSize,mbedtls_srp_digest xBuff,mbedtls_srp_context * pCtx)390 uint32_t SRP_xBuffCalc(uint8_t *pSalt,
391 size_t saltSize,
392 mbedtls_srp_digest xBuff, // out
393 mbedtls_srp_context *pCtx)
394 {
395 CCError_t rc = 0;
396 CCHashResultBuf_t hashResultBuff;
397 const mbedtls_md_info_t *md_info=NULL;
398 mbedtls_md_context_t hash_ctx;
399
400 // verify input
401 if ((pSalt == NULL) ||
402 (saltSize < CC_SRP_MIN_SALT_SIZE) || (saltSize > CC_SRP_MAX_SALT_SIZE) ||
403 (xBuff == NULL) ||
404 (pCtx == NULL)) {
405 rc = CC_SRP_PARAM_INVALID_ERROR;
406 goto End;
407 }
408 md_info = mbedtls_md_info_from_string( HashAlgMode2mbedtlsString[pCtx->hashMode] );
409 if (NULL == md_info) {
410 rc = CC_SRP_PARAM_INVALID_ERROR;
411 goto End;
412 }
413 mbedtls_md_init(&hash_ctx);
414 rc = mbedtls_md_setup(&hash_ctx, md_info, 0); // 0 = HASH, not HMAC
415 if (rc != 0) {
416 goto End;
417 }
418 rc = mbedtls_md_starts(&hash_ctx);
419 if (rc != 0) {
420 goto End;
421 }
422 rc = mbedtls_md_update(&hash_ctx, pSalt, saltSize);
423 if (rc != 0) {
424 goto End;
425 }
426 rc = mbedtls_md_update(&hash_ctx, pCtx->credDigest, pCtx->hashDigestSize);
427 if (rc != 0) {
428 goto End;
429 }
430 rc = mbedtls_md_finish(&hash_ctx, (unsigned char *)hashResultBuff);
431 if (rc != 0) {
432 goto End;
433 }
434 CC_PalMemCopy(xBuff, (uint8_t *)hashResultBuff, pCtx->hashDigestSize);
435
436 End:
437 if (NULL != md_info) {
438 mbedtls_md_free(&hash_ctx);
439 }
440
441 return rc;
442 }
443
444
445 //SHA(U)
SRP_UserNameDigCalc(uint8_t * pUserName,size_t userNameSize,mbedtls_srp_context * pCtx)446 uint32_t SRP_UserNameDigCalc(uint8_t *pUserName,
447 size_t userNameSize,
448 mbedtls_srp_context *pCtx)
449 {
450 CCError_t rc = 0;
451 CCHashResultBuf_t hashResultBuff;
452 const mbedtls_md_info_t *md_info=NULL;
453
454 // verify input
455 if ((pUserName == NULL) || (userNameSize == 0) ||
456 (pCtx == NULL)) {
457 return CC_SRP_PARAM_INVALID_ERROR;
458 }
459
460 if (pCtx->hashDigestSize > sizeof(CCHashResultBuf_t)) {
461 return CC_SRP_PARAM_INVALID_ERROR;
462 }
463
464 // SHA(U)
465 md_info = mbedtls_md_info_from_string( HashAlgMode2mbedtlsString[pCtx->hashMode] );
466 if (NULL == md_info) {
467 return CC_SRP_PARAM_INVALID_ERROR;
468 }
469 rc = mbedtls_md(md_info,
470 pUserName,
471 userNameSize,
472 (unsigned char *)hashResultBuff);
473 if (rc != 0) {
474 return rc;
475 }
476 CC_PalMemCopy(pCtx->userNameDigest, (uint8_t *)hashResultBuff, pCtx->hashDigestSize);
477
478 return rc;
479 }
480
481 // SHA((SHA(N) XOR SHA(g))|SHA(U)|s|A|B|K)
SRP_UserProofCalc2(uint8_t * pSalt,size_t saltSize,mbedtls_srp_modulus userPubKeyA,mbedtls_srp_modulus hostPubKeyB,mbedtls_srp_sessionKey sessionKey,mbedtls_srp_digest userProof,mbedtls_srp_context * pCtx)482 uint32_t SRP_UserProofCalc2(uint8_t *pSalt,
483 size_t saltSize,
484 mbedtls_srp_modulus userPubKeyA,
485 mbedtls_srp_modulus hostPubKeyB,
486 mbedtls_srp_sessionKey sessionKey,
487 mbedtls_srp_digest userProof, // out
488 mbedtls_srp_context *pCtx)
489 {
490 CCError_t rc = 0;
491 CCHashResultBuf_t hashResultBuff;
492 size_t hashDigestSize;
493 size_t modSize;
494 uint32_t i = 0;
495 uint8_t *pPubKey;
496 size_t pubKeySize;
497 CCHashResultBuf_t buff1 = {0};
498 CCHashResultBuf_t buff2 = {0};
499 CCHashOperationMode_t hashMode;
500 mbedtls_md_context_t hash_ctx;
501
502 const mbedtls_md_info_t *md_info=NULL;
503 mbedtls_md_context_t *md_ctx=NULL;
504
505 // verify input
506 if ((pSalt == NULL) ||
507 (saltSize < CC_SRP_MIN_SALT_SIZE) || (saltSize > CC_SRP_MAX_SALT_SIZE) ||
508 (userPubKeyA == NULL) ||
509 (hostPubKeyB == NULL) ||
510 (sessionKey == NULL) ||
511 (userProof == NULL) ||
512 (pCtx == NULL)) {
513 return CC_SRP_PARAM_INVALID_ERROR;
514 }
515
516 hashDigestSize = pCtx->hashDigestSize;
517 modSize = CALC_FULL_BYTES(pCtx->groupParam.modSizeInBits);
518 hashMode = pCtx->hashMode;
519
520 CC_PalMemSetZero(userProof, sizeof(mbedtls_srp_digest));
521
522 // SHA(N)
523 md_info = mbedtls_md_info_from_string( HashAlgMode2mbedtlsString[hashMode] );
524 if (NULL == md_info) {
525 rc = CC_SRP_PARAM_INVALID_ERROR;
526 goto End;
527 }
528 rc = mbedtls_md(md_info,
529 pCtx->groupParam.modulus,
530 CALC_FULL_BYTES(pCtx->groupParam.modSizeInBits),
531 (unsigned char *)buff1);
532 if (rc != 0) {
533 goto End;
534 }
535
536 // SHA(g)
537 rc = mbedtls_md(md_info,
538 &pCtx->groupParam.gen,
539 sizeof(pCtx->groupParam.gen),
540 (unsigned char *)buff2);
541 if (rc != 0) {
542 goto End;
543 }
544 // XOR SHA(N)^=SHA(g)
545 for (i = 0; i < CALC_32BIT_WORDS_FROM_BYTES(hashDigestSize); i++) {
546 buff1[i] ^= buff2[i];
547 }
548 md_info = mbedtls_md_info_from_string( HashAlgMode2mbedtlsString[hashMode] );
549 if (NULL == md_info) {
550 rc = CC_SRP_PARAM_INVALID_ERROR;
551 goto End;
552 }
553 md_ctx = &hash_ctx;
554 mbedtls_md_init(md_ctx);
555 rc = mbedtls_md_setup(md_ctx, md_info, 0); // 0 = HASH, not HMAC
556 if (rc != 0) {
557 goto End;
558 }
559 rc = mbedtls_md_starts(md_ctx);
560 if (rc != 0) {
561 goto End;
562 }
563 // Update(SHA(N)^=SHA(g))
564 rc = mbedtls_md_update(md_ctx, (uint8_t *)buff1, hashDigestSize);
565 if (rc != 0) {
566 goto End;
567 }
568 // Update(SHA(U))
569 rc = mbedtls_md_update(md_ctx, pCtx->userNameDigest, hashDigestSize);
570 if (rc != 0) {
571 goto End;
572 }
573 //Update(salt)
574 rc = mbedtls_md_update(md_ctx, pSalt, saltSize);
575 if (rc != 0) {
576 goto End;
577 }
578 //Update(A)
579 REMOVE_LEADING_BYTE_ZEROS((uint8_t *)userPubKeyA, modSize, pPubKey, pubKeySize);
580 rc = mbedtls_md_update(md_ctx, (uint8_t *)pPubKey, pubKeySize);
581 if (rc != 0) {
582 goto End;
583 }
584 //Update(B)
585 REMOVE_LEADING_BYTE_ZEROS((uint8_t *)hostPubKeyB, modSize, pPubKey, pubKeySize);
586 rc = mbedtls_md_update(md_ctx, (uint8_t *)pPubKey, pubKeySize);
587 if (rc != 0) {
588 goto End;
589 }
590 //Update(K)
591 rc = mbedtls_md_update(md_ctx, (uint8_t *)sessionKey, pCtx->sessionKeySize);
592 if (rc != 0) {
593 goto End;
594 }
595 rc = mbedtls_md_finish(md_ctx, (unsigned char *)hashResultBuff);
596 if (rc != 0) {
597 goto End;
598 }
599 CC_PalMemCopy(userProof, (uint8_t *)hashResultBuff, hashDigestSize);
600
601 End:
602 if((md_info!=NULL) && (md_ctx!=NULL)) {
603 mbedtls_md_free(md_ctx);
604 }
605
606 return rc;
607 }
608
609
610
611 // SHA(A|M1|K)
SRP_HostProofCalc(mbedtls_srp_modulus userPubKeyA,mbedtls_srp_digest userProof,mbedtls_srp_sessionKey sessionKey,mbedtls_srp_digest hostProof,mbedtls_srp_context * pCtx)612 uint32_t SRP_HostProofCalc(mbedtls_srp_modulus userPubKeyA,
613 mbedtls_srp_digest userProof,
614 mbedtls_srp_sessionKey sessionKey,
615 mbedtls_srp_digest hostProof, // out
616 mbedtls_srp_context *pCtx)
617 {
618 CCError_t rc = 0;
619 size_t hashDigestSize;
620 CCHashResultBuf_t hashResultBuff;
621 const mbedtls_md_info_t *md_info=NULL;
622 mbedtls_md_context_t hash_ctx;
623 uint8_t *pPubKey;
624 size_t pubKeySize;
625
626 // verify input
627 if ((userPubKeyA == NULL) ||
628 (userProof == NULL) ||
629 (sessionKey == NULL) ||
630 (hostProof == NULL) ||
631 (pCtx == NULL)) {
632 return CC_SRP_PARAM_INVALID_ERROR;
633 }
634 hashDigestSize = pCtx->hashDigestSize;
635
636 CC_PalMemSetZero(hostProof, sizeof(mbedtls_srp_digest));
637
638 md_info = mbedtls_md_info_from_string( HashAlgMode2mbedtlsString[pCtx->hashMode] );
639 if (NULL == md_info) {
640 rc = CC_SRP_PARAM_INVALID_ERROR;
641 goto End;
642 }
643 mbedtls_md_init(&hash_ctx);
644 rc = mbedtls_md_setup(&hash_ctx, md_info, 0); // 0 = HASH, not HMAC
645 if (rc != 0) {
646 goto End;
647 }
648 rc = mbedtls_md_starts(&hash_ctx);
649 if (rc != 0) {
650 goto End;
651 }
652 REMOVE_LEADING_BYTE_ZEROS((uint8_t *)userPubKeyA, CALC_FULL_BYTES(pCtx->groupParam.modSizeInBits), pPubKey, pubKeySize);
653 rc = mbedtls_md_update(&hash_ctx, (uint8_t *)pPubKey, pubKeySize);
654 if (rc != 0) {
655 goto End;
656 }
657 rc = mbedtls_md_update(&hash_ctx, (uint8_t *)userProof, hashDigestSize);
658 if (rc != 0) {
659 goto End;
660 }
661 rc = mbedtls_md_update(&hash_ctx, (uint8_t *)sessionKey, pCtx->sessionKeySize);
662 if (rc != 0) {
663 goto End;
664 }
665 rc = mbedtls_md_finish(&hash_ctx, (unsigned char *)hashResultBuff);
666 if (rc != 0) {
667 goto End;
668 }
669 CC_PalMemCopy(hostProof, (uint8_t *)hashResultBuff, hashDigestSize);
670
671 End:
672 if (NULL != md_info) {
673 mbedtls_md_free(&hash_ctx);
674 }
675
676 return rc;
677 }
678
SRP_SessionKeyCalc(uint8_t * pInBuff,size_t inBuffSize,mbedtls_srp_sessionKey sessionKey,mbedtls_srp_context * pCtx)679 uint32_t SRP_SessionKeyCalc(uint8_t *pInBuff, /* in buff to hash*/
680 size_t inBuffSize, /* in buffer size */
681 mbedtls_srp_sessionKey sessionKey, /* out hash interleave buff - shared secret */
682 mbedtls_srp_context *pCtx)
683 {
684 CCError_t rc = 0;
685
686 //Verify inputs
687 if ((pInBuff == NULL) ||
688 (inBuffSize == 0) || (inBuffSize > CC_SRP_MAX_MODULUS) ||
689 (sessionKey == NULL) ||
690 (pCtx == NULL)) {
691 return CC_SRP_PARAM_INVALID_ERROR;
692 }
693
694 CC_PalMemSetZero(sessionKey, sizeof(mbedtls_srp_sessionKey));
695
696 switch(pCtx->srpVer) {
697 case CC_SRP_VER_HK:
698 rc = SRP_shaInterleaveHK(pInBuff, inBuffSize, sessionKey, pCtx);
699 break;
700 case CC_SRP_VER_3:
701 case CC_SRP_VER_6:
702 /* Does 6A requires sha-interleave or just sha?
703 * see details in Cerberus confluence */
704 case CC_SRP_VER_6A:
705 rc = SRP_shaInterleave(pInBuff, inBuffSize, sessionKey, pCtx);
706 break;
707 default: // should not reach here
708 return CC_SRP_PARAM_INVALID_ERROR;
709 }
710 return rc;
711 }
712
713
SRP_SecureMemCmp(const uint8_t * aTarget,const uint8_t * aSource,size_t aSize)714 uint32_t SRP_SecureMemCmp( const uint8_t* aTarget, /*!< [in] The target buffer to compare. */
715 const uint8_t* aSource, /*!< [in] The Source buffer to compare to. */
716 size_t aSize /*!< [in] Number of bytes to compare. */)
717 {
718 uint32_t i;
719 uint32_t stat = 0;
720
721 for( i = 0; i < aSize; i++ ) {
722 stat |= (aTarget[i] ^ aSource[i]);
723 }
724
725 return stat;
726 }
727