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.
Fork of wolfSSL by
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 #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 SHA_DIGEST_SIZE; 00161 #else 00162 return 0; 00163 #endif 00164 00165 case SRP_TYPE_SHA256: 00166 #ifndef NO_SHA256 00167 return SHA256_DIGEST_SIZE; 00168 #else 00169 return 0; 00170 #endif 00171 00172 case SRP_TYPE_SHA384: 00173 #ifdef WOLFSSL_SHA384 00174 return SHA384_DIGEST_SIZE; 00175 #else 00176 return 0; 00177 #endif 00178 00179 case SRP_TYPE_SHA512: 00180 #ifdef WOLFSSL_SHA512 00181 return 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 00273 if (srp->salt) { 00274 ForceZero(srp->salt, srp->saltSz); 00275 XFREE(srp->salt, srp->heap, DYNAMIC_TYPE_SRP); 00276 } 00277 if (srp->user) { 00278 ForceZero(srp->user, srp->userSz); 00279 XFREE(srp->user, srp->heap, DYNAMIC_TYPE_SRP); 00280 } 00281 if (srp->key) { 00282 ForceZero(srp->key, srp->keySz); 00283 XFREE(srp->key, srp->heap, DYNAMIC_TYPE_SRP); 00284 } 00285 00286 ForceZero(srp, sizeof(Srp)); 00287 } 00288 } 00289 00290 int wc_SrpSetUsername(Srp* srp, const byte* username, word32 size) 00291 { 00292 if (!srp || !username) 00293 return BAD_FUNC_ARG; 00294 00295 srp->user = (byte*)XMALLOC(size, srp->heap, DYNAMIC_TYPE_SRP); 00296 if (srp->user == NULL) 00297 return MEMORY_E; 00298 00299 srp->userSz = size; 00300 XMEMCPY(srp->user, username, srp->userSz); 00301 00302 return 0; 00303 } 00304 00305 int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, 00306 const byte* g, word32 gSz, 00307 const byte* salt, word32 saltSz) 00308 { 00309 SrpHash hash; 00310 byte digest1[SRP_MAX_DIGEST_SIZE]; 00311 byte digest2[SRP_MAX_DIGEST_SIZE]; 00312 byte pad = 0; 00313 int i, r; 00314 int j = 0; 00315 00316 if (!srp || !N || !g || !salt || nSz < gSz) 00317 return BAD_FUNC_ARG; 00318 00319 if (!srp->user) 00320 return SRP_CALL_ORDER_E; 00321 00322 /* Set N */ 00323 if (mp_read_unsigned_bin(&srp->N, N, nSz) != MP_OKAY) 00324 return MP_READ_E; 00325 00326 if (mp_count_bits(&srp->N) < SRP_MODULUS_MIN_BITS) 00327 return BAD_FUNC_ARG; 00328 00329 /* Set g */ 00330 if (mp_read_unsigned_bin(&srp->g, g, gSz) != MP_OKAY) 00331 return MP_READ_E; 00332 00333 if (mp_cmp(&srp->N, &srp->g) != MP_GT) 00334 return BAD_FUNC_ARG; 00335 00336 /* Set salt */ 00337 if (srp->salt) { 00338 ForceZero(srp->salt, srp->saltSz); 00339 XFREE(srp->salt, srp->heap, DYNAMIC_TYPE_SRP); 00340 } 00341 00342 srp->salt = (byte*)XMALLOC(saltSz, srp->heap, DYNAMIC_TYPE_SRP); 00343 if (srp->salt == NULL) 00344 return MEMORY_E; 00345 00346 XMEMCPY(srp->salt, salt, saltSz); 00347 srp->saltSz = saltSz; 00348 00349 /* Set k = H(N, g) */ 00350 r = SrpHashInit(&hash, srp->type); 00351 if (!r) r = SrpHashUpdate(&hash, (byte*) N, nSz); 00352 for (i = 0; (word32)i < nSz - gSz; i++) { 00353 if (!r) r = SrpHashUpdate(&hash, &pad, 1); 00354 } 00355 if (!r) r = SrpHashUpdate(&hash, (byte*) g, gSz); 00356 if (!r) r = SrpHashFinal(&hash, srp->k); 00357 00358 /* update client proof */ 00359 00360 /* digest1 = H(N) */ 00361 if (!r) r = SrpHashInit(&hash, srp->type); 00362 if (!r) r = SrpHashUpdate(&hash, (byte*) N, nSz); 00363 if (!r) r = SrpHashFinal(&hash, digest1); 00364 00365 /* digest2 = H(g) */ 00366 if (!r) r = SrpHashInit(&hash, srp->type); 00367 if (!r) r = SrpHashUpdate(&hash, (byte*) g, gSz); 00368 if (!r) r = SrpHashFinal(&hash, digest2); 00369 00370 /* digest1 = H(N) ^ H(g) */ 00371 if (r == 0) { 00372 for (i = 0, j = SrpHashSize(srp->type); i < j; i++) 00373 digest1[i] ^= digest2[i]; 00374 } 00375 00376 /* digest2 = H(user) */ 00377 if (!r) r = SrpHashInit(&hash, srp->type); 00378 if (!r) r = SrpHashUpdate(&hash, srp->user, srp->userSz); 00379 if (!r) r = SrpHashFinal(&hash, digest2); 00380 00381 /* client proof = H( H(N) ^ H(g) | H(user) | salt) */ 00382 if (!r) r = SrpHashUpdate(&srp->client_proof, digest1, j); 00383 if (!r) r = SrpHashUpdate(&srp->client_proof, digest2, j); 00384 if (!r) r = SrpHashUpdate(&srp->client_proof, salt, saltSz); 00385 00386 return r; 00387 } 00388 00389 int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size) 00390 { 00391 SrpHash hash; 00392 byte digest[SRP_MAX_DIGEST_SIZE]; 00393 word32 digestSz; 00394 int r; 00395 00396 if (!srp || !password || srp->side != SRP_CLIENT_SIDE) 00397 return BAD_FUNC_ARG; 00398 00399 if (!srp->salt) 00400 return SRP_CALL_ORDER_E; 00401 00402 digestSz = SrpHashSize(srp->type); 00403 00404 /* digest = H(username | ':' | password) */ 00405 r = SrpHashInit(&hash, srp->type); 00406 if (!r) r = SrpHashUpdate(&hash, srp->user, srp->userSz); 00407 if (!r) r = SrpHashUpdate(&hash, (const byte*) ":", 1); 00408 if (!r) r = SrpHashUpdate(&hash, password, size); 00409 if (!r) r = SrpHashFinal(&hash, digest); 00410 00411 /* digest = H(salt | H(username | ':' | password)) */ 00412 if (!r) r = SrpHashInit(&hash, srp->type); 00413 if (!r) r = SrpHashUpdate(&hash, srp->salt, srp->saltSz); 00414 if (!r) r = SrpHashUpdate(&hash, digest, digestSz); 00415 if (!r) r = SrpHashFinal(&hash, digest); 00416 00417 /* Set x (private key) */ 00418 if (!r) r = mp_read_unsigned_bin(&srp->auth, digest, digestSz); 00419 00420 ForceZero(digest, SRP_MAX_DIGEST_SIZE); 00421 00422 return r; 00423 } 00424 00425 int wc_SrpGetVerifier(Srp* srp, byte* verifier, word32* size) 00426 { 00427 mp_int v; 00428 int r; 00429 00430 if (!srp || !verifier || !size || srp->side != SRP_CLIENT_SIDE) 00431 return BAD_FUNC_ARG; 00432 00433 if (mp_iszero(&srp->auth) == MP_YES) 00434 return SRP_CALL_ORDER_E; 00435 00436 r = mp_init(&v); 00437 if (r != MP_OKAY) 00438 return MP_INIT_E; 00439 00440 /* v = g ^ x % N */ 00441 if (!r) r = mp_exptmod(&srp->g, &srp->auth, &srp->N, &v); 00442 if (!r) r = *size < (word32)mp_unsigned_bin_size(&v) ? BUFFER_E : MP_OKAY; 00443 if (!r) r = mp_to_unsigned_bin(&v, verifier); 00444 if (!r) *size = mp_unsigned_bin_size(&v); 00445 00446 mp_clear(&v); 00447 00448 return r; 00449 } 00450 00451 int wc_SrpSetVerifier(Srp* srp, const byte* verifier, word32 size) 00452 { 00453 if (!srp || !verifier || srp->side != SRP_SERVER_SIDE) 00454 return BAD_FUNC_ARG; 00455 00456 return mp_read_unsigned_bin(&srp->auth, verifier, size); 00457 } 00458 00459 int wc_SrpSetPrivate(Srp* srp, const byte* priv, word32 size) 00460 { 00461 mp_int p; 00462 int r; 00463 00464 if (!srp || !priv || !size) 00465 return BAD_FUNC_ARG; 00466 00467 if (mp_iszero(&srp->auth) == MP_YES) 00468 return SRP_CALL_ORDER_E; 00469 00470 r = mp_init(&p); 00471 if (r != MP_OKAY) 00472 return MP_INIT_E; 00473 if (!r) r = mp_read_unsigned_bin(&p, priv, size); 00474 if (!r) r = mp_mod(&p, &srp->N, &srp->priv); 00475 if (!r) r = mp_iszero(&srp->priv) == MP_YES ? SRP_BAD_KEY_E : 0; 00476 00477 mp_clear(&p); 00478 00479 return r; 00480 } 00481 00482 /** Generates random data using wolfcrypt RNG. */ 00483 static int wc_SrpGenPrivate(Srp* srp, byte* priv, word32 size) 00484 { 00485 WC_RNG rng; 00486 int r = wc_InitRng(&rng); 00487 00488 if (!r) r = wc_RNG_GenerateBlock(&rng, priv, size); 00489 if (!r) r = wc_SrpSetPrivate(srp, priv, size); 00490 if (!r) wc_FreeRng(&rng); 00491 00492 return r; 00493 } 00494 00495 int wc_SrpGetPublic(Srp* srp, byte* pub, word32* size) 00496 { 00497 mp_int pubkey; 00498 word32 modulusSz; 00499 int r; 00500 00501 if (!srp || !pub || !size) 00502 return BAD_FUNC_ARG; 00503 00504 if (mp_iszero(&srp->auth) == MP_YES) 00505 return SRP_CALL_ORDER_E; 00506 00507 modulusSz = mp_unsigned_bin_size(&srp->N); 00508 if (*size < modulusSz) 00509 return BUFFER_E; 00510 00511 r = mp_init(&pubkey); 00512 if (r != MP_OKAY) 00513 return MP_INIT_E; 00514 00515 /* priv = random() */ 00516 if (mp_iszero(&srp->priv) == MP_YES) 00517 r = wc_SrpGenPrivate(srp, pub, SRP_PRIVATE_KEY_MIN_BITS / 8); 00518 00519 /* client side: A = g ^ a % N */ 00520 if (srp->side == SRP_CLIENT_SIDE) { 00521 if (!r) r = mp_exptmod(&srp->g, &srp->priv, &srp->N, &pubkey); 00522 00523 /* server side: B = (k * v + (g ^ b % N)) % N */ 00524 } else { 00525 mp_int i, j; 00526 00527 if (mp_init_multi(&i, &j, 0, 0, 0, 0) == MP_OKAY) { 00528 if (!r) r = mp_read_unsigned_bin(&i, srp->k,SrpHashSize(srp->type)); 00529 if (!r) r = mp_iszero(&i) == MP_YES ? SRP_BAD_KEY_E : 0; 00530 if (!r) r = mp_exptmod(&srp->g, &srp->priv, &srp->N, &pubkey); 00531 if (!r) r = mp_mulmod(&i, &srp->auth, &srp->N, &j); 00532 if (!r) r = mp_add(&j, &pubkey, &i); 00533 if (!r) r = mp_mod(&i, &srp->N, &pubkey); 00534 00535 mp_clear(&i); mp_clear(&j); 00536 } 00537 } 00538 00539 /* extract public key to buffer */ 00540 XMEMSET(pub, 0, modulusSz); 00541 if (!r) r = mp_to_unsigned_bin(&pubkey, pub); 00542 if (!r) *size = mp_unsigned_bin_size(&pubkey); 00543 mp_clear(&pubkey); 00544 00545 return r; 00546 } 00547 00548 static int wc_SrpSetKey(Srp* srp, byte* secret, word32 size) 00549 { 00550 SrpHash hash; 00551 byte digest[SRP_MAX_DIGEST_SIZE]; 00552 word32 i, j, digestSz = SrpHashSize(srp->type); 00553 byte counter[4]; 00554 int r = BAD_FUNC_ARG; 00555 00556 XMEMSET(digest, 0, SRP_MAX_DIGEST_SIZE); 00557 00558 srp->key = (byte*)XMALLOC(2 * digestSz, srp->heap, DYNAMIC_TYPE_SRP); 00559 if (srp->key == NULL) 00560 return MEMORY_E; 00561 00562 srp->keySz = 2 * digestSz; 00563 00564 for (i = j = 0; j < srp->keySz; i++) { 00565 counter[0] = (i >> 24) & 0xFF; 00566 counter[1] = (i >> 16) & 0xFF; 00567 counter[2] = (i >> 8) & 0xFF; 00568 counter[3] = i & 0xFF; 00569 00570 r = SrpHashInit(&hash, srp->type); 00571 if (!r) r = SrpHashUpdate(&hash, secret, size); 00572 if (!r) r = SrpHashUpdate(&hash, counter, 4); 00573 00574 if (j + digestSz > srp->keySz) { 00575 if (!r) r = SrpHashFinal(&hash, digest); 00576 XMEMCPY(srp->key + j, digest, srp->keySz - j); 00577 j = srp->keySz; 00578 } 00579 else { 00580 if (!r) r = SrpHashFinal(&hash, srp->key + j); 00581 j += digestSz; 00582 } 00583 } 00584 00585 ForceZero(digest, sizeof(digest)); 00586 ForceZero(&hash, sizeof(SrpHash)); 00587 00588 return r; 00589 } 00590 00591 int wc_SrpComputeKey(Srp* srp, byte* clientPubKey, word32 clientPubKeySz, 00592 byte* serverPubKey, word32 serverPubKeySz) 00593 { 00594 SrpHash hash; 00595 byte *secret; 00596 byte digest[SRP_MAX_DIGEST_SIZE]; 00597 word32 i, secretSz, digestSz; 00598 mp_int u, s, temp1, temp2; 00599 byte pad = 0; 00600 int r; 00601 00602 /* validating params */ 00603 00604 if (!srp || !clientPubKey || clientPubKeySz == 0 00605 || !serverPubKey || serverPubKeySz == 0) 00606 return BAD_FUNC_ARG; 00607 00608 if (mp_iszero(&srp->priv) == MP_YES) 00609 return SRP_CALL_ORDER_E; 00610 00611 /* initializing variables */ 00612 00613 if ((r = SrpHashInit(&hash, srp->type)) != 0) 00614 return r; 00615 00616 digestSz = SrpHashSize(srp->type); 00617 secretSz = mp_unsigned_bin_size(&srp->N); 00618 00619 if ((secret = (byte*)XMALLOC(secretSz, srp->heap, DYNAMIC_TYPE_SRP)) ==NULL) 00620 return MEMORY_E; 00621 00622 if ((r = mp_init_multi(&u, &s, &temp1, &temp2, 0, 0)) != MP_OKAY) { 00623 XFREE(secret, srp->heap, DYNAMIC_TYPE_SRP); 00624 return r; 00625 } 00626 00627 /* building u (random scrambling parameter) */ 00628 00629 /* H(A) */ 00630 for (i = 0; !r && i < secretSz - clientPubKeySz; i++) 00631 r = SrpHashUpdate(&hash, &pad, 1); 00632 if (!r) r = SrpHashUpdate(&hash, clientPubKey, clientPubKeySz); 00633 00634 /* H(A | B) */ 00635 for (i = 0; !r && i < secretSz - serverPubKeySz; i++) 00636 r = SrpHashUpdate(&hash, &pad, 1); 00637 if (!r) r = SrpHashUpdate(&hash, serverPubKey, serverPubKeySz); 00638 00639 /* set u */ 00640 if (!r) r = SrpHashFinal(&hash, digest); 00641 if (!r) r = mp_read_unsigned_bin(&u, digest, SrpHashSize(srp->type)); 00642 00643 /* building s (secret) */ 00644 00645 if (!r && srp->side == SRP_CLIENT_SIDE) { 00646 00647 /* temp1 = B - k * v; rejects k == 0, B == 0 and B >= N. */ 00648 r = mp_read_unsigned_bin(&temp1, srp->k, digestSz); 00649 if (!r) r = mp_iszero(&temp1) == MP_YES ? SRP_BAD_KEY_E : 0; 00650 if (!r) r = mp_exptmod(&srp->g, &srp->auth, &srp->N, &temp2); 00651 if (!r) r = mp_mulmod(&temp1, &temp2, &srp->N, &s); 00652 if (!r) r = mp_read_unsigned_bin(&temp2, serverPubKey, serverPubKeySz); 00653 if (!r) r = mp_iszero(&temp2) == MP_YES ? SRP_BAD_KEY_E : 0; 00654 if (!r) r = mp_cmp(&temp2, &srp->N) != MP_LT ? SRP_BAD_KEY_E : 0; 00655 if (!r) r = mp_sub(&temp2, &s, &temp1); 00656 00657 /* temp2 = a + u * x */ 00658 if (!r) r = mp_mulmod(&u, &srp->auth, &srp->N, &s); 00659 if (!r) r = mp_add(&srp->priv, &s, &temp2); 00660 00661 /* secret = temp1 ^ temp2 % N */ 00662 if (!r) r = mp_exptmod(&temp1, &temp2, &srp->N, &s); 00663 00664 } else if (!r && srp->side == SRP_SERVER_SIDE) { 00665 /* temp1 = v ^ u % N */ 00666 r = mp_exptmod(&srp->auth, &u, &srp->N, &temp1); 00667 00668 /* temp2 = A * temp1 % N; rejects A == 0, A >= N */ 00669 if (!r) r = mp_read_unsigned_bin(&s, clientPubKey, clientPubKeySz); 00670 if (!r) r = mp_iszero(&s) == MP_YES ? SRP_BAD_KEY_E : 0; 00671 if (!r) r = mp_cmp(&s, &srp->N) != MP_LT ? SRP_BAD_KEY_E : 0; 00672 if (!r) r = mp_mulmod(&s, &temp1, &srp->N, &temp2); 00673 00674 /* rejects A * v ^ u % N >= 1, A * v ^ u % N == -1 % N */ 00675 if (!r) r = mp_read_unsigned_bin(&temp1, (const byte*)"\001", 1); 00676 if (!r) r = mp_cmp(&temp2, &temp1) != MP_GT ? SRP_BAD_KEY_E : 0; 00677 if (!r) r = mp_sub(&srp->N, &temp1, &s); 00678 if (!r) r = mp_cmp(&temp2, &s) == MP_EQ ? SRP_BAD_KEY_E : 0; 00679 00680 /* secret = temp2 * b % N */ 00681 if (!r) r = mp_exptmod(&temp2, &srp->priv, &srp->N, &s); 00682 } 00683 00684 /* building session key from secret */ 00685 00686 if (!r) r = mp_to_unsigned_bin(&s, secret); 00687 if (!r) r = srp->keyGenFunc_cb(srp, secret, mp_unsigned_bin_size(&s)); 00688 00689 /* updating client proof = H( H(N) ^ H(g) | H(user) | salt | A | B | K) */ 00690 00691 if (!r) r = SrpHashUpdate(&srp->client_proof, clientPubKey, clientPubKeySz); 00692 if (!r) r = SrpHashUpdate(&srp->client_proof, serverPubKey, serverPubKeySz); 00693 if (!r) r = SrpHashUpdate(&srp->client_proof, srp->key, srp->keySz); 00694 00695 /* updating server proof = H(A) */ 00696 00697 if (!r) r = SrpHashUpdate(&srp->server_proof, clientPubKey, clientPubKeySz); 00698 00699 XFREE(secret, srp->heap, DYNAMIC_TYPE_SRP); 00700 mp_clear(&u); mp_clear(&s); mp_clear(&temp1); mp_clear(&temp2); 00701 00702 return r; 00703 } 00704 00705 int wc_SrpGetProof(Srp* srp, byte* proof, word32* size) 00706 { 00707 int r; 00708 00709 if (!srp || !proof || !size) 00710 return BAD_FUNC_ARG; 00711 00712 if (*size < SrpHashSize(srp->type)) 00713 return BUFFER_E; 00714 00715 if ((r = SrpHashFinal(srp->side == SRP_CLIENT_SIDE 00716 ? &srp->client_proof 00717 : &srp->server_proof, proof)) != 0) 00718 return r; 00719 00720 *size = SrpHashSize(srp->type); 00721 00722 if (srp->side == SRP_CLIENT_SIDE) { 00723 /* server proof = H( A | client proof | K) */ 00724 if (!r) r = SrpHashUpdate(&srp->server_proof, proof, *size); 00725 if (!r) r = SrpHashUpdate(&srp->server_proof, srp->key, srp->keySz); 00726 } 00727 00728 return r; 00729 } 00730 00731 int wc_SrpVerifyPeersProof(Srp* srp, byte* proof, word32 size) 00732 { 00733 byte digest[SRP_MAX_DIGEST_SIZE]; 00734 int r; 00735 00736 if (!srp || !proof) 00737 return BAD_FUNC_ARG; 00738 00739 if (size != SrpHashSize(srp->type)) 00740 return BUFFER_E; 00741 00742 r = SrpHashFinal(srp->side == SRP_CLIENT_SIDE ? &srp->server_proof 00743 : &srp->client_proof, digest); 00744 00745 if (srp->side == SRP_SERVER_SIDE) { 00746 /* server proof = H( A | client proof | K) */ 00747 if (!r) r = SrpHashUpdate(&srp->server_proof, proof, size); 00748 if (!r) r = SrpHashUpdate(&srp->server_proof, srp->key, srp->keySz); 00749 } 00750 00751 if (!r && XMEMCMP(proof, digest, size) != 0) 00752 r = SRP_VERIFY_E; 00753 00754 return r; 00755 } 00756 00757 #endif /* WOLFCRYPT_HAVE_SRP */ 00758
Generated on Tue Jul 12 2022 23:30:59 by
1.7.2
