68
68
69
69
#include "../internal.h"
70
70
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 ;
84
95
}
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
95
174
} else {
96
- ret = -1 ;
175
+ ret = ( int ) processed ;
97
176
}
98
177
}
178
+
99
179
return ret ;
100
180
}
101
181
@@ -112,6 +192,7 @@ BIO *BIO_new(const BIO_METHOD *method) {
112
192
ret -> shutdown = 1 ;
113
193
ret -> references = 1 ;
114
194
ret -> callback_ex = NULL ;
195
+ ret -> callback = NULL ;
115
196
CRYPTO_new_ex_data (& ret -> ex_data );
116
197
117
198
if (method -> create != NULL && !method -> create (ret )) {
@@ -135,8 +216,10 @@ int BIO_free(BIO *bio) {
135
216
if (bio -> method != NULL && bio -> method -> destroy != NULL ) {
136
217
bio -> method -> destroy (bio );
137
218
}
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 );
140
223
if (ret <= 0 ) {
141
224
if (ret >= INT_MIN ) {
142
225
return (int )ret ;
@@ -165,7 +248,7 @@ void BIO_free_all(BIO *bio) {
165
248
}
166
249
167
250
int BIO_read (BIO * bio , void * buf , int len ) {
168
- int ret = 0 ;
251
+
169
252
if (bio == NULL || bio -> method == NULL || bio -> method -> bread == NULL ) {
170
253
OPENSSL_PUT_ERROR (BIO , BIO_R_UNSUPPORTED_METHOD );
171
254
return -2 ;
@@ -174,28 +257,24 @@ int BIO_read(BIO *bio, void *buf, int len) {
174
257
return 0 ;
175
258
}
176
259
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 );
179
263
if (callback_ret <= 0 ) {
180
264
if (callback_ret >= INT_MIN ) {
181
265
return (int )callback_ret ;
182
266
}
183
267
return INT_MIN ;
184
268
}
185
269
}
270
+
186
271
if (!bio -> init ) {
187
272
OPENSSL_PUT_ERROR (BIO , BIO_R_UNINITIALIZED );
188
273
return -2 ;
189
274
}
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 );
197
276
198
- return ret ;
277
+ return handle_callback_return ( bio , BIO_CB_READ , buf , len , ret ) ;
199
278
}
200
279
201
280
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) {
228
307
return 0 ;
229
308
}
230
309
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 );
233
313
if (callback_ret <= 0 ) {
234
314
if (callback_ret >= INT_MIN ) {
235
315
return (int )callback_ret ;
236
316
}
237
317
return INT_MIN ;
238
318
}
239
319
}
320
+
240
321
if (!bio -> init ) {
241
322
OPENSSL_PUT_ERROR (BIO , BIO_R_UNINITIALIZED );
242
323
return -2 ;
243
324
}
244
325
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 );
251
328
}
252
329
253
330
int BIO_write (BIO * bio , const void * in , int inl ) {
254
- int ret = 0 ;
331
+
255
332
if (bio == NULL || bio -> method == NULL || bio -> method -> bwrite == NULL ) {
256
333
OPENSSL_PUT_ERROR (BIO , BIO_R_UNSUPPORTED_METHOD );
257
334
return -2 ;
@@ -260,8 +337,9 @@ int BIO_write(BIO *bio, const void *in, int inl) {
260
337
return 0 ;
261
338
}
262
339
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 );
265
343
if (callback_ret <= 0 ) {
266
344
if (callback_ret >= INT_MIN ) {
267
345
return (int )callback_ret ;
@@ -274,15 +352,9 @@ int BIO_write(BIO *bio, const void *in, int inl) {
274
352
OPENSSL_PUT_ERROR (BIO , BIO_R_UNINITIALIZED );
275
353
return -2 ;
276
354
}
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 );
284
356
285
- return ret ;
357
+ return handle_callback_return ( bio , BIO_CB_WRITE , in , inl , ret ) ;
286
358
}
287
359
288
360
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) {
333
405
OPENSSL_PUT_ERROR (BIO , BIO_R_UNSUPPORTED_METHOD );
334
406
return -2 ;
335
407
}
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 );
338
412
if (callback_ret <= 0 ) {
339
413
if (callback_ret >= INT_MIN ) {
340
414
return (int )callback_ret ;
@@ -348,6 +422,7 @@ int BIO_puts(BIO *bio, const char *in) {
348
422
return -2 ;
349
423
}
350
424
int ret = 0 ;
425
+
351
426
if (bio -> method -> bputs != NULL ) {
352
427
ret = bio -> method -> bputs (bio , in );
353
428
} else {
@@ -359,13 +434,8 @@ int BIO_puts(BIO *bio, const char *in) {
359
434
}
360
435
ret = bio -> method -> bwrite (bio , in , len );
361
436
}
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 );
369
439
}
370
440
371
441
int BIO_flush (BIO * bio ) {
@@ -382,18 +452,24 @@ long BIO_ctrl(BIO *bio, int cmd, long larg, void *parg) {
382
452
return -2 ;
383
453
}
384
454
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 );
387
459
if (ret <= 0 ) {
388
460
return ret ;
389
461
}
390
462
}
391
463
464
+
392
465
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 ,
395
470
ret , NULL );
396
471
}
472
+
397
473
return ret ;
398
474
}
399
475
@@ -922,6 +998,10 @@ void BIO_set_callback_ex(BIO *bio, BIO_callback_fn_ex callback) {
922
998
bio -> callback_ex = callback ;
923
999
}
924
1000
1001
+ void BIO_set_callback (BIO * bio , BIO_callback_fn callback ) {
1002
+ bio -> callback = callback ;
1003
+ }
1004
+
925
1005
void BIO_set_callback_arg (BIO * bio , char * arg ) {
926
1006
bio -> cb_arg = arg ;
927
1007
}
0 commit comments