Xuyi Wang / wolfcrypt

Dependents:   OS

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers srp.c Source File

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