Coverage Report

Created: 2025-01-28 06:58

/src/gnutls/lib/srp.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2001-2016 Free Software Foundation, Inc.
3
 * Copyright (C) 2015-2016 Red Hat, Inc.
4
 *
5
 * Author: Nikos Mavrogiannopoulos
6
 *
7
 * This file is part of GnuTLS.
8
 *
9
 * The GnuTLS is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Lesser General Public License
11
 * as published by the Free Software Foundation; either version 2.1 of
12
 * the License, or (at your option) any later version.
13
 *
14
 * This library is distributed in the hope that it will be useful, but
15
 * WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 * Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public License
20
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
21
 *
22
 */
23
24
#include "gnutls_int.h"
25
#include "errors.h"
26
#include "auth/srp_kx.h"
27
#include "state.h"
28
29
#ifdef ENABLE_SRP
30
31
#include "srp.h"
32
#include "auth/srp_passwd.h"
33
#include "mpi.h"
34
#include "num.h"
35
#include "file.h"
36
#include "algorithms.h"
37
#include "random.h"
38
39
#include "debug.h"
40
#include "attribute.h"
41
42
/* Here functions for SRP (like g^x mod n) are defined 
43
 */
44
45
static int _gnutls_srp_gx(uint8_t *text, size_t textsize, uint8_t **result,
46
        bigint_t g, bigint_t prime)
47
{
48
  bigint_t x, e = NULL;
49
  size_t result_size;
50
  int ret;
51
52
  if (_gnutls_mpi_init_scan_nz(&x, text, textsize)) {
53
    gnutls_assert();
54
    return GNUTLS_E_MPI_SCAN_FAILED;
55
  }
56
57
  ret = _gnutls_mpi_init(&e);
58
  if (ret < 0)
59
    goto cleanup;
60
61
  /* e = g^x mod prime (n) */
62
  ret = _gnutls_mpi_powm(e, g, x, prime);
63
  if (ret < 0)
64
    goto cleanup;
65
66
  ret = _gnutls_mpi_print(e, NULL, &result_size);
67
  if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) {
68
    *result = gnutls_malloc(result_size);
69
    if ((*result) == NULL) {
70
      ret = GNUTLS_E_MEMORY_ERROR;
71
      goto cleanup;
72
    }
73
74
    ret = _gnutls_mpi_print(e, *result, &result_size);
75
    if (ret < 0)
76
      goto cleanup;
77
78
    ret = result_size;
79
  } else {
80
    gnutls_assert();
81
    ret = GNUTLS_E_MPI_PRINT_FAILED;
82
  }
83
84
cleanup:
85
  _gnutls_mpi_release(&e);
86
  _gnutls_mpi_release(&x);
87
88
  return ret;
89
}
90
91
/****************
92
 * Choose a random value b and calculate B = (k* v + g^b) % N.
93
 * where k == SHA1(N|g)
94
 * Return: B and if ret_b is not NULL b.
95
 */
96
bigint_t _gnutls_calc_srp_B(bigint_t *ret_b, bigint_t g, bigint_t n, bigint_t v)
97
{
98
  bigint_t tmpB = NULL, tmpV = NULL;
99
  bigint_t b = NULL, B = NULL, k = NULL;
100
  int ret;
101
102
  /* calculate:  B = (k*v + g^b) % N 
103
   */
104
  ret = _gnutls_mpi_init_multi(&tmpV, &tmpB, &B, &b, NULL);
105
  if (ret < 0)
106
    return NULL;
107
108
  _gnutls_mpi_random_modp(b, n, GNUTLS_RND_RANDOM);
109
110
  k = _gnutls_calc_srp_u(n, g, n);
111
  if (k == NULL) {
112
    gnutls_assert();
113
    goto error;
114
  }
115
116
  ret = _gnutls_mpi_mulm(tmpV, k, v, n);
117
  if (ret < 0) {
118
    gnutls_assert();
119
    goto error;
120
  }
121
122
  ret = _gnutls_mpi_powm(tmpB, g, b, n);
123
  if (ret < 0) {
124
    gnutls_assert();
125
    goto error;
126
  }
127
128
  ret = _gnutls_mpi_addm(B, tmpV, tmpB, n);
129
  if (ret < 0) {
130
    gnutls_assert();
131
    goto error;
132
  }
133
134
  _gnutls_mpi_release(&k);
135
  _gnutls_mpi_release(&tmpB);
136
  _gnutls_mpi_release(&tmpV);
137
138
  if (ret_b)
139
    *ret_b = b;
140
  else
141
    _gnutls_mpi_release(&b);
142
143
  return B;
144
145
error:
146
  _gnutls_mpi_release(&b);
147
  _gnutls_mpi_release(&B);
148
  _gnutls_mpi_release(&k);
149
  _gnutls_mpi_release(&tmpB);
150
  _gnutls_mpi_release(&tmpV);
151
  return NULL;
152
}
153
154
/* This calculates the SHA1(A | B)
155
 * A and B will be left-padded with zeros to fill n_size.
156
 */
