20e42584276b68ab46d2c6c9dd15d5dad6f82a0e
[openssl.git] / crypto / srp / srp_vfy.c
1 /*
2  * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #ifndef OPENSSL_NO_SRP
11 # include "internal/cryptlib.h"
12 # include <openssl/sha.h>
13 # include <openssl/srp.h>
14 # include <openssl/evp.h>
15 # include <openssl/buffer.h>
16 # include <openssl/rand.h>
17 # include <openssl/txt_db.h>
18
19 # define SRP_RANDOM_SALT_LEN 20
20 # define MAX_LEN 2500
21
22 static char b64table[] =
23     "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz./";
24
25 /*
26  * the following two conversion routines have been inspired by code from
27  * Stanford
28  */
29
30 /*
31  * Convert a base64 string into raw byte array representation.
32  */
33 static int t_fromb64(unsigned char *a, size_t alen, const char *src)
34 {
35     char *loc;
36     int i, j;
37     int size;
38
39     if (alen == 0 || alen > INT_MAX)
40         return -1;
41
42     while (*src && (*src == ' ' || *src == '\t' || *src == '\n'))
43         ++src;
44     size = strlen(src);
45     if (size < 0 || size >= (int)alen)
46         return -1;
47
48     i = 0;
49     while (i < size) {
50         loc = strchr(b64table, src[i]);
51         if (loc == (char *)0)
52             break;
53         else
54             a[i] = loc - b64table;
55         ++i;
56     }
57     /* if nothing valid to process we have a zero length response */
58     if (i == 0)
59         return 0;
60     size = i;
61     i = size - 1;
62     j = size;
63     while (1) {
64         a[j] = a[i];
65         if (--i < 0)
66             break;
67         a[j] |= (a[i] & 3) << 6;
68         --j;
69         a[j] = (unsigned char)((a[i] & 0x3c) >> 2);
70         if (--i < 0)
71             break;
72         a[j] |= (a[i] & 0xf) << 4;
73         --j;
74         a[j] = (unsigned char)((a[i] & 0x30) >> 4);
75         if (--i < 0)
76             break;
77         a[j] |= (a[i] << 2);
78
79         a[--j] = 0;
80         if (--i < 0)
81             break;
82     }
83     while (j <= size && a[j] == 0)
84         ++j;
85     i = 0;
86     while (j <= size)
87         a[i++] = a[j++];
88     return i;
89 }
90
91 /*
92  * Convert a raw byte string into a null-terminated base64 ASCII string.
93  */
94 static char *t_tob64(char *dst, const unsigned char *src, int size)
95 {
96     int c, pos = size % 3;
97     unsigned char b0 = 0, b1 = 0, b2 = 0, notleading = 0;
98     char *olddst = dst;
99
100     switch (pos) {
101     case 1:
102         b2 = src[0];
103         break;
104     case 2:
105         b1 = src[0];
106         b2 = src[1];
107         break;
108     }
109
110     while (1) {
111         c = (b0 & 0xfc) >> 2;
112         if (notleading || c != 0) {
113             *dst++ = b64table[c];
114             notleading = 1;
115         }
116         c = ((b0 & 3) << 4) | ((b1 & 0xf0) >> 4);
117         if (notleading || c != 0) {
118             *dst++ = b64table[c];
119             notleading = 1;
120         }
121         c = ((b1 & 0xf) << 2) | ((b2 & 0xc0) >> 6);
122         if (notleading || c != 0) {
123             *dst++ = b64table[c];
124             notleading = 1;
125         }
126         c = b2 & 0x3f;
127         if (notleading || c != 0) {
128             *dst++ = b64table[c];
129             notleading = 1;
130         }
131         if (pos >= size)
132             break;
133         else {
134             b0 = src[pos++];
135             b1 = src[pos++];
136             b2 = src[pos++];
137         }
138     }
139
140     *dst++ = '\0';
141     return olddst;
142 }
143
144 void SRP_user_pwd_free(SRP_user_pwd *user_pwd)
145 {
146     if (user_pwd == NULL)
147         return;
148     BN_free(user_pwd->s);
149     BN_clear_free(user_pwd->v);
150     OPENSSL_free(user_pwd->id);
151     OPENSSL_free(user_pwd->info);
152     OPENSSL_free(user_pwd);
153 }
154
155 static SRP_user_pwd *SRP_user_pwd_new(void)
156 {
157     SRP_user_pwd *ret = OPENSSL_malloc(sizeof(*ret));
158     if (ret == NULL)
159         return NULL;
160     ret->N = NULL;
161     ret->g = NULL;
162     ret->s = NULL;
163     ret->v = NULL;
164     ret->id = NULL;
165     ret->info = NULL;
166     return ret;
167 }
168
169 static void SRP_user_pwd_set_gN(SRP_user_pwd *vinfo, const BIGNUM *g,
170                                 const BIGNUM *N)
171 {
172     vinfo->N = N;
173     vinfo->g = g;
174 }
175
176 static int SRP_user_pwd_set_ids(SRP_user_pwd *vinfo, const char *id,
177                                 const char *info)
178 {
179     if (id != NULL && NULL == (vinfo->id = OPENSSL_strdup(id)))
180         return 0;
181     return (info == NULL || NULL != (vinfo->info = OPENSSL_strdup(info)));
182 }
183
184 static int SRP_user_pwd_set_sv(SRP_user_pwd *vinfo, const char *s,
185                                const char *v)
186 {
187     unsigned char tmp[MAX_LEN];
188     int len;
189
190     vinfo->v = NULL;
191     vinfo->s = NULL;
192
193     len = t_fromb64(tmp, sizeof(tmp), v);
194     if (len < 0)
195         return 0;
196     if (NULL == (vinfo->v = BN_bin2bn(tmp, len, NULL)))
197         return 0;
198     len = t_fromb64(tmp, sizeof(tmp), s);
199     if (len < 0)
200         goto err;
201     vinfo->s = BN_bin2bn(tmp, len, NULL);
202     if (vinfo->s == NULL)
203         goto err;
204     return 1;
205  err:
206     BN_free(vinfo->v);
207     vinfo->v = NULL;
208     return 0;
209 }
210
211 static int SRP_user_pwd_set_sv_BN(SRP_user_pwd *vinfo, BIGNUM *s, BIGNUM *v)
212 {
213     vinfo->v = v;
214     vinfo->s = s;
215     return (vinfo->s != NULL && vinfo->v != NULL);
216 }
217
218 static SRP_user_pwd *srp_user_pwd_dup(SRP_user_pwd *src)
219 {
220     SRP_user_pwd *ret;
221
222     if (src == NULL)
223         return NULL;
224     if ((ret = SRP_user_pwd_new()) == NULL)
225         return NULL;
226
227     SRP_user_pwd_set_gN(ret, src->g, src->N);
228     if (!SRP_user_pwd_set_ids(ret, src->id, src->info)
229         || !SRP_user_pwd_set_sv_BN(ret, BN_dup(src->s), BN_dup(src->v))) {
230             SRP_user_pwd_free(ret);
231             return NULL;
232     }
233     return ret;
234 }
235
236 SRP_VBASE *SRP_VBASE_new(char *seed_key)
237 {
238     SRP_VBASE *vb = OPENSSL_malloc(sizeof(*vb));
239
240     if (vb == NULL)
241         return NULL;
242     if ((vb->users_pwd = sk_SRP_user_pwd_new_null()) == NULL
243         || (vb->gN_cache = sk_SRP_gN_cache_new_null()) == NULL) {
244         OPENSSL_free(vb);
245         return NULL;
246     }
247     vb->default_g = NULL;
248     vb->default_N = NULL;
249     vb->seed_key = NULL;
250     if ((seed_key != NULL) && (vb->seed_key = OPENSSL_strdup(seed_key)) == NULL) {
251         sk_SRP_user_pwd_free(vb->users_pwd);
252         sk_SRP_gN_cache_free(vb->gN_cache);
253         OPENSSL_free(vb);
254         return NULL;
255     }
256     return vb;
257 }
258
259 void SRP_VBASE_free(SRP_VBASE *vb)
260 {
261     if (!vb)
262         return;
263     sk_SRP_user_pwd_pop_free(vb->users_pwd, SRP_user_pwd_free);
264     sk_SRP_gN_cache_free(vb->gN_cache);
265     OPENSSL_free(vb->seed_key);
266     OPENSSL_free(vb);
267 }
268
269 static SRP_gN_cache *SRP_gN_new_init(const char *ch)
270 {
271     unsigned char tmp[MAX_LEN];
272     int len;
273     SRP_gN_cache *newgN = OPENSSL_malloc(sizeof(*newgN));
274
275     if (newgN == NULL)
276         return NULL;
277
278     len = t_fromb64(tmp, sizeof(tmp), ch);
279     if (len < 0)
280         goto err;
281
282     if ((newgN->b64_bn = OPENSSL_strdup(ch)) == NULL)
283         goto err;
284
285     if ((newgN->bn = BN_bin2bn(tmp, len, NULL)))
286         return newgN;
287
288     OPENSSL_free(newgN->b64_bn);
289  err:
290     OPENSSL_free(newgN);
291     return NULL;
292 }
293
294 static void SRP_gN_free(SRP_gN_cache *gN_cache)
295 {
296     if (gN_cache == NULL)
297         return;
298     OPENSSL_free(gN_cache->b64_bn);
299     BN_free(gN_cache->bn);
300     OPENSSL_free(gN_cache);
301 }
302
303 static SRP_gN *SRP_get_gN_by_id(const char *id, STACK_OF(SRP_gN) *gN_tab)
304 {
305     int i;
306
307     SRP_gN *gN;
308     if (gN_tab != NULL)
309         for (i = 0; i < sk_SRP_gN_num(gN_tab); i++) {
310             gN = sk_SRP_gN_value(gN_tab, i);
311             if (gN && (id == NULL || strcmp(gN->id, id) == 0))
312                 return gN;
313         }
314
315     return SRP_get_default_gN(id);
316 }
317
318 static BIGNUM *SRP_gN_place_bn(STACK_OF(SRP_gN_cache) *gN_cache, char *ch)
319 {
320     int i;
321     if (gN_cache == NULL)
322         return NULL;
323
324     /* search if we have already one... */
325     for (i = 0; i < sk_SRP_gN_cache_num(gN_cache); i++) {
326         SRP_gN_cache *cache = sk_SRP_gN_cache_value(gN_cache, i);
327         if (strcmp(cache->b64_bn, ch) == 0)
328             return cache->bn;
329     }
330     {                           /* it is the first time that we find it */
331         SRP_gN_cache *newgN = SRP_gN_new_init(ch);
332         if (newgN) {
333             if (sk_SRP_gN_cache_insert(gN_cache, newgN, 0) > 0)
334                 return newgN->bn;
335             SRP_gN_free(newgN);
336         }
337     }
338     return NULL;
339 }
340
341 /*
342  * this function parses verifier file. Format is:
343  * string(index):base64(N):base64(g):0
344  * string(username):base64(v):base64(salt):int(index)
345  */
346
347 int SRP_VBASE_init(SRP_VBASE *vb, char *verifier_file)
348 {
349     int error_code;
350     STACK_OF(SRP_gN) *SRP_gN_tab = sk_SRP_gN_new_null();
351     char *last_index = NULL;
352     int i;
353     char **pp;
354
355     SRP_gN *gN = NULL;
356     SRP_user_pwd *user_pwd = NULL;
357
358     TXT_DB *tmpdb = NULL;
359     BIO *in = BIO_new(BIO_s_file());
360
361     error_code = SRP_ERR_OPEN_FILE;
362
363     if (in == NULL || BIO_read_filename(in, verifier_file) <= 0)
364         goto err;
365
366     error_code = SRP_ERR_VBASE_INCOMPLETE_FILE;
367
368     if ((tmpdb = TXT_DB_read(in, DB_NUMBER)) == NULL)
369         goto err;
370
371     error_code = SRP_ERR_MEMORY;
372
373     if (vb->seed_key) {
374         last_index = SRP_get_default_gN(NULL)->id;
375     }
376     for (i = 0; i < sk_OPENSSL_PSTRING_num(tmpdb->data); i++) {
377         pp = sk_OPENSSL_PSTRING_value(tmpdb->data, i);
378         if (pp[DB_srptype][0] == DB_SRP_INDEX) {
379             /*
380              * we add this couple in the internal Stack
381              */
382
383             if ((gN = OPENSSL_malloc(sizeof(*gN))) == NULL)
384                 goto err;
385
386             if ((gN->id = OPENSSL_strdup(pp[DB_srpid])) == NULL
387                 || (gN->N = SRP_gN_place_bn(vb->gN_cache, pp[DB_srpverifier]))
388                         == NULL
389                 || (gN->g = SRP_gN_place_bn(vb->gN_cache, pp[DB_srpsalt]))
390                         == NULL
391                 || sk_SRP_gN_insert(SRP_gN_tab, gN, 0) == 0)
392                 goto err;
393
394             gN = NULL;
395
396             if (vb->seed_key != NULL) {
397                 last_index = pp[DB_srpid];
398             }
399         } else if (pp[DB_srptype][0] == DB_SRP_VALID) {
400             /* it is a user .... */
401             const SRP_gN *lgN;
402
403             if ((lgN = SRP_get_gN_by_id(pp[DB_srpgN], SRP_gN_tab)) != NULL) {
404                 error_code = SRP_ERR_MEMORY;
405                 if ((user_pwd = SRP_user_pwd_new()) == NULL)
406                     goto err;
407
408                 SRP_user_pwd_set_gN(user_pwd, lgN->g, lgN->N);
409                 if (!SRP_user_pwd_set_ids
410                     (user_pwd, pp[DB_srpid], pp[DB_srpinfo]))
411                     goto err;
412
413                 error_code = SRP_ERR_VBASE_BN_LIB;
414                 if (!SRP_user_pwd_set_sv
415                     (user_pwd, pp[DB_srpsalt], pp[DB_srpverifier]))
416                     goto err;
417
418                 if (sk_SRP_user_pwd_insert(vb->users_pwd, user_pwd, 0) == 0)
419                     goto err;
420                 user_pwd = NULL; /* abandon responsibility */
421             }
422         }
423     }
424
425     if (last_index != NULL) {
426         /* this means that we want to simulate a default user */
427
428         if (((gN = SRP_get_gN_by_id(last_index, SRP_gN_tab)) == NULL)) {
429             error_code = SRP_ERR_VBASE_BN_LIB;
430             goto err;
431         }
432         vb->default_g = gN->g;
433         vb->default_N = gN->N;
434         gN = NULL;
435     }
436     error_code = SRP_NO_ERROR;
437
438  err:
439     /*
440      * there may be still some leaks to fix, if this fails, the application
441      * terminates most likely
442      */
443
444     if (gN != NULL) {
445         OPENSSL_free(gN->id);
446         OPENSSL_free(gN);
447     }
448
449     SRP_user_pwd_free(user_pwd);
450
451     TXT_DB_free(tmpdb);
452     BIO_free_all(in);
453
454     sk_SRP_gN_free(SRP_gN_tab);
455
456     return error_code;
457
458 }
459
460 static SRP_user_pwd *find_user(SRP_VBASE *vb, char *username)
461 {
462     int i;
463     SRP_user_pwd *user;
464
465     if (vb == NULL)
466         return NULL;
467
468     for (i = 0; i < sk_SRP_user_pwd_num(vb->users_pwd); i++) {
469         user = sk_SRP_user_pwd_value(vb->users_pwd, i);
470         if (strcmp(user->id, username) == 0)
471             return user;
472     }
473
474     return NULL;
475 }
476
477 # if OPENSSL_API_COMPAT < 0x10100000L
478 /*
479  * DEPRECATED: use SRP_VBASE_get1_by_user instead.
480  * This method ignores the configured seed and fails for an unknown user.
481  * Ownership of the returned pointer is not released to the caller.
482  * In other words, caller must not free the result.
483  */
484 SRP_user_pwd *SRP_VBASE_get_by_user(SRP_VBASE *vb, char *username)
485 {
486     return find_user(vb, username);
487 }
488 # endif
489
490 /*
491  * Ownership of the returned pointer is released to the caller.
492  * In other words, caller must free the result once done.
493  */
494 SRP_user_pwd *SRP_VBASE_get1_by_user(SRP_VBASE *vb, char *username)
495 {
496     SRP_user_pwd *user;
497     unsigned char digv[SHA_DIGEST_LENGTH];
498     unsigned char digs[SHA_DIGEST_LENGTH];
499     EVP_MD_CTX *ctxt = NULL;
500
501     if (vb == NULL)
502         return NULL;
503
504     if ((user = find_user(vb, username)) != NULL)
505         return srp_user_pwd_dup(user);
506
507     if ((vb->seed_key == NULL) ||
508         (vb->default_g == NULL) || (vb->default_N == NULL))
509         return NULL;
510
511 /* if the user is unknown we set parameters as well if we have a seed_key */
512
513     if ((user = SRP_user_pwd_new()) == NULL)
514         return NULL;
515
516     SRP_user_pwd_set_gN(user, vb->default_g, vb->default_N);
517
518     if (!SRP_user_pwd_set_ids(user, username, NULL))
519         goto err;
520
521     if (RAND_bytes(digv, SHA_DIGEST_LENGTH) <= 0)
522         goto err;
523     ctxt = EVP_MD_CTX_new();
524     if (ctxt == NULL
525         || !EVP_DigestInit_ex(ctxt, EVP_sha1(), NULL)
526         || !EVP_DigestUpdate(ctxt, vb->seed_key, strlen(vb->seed_key))
527         || !EVP_DigestUpdate(ctxt, username, strlen(username))
528         || !EVP_DigestFinal_ex(ctxt, digs, NULL))
529         goto err;
530     EVP_MD_CTX_free(ctxt);
531     ctxt = NULL;
532     if (SRP_user_pwd_set_sv_BN(user,
533                                BN_bin2bn(digs, SHA_DIGEST_LENGTH, NULL),
534                                BN_bin2bn(digv, SHA_DIGEST_LENGTH, NULL)))
535         return user;
536
537  err:
538     EVP_MD_CTX_free(ctxt);
539     SRP_user_pwd_free(user);
540     return NULL;
541 }
542
543 /*
544  * create a verifier (*salt,*verifier,g and N are in base64)
545  */
546 char *SRP_create_verifier(const char *user, const char *pass, char **salt,
547                           char **verifier, const char *N, const char *g)
548 {
549     int len;
550     char *result = NULL, *vf = NULL;
551     const BIGNUM *N_bn = NULL, *g_bn = NULL;
552     BIGNUM *N_bn_alloc = NULL, *g_bn_alloc = NULL, *s = NULL, *v = NULL;
553     unsigned char tmp[MAX_LEN];
554     unsigned char tmp2[MAX_LEN];
555     char *defgNid = NULL;
556     int vfsize = 0;
557
558     if ((user == NULL) ||
559         (pass == NULL) || (salt == NULL) || (verifier == NULL))
560         goto err;
561
562     if (N) {
563         if ((len = t_fromb64(tmp, sizeof(tmp), N)) <= 0)
564             goto err;
565         N_bn_alloc = BN_bin2bn(tmp, len, NULL);
566         N_bn = N_bn_alloc;
567         if ((len = t_fromb64(tmp, sizeof(tmp) ,g)) <= 0)
568             goto err;
569         g_bn_alloc = BN_bin2bn(tmp, len, NULL);
570         g_bn = g_bn_alloc;
571         defgNid = "*";
572     } else {
573         SRP_gN *gN = SRP_get_gN_by_id(g, NULL);
574         if (gN == NULL)
575             goto err;
576         N_bn = gN->N;
577         g_bn = gN->g;
578         defgNid = gN->id;
579     }
580
581     if (*salt == NULL) {
582         if (RAND_bytes(tmp2, SRP_RANDOM_SALT_LEN) <= 0)
583             goto err;
584
585         s = BN_bin2bn(tmp2, SRP_RANDOM_SALT_LEN, NULL);
586     } else {
587         if ((len = t_fromb64(tmp2, sizeof(tmp2), *salt)) <= 0)
588             goto err;
589         s = BN_bin2bn(tmp2, len, NULL);
590     }
591
592     if (!SRP_create_verifier_BN(user, pass, &s, &v, N_bn, g_bn))
593         goto err;
594
595     BN_bn2bin(v, tmp);
596     vfsize = BN_num_bytes(v) * 2;
597     if (((vf = OPENSSL_malloc(vfsize)) == NULL))
598         goto err;
599     t_tob64(vf, tmp, BN_num_bytes(v));
600
601     if (*salt == NULL) {
602         char *tmp_salt;
603
604         if ((tmp_salt = OPENSSL_malloc(SRP_RANDOM_SALT_LEN * 2)) == NULL) {
605             goto err;
606         }
607         t_tob64(tmp_salt, tmp2, SRP_RANDOM_SALT_LEN);
608         *salt = tmp_salt;
609     }
610
611     *verifier = vf;
612     vf = NULL;
613     result = defgNid;
614
615  err:
616     BN_free(N_bn_alloc);
617     BN_free(g_bn_alloc);
618     OPENSSL_clear_free(vf, vfsize);
619     BN_clear_free(s);
620     BN_clear_free(v);
621     return result;
622 }
623
624 /*
625  * create a verifier (*salt,*verifier,g and N are BIGNUMs). If *salt != NULL
626  * then the provided salt will be used. On successful exit *verifier will point
627  * to a newly allocated BIGNUM containing the verifier and (if a salt was not
628  * provided) *salt will be populated with a newly allocated BIGNUM containing a
629  * random salt.
630  * The caller is responsible for freeing the allocated *salt and *verifier
631  * BIGNUMS.
632  */
633 int SRP_create_verifier_BN(const char *user, const char *pass, BIGNUM **salt,
634                            BIGNUM **verifier, const BIGNUM *N,
635                            const BIGNUM *g)
636 {
637     int result = 0;
638     BIGNUM *x = NULL;
639     BN_CTX *bn_ctx = BN_CTX_new();
640     unsigned char tmp2[MAX_LEN];
641     BIGNUM *salttmp = NULL;
642
643     if ((user == NULL) ||
644         (pass == NULL) ||
645         (salt == NULL) ||
646         (verifier == NULL) || (N == NULL) || (g == NULL) || (bn_ctx == NULL))
647         goto err;
648
649     if (*salt == NULL) {
650         if (RAND_bytes(tmp2, SRP_RANDOM_SALT_LEN) <= 0)
651             goto err;
652
653         salttmp = BN_bin2bn(tmp2, SRP_RANDOM_SALT_LEN, NULL);
654     } else {
655         salttmp = *salt;
656     }
657
658     x = SRP_Calc_x(salttmp, user, pass);
659
660     *verifier = BN_new();
661     if (*verifier == NULL)
662         goto err;
663
664     if (!BN_mod_exp(*verifier, g, x, N, bn_ctx)) {
665         BN_clear_free(*verifier);
666         goto err;
667     }
668
669     result = 1;
670     *salt = salttmp;
671
672  err:
673     if (salt != NULL && *salt != salttmp)
674         BN_clear_free(salttmp);
675     BN_clear_free(x);
676     BN_CTX_free(bn_ctx);
677     return result;
678 }
679
680 #endif