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