157
bigint_t _gnutls_calc_srp_u(bigint_t A, bigint_t B, bigint_t n)
158
{
159
  size_t b_size, a_size;
160
  uint8_t *holder, hd[MAX_HASH_SIZE];
161
  size_t holder_size, hash_size, n_size;
162
  int ret;
163
  bigint_t res;
164
165
  /* get the size of n in bytes */
166
  _gnutls_mpi_print(n, NULL, &n_size);
167
168
  _gnutls_mpi_print(A, NULL, &a_size);
169
  _gnutls_mpi_print(B, NULL, &b_size);
170
171
  if (a_size > n_size || b_size > n_size) {
172
    gnutls_assert();
173
    return NULL; /* internal error */
174
  }
175
176
  holder_size = n_size + n_size;
177
178
  holder = gnutls_calloc(1, holder_size);
179
  if (holder == NULL)
180
    return NULL;
181
182
  _gnutls_mpi_print(A, &holder[n_size - a_size], &a_size);
183
  _gnutls_mpi_print(B, &holder[n_size + n_size - b_size], &b_size);
184
185
  ret = _gnutls_hash_fast(GNUTLS_DIG_SHA1, holder, holder_size, hd);
186
  if (ret < 0) {
187
    gnutls_free(holder);
188
    gnutls_assert();
189
    return NULL;
190
  }
191
192
  /* convert the bytes of hd to integer
193
   */
194
  hash_size = 20; /* SHA */
195
  ret = _gnutls_mpi_init_scan_nz(&res, hd, hash_size);
196
  gnutls_free(holder);
197
198
  if (ret < 0) {
199
    gnutls_assert();
200
    return NULL;
201
  }
202
203
  return res;
204
}
205
206
/* S = (A * v^u) ^ b % N 
207
 * this is our shared key (server premaster secret)
208
 */
209
bigint_t _gnutls_calc_srp_S1(bigint_t A, bigint_t b, bigint_t u, bigint_t v,
210
           bigint_t n)
211
{
212
  bigint_t tmp1 = NULL, tmp2 = NULL;
213
  bigint_t S = NULL;
214
  int ret;
215
216
  ret = _gnutls_mpi_init_multi(&S, &tmp1, &tmp2, NULL);
217
  if (ret < 0)
218
    return NULL;
219
220
  ret = _gnutls_mpi_powm(tmp1, v, u, n);
221
  if (ret < 0) {
222
    gnutls_assert();
223
    goto error;
224
  }
225
226
  ret = _gnutls_mpi_mulm(tmp2, A, tmp1, n);
227
  if (ret < 0) {
228
    gnutls_assert();
229
    goto error;
230
  }
231
232
  _gnutls_mpi_powm(S, tmp2, b, n);
233
234
  _gnutls_mpi_release(&tmp1);
235
  _gnutls_mpi_release(&tmp2);
236
237
  return S;
238
239
error:
240
  _gnutls_mpi_release(&S);
241
  _gnutls_mpi_release(&tmp1);
242
  _gnutls_mpi_release(&tmp2);
243
  return NULL;
244
}
245
246
/* A = g^a % N 
247
 * returns A and a (which is random)
248
 */
