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 ((tmp = OPENSSL_malloc(longN)) == NULL) 93 return NULL; 94 BN_bn2bin(N,tmp) ; 95 96 EVP_MD_CTX_init(&ctxt); 97 EVP_DigestInit_ex(&ctxt, EVP_sha1(), NULL); 98 EVP_DigestUpdate(&ctxt, tmp, longN); 99 100 memset(tmp, 0, longN); 101 longg = BN_bn2bin(g,tmp) ; 102 /* use the zeros behind to pad on left */ 103 EVP_DigestUpdate(&ctxt, tmp + longg, longN-longg); 104 EVP_DigestUpdate(&ctxt, tmp, longg); 105 OPENSSL_free(tmp); 106 107 EVP_DigestFinal_ex(&ctxt, digest, NULL); 108 EVP_MD_CTX_cleanup(&ctxt); 109 return BN_bin2bn(digest, sizeof(digest), NULL); 110 } 111 112 BIGNUM *SRP_Calc_u(BIGNUM *A, BIGNUM *B, BIGNUM *N) 113 { 114 /* k = SHA1(PAD(A) || PAD(B) ) -- tls-srp draft 8 */ 115 116 BIGNUM *u; 117 unsigned char cu[SHA_DIGEST_LENGTH]; 118 unsigned char *cAB; 119 EVP_MD_CTX ctxt; 120 int longN; 121 if ((A == NULL) ||(B == NULL) || (N == NULL)) 122 return NULL; 123 124 longN= BN_num_bytes(N); 125 126 if ((cAB = OPENSSL_malloc(2*longN)) == NULL) 127 return NULL; 128 129 memset(cAB, 0, longN); 130 131 EVP_MD_CTX_init(&ctxt); 132 EVP_DigestInit_ex(&ctxt, EVP_sha1(), NULL); 133 EVP_DigestUpdate(&ctxt, cAB + BN_bn2bin(A,cAB+longN), longN); 134 EVP_DigestUpdate(&ctxt, cAB + BN_bn2bin(B,cAB+longN), longN); 135 OPENSSL_free(cAB); 136 EVP_DigestFinal_ex(&ctxt, cu, NULL); 137 EVP_MD_CTX_cleanup(&ctxt); 138 139 if (!(u = BN_bin2bn(cu, sizeof(cu), NULL))) 140 return NULL; 141 if (!BN_is_zero(u)) 142 return u; 143 BN_free(u); 144 return NULL; 145 } 146 147 BIGNUM *SRP_Calc_server_key(BIGNUM *A, BIGNUM *v, BIGNUM *u, BIGNUM *b, BIGNUM *N) 148 { 149 BIGNUM *tmp = NULL, *S = NULL; 150 BN_CTX *bn_ctx; 151 152 if (u == NULL || A == NULL || v == NULL || b == NULL || N == NULL) 153 return NULL; 154 155 if ((bn_ctx = BN_CTX_new()) == NULL || 156 (tmp = BN_new()) == NULL || 157 (S = BN_new()) == NULL ) 158 goto err; 159 160 /* S = (A*v**u) ** b */ 161 162 if (!BN_mod_exp(tmp,v,u,N,bn_ctx)) 163 goto err; 164 if (!BN_mod_mul(tmp,A,tmp,N,bn_ctx)) 165 goto err; 166 if (!BN_mod_exp(S,tmp,b,N,bn_ctx)) 167 goto err; 168 err: 169 BN_CTX_free(bn_ctx); 170 BN_clear_free(tmp); 171 return S; 172 } 173 174 BIGNUM *SRP_Calc_B(BIGNUM *b, BIGNUM *N, BIGNUM *g, BIGNUM *v) 175 { 176 BIGNUM *kv = NULL, *gb = NULL; 177 BIGNUM *B = NULL, *k = NULL; 178 BN_CTX *bn_ctx; 179 180 if (b == NULL || N == NULL || g == NULL || v == NULL || 181 (bn_ctx = BN_CTX_new()) == NULL) 182 return NULL; 183 184 if ( (kv = BN_new()) == NULL || 185 (gb = BN_new()) == NULL || 186 (B = BN_new())== NULL) 187 goto err; 188 189 /* B = g**b + k*v */ 190 191 if (!BN_mod_exp(gb,g,b,N,bn_ctx) || 192 !(k = srp_Calc_k(N,g)) || 193 !BN_mod_mul(kv,v,k,N,bn_ctx) || 194 !BN_mod_add(B,gb,kv,N,bn_ctx)) 195 { 196 BN_free(B); 197 B = NULL; 198 } 199 err: 200 BN_CTX_free(bn_ctx); 201 BN_clear_free(kv); 202 BN_clear_free(gb); 203 BN_free(k); 204 return B; 205 } 206 207 BIGNUM *SRP_Calc_x(BIGNUM *s, const char *user, const char *pass) 208 { 209 unsigned char dig[SHA_DIGEST_LENGTH]; 210 EVP_MD_CTX ctxt; 211 unsigned char *cs; 212 213 if ((s == NULL) || 214 (user == NULL) || 215 (pass == NULL)) 216 return NULL; 217 218 if ((cs = OPENSSL_malloc(BN_num_bytes(s))) == NULL) 219 return NULL; 220 221 EVP_MD_CTX_init(&ctxt); 222 EVP_DigestInit_ex(&ctxt, EVP_sha1(), NULL); 223 EVP_DigestUpdate(&ctxt, user, strlen(user)); 224 EVP_DigestUpdate(&ctxt, ":", 1); 225 EVP_DigestUpdate(&ctxt, pass, strlen(pass)); 226 EVP_DigestFinal_ex(&ctxt, dig, NULL); 227 228 EVP_DigestInit_ex(&ctxt, EVP_sha1(), NULL); 229 BN_bn2bin(s,cs); 230 EVP_DigestUpdate(&ctxt, cs, BN_num_bytes(s)); 231 OPENSSL_free(cs); 232 EVP_DigestUpdate(&ctxt, dig, sizeof(dig)); 233 EVP_DigestFinal_ex(&ctxt, dig, NULL); 234 EVP_MD_CTX_cleanup(&ctxt); 235 236 return BN_bin2bn(dig, sizeof(dig), NULL); 237 } 238 239 BIGNUM *SRP_Calc_A(BIGNUM *a, BIGNUM *N, BIGNUM *g) 240 { 241 BN_CTX *bn_ctx; 242 BIGNUM * A = NULL; 243 244 if (a == NULL || N == NULL || g == NULL || 245 (bn_ctx = BN_CTX_new()) == NULL) 246 return NULL; 247 248 if ((A = BN_new()) != NULL && 249 !BN_mod_exp(A,g,a,N,bn_ctx)) 250 { 251 BN_free(A); 252 A = NULL; 253 } 254 BN_CTX_free(bn_ctx); 255 return A; 256 } 257 258 259 BIGNUM *SRP_Calc_client_key(BIGNUM *N, BIGNUM *B, BIGNUM *g, BIGNUM *x, BIGNUM *a, BIGNUM *u) 260 { 261 BIGNUM *tmp = NULL, *tmp2 = NULL, *tmp3 = NULL , *k = NULL, *K = NULL; 262 BN_CTX *bn_ctx; 263 264 if (u == NULL || B == NULL || N == NULL || g == NULL || x == NULL || a == NULL || 265 (bn_ctx = BN_CTX_new()) == NULL) 266 return NULL; 267 268 if ((tmp = BN_new()) == NULL || 269 (tmp2 = BN_new())== NULL || 270 (tmp3 = BN_new())== NULL || 271 (K = BN_new()) == NULL) 272 goto err; 273 274 if (!BN_mod_exp(tmp,g,x,N,bn_ctx)) 275 goto err; 276 if (!(k = srp_Calc_k(N,g))) 277 goto err; 278 if (!BN_mod_mul(tmp2,tmp,k,N,bn_ctx)) 279 goto err; 280 if (!BN_mod_sub(tmp,B,tmp2,N,bn_ctx)) 281 goto err; 282 283 if (!BN_mod_mul(tmp3,u,x,N,bn_ctx)) 284 goto err; 285 if (!BN_mod_add(tmp2,a,tmp3,N,bn_ctx)) 286 goto err; 287 if (!BN_mod_exp(K,tmp,tmp2,N,bn_ctx)) 288 goto err; 289 290 err : 291 BN_CTX_free(bn_ctx); 292 BN_clear_free(tmp); 293 BN_clear_free(tmp2); 294 BN_clear_free(tmp3); 295 BN_free(k); 296 return K; 297 } 298 299 int SRP_Verify_B_mod_N(BIGNUM *B, BIGNUM *N) 300 { 301 BIGNUM *r; 302 BN_CTX *bn_ctx; 303 int ret = 0; 304 305 if (B == NULL || N == NULL || 306 (bn_ctx = BN_CTX_new()) == NULL) 307 return 0; 308 309 if ((r = BN_new()) == NULL) 310 goto err; 311 /* Checks if B % N == 0 */ 312 if (!BN_nnmod(r,B,N,bn_ctx)) 313 goto err; 314 ret = !BN_is_zero(r); 315 err: 316 BN_CTX_free(bn_ctx); 317 BN_free(r); 318 return ret; 319 } 320 321 int SRP_Verify_A_mod_N(BIGNUM *A, BIGNUM *N) 322 { 323 /* Checks if A % N == 0 */ 324 return SRP_Verify_B_mod_N(A,N) ; 325 } 326 327 328 /* Check if G and N are kwown parameters. 329 The values have been generated from the ietf-tls-srp draft version 8 330 */ 331 char *SRP_check_known_gN_param(BIGNUM *g, BIGNUM *N) 332 { 333 size_t i; 334 if ((g == NULL) || (N == NULL)) 335 return 0; 336 337 srp_bn_print(g); 338 srp_bn_print(N); 339 340 for(i = 0; i < KNOWN_GN_NUMBER; i++) 341 { 342 if (BN_cmp(knowngN[i].g, g) == 0 && BN_cmp(knowngN[i].N, N) == 0) 343 return knowngN[i].id; 344 } 345 return NULL; 346 } 347 348 SRP_gN *SRP_get_default_gN(const char *id) 349 { 350 size_t i; 351 352 if (id == NULL) 353 return knowngN; 354 for(i = 0; i < KNOWN_GN_NUMBER; i++) 355 { 356 if (strcmp(knowngN[i].id, id)==0) 357 return knowngN + i; 358 } 359 return NULL; 360 } 361 #endif 362