LCOV - code coverage report
Current view: top level - stuffer - s2n_stuffer.h (source / functions) Hit Total Coverage
Test: unit_test_coverage.info Lines: 5 5 100.0 %
Date: 2025-08-15 07:28:39 Functions: 0 0 -
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
       3                 :            :  *
       4                 :            :  * Licensed under the Apache License, Version 2.0 (the "License").
       5                 :            :  * You may not use this file except in compliance with the License.
       6                 :            :  * A copy of the License is located at
       7                 :            :  *
       8                 :            :  *  http://aws.amazon.com/apache2.0
       9                 :            :  *
      10                 :            :  * or in the "license" file accompanying this file. This file is distributed
      11                 :            :  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
      12                 :            :  * express or implied. See the License for the specific language governing
      13                 :            :  * permissions and limitations under the License.
      14                 :            :  */
      15                 :            : 
      16                 :            : #pragma once
      17                 :            : 
      18                 :            : #include <limits.h>
      19                 :            : #include <stdarg.h>
      20                 :            : #include <stdint.h>
      21                 :            : #include <stdlib.h>
      22                 :            : #include <sys/uio.h>
      23                 :            : 
      24                 :            : #include "utils/s2n_blob.h"
      25                 :            : #include "utils/s2n_result.h"
      26                 :            : 
      27                 :            : #define S2N_MIN_STUFFER_GROWTH_IN_BYTES 1024
      28                 :            : 
      29                 :            : /* Using a non-zero value
      30                 :            :  * (a) makes wiped data easy to see in the debugger
      31                 :            :  * (b) makes use of wiped data obvious since this is unlikely to be a valid bit pattern
      32                 :            :  */
      33                 :            : #define S2N_WIPE_PATTERN 'w'
      34                 :            : 
      35                 :            : #define SIZEOF_IN_BITS(t) (sizeof(t) * CHAR_BIT)
      36                 :            : 
      37                 :     109730 : #define SIZEOF_UINT24 3
      38                 :            : 
      39                 :            : struct s2n_stuffer {
      40                 :            :     /* The data for the s2n_stuffer */
      41                 :            :     struct s2n_blob blob;
      42                 :            : 
      43                 :            :     /* Cursors to the current read/write position in the s2n_stuffer */
      44                 :            :     uint32_t read_cursor;
      45                 :            :     uint32_t write_cursor;
      46                 :            :     uint32_t high_water_mark;
      47                 :            : 
      48                 :            :     /* Was this stuffer alloc()'d?
      49                 :            :      * This field controls whether the stuffer "owns" the blob. If the stuffer
      50                 :            :      * was allocated, then `blob` must be freed when the stuffer is freed. If the
      51                 :            :      * stuffer was not allocated, then the blob must not be freed by the stuffer, even if the 
      52                 :            :      * blob itself is allocated. */
      53                 :            :     unsigned int alloced : 1;
      54                 :            : 
      55                 :            :     /* Is this stuffer growable? */
      56                 :            :     unsigned int growable : 1;
      57                 :            : 
      58                 :            :     /* Can this stuffer be safely resized?
      59                 :            :      * A growable stuffer can be temporarily tainted by a raw read/write,
      60                 :            :      * preventing it from resizing. */
      61                 :            :     unsigned int tainted : 1;
      62                 :            : };
      63                 :            : 
      64                 :   14061736 : #define s2n_stuffer_data_available(s)  ((s)->write_cursor - (s)->read_cursor)
      65                 :   83378777 : #define s2n_stuffer_space_remaining(s) ((s)->blob.size - (s)->write_cursor)
      66                 :   41544258 : #define s2n_stuffer_is_wiped(s)        ((s)->high_water_mark == 0)
      67                 :    3828955 : #define s2n_stuffer_is_freed(s)        ((s)->blob.data == NULL)
      68                 :            : /* Check basic validity constraints on the stuffer: e.g. that cursors point within the blob */
      69                 :            : S2N_RESULT s2n_stuffer_validate(const struct s2n_stuffer *stuffer);
      70                 :            : 
      71                 :            : /* Initialize and destroying stuffers */
      72                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_init(struct s2n_stuffer *stuffer, struct s2n_blob *in);
      73                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_init_written(struct s2n_stuffer *stuffer, struct s2n_blob *in);
      74                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_alloc(struct s2n_stuffer *stuffer, const uint32_t size);
      75                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_growable_alloc(struct s2n_stuffer *stuffer, const uint32_t size);
      76                 :            : int s2n_stuffer_free(struct s2n_stuffer *stuffer);
      77                 :            : /**
      78                 :            :  * Frees the stuffer without zeroizing the contained data.
      79                 :            :  *
      80                 :            :  * This should only be used in scenarios where the data is encrypted or has been
      81                 :            :  * cleared with `s2n_stuffer_erase_and_read`. In most cases, prefer `s2n_stuffer_free`.
      82                 :            :  */
      83                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_free_without_wipe(struct s2n_stuffer *stuffer);
      84                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_resize(struct s2n_stuffer *stuffer, const uint32_t size);
      85                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_resize_if_empty(struct s2n_stuffer *stuffer, const uint32_t size);
      86                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_rewind_read(struct s2n_stuffer *stuffer, const uint32_t size);
      87                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_reread(struct s2n_stuffer *stuffer);
      88                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_rewrite(struct s2n_stuffer *stuffer);
      89                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_shift(struct s2n_stuffer *stuffer);
      90                 :            : int s2n_stuffer_wipe(struct s2n_stuffer *stuffer);
      91                 :            : int s2n_stuffer_wipe_n(struct s2n_stuffer *stuffer, const uint32_t n);
      92                 :            : bool s2n_stuffer_is_consumed(struct s2n_stuffer *stuffer);
      93                 :            : 
      94                 :            : /* Basic read and write */
      95                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_read(struct s2n_stuffer *stuffer, struct s2n_blob *out);
      96                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_erase_and_read(struct s2n_stuffer *stuffer, struct s2n_blob *out);
      97                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_write(struct s2n_stuffer *stuffer, const struct s2n_blob *in);
      98                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_read_bytes(struct s2n_stuffer *stuffer, uint8_t *out, uint32_t n);
      99                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_erase_and_read_bytes(struct s2n_stuffer *stuffer, uint8_t *data, uint32_t size);
     100                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_write_bytes(struct s2n_stuffer *stuffer, const uint8_t *in, const uint32_t n);
     101                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_writev_bytes(struct s2n_stuffer *stuffer, const struct iovec *iov, size_t iov_count,
     102                 :            :         uint32_t offs, uint32_t size);
     103                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_skip_read(struct s2n_stuffer *stuffer, uint32_t n);
     104                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_skip_write(struct s2n_stuffer *stuffer, const uint32_t n);
     105                 :            : 
     106                 :            : /* Tries to reserve enough space to write n additional bytes into the stuffer.*/
     107                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_reserve_space(struct s2n_stuffer *stuffer, uint32_t n);
     108                 :            : 
     109                 :            : /* Raw read/write move the cursor along and give you a pointer you can
     110                 :            :  * read/write data_len bytes from/to in-place.
     111                 :            :  */
     112                 :            : void *s2n_stuffer_raw_write(struct s2n_stuffer *stuffer, const uint32_t data_len);
     113                 :            : void *s2n_stuffer_raw_read(struct s2n_stuffer *stuffer, uint32_t data_len);
     114                 :            : 
     115                 :            : /* Send/receive stuffer to/from a file descriptor */
     116                 :            : int s2n_stuffer_recv_from_fd(struct s2n_stuffer *stuffer, const int rfd, const uint32_t len,
     117                 :            :         uint32_t *bytes_written);
     118                 :            : int s2n_stuffer_send_to_fd(struct s2n_stuffer *stuffer, const int wfd, const uint32_t len, uint32_t *bytes_sent);
     119                 :            : 
     120                 :            : /* Read and write integers in network order */
     121                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_read_uint8(struct s2n_stuffer *stuffer, uint8_t *u);
     122                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_read_uint16(struct s2n_stuffer *stuffer, uint16_t *u);
     123                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_read_uint24(struct s2n_stuffer *stuffer, uint32_t *u);
     124                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_read_uint32(struct s2n_stuffer *stuffer, uint32_t *u);
     125                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_read_uint64(struct s2n_stuffer *stuffer, uint64_t *u);
     126                 :            : 
     127                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_write_uint8(struct s2n_stuffer *stuffer, const uint8_t u);
     128                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_write_uint16(struct s2n_stuffer *stuffer, const uint16_t u);
     129                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_write_uint24(struct s2n_stuffer *stuffer, const uint32_t u);
     130                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_write_uint32(struct s2n_stuffer *stuffer, const uint32_t u);
     131                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_write_uint64(struct s2n_stuffer *stuffer, const uint64_t u);
     132                 :            : 
     133                 :            : /* Allocate space now for network order integers that will be written later.
     134                 :            :  * These are primarily intended to handle the vector type defined in the RFC:
     135                 :            :  * https://tools.ietf.org/html/rfc8446#section-3.4 */
     136                 :            : struct s2n_stuffer_reservation {
     137                 :            :     struct s2n_stuffer *stuffer;
     138                 :            :     uint32_t write_cursor;
     139                 :            :     uint8_t length;
     140                 :            : };
     141                 :            : /* Check basic validity constraints on the s2n_stuffer_reservation: e.g. stuffer validity. */
     142                 :            : S2N_RESULT s2n_stuffer_reservation_validate(const struct s2n_stuffer_reservation *reservation);
     143                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_reserve_uint8(struct s2n_stuffer *stuffer, struct s2n_stuffer_reservation *reservation);
     144                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_reserve_uint16(struct s2n_stuffer *stuffer, struct s2n_stuffer_reservation *reservation);
     145                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_reserve_uint24(struct s2n_stuffer *stuffer, struct s2n_stuffer_reservation *reservation);
     146                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_write_reservation(struct s2n_stuffer_reservation *reservation, const uint32_t value);
     147                 :            : /* Reservations are primarily intended to handle the variable-length vector type
     148                 :            :  * defined in the RFC: https://tools.ietf.org/html/rfc8446#section-3.4
     149                 :            :  * Variable-length vectors are preceded by the total size of the vector in bytes
     150                 :            :  * (not to be confused with the number of elements in the vector).
     151                 :            :  *
     152                 :            :  * These methods calculate the size of the vector just written to a stuffer based
     153                 :            :  * on the stuffer's current write cursor.
     154                 :            :  */
     155                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_get_vector_size(const struct s2n_stuffer_reservation *reservation, uint32_t *size);
     156                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_write_vector_size(struct s2n_stuffer_reservation *reservation);
     157                 :            : 
     158                 :            : /* Copy one stuffer to another */
     159                 :            : int s2n_stuffer_copy(struct s2n_stuffer *from, struct s2n_stuffer *to, uint32_t len);
     160                 :            : 
     161                 :            : /* Convert between hex strings and raw bytes.
     162                 :            :  *
     163                 :            :  * When reading hex, the characters can be uppercase or lowercase.
     164                 :            :  * When writing hex, lowercase characters are used.
     165                 :            :  *
     166                 :            :  * Examples:
     167                 :            :  * "1234567890ABCdef" == [ 0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef ]
     168                 :            :  * "FF" == 255 or [ 0xff ]
     169                 :            :  * "0001" == 1 or [ 0x00, 0x01 ]
     170                 :            :  */
     171                 :            : S2N_RESULT s2n_hex_digit(uint8_t half_byte, uint8_t *hex_digit);
     172                 :            : S2N_RESULT s2n_stuffer_read_hex(struct s2n_stuffer *hex_in, const struct s2n_blob *bytes_out);
     173                 :            : S2N_RESULT s2n_stuffer_write_hex(struct s2n_stuffer *hex_out, const struct s2n_blob *bytes_in);
     174                 :            : S2N_RESULT s2n_stuffer_read_uint8_hex(struct s2n_stuffer *stuffer, uint8_t *u);
     175                 :            : S2N_RESULT s2n_stuffer_write_uint8_hex(struct s2n_stuffer *stuffer, uint8_t u);
     176                 :            : S2N_RESULT s2n_stuffer_read_uint16_hex(struct s2n_stuffer *stuffer, uint16_t *u);
     177                 :            : S2N_RESULT s2n_stuffer_write_uint16_hex(struct s2n_stuffer *stuffer, uint16_t u);
     178                 :            : 
     179                 :            : /**
     180                 :            :  * Given base64 data in `stuffer`, write the decoded (binary) data into `out`. 
     181                 :            :  * 
     182                 :            :  * DANGER: If the data to be read is not a multiple of 4, any trailing bytes will
     183                 :            :  * be silently ignored.
     184                 :            :  */
     185                 :            : int s2n_stuffer_read_base64(struct s2n_stuffer *stuffer, struct s2n_stuffer *out);
     186                 :            : 
     187                 :            : /* Given some binary data in `in`, write the encoded (base64) data to `stuffer`. */
     188                 :            : int s2n_stuffer_write_base64(struct s2n_stuffer *stuffer, struct s2n_stuffer *in);
     189                 :            : 
     190                 :            : /* Useful for text manipulation ... */
     191                 :            : #define s2n_stuffer_write_char(stuffer, c)    s2n_stuffer_write_uint8((stuffer), (uint8_t) (c))
     192                 :            : #define s2n_stuffer_read_char(stuffer, c)     s2n_stuffer_read_uint8((stuffer), (uint8_t *) (c))
     193                 :            : #define s2n_stuffer_write_str(stuffer, c)     s2n_stuffer_write_bytes((stuffer), (const uint8_t *) (c), strlen((c)))
     194                 :            : #define s2n_stuffer_write_text(stuffer, c, n) s2n_stuffer_write_bytes((stuffer), (const uint8_t *) (c), (n))
     195                 :            : #define s2n_stuffer_read_text(stuffer, c, n)  s2n_stuffer_read_bytes((stuffer), (uint8_t *) (c), (n))
     196                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_read_expected_str(struct s2n_stuffer *stuffer, const char *expected);
     197                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_peek_char(struct s2n_stuffer *stuffer, char *c);
     198                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_read_token(struct s2n_stuffer *stuffer, struct s2n_stuffer *token, char delim);
     199                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_read_line(struct s2n_stuffer *stuffer, struct s2n_stuffer *token);
     200                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_peek_check_for_str(struct s2n_stuffer *s2n_stuffer, const char *expected);
     201                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_skip_whitespace(struct s2n_stuffer *stuffer, uint32_t *skipped);
     202                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_skip_to_char(struct s2n_stuffer *stuffer, char target);
     203                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_skip_expected_char(struct s2n_stuffer *stuffer, const char expected, const uint32_t min,
     204                 :            :         const uint32_t max, uint32_t *skipped);
     205                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_skip_read_until(struct s2n_stuffer *stuffer, const char *target);
     206                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_alloc_ro_from_string(struct s2n_stuffer *stuffer, const char *str);
     207                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_init_ro_from_string(struct s2n_stuffer *stuffer, uint8_t *data, uint32_t length);
     208                 :            : 
     209                 :            : /* Stuffer versions of sprintf methods, except:
     210                 :            :  * - They write bytes, not strings. They do not write a final '\0'. Unfortunately,
     211                 :            :  *   they do still require enough space for a final '\0'-- we'd have to reimplement
     212                 :            :  *   sprintf to avoid that.
     213                 :            :  * - vprintf does not consume the vargs. It calls va_copy before using
     214                 :            :  *   the varg argument, so can be called repeatedly with the same vargs.
     215                 :            :  */
     216                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_printf(struct s2n_stuffer *stuffer, const char *format, ...);
     217                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_vprintf(struct s2n_stuffer *stuffer, const char *format, va_list vargs);
     218                 :            : 
     219                 :            : /* Read a private key from a PEM encoded stuffer to an ASN1/DER encoded one */
     220                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_private_key_from_pem(struct s2n_stuffer *pem, struct s2n_stuffer *asn1, int *type);
     221                 :            : 
     222                 :            : /* Read a certificate from a PEM encoded stuffer to an ASN1/DER encoded one */
     223                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_certificate_from_pem(struct s2n_stuffer *pem, struct s2n_stuffer *asn1);
     224                 :            : bool s2n_stuffer_has_pem_encapsulated_block(struct s2n_stuffer *pem);
     225                 :            : 
     226                 :            : /* Read a CRL from a PEM encoded stuffer to an ASN1/DER encoded one */
     227                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_crl_from_pem(struct s2n_stuffer *pem, struct s2n_stuffer *asn1);
     228                 :            : 
     229                 :            : /* Read DH parameters om a PEM encoded stuffer to a PKCS3 encoded one */
     230                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_dhparams_from_pem(struct s2n_stuffer *pem, struct s2n_stuffer *pkcs3);
     231                 :            : 
     232                 :            : bool s2n_is_base64_char(unsigned char c);
     233                 :            : 
     234                 :            : /* Copies all valid data from "stuffer" into "out".
     235                 :            :  * The old blob "out" pointed to is freed.
     236                 :            :  * It is the responsibility of the caller to free the free "out".
     237                 :            :  */
     238                 :            : int S2N_RESULT_MUST_USE s2n_stuffer_extract_blob(struct s2n_stuffer *stuffer, struct s2n_blob *out);

Generated by: LCOV version 1.14