249
bigint_t _gnutls_calc_srp_A(bigint_t *a, bigint_t g, bigint_t n)
250
{
251
  bigint_t tmpa;
252
  bigint_t A;
253
  int ret;
254
255
  ret = _gnutls_mpi_init_multi(&A, &tmpa, NULL);
256
  if (ret < 0) {
257
    gnutls_assert();
258
    return NULL;
259
  }
260
261
  _gnutls_mpi_random_modp(tmpa, n, GNUTLS_RND_RANDOM);
262
263
  ret = _gnutls_mpi_powm(A, g, tmpa, n);
264
  if (ret < 0)
265
    goto error;
266
267
  if (a != NULL)
268
    *a = tmpa;
269
  else
270
    _gnutls_mpi_release(&tmpa);
271
272
  return A;
273
error:
274
  _gnutls_mpi_release(&tmpa);
275
  _gnutls_mpi_release(&A);
276
  return NULL;
277
}
278
279
/* generate x = SHA(s | SHA(U | ":" | p))
280
 * The output is exactly 20 bytes
281
 */
282
static int _gnutls_calc_srp_sha(const char *username, const char *_password,
283
        uint8_t *salt, int salt_size, size_t *size,
284
        void *digest, unsigned allow_invalid_pass)
285
{
286
  digest_hd_st td;
287
  uint8_t res[MAX_HASH_SIZE];
288
  int ret;
289
  const mac_entry_st *me = mac_to_entry(GNUTLS_MAC_SHA1);
290
  char *password;
291
  gnutls_datum_t pout;
292
293
  *size = 20;
294
295
  ret = _gnutls_utf8_password_normalize(_password, strlen(_password),
296
                &pout, allow_invalid_pass);
297
  if (ret < 0)
298
    return gnutls_assert_val(ret);
299
  password = (char *)pout.data;
300
301
  ret = _gnutls_hash_init(&td, me);
302
  if (ret < 0) {
303
    ret = GNUTLS_E_MEMORY_ERROR;
304
    goto cleanup;
305
  }
306
  _gnutls_hash(&td, username, strlen(username));
307
  _gnutls_hash(&td, ":", 1);
308
  _gnutls_hash(&td, password, strlen(password));
309
310
  _gnutls_hash_deinit(&td, res);
311
312
  ret = _gnutls_hash_init(&td, me);
313
  if (ret < 0) {
314
    ret = GNUTLS_E_MEMORY_ERROR;
315
    goto cleanup;
316
  }
317
318
  _gnutls_hash(&td, salt, salt_size);
319
  _gnutls_hash(&td, res, 20); /* 20 bytes is the output of sha1 */
320
321
  _gnutls_hash_deinit(&td, digest);
322
  ret = 0;
323
324
cleanup:
325
  gnutls_free(password);
326
  return ret;
327
}
328
329
int _gnutls_calc_srp_x(char *username, char *password, uint8_t *salt,
330
           size_t salt_size, size_t *size, void *digest)
331
{
332
  return _gnutls_calc_srp_sha(username, password, salt, salt_size, size,
333
            digest, 1);
334
}
335
336
/* S = (B - k*g^x) ^ (a + u * x) % N
337
 * this is our shared key (client premaster secret)
338
 */
339
bigint_t _gnutls_calc_srp_S2(bigint_t B, bigint_t g, bigint_t x, bigint_t a,
340
           bigint_t u, bigint_t n)
