Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/openssl/ssl/tls_srp.c
48150 views
1
/*
2
* Copyright 2004-2025 The OpenSSL Project Authors. All Rights Reserved.
3
* Copyright (c) 2004, EdelKey Project. All Rights Reserved.
4
*
5
* Licensed under the Apache License 2.0 (the "License"). You may not use
6
* this file except in compliance with the License. You can obtain a copy
7
* in the file LICENSE in the source distribution or at
8
* https://www.openssl.org/source/license.html
9
*
10
* Originally written by Christophe Renou and Peter Sylvester,
11
* for the EdelKey project.
12
*/
13
14
/*
15
* We need to use the SRP deprecated APIs in order to implement the SSL SRP
16
* APIs - which are themselves deprecated.
17
*/
18
#define OPENSSL_SUPPRESS_DEPRECATED
19
20
#include <openssl/crypto.h>
21
#include <openssl/rand.h>
22
#include <openssl/err.h>
23
#include "ssl_local.h"
24
#include "internal/ssl_unwrap.h"
25
26
#ifndef OPENSSL_NO_SRP
27
# include <openssl/srp.h>
28
29
/*
30
* The public API SSL_CTX_SRP_CTX_free() is deprecated so we use
31
* ssl_ctx_srp_ctx_free_intern() internally.
32
*/
33
int ssl_ctx_srp_ctx_free_intern(SSL_CTX *ctx)
34
{
35
if (ctx == NULL)
36
return 0;
37
OPENSSL_free(ctx->srp_ctx.login);
38
OPENSSL_free(ctx->srp_ctx.info);
39
BN_free(ctx->srp_ctx.N);
40
BN_free(ctx->srp_ctx.g);
41
BN_free(ctx->srp_ctx.s);
42
BN_free(ctx->srp_ctx.B);
43
BN_free(ctx->srp_ctx.A);
44
BN_free(ctx->srp_ctx.a);
45
BN_free(ctx->srp_ctx.b);
46
BN_free(ctx->srp_ctx.v);
47
memset(&ctx->srp_ctx, 0, sizeof(ctx->srp_ctx));
48
ctx->srp_ctx.strength = SRP_MINIMAL_N;
49
return 1;
50
}
51
52
int SSL_CTX_SRP_CTX_free(SSL_CTX *ctx)
53
{
54
return ssl_ctx_srp_ctx_free_intern(ctx);
55
}
56
57
/*
58
* The public API SSL_SRP_CTX_free() is deprecated so we use
59
* ssl_srp_ctx_free_intern() internally.
60
*/
61
int ssl_srp_ctx_free_intern(SSL_CONNECTION *s)
62
{
63
if (s == NULL)
64
return 0;
65
OPENSSL_free(s->srp_ctx.login);
66
OPENSSL_free(s->srp_ctx.info);
67
BN_free(s->srp_ctx.N);
68
BN_free(s->srp_ctx.g);
69
BN_free(s->srp_ctx.s);
70
BN_free(s->srp_ctx.B);
71
BN_free(s->srp_ctx.A);
72
BN_free(s->srp_ctx.a);
73
BN_free(s->srp_ctx.b);
74
BN_free(s->srp_ctx.v);
75
memset(&s->srp_ctx, 0, sizeof(s->srp_ctx));
76
s->srp_ctx.strength = SRP_MINIMAL_N;
77
return 1;
78
}
79
80
int SSL_SRP_CTX_free(SSL *s)
81
{
82
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
83
84
/* the call works with NULL sc */
85
return ssl_srp_ctx_free_intern(sc);
86
}
87
88
/*
89
* The public API SSL_SRP_CTX_init() is deprecated so we use
90
* ssl_srp_ctx_init_intern() internally.
91
*/
92
int ssl_srp_ctx_init_intern(SSL_CONNECTION *s)
93
{
94
SSL_CTX *ctx;
95
96
if (s == NULL || (ctx = SSL_CONNECTION_GET_CTX(s)) == NULL)
97
return 0;
98
99
memset(&s->srp_ctx, 0, sizeof(s->srp_ctx));
100
101
s->srp_ctx.SRP_cb_arg = ctx->srp_ctx.SRP_cb_arg;
102
/* set client Hello login callback */
103
s->srp_ctx.TLS_ext_srp_username_callback =
104
ctx->srp_ctx.TLS_ext_srp_username_callback;
105
/* set SRP N/g param callback for verification */
106
s->srp_ctx.SRP_verify_param_callback =
107
ctx->srp_ctx.SRP_verify_param_callback;
108
/* set SRP client passwd callback */
109
s->srp_ctx.SRP_give_srp_client_pwd_callback =
110
ctx->srp_ctx.SRP_give_srp_client_pwd_callback;
111
112
s->srp_ctx.strength = ctx->srp_ctx.strength;
113
114
if (((ctx->srp_ctx.N != NULL) &&
115
((s->srp_ctx.N = BN_dup(ctx->srp_ctx.N)) == NULL)) ||
116
((ctx->srp_ctx.g != NULL) &&
117
((s->srp_ctx.g = BN_dup(ctx->srp_ctx.g)) == NULL)) ||
118
((ctx->srp_ctx.s != NULL) &&
119
((s->srp_ctx.s = BN_dup(ctx->srp_ctx.s)) == NULL)) ||
120
((ctx->srp_ctx.B != NULL) &&
121
((s->srp_ctx.B = BN_dup(ctx->srp_ctx.B)) == NULL)) ||
122
((ctx->srp_ctx.A != NULL) &&
123
((s->srp_ctx.A = BN_dup(ctx->srp_ctx.A)) == NULL)) ||
124
((ctx->srp_ctx.a != NULL) &&
125
((s->srp_ctx.a = BN_dup(ctx->srp_ctx.a)) == NULL)) ||
126
((ctx->srp_ctx.v != NULL) &&
127
((s->srp_ctx.v = BN_dup(ctx->srp_ctx.v)) == NULL)) ||
128
((ctx->srp_ctx.b != NULL) &&
129
((s->srp_ctx.b = BN_dup(ctx->srp_ctx.b)) == NULL))) {
130
ERR_raise(ERR_LIB_SSL, ERR_R_BN_LIB);
131
goto err;
132
}
133
if ((ctx->srp_ctx.login != NULL) &&
134
((s->srp_ctx.login = OPENSSL_strdup(ctx->srp_ctx.login)) == NULL)) {
135
ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
136
goto err;
137
}
138
if ((ctx->srp_ctx.info != NULL) &&
139
((s->srp_ctx.info = OPENSSL_strdup(ctx->srp_ctx.info)) == NULL)) {
140
ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
141
goto err;
142
}
143
s->srp_ctx.srp_Mask = ctx->srp_ctx.srp_Mask;
144
145
return 1;
146
err:
147
OPENSSL_free(s->srp_ctx.login);
148
OPENSSL_free(s->srp_ctx.info);
149
BN_free(s->srp_ctx.N);
150
BN_free(s->srp_ctx.g);
151
BN_free(s->srp_ctx.s);
152
BN_free(s->srp_ctx.B);
153
BN_free(s->srp_ctx.A);
154
BN_free(s->srp_ctx.a);
155
BN_free(s->srp_ctx.b);
156
BN_free(s->srp_ctx.v);
157
memset(&s->srp_ctx, 0, sizeof(s->srp_ctx));
158
return 0;
159
}
160
161
int SSL_SRP_CTX_init(SSL *s)
162
{
163
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
164
165
/* the call works with NULL sc */
166
return ssl_srp_ctx_init_intern(sc);
167
}
168
169
/*
170
* The public API SSL_CTX_SRP_CTX_init() is deprecated so we use
171
* ssl_ctx_srp_ctx_init_intern() internally.
172
*/
173
int ssl_ctx_srp_ctx_init_intern(SSL_CTX *ctx)
174
{
175
if (ctx == NULL)
176
return 0;
177
178
memset(&ctx->srp_ctx, 0, sizeof(ctx->srp_ctx));
179
ctx->srp_ctx.strength = SRP_MINIMAL_N;
180
181
return 1;
182
}
183
184
int SSL_CTX_SRP_CTX_init(SSL_CTX *ctx)
185
{
186
return ssl_ctx_srp_ctx_init_intern(ctx);
187
}
188
189
/* server side */
190
/*
191
* The public API SSL_srp_server_param_with_username() is deprecated so we use
192
* ssl_srp_server_param_with_username_intern() internally.
193
*/
194
int ssl_srp_server_param_with_username_intern(SSL_CONNECTION *s, int *ad)
195
{
196
unsigned char b[SSL_MAX_MASTER_KEY_LENGTH];
197
int al;
198
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
199
200
*ad = SSL_AD_UNKNOWN_PSK_IDENTITY;
201
if ((s->srp_ctx.TLS_ext_srp_username_callback != NULL) &&
202
((al =
203
s->srp_ctx.TLS_ext_srp_username_callback(SSL_CONNECTION_GET_USER_SSL(s),
204
ad,
205
s->srp_ctx.SRP_cb_arg)) !=
206
SSL_ERROR_NONE))
207
return al;
208
209
*ad = SSL_AD_INTERNAL_ERROR;
210
if ((s->srp_ctx.N == NULL) ||
211
(s->srp_ctx.g == NULL) ||
212
(s->srp_ctx.s == NULL) || (s->srp_ctx.v == NULL))
213
return SSL3_AL_FATAL;
214
215
if (RAND_priv_bytes_ex(SSL_CONNECTION_GET_CTX(s)->libctx, b, sizeof(b),
216
0) <= 0)
217
return SSL3_AL_FATAL;
218
s->srp_ctx.b = BN_bin2bn(b, sizeof(b), NULL);
219
OPENSSL_cleanse(b, sizeof(b));
220
221
/* Calculate: B = (kv + g^b) % N */
222
223
return ((s->srp_ctx.B =
224
SRP_Calc_B_ex(s->srp_ctx.b, s->srp_ctx.N, s->srp_ctx.g,
225
s->srp_ctx.v, sctx->libctx, sctx->propq)) !=
226
NULL) ? SSL_ERROR_NONE : SSL3_AL_FATAL;
227
}
228
229
int SSL_srp_server_param_with_username(SSL *s, int *ad)
230
{
231
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
232
233
if (sc == NULL)
234
return SSL3_AL_FATAL;
235
236
return ssl_srp_server_param_with_username_intern(sc, ad);
237
}
238
239
/*
240
* If the server just has the raw password, make up a verifier entry on the
241
* fly
242
*/
243
int SSL_set_srp_server_param_pw(SSL *s, const char *user, const char *pass,
244
const char *grp)
245
{
246
SRP_gN *GN;
247
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
248
249
if (sc == NULL)
250
return -1;
251
252
GN = SRP_get_default_gN(grp);
253
if (GN == NULL)
254
return -1;
255
sc->srp_ctx.N = BN_dup(GN->N);
256
sc->srp_ctx.g = BN_dup(GN->g);
257
BN_clear_free(sc->srp_ctx.v);
258
sc->srp_ctx.v = NULL;
259
BN_clear_free(sc->srp_ctx.s);
260
sc->srp_ctx.s = NULL;
261
if (!SRP_create_verifier_BN_ex(user, pass, &sc->srp_ctx.s, &sc->srp_ctx.v,
262
sc->srp_ctx.N, sc->srp_ctx.g, s->ctx->libctx,
263
s->ctx->propq))
264
return -1;
265
266
return 1;
267
}
268
269
int SSL_set_srp_server_param(SSL *s, const BIGNUM *N, const BIGNUM *g,
270
BIGNUM *sa, BIGNUM *v, char *info)
271
{
272
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
273
274
if (sc == NULL)
275
return -1;
276
277
if (N != NULL) {
278
if (sc->srp_ctx.N != NULL) {
279
if (!BN_copy(sc->srp_ctx.N, N)) {
280
BN_free(sc->srp_ctx.N);
281
sc->srp_ctx.N = NULL;
282
}
283
} else
284
sc->srp_ctx.N = BN_dup(N);
285
}
286
if (g != NULL) {
287
if (sc->srp_ctx.g != NULL) {
288
if (!BN_copy(sc->srp_ctx.g, g)) {
289
BN_free(sc->srp_ctx.g);
290
sc->srp_ctx.g = NULL;
291
}
292
} else
293
sc->srp_ctx.g = BN_dup(g);
294
}
295
if (sa != NULL) {
296
if (sc->srp_ctx.s != NULL) {
297
if (!BN_copy(sc->srp_ctx.s, sa)) {
298
BN_free(sc->srp_ctx.s);
299
sc->srp_ctx.s = NULL;
300
}
301
} else
302
sc->srp_ctx.s = BN_dup(sa);
303
}
304
if (v != NULL) {
305
if (sc->srp_ctx.v != NULL) {
306
if (!BN_copy(sc->srp_ctx.v, v)) {
307
BN_free(sc->srp_ctx.v);
308
sc->srp_ctx.v = NULL;
309
}
310
} else
311
sc->srp_ctx.v = BN_dup(v);
312
}
313
if (info != NULL) {
314
if (sc->srp_ctx.info)
315
OPENSSL_free(sc->srp_ctx.info);
316
if ((sc->srp_ctx.info = OPENSSL_strdup(info)) == NULL)
317
return -1;
318
}
319
320
if (!(sc->srp_ctx.N) ||
321
!(sc->srp_ctx.g) || !(sc->srp_ctx.s) || !(sc->srp_ctx.v))
322
return -1;
323
324
return 1;
325
}
326
327
int srp_generate_server_master_secret(SSL_CONNECTION *s)
328
{
329
BIGNUM *K = NULL, *u = NULL;
330
int ret = 0, tmp_len = 0;
331
unsigned char *tmp = NULL;
332
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
333
334
if (!SRP_Verify_A_mod_N(s->srp_ctx.A, s->srp_ctx.N))
335
goto err;
336
if ((u = SRP_Calc_u_ex(s->srp_ctx.A, s->srp_ctx.B, s->srp_ctx.N,
337
sctx->libctx, sctx->propq)) == NULL)
338
goto err;
339
if ((K = SRP_Calc_server_key(s->srp_ctx.A, s->srp_ctx.v, u, s->srp_ctx.b,
340
s->srp_ctx.N)) == NULL)
341
goto err;
342
343
tmp_len = BN_num_bytes(K);
344
if ((tmp = OPENSSL_malloc(tmp_len)) == NULL) {
345
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB);
346
goto err;
347
}
348
BN_bn2bin(K, tmp);
349
/* Calls SSLfatal() as required */
350
ret = ssl_generate_master_secret(s, tmp, tmp_len, 1);
351
err:
352
BN_clear_free(K);
353
BN_clear_free(u);
354
return ret;
355
}
356
357
/* client side */
358
int srp_generate_client_master_secret(SSL_CONNECTION *s)
359
{
360
BIGNUM *x = NULL, *u = NULL, *K = NULL;
361
int ret = 0, tmp_len = 0;
362
char *passwd = NULL;
363
unsigned char *tmp = NULL;
364
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
365
366
/*
367
* Checks if b % n == 0
368
*/
369
if (SRP_Verify_B_mod_N(s->srp_ctx.B, s->srp_ctx.N) == 0
370
|| (u = SRP_Calc_u_ex(s->srp_ctx.A, s->srp_ctx.B, s->srp_ctx.N,
371
sctx->libctx, sctx->propq))
372
== NULL
373
|| s->srp_ctx.SRP_give_srp_client_pwd_callback == NULL) {
374
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
375
goto err;
376
}
377
if ((passwd = s->srp_ctx.SRP_give_srp_client_pwd_callback(SSL_CONNECTION_GET_USER_SSL(s),
378
s->srp_ctx.SRP_cb_arg))
379
== NULL) {
380
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_CALLBACK_FAILED);
381
goto err;
382
}
383
if ((x = SRP_Calc_x_ex(s->srp_ctx.s, s->srp_ctx.login, passwd,
384
sctx->libctx, sctx->propq)) == NULL
385
|| (K = SRP_Calc_client_key_ex(s->srp_ctx.N, s->srp_ctx.B,
386
s->srp_ctx.g, x,
387
s->srp_ctx.a, u,
388
sctx->libctx,
389
sctx->propq)) == NULL) {
390
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
391
goto err;
392
}
393
394
tmp_len = BN_num_bytes(K);
395
if ((tmp = OPENSSL_malloc(tmp_len)) == NULL) {
396
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB);
397
goto err;
398
}
399
BN_bn2bin(K, tmp);
400
/* Calls SSLfatal() as required */
401
ret = ssl_generate_master_secret(s, tmp, tmp_len, 1);
402
err:
403
BN_clear_free(K);
404
BN_clear_free(x);
405
if (passwd != NULL)
406
OPENSSL_clear_free(passwd, strlen(passwd));
407
BN_clear_free(u);
408
return ret;
409
}
410
411
int srp_verify_server_param(SSL_CONNECTION *s)
412
{
413
SRP_CTX *srp = &s->srp_ctx;
414
/*
415
* Sanity check parameters: we can quickly check B % N == 0 by checking B
416
* != 0 since B < N
417
*/
418
if (BN_ucmp(srp->g, srp->N) >= 0 || BN_ucmp(srp->B, srp->N) >= 0
419
|| BN_is_zero(srp->B)) {
420
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_DATA);
421
return 0;
422
}
423
424
if (BN_num_bits(srp->N) < srp->strength) {
425
SSLfatal(s, SSL_AD_INSUFFICIENT_SECURITY, SSL_R_INSUFFICIENT_SECURITY);
426
return 0;
427
}
428
429
if (srp->SRP_verify_param_callback) {
430
if (srp->SRP_verify_param_callback(SSL_CONNECTION_GET_USER_SSL(s),
431
srp->SRP_cb_arg) <= 0) {
432
SSLfatal(s, SSL_AD_INSUFFICIENT_SECURITY, SSL_R_CALLBACK_FAILED);
433
return 0;
434
}
435
} else if (!SRP_check_known_gN_param(srp->g, srp->N)) {
436
SSLfatal(s, SSL_AD_INSUFFICIENT_SECURITY,
437
SSL_R_INSUFFICIENT_SECURITY);
438
return 0;
439
}
440
441
return 1;
442
}
443
444
/*
445
* The public API SRP_Calc_A_param() is deprecated so we use
446
* ssl_srp_calc_a_param_intern() internally.
447
*/
448
int ssl_srp_calc_a_param_intern(SSL_CONNECTION *s)
449
{
450
unsigned char rnd[SSL_MAX_MASTER_KEY_LENGTH];
451
452
if (RAND_priv_bytes_ex(SSL_CONNECTION_GET_CTX(s)->libctx,
453
rnd, sizeof(rnd), 0) <= 0)
454
return 0;
455
s->srp_ctx.a = BN_bin2bn(rnd, sizeof(rnd), s->srp_ctx.a);
456
OPENSSL_cleanse(rnd, sizeof(rnd));
457
458
if (!(s->srp_ctx.A = SRP_Calc_A(s->srp_ctx.a, s->srp_ctx.N, s->srp_ctx.g)))
459
return 0;
460
461
return 1;
462
}
463
464
int SRP_Calc_A_param(SSL *s)
465
{
466
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
467
468
if (sc == NULL)
469
return 0;
470
471
return ssl_srp_calc_a_param_intern(sc);
472
}
473
474
BIGNUM *SSL_get_srp_g(SSL *s)
475
{
476
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
477
478
if (sc == NULL)
479
return NULL;
480
481
if (sc->srp_ctx.g != NULL)
482
return sc->srp_ctx.g;
483
return s->ctx->srp_ctx.g;
484
}
485
486
BIGNUM *SSL_get_srp_N(SSL *s)
487
{
488
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
489
490
if (sc == NULL)
491
return NULL;
492
493
if (sc->srp_ctx.N != NULL)
494
return sc->srp_ctx.N;
495
return s->ctx->srp_ctx.N;
496
}
497
498
char *SSL_get_srp_username(SSL *s)
499
{
500
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
501
502
if (sc == NULL)
503
return NULL;
504
505
if (sc->srp_ctx.login != NULL)
506
return sc->srp_ctx.login;
507
return s->ctx->srp_ctx.login;
508
}
509
510
char *SSL_get_srp_userinfo(SSL *s)
511
{
512
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
513
514
if (sc == NULL)
515
return NULL;
516
517
if (sc->srp_ctx.info != NULL)
518
return sc->srp_ctx.info;
519
return s->ctx->srp_ctx.info;
520
}
521
522
# define tls1_ctx_ctrl ssl3_ctx_ctrl
523
# define tls1_ctx_callback_ctrl ssl3_ctx_callback_ctrl
524
525
int SSL_CTX_set_srp_username(SSL_CTX *ctx, char *name)
526
{
527
return tls1_ctx_ctrl(ctx, SSL_CTRL_SET_TLS_EXT_SRP_USERNAME, 0, name);
528
}
529
530
int SSL_CTX_set_srp_password(SSL_CTX *ctx, char *password)
531
{
532
return tls1_ctx_ctrl(ctx, SSL_CTRL_SET_TLS_EXT_SRP_PASSWORD, 0, password);
533
}
534
535
int SSL_CTX_set_srp_strength(SSL_CTX *ctx, int strength)
536
{
537
return tls1_ctx_ctrl(ctx, SSL_CTRL_SET_TLS_EXT_SRP_STRENGTH, strength,
538
NULL);
539
}
540
541
int SSL_CTX_set_srp_verify_param_callback(SSL_CTX *ctx,
542
int (*cb) (SSL *, void *))
543
{
544
return tls1_ctx_callback_ctrl(ctx, SSL_CTRL_SET_SRP_VERIFY_PARAM_CB,
545
(void (*)(void))cb);
546
}
547
548
int SSL_CTX_set_srp_cb_arg(SSL_CTX *ctx, void *arg)
549
{
550
return tls1_ctx_ctrl(ctx, SSL_CTRL_SET_SRP_ARG, 0, arg);
551
}
552
553
int SSL_CTX_set_srp_username_callback(SSL_CTX *ctx,
554
int (*cb) (SSL *, int *, void *))
555
{
556
return tls1_ctx_callback_ctrl(ctx, SSL_CTRL_SET_TLS_EXT_SRP_USERNAME_CB,
557
(void (*)(void))cb);
558
}
559
560
int SSL_CTX_set_srp_client_pwd_callback(SSL_CTX *ctx,
561
char *(*cb) (SSL *, void *))
562
{
563
return tls1_ctx_callback_ctrl(ctx, SSL_CTRL_SET_SRP_GIVE_CLIENT_PWD_CB,
564
(void (*)(void))cb);
565
}
566
567
#endif
568
569