@@ -14,8 +14,8 @@ struct Datagram {
14
14
15
15
static void ssl_info_cb (const SSL * ssl , int where , int ret );
16
16
static int verify_cb (int preverify_ok , X509_STORE_CTX * ctx );
17
- static void read_pending_data (UnifexPayload * * * payloads , int * size ,
18
- State * state );
17
+ static int read_pending_data (UnifexPayload * * * payloads , int * size ,
18
+ State * state );
19
19
static void cert_to_payload (UnifexEnv * env , X509 * x509 , UnifexPayload * payload );
20
20
static void pkey_to_payload (UnifexEnv * env , EVP_PKEY * pkey ,
21
21
UnifexPayload * payload );
@@ -245,27 +245,23 @@ UNIFEX_TERM get_cert_fingerprint(UnifexEnv *env, UnifexPayload *cert) {
245
245
UNIFEX_TERM do_handshake (UnifexEnv * env , State * state ) {
246
246
SSL_do_handshake (state -> ssl );
247
247
248
- size_t pending_data_len = BIO_ctrl_pending (SSL_get_wbio (state -> ssl ));
249
- if (pending_data_len > 0 ) {
250
- DEBUG ("WBIO: pending data: %ld bytes" , pending_data_len );
251
-
252
- UnifexPayload * * gen_packets ;
253
- int gen_packets_size ;
254
- read_pending_data (& gen_packets , & gen_packets_size , state );
248
+ UnifexPayload * * gen_packets ;
249
+ int gen_packets_size ;
250
+ int ret = read_pending_data (& gen_packets , & gen_packets_size , state );
255
251
256
- if (gen_packets == NULL ) {
257
- return unifex_raise (state -> env , "Handshake failed: write BIO error" );
258
- } else {
259
- int timeout = get_timeout (state -> ssl );
260
- UNIFEX_TERM res_term =
261
- do_handshake_result (env , gen_packets , gen_packets_size , timeout );
262
- free_payload_array (gen_packets , gen_packets_size );
252
+ if (ret == 0 && (gen_packets == NULL || gen_packets_size == 0 )) {
253
+ return unifex_raise (state -> env , "Handshake failed: no packets generated" );
254
+ } else if (ret < 0 ) {
255
+ return unifex_raise (state -> env ,
256
+ "Handshake failed: couldn't read pending data" );
257
+ } else {
258
+ int timeout = get_timeout (state -> ssl );
259
+ UNIFEX_TERM res_term =
260
+ do_handshake_result (env , gen_packets , gen_packets_size , timeout );
261
+ free_payload_array (gen_packets , gen_packets_size );
263
262
264
- return res_term ;
265
- }
263
+ return res_term ;
266
264
}
267
-
268
- return unifex_raise (state -> env , "Handshake failed: no packets generated" );
269
265
}
270
266
271
267
UNIFEX_TERM write_data (UnifexEnv * env , State * state , UnifexPayload * payload ) {
@@ -290,7 +286,7 @@ UNIFEX_TERM write_data(UnifexEnv *env, State *state, UnifexPayload *payload) {
290
286
UnifexPayload * * gen_packets = NULL ;
291
287
int gen_packets_size = 0 ;
292
288
read_pending_data (& gen_packets , & gen_packets_size , state );
293
- if (gen_packets == NULL ) {
289
+ if (gen_packets == NULL || gen_packets_size == 0 ) {
294
290
DEBUG ("Unable to read data from BIO after writing" );
295
291
return unifex_raise (env , "Unable to read data from BIO after writing" );
296
292
}
@@ -394,16 +390,12 @@ UNIFEX_TERM handle_handshake_finished(State *state) {
394
390
memcpy (server_keying_material .data , keying_material -> server , len );
395
391
server_keying_material .size = len ;
396
392
397
- size_t pending_data_len = BIO_ctrl_pending (SSL_get_wbio (state -> ssl ));
398
- DEBUG ("WBIO: pending data: %ld bytes" , pending_data_len );
399
-
400
- if (pending_data_len > 0 ) {
401
- read_pending_data (& gen_packets , & gen_packets_size , state );
402
- if (gen_packets == NULL ) {
403
- res_term = unifex_raise (state -> env , "Handshake failed: write BIO error" );
404
- goto cleanup ;
405
- }
393
+ int ret = read_pending_data (& gen_packets , & gen_packets_size , state );
394
+ if (ret < 0 ) {
395
+ res_term = unifex_raise (state -> env , "Handshake failed: write BIO error" );
396
+ goto cleanup ;
406
397
}
398
+
407
399
state -> hsk_finished = 1 ;
408
400
409
401
UnifexPayload * local_keying_material ;
@@ -422,9 +414,7 @@ UNIFEX_TERM handle_handshake_finished(State *state) {
422
414
keying_material -> protection_profile , gen_packets , gen_packets_size );
423
415
424
416
cleanup :
425
-
426
417
free_payload_array (gen_packets , gen_packets_size );
427
-
428
418
unifex_payload_release (& client_keying_material );
429
419
unifex_payload_release (& server_keying_material );
430
420
return res_term ;
@@ -435,25 +425,22 @@ UNIFEX_TERM handle_handshake_in_progress(State *state, int ret) {
435
425
switch (ssl_error ) {
436
426
case SSL_ERROR_WANT_READ :
437
427
DEBUG ("SSL WANT READ" );
438
- size_t pending_data_len = BIO_ctrl_pending (SSL_get_wbio (state -> ssl ));
439
- DEBUG ("WBIO: pending data: %ld bytes" , pending_data_len );
428
+ UnifexPayload * * gen_packets = NULL ;
429
+ int gen_packets_size = 0 ;
430
+ int read_err = read_pending_data (& gen_packets , & gen_packets_size , state );
440
431
441
- if (pending_data_len > 0 ) {
442
- UnifexPayload * * gen_packets = NULL ;
443
- int gen_packets_size = 0 ;
444
- read_pending_data (& gen_packets , & gen_packets_size , state );
445
- if (gen_packets == NULL ) {
446
- return unifex_raise (state -> env , "Handshake failed: write BIO error" );
447
- }
432
+ if (read_err < 0 ) {
433
+ return unifex_raise (state -> env , "Handshake failed: write BIO error" );
434
+ } else if (read_err == 0 && gen_packets_size == 0 ) {
435
+ return handle_data_result_handshake_want_read (state -> env );
436
+ } else {
448
437
int timeout = get_timeout (state -> ssl );
449
438
UNIFEX_TERM res_term = handle_data_result_handshake_packets (
450
439
state -> env , gen_packets , gen_packets_size , timeout );
451
440
452
441
free_payload_array (gen_packets , gen_packets_size );
453
442
454
443
return res_term ;
455
- } else {
456
- return handle_data_result_handshake_want_read (state -> env );
457
444
}
458
445
default :
459
446
return handle_read_error (state , ret );
@@ -469,7 +456,7 @@ UNIFEX_TERM handle_timeout(UnifexEnv *env, State *state) {
469
456
int gen_packets_size = 0 ;
470
457
read_pending_data (& gen_packets , & gen_packets_size , state );
471
458
472
- if (gen_packets == NULL ) {
459
+ if (gen_packets == NULL || gen_packets_size == 0 ) {
473
460
return unifex_raise (state -> env ,
474
461
"Retransmit handshake failed: write BIO error" );
475
462
} else {
@@ -517,21 +504,14 @@ static int verify_cb(int preverify_ok, X509_STORE_CTX *ctx) {
517
504
}
518
505
519
506
static UnifexPayload * * to_payload_array (struct Datagram * dgram_list , int len ) {
507
+ if (len == 0 ) {
508
+ return NULL ;
509
+ }
520
510
521
511
UnifexPayload * * payloads = calloc (len , sizeof (UnifexPayload * ));
522
512
523
- for (int i = 0 ; i < len ; i ++ ) {
524
- DEBUG ("%d" , i );
525
- payloads [i ] = NULL ;
526
- }
527
-
528
513
struct Datagram * itr = dgram_list ;
529
514
530
- for (int i = 0 ; i < len ; i ++ ) {
531
- itr = itr -> next ;
532
- }
533
-
534
- itr = dgram_list ;
535
515
for (int i = 0 ; i < len ; i ++ ) {
536
516
payloads [i ] = itr -> packet ;
537
517
itr = itr -> next ;
@@ -553,15 +533,16 @@ static UnifexPayload **to_payload_array(struct Datagram *dgram_list, int len) {
553
533
return payloads ;
554
534
}
555
535
556
- static void read_pending_data (UnifexPayload * * * payloads , int * size ,
557
- State * state ) {
536
+ static int read_pending_data (UnifexPayload * * * payloads , int * size ,
537
+ State * state ) {
558
538
559
539
struct Datagram * dgram_list = NULL ;
560
540
struct Datagram * itr = NULL ;
561
541
* size = 0 ;
562
542
563
543
size_t pending_data_len = 0 ;
564
544
while ((pending_data_len = BIO_ctrl_pending (SSL_get_wbio (state -> ssl ))) > 0 ) {
545
+ DEBUG ("WBIO: pending data: %ld bytes" , pending_data_len );
565
546
struct Datagram * dgram = calloc (1 , sizeof (struct Datagram ));
566
547
UnifexPayload * payload = calloc (1 , sizeof (UnifexPayload ));
567
548
unifex_payload_alloc (state -> env , UNIFEX_PAYLOAD_BINARY , pending_data_len ,
@@ -598,7 +579,7 @@ static void read_pending_data(UnifexPayload ***payloads, int *size,
598
579
599
580
* size = 0 ;
600
581
* payloads = NULL ;
601
- return ;
582
+ return -1 ;
602
583
} else {
603
584
DEBUG ("WBIO: read: %d bytes" , read_bytes );
604
585
dgram -> packet -> size = (unsigned int )pending_data_len ;
@@ -616,6 +597,7 @@ static void read_pending_data(UnifexPayload ***payloads, int *size,
616
597
}
617
598
618
599
* payloads = to_payload_array (dgram_list , * size );
600
+ return 0 ;
619
601
}
620
602
621
603
static void cert_to_payload (UnifexEnv * env , X509 * x509 ,
@@ -637,6 +619,10 @@ static void pkey_to_payload(UnifexEnv *env, EVP_PKEY *pkey,
637
619
}
638
620
639
621
static void free_payload_array (UnifexPayload * * payloads , int len ) {
622
+ if (payloads == NULL ) {
623
+ return ;
624
+ }
625
+
640
626
for (int i = 0 ; i < len ; i ++ ) {
641
627
unifex_payload_release (payloads [i ]);
642
628
free (payloads [i ]);
0 commit comments