Home | History | Annotate | Line # | Download | only in internal
      1 /*
      2  * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.
      3  *
      4  * Licensed under the Apache License 2.0 (the "License").  You may not use
      5  * this file except in compliance with the License.  You can obtain a copy
      6  * in the file LICENSE in the source distribution or at
      7  * https://www.openssl.org/source/license.html
      8  */
      9 
     10 #ifndef OSSL_INTERNAL_QUIC_VLINT_H
     11 #define OSSL_INTERNAL_QUIC_VLINT_H
     12 #pragma once
     13 
     14 #include "internal/e_os.h"
     15 
     16 #ifndef OPENSSL_NO_QUIC
     17 
     18 /* The smallest value requiring a 1, 2, 4, or 8-byte representation. */
     19 #define OSSL_QUIC_VLINT_1B_MIN 0
     20 #define OSSL_QUIC_VLINT_2B_MIN 64
     21 #define OSSL_QUIC_VLINT_4B_MIN 16384
     22 #define OSSL_QUIC_VLINT_8B_MIN 1073741824
     23 
     24 /* The largest value representable in a given number of bytes. */
     25 #define OSSL_QUIC_VLINT_1B_MAX (OSSL_QUIC_VLINT_2B_MIN - 1)
     26 #define OSSL_QUIC_VLINT_2B_MAX (OSSL_QUIC_VLINT_4B_MIN - 1)
     27 #define OSSL_QUIC_VLINT_4B_MAX (OSSL_QUIC_VLINT_8B_MIN - 1)
     28 #define OSSL_QUIC_VLINT_8B_MAX (((uint64_t)1 << 62) - 1)
     29 
     30 /* The largest value representable as a variable-length integer. */
     31 #define OSSL_QUIC_VLINT_MAX OSSL_QUIC_VLINT_8B_MAX
     32 
     33 /*
     34  * Returns the number of bytes needed to encode v in the QUIC variable-length
     35  * integer encoding.
     36  *
     37  * Returns 0 if v exceeds OSSL_QUIC_VLINT_MAX.
     38  */
     39 static ossl_unused ossl_inline size_t ossl_quic_vlint_encode_len(uint64_t v)
     40 {
     41     if (v < OSSL_QUIC_VLINT_2B_MIN)
     42         return 1;
     43 
     44     if (v < OSSL_QUIC_VLINT_4B_MIN)
     45         return 2;
     46 
     47     if (v < OSSL_QUIC_VLINT_8B_MIN)
     48         return 4;
     49 
     50     if (v <= OSSL_QUIC_VLINT_MAX)
     51         return 8;
     52 
     53     return 0;
     54 }
     55 
     56 /*
     57  * This function writes a QUIC varable-length encoded integer to buf.
     58  * The smallest usable representation is used.
     59  *
     60  * It is the caller's responsibility to ensure that the buffer is big enough by
     61  * calling ossl_quic_vlint_encode_len(v) before calling this function.
     62  *
     63  * Precondition: buf is at least ossl_quic_vlint_enc_len(v) bytes in size
     64  *   (unchecked)
     65  * Precondition: v does not exceed OSSL_QUIC_VLINT_MAX
     66  *   (unchecked)
     67  */
     68 void ossl_quic_vlint_encode(unsigned char *buf, uint64_t v);
     69 
     70 /*
     71  * This function writes a QUIC variable-length encoded integer to buf. The
     72  * specified number of bytes n are used for the encoding, which means that the
     73  * encoded value may take up more space than necessary.
     74  *
     75  * It is the caller's responsibility to ensure that the buffer is of at least n
     76  * bytes, and that v is representable by a n-byte QUIC variable-length integer.
     77  * The representable ranges are:
     78  *
     79  *   1-byte encoding: [0, 2** 6-1]
     80  *   2-byte encoding: [0, 2**14-1]
     81  *   4-byte encoding: [0, 2**30-1]
     82  *   8-byte encoding: [0, 2**62-1]
     83  *
     84  * Precondition: buf is at least n bytes in size (unchecked)
     85  * Precondition: v does not exceed the representable range
     86  *   (ossl_quic_vlint_encode_len(v) <= n) (unchecked)
     87  * Precondition: v does not exceed OSSL_QUIC_VLINT_MAX
     88  *   (unchecked)
     89  */
     90 void ossl_quic_vlint_encode_n(unsigned char *buf, uint64_t v, int n);
     91 
     92 /*
     93  * Given the first byte of an encoded QUIC variable-length integer, returns
     94  * the number of bytes comprising the encoded integer, including the first
     95  * byte.
     96  */
     97 static ossl_unused ossl_inline size_t ossl_quic_vlint_decode_len(uint8_t first_byte)
     98 {
     99     return 1U << ((first_byte & 0xC0) >> 6);
    100 }
    101 
    102 /*
    103  * Given a buffer containing an encoded QUIC variable-length integer, returns
    104  * the decoded value. The buffer must be of at least
    105  * ossl_quic_vlint_decode_len(buf[0]) bytes in size, and the caller is responsible
    106  * for checking this.
    107  *
    108  * Precondition: buf is at least ossl_quic_vlint_decode_len(buf[0]) bytes in size
    109  *   (unchecked)
    110  */
    111 uint64_t ossl_quic_vlint_decode_unchecked(const unsigned char *buf);
    112 
    113 /*
    114  * Given a buffer buf of buf_len bytes in length, attempts to decode an encoded
    115  * QUIC variable-length integer at the start of the buffer and writes the result
    116  * to *v. If buf_len is inadequate, suggesting a truncated encoded integer, the
    117  * function fails and 0 is returned. Otherwise, returns the number of bytes
    118  * consumed.
    119  *
    120  * Precondition: buf is at least buf_len bytes in size
    121  * Precondition: v (unchecked)
    122  */
    123 int ossl_quic_vlint_decode(const unsigned char *buf, size_t buf_len, uint64_t *v);
    124 
    125 #endif
    126 
    127 #endif
    128