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