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