Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/openssl/ssl/tls_srp.c
105671 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 = ctx->srp_ctx.TLS_ext_srp_username_callback;
104
/* set SRP N/g param callback for verification */
105
s->srp_ctx.SRP_verify_param_callback = ctx->srp_ctx.SRP_verify_param_callback;
106
/* set SRP client passwd callback */
107
s->srp_ctx.SRP_give_srp_client_pwd_callback = ctx->srp_ctx.SRP_give_srp_client_pwd_callback;
108
109
s->srp_ctx.strength = ctx->srp_ctx.strength;
110
111
if (((ctx->srp_ctx.N != NULL) && ((s->srp_ctx.N = BN_dup(ctx->srp_ctx.N)) == NULL)) || ((ctx->srp_ctx.g != NULL) && ((s->srp_ctx.g = BN_dup(ctx->srp_ctx.g)) == NULL)) || ((ctx->srp_ctx.s != NULL) && ((s->srp_ctx.s = BN_dup(ctx->srp_ctx.s)) == NULL)) || ((ctx->srp_ctx.B != NULL) && ((s->srp_ctx.B = BN_dup(ctx->srp_ctx.B)) == NULL)) || ((ctx->srp_ctx.A != NULL) && ((s->srp_ctx.A = BN_dup(ctx->srp_ctx.A)) == NULL)) || ((ctx->srp_ctx.a != NULL) && ((s->srp_ctx.a = BN_dup(ctx->srp_ctx.a)) == NULL)) || ((ctx->srp_ctx.v != NULL) && ((s->srp_ctx.v = BN_dup(ctx->srp_ctx.v)) == NULL)) || ((ctx->srp_ctx.b != NULL) && ((s->srp_ctx.b = BN_dup(ctx->srp_ctx.b)) == NULL))) {
112
ERR_raise(ERR_LIB_SSL, ERR_R_BN_LIB);
113
goto err;
114
}
115
if ((ctx->srp_ctx.login != NULL) && ((s->srp_ctx.login = OPENSSL_strdup(ctx->srp_ctx.login)) == NULL)) {
116
ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
117
goto err;
118
}
119
if ((ctx->srp_ctx.info != NULL) && ((s->srp_ctx.info = OPENSSL_strdup(ctx->srp_ctx.info)) == NULL)) {
120
ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
121
goto err;
122
}
123
s->srp_ctx.srp_Mask = ctx->srp_ctx.srp_Mask;
124
125
return 1;
126
err:
127
OPENSSL_free(s->srp_ctx.login);
128
OPENSSL_free(s->srp_ctx.info);
129
BN_free(s->srp_ctx.N);
130
BN_free(s->srp_ctx.g);
131
BN_free(s->srp_ctx.s);
132
BN_free(s->srp_ctx.B);
133
BN_free(s->srp_ctx.A);
134
BN_free(s->srp_ctx.a);
135
BN_free(s->srp_ctx.b);
136
BN_free(s->srp_ctx.v);
137
memset(&s->srp_ctx, 0, sizeof(s->srp_ctx));
138
return 0;
139
}
140
141
int SSL_SRP_CTX_init(SSL *s)
142
{
143
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
144
145
/* the call works with NULL sc */
146
return ssl_srp_ctx_init_intern(sc);
147
}
148
149
/*
150
* The public API SSL_CTX_SRP_CTX_init() is deprecated so we use
151
* ssl_ctx_srp_ctx_init_intern() internally.
152
*/
153
int ssl_ctx_srp_ctx_init_intern(SSL_CTX *ctx)
154
{
155
if (ctx == NULL)
156
return 0;
157
158
memset(&ctx->srp_ctx, 0, sizeof(ctx->srp_ctx));
159
ctx->srp_ctx.strength = SRP_MINIMAL_N;
160
161
return 1;
162
}
163
164
int SSL_CTX_SRP_CTX_init(SSL_CTX *ctx)
165
{
166
return ssl_ctx_srp_ctx_init_intern(ctx);
167
}
168
169
/* server side */
170
/*
171
* The public API SSL_srp_server_param_with_username() is deprecated so we use
172
* ssl_srp_server_param_with_username_intern() internally.
173
*/
174
int ssl_srp_server_param_with_username_intern(SSL_CONNECTION *s, int *ad)
175
{
176
unsigned char b[SSL_MAX_MASTER_KEY_LENGTH];
177
int al;
178
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
179
180
*ad = SSL_AD_UNKNOWN_PSK_IDENTITY;
181
if ((s->srp_ctx.TLS_ext_srp_username_callback != NULL) && ((al = s->srp_ctx.TLS_ext_srp_username_callback(SSL_CONNECTION_GET_USER_SSL(s), ad, s->srp_ctx.SRP_cb_arg)) != SSL_ERROR_NONE))
182
return al;
183
184
*ad = SSL_AD_INTERNAL_ERROR;
185
if ((s->srp_ctx.N == NULL) || (s->srp_ctx.g == NULL) || (s->srp_ctx.s == NULL) || (s->srp_ctx.v == NULL))
186
return SSL3_AL_FATAL;
187
188
if (RAND_priv_bytes_ex(SSL_CONNECTION_GET_CTX(s)->libctx, b, sizeof(b),
189
0)
190
<= 0)
191
return SSL3_AL_FATAL;
192
s->srp_ctx.b = BN_bin2bn(b, sizeof(b), NULL);
193
OPENSSL_cleanse(b, sizeof(b));
194
195
/* Calculate: B = (kv + g^b) % N */
196
197
return ((s->srp_ctx.B = SRP_Calc_B_ex(s->srp_ctx.b, s->srp_ctx.N, s->srp_ctx.g,
198
s->srp_ctx.v, sctx->libctx, sctx->propq))
199
!= NULL)
200
? SSL_ERROR_NONE
201
: SSL3_AL_FATAL;
202
}
203
204
int SSL_srp_server_param_with_username(SSL *s, int *ad)
205
{
206
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
207
208
if (sc == NULL)
209
return SSL3_AL_FATAL;
210
211
return ssl_srp_server_param_with_username_intern(sc, ad);
212
}
213
214
/*
215
* If the server just has the raw password, make up a verifier entry on the
216
* fly
217
*/
218
int SSL_set_srp_server_param_pw(SSL *s, const char *user, const char *pass,
219
const char *grp)
220
{
221
SRP_gN *GN;
222
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
223
224
if (sc == NULL)
225
return -1;
226
227
GN = SRP_get_default_gN(grp);
228
if (GN == NULL)
229
return -1;
230
sc->srp_ctx.N = BN_dup(GN->N);
231
sc->srp_ctx.g = BN_dup(GN->g);
232
BN_clear_free(sc->srp_ctx.v);
233
sc->srp_ctx.v = NULL;
234
BN_clear_free(sc->srp_ctx.s);
235
sc->srp_ctx.s = NULL;
236
if (!SRP_create_verifier_BN_ex(user, pass, &sc->srp_ctx.s, &sc->srp_ctx.v,
237
sc->srp_ctx.N, sc->srp_ctx.g, s->ctx->libctx,
238
s->ctx->propq))
239
return -1;
240
241
return 1;
242
}
243
244
int SSL_set_srp_server_param(SSL *s, const BIGNUM *N, const BIGNUM *g,
245
BIGNUM *sa, BIGNUM *v, char *info)
246
{
247
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
248
249
if (sc == NULL)
250
return -1;
251
252
if (N != NULL) {
253
if (sc->srp_ctx.N != NULL) {
254
if (!BN_copy(sc->srp_ctx.N, N)) {
255
BN_free(sc->srp_ctx.N);
256
sc->srp_ctx.N = NULL;
257
}
258
} else
259
sc->srp_ctx.N = BN_dup(N);
260
}
261
if (g != NULL) {
262
if (sc->srp_ctx.g != NULL) {
263
if (!BN_copy(sc->srp_ctx.g, g)) {
264
BN_free(sc->srp_ctx.g);
265
sc->srp_ctx.g = NULL;
266
}
267
} else
268
sc->srp_ctx.g = BN_dup(g);
269
}
270
if (sa != NULL) {
271
if (sc->srp_ctx.s != NULL) {
272
if (!BN_copy(sc->srp_ctx.s, sa)) {
273
BN_free(sc->srp_ctx.s);
274
sc->srp_ctx.s = NULL;
275
}
276
} else
277
sc->srp_ctx.s = BN_dup(sa);
278
}
279
if (v != NULL) {
280
if (sc->srp_ctx.v != NULL) {
281
if (!BN_copy(sc->srp_ctx.v, v)) {
282
BN_free(sc->srp_ctx.v);
283
sc->srp_ctx.v = NULL;
284
}
285
} else
286
sc->srp_ctx.v = BN_dup(v);
287
}
288
if (info != NULL) {
289
if (sc->srp_ctx.info)
290
OPENSSL_free(sc->srp_ctx.info);
291
if ((sc->srp_ctx.info = OPENSSL_strdup(info)) == NULL)
292
return -1;
293
}
294
295
if (!(sc->srp_ctx.N) || !(sc->srp_ctx.g) || !(sc->srp_ctx.s) || !(sc->srp_ctx.v))
296
return -1;
297
298
return 1;
299
}
300
301
int srp_generate_server_master_secret(SSL_CONNECTION *s)
302
{
303
BIGNUM *K = NULL, *u = NULL;
304
int ret = 0, tmp_len = 0;
305
unsigned char *tmp = NULL;
306
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
307
308
if (!SRP_Verify_A_mod_N(s->srp_ctx.A, s->srp_ctx.N))
309
goto err;
310
if ((u = SRP_Calc_u_ex(s->srp_ctx.A, s->srp_ctx.B, s->srp_ctx.N,
311
sctx->libctx, sctx->propq))
312
== NULL)
313
goto err;
314
if ((K = SRP_Calc_server_key(s->srp_ctx.A, s->srp_ctx.v, u, s->srp_ctx.b,
315
s->srp_ctx.N))
316
== NULL)
317
goto err;
318
319
tmp_len = BN_num_bytes(K);
320
if ((tmp = OPENSSL_malloc(tmp_len)) == NULL) {
321
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB);
322
goto err;
323
}
324
BN_bn2bin(K, tmp);
325
/* Calls SSLfatal() as required */
326
ret = ssl_generate_master_secret(s, tmp, tmp_len, 1);
327
err:
328
BN_clear_free(K);
329
BN_clear_free(u);
330
return ret;
331
}
332
333
/* client side */
334
int srp_generate_client_master_secret(SSL_CONNECTION *s)
335
{
336
BIGNUM *x = NULL, *u = NULL, *K = NULL;
337
int ret = 0, tmp_len = 0;
338
char *passwd = NULL;
339
unsigned char *tmp = NULL;
340
SSL_CTX *sctx = SSL_CONNECTION_GET_CTX(s);
341
342
/*
343
* Checks if b % n == 0
344
*/
345
if (SRP_Verify_B_mod_N(s->srp_ctx.B, s->srp_ctx.N) == 0
346
|| (u = SRP_Calc_u_ex(s->srp_ctx.A, s->srp_ctx.B, s->srp_ctx.N,
347
sctx->libctx, sctx->propq))
348
== NULL
349
|| s->srp_ctx.SRP_give_srp_client_pwd_callback == NULL) {
350
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
351
goto err;
352
}
353
if ((passwd = s->srp_ctx.SRP_give_srp_client_pwd_callback(SSL_CONNECTION_GET_USER_SSL(s),
354
s->srp_ctx.SRP_cb_arg))
355
== NULL) {
356
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_CALLBACK_FAILED);
357
goto err;
358
}
359
if ((x = SRP_Calc_x_ex(s->srp_ctx.s, s->srp_ctx.login, passwd,
360
sctx->libctx, sctx->propq))
361
== NULL
362
|| (K = SRP_Calc_client_key_ex(s->srp_ctx.N, s->srp_ctx.B,
363
s->srp_ctx.g, x,
364
s->srp_ctx.a, u,
365
sctx->libctx,
366
sctx->propq))
367
== NULL) {
368
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
369
goto err;
370
}
371
372
tmp_len = BN_num_bytes(K);
373
if ((tmp = OPENSSL_malloc(tmp_len)) == NULL) {
374
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_CRYPTO_LIB);
375
goto err;
376
}
377
BN_bn2bin(K, tmp);
378
/* Calls SSLfatal() as required */
379
ret = ssl_generate_master_secret(s, tmp, tmp_len, 1);
380
err:
381
BN_clear_free(K);
382
BN_clear_free(x);
383
if (passwd != NULL)
384
OPENSSL_clear_free(passwd, strlen(passwd));
385
BN_clear_free(u);
386
return ret;
387
}
388
389
int srp_verify_server_param(SSL_CONNECTION *s)
390
{
391
SRP_CTX *srp = &s->srp_ctx;
392
/*
393
* Sanity check parameters: we can quickly check B % N == 0 by checking B
394
* != 0 since B < N
395
*/
396
if (BN_ucmp(srp->g, srp->N) >= 0 || BN_ucmp(srp->B, srp->N) >= 0
397
|| BN_is_zero(srp->B)) {
398
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_DATA);
399
return 0;
400
}
401
402
if (BN_num_bits(srp->N) < srp->strength) {
403
SSLfatal(s, SSL_AD_INSUFFICIENT_SECURITY, SSL_R_INSUFFICIENT_SECURITY);
404
return 0;
405
}
406
407
if (srp->SRP_verify_param_callback) {
408
if (srp->SRP_verify_param_callback(SSL_CONNECTION_GET_USER_SSL(s),
409
srp->SRP_cb_arg)
410
<= 0) {
411
SSLfatal(s, SSL_AD_INSUFFICIENT_SECURITY, SSL_R_CALLBACK_FAILED);
412
return 0;
413
}
414
} else if (!SRP_check_known_gN_param(srp->g, srp->N)) {
415
SSLfatal(s, SSL_AD_INSUFFICIENT_SECURITY,
416
SSL_R_INSUFFICIENT_SECURITY);
417
return 0;
418
}
419
420
return 1;
421
}
422
423
/*
424
* The public API SRP_Calc_A_param() is deprecated so we use
425
* ssl_srp_calc_a_param_intern() internally.
426
*/
427
int ssl_srp_calc_a_param_intern(SSL_CONNECTION *s)
428
{
429
unsigned char rnd[SSL_MAX_MASTER_KEY_LENGTH];
430
431
if (RAND_priv_bytes_ex(SSL_CONNECTION_GET_CTX(s)->libctx,
432
rnd, sizeof(rnd), 0)
433
<= 0)
434
return 0;
435
s->srp_ctx.a = BN_bin2bn(rnd, sizeof(rnd), s->srp_ctx.a);
436
OPENSSL_cleanse(rnd, sizeof(rnd));
437
438
if (!(s->srp_ctx.A = SRP_Calc_A(s->srp_ctx.a, s->srp_ctx.N, s->srp_ctx.g)))
439
return 0;
440
441
return 1;
442
}
443
444
int SRP_Calc_A_param(SSL *s)
445
{
446
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
447
448
if (sc == NULL)
449
return 0;
450
451
return ssl_srp_calc_a_param_intern(sc);
452
}
453
454
BIGNUM *SSL_get_srp_g(SSL *s)
455
{
456
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
457
458
if (sc == NULL)
459
return NULL;
460
461
if (sc->srp_ctx.g != NULL)
462
return sc->srp_ctx.g;
463
return s->ctx->srp_ctx.g;
464
}
465
466
BIGNUM *SSL_get_srp_N(SSL *s)
467
{
468
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
469
470
if (sc == NULL)
471
return NULL;
472
473
if (sc->srp_ctx.N != NULL)
474
return sc->srp_ctx.N;
475
return s->ctx->srp_ctx.N;
476
}
477
478
char *SSL_get_srp_username(SSL *s)
479
{
480
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
481
482
if (sc == NULL)
483
return NULL;
484
485
if (sc->srp_ctx.login != NULL)
486
return sc->srp_ctx.login;
487
return s->ctx->srp_ctx.login;
488
}
489
490
char *SSL_get_srp_userinfo(SSL *s)
491
{
492
SSL_CONNECTION *sc = SSL_CONNECTION_FROM_SSL(s);
493
494
if (sc == NULL)
495
return NULL;
496
497
if (sc->srp_ctx.info != NULL)
498
return sc->srp_ctx.info;
499
return s->ctx->srp_ctx.info;
500
}
501
502
#define tls1_ctx_ctrl ssl3_ctx_ctrl
503
#define tls1_ctx_callback_ctrl ssl3_ctx_callback_ctrl
504
505
int SSL_CTX_set_srp_username(SSL_CTX *ctx, char *name)
506
{
507
return tls1_ctx_ctrl(ctx, SSL_CTRL_SET_TLS_EXT_SRP_USERNAME, 0, name);
508
}
509
510
int SSL_CTX_set_srp_password(SSL_CTX *ctx, char *password)
511
{
512
return tls1_ctx_ctrl(ctx, SSL_CTRL_SET_TLS_EXT_SRP_PASSWORD, 0, password);
513
}
514
515
int SSL_CTX_set_srp_strength(SSL_CTX *ctx, int strength)
516
{
517
return tls1_ctx_ctrl(ctx, SSL_CTRL_SET_TLS_EXT_SRP_STRENGTH, strength,
518
NULL);
519
}
520
521
int SSL_CTX_set_srp_verify_param_callback(SSL_CTX *ctx,
522
int (*cb)(SSL *, void *))
523
{
524
return tls1_ctx_callback_ctrl(ctx, SSL_CTRL_SET_SRP_VERIFY_PARAM_CB,
525
(void (*)(void))cb);
526
}
527
528
int SSL_CTX_set_srp_cb_arg(SSL_CTX *ctx, void *arg)
529
{
530
return tls1_ctx_ctrl(ctx, SSL_CTRL_SET_SRP_ARG, 0, arg);
531
}
532
533
int SSL_CTX_set_srp_username_callback(SSL_CTX *ctx,
534
int (*cb)(SSL *, int *, void *))
535
{
536
return tls1_ctx_callback_ctrl(ctx, SSL_CTRL_SET_TLS_EXT_SRP_USERNAME_CB,
537
(void (*)(void))cb);
538
}
539
540
int SSL_CTX_set_srp_client_pwd_callback(SSL_CTX *ctx,
541
char *(*cb)(SSL *, void *))
542
{
543
return tls1_ctx_callback_ctrl(ctx, SSL_CTRL_SET_SRP_GIVE_CLIENT_PWD_CB,
544
(void (*)(void))cb);
545
}
546
547
#endif
548
549