341
{
342
  bigint_t S = NULL, tmp1 = NULL, tmp2 = NULL;
343
  bigint_t tmp4 = NULL, tmp3 = NULL, k = NULL;
344
  int ret;
345
346
  ret = _gnutls_mpi_init_multi(&S, &tmp1, &tmp2, &tmp3, &tmp4, NULL);
347
  if (ret < 0)
348
    return NULL;
349
350
  k = _gnutls_calc_srp_u(n, g, n);
351
  if (k == NULL) {
352
    gnutls_assert();
353
    goto freeall;
354
  }
355
356
  ret = _gnutls_mpi_powm(tmp1, g, x, n); /* g^x */
357
  if (ret < 0) {
358
    gnutls_assert();
359
    goto freeall;
360
  }
361
362
  ret = _gnutls_mpi_mulm(tmp3, tmp1, k, n); /* k*g^x mod n */
363
  if (ret < 0) {
364
    gnutls_assert();
365
    goto freeall;
366
  }
367
368
  ret = _gnutls_mpi_subm(tmp2, B, tmp3, n);
369
  if (ret < 0) {
370
    gnutls_assert();
371
    goto freeall;
372
  }
373
374
  ret = _gnutls_mpi_mul(tmp1, u, x);
375
  if (ret < 0) {
376
    gnutls_assert();
377
    goto freeall;
378
  }
379
380
  ret = _gnutls_mpi_add(tmp4, a, tmp1);
381
  if (ret < 0) {
382
    gnutls_assert();
383
    goto freeall;
384
  }
385
386
  ret = _gnutls_mpi_powm(S, tmp2, tmp4, n);
387
  if (ret < 0) {
388
    gnutls_assert();
389
    goto freeall;
390
  }
391
392
  _gnutls_mpi_release(&tmp1);
393
  _gnutls_mpi_release(&tmp2);
394
  _gnutls_mpi_release(&tmp3);
395
  _gnutls_mpi_release(&tmp4);
396
  _gnutls_mpi_release(&k);
397
398
  return S;
399
400
freeall:
401
  _gnutls_mpi_release(&k);
402
  _gnutls_mpi_release(&tmp1);
403
  _gnutls_mpi_release(&tmp2);
404
  _gnutls_mpi_release(&tmp3);
405
  _gnutls_mpi_release(&tmp4);
406
  _gnutls_mpi_release(&S);
407
  return NULL;
408
}
409
410
/**
411
 * gnutls_srp_free_client_credentials:
412
 * @sc: is a #gnutls_srp_client_credentials_t type.
413
 *
414
 * Free a gnutls_srp_client_credentials_t structure.
415
 **/
416
void gnutls_srp_free_client_credentials(gnutls_srp_client_credentials_t sc)
417
{
418
  gnutls_free(sc->username);
419
  gnutls_free(sc->password);
420
  gnutls_free(sc);
421
}
422
423
/**
424
 * gnutls_srp_allocate_client_credentials:
425
 * @sc: is a pointer to a #gnutls_srp_server_credentials_t type.
426
 *
427
 * Allocate a gnutls_srp_client_credentials_t structure.
428
 *
429
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
430
 *   error code.
431
 **/
432
int gnutls_srp_allocate_client_credentials(gnutls_srp_client_credentials_t *sc)
433
{
434
  *sc = gnutls_calloc(1, sizeof(srp_client_credentials_st));
435
436
  if (*sc == NULL)
437
    return GNUTLS_E_MEMORY_ERROR;
438
439
  return 0;
440
}
441
442
/**
443
 * gnutls_srp_set_client_credentials:
444
 * @res: is a #gnutls_srp_client_credentials_t type.
445
 * @username: is the user's userid
446
 * @password: is the user's password
447
 *
448
 * This function sets the username and password, in a
449
 * #gnutls_srp_client_credentials_t type.  Those will be used in
450
 * SRP authentication.  @username should be an ASCII string or UTF-8
451
 * string. In case of a UTF-8 string it is recommended to be following
452
 * the PRECIS framework for usernames (rfc8265). The password can
453
 * be in ASCII format, or normalized using gnutls_utf8_password_normalize().
454
455
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
456
 *   error code.
457
 **/
458
int gnutls_srp_set_client_credentials(gnutls_srp_client_credentials_t res,
459
              const char *username,
460
              const char *password)
461
{
462
  if (username == NULL || password == NULL) {
463
    gnutls_assert();
464
    return GNUTLS_E_INVALID_REQUEST;
465
  }
466
467
  res->username = gnutls_strdup(username);
468
  if (res->username == NULL)
469
    return GNUTLS_E_MEMORY_ERROR;
470
471
  res->password = gnutls_strdup(password);
472
  if (res->password == NULL) {
473
    gnutls_free(res->username);
474
    return GNUTLS_E_MEMORY_ERROR;
475
  }
476
477
  return 0;
478
}
479
480
/**
481
 * gnutls_srp_free_server_credentials:
482
 * @sc: is a #gnutls_srp_server_credentials_t type.
483
 *
484
 * Free a gnutls_srp_server_credentials_t structure.
485
 **/
