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