Skip to content

Commit 38991b5

Browse files
authored
Merge branch 'main' into mldsa_type_fix
2 parents 298b0cf + 54453b4 commit 38991b5

File tree

3 files changed

+359
-110
lines changed

3 files changed

+359
-110
lines changed

crypto/bio/bio.c

Lines changed: 149 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -68,34 +68,114 @@
6868

6969
#include "../internal.h"
7070

71-
#define HAS_CALLBACK(b) ((b)->callback_ex != NULL)
72-
73-
// Helper function to create a placeholder |processed| that the callback can
74-
// modify and return to the caller. Used only in callbacks that pass in
75-
// |processed|.
76-
static int call_bio_callback_with_processed(BIO *bio, const int oper,
77-
const void *buf, int len, int ret) {
78-
if (HAS_CALLBACK(bio)) {
79-
size_t processed = 0;
80-
// The original BIO return value can be an error value (less than 0) or
81-
// the number of bytes read/written
82-
if (ret > 0) {
83-
processed = ret;
71+
// |callback_fn_wrap_ex| adapts the legacy callback interface |BIO_callback_fn| to the
72+
// extended callback interface |BIO_callback_fn_ex|. This function should only be
73+
// called when |callback_ex| is not available and the legacy callback is set.
74+
//
75+
// The extended interface parameters |len| and |processed| are mapped to the legacy
76+
// interface parameters |argi| and |bio_ret| respectively.
77+
//
78+
// Returns -1 on NULL |BIO| or callback, otherwise returns the result of the legacy
79+
// callback.
80+
static long callback_fn_wrap_ex(BIO *bio, int oper, const char *argp,
81+
size_t len, int argi, long argl, int bio_ret,
82+
size_t *processed) {
83+
assert(bio != NULL);
84+
assert(bio->callback != NULL);
85+
assert(bio->callback_ex == NULL);
86+
87+
/* Strip off any BIO_CB_RETURN flag */
88+
int bareoper = oper & ~BIO_CB_RETURN;
89+
90+
if (bareoper == BIO_CB_READ || bareoper == BIO_CB_WRITE
91+
|| bareoper == BIO_CB_GETS) {
92+
/* In this case |len| is set, and should be used instead of |argi| */
93+
if (len > INT_MAX) {
94+
return -1;
8495
}
85-
// Pass the original BIO's return value to the callback. If the callback
86-
// is successful return processed from the callback, if the callback is
87-
// not successful return the callback's return value.
88-
long callback_ret = bio->callback_ex(bio, oper, buf, len, 0, 0L, ret, &processed);
89-
if (callback_ret <= INT_MAX && callback_ret >= INT_MIN) {
90-
ret = (int)callback_ret;
91-
if (ret > 0) {
92-
// BIO will only read int |len| bytes so this is a safe cast
93-
ret = (int)processed;
94-
}
96+
97+
argi = (int)len;
98+
}
99+
100+
if (bio_ret > 0 && (oper & BIO_CB_RETURN) && bareoper != BIO_CB_CTRL) {
101+
if (*processed > INT_MAX) {
102+
return -1;
103+
}
104+
105+
bio_ret = *processed;
106+
}
107+
108+
109+
long ret = bio->callback(bio, oper, argp, argi, argl, bio_ret);
110+
111+
if (ret > 0 && (oper & BIO_CB_RETURN) && bareoper != BIO_CB_CTRL) {
112+
*processed = (size_t)ret;
113+
ret = 1;
114+
}
115+
116+
return ret;
117+
}
118+
119+
// |get_callback| returns the appropriate callback function for a given |BIO|, preferring
120+
// the extended interface |callback_ex| over the legacy interface.
121+
//
122+
// When only the legacy callback is available, it is wrapped in the extended format
123+
// via |callback_fn_wrap_ex| to provide a consistent interface. The extended callback
124+
// provides additional parameters for length and bytes processed tracking.
125+
//
126+
// Returns the |callback_ex| function if available, a wrapped legacy callback if only
127+
// |callback| is set, or NULL if no callbacks are set.
128+
static BIO_callback_fn_ex get_callback(BIO *bio) {
129+
assert(bio != NULL);
130+
131+
if (bio->callback_ex != NULL) {
132+
return bio->callback_ex;
133+
}
134+
if (bio->callback != NULL) {
135+
// Wrap old-style callback in extended format
136+
return callback_fn_wrap_ex;
137+
}
138+
return NULL;
139+
}
140+
141+
// Helper function to handle return values from |BIO_read|, |BIO_write|,
142+
// |BIO_gets|, and |BIO_puts| operations.
143+
static int handle_callback_return(BIO *bio, int oper, const void *buf,
144+
int len, int ret) {
145+
146+
size_t processed = 0;
147+
148+
if (ret > 0) {
149+
if (oper == BIO_CB_READ || oper == BIO_CB_GETS) {
150+
bio->num_read += ret;
151+
} else if (oper == BIO_CB_WRITE || oper == BIO_CB_PUTS) {
152+
bio->num_write += ret;
153+
}
154+
// |callback_ex| receives the number of bytes processed via the |processed| parameter,
155+
// while the legacy callback receives this information through both |argi| and |ret|.
156+
// When using the legacy callback, the |processed| value will be mapped back to |ret|.
157+
processed = ret;
158+
ret = 1;
159+
}
160+
161+
BIO_callback_fn_ex cb = get_callback(bio);
162+
if (cb != NULL) {
163+
long callback_ret = cb(bio, oper | BIO_CB_RETURN, buf, len, 0, 0L, ret, &processed);
164+
if (callback_ret > INT_MAX || callback_ret < INT_MIN) {
165+
return -1;
166+
}
167+
ret = (int)callback_ret;
168+
}
169+
170+
171+
if (ret > 0) {
172+
if (processed > INT_MAX) {
173+
ret = -1; // Value too large to represent as int
95174
} else {
96-
ret = -1;
175+
ret = (int)processed;
97176
}
98177
}
178+
99179
return ret;
100180
}
101181

@@ -112,6 +192,7 @@ BIO *BIO_new(const BIO_METHOD *method) {
112192
ret->shutdown = 1;
113193
ret->references = 1;
114194
ret->callback_ex = NULL;
195+
ret->callback = NULL;
115196
CRYPTO_new_ex_data(&ret->ex_data);
116197

117198
if (method->create != NULL && !method->create(ret)) {
@@ -135,8 +216,10 @@ int BIO_free(BIO *bio) {
135216
if (bio->method != NULL && bio->method->destroy != NULL) {
136217
bio->method->destroy(bio);
137218
}
138-
if (HAS_CALLBACK(bio)) {
139-
long ret = bio->callback_ex(bio, BIO_CB_FREE, NULL, 0, 0, 0L, 1L, NULL);
219+
220+
BIO_callback_fn_ex cb = get_callback(bio);
221+
if (cb != NULL) {
222+
long ret = cb(bio, BIO_CB_FREE, NULL, 0, 0, 0L, 1L, NULL);
140223
if (ret <= 0) {
141224
if (ret >= INT_MIN) {
142225
return (int)ret;
@@ -165,7 +248,7 @@ void BIO_free_all(BIO *bio) {
165248
}
166249

167250
int BIO_read(BIO *bio, void *buf, int len) {
168-
int ret = 0;
251+
169252
if (bio == NULL || bio->method == NULL || bio->method->bread == NULL) {
170253
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
171254
return -2;
@@ -174,28 +257,24 @@ int BIO_read(BIO *bio, void *buf, int len) {
174257
return 0;
175258
}
176259

177-
if (HAS_CALLBACK(bio)) {
178-
long callback_ret = bio->callback_ex(bio, BIO_CB_READ, buf, len, 0, 0L, 1L, NULL);
260+
BIO_callback_fn_ex cb = get_callback(bio);
261+
if (cb != NULL) {
262+
long callback_ret = cb(bio, BIO_CB_READ, buf, len, 0, 0L, 1L, NULL);
179263
if (callback_ret <= 0) {
180264
if (callback_ret >= INT_MIN) {
181265
return (int)callback_ret;
182266
}
183267
return INT_MIN;
184268
}
185269
}
270+
186271
if (!bio->init) {
187272
OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
188273
return -2;
189274
}
190-
ret = bio->method->bread(bio, buf, len);
191-
if (ret > 0) {
192-
bio->num_read += ret;
193-
}
194-
195-
ret = call_bio_callback_with_processed(bio, BIO_CB_READ | BIO_CB_RETURN, buf,
196-
len, ret);
275+
int ret = bio->method->bread(bio, buf, len);
197276

198-
return ret;
277+
return handle_callback_return(bio, BIO_CB_READ, buf, len, ret);
199278
}
200279

201280
int BIO_read_ex(BIO *bio, void *data, size_t data_len, size_t *read_bytes) {
@@ -228,30 +307,28 @@ int BIO_gets(BIO *bio, char *buf, int len) {
228307
return 0;
229308
}
230309

231-
if (HAS_CALLBACK(bio)) {
232-
long callback_ret = bio->callback_ex(bio, BIO_CB_GETS, buf, len, 0, 0L, 1L, NULL);
310+
BIO_callback_fn_ex cb = get_callback(bio);
311+
if (cb != NULL) {
312+
long callback_ret = cb(bio, BIO_CB_GETS, buf, len, 0, 0L, 1L, NULL);
233313
if (callback_ret <= 0) {
234314
if (callback_ret >= INT_MIN) {
235315
return (int)callback_ret;
236316
}
237317
return INT_MIN;
238318
}
239319
}
320+
240321
if (!bio->init) {
241322
OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
242323
return -2;
243324
}
244325
int ret = bio->method->bgets(bio, buf, len);
245-
if (ret > 0) {
246-
bio->num_read += ret;
247-
}
248-
ret = call_bio_callback_with_processed(bio, BIO_CB_GETS | BIO_CB_RETURN, buf,
249-
len, ret);
250-
return ret;
326+
327+
return handle_callback_return(bio, BIO_CB_GETS, buf, len, ret);
251328
}
252329

253330
int BIO_write(BIO *bio, const void *in, int inl) {
254-
int ret = 0;
331+
255332
if (bio == NULL || bio->method == NULL || bio->method->bwrite == NULL) {
256333
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
257334
return -2;
@@ -260,8 +337,9 @@ int BIO_write(BIO *bio, const void *in, int inl) {
260337
return 0;
261338
}
262339

263-
if (HAS_CALLBACK(bio)) {
264-
long callback_ret = bio->callback_ex(bio, BIO_CB_WRITE, in, inl, 0, 0L, 1L, NULL);
340+
BIO_callback_fn_ex cb = get_callback(bio);
341+
if (cb != NULL) {
342+
long callback_ret = cb(bio, BIO_CB_WRITE, in, inl, 0, 0L, 1L, NULL);
265343
if (callback_ret <= 0) {
266344
if (callback_ret >= INT_MIN) {
267345
return (int)callback_ret;
@@ -274,15 +352,9 @@ int BIO_write(BIO *bio, const void *in, int inl) {
274352
OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
275353
return -2;
276354
}
277-
ret = bio->method->bwrite(bio, in, inl);
278-
if (ret > 0) {
279-
bio->num_write += ret;
280-
}
281-
282-
ret = call_bio_callback_with_processed(bio, BIO_CB_WRITE | BIO_CB_RETURN, in,
283-
inl, ret);
355+
int ret = bio->method->bwrite(bio, in, inl);
284356

285-
return ret;
357+
return handle_callback_return(bio, BIO_CB_WRITE, in, inl, ret);
286358
}
287359

288360
int BIO_write_ex(BIO *bio, const void *data, size_t data_len, size_t *written_bytes) {
@@ -333,8 +405,10 @@ int BIO_puts(BIO *bio, const char *in) {
333405
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
334406
return -2;
335407
}
336-
if(HAS_CALLBACK(bio)) {
337-
long callback_ret = bio->callback_ex(bio, BIO_CB_PUTS, in, 0, 0, 0L, 1L, NULL);
408+
409+
BIO_callback_fn_ex cb = get_callback(bio);
410+
if (cb != NULL) {
411+
long callback_ret = cb(bio, BIO_CB_PUTS, in, 0, 0, 0L, 1L, NULL);
338412
if (callback_ret <= 0) {
339413
if (callback_ret >= INT_MIN) {
340414
return (int)callback_ret;
@@ -348,6 +422,7 @@ int BIO_puts(BIO *bio, const char *in) {
348422
return -2;
349423
}
350424
int ret = 0;
425+
351426
if (bio->method->bputs != NULL) {
352427
ret = bio->method->bputs(bio, in);
353428
} else {
@@ -359,13 +434,8 @@ int BIO_puts(BIO *bio, const char *in) {
359434
}
360435
ret = bio->method->bwrite(bio, in, len);
361436
}
362-
if (ret > 0) {
363-
bio->num_write += ret;
364-
}
365-
ret = call_bio_callback_with_processed(bio, BIO_CB_PUTS | BIO_CB_RETURN,
366-
in, 0, ret);
367-
368-
return ret;
437+
438+
return handle_callback_return(bio, BIO_CB_PUTS, in, 0, ret);
369439
}
370440

371441
int BIO_flush(BIO *bio) {
@@ -382,18 +452,24 @@ long BIO_ctrl(BIO *bio, int cmd, long larg, void *parg) {
382452
return -2;
383453
}
384454
long ret = 0;
385-
if (HAS_CALLBACK(bio)) {
386-
ret = bio->callback_ex(bio, BIO_CB_CTRL, parg, 0, cmd, larg, 1L, NULL);
455+
456+
BIO_callback_fn_ex cb = get_callback(bio);
457+
if (cb != NULL) {
458+
ret = cb(bio, BIO_CB_CTRL, parg, 0, cmd, larg, 1L, NULL);
387459
if (ret <= 0) {
388460
return ret;
389461
}
390462
}
391463

464+
392465
ret = bio->method->ctrl(bio, cmd, larg, parg);
393-
if (HAS_CALLBACK(bio)) {
394-
ret = bio->callback_ex(bio, BIO_CB_CTRL | BIO_CB_RETURN, parg, 0, cmd, larg,
466+
467+
cb = get_callback(bio);
468+
if (cb != NULL) {
469+
ret = cb(bio, BIO_CB_CTRL | BIO_CB_RETURN, parg, 0, cmd, larg,
395470
ret, NULL);
396471
}
472+
397473
return ret;
398474
}
399475

@@ -922,6 +998,10 @@ void BIO_set_callback_ex(BIO *bio, BIO_callback_fn_ex callback) {
922998
bio->callback_ex = callback;
923999
}
9241000

1001+
void BIO_set_callback(BIO *bio, BIO_callback_fn callback) {
1002+
bio->callback = callback;
1003+
}
1004+
9251005
void BIO_set_callback_arg(BIO *bio, char *arg) {
9261006
bio->cb_arg = arg;
9271007
}

0 commit comments

Comments
 (0)