486
void gnutls_srp_free_server_credentials(gnutls_srp_server_credentials_t sc)
487
{
488
  gnutls_free(sc->password_file);
489
  gnutls_free(sc->password_conf_file);
490
491
  gnutls_free(sc);
492
}
493
494
/* Size of the default (random) seed if
495
 * gnutls_srp_set_server_fake_salt_seed() is not called to set
496
 * a seed.
497
 */
498
#define DEFAULT_FAKE_SALT_SEED_SIZE 20
499
500
/* Size of the fake salts generated if
501
 * gnutls_srp_set_server_fake_salt_seed() is not called to set
502
 * another size.
503
 */
504
#define DEFAULT_FAKE_SALT_SIZE 16
505
506
/**
507
 * gnutls_srp_allocate_server_credentials:
508
 * @sc: is a pointer to a #gnutls_srp_server_credentials_t type.
509
 *
510
 * Allocate a gnutls_srp_server_credentials_t structure.
511
 *
512
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
513
 *   error code.
514
 **/
515
int gnutls_srp_allocate_server_credentials(gnutls_srp_server_credentials_t *sc)
516
{
517
  int ret;
518
  *sc = gnutls_calloc(1, sizeof(srp_server_cred_st));
519
520
  if (*sc == NULL)
521
    return GNUTLS_E_MEMORY_ERROR;
522
523
  (*sc)->fake_salt_seed_size = DEFAULT_FAKE_SALT_SEED_SIZE;
524
  ret = gnutls_rnd(GNUTLS_RND_RANDOM, (*sc)->fake_salt_seed,
525
       DEFAULT_FAKE_SALT_SEED_SIZE);
526
527
  if (ret < 0) {
528
    gnutls_assert();
529
    goto cleanup;
530
  }
531
532
  (*sc)->fake_salt_length = DEFAULT_FAKE_SALT_SIZE;
533
  return 0;
534
535
cleanup:
536
  gnutls_free(*sc);
537
  return ret;
538
}
539
540
/**
541
 * gnutls_srp_set_server_credentials_file:
542
 * @res: is a #gnutls_srp_server_credentials_t type.
543
 * @password_file: is the SRP password file (tpasswd)
544
 * @password_conf_file: is the SRP password conf file (tpasswd.conf)
545
 *
546
 * This function sets the password files, in a
547
 * #gnutls_srp_server_credentials_t type.  Those password files
548
 * hold usernames and verifiers and will be used for SRP
549
 * authentication.
550
 *
551
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
552
 *   error code.
553
 **/
554
int gnutls_srp_set_server_credentials_file(gnutls_srp_server_credentials_t res,
555
             const char *password_file,
556
             const char *password_conf_file)
