1 /** \file ssl_helpers.h 2 * 3 * \brief This file contains helper functions to set up a TLS connection. 4 */ 5 6 /* 7 * Copyright The Mbed TLS Contributors 8 * SPDX-License-Identifier: Apache-2.0 9 * 10 * Licensed under the Apache License, Version 2.0 (the "License"); you may 11 * not use this file except in compliance with the License. 12 * You may obtain a copy of the License at 13 * 14 * http://www.apache.org/licenses/LICENSE-2.0 15 * 16 * Unless required by applicable law or agreed to in writing, software 17 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 18 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 * See the License for the specific language governing permissions and 20 * limitations under the License. 21 */ 22 23 #ifndef SSL_HELPERS_H 24 #define SSL_HELPERS_H 25 26 #include "mbedtls/build_info.h" 27 28 #include <string.h> 29 30 #include <test/helpers.h> 31 #include <test/macros.h> 32 #include <test/random.h> 33 #include <test/psa_crypto_helpers.h> 34 35 #if defined(MBEDTLS_SSL_TLS_C) 36 #include <ssl_misc.h> 37 #include <mbedtls/timing.h> 38 #include <mbedtls/debug.h> 39 #include "hash_info.h" 40 41 #include "test/certs.h" 42 43 #if defined(MBEDTLS_SSL_CACHE_C) 44 #include "mbedtls/ssl_cache.h" 45 #endif 46 47 #if defined(MBEDTLS_USE_PSA_CRYPTO) 48 #define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \ 49 psa_to_ssl_errors, \ 50 psa_generic_status_to_mbedtls) 51 #endif 52 53 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ 54 defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ 55 defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) 56 #define MBEDTLS_CAN_HANDLE_RSA_TEST_KEY 57 #endif 58 enum { 59 #define MBEDTLS_SSL_TLS1_3_LABEL(name, string) \ 60 tls13_label_ ## name, 61 MBEDTLS_SSL_TLS1_3_LABEL_LIST 62 #undef MBEDTLS_SSL_TLS1_3_LABEL 63 }; 64 65 typedef struct mbedtls_test_ssl_log_pattern { 66 const char *pattern; 67 size_t counter; 68 } mbedtls_test_ssl_log_pattern; 69 70 typedef struct mbedtls_test_handshake_test_options { 71 const char *cipher; 72 mbedtls_ssl_protocol_version client_min_version; 73 mbedtls_ssl_protocol_version client_max_version; 74 mbedtls_ssl_protocol_version server_min_version; 75 mbedtls_ssl_protocol_version server_max_version; 76 mbedtls_ssl_protocol_version expected_negotiated_version; 77 int expected_handshake_result; 78 int expected_ciphersuite; 79 int pk_alg; 80 int opaque_alg; 81 int opaque_alg2; 82 int opaque_usage; 83 data_t *psk_str; 84 int dtls; 85 int srv_auth_mode; 86 int serialize; 87 int mfl; 88 int cli_msg_len; 89 int srv_msg_len; 90 int expected_cli_fragments; 91 int expected_srv_fragments; 92 int renegotiate; 93 int legacy_renegotiation; 94 void *srv_log_obj; 95 void *cli_log_obj; 96 void (*srv_log_fun)(void *, int, const char *, int, const char *); 97 void (*cli_log_fun)(void *, int, const char *, int, const char *); 98 int resize_buffers; 99 #if defined(MBEDTLS_SSL_CACHE_C) 100 mbedtls_ssl_cache_context *cache; 101 #endif 102 } mbedtls_test_handshake_test_options; 103 104 typedef struct mbedtls_test_ssl_buffer { 105 size_t start; 106 size_t content_length; 107 size_t capacity; 108 unsigned char *buffer; 109 } mbedtls_test_ssl_buffer; 110 111 /* 112 * Context for a message metadata queue (fifo) that is on top of the ring buffer. 113 */ 114 typedef struct mbedtls_test_ssl_message_queue { 115 size_t *messages; 116 int pos; 117 int num; 118 int capacity; 119 } mbedtls_test_ssl_message_queue; 120 121 /* 122 * Context for the I/O callbacks simulating network connection. 123 */ 124 125 #define MBEDTLS_MOCK_SOCKET_CONNECTED 1 126 127 typedef struct mbedtls_test_mock_socket { 128 int status; 129 mbedtls_test_ssl_buffer *input; 130 mbedtls_test_ssl_buffer *output; 131 struct mbedtls_test_mock_socket *peer; 132 } mbedtls_test_mock_socket; 133 134 /* Errors used in the message socket mocks */ 135 136 #define MBEDTLS_TEST_ERROR_CONTEXT_ERROR -55 137 #define MBEDTLS_TEST_ERROR_SEND_FAILED -66 138 #define MBEDTLS_TEST_ERROR_RECV_FAILED -77 139 140 /* 141 * Structure used as an addon, or a wrapper, around the mocked sockets. 142 * Contains an input queue, to which the other socket pushes metadata, 143 * and an output queue, to which this one pushes metadata. This context is 144 * considered as an owner of the input queue only, which is initialized and 145 * freed in the respective setup and free calls. 146 */ 147 typedef struct mbedtls_test_message_socket_context { 148 mbedtls_test_ssl_message_queue *queue_input; 149 mbedtls_test_ssl_message_queue *queue_output; 150 mbedtls_test_mock_socket *socket; 151 } mbedtls_test_message_socket_context; 152 153 #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) 154 155 /* 156 * Structure with endpoint's certificates for SSL communication tests. 157 */ 158 typedef struct mbedtls_test_ssl_endpoint_certificate { 159 mbedtls_x509_crt *ca_cert; 160 mbedtls_x509_crt *cert; 161 mbedtls_pk_context *pkey; 162 } mbedtls_test_ssl_endpoint_certificate; 163 164 /* 165 * Endpoint structure for SSL communication tests. 166 */ 167 typedef struct mbedtls_test_ssl_endpoint { 168 const char *name; 169 mbedtls_ssl_context ssl; 170 mbedtls_ssl_config conf; 171 mbedtls_test_mock_socket socket; 172 mbedtls_test_ssl_endpoint_certificate cert; 173 } mbedtls_test_ssl_endpoint; 174 175 #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ 176 177 /* 178 * This function can be passed to mbedtls to receive output logs from it. In 179 * this case, it will count the instances of a mbedtls_test_ssl_log_pattern 180 * in the received logged messages. 181 */ 182 void mbedtls_test_ssl_log_analyzer(void *ctx, int level, 183 const char *file, int line, 184 const char *str); 185 186 void mbedtls_test_init_handshake_options( 187 mbedtls_test_handshake_test_options *opts); 188 189 void mbedtls_test_free_handshake_options( 190 mbedtls_test_handshake_test_options *opts); 191 192 /* 193 * Initialises \p buf. After calling this function it is safe to call 194 * `mbedtls_test_ssl_buffer_free()` on \p buf. 195 */ 196 void mbedtls_test_ssl_buffer_init(mbedtls_test_ssl_buffer *buf); 197 198 /* 199 * Sets up \p buf. After calling this function it is safe to call 200 * `mbedtls_test_ssl_buffer_put()` and `mbedtls_test_ssl_buffer_get()` 201 * on \p buf. 202 */ 203 int mbedtls_test_ssl_buffer_setup(mbedtls_test_ssl_buffer *buf, 204 size_t capacity); 205 206 void mbedtls_test_ssl_buffer_free(mbedtls_test_ssl_buffer *buf); 207 208 /* 209 * Puts \p input_len bytes from the \p input buffer into the ring buffer \p buf. 210 * 211 * \p buf must have been initialized and set up by calling 212 * `mbedtls_test_ssl_buffer_init()` and `mbedtls_test_ssl_buffer_setup()`. 213 * 214 * \retval \p input_len, if the data fits. 215 * \retval 0 <= value < \p input_len, if the data does not fit. 216 * \retval -1, if \p buf is NULL, it hasn't been set up or \p input_len is not 217 * zero and \p input is NULL. 218 */ 219 int mbedtls_test_ssl_buffer_put(mbedtls_test_ssl_buffer *buf, 220 const unsigned char *input, size_t input_len); 221 222 /* 223 * Gets \p output_len bytes from the ring buffer \p buf into the 224 * \p output buffer. The output buffer can be NULL, in this case a part of the 225 * ring buffer will be dropped, if the requested length is available. 226 * 227 * \p buf must have been initialized and set up by calling 228 * `mbedtls_test_ssl_buffer_init()` and `mbedtls_test_ssl_buffer_setup()`. 229 * 230 * \retval \p output_len, if the data is available. 231 * \retval 0 <= value < \p output_len, if the data is not available. 232 * \retval -1, if \buf is NULL or it hasn't been set up. 233 */ 234 int mbedtls_test_ssl_buffer_get(mbedtls_test_ssl_buffer *buf, 235 unsigned char *output, size_t output_len); 236 237 /* 238 * Errors used in the message transport mock tests 239 */ 240 #define MBEDTLS_TEST_ERROR_ARG_NULL -11 241 #define MBEDTLS_TEST_ERROR_MESSAGE_TRUNCATED -44 242 243 /* 244 * Setup and free functions for the message metadata queue. 245 * 246 * \p capacity describes the number of message metadata chunks that can be held 247 * within the queue. 248 * 249 * \retval 0, if a metadata queue of a given length can be allocated. 250 * \retval MBEDTLS_ERR_SSL_ALLOC_FAILED, if allocation failed. 251 */ 252 int mbedtls_test_ssl_message_queue_setup( 253 mbedtls_test_ssl_message_queue *queue, size_t capacity); 254 255 void mbedtls_test_ssl_message_queue_free( 256 mbedtls_test_ssl_message_queue *queue); 257 258 /* 259 * Push message length information onto the message metadata queue. 260 * This will become the last element to leave it (fifo). 261 * 262 * \retval MBEDTLS_TEST_ERROR_ARG_NULL, if the queue is null. 263 * \retval MBEDTLS_ERR_SSL_WANT_WRITE, if the queue is full. 264 * \retval \p len, if the push was successful. 265 */ 266 int mbedtls_test_ssl_message_queue_push_info( 267 mbedtls_test_ssl_message_queue *queue, size_t len); 268 269 /* 270 * Pop information about the next message length from the queue. This will be 271 * the oldest inserted message length(fifo). \p msg_len can be null, in which 272 * case the data will be popped from the queue but not copied anywhere. 273 * 274 * \retval MBEDTLS_TEST_ERROR_ARG_NULL, if the queue is null. 275 * \retval MBEDTLS_ERR_SSL_WANT_READ, if the queue is empty. 276 * \retval message length, if the pop was successful, up to the given 277 \p buf_len. 278 */ 279 int mbedtls_test_ssl_message_queue_pop_info( 280 mbedtls_test_ssl_message_queue *queue, size_t buf_len); 281 282 /* 283 * Setup and teardown functions for mock sockets. 284 */ 285 void mbedtls_mock_socket_init(mbedtls_test_mock_socket *socket); 286 287 /* 288 * Closes the socket \p socket. 289 * 290 * \p socket must have been previously initialized by calling 291 * mbedtls_mock_socket_init(). 292 * 293 * This function frees all allocated resources and both sockets are aware of the 294 * new connection state. 295 * 296 * That is, this function does not simulate half-open TCP connections and the 297 * phenomenon that when closing a UDP connection the peer is not aware of the 298 * connection having been closed. 299 */ 300 void mbedtls_test_mock_socket_close(mbedtls_test_mock_socket *socket); 301 302 /* 303 * Establishes a connection between \p peer1 and \p peer2. 304 * 305 * \p peer1 and \p peer2 must have been previously initialized by calling 306 * mbedtls_mock_socket_init(). 307 * 308 * The capacities of the internal buffers are set to \p bufsize. Setting this to 309 * the correct value allows for simulation of MTU, sanity testing the mock 310 * implementation and mocking TCP connections with lower memory cost. 311 */ 312 int mbedtls_test_mock_socket_connect(mbedtls_test_mock_socket *peer1, 313 mbedtls_test_mock_socket *peer2, 314 size_t bufsize); 315 316 317 /* 318 * Callbacks for simulating blocking I/O over connection-oriented transport. 319 */ 320 int mbedtls_test_mock_tcp_send_b(void *ctx, 321 const unsigned char *buf, size_t len); 322 323 int mbedtls_test_mock_tcp_recv_b(void *ctx, unsigned char *buf, size_t len); 324 325 /* 326 * Callbacks for simulating non-blocking I/O over connection-oriented transport. 327 */ 328 int mbedtls_test_mock_tcp_send_nb(void *ctx, 329 const unsigned char *buf, size_t len); 330 331 int mbedtls_test_mock_tcp_recv_nb(void *ctx, unsigned char *buf, size_t len); 332 333 void mbedtls_test_message_socket_init( 334 mbedtls_test_message_socket_context *ctx); 335 336 /* 337 * Setup a given message socket context including initialization of 338 * input/output queues to a chosen capacity of messages. Also set the 339 * corresponding mock socket. 340 * 341 * \retval 0, if everything succeeds. 342 * \retval MBEDTLS_ERR_SSL_ALLOC_FAILED, if allocation of a message 343 * queue failed. 344 */ 345 int mbedtls_test_message_socket_setup( 346 mbedtls_test_ssl_message_queue *queue_input, 347 mbedtls_test_ssl_message_queue *queue_output, 348 size_t queue_capacity, mbedtls_test_mock_socket *socket, 349 mbedtls_test_message_socket_context *ctx); 350 351 /* 352 * Close a given message socket context, along with the socket itself. Free the 353 * memory allocated by the input queue. 354 */ 355 void mbedtls_test_message_socket_close( 356 mbedtls_test_message_socket_context *ctx); 357 358 /* 359 * Send one message through a given message socket context. 360 * 361 * \retval \p len, if everything succeeds. 362 * \retval MBEDTLS_TEST_ERROR_CONTEXT_ERROR, if any of the needed context 363 * elements or the context itself is null. 364 * \retval MBEDTLS_TEST_ERROR_SEND_FAILED if 365 * mbedtls_test_mock_tcp_send_b failed. 366 * \retval MBEDTLS_ERR_SSL_WANT_WRITE, if the output queue is full. 367 * 368 * This function will also return any error from 369 * mbedtls_test_ssl_message_queue_push_info. 370 */ 371 int mbedtls_test_mock_tcp_send_msg(void *ctx, 372 const unsigned char *buf, size_t len); 373 374 /* 375 * Receive one message from a given message socket context and return message 376 * length or an error. 377 * 378 * \retval message length, if everything succeeds. 379 * \retval MBEDTLS_TEST_ERROR_CONTEXT_ERROR, if any of the needed context 380 * elements or the context itself is null. 381 * \retval MBEDTLS_TEST_ERROR_RECV_FAILED if 382 * mbedtls_test_mock_tcp_recv_b failed. 383 * 384 * This function will also return any error other than 385 * MBEDTLS_TEST_ERROR_MESSAGE_TRUNCATED from 386 * mbedtls_test_message_queue_peek_info. 387 */ 388 int mbedtls_test_mock_tcp_recv_msg(void *ctx, 389 unsigned char *buf, size_t buf_len); 390 391 #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) 392 393 /* 394 * Initializes \p ep_cert structure and assigns it to endpoint 395 * represented by \p ep. 396 * 397 * \retval 0 on success, otherwise error code. 398 */ 399 int mbedtls_test_ssl_endpoint_certificate_init(mbedtls_test_ssl_endpoint *ep, 400 int pk_alg, 401 int opaque_alg, int opaque_alg2, 402 int opaque_usage); 403 404 /* 405 * Initializes \p ep structure. It is important to call 406 * `mbedtls_test_ssl_endpoint_free()` after calling this function 407 * even if it fails. 408 * 409 * \p endpoint_type must be set as MBEDTLS_SSL_IS_SERVER or 410 * MBEDTLS_SSL_IS_CLIENT. 411 * \p pk_alg the algorithm to use, currently only MBEDTLS_PK_RSA and 412 * MBEDTLS_PK_ECDSA are supported. 413 * \p dtls_context - in case of DTLS - this is the context handling metadata. 414 * \p input_queue - used only in case of DTLS. 415 * \p output_queue - used only in case of DTLS. 416 * 417 * \retval 0 on success, otherwise error code. 418 */ 419 int mbedtls_test_ssl_endpoint_init( 420 mbedtls_test_ssl_endpoint *ep, int endpoint_type, 421 mbedtls_test_handshake_test_options *options, 422 mbedtls_test_message_socket_context *dtls_context, 423 mbedtls_test_ssl_message_queue *input_queue, 424 mbedtls_test_ssl_message_queue *output_queue, 425 uint16_t *group_list); 426 427 /* 428 * Deinitializes endpoint represented by \p ep. 429 */ 430 void mbedtls_test_ssl_endpoint_free( 431 mbedtls_test_ssl_endpoint *ep, 432 mbedtls_test_message_socket_context *context); 433 434 /* 435 * This function moves ssl handshake from \p ssl to prescribed \p state. 436 * /p second_ssl is used as second endpoint and their sockets have to be 437 * connected before calling this function. 438 * 439 * \retval 0 on success, otherwise error code. 440 */ 441 int mbedtls_test_move_handshake_to_state(mbedtls_ssl_context *ssl, 442 mbedtls_ssl_context *second_ssl, 443 int state); 444 445 #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ 446 447 /* 448 * Helper function setting up inverse record transformations 449 * using given cipher, hash, EtM mode, authentication tag length, 450 * and version. 451 */ 452 #define CHK(x) \ 453 do \ 454 { \ 455 if (!(x)) \ 456 { \ 457 ret = -1; \ 458 goto cleanup; \ 459 } \ 460 } while (0) 461 462 #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ 463 defined(MBEDTLS_CIPHER_MODE_CBC) && defined(MBEDTLS_AES_C) 464 int mbedtls_test_psa_cipher_encrypt_helper(mbedtls_ssl_transform *transform, 465 const unsigned char *iv, 466 size_t iv_len, 467 const unsigned char *input, 468 size_t ilen, 469 unsigned char *output, 470 size_t *olen); 471 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_CIPHER_MODE_CBC && 472 MBEDTLS_AES_C */ 473 474 int mbedtls_test_ssl_build_transforms(mbedtls_ssl_transform *t_in, 475 mbedtls_ssl_transform *t_out, 476 int cipher_type, int hash_id, 477 int etm, int tag_mode, 478 mbedtls_ssl_protocol_version tls_version, 479 size_t cid0_len, 480 size_t cid1_len); 481 482 /* 483 * Populate a session structure for serialization tests. 484 * Choose dummy values, mostly non-0 to distinguish from the init default. 485 */ 486 int mbedtls_test_ssl_tls12_populate_session(mbedtls_ssl_session *session, 487 int ticket_len, 488 const char *crt_file); 489 490 #if defined(MBEDTLS_SSL_PROTO_TLS1_3) 491 int mbedtls_test_ssl_tls13_populate_session(mbedtls_ssl_session *session, 492 int ticket_len, 493 int endpoint_type); 494 #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */ 495 496 /* 497 * Perform data exchanging between \p ssl_1 and \p ssl_2 and check if the 498 * message was sent in the correct number of fragments. 499 * 500 * /p ssl_1 and /p ssl_2 Endpoints represented by mbedtls_ssl_context. Both 501 * of them must be initialized and connected 502 * beforehand. 503 * /p msg_len_1 and /p msg_len_2 specify the size of the message to send. 504 * /p expected_fragments_1 and /p expected_fragments_2 determine in how many 505 * fragments the message should be sent. 506 * expected_fragments is 0: can be used for DTLS testing while the message 507 * size is larger than MFL. In that case the message 508 * cannot be fragmented and sent to the second 509 * endpoint. 510 * This value can be used for negative tests. 511 * expected_fragments is 1: can be used for TLS/DTLS testing while the 512 * message size is below MFL 513 * expected_fragments > 1: can be used for TLS testing while the message 514 * size is larger than MFL 515 * 516 * \retval 0 on success, otherwise error code. 517 */ 518 int mbedtls_exchange_data(mbedtls_ssl_context *ssl_1, 519 int msg_len_1, const int expected_fragments_1, 520 mbedtls_ssl_context *ssl_2, 521 int msg_len_2, const int expected_fragments_2); 522 523 #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) 524 void mbedtls_test_ssl_perform_handshake( 525 mbedtls_test_handshake_test_options *options); 526 #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */ 527 528 #if defined(MBEDTLS_TEST_HOOKS) 529 /* 530 * Tweak vector lengths in a TLS 1.3 Certificate message 531 * 532 * \param[in] buf Buffer containing the Certificate message to tweak 533 * \param[in]]out] end End of the buffer to parse 534 * \param tweak Tweak identifier (from 1 to the number of tweaks). 535 * \param[out] expected_result Error code expected from the parsing function 536 * \param[out] args Arguments of the MBEDTLS_SSL_CHK_BUF_READ_PTR call that 537 * is expected to fail. All zeroes if no 538 * MBEDTLS_SSL_CHK_BUF_READ_PTR failure is expected. 539 */ 540 int tweak_tls13_certificate_msg_vector_len( 541 unsigned char *buf, unsigned char **end, int tweak, 542 int *expected_result, mbedtls_ssl_chk_buf_ptr_args *args); 543 #endif /* MBEDTLS_TEST_HOOKS */ 544 545 #define ECJPAKE_TEST_PWD "bla" 546 547 #if defined(MBEDTLS_USE_PSA_CRYPTO) 548 #define ECJPAKE_TEST_SET_PASSWORD(exp_ret_val) \ 549 ret = (use_opaque_arg) ? \ 550 mbedtls_ssl_set_hs_ecjpake_password_opaque(&ssl, pwd_slot) : \ 551 mbedtls_ssl_set_hs_ecjpake_password(&ssl, pwd_string, pwd_len); \ 552 TEST_EQUAL(ret, exp_ret_val) 553 #else 554 #define ECJPAKE_TEST_SET_PASSWORD(exp_ret_val) \ 555 ret = mbedtls_ssl_set_hs_ecjpake_password(&ssl, \ 556 pwd_string, pwd_len); \ 557 TEST_EQUAL(ret, exp_ret_val) 558 #endif /* MBEDTLS_USE_PSA_CRYPTO */ 559 560 #define TEST_AVAILABLE_ECC(tls_id_, group_id_, psa_family_, psa_bits_) \ 561 TEST_EQUAL(mbedtls_ssl_get_ecp_group_id_from_tls_id(tls_id_), \ 562 group_id_); \ 563 TEST_EQUAL(mbedtls_ssl_get_tls_id_from_ecp_group_id(group_id_), \ 564 tls_id_); \ 565 TEST_EQUAL(mbedtls_ssl_get_psa_curve_info_from_tls_id(tls_id_, \ 566 &psa_family, &psa_bits), PSA_SUCCESS); \ 567 TEST_EQUAL(psa_family_, psa_family); \ 568 TEST_EQUAL(psa_bits_, psa_bits); 569 570 #define TEST_UNAVAILABLE_ECC(tls_id_, group_id_, psa_family_, psa_bits_) \ 571 TEST_EQUAL(mbedtls_ssl_get_ecp_group_id_from_tls_id(tls_id_), \ 572 MBEDTLS_ECP_DP_NONE); \ 573 TEST_EQUAL(mbedtls_ssl_get_tls_id_from_ecp_group_id(group_id_), \ 574 0); \ 575 TEST_EQUAL(mbedtls_ssl_get_psa_curve_info_from_tls_id(tls_id_, \ 576 &psa_family, &psa_bits), \ 577 PSA_ERROR_NOT_SUPPORTED); 578 579 #endif /* MBEDTLS_SSL_TLS_C */ 580 581 #endif /* SSL_HELPERS_H */ 582