wolf SSL / wolfSSL-TLS13-Beta

Fork of wolfSSL by wolf SSL

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-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