1238384Sjkim/* crypto/srp/srp_lib.c */ 2280304Sjkim/* 3280304Sjkim * Written by Christophe Renou (christophe.renou@edelweb.fr) with the 4280304Sjkim * precious help of Peter Sylvester (peter.sylvester@edelweb.fr) for the 5280304Sjkim * EdelKey project and contributed to the OpenSSL project 2004. 6238384Sjkim */ 7238384Sjkim/* ==================================================================== 8238384Sjkim * Copyright (c) 2004 The OpenSSL Project. All rights reserved. 9238384Sjkim * 10238384Sjkim * Redistribution and use in source and binary forms, with or without 11238384Sjkim * modification, are permitted provided that the following conditions 12238384Sjkim * are met: 13238384Sjkim * 14238384Sjkim * 1. Redistributions of source code must retain the above copyright 15280304Sjkim * notice, this list of conditions and the following disclaimer. 16238384Sjkim * 17238384Sjkim * 2. Redistributions in binary form must reproduce the above copyright 18238384Sjkim * notice, this list of conditions and the following disclaimer in 19238384Sjkim * the documentation and/or other materials provided with the 20238384Sjkim * distribution. 21238384Sjkim * 22238384Sjkim * 3. All advertising materials mentioning features or use of this 23238384Sjkim * software must display the following acknowledgment: 24238384Sjkim * "This product includes software developed by the OpenSSL Project 25238384Sjkim * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 26238384Sjkim * 27238384Sjkim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 28238384Sjkim * endorse or promote products derived from this software without 29238384Sjkim * prior written permission. For written permission, please contact 30238384Sjkim * licensing@OpenSSL.org. 31238384Sjkim * 32238384Sjkim * 5. Products derived from this software may not be called "OpenSSL" 33238384Sjkim * nor may "OpenSSL" appear in their names without prior written 34238384Sjkim * permission of the OpenSSL Project. 35238384Sjkim * 36238384Sjkim * 6. Redistributions of any form whatsoever must retain the following 37238384Sjkim * acknowledgment: 38238384Sjkim * "This product includes software developed by the OpenSSL Project 39238384Sjkim * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 40238384Sjkim * 41238384Sjkim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 42238384Sjkim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43238384Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 44238384Sjkim * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 45238384Sjkim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 46238384Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 47238384Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 48238384Sjkim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 49238384Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 50238384Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 51238384Sjkim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 52238384Sjkim * OF THE POSSIBILITY OF SUCH DAMAGE. 53238384Sjkim * ==================================================================== 54238384Sjkim * 55238384Sjkim * This product includes cryptographic software written by Eric Young 56238384Sjkim * (eay@cryptsoft.com). This product includes software written by Tim 57238384Sjkim * Hudson (tjh@cryptsoft.com). 58238384Sjkim * 59238384Sjkim */ 60238384Sjkim#ifndef OPENSSL_NO_SRP 61280304Sjkim# include "cryptlib.h" 62280304Sjkim# include "srp_lcl.h" 63280304Sjkim# include <openssl/srp.h> 64280304Sjkim# include <openssl/evp.h> 65238384Sjkim 66280304Sjkim# if (BN_BYTES == 8) 67280304Sjkim# if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__) 68280304Sjkim# define bn_pack4(a1,a2,a3,a4) ((a1##UI64<<48)|(a2##UI64<<32)|(a3##UI64<<16)|a4##UI64) 69280304Sjkim# elif defined(__arch64__) 70280304Sjkim# define bn_pack4(a1,a2,a3,a4) ((a1##UL<<48)|(a2##UL<<32)|(a3##UL<<16)|a4##UL) 71280304Sjkim# else 72280304Sjkim# define bn_pack4(a1,a2,a3,a4) ((a1##ULL<<48)|(a2##ULL<<32)|(a3##ULL<<16)|a4##ULL) 73280304Sjkim# endif 74280304Sjkim# elif (BN_BYTES == 4) 75280304Sjkim# define bn_pack4(a1,a2,a3,a4) ((a3##UL<<16)|a4##UL), ((a1##UL<<16)|a2##UL) 76264331Sjkim# else 77280304Sjkim# error "unsupported BN_BYTES" 78264331Sjkim# endif 79238384Sjkim 80280304Sjkim# include "srp_grps.h" 81238384Sjkim 82238384Sjkimstatic BIGNUM *srp_Calc_k(BIGNUM *N, BIGNUM *g) 83280304Sjkim{ 84280304Sjkim /* k = SHA1(N | PAD(g)) -- tls-srp draft 8 */ 85238384Sjkim 86280304Sjkim unsigned char digest[SHA_DIGEST_LENGTH]; 87280304Sjkim unsigned char *tmp; 88280304Sjkim EVP_MD_CTX ctxt; 89280304Sjkim int longg; 90280304Sjkim int longN = BN_num_bytes(N); 91238384Sjkim 92280304Sjkim if (BN_ucmp(g, N) >= 0) 93280304Sjkim return NULL; 94269686Sjkim 95280304Sjkim if ((tmp = OPENSSL_malloc(longN)) == NULL) 96280304Sjkim return NULL; 97280304Sjkim BN_bn2bin(N, tmp); 98238384Sjkim 99280304Sjkim EVP_MD_CTX_init(&ctxt); 100280304Sjkim EVP_DigestInit_ex(&ctxt, EVP_sha1(), NULL); 101280304Sjkim EVP_DigestUpdate(&ctxt, tmp, longN); 102238384Sjkim 103280304Sjkim memset(tmp, 0, longN); 104280304Sjkim longg = BN_bn2bin(g, tmp); 105280304Sjkim /* use the zeros behind to pad on left */ 106280304Sjkim EVP_DigestUpdate(&ctxt, tmp + longg, longN - longg); 107280304Sjkim EVP_DigestUpdate(&ctxt, tmp, longg); 108280304Sjkim OPENSSL_free(tmp); 109238384Sjkim 110280304Sjkim EVP_DigestFinal_ex(&ctxt, digest, NULL); 111280304Sjkim EVP_MD_CTX_cleanup(&ctxt); 112280304Sjkim return BN_bin2bn(digest, sizeof(digest), NULL); 113280304Sjkim} 114238384Sjkim 115238384SjkimBIGNUM *SRP_Calc_u(BIGNUM *A, BIGNUM *B, BIGNUM *N) 116280304Sjkim{ 117280304Sjkim /* k = SHA1(PAD(A) || PAD(B) ) -- tls-srp draft 8 */ 118238384Sjkim 119280304Sjkim BIGNUM *u; 120280304Sjkim unsigned char cu[SHA_DIGEST_LENGTH]; 121280304Sjkim unsigned char *cAB; 122280304Sjkim EVP_MD_CTX ctxt; 123280304Sjkim int longN; 124280304Sjkim if ((A == NULL) || (B == NULL) || (N == NULL)) 125280304Sjkim return NULL; 126238384Sjkim 127280304Sjkim if (BN_ucmp(A, N) >= 0 || BN_ucmp(B, N) >= 0) 128280304Sjkim return NULL; 129269686Sjkim 130280304Sjkim longN = BN_num_bytes(N); 131238384Sjkim 132280304Sjkim if ((cAB = OPENSSL_malloc(2 * longN)) == NULL) 133280304Sjkim return NULL; 134238384Sjkim 135280304Sjkim memset(cAB, 0, longN); 136238384Sjkim 137280304Sjkim EVP_MD_CTX_init(&ctxt); 138280304Sjkim EVP_DigestInit_ex(&ctxt, EVP_sha1(), NULL); 139280304Sjkim EVP_DigestUpdate(&ctxt, cAB + BN_bn2bin(A, cAB + longN), longN); 140280304Sjkim EVP_DigestUpdate(&ctxt, cAB + BN_bn2bin(B, cAB + longN), longN); 141280304Sjkim OPENSSL_free(cAB); 142280304Sjkim EVP_DigestFinal_ex(&ctxt, cu, NULL); 143280304Sjkim EVP_MD_CTX_cleanup(&ctxt); 144238384Sjkim 145280304Sjkim if (!(u = BN_bin2bn(cu, sizeof(cu), NULL))) 146280304Sjkim return NULL; 147280304Sjkim if (!BN_is_zero(u)) 148280304Sjkim return u; 149280304Sjkim BN_free(u); 150280304Sjkim return NULL; 151238384Sjkim} 152238384Sjkim 153280304SjkimBIGNUM *SRP_Calc_server_key(BIGNUM *A, BIGNUM *v, BIGNUM *u, BIGNUM *b, 154280304Sjkim BIGNUM *N) 155280304Sjkim{ 156280304Sjkim BIGNUM *tmp = NULL, *S = NULL; 157280304Sjkim BN_CTX *bn_ctx; 158238384Sjkim 159280304Sjkim if (u == NULL || A == NULL || v == NULL || b == NULL || N == NULL) 160280304Sjkim return NULL; 161238384Sjkim 162280304Sjkim if ((bn_ctx = BN_CTX_new()) == NULL || 163280304Sjkim (tmp = BN_new()) == NULL || (S = BN_new()) == NULL) 164280304Sjkim goto err; 165238384Sjkim 166280304Sjkim /* S = (A*v**u) ** b */ 167238384Sjkim 168280304Sjkim if (!BN_mod_exp(tmp, v, u, N, bn_ctx)) 169280304Sjkim goto err; 170280304Sjkim if (!BN_mod_mul(tmp, A, tmp, N, bn_ctx)) 171280304Sjkim goto err; 172280304Sjkim if (!BN_mod_exp(S, tmp, b, N, bn_ctx)) 173280304Sjkim goto err; 174280304Sjkim err: 175280304Sjkim BN_CTX_free(bn_ctx); 176280304Sjkim BN_clear_free(tmp); 177280304Sjkim return S; 178280304Sjkim} 179280304Sjkim 180238384SjkimBIGNUM *SRP_Calc_B(BIGNUM *b, BIGNUM *N, BIGNUM *g, BIGNUM *v) 181280304Sjkim{ 182280304Sjkim BIGNUM *kv = NULL, *gb = NULL; 183280304Sjkim BIGNUM *B = NULL, *k = NULL; 184280304Sjkim BN_CTX *bn_ctx; 185238384Sjkim 186280304Sjkim if (b == NULL || N == NULL || g == NULL || v == NULL || 187280304Sjkim (bn_ctx = BN_CTX_new()) == NULL) 188280304Sjkim return NULL; 189238384Sjkim 190280304Sjkim if ((kv = BN_new()) == NULL || 191280304Sjkim (gb = BN_new()) == NULL || (B = BN_new()) == NULL) 192280304Sjkim goto err; 193238384Sjkim 194280304Sjkim /* B = g**b + k*v */ 195238384Sjkim 196280304Sjkim if (!BN_mod_exp(gb, g, b, N, bn_ctx) || 197280304Sjkim !(k = srp_Calc_k(N, g)) || 198280304Sjkim !BN_mod_mul(kv, v, k, N, bn_ctx) || 199280304Sjkim !BN_mod_add(B, gb, kv, N, bn_ctx)) { 200280304Sjkim BN_free(B); 201280304Sjkim B = NULL; 202280304Sjkim } 203280304Sjkim err: 204280304Sjkim BN_CTX_free(bn_ctx); 205280304Sjkim BN_clear_free(kv); 206280304Sjkim BN_clear_free(gb); 207280304Sjkim BN_free(k); 208280304Sjkim return B; 209280304Sjkim} 210238384Sjkim 211238384SjkimBIGNUM *SRP_Calc_x(BIGNUM *s, const char *user, const char *pass) 212280304Sjkim{ 213280304Sjkim unsigned char dig[SHA_DIGEST_LENGTH]; 214280304Sjkim EVP_MD_CTX ctxt; 215280304Sjkim unsigned char *cs; 216238384Sjkim 217280304Sjkim if ((s == NULL) || (user == NULL) || (pass == NULL)) 218280304Sjkim return NULL; 219238384Sjkim 220280304Sjkim if ((cs = OPENSSL_malloc(BN_num_bytes(s))) == NULL) 221280304Sjkim return NULL; 222238384Sjkim 223280304Sjkim EVP_MD_CTX_init(&ctxt); 224280304Sjkim EVP_DigestInit_ex(&ctxt, EVP_sha1(), NULL); 225280304Sjkim EVP_DigestUpdate(&ctxt, user, strlen(user)); 226280304Sjkim EVP_DigestUpdate(&ctxt, ":", 1); 227280304Sjkim EVP_DigestUpdate(&ctxt, pass, strlen(pass)); 228280304Sjkim EVP_DigestFinal_ex(&ctxt, dig, NULL); 229238384Sjkim 230280304Sjkim EVP_DigestInit_ex(&ctxt, EVP_sha1(), NULL); 231280304Sjkim BN_bn2bin(s, cs); 232280304Sjkim EVP_DigestUpdate(&ctxt, cs, BN_num_bytes(s)); 233280304Sjkim OPENSSL_free(cs); 234280304Sjkim EVP_DigestUpdate(&ctxt, dig, sizeof(dig)); 235280304Sjkim EVP_DigestFinal_ex(&ctxt, dig, NULL); 236280304Sjkim EVP_MD_CTX_cleanup(&ctxt); 237238384Sjkim 238280304Sjkim return BN_bin2bn(dig, sizeof(dig), NULL); 239280304Sjkim} 240238384Sjkim 241238384SjkimBIGNUM *SRP_Calc_A(BIGNUM *a, BIGNUM *N, BIGNUM *g) 242280304Sjkim{ 243280304Sjkim BN_CTX *bn_ctx; 244280304Sjkim BIGNUM *A = NULL; 245238384Sjkim 246280304Sjkim if (a == NULL || N == NULL || g == NULL || 247280304Sjkim (bn_ctx = BN_CTX_new()) == NULL) 248280304Sjkim return NULL; 249238384Sjkim 250280304Sjkim if ((A = BN_new()) != NULL && !BN_mod_exp(A, g, a, N, bn_ctx)) { 251280304Sjkim BN_free(A); 252280304Sjkim A = NULL; 253280304Sjkim } 254280304Sjkim BN_CTX_free(bn_ctx); 255280304Sjkim return A; 256280304Sjkim} 257238384Sjkim 258280304SjkimBIGNUM *SRP_Calc_client_key(BIGNUM *N, BIGNUM *B, BIGNUM *g, BIGNUM *x, 259280304Sjkim BIGNUM *a, BIGNUM *u) 260280304Sjkim{ 261280304Sjkim BIGNUM *tmp = NULL, *tmp2 = NULL, *tmp3 = NULL, *k = NULL, *K = NULL; 262280304Sjkim BN_CTX *bn_ctx; 263238384Sjkim 264280304Sjkim if (u == NULL || B == NULL || N == NULL || g == NULL || x == NULL 265280304Sjkim || a == NULL || (bn_ctx = BN_CTX_new()) == NULL) 266280304Sjkim return NULL; 267238384Sjkim 268280304Sjkim if ((tmp = BN_new()) == NULL || 269280304Sjkim (tmp2 = BN_new()) == NULL || 270280304Sjkim (tmp3 = BN_new()) == NULL || (K = BN_new()) == NULL) 271280304Sjkim goto err; 272238384Sjkim 273280304Sjkim if (!BN_mod_exp(tmp, g, x, N, bn_ctx)) 274280304Sjkim goto err; 275280304Sjkim if (!(k = srp_Calc_k(N, g))) 276280304Sjkim goto err; 277280304Sjkim if (!BN_mod_mul(tmp2, tmp, k, N, bn_ctx)) 278280304Sjkim goto err; 279280304Sjkim if (!BN_mod_sub(tmp, B, tmp2, N, bn_ctx)) 280280304Sjkim goto err; 281238384Sjkim 282280304Sjkim if (!BN_mod_mul(tmp3, u, x, N, bn_ctx)) 283280304Sjkim goto err; 284280304Sjkim if (!BN_mod_add(tmp2, a, tmp3, N, bn_ctx)) 285280304Sjkim goto err; 286280304Sjkim if (!BN_mod_exp(K, tmp, tmp2, N, bn_ctx)) 287280304Sjkim goto err; 288238384Sjkim 289280304Sjkim err: 290280304Sjkim BN_CTX_free(bn_ctx); 291280304Sjkim BN_clear_free(tmp); 292280304Sjkim BN_clear_free(tmp2); 293280304Sjkim BN_clear_free(tmp3); 294280304Sjkim BN_free(k); 295280304Sjkim return K; 296280304Sjkim} 297238384Sjkim 298238384Sjkimint SRP_Verify_B_mod_N(BIGNUM *B, BIGNUM *N) 299280304Sjkim{ 300280304Sjkim BIGNUM *r; 301280304Sjkim BN_CTX *bn_ctx; 302280304Sjkim int ret = 0; 303238384Sjkim 304280304Sjkim if (B == NULL || N == NULL || (bn_ctx = BN_CTX_new()) == NULL) 305280304Sjkim return 0; 306238384Sjkim 307280304Sjkim if ((r = BN_new()) == NULL) 308280304Sjkim goto err; 309280304Sjkim /* Checks if B % N == 0 */ 310280304Sjkim if (!BN_nnmod(r, B, N, bn_ctx)) 311280304Sjkim goto err; 312280304Sjkim ret = !BN_is_zero(r); 313280304Sjkim err: 314280304Sjkim BN_CTX_free(bn_ctx); 315280304Sjkim BN_free(r); 316280304Sjkim return ret; 317280304Sjkim} 318238384Sjkim 319238384Sjkimint SRP_Verify_A_mod_N(BIGNUM *A, BIGNUM *N) 320280304Sjkim{ 321280304Sjkim /* Checks if A % N == 0 */ 322280304Sjkim return SRP_Verify_B_mod_N(A, N); 323280304Sjkim} 324238384Sjkim 325280304Sjkim/* 326280304Sjkim * Check if G and N are kwown parameters. The values have been generated 327280304Sjkim * from the ietf-tls-srp draft version 8 328280304Sjkim */ 329238384Sjkimchar *SRP_check_known_gN_param(BIGNUM *g, BIGNUM *N) 330280304Sjkim{ 331280304Sjkim size_t i; 332280304Sjkim if ((g == NULL) || (N == NULL)) 333280304Sjkim return 0; 334238384Sjkim 335280304Sjkim srp_bn_print(g); 336280304Sjkim srp_bn_print(N); 337238384Sjkim 338280304Sjkim for (i = 0; i < KNOWN_GN_NUMBER; i++) { 339280304Sjkim if (BN_cmp(knowngN[i].g, g) == 0 && BN_cmp(knowngN[i].N, N) == 0) 340280304Sjkim return knowngN[i].id; 341280304Sjkim } 342280304Sjkim return NULL; 343280304Sjkim} 344238384Sjkim 345238384SjkimSRP_gN *SRP_get_default_gN(const char *id) 346280304Sjkim{ 347280304Sjkim size_t i; 348238384Sjkim 349280304Sjkim if (id == NULL) 350280304Sjkim return knowngN; 351280304Sjkim for (i = 0; i < KNOWN_GN_NUMBER; i++) { 352280304Sjkim if (strcmp(knowngN[i].id, id) == 0) 353280304Sjkim return knowngN + i; 354280304Sjkim } 355280304Sjkim return NULL; 356280304Sjkim} 357238384Sjkim#endif 358