1 /* crypto/srp/srp_lib.c */
   2 /* Written by Christophe Renou (christophe.renou@edelweb.fr) with
   3  * the precious help of Peter Sylvester (peter.sylvester@edelweb.fr)
   4  * for the EdelKey project and contributed to the OpenSSL project 2004.
   5  */
   6 /* ====================================================================
   7  * Copyright (c) 2004 The OpenSSL Project.  All rights reserved.
   8  *
   9  * Redistribution and use in source and binary forms, with or without
  10  * modification, are permitted provided that the following conditions
  11  * are met:
  12  *
  13  * 1. Redistributions of source code must retain the above copyright
  14  *    notice, this list of conditions and the following disclaimer.
  15  *
  16  * 2. Redistributions in binary form must reproduce the above copyright
  17  *    notice, this list of conditions and the following disclaimer in
  18  *    the documentation and/or other materials provided with the
  19  *    distribution.
  20  *
  21  * 3. All advertising materials mentioning features or use of this
  22  *    software must display the following acknowledgment:
  23  *    "This product includes software developed by the OpenSSL Project
  24  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
  25  *
  26  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  27  *    endorse or promote products derived from this software without
  28  *    prior written permission. For written permission, please contact
  29  *    licensing@OpenSSL.org.
  30  *
  31  * 5. Products derived from this software may not be called "OpenSSL"
  32  *    nor may "OpenSSL" appear in their names without prior written
  33  *    permission of the OpenSSL Project.
  34  *
  35  * 6. Redistributions of any form whatsoever must retain the following
  36  *    acknowledgment:
  37  *    "This product includes software developed by the OpenSSL Project
  38  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
  39  *
  40  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  41  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  43  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  44  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  45  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  46  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  47  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  49  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  50  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  51  * OF THE POSSIBILITY OF SUCH DAMAGE.
  52  * ====================================================================
  53  *
  54  * This product includes cryptographic software written by Eric Young
  55  * (eay@cryptsoft.com).  This product includes software written by Tim
  56  * Hudson (tjh@cryptsoft.com).
  57  *
  58  */
  59 #ifndef OPENSSL_NO_SRP
  60 #include "cryptlib.h"
  61 #include "srp_lcl.h"
  62 #include <openssl/srp.h>
  63 #include <openssl/evp.h>
  64 
  65 #if (BN_BYTES == 8)
  66 # if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__)
  67 #  define bn_pack4(a1,a2,a3,a4) ((a1##UI64<<48)|(a2##UI64<<32)|(a3##UI64<<16)|a4##UI64)
  68 # elif defined(__arch64__)
  69 #  define bn_pack4(a1,a2,a3,a4) ((a1##UL<<48)|(a2##UL<<32)|(a3##UL<<16)|a4##UL)
  70 # else
  71 #  define bn_pack4(a1,a2,a3,a4) ((a1##ULL<<48)|(a2##ULL<<32)|(a3##ULL<<16)|a4##ULL)
  72 # endif
  73 #elif (BN_BYTES == 4)
  74 # define bn_pack4(a1,a2,a3,a4)  ((a3##UL<<16)|a4##UL), ((a1##UL<<16)|a2##UL)
  75 #else
  76 # error "unsupported BN_BYTES"
  77 #endif
  78 
  79 
  80 #include "srp_grps.h"
  81 
  82 static BIGNUM *srp_Calc_k(BIGNUM *N, BIGNUM *g)
  83         {
  84         /* k = SHA1(N | PAD(g)) -- tls-srp draft 8 */
  85 
  86         unsigned char digest[SHA_DIGEST_LENGTH];
  87         unsigned char *tmp;
  88         EVP_MD_CTX ctxt;
  89         int longg ;
  90         int longN = BN_num_bytes(N);
  91 
  92         if (BN_ucmp(g, N) >= 0)
  93                 return NULL;
  94 
  95         if ((tmp = OPENSSL_malloc(longN)) == NULL)
  96                 return NULL;
  97         BN_bn2bin(N,tmp) ;
  98 
  99         EVP_MD_CTX_init(&ctxt);
 100         EVP_DigestInit_ex(&ctxt, EVP_sha1(), NULL);
 101         EVP_DigestUpdate(&ctxt, tmp, longN);
 102 
 103         memset(tmp, 0, longN);
 104         longg = BN_bn2bin(g,tmp) ;
 105         /* use the zeros behind to pad on left */
 106         EVP_DigestUpdate(&ctxt, tmp + longg, longN-longg);
 107         EVP_DigestUpdate(&ctxt, tmp, longg);
 108         OPENSSL_free(tmp);
 109 
 110         EVP_DigestFinal_ex(&ctxt, digest, NULL);
 111         EVP_MD_CTX_cleanup(&ctxt);
 112         return BN_bin2bn(digest, sizeof(digest), NULL);
 113         }
 114 
 115 BIGNUM *SRP_Calc_u(BIGNUM *A, BIGNUM *B, BIGNUM *N)
 116         {
 117         /* k = SHA1(PAD(A) || PAD(B) ) -- tls-srp draft 8 */
 118 
 119         BIGNUM *u;
 120         unsigned char cu[SHA_DIGEST_LENGTH];
 121         unsigned char *cAB;
 122         EVP_MD_CTX ctxt;
 123         int longN;
 124         if ((A == NULL) ||(B == NULL) || (N == NULL))
 125                 return NULL;
 126 
 127         if (BN_ucmp(A, N) >= 0 || BN_ucmp(B, N) >= 0)
 128                 return NULL;
 129 
 130         longN= BN_num_bytes(N);
 131 
 132         if ((cAB = OPENSSL_malloc(2*longN)) == NULL)
 133                 return NULL;
 134 
 135         memset(cAB, 0, longN);
 136 
 137         EVP_MD_CTX_init(&ctxt);
 138         EVP_DigestInit_ex(&ctxt, EVP_sha1(), NULL);
 139         EVP_DigestUpdate(&ctxt, cAB + BN_bn2bin(A,cAB+longN), longN);
 140         EVP_DigestUpdate(&ctxt, cAB + BN_bn2bin(B,cAB+longN), longN);
 141         OPENSSL_free(cAB);
 142         EVP_DigestFinal_ex(&ctxt, cu, NULL);
 143         EVP_MD_CTX_cleanup(&ctxt);
 144 
 145         if (!(u = BN_bin2bn(cu, sizeof(cu), NULL)))
 146                 return NULL;
 147         if (!BN_is_zero(u))
 148                 return u;
 149         BN_free(u);
 150         return NULL;
 151 }
 152 
 153 BIGNUM *SRP_Calc_server_key(BIGNUM *A, BIGNUM *v, BIGNUM *u, BIGNUM *b, BIGNUM *N)
 154         {
 155         BIGNUM *tmp = NULL, *S = NULL;
 156         BN_CTX *bn_ctx;
 157 
 158         if (u == NULL || A == NULL || v == NULL || b == NULL || N == NULL)
 159                 return NULL;
 160 
 161         if ((bn_ctx = BN_CTX_new()) == NULL ||
 162                 (tmp = BN_new()) == NULL ||
 163                 (S = BN_new()) == NULL )
 164                 goto err;
 165 
 166         /* S = (A*v**u) ** b */
 167 
 168         if (!BN_mod_exp(tmp,v,u,N,bn_ctx))
 169                 goto err;
 170         if (!BN_mod_mul(tmp,A,tmp,N,bn_ctx))
 171                 goto err;
 172         if (!BN_mod_exp(S,tmp,b,N,bn_ctx))
 173                 goto err;
 174 err:
 175         BN_CTX_free(bn_ctx);
 176         BN_clear_free(tmp);
 177         return S;
 178         }
 179 
 180 BIGNUM *SRP_Calc_B(BIGNUM *b, BIGNUM *N, BIGNUM *g, BIGNUM *v)
 181         {
 182         BIGNUM  *kv = NULL, *gb = NULL;
 183         BIGNUM *B = NULL, *k = NULL;
 184         BN_CTX *bn_ctx;
 185 
 186         if (b == NULL || N == NULL || g == NULL || v == NULL ||
 187                 (bn_ctx = BN_CTX_new()) == NULL)
 188                 return NULL;
 189 
 190         if ( (kv = BN_new()) == NULL ||
 191                 (gb = BN_new()) == NULL ||
 192                 (B = BN_new())== NULL)
 193                 goto err;
 194 
 195         /* B = g**b + k*v */
 196 
 197         if (!BN_mod_exp(gb,g,b,N,bn_ctx) ||
 198            !(k = srp_Calc_k(N,g)) ||
 199            !BN_mod_mul(kv,v,k,N,bn_ctx) ||
 200            !BN_mod_add(B,gb,kv,N,bn_ctx))
 201                 {
 202                 BN_free(B);
 203                 B = NULL;
 204                 }
 205 err:
 206         BN_CTX_free(bn_ctx);
 207         BN_clear_free(kv);
 208         BN_clear_free(gb);
 209         BN_free(k);
 210         return B;
 211         }
 212 
 213 BIGNUM *SRP_Calc_x(BIGNUM *s, const char *user, const char *pass)
 214         {
 215         unsigned char dig[SHA_DIGEST_LENGTH];
 216         EVP_MD_CTX ctxt;
 217         unsigned char *cs;
 218 
 219         if ((s == NULL) ||
 220                 (user == NULL) ||
 221                 (pass == NULL))
 222                 return NULL;
 223 
 224         if ((cs = OPENSSL_malloc(BN_num_bytes(s))) == NULL)
 225                 return NULL;
 226 
 227         EVP_MD_CTX_init(&ctxt);
 228         EVP_DigestInit_ex(&ctxt, EVP_sha1(), NULL);
 229         EVP_DigestUpdate(&ctxt, user, strlen(user));
 230         EVP_DigestUpdate(&ctxt, ":", 1);
 231         EVP_DigestUpdate(&ctxt, pass, strlen(pass));
 232         EVP_DigestFinal_ex(&ctxt, dig, NULL);
 233 
 234         EVP_DigestInit_ex(&ctxt, EVP_sha1(), NULL);
 235         BN_bn2bin(s,cs);
 236         EVP_DigestUpdate(&ctxt, cs, BN_num_bytes(s));
 237         OPENSSL_free(cs);
 238         EVP_DigestUpdate(&ctxt, dig, sizeof(dig));
 239         EVP_DigestFinal_ex(&ctxt, dig, NULL);
 240         EVP_MD_CTX_cleanup(&ctxt);
 241 
 242         return BN_bin2bn(dig, sizeof(dig), NULL);
 243         }
 244 
 245 BIGNUM *SRP_Calc_A(BIGNUM *a, BIGNUM *N, BIGNUM *g)
 246         {
 247         BN_CTX *bn_ctx;
 248         BIGNUM * A = NULL;
 249 
 250         if (a == NULL || N == NULL || g == NULL ||
 251                 (bn_ctx = BN_CTX_new()) == NULL)
 252                 return NULL;
 253 
 254         if ((A = BN_new()) != NULL &&
 255            !BN_mod_exp(A,g,a,N,bn_ctx))
 256                 {
 257                 BN_free(A);
 258                 A = NULL;
 259                 }
 260         BN_CTX_free(bn_ctx);
 261         return A;
 262         }
 263 
 264 
 265 BIGNUM *SRP_Calc_client_key(BIGNUM *N, BIGNUM *B, BIGNUM *g, BIGNUM *x, BIGNUM *a, BIGNUM *u)
 266         {
 267         BIGNUM *tmp = NULL, *tmp2 = NULL, *tmp3 = NULL , *k = NULL, *K = NULL;
 268         BN_CTX *bn_ctx;
 269 
 270         if (u == NULL || B == NULL || N == NULL || g == NULL || x == NULL || a == NULL ||
 271                 (bn_ctx = BN_CTX_new()) == NULL)
 272                 return NULL;
 273 
 274         if ((tmp = BN_new()) == NULL ||
 275                 (tmp2 = BN_new())== NULL ||
 276                 (tmp3 = BN_new())== NULL ||
 277                 (K = BN_new()) == NULL)
 278                 goto err;
 279 
 280         if (!BN_mod_exp(tmp,g,x,N,bn_ctx))
 281                 goto err;
 282         if (!(k = srp_Calc_k(N,g)))
 283                 goto err;
 284         if (!BN_mod_mul(tmp2,tmp,k,N,bn_ctx))
 285                 goto err;
 286         if (!BN_mod_sub(tmp,B,tmp2,N,bn_ctx))
 287                 goto err;
 288 
 289         if (!BN_mod_mul(tmp3,u,x,N,bn_ctx))
 290                 goto err;
 291         if (!BN_mod_add(tmp2,a,tmp3,N,bn_ctx))
 292                 goto err;
 293         if (!BN_mod_exp(K,tmp,tmp2,N,bn_ctx))
 294                 goto err;
 295 
 296 err :
 297         BN_CTX_free(bn_ctx);
 298         BN_clear_free(tmp);
 299         BN_clear_free(tmp2);
 300         BN_clear_free(tmp3);
 301         BN_free(k);
 302         return K;
 303         }
 304 
 305 int SRP_Verify_B_mod_N(BIGNUM *B, BIGNUM *N)
 306         {
 307         BIGNUM *r;
 308         BN_CTX *bn_ctx;
 309         int ret = 0;
 310 
 311         if (B == NULL || N == NULL ||
 312                 (bn_ctx = BN_CTX_new()) == NULL)
 313                 return 0;
 314 
 315         if ((r = BN_new()) == NULL)
 316                 goto err;
 317         /* Checks if B % N == 0 */
 318         if (!BN_nnmod(r,B,N,bn_ctx))
 319                 goto err;
 320         ret = !BN_is_zero(r);
 321 err:
 322         BN_CTX_free(bn_ctx);
 323         BN_free(r);
 324         return ret;
 325         }
 326 
 327 int SRP_Verify_A_mod_N(BIGNUM *A, BIGNUM *N)
 328         {
 329         /* Checks if A % N == 0 */
 330         return SRP_Verify_B_mod_N(A,N) ;
 331         }
 332 
 333 
 334 /* Check if G and N are kwown parameters.
 335    The values have been generated from the ietf-tls-srp draft version 8
 336 */
 337 char *SRP_check_known_gN_param(BIGNUM *g, BIGNUM *N)
 338         {
 339         size_t i;
 340         if ((g == NULL) || (N == NULL))
 341                 return 0;
 342 
 343         srp_bn_print(g);
 344         srp_bn_print(N);
 345 
 346         for(i = 0; i < KNOWN_GN_NUMBER; i++)
 347                 {
 348                 if (BN_cmp(knowngN[i].g, g) == 0 && BN_cmp(knowngN[i].N, N) == 0)
 349                         return knowngN[i].id;
 350                 }
 351         return NULL;
 352         }
 353 
 354 SRP_gN *SRP_get_default_gN(const char *id)
 355         {
 356         size_t i;
 357 
 358         if (id == NULL)
 359                 return knowngN;
 360         for(i = 0; i < KNOWN_GN_NUMBER; i++)
 361                 {
 362                 if (strcmp(knowngN[i].id, id)==0)
 363                         return knowngN + i;
 364                 }
 365         return NULL;
 366         }
 367 #endif