@@ -14,8 +14,8 @@ struct Datagram {
1414
1515static void ssl_info_cb (const SSL * ssl , int where , int ret );
1616static 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 );
1919static void cert_to_payload (UnifexEnv * env , X509 * x509 , UnifexPayload * payload );
2020static void pkey_to_payload (UnifexEnv * env , EVP_PKEY * pkey ,
2121 UnifexPayload * payload );
@@ -245,27 +245,23 @@ UNIFEX_TERM get_cert_fingerprint(UnifexEnv *env, UnifexPayload *cert) {
245245UNIFEX_TERM do_handshake (UnifexEnv * env , State * state ) {
246246 SSL_do_handshake (state -> ssl );
247247
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 );
255251
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 );
263262
264- return res_term ;
265- }
263+ return res_term ;
266264 }
267-
268- return unifex_raise (state -> env , "Handshake failed: no packets generated" );
269265}
270266
271267UNIFEX_TERM write_data (UnifexEnv * env , State * state , UnifexPayload * payload ) {
@@ -290,7 +286,7 @@ UNIFEX_TERM write_data(UnifexEnv *env, State *state, UnifexPayload *payload) {
290286 UnifexPayload * * gen_packets = NULL ;
291287 int gen_packets_size = 0 ;
292288 read_pending_data (& gen_packets , & gen_packets_size , state );
293- if (gen_packets == NULL ) {
289+ if (gen_packets == NULL || gen_packets_size == 0 ) {
294290 DEBUG ("Unable to read data from BIO after writing" );
295291 return unifex_raise (env , "Unable to read data from BIO after writing" );
296292 }
@@ -394,16 +390,12 @@ UNIFEX_TERM handle_handshake_finished(State *state) {
394390 memcpy (server_keying_material .data , keying_material -> server , len );
395391 server_keying_material .size = len ;
396392
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 ;
406397 }
398+
407399 state -> hsk_finished = 1 ;
408400
409401 UnifexPayload * local_keying_material ;
@@ -422,9 +414,7 @@ UNIFEX_TERM handle_handshake_finished(State *state) {
422414 keying_material -> protection_profile , gen_packets , gen_packets_size );
423415
424416cleanup :
425-
426417 free_payload_array (gen_packets , gen_packets_size );
427-
428418 unifex_payload_release (& client_keying_material );
429419 unifex_payload_release (& server_keying_material );
430420 return res_term ;
@@ -435,25 +425,22 @@ UNIFEX_TERM handle_handshake_in_progress(State *state, int ret) {
435425 switch (ssl_error ) {
436426 case SSL_ERROR_WANT_READ :
437427 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 );
440431
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 {
448437 int timeout = get_timeout (state -> ssl );
449438 UNIFEX_TERM res_term = handle_data_result_handshake_packets (
450439 state -> env , gen_packets , gen_packets_size , timeout );
451440
452441 free_payload_array (gen_packets , gen_packets_size );
453442
454443 return res_term ;
455- } else {
456- return handle_data_result_handshake_want_read (state -> env );
457444 }
458445 default :
459446 return handle_read_error (state , ret );
@@ -469,7 +456,7 @@ UNIFEX_TERM handle_timeout(UnifexEnv *env, State *state) {
469456 int gen_packets_size = 0 ;
470457 read_pending_data (& gen_packets , & gen_packets_size , state );
471458
472- if (gen_packets == NULL ) {
459+ if (gen_packets == NULL || gen_packets_size == 0 ) {
473460 return unifex_raise (state -> env ,
474461 "Retransmit handshake failed: write BIO error" );
475462 } else {
@@ -517,21 +504,14 @@ static int verify_cb(int preverify_ok, X509_STORE_CTX *ctx) {
517504}
518505
519506static UnifexPayload * * to_payload_array (struct Datagram * dgram_list , int len ) {
507+ if (len == 0 ) {
508+ return NULL ;
509+ }
520510
521511 UnifexPayload * * payloads = calloc (len , sizeof (UnifexPayload * ));
522512
523- for (int i = 0 ; i < len ; i ++ ) {
524- DEBUG ("%d" , i );
525- payloads [i ] = NULL ;
526- }
527-
528513 struct Datagram * itr = dgram_list ;
529514
530- for (int i = 0 ; i < len ; i ++ ) {
531- itr = itr -> next ;
532- }
533-
534- itr = dgram_list ;
535515 for (int i = 0 ; i < len ; i ++ ) {
536516 payloads [i ] = itr -> packet ;
537517 itr = itr -> next ;
@@ -553,15 +533,16 @@ static UnifexPayload **to_payload_array(struct Datagram *dgram_list, int len) {
553533 return payloads ;
554534}
555535
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 ) {
558538
559539 struct Datagram * dgram_list = NULL ;
560540 struct Datagram * itr = NULL ;
561541 * size = 0 ;
562542
563543 size_t pending_data_len = 0 ;
564544 while ((pending_data_len = BIO_ctrl_pending (SSL_get_wbio (state -> ssl ))) > 0 ) {
545+ DEBUG ("WBIO: pending data: %ld bytes" , pending_data_len );
565546 struct Datagram * dgram = calloc (1 , sizeof (struct Datagram ));
566547 UnifexPayload * payload = calloc (1 , sizeof (UnifexPayload ));
567548 unifex_payload_alloc (state -> env , UNIFEX_PAYLOAD_BINARY , pending_data_len ,
@@ -598,7 +579,7 @@ static void read_pending_data(UnifexPayload ***payloads, int *size,
598579
599580 * size = 0 ;
600581 * payloads = NULL ;
601- return ;
582+ return -1 ;
602583 } else {
603584 DEBUG ("WBIO: read: %d bytes" , read_bytes );
604585 dgram -> packet -> size = (unsigned int )pending_data_len ;
@@ -616,6 +597,7 @@ static void read_pending_data(UnifexPayload ***payloads, int *size,
616597 }
617598
618599 * payloads = to_payload_array (dgram_list , * size );
600+ return 0 ;
619601}
620602
621603static void cert_to_payload (UnifexEnv * env , X509 * x509 ,
@@ -637,6 +619,10 @@ static void pkey_to_payload(UnifexEnv *env, EVP_PKEY *pkey,
637619}
638620
639621static void free_payload_array (UnifexPayload * * payloads , int len ) {
622+ if (payloads == NULL ) {
623+ return ;
624+ }
625+
640626 for (int i = 0 ; i < len ; i ++ ) {
641627 unifex_payload_release (payloads [i ]);
642628 free (payloads [i ]);
0 commit comments