srp_vfy.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661
  1. /* crypto/srp/srp_vfy.c */
  2. /* Written by Christophe Renou ([email protected]) with
  3. * the precious help of Peter Sylvester ([email protected])
  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. * [email protected].
  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. * ([email protected]). This product includes software written by Tim
  56. * Hudson ([email protected]).
  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. #include <openssl/buffer.h>
  65. #include <openssl/rand.h>
  66. #include <openssl/txt_db.h>
  67. #define SRP_RANDOM_SALT_LEN 20
  68. #define MAX_LEN 2500
  69. static char b64table[] =
  70. "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./";
  71. /* the following two conversion routines have been inspired by code from Stanford */
  72. /*
  73. * Convert a base64 string into raw byte array representation.
  74. */
  75. static int t_fromb64(unsigned char *a, const char *src)
  76. {
  77. char *loc;
  78. int i, j;
  79. int size;
  80. while(*src && (*src == ' ' || *src == '\t' || *src == '\n'))
  81. ++src;
  82. size = strlen(src);
  83. i = 0;
  84. while(i < size)
  85. {
  86. loc = strchr(b64table, src[i]);
  87. if(loc == (char *) 0) break;
  88. else a[i] = loc - b64table;
  89. ++i;
  90. }
  91. /* if nothing valid to process we have a zero length response */
  92. if (i == 0)
  93. return 0;
  94. size = i;
  95. i = size - 1;
  96. j = size;
  97. while(1)
  98. {
  99. a[j] = a[i];
  100. if(--i < 0) break;
  101. a[j] |= (a[i] & 3) << 6;
  102. --j;
  103. a[j] = (unsigned char) ((a[i] & 0x3c) >> 2);
  104. if(--i < 0) break;
  105. a[j] |= (a[i] & 0xf) << 4;
  106. --j;
  107. a[j] = (unsigned char) ((a[i] & 0x30) >> 4);
  108. if(--i < 0) break;
  109. a[j] |= (a[i] << 2);
  110. a[--j] = 0;
  111. if(--i < 0) break;
  112. }
  113. while(a[j] == 0 && j <= size) ++j;
  114. i = 0;
  115. while (j <= size) a[i++] = a[j++];
  116. return i;
  117. }
  118. /*
  119. * Convert a raw byte string into a null-terminated base64 ASCII string.
  120. */
  121. static char *t_tob64(char *dst, const unsigned char *src, int size)
  122. {
  123. int c, pos = size % 3;
  124. unsigned char b0 = 0, b1 = 0, b2 = 0, notleading = 0;
  125. char *olddst = dst;
  126. switch(pos)
  127. {
  128. case 1:
  129. b2 = src[0];
  130. break;
  131. case 2:
  132. b1 = src[0];
  133. b2 = src[1];
  134. break;
  135. }
  136. while(1)
  137. {
  138. c = (b0 & 0xfc) >> 2;
  139. if(notleading || c != 0)
  140. {
  141. *dst++ = b64table[c];
  142. notleading = 1;
  143. }
  144. c = ((b0 & 3) << 4) | ((b1 & 0xf0) >> 4);
  145. if(notleading || c != 0)
  146. {
  147. *dst++ = b64table[c];
  148. notleading = 1;
  149. }
  150. c = ((b1 & 0xf) << 2) | ((b2 & 0xc0) >> 6);
  151. if(notleading || c != 0)
  152. {
  153. *dst++ = b64table[c];
  154. notleading = 1;
  155. }
  156. c = b2 & 0x3f;
  157. if(notleading || c != 0)
  158. {
  159. *dst++ = b64table[c];
  160. notleading = 1;
  161. }
  162. if(pos >= size) break;
  163. else
  164. {
  165. b0 = src[pos++];
  166. b1 = src[pos++];
  167. b2 = src[pos++];
  168. }
  169. }
  170. *dst++ = '\0';
  171. return olddst;
  172. }
  173. static void SRP_user_pwd_free(SRP_user_pwd *user_pwd)
  174. {
  175. if (user_pwd == NULL)
  176. return;
  177. BN_free(user_pwd->s);
  178. BN_clear_free(user_pwd->v);
  179. OPENSSL_free(user_pwd->id);
  180. OPENSSL_free(user_pwd->info);
  181. OPENSSL_free(user_pwd);
  182. }
  183. static SRP_user_pwd *SRP_user_pwd_new()
  184. {
  185. SRP_user_pwd *ret = OPENSSL_malloc(sizeof(SRP_user_pwd));
  186. if (ret == NULL)
  187. return NULL;
  188. ret->N = NULL;
  189. ret->g = NULL;
  190. ret->s = NULL;
  191. ret->v = NULL;
  192. ret->id = NULL ;
  193. ret->info = NULL;
  194. return ret;
  195. }
  196. static void SRP_user_pwd_set_gN(SRP_user_pwd *vinfo, const BIGNUM *g,
  197. const BIGNUM *N)
  198. {
  199. vinfo->N = N;
  200. vinfo->g = g;
  201. }
  202. static int SRP_user_pwd_set_ids(SRP_user_pwd *vinfo, const char *id,
  203. const char *info)
  204. {
  205. if (id != NULL && NULL == (vinfo->id = BUF_strdup(id)))
  206. return 0;
  207. return (info == NULL || NULL != (vinfo->info = BUF_strdup(info))) ;
  208. }
  209. static int SRP_user_pwd_set_sv(SRP_user_pwd *vinfo, const char *s,
  210. const char *v)
  211. {
  212. unsigned char tmp[MAX_LEN];
  213. int len;
  214. if (strlen(s) > MAX_LEN || strlen(v) > MAX_LEN)
  215. return 0;
  216. len = t_fromb64(tmp, v);
  217. if (NULL == (vinfo->v = BN_bin2bn(tmp, len, NULL)) )
  218. return 0;
  219. len = t_fromb64(tmp, s);
  220. return ((vinfo->s = BN_bin2bn(tmp, len, NULL)) != NULL) ;
  221. }
  222. static int SRP_user_pwd_set_sv_BN(SRP_user_pwd *vinfo, BIGNUM *s, BIGNUM *v)
  223. {
  224. vinfo->v = v;
  225. vinfo->s = s;
  226. return (vinfo->s != NULL && vinfo->v != NULL) ;
  227. }
  228. SRP_VBASE *SRP_VBASE_new(char *seed_key)
  229. {
  230. SRP_VBASE *vb = (SRP_VBASE *) OPENSSL_malloc(sizeof(SRP_VBASE));
  231. if (vb == NULL)
  232. return NULL;
  233. if (!(vb->users_pwd = sk_SRP_user_pwd_new_null()) ||
  234. !(vb->gN_cache = sk_SRP_gN_cache_new_null()))
  235. {
  236. OPENSSL_free(vb);
  237. return NULL;
  238. }
  239. vb->default_g = NULL;
  240. vb->default_N = NULL;
  241. vb->seed_key = NULL;
  242. if ((seed_key != NULL) &&
  243. (vb->seed_key = BUF_strdup(seed_key)) == NULL)
  244. {
  245. sk_SRP_user_pwd_free(vb->users_pwd);
  246. sk_SRP_gN_cache_free(vb->gN_cache);
  247. OPENSSL_free(vb);
  248. return NULL;
  249. }
  250. return vb;
  251. }
  252. int SRP_VBASE_free(SRP_VBASE *vb)
  253. {
  254. sk_SRP_user_pwd_pop_free(vb->users_pwd,SRP_user_pwd_free);
  255. sk_SRP_gN_cache_free(vb->gN_cache);
  256. OPENSSL_free(vb->seed_key);
  257. OPENSSL_free(vb);
  258. return 0;
  259. }
  260. static SRP_gN_cache *SRP_gN_new_init(const char *ch)
  261. {
  262. unsigned char tmp[MAX_LEN];
  263. int len;
  264. SRP_gN_cache *newgN = (SRP_gN_cache *)OPENSSL_malloc(sizeof(SRP_gN_cache));
  265. if (newgN == NULL)
  266. return NULL;
  267. if ((newgN->b64_bn = BUF_strdup(ch)) == NULL)
  268. goto err;
  269. len = t_fromb64(tmp, ch);
  270. if ((newgN->bn = BN_bin2bn(tmp, len, NULL)))
  271. return newgN;
  272. OPENSSL_free(newgN->b64_bn);
  273. err:
  274. OPENSSL_free(newgN);
  275. return NULL;
  276. }
  277. static void SRP_gN_free(SRP_gN_cache *gN_cache)
  278. {
  279. if (gN_cache == NULL)
  280. return;
  281. OPENSSL_free(gN_cache->b64_bn);
  282. BN_free(gN_cache->bn);
  283. OPENSSL_free(gN_cache);
  284. }
  285. static SRP_gN *SRP_get_gN_by_id(const char *id, STACK_OF(SRP_gN) *gN_tab)
  286. {
  287. int i;
  288. SRP_gN *gN;
  289. if (gN_tab != NULL)
  290. for(i = 0; i < sk_SRP_gN_num(gN_tab); i++)
  291. {
  292. gN = sk_SRP_gN_value(gN_tab, i);
  293. if (gN && (id == NULL || strcmp(gN->id,id)==0))
  294. return gN;
  295. }
  296. return SRP_get_default_gN(id);
  297. }
  298. static BIGNUM *SRP_gN_place_bn(STACK_OF(SRP_gN_cache) *gN_cache, char *ch)
  299. {
  300. int i;
  301. if (gN_cache == NULL)
  302. return NULL;
  303. /* search if we have already one... */
  304. for(i = 0; i < sk_SRP_gN_cache_num(gN_cache); i++)
  305. {
  306. SRP_gN_cache *cache = sk_SRP_gN_cache_value(gN_cache, i);
  307. if (strcmp(cache->b64_bn,ch)==0)
  308. return cache->bn;
  309. }
  310. { /* it is the first time that we find it */
  311. SRP_gN_cache *newgN = SRP_gN_new_init(ch);
  312. if (newgN)
  313. {
  314. if (sk_SRP_gN_cache_insert(gN_cache,newgN,0)>0)
  315. return newgN->bn;
  316. SRP_gN_free(newgN);
  317. }
  318. }
  319. return NULL;
  320. }
  321. /* this function parses verifier file. Format is:
  322. * string(index):base64(N):base64(g):0
  323. * string(username):base64(v):base64(salt):int(index)
  324. */
  325. int SRP_VBASE_init(SRP_VBASE *vb, char *verifier_file)
  326. {
  327. int error_code ;
  328. STACK_OF(SRP_gN) *SRP_gN_tab = sk_SRP_gN_new_null();
  329. char *last_index = NULL;
  330. int i;
  331. char **pp;
  332. SRP_gN *gN = NULL;
  333. SRP_user_pwd *user_pwd = NULL ;
  334. TXT_DB *tmpdb = NULL;
  335. BIO *in = BIO_new(BIO_s_file());
  336. error_code = SRP_ERR_OPEN_FILE;
  337. if (in == NULL || BIO_read_filename(in,verifier_file) <= 0)
  338. goto err;
  339. error_code = SRP_ERR_VBASE_INCOMPLETE_FILE;
  340. if ((tmpdb =TXT_DB_read(in,DB_NUMBER)) == NULL)
  341. goto err;
  342. error_code = SRP_ERR_MEMORY;
  343. if (vb->seed_key)
  344. {
  345. last_index = SRP_get_default_gN(NULL)->id;
  346. }
  347. for (i = 0; i < sk_OPENSSL_PSTRING_num(tmpdb->data); i++)
  348. {
  349. pp = sk_OPENSSL_PSTRING_value(tmpdb->data,i);
  350. if (pp[DB_srptype][0] == DB_SRP_INDEX)
  351. {
  352. /*we add this couple in the internal Stack */
  353. if ((gN = (SRP_gN *)OPENSSL_malloc(sizeof(SRP_gN))) == NULL)
  354. goto err;
  355. if (!(gN->id = BUF_strdup(pp[DB_srpid]))
  356. || !(gN->N = SRP_gN_place_bn(vb->gN_cache,pp[DB_srpverifier]))
  357. || !(gN->g = SRP_gN_place_bn(vb->gN_cache,pp[DB_srpsalt]))
  358. || sk_SRP_gN_insert(SRP_gN_tab,gN,0) == 0)
  359. goto err;
  360. gN = NULL;
  361. if (vb->seed_key != NULL)
  362. {
  363. last_index = pp[DB_srpid];
  364. }
  365. }
  366. else if (pp[DB_srptype][0] == DB_SRP_VALID)
  367. {
  368. /* it is a user .... */
  369. SRP_gN *lgN;
  370. if ((lgN = SRP_get_gN_by_id(pp[DB_srpgN],SRP_gN_tab))!=NULL)
  371. {
  372. error_code = SRP_ERR_MEMORY;
  373. if ((user_pwd = SRP_user_pwd_new()) == NULL)
  374. goto err;
  375. SRP_user_pwd_set_gN(user_pwd,lgN->g,lgN->N);
  376. if (!SRP_user_pwd_set_ids(user_pwd, pp[DB_srpid],pp[DB_srpinfo]))
  377. goto err;
  378. error_code = SRP_ERR_VBASE_BN_LIB;
  379. if (!SRP_user_pwd_set_sv(user_pwd, pp[DB_srpsalt],pp[DB_srpverifier]))
  380. goto err;
  381. if (sk_SRP_user_pwd_insert(vb->users_pwd, user_pwd, 0) == 0)
  382. goto err;
  383. user_pwd = NULL; /* abandon responsability */
  384. }
  385. }
  386. }
  387. if (last_index != NULL)
  388. {
  389. /* this means that we want to simulate a default user */
  390. if (((gN = SRP_get_gN_by_id(last_index,SRP_gN_tab))==NULL))
  391. {
  392. error_code = SRP_ERR_VBASE_BN_LIB;
  393. goto err;
  394. }
  395. vb->default_g = gN->g ;
  396. vb->default_N = gN->N ;
  397. gN = NULL ;
  398. }
  399. error_code = SRP_NO_ERROR;
  400. err:
  401. /* there may be still some leaks to fix, if this fails, the application terminates most likely */
  402. if (gN != NULL)
  403. {
  404. OPENSSL_free(gN->id);
  405. OPENSSL_free(gN);
  406. }
  407. SRP_user_pwd_free(user_pwd);
  408. if (tmpdb) TXT_DB_free(tmpdb);
  409. if (in) BIO_free_all(in);
  410. sk_SRP_gN_free(SRP_gN_tab);
  411. return error_code;
  412. }
  413. SRP_user_pwd *SRP_VBASE_get_by_user(SRP_VBASE *vb, char *username)
  414. {
  415. int i;
  416. SRP_user_pwd *user;
  417. unsigned char digv[SHA_DIGEST_LENGTH];
  418. unsigned char digs[SHA_DIGEST_LENGTH];
  419. EVP_MD_CTX ctxt;
  420. if (vb == NULL)
  421. return NULL;
  422. for(i = 0; i < sk_SRP_user_pwd_num(vb->users_pwd); i++)
  423. {
  424. user = sk_SRP_user_pwd_value(vb->users_pwd, i);
  425. if (strcmp(user->id,username)==0)
  426. return user;
  427. }
  428. if ((vb->seed_key == NULL) ||
  429. (vb->default_g == NULL) ||
  430. (vb->default_N == NULL))
  431. return NULL;
  432. /* if the user is unknown we set parameters as well if we have a seed_key */
  433. if ((user = SRP_user_pwd_new()) == NULL)
  434. return NULL;
  435. SRP_user_pwd_set_gN(user,vb->default_g,vb->default_N);
  436. if (!SRP_user_pwd_set_ids(user,username,NULL))
  437. goto err;
  438. RAND_pseudo_bytes(digv, SHA_DIGEST_LENGTH);
  439. EVP_MD_CTX_init(&ctxt);
  440. EVP_DigestInit_ex(&ctxt, EVP_sha1(), NULL);
  441. EVP_DigestUpdate(&ctxt, vb->seed_key, strlen(vb->seed_key));
  442. EVP_DigestUpdate(&ctxt, username, strlen(username));
  443. EVP_DigestFinal_ex(&ctxt, digs, NULL);
  444. EVP_MD_CTX_cleanup(&ctxt);
  445. if (SRP_user_pwd_set_sv_BN(user, BN_bin2bn(digs,SHA_DIGEST_LENGTH,NULL), BN_bin2bn(digv,SHA_DIGEST_LENGTH, NULL)))
  446. return user;
  447. err: SRP_user_pwd_free(user);
  448. return NULL;
  449. }
  450. /*
  451. create a verifier (*salt,*verifier,g and N are in base64)
  452. */
  453. char *SRP_create_verifier(const char *user, const char *pass, char **salt,
  454. char **verifier, const char *N, const char *g)
  455. {
  456. int len;
  457. char * result=NULL;
  458. char *vf;
  459. BIGNUM *N_bn = NULL, *g_bn = NULL, *s = NULL, *v = NULL;
  460. unsigned char tmp[MAX_LEN];
  461. unsigned char tmp2[MAX_LEN];
  462. char * defgNid = NULL;
  463. if ((user == NULL)||
  464. (pass == NULL)||
  465. (salt == NULL)||
  466. (verifier == NULL))
  467. goto err;
  468. if (N)
  469. {
  470. if (!(len = t_fromb64(tmp, N))) goto err;
  471. N_bn = BN_bin2bn(tmp, len, NULL);
  472. if (!(len = t_fromb64(tmp, g))) goto err;
  473. g_bn = BN_bin2bn(tmp, len, NULL);
  474. defgNid = "*";
  475. }
  476. else
  477. {
  478. SRP_gN * gN = SRP_get_gN_by_id(g, NULL) ;
  479. if (gN == NULL)
  480. goto err;
  481. N_bn = gN->N;
  482. g_bn = gN->g;
  483. defgNid = gN->id;
  484. }
  485. if (*salt == NULL)
  486. {
  487. RAND_pseudo_bytes(tmp2, SRP_RANDOM_SALT_LEN);
  488. s = BN_bin2bn(tmp2, SRP_RANDOM_SALT_LEN, NULL);
  489. }
  490. else
  491. {
  492. if (!(len = t_fromb64(tmp2, *salt)))
  493. goto err;
  494. s = BN_bin2bn(tmp2, len, NULL);
  495. }
  496. if(!SRP_create_verifier_BN(user, pass, &s, &v, N_bn, g_bn)) goto err;
  497. BN_bn2bin(v,tmp);
  498. if (((vf = OPENSSL_malloc(BN_num_bytes(v)*2)) == NULL))
  499. goto err;
  500. t_tob64(vf, tmp, BN_num_bytes(v));
  501. *verifier = vf;
  502. if (*salt == NULL)
  503. {
  504. char *tmp_salt;
  505. if ((tmp_salt = OPENSSL_malloc(SRP_RANDOM_SALT_LEN * 2)) == NULL)
  506. {
  507. OPENSSL_free(vf);
  508. goto err;
  509. }
  510. t_tob64(tmp_salt, tmp2, SRP_RANDOM_SALT_LEN);
  511. *salt = tmp_salt;
  512. }
  513. result=defgNid;
  514. err:
  515. if(N)
  516. {
  517. BN_free(N_bn);
  518. BN_free(g_bn);
  519. }
  520. return result;
  521. }
  522. /*
  523. create a verifier (*salt,*verifier,g and N are BIGNUMs)
  524. */
  525. int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt, BIGNUM **verifier, BIGNUM *N, BIGNUM *g)
  526. {
  527. int result=0;
  528. BIGNUM *x = NULL;
  529. BN_CTX *bn_ctx = BN_CTX_new();
  530. unsigned char tmp2[MAX_LEN];
  531. if ((user == NULL)||
  532. (pass == NULL)||
  533. (salt == NULL)||
  534. (verifier == NULL)||
  535. (N == NULL)||
  536. (g == NULL)||
  537. (bn_ctx == NULL))
  538. goto err;
  539. srp_bn_print(N);
  540. srp_bn_print(g);
  541. if (*salt == NULL)
  542. {
  543. RAND_pseudo_bytes(tmp2, SRP_RANDOM_SALT_LEN);
  544. *salt = BN_bin2bn(tmp2,SRP_RANDOM_SALT_LEN,NULL);
  545. }
  546. x = SRP_Calc_x(*salt,user,pass);
  547. *verifier = BN_new();
  548. if(*verifier == NULL) goto err;
  549. if (!BN_mod_exp(*verifier,g,x,N,bn_ctx))
  550. {
  551. BN_clear_free(*verifier);
  552. goto err;
  553. }
  554. srp_bn_print(*verifier);
  555. result=1;
  556. err:
  557. BN_clear_free(x);
  558. BN_CTX_free(bn_ctx);
  559. return result;
  560. }
  561. #endif