557
{
558
  if (password_file == NULL || password_conf_file == NULL) {
559
    gnutls_assert();
560
    return GNUTLS_E_INVALID_REQUEST;
561
  }
562
563
  /* Check if the files can be opened */
564
  if (_gnutls_file_exists(password_file) != 0) {
565
    gnutls_assert();
566
    return GNUTLS_E_FILE_ERROR;
567
  }
568
569
  if (_gnutls_file_exists(password_conf_file) != 0) {
570
    gnutls_assert();
571
    return GNUTLS_E_FILE_ERROR;
572
  }
573
574
  res->password_file = gnutls_strdup(password_file);
575
  if (res->password_file == NULL) {
576
    gnutls_assert();
577
    return GNUTLS_E_MEMORY_ERROR;
578
  }
579
580
  res->password_conf_file = gnutls_strdup(password_conf_file);
581
  if (res->password_conf_file == NULL) {
582
    gnutls_assert();
583
    gnutls_free(res->password_file);
584
    return GNUTLS_E_MEMORY_ERROR;
585
  }
586
587
  return 0;
588
}
589
590
/**
591
 * gnutls_srp_set_server_credentials_function:
592
 * @cred: is a #gnutls_srp_server_credentials_t type.
593
 * @func: is the callback function
594
 *
595
 * This function can be used to set a callback to retrieve the user's
596
 * SRP credentials.  The callback's function form is:
597
 *
598
 * int (*callback)(gnutls_session_t, const char* username,
599
 *  gnutls_datum_t *salt, gnutls_datum_t *verifier, gnutls_datum_t *generator,
600
 *  gnutls_datum_t *prime);
601
 *
602
 * @username contains the actual username.
603
 * The @salt, @verifier, @generator and @prime must be filled
604
 * in using the gnutls_malloc(). For convenience @prime and @generator
605
 * may also be one of the static parameters defined in gnutls.h.
606
 *
607
 * Initially, the data field is NULL in every #gnutls_datum_t
608
 * structure that the callback has to fill in. When the
609
 * callback is done GnuTLS deallocates all of those buffers
610
 * which are non-NULL, regardless of the return value.
611
 *
612
 * In order to prevent attackers from guessing valid usernames,
613
 * if a user does not exist, g and n values should be filled in
614
 * using a random user's parameters. In that case the callback must
615
 * return the special value (1).
616
 * See #gnutls_srp_set_server_fake_salt_seed too.
617
 * If this is not required for your application, return a negative
618
 * number from the callback to abort the handshake.
619
 *
620
 * The callback function will only be called once per handshake.
621
 * The callback function should return 0 on success, while
622
 * -1 indicates an error.
623
 **/
624
void gnutls_srp_set_server_credentials_function(
625
  gnutls_srp_server_credentials_t cred,
626
  gnutls_srp_server_credentials_function *func)
627
{
628
  cred->pwd_callback = func;
629
}
630
631
/**
632
 * gnutls_srp_set_client_credentials_function:
633
 * @cred: is a #gnutls_srp_server_credentials_t type.
634
 * @func: is the callback function
635
 *
636
 * This function can be used to set a callback to retrieve the
637
 * username and password for client SRP authentication.  The
638
 * callback's function form is:
639
 *
640
 * int (*callback)(gnutls_session_t, char** username, char**password);
641
 *
642
 * The @username and @password must be allocated using
643
 * gnutls_malloc().
644
 *
645
 * The @username should be an ASCII string or UTF-8
646
 * string. In case of a UTF-8 string it is recommended to be following
647
 * the PRECIS framework for usernames (rfc8265). The password can
648
 * be in ASCII format, or normalized using gnutls_utf8_password_normalize().
649
 *
650
 * The callback function will be called once per handshake before the
651
 * initial hello message is sent.
652
 *
653
 * The callback should not return a negative error code the second
654
 * time called, since the handshake procedure will be aborted.
655
 *
656
 * The callback function should return 0 on success.
657
 * -1 indicates an error.
658
 **/
659
void gnutls_srp_set_client_credentials_function(
660
  gnutls_srp_client_credentials_t cred,
661
  gnutls_srp_client_credentials_function *func)
662
{
663
  cred->get_function = func;
664
}
665
666
/**
667
 * gnutls_srp_server_get_username:
668
 * @session: is a gnutls session
669
 *
670
 * This function will return the username of the peer.  This should
671
 * only be called in case of SRP authentication and in case of a
672
 * server.  Returns NULL in case of an error.
673
 *
674
 * Returns: SRP username of the peer, or NULL in case of error.
675
 **/
676
const char *gnutls_srp_server_get_username(gnutls_session_t session)
677
{
678
  srp_server_auth_info_t info;
679
680
  CHECK_AUTH_TYPE(GNUTLS_CRD_SRP, NULL);
681
682
  info = _gnutls_get_auth_info(session, GNUTLS_CRD_SRP);
683
  if (info == NULL)
684
    return NULL;
685
  return info->username;
686
}
687
688
/**
689
 * gnutls_srp_verifier:
690
 * @username: is the user's name
691
 * @password: is the user's password
692
 * @salt: should be some randomly generated bytes
693
 * @generator: is the generator of the group
694
 * @prime: is the group's prime
695
 * @res: where the verifier will be stored.
696
 *
697
 * This function will create an SRP verifier, as specified in
698
 * RFC2945.  The @prime and @generator should be one of the static
699
 * parameters defined in gnutls/gnutls.h or may be generated.
700
 *
701
 * The verifier will be allocated with @gnutls_malloc() and will be stored in
702
 * @res using binary format.
703
 *
704
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
705
 *   error code.
706
 **/
