Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
srp.c
00001 /* srp.c 00002 * 00003 * Copyright (C) 2006-2016 wolfSSL Inc. 00004 * 00005 * This file is part of wolfSSL. 00006 * 00007 * wolfSSL is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 2 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * wolfSSL is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA 00020 */ 00021 00022 00023 #ifdef HAVE_CONFIG_H 00024 #include <config.h> 00025 #endif 00026 00027 #include <wolfssl/wolfcrypt/settings.h> 00028 00029 #ifdef WOLFCRYPT_HAVE_SRP 00030 00031 #include <wolfssl/wolfcrypt/srp.h> 00032 #include <wolfssl/wolfcrypt/random.h> 00033 #include <wolfssl/wolfcrypt/error-crypt.h> 00034 00035 #ifdef NO_INLINE 00036 #include <wolfssl/wolfcrypt/misc.h> 00037 #else 00038 #include <wolfcrypt/src/misc.c> 00039 #endif 00040 00041 /** Computes the session key using the Mask Generation Function 1. */ 00042 static int wc_SrpSetKey(Srp* srp, byte* secret, word32 size); 00043 00044 static int SrpHashInit(SrpHash* hash, SrpType type) 00045 { 00046 hash->type = type; 00047 00048 switch (type) { 00049 case SRP_TYPE_SHA: 00050 #ifndef NO_SHA 00051 return wc_InitSha(&hash->data.sha); 00052 #else 00053 return BAD_FUNC_ARG; 00054 #endif 00055 00056 case SRP_TYPE_SHA256: 00057 #ifndef NO_SHA256 00058 return wc_InitSha256(&hash->data.sha256); 00059 #else 00060 return BAD_FUNC_ARG; 00061 #endif 00062 00063 case SRP_TYPE_SHA384: 00064 #ifdef WOLFSSL_SHA384 00065 return wc_InitSha384(&hash->data.sha384); 00066 #else 00067 return BAD_FUNC_ARG; 00068 #endif 00069 00070 case SRP_TYPE_SHA512: 00071 #ifdef WOLFSSL_SHA512 00072 return wc_InitSha512(&hash->data.sha512); 00073 #else 00074 return BAD_FUNC_ARG; 00075 #endif 00076 00077 default: 00078 return BAD_FUNC_ARG; 00079 } 00080 } 00081 00082 static int SrpHashUpdate(SrpHash* hash, const byte* data, word32 size) 00083 { 00084 switch (hash->type) { 00085 case SRP_TYPE_SHA: 00086 #ifndef NO_SHA 00087 return wc_ShaUpdate(&hash->data.sha, data, size); 00088 #else 00089 return BAD_FUNC_ARG; 00090 #endif 00091 00092 case SRP_TYPE_SHA256: 00093 #ifndef NO_SHA256 00094 return wc_Sha256Update(&hash->data.sha256, data, size); 00095 #else 00096 return BAD_FUNC_ARG; 00097 #endif 00098 00099 case SRP_TYPE_SHA384: 00100 #ifdef WOLFSSL_SHA384 00101 return wc_Sha384Update(&hash->data.sha384, data, size); 00102 #else 00103 return BAD_FUNC_ARG; 00104 #endif 00105 00106 case SRP_TYPE_SHA512: 00107 #ifdef WOLFSSL_SHA512 00108 return wc_Sha512Update(&hash->data.sha512, data, size); 00109 #else 00110 return BAD_FUNC_ARG; 00111 #endif 00112 00113 default: 00114 return BAD_FUNC_ARG; 00115 } 00116 } 00117 00118 static int SrpHashFinal(SrpHash* hash, byte* digest) 00119 { 00120 switch (hash->type) { 00121 case SRP_TYPE_SHA: 00122 #ifndef NO_SHA 00123 return wc_ShaFinal(&hash->data.sha, digest); 00124 #else 00125 return BAD_FUNC_ARG; 00126 #endif 00127 00128 case SRP_TYPE_SHA256: 00129 #ifndef NO_SHA256 00130 return wc_Sha256Final(&hash->data.sha256, digest); 00131 #else 00132 return BAD_FUNC_ARG; 00133 #endif 00134 00135 case SRP_TYPE_SHA384: 00136 #ifdef WOLFSSL_SHA384 00137 return wc_Sha384Final(&hash->data.sha384, digest); 00138 #else 00139 return BAD_FUNC_ARG; 00140 #endif 00141 00142 case SRP_TYPE_SHA512: 00143 #ifdef WOLFSSL_SHA512 00144 return wc_Sha512Final(&hash->data.sha512, digest); 00145 #else 00146 return BAD_FUNC_ARG; 00147 #endif 00148 00149 default: 00150 return BAD_FUNC_ARG; 00151 } 00152 } 00153 00154 static word32 SrpHashSize(SrpType type) 00155 { 00156 switch (type) { 00157 case SRP_TYPE_SHA: 00158 #ifndef NO_SHA 00159 return SHA_DIGEST_SIZE; 00160 #else 00161 return 0; 00162 #endif 00163 00164 case SRP_TYPE_SHA256: 00165 #ifndef NO_SHA256 00166 return SHA256_DIGEST_SIZE; 00167 #else 00168 return 0; 00169 #endif 00170 00171 case SRP_TYPE_SHA384: 00172 #ifdef WOLFSSL_SHA384 00173 return SHA384_DIGEST_SIZE; 00174 #else 00175 return 0; 00176 #endif 00177 00178 case SRP_TYPE_SHA512: 00179 #ifdef WOLFSSL_SHA512 00180 return SHA512_DIGEST_SIZE; 00181 #else 00182 return 0; 00183 #endif 00184 00185 default: 00186 return 0; 00187 } 00188 } 00189 00190 int wc_SrpInit(Srp* srp, SrpType type, SrpSide side) 00191 { 00192 int r; 00193 00194 /* validating params */ 00195 00196 if (!srp) 00197 return BAD_FUNC_ARG; 00198 00199 if (side != SRP_CLIENT_SIDE && side != SRP_SERVER_SIDE) 00200 return BAD_FUNC_ARG; 00201 00202 switch (type) { 00203 case SRP_TYPE_SHA: 00204 #ifdef NO_SHA 00205 return NOT_COMPILED_IN; 00206 #else 00207 break; /* OK */ 00208 #endif 00209 00210 case SRP_TYPE_SHA256: 00211 #ifdef NO_SHA256 00212 return NOT_COMPILED_IN; 00213 #else 00214 break; /* OK */ 00215 #endif 00216 00217 case SRP_TYPE_SHA384: 00218 #ifndef WOLFSSL_SHA384 00219 return NOT_COMPILED_IN; 00220 #else 00221 break; /* OK */ 00222 #endif 00223 00224 case SRP_TYPE_SHA512: 00225 #ifndef WOLFSSL_SHA512 00226 return NOT_COMPILED_IN; 00227 #else 00228 break; /* OK */ 00229 #endif 00230 00231 default: 00232 return BAD_FUNC_ARG; 00233 } 00234 00235 /* initializing variables */ 00236 00237 XMEMSET(srp, 0, sizeof(Srp)); 00238 00239 if ((r = SrpHashInit(&srp->client_proof, type)) != 0) 00240 return r; 00241 00242 if ((r = SrpHashInit(&srp->server_proof, type)) != 0) 00243 return r; 00244 00245 if ((r = mp_init_multi(&srp->N, &srp->g, &srp->auth, 00246 &srp->priv, 0, 0)) != 0) 00247 return r; 00248 00249 srp->side = side; srp->type = type; 00250 srp->salt = NULL; srp->saltSz = 0; 00251 srp->user = NULL; srp->userSz = 0; 00252 srp->key = NULL; srp->keySz = 0; 00253 00254 srp->keyGenFunc_cb = wc_SrpSetKey; 00255 00256 return 0; 00257 } 00258 00259 void wc_SrpTerm(Srp* srp) 00260 { 00261 if (srp) { 00262 mp_clear(&srp->N); mp_clear(&srp->g); 00263 mp_clear(&srp->auth); mp_clear(&srp->priv); 00264 00265 ForceZero(srp->salt, srp->saltSz); 00266 XFREE(srp->salt, NULL, DYNAMIC_TYPE_SRP); 00267 ForceZero(srp->user, srp->userSz); 00268 XFREE(srp->user, NULL, DYNAMIC_TYPE_SRP); 00269 ForceZero(srp->key, srp->keySz); 00270 XFREE(srp->key, NULL, DYNAMIC_TYPE_SRP); 00271 00272 ForceZero(srp, sizeof(Srp)); 00273 } 00274 } 00275 00276 int wc_SrpSetUsername(Srp* srp, const byte* username, word32 size) 00277 { 00278 if (!srp || !username) 00279 return BAD_FUNC_ARG; 00280 00281 srp->user = (byte*)XMALLOC(size, NULL, DYNAMIC_TYPE_SRP); 00282 if (srp->user == NULL) 00283 return MEMORY_E; 00284 00285 srp->userSz = size; 00286 XMEMCPY(srp->user, username, srp->userSz); 00287 00288 return 0; 00289 } 00290 00291 int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, 00292 const byte* g, word32 gSz, 00293 const byte* salt, word32 saltSz) 00294 { 00295 SrpHash hash; 00296 byte digest1[SRP_MAX_DIGEST_SIZE]; 00297 byte digest2[SRP_MAX_DIGEST_SIZE]; 00298 byte pad = 0; 00299 int i, j, r; 00300 00301 if (!srp || !N || !g || !salt || nSz < gSz) 00302 return BAD_FUNC_ARG; 00303 00304 if (!srp->user) 00305 return SRP_CALL_ORDER_E; 00306 00307 /* Set N */ 00308 if (mp_read_unsigned_bin(&srp->N, N, nSz) != MP_OKAY) 00309 return MP_READ_E; 00310 00311 if (mp_count_bits(&srp->N) < SRP_DEFAULT_MIN_BITS) 00312 return BAD_FUNC_ARG; 00313 00314 /* Set g */ 00315 if (mp_read_unsigned_bin(&srp->g, g, gSz) != MP_OKAY) 00316 return MP_READ_E; 00317 00318 if (mp_cmp(&srp->N, &srp->g) != MP_GT) 00319 return BAD_FUNC_ARG; 00320 00321 /* Set salt */ 00322 if (srp->salt) { 00323 ForceZero(srp->salt, srp->saltSz); 00324 XFREE(srp->salt, NULL, DYNAMIC_TYPE_SRP); 00325 } 00326 00327 srp->salt = (byte*)XMALLOC(saltSz, NULL, DYNAMIC_TYPE_SRP); 00328 if (srp->salt == NULL) 00329 return MEMORY_E; 00330 00331 XMEMCPY(srp->salt, salt, saltSz); 00332 srp->saltSz = saltSz; 00333 00334 /* Set k = H(N, g) */ 00335 r = SrpHashInit(&hash, srp->type); 00336 if (!r) r = SrpHashUpdate(&hash, (byte*) N, nSz); 00337 for (i = 0; (word32)i < nSz - gSz; i++) 00338 SrpHashUpdate(&hash, &pad, 1); 00339 if (!r) r = SrpHashUpdate(&hash, (byte*) g, gSz); 00340 if (!r) r = SrpHashFinal(&hash, srp->k); 00341 00342 /* update client proof */ 00343 00344 /* digest1 = H(N) */ 00345 if (!r) r = SrpHashInit(&hash, srp->type); 00346 if (!r) r = SrpHashUpdate(&hash, (byte*) N, nSz); 00347 if (!r) r = SrpHashFinal(&hash, digest1); 00348 00349 /* digest2 = H(g) */ 00350 if (!r) r = SrpHashInit(&hash, srp->type); 00351 if (!r) r = SrpHashUpdate(&hash, (byte*) g, gSz); 00352 if (!r) r = SrpHashFinal(&hash, digest2); 00353 00354 /* digest1 = H(N) ^ H(g) */ 00355 if (r == 0) { 00356 for (i = 0, j = SrpHashSize(srp->type); i < j; i++) 00357 digest1[i] ^= digest2[i]; 00358 } 00359 00360 /* digest2 = H(user) */ 00361 if (!r) r = SrpHashInit(&hash, srp->type); 00362 if (!r) r = SrpHashUpdate(&hash, srp->user, srp->userSz); 00363 if (!r) r = SrpHashFinal(&hash, digest2); 00364 00365 /* client proof = H( H(N) ^ H(g) | H(user) | salt) */ 00366 if (!r) r = SrpHashUpdate(&srp->client_proof, digest1, j); 00367 if (!r) r = SrpHashUpdate(&srp->client_proof, digest2, j); 00368 if (!r) r = SrpHashUpdate(&srp->client_proof, salt, saltSz); 00369 00370 return r; 00371 } 00372 00373 int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size) 00374 { 00375 SrpHash hash; 00376 byte digest[SRP_MAX_DIGEST_SIZE]; 00377 word32 digestSz; 00378 int r; 00379 00380 if (!srp || !password || srp->side != SRP_CLIENT_SIDE) 00381 return BAD_FUNC_ARG; 00382 00383 if (!srp->salt) 00384 return SRP_CALL_ORDER_E; 00385 00386 digestSz = SrpHashSize(srp->type); 00387 00388 /* digest = H(username | ':' | password) */ 00389 r = SrpHashInit(&hash, srp->type); 00390 if (!r) r = SrpHashUpdate(&hash, srp->user, srp->userSz); 00391 if (!r) r = SrpHashUpdate(&hash, (const byte*) ":", 1); 00392 if (!r) r = SrpHashUpdate(&hash, password, size); 00393 if (!r) r = SrpHashFinal(&hash, digest); 00394 00395 /* digest = H(salt | H(username | ':' | password)) */ 00396 if (!r) r = SrpHashInit(&hash, srp->type); 00397 if (!r) r = SrpHashUpdate(&hash, srp->salt, srp->saltSz); 00398 if (!r) r = SrpHashUpdate(&hash, digest, digestSz); 00399 if (!r) r = SrpHashFinal(&hash, digest); 00400 00401 /* Set x (private key) */ 00402 if (!r) r = mp_read_unsigned_bin(&srp->auth, digest, digestSz); 00403 00404 ForceZero(digest, SRP_MAX_DIGEST_SIZE); 00405 00406 return r; 00407 } 00408 00409 int wc_SrpGetVerifier(Srp* srp, byte* verifier, word32* size) 00410 { 00411 mp_int v; 00412 int r; 00413 00414 if (!srp || !verifier || !size || srp->side != SRP_CLIENT_SIDE) 00415 return BAD_FUNC_ARG; 00416 00417 if (mp_iszero(&srp->auth)) 00418 return SRP_CALL_ORDER_E; 00419 00420 r = mp_init(&v); 00421 if (r != MP_OKAY) 00422 return MP_INIT_E; 00423 00424 /* v = g ^ x % N */ 00425 if (!r) r = mp_exptmod(&srp->g, &srp->auth, &srp->N, &v); 00426 if (!r) r = *size < (word32)mp_unsigned_bin_size(&v) ? BUFFER_E : MP_OKAY; 00427 if (!r) r = mp_to_unsigned_bin(&v, verifier); 00428 if (!r) *size = mp_unsigned_bin_size(&v); 00429 00430 mp_clear(&v); 00431 00432 return r; 00433 } 00434 00435 int wc_SrpSetVerifier(Srp* srp, const byte* verifier, word32 size) 00436 { 00437 if (!srp || !verifier || srp->side != SRP_SERVER_SIDE) 00438 return BAD_FUNC_ARG; 00439 00440 return mp_read_unsigned_bin(&srp->auth, verifier, size); 00441 } 00442 00443 int wc_SrpSetPrivate(Srp* srp, const byte* private, word32 size) 00444 { 00445 mp_int p; 00446 int r; 00447 00448 if (!srp || !private || !size) 00449 return BAD_FUNC_ARG; 00450 00451 if (mp_iszero(&srp->auth)) 00452 return SRP_CALL_ORDER_E; 00453 00454 r = mp_init(&p); 00455 if (r != MP_OKAY) 00456 return MP_INIT_E; 00457 if (!r) r = mp_read_unsigned_bin(&p, private, size); 00458 if (!r) r = mp_mod(&p, &srp->N, &srp->priv); 00459 if (!r) r = mp_iszero(&srp->priv) ? SRP_BAD_KEY_E : 0; 00460 00461 mp_clear(&p); 00462 00463 return r; 00464 } 00465 00466 /** Generates random data using wolfcrypt RNG. */ 00467 static int wc_SrpGenPrivate(Srp* srp, byte* priv, word32 size) 00468 { 00469 WC_RNG rng; 00470 int r = wc_InitRng(&rng); 00471 00472 if (!r) r = wc_RNG_GenerateBlock(&rng, priv, size); 00473 if (!r) r = wc_SrpSetPrivate(srp, priv, size); 00474 if (!r) wc_FreeRng(&rng); 00475 00476 return r; 00477 } 00478 00479 int wc_SrpGetPublic(Srp* srp, byte* pub, word32* size) 00480 { 00481 mp_int pubkey; 00482 word32 modulusSz; 00483 int r; 00484 00485 if (!srp || !pub || !size) 00486 return BAD_FUNC_ARG; 00487 00488 if (mp_iszero(&srp->auth)) 00489 return SRP_CALL_ORDER_E; 00490 00491 modulusSz = mp_unsigned_bin_size(&srp->N); 00492 if (*size < modulusSz) 00493 return BUFFER_E; 00494 00495 r = mp_init(&pubkey); 00496 if (r != MP_OKAY) 00497 return MP_INIT_E; 00498 00499 /* priv = random() */ 00500 if (mp_iszero(&srp->priv)) 00501 r = wc_SrpGenPrivate(srp, pub, modulusSz); 00502 00503 /* client side: A = g ^ a % N */ 00504 if (srp->side == SRP_CLIENT_SIDE) { 00505 if (!r) r = mp_exptmod(&srp->g, &srp->priv, &srp->N, &pubkey); 00506 00507 /* server side: B = (k * v + (g ^ b % N)) % N */ 00508 } else { 00509 mp_int i, j; 00510 00511 if (mp_init_multi(&i, &j, 0, 0, 0, 0) == MP_OKAY) { 00512 if (!r) r = mp_read_unsigned_bin(&i, srp->k,SrpHashSize(srp->type)); 00513 if (!r) r = mp_iszero(&i) ? SRP_BAD_KEY_E : 0; 00514 if (!r) r = mp_exptmod(&srp->g, &srp->priv, &srp->N, &pubkey); 00515 if (!r) r = mp_mulmod(&i, &srp->auth, &srp->N, &j); 00516 if (!r) r = mp_add(&j, &pubkey, &i); 00517 if (!r) r = mp_mod(&i, &srp->N, &pubkey); 00518 00519 mp_clear(&i); mp_clear(&j); 00520 } 00521 } 00522 00523 /* extract public key to buffer */ 00524 XMEMSET(pub, 0, modulusSz); 00525 if (!r) r = mp_to_unsigned_bin(&pubkey, pub); 00526 if (!r) *size = mp_unsigned_bin_size(&pubkey); 00527 mp_clear(&pubkey); 00528 00529 return r; 00530 } 00531 00532 static int wc_SrpSetKey(Srp* srp, byte* secret, word32 size) 00533 { 00534 SrpHash hash; 00535 byte digest[SRP_MAX_DIGEST_SIZE]; 00536 word32 i, j, digestSz = SrpHashSize(srp->type); 00537 byte counter[4]; 00538 int r = BAD_FUNC_ARG; 00539 00540 srp->key = (byte*)XMALLOC(2 * digestSz, NULL, DYNAMIC_TYPE_SRP); 00541 if (srp->key == NULL) 00542 return MEMORY_E; 00543 00544 srp->keySz = 2 * digestSz; 00545 00546 for (i = j = 0; j < srp->keySz; i++) { 00547 counter[0] = (i >> 24) & 0xFF; 00548 counter[1] = (i >> 16) & 0xFF; 00549 counter[2] = (i >> 8) & 0xFF; 00550 counter[3] = i & 0xFF; 00551 00552 r = SrpHashInit(&hash, srp->type); 00553 if (!r) r = SrpHashUpdate(&hash, secret, size); 00554 if (!r) r = SrpHashUpdate(&hash, counter, 4); 00555 00556 if(j + digestSz > srp->keySz) { 00557 if (!r) r = SrpHashFinal(&hash, digest); 00558 XMEMCPY(srp->key + j, digest, srp->keySz - j); 00559 j = srp->keySz; 00560 } 00561 else { 00562 if (!r) r = SrpHashFinal(&hash, srp->key + j); 00563 j += digestSz; 00564 } 00565 } 00566 00567 ForceZero(digest, sizeof(digest)); 00568 ForceZero(&hash, sizeof(SrpHash)); 00569 00570 return r; 00571 } 00572 00573 int wc_SrpComputeKey(Srp* srp, byte* clientPubKey, word32 clientPubKeySz, 00574 byte* serverPubKey, word32 serverPubKeySz) 00575 { 00576 SrpHash hash; 00577 byte *secret; 00578 byte digest[SRP_MAX_DIGEST_SIZE]; 00579 word32 i, secretSz, digestSz; 00580 mp_int u, s, temp1, temp2; 00581 byte pad = 0; 00582 int r; 00583 00584 /* validating params */ 00585 00586 if (!srp || !clientPubKey || clientPubKeySz == 0 00587 || !serverPubKey || serverPubKeySz == 0) 00588 return BAD_FUNC_ARG; 00589 00590 if (mp_iszero(&srp->priv)) 00591 return SRP_CALL_ORDER_E; 00592 00593 /* initializing variables */ 00594 00595 if ((r = SrpHashInit(&hash, srp->type)) != 0) 00596 return r; 00597 00598 digestSz = SrpHashSize(srp->type); 00599 secretSz = mp_unsigned_bin_size(&srp->N); 00600 00601 if ((secret = (byte*)XMALLOC(secretSz, NULL, DYNAMIC_TYPE_SRP)) == NULL) 00602 return MEMORY_E; 00603 00604 if ((r = mp_init_multi(&u, &s, &temp1, &temp2, 0, 0)) != MP_OKAY) { 00605 XFREE(secret, NULL, DYNAMIC_TYPE_SRP); 00606 return r; 00607 } 00608 00609 /* building u (random scrambling parameter) */ 00610 00611 /* H(A) */ 00612 for (i = 0; !r && i < secretSz - clientPubKeySz; i++) 00613 r = SrpHashUpdate(&hash, &pad, 1); 00614 if (!r) r = SrpHashUpdate(&hash, clientPubKey, clientPubKeySz); 00615 00616 /* H(A | B) */ 00617 for (i = 0; !r && i < secretSz - serverPubKeySz; i++) 00618 r = SrpHashUpdate(&hash, &pad, 1); 00619 if (!r) r = SrpHashUpdate(&hash, serverPubKey, serverPubKeySz); 00620 00621 /* set u */ 00622 if (!r) r = SrpHashFinal(&hash, digest); 00623 if (!r) r = mp_read_unsigned_bin(&u, digest, SrpHashSize(srp->type)); 00624 00625 /* building s (secret) */ 00626 00627 if (!r && srp->side == SRP_CLIENT_SIDE) { 00628 00629 /* temp1 = B - k * v; rejects k == 0, B == 0 and B >= N. */ 00630 r = mp_read_unsigned_bin(&temp1, srp->k, digestSz); 00631 if (!r) r = mp_iszero(&temp1) ? SRP_BAD_KEY_E : 0; 00632 if (!r) r = mp_exptmod(&srp->g, &srp->auth, &srp->N, &temp2); 00633 if (!r) r = mp_mulmod(&temp1, &temp2, &srp->N, &s); 00634 if (!r) r = mp_read_unsigned_bin(&temp2, serverPubKey, serverPubKeySz); 00635 if (!r) r = mp_iszero(&temp2) ? SRP_BAD_KEY_E : 0; 00636 if (!r) r = mp_cmp(&temp2, &srp->N) != MP_LT ? SRP_BAD_KEY_E : 0; 00637 if (!r) r = mp_sub(&temp2, &s, &temp1); 00638 00639 /* temp2 = a + u * x */ 00640 if (!r) r = mp_mulmod(&u, &srp->auth, &srp->N, &s); 00641 if (!r) r = mp_add(&srp->priv, &s, &temp2); 00642 00643 /* secret = temp1 ^ temp2 % N */ 00644 if (!r) r = mp_exptmod(&temp1, &temp2, &srp->N, &s); 00645 00646 } else if (!r && srp->side == SRP_SERVER_SIDE) { 00647 /* temp1 = v ^ u % N */ 00648 r = mp_exptmod(&srp->auth, &u, &srp->N, &temp1); 00649 00650 /* temp2 = A * temp1 % N; rejects A == 0, A >= N */ 00651 if (!r) r = mp_read_unsigned_bin(&s, clientPubKey, clientPubKeySz); 00652 if (!r) r = mp_iszero(&s) ? SRP_BAD_KEY_E : 0; 00653 if (!r) r = mp_cmp(&s, &srp->N) != MP_LT ? SRP_BAD_KEY_E : 0; 00654 if (!r) r = mp_mulmod(&s, &temp1, &srp->N, &temp2); 00655 00656 /* rejects A * v ^ u % N >= 1, A * v ^ u % N == -1 % N */ 00657 if (!r) r = mp_read_unsigned_bin(&temp1, (const byte*)"\001", 1); 00658 if (!r) r = mp_cmp(&temp2, &temp1) != MP_GT ? SRP_BAD_KEY_E : 0; 00659 if (!r) r = mp_sub(&srp->N, &temp1, &s); 00660 if (!r) r = mp_cmp(&temp2, &s) == MP_EQ ? SRP_BAD_KEY_E : 0; 00661 00662 /* secret = temp2 * b % N */ 00663 if (!r) r = mp_exptmod(&temp2, &srp->priv, &srp->N, &s); 00664 } 00665 00666 /* building session key from secret */ 00667 00668 if (!r) r = mp_to_unsigned_bin(&s, secret); 00669 if (!r) r = srp->keyGenFunc_cb(srp, secret, mp_unsigned_bin_size(&s)); 00670 00671 /* updating client proof = H( H(N) ^ H(g) | H(user) | salt | A | B | K) */ 00672 00673 if (!r) r = SrpHashUpdate(&srp->client_proof, clientPubKey, clientPubKeySz); 00674 if (!r) r = SrpHashUpdate(&srp->client_proof, serverPubKey, serverPubKeySz); 00675 if (!r) r = SrpHashUpdate(&srp->client_proof, srp->key, srp->keySz); 00676 00677 /* updating server proof = H(A) */ 00678 00679 if (!r) r = SrpHashUpdate(&srp->server_proof, clientPubKey, clientPubKeySz); 00680 00681 XFREE(secret, NULL, DYNAMIC_TYPE_SRP); 00682 mp_clear(&u); mp_clear(&s); mp_clear(&temp1); mp_clear(&temp2); 00683 00684 return r; 00685 } 00686 00687 int wc_SrpGetProof(Srp* srp, byte* proof, word32* size) 00688 { 00689 int r; 00690 00691 if (!srp || !proof || !size) 00692 return BAD_FUNC_ARG; 00693 00694 if (*size < SrpHashSize(srp->type)) 00695 return BUFFER_E; 00696 00697 if ((r = SrpHashFinal(srp->side == SRP_CLIENT_SIDE 00698 ? &srp->client_proof 00699 : &srp->server_proof, proof)) != 0) 00700 return r; 00701 00702 *size = SrpHashSize(srp->type); 00703 00704 if (srp->side == SRP_CLIENT_SIDE) { 00705 /* server proof = H( A | client proof | K) */ 00706 if (!r) r = SrpHashUpdate(&srp->server_proof, proof, *size); 00707 if (!r) r = SrpHashUpdate(&srp->server_proof, srp->key, srp->keySz); 00708 } 00709 00710 return r; 00711 } 00712 00713 int wc_SrpVerifyPeersProof(Srp* srp, byte* proof, word32 size) 00714 { 00715 byte digest[SRP_MAX_DIGEST_SIZE]; 00716 int r; 00717 00718 if (!srp || !proof) 00719 return BAD_FUNC_ARG; 00720 00721 if (size != SrpHashSize(srp->type)) 00722 return BUFFER_E; 00723 00724 r = SrpHashFinal(srp->side == SRP_CLIENT_SIDE ? &srp->server_proof 00725 : &srp->client_proof, digest); 00726 00727 if (srp->side == SRP_SERVER_SIDE) { 00728 /* server proof = H( A | client proof | K) */ 00729 if (!r) r = SrpHashUpdate(&srp->server_proof, proof, size); 00730 if (!r) r = SrpHashUpdate(&srp->server_proof, srp->key, srp->keySz); 00731 } 00732 00733 if (!r && XMEMCMP(proof, digest, size) != 0) 00734 r = SRP_VERIFY_E; 00735 00736 return r; 00737 } 00738 00739 #endif /* WOLFCRYPT_HAVE_SRP */ 00740
Generated on Tue Jul 12 2022 15:55:21 by
1.7.2