707
int gnutls_srp_verifier(const char *username, const char *password,
708
      const gnutls_datum_t *salt,
709
      const gnutls_datum_t *generator,
710
      const gnutls_datum_t *prime, gnutls_datum_t *res)
711
{
712
  bigint_t _n, _g;
713
  int ret;
714
  size_t digest_size = 20, size;
715
  uint8_t digest[20];
716
717
  ret = _gnutls_calc_srp_sha(username, password, salt->data, salt->size,
718
           &digest_size, digest, 0);
719
  if (ret < 0) {
720
    gnutls_assert();
721
    return ret;
722
  }
723
724
  size = prime->size;
725
  if (_gnutls_mpi_init_scan_nz(&_n, prime->data, size)) {
726
    gnutls_assert();
727
    return GNUTLS_E_MPI_SCAN_FAILED;
728
  }
729
730
  size = generator->size;
731
  if (_gnutls_mpi_init_scan_nz(&_g, generator->data, size)) {
732
    gnutls_assert();
733
    _gnutls_mpi_release(&_n);
734
    return GNUTLS_E_MPI_SCAN_FAILED;
735
  }
736
737
  ret = _gnutls_srp_gx(digest, 20, &res->data, _g, _n);
738
  if (ret < 0) {
739
    gnutls_assert();
740
    _gnutls_mpi_release(&_n);
741
    _gnutls_mpi_release(&_g);
742
    return ret;
743
  }
744
  res->size = ret;
745
746
  _gnutls_mpi_release(&_n);
747
  _gnutls_mpi_release(&_g);
748
749
  return 0;
750
}
751
752
/**
753
 * gnutls_srp_set_prime_bits:
754
 * @session: is a #gnutls_session_t type.
755
 * @bits: is the number of bits
756
 *
757
 * This function sets the minimum accepted number of bits, for use in
758
 * an SRP key exchange.  If zero, the default 2048 bits will be used.
759
 *
760
 * In the client side it sets the minimum accepted number of bits.  If
761
 * a server sends a prime with less bits than that
762
 * %GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER will be returned by the
763
 * handshake.
764
 *
765
 * This function has no effect in server side.
766
 *
767
 * Since: 2.6.0
768
 **/
769
void gnutls_srp_set_prime_bits(gnutls_session_t session, unsigned int bits)
770
{
771
  session->internals.dh_prime_bits = bits;
772
}
773
774
/**
775
 * gnutls_srp_set_server_fake_salt_seed:
776
 * @cred: is a #gnutls_srp_server_credentials_t type
777
 * @seed: is the seed data, only needs to be valid until the function
778
 * returns; size of the seed must be greater than zero
779
 * @salt_length: is the length of the generated fake salts
780
 *
781
 * This function sets the seed that is used to generate salts for
782
 * invalid (non-existent) usernames.
783
 *
784
 * In order to prevent attackers from guessing valid usernames,
785
 * when a user does not exist gnutls generates a salt and a verifier
786
 * and proceeds with the protocol as usual.
787
 * The authentication will ultimately fail, but the client cannot tell
788
 * whether the username is valid (exists) or invalid.
789
 *
790
 * If an attacker learns the seed, given a salt (which is part of the
791
 * handshake) which was generated when the seed was in use, it can tell
792
 * whether or not the authentication failed because of an unknown username.
793
 * This seed cannot be used to reveal application data or passwords.
794
 *
795
 * @salt_length should represent the salt length your application uses.
796
 * Generating fake salts longer than 20 bytes is not supported.
797
 *
798
 * By default the seed is a random value, different each time a
799
 * #gnutls_srp_server_credentials_t is allocated and fake salts are
800
 * 16 bytes long.
801
 *
802
 * Since: 3.3.0
803
 **/
804
void gnutls_srp_set_server_fake_salt_seed(gnutls_srp_server_credentials_t cred,
805
            const gnutls_datum_t *seed,
806
            unsigned int salt_length)
807
{
808
  unsigned seed_size = seed->size;
809
  const unsigned char *seed_data = seed->data;
810
811
  if (seed_size > sizeof(cred->fake_salt_seed))
812
    seed_size = sizeof(cred->fake_salt_seed);
813
814
  memcpy(cred->fake_salt_seed, seed_data, seed_size);
815
  cred->fake_salt_seed_size = seed_size;
816
817
  /* Cap the salt length at the output size of the MAC algorithm
818
   * we are using to generate the fake salts.
819
   */
820
  const mac_entry_st *me = mac_to_entry(SRP_FAKE_SALT_MAC);
821
  const size_t mac_len = me->output_size;
822
823
  cred->fake_salt_length =
824
    (salt_length < mac_len ? salt_length : mac_len);
825
}
826
827
#else
828
829
void gnutls_srp_free_client_credentials(
830
  gnutls_srp_client_credentials_t sc MAYBE_UNUSED)
831
0
{
832
0
}
833
834
int gnutls_srp_allocate_client_credentials(
835
  gnutls_srp_client_credentials_t *sc MAYBE_UNUSED)
836
0
{
837
0
  return GNUTLS_E_UNIMPLEMENTED_FEATURE;
838
0
}
839
840
int gnutls_srp_set_client_credentials(
841
  gnutls_srp_client_credentials_t res MAYBE_UNUSED,
842
  const char *username MAYBE_UNUSED, const char *password MAYBE_UNUSED)
843
0
{
844
0
  return GNUTLS_E_UNIMPLEMENTED_FEATURE;
845
0
}
846
847
void gnutls_srp_free_server_credentials(
848
  gnutls_srp_server_credentials_t sc MAYBE_UNUSED)
849
0
{
850
0
}
851
852
int gnutls_srp_allocate_server_credentials(
853
  gnutls_srp_server_credentials_t *sc MAYBE_UNUSED)
854
0
{
855
0
  return GNUTLS_E_UNIMPLEMENTED_FEATURE;
856
0
}
857
858
int gnutls_srp_set_server_credentials_file(
859
  gnutls_srp_server_credentials_t res MAYBE_UNUSED,
860
  const char *password_file MAYBE_UNUSED,
861
  const char *password_conf_file MAYBE_UNUSED)
862
0
{
863
0
  return GNUTLS_E_UNIMPLEMENTED_FEATURE;
864
0
}
865
866
void gnutls_srp_set_server_credentials_function(
867
  gnutls_srp_server_credentials_t cred MAYBE_UNUSED,
868
  gnutls_srp_server_credentials_function *func MAYBE_UNUSED)
869
0
{
870
0
}
871
872
void gnutls_srp_set_client_credentials_function(
873
  gnutls_srp_client_credentials_t cred MAYBE_UNUSED,
874
  gnutls_srp_client_credentials_function *func MAYBE_UNUSED)
875
0
{
876
0
}
877
878
const char *
879
gnutls_srp_server_get_username(gnutls_session_t session MAYBE_UNUSED)
880
0
{
881
0
  return NULL;
882
0
}
883
884
int gnutls_srp_verifier(const char *username MAYBE_UNUSED,
885
      const char *password MAYBE_UNUSED,
886
      const gnutls_datum_t *salt MAYBE_UNUSED,
887
      const gnutls_datum_t *generator MAYBE_UNUSED,
888
      const gnutls_datum_t *prime MAYBE_UNUSED,
889
      gnutls_datum_t *res MAYBE_UNUSED)
890
0
{
891
0
  return GNUTLS_E_UNIMPLEMENTED_FEATURE;
892
0
}
893
894
void gnutls_srp_set_prime_bits(gnutls_session_t session MAYBE_UNUSED,
895
             unsigned int bits MAYBE_UNUSED)
896
0
{
897
0
}
898
899
void gnutls_srp_set_server_fake_salt_seed(
900
  gnutls_srp_server_credentials_t cred MAYBE_UNUSED,
901
  const gnutls_datum_t *seed MAYBE_UNUSED,
902
  unsigned int salt_length MAYBE_UNUSED)
903
0
{
904
0
}
905
906
#endif /* ENABLE_SRP */