tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Hacl_Chacha20.c (7706B)


      1 /* MIT License
      2 *
      3 * Copyright (c) 2016-2022 INRIA, CMU and Microsoft Corporation
      4 * Copyright (c) 2022-2023 HACL* Contributors
      5 *
      6 * Permission is hereby granted, free of charge, to any person obtaining a copy
      7 * of this software and associated documentation files (the "Software"), to deal
      8 * in the Software without restriction, including without limitation the rights
      9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10 * copies of the Software, and to permit persons to whom the Software is
     11 * furnished to do so, subject to the following conditions:
     12 *
     13 * The above copyright notice and this permission notice shall be included in all
     14 * copies or substantial portions of the Software.
     15 *
     16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     22 * SOFTWARE.
     23 */
     24 
     25 #include "internal/Hacl_Chacha20.h"
     26 
     27 const uint32_t
     28    Hacl_Impl_Chacha20_Vec_chacha20_constants[4U] = { (uint32_t)0x61707865U, (uint32_t)0x3320646eU, (uint32_t)0x79622d32U, (uint32_t)0x6b206574U };
     29 
     30 static inline void
     31 quarter_round(uint32_t *st, uint32_t a, uint32_t b, uint32_t c, uint32_t d)
     32 {
     33    uint32_t sta = st[a];
     34    uint32_t stb0 = st[b];
     35    uint32_t std0 = st[d];
     36    uint32_t sta10 = sta + stb0;
     37    uint32_t std10 = std0 ^ sta10;
     38    uint32_t std2 = std10 << (uint32_t)16U | std10 >> (uint32_t)16U;
     39    st[a] = sta10;
     40    st[d] = std2;
     41    uint32_t sta0 = st[c];
     42    uint32_t stb1 = st[d];
     43    uint32_t std3 = st[b];
     44    uint32_t sta11 = sta0 + stb1;
     45    uint32_t std11 = std3 ^ sta11;
     46    uint32_t std20 = std11 << (uint32_t)12U | std11 >> (uint32_t)20U;
     47    st[c] = sta11;
     48    st[b] = std20;
     49    uint32_t sta2 = st[a];
     50    uint32_t stb2 = st[b];
     51    uint32_t std4 = st[d];
     52    uint32_t sta12 = sta2 + stb2;
     53    uint32_t std12 = std4 ^ sta12;
     54    uint32_t std21 = std12 << (uint32_t)8U | std12 >> (uint32_t)24U;
     55    st[a] = sta12;
     56    st[d] = std21;
     57    uint32_t sta3 = st[c];
     58    uint32_t stb = st[d];
     59    uint32_t std = st[b];
     60    uint32_t sta1 = sta3 + stb;
     61    uint32_t std1 = std ^ sta1;
     62    uint32_t std22 = std1 << (uint32_t)7U | std1 >> (uint32_t)25U;
     63    st[c] = sta1;
     64    st[b] = std22;
     65 }
     66 
     67 static inline void
     68 double_round(uint32_t *st)
     69 {
     70    quarter_round(st, (uint32_t)0U, (uint32_t)4U, (uint32_t)8U, (uint32_t)12U);
     71    quarter_round(st, (uint32_t)1U, (uint32_t)5U, (uint32_t)9U, (uint32_t)13U);
     72    quarter_round(st, (uint32_t)2U, (uint32_t)6U, (uint32_t)10U, (uint32_t)14U);
     73    quarter_round(st, (uint32_t)3U, (uint32_t)7U, (uint32_t)11U, (uint32_t)15U);
     74    quarter_round(st, (uint32_t)0U, (uint32_t)5U, (uint32_t)10U, (uint32_t)15U);
     75    quarter_round(st, (uint32_t)1U, (uint32_t)6U, (uint32_t)11U, (uint32_t)12U);
     76    quarter_round(st, (uint32_t)2U, (uint32_t)7U, (uint32_t)8U, (uint32_t)13U);
     77    quarter_round(st, (uint32_t)3U, (uint32_t)4U, (uint32_t)9U, (uint32_t)14U);
     78 }
     79 
     80 static inline void
     81 rounds(uint32_t *st)
     82 {
     83    double_round(st);
     84    double_round(st);
     85    double_round(st);
     86    double_round(st);
     87    double_round(st);
     88    double_round(st);
     89    double_round(st);
     90    double_round(st);
     91    double_round(st);
     92    double_round(st);
     93 }
     94 
     95 static inline void
     96 chacha20_core(uint32_t *k, uint32_t *ctx, uint32_t ctr)
     97 {
     98    memcpy(k, ctx, (uint32_t)16U * sizeof(uint32_t));
     99    uint32_t ctr_u32 = ctr;
    100    k[12U] = k[12U] + ctr_u32;
    101    rounds(k);
    102    KRML_MAYBE_FOR16(i,
    103                     (uint32_t)0U,
    104                     (uint32_t)16U,
    105                     (uint32_t)1U,
    106                     uint32_t *os = k;
    107                     uint32_t x = k[i] + ctx[i];
    108                     os[i] = x;);
    109    k[12U] = k[12U] + ctr_u32;
    110 }
    111 
    112 static const uint32_t
    113    chacha20_constants[4U] = { (uint32_t)0x61707865U, (uint32_t)0x3320646eU, (uint32_t)0x79622d32U, (uint32_t)0x6b206574U };
    114 
    115 void
    116 Hacl_Impl_Chacha20_chacha20_init(uint32_t *ctx, uint8_t *k, uint8_t *n, uint32_t ctr)
    117 {
    118    KRML_MAYBE_FOR4(i,
    119                    (uint32_t)0U,
    120                    (uint32_t)4U,
    121                    (uint32_t)1U,
    122                    uint32_t *os = ctx;
    123                    uint32_t x = chacha20_constants[i];
    124                    os[i] = x;);
    125    KRML_MAYBE_FOR8(i,
    126                    (uint32_t)0U,
    127                    (uint32_t)8U,
    128                    (uint32_t)1U,
    129                    uint32_t *os = ctx + (uint32_t)4U;
    130                    uint8_t *bj = k + i * (uint32_t)4U;
    131                    uint32_t u = load32_le(bj);
    132                    uint32_t r = u;
    133                    uint32_t x = r;
    134                    os[i] = x;);
    135    ctx[12U] = ctr;
    136    KRML_MAYBE_FOR3(i,
    137                    (uint32_t)0U,
    138                    (uint32_t)3U,
    139                    (uint32_t)1U,
    140                    uint32_t *os = ctx + (uint32_t)13U;
    141                    uint8_t *bj = n + i * (uint32_t)4U;
    142                    uint32_t u = load32_le(bj);
    143                    uint32_t r = u;
    144                    uint32_t x = r;
    145                    os[i] = x;);
    146 }
    147 
    148 static void
    149 chacha20_encrypt_block(uint32_t *ctx, uint8_t *out, uint32_t incr, uint8_t *text)
    150 {
    151    uint32_t k[16U] = { 0U };
    152    chacha20_core(k, ctx, incr);
    153    uint32_t bl[16U] = { 0U };
    154    KRML_MAYBE_FOR16(i,
    155                     (uint32_t)0U,
    156                     (uint32_t)16U,
    157                     (uint32_t)1U,
    158                     uint32_t *os = bl;
    159                     uint8_t *bj = text + i * (uint32_t)4U;
    160                     uint32_t u = load32_le(bj);
    161                     uint32_t r = u;
    162                     uint32_t x = r;
    163                     os[i] = x;);
    164    KRML_MAYBE_FOR16(i,
    165                     (uint32_t)0U,
    166                     (uint32_t)16U,
    167                     (uint32_t)1U,
    168                     uint32_t *os = bl;
    169                     uint32_t x = bl[i] ^ k[i];
    170                     os[i] = x;);
    171    KRML_MAYBE_FOR16(i,
    172                     (uint32_t)0U,
    173                     (uint32_t)16U,
    174                     (uint32_t)1U,
    175                     store32_le(out + i * (uint32_t)4U, bl[i]););
    176 }
    177 
    178 static inline void
    179 chacha20_encrypt_last(uint32_t *ctx, uint32_t len, uint8_t *out, uint32_t incr, uint8_t *text)
    180 {
    181    uint8_t plain[64U] = { 0U };
    182    memcpy(plain, text, len * sizeof(uint8_t));
    183    chacha20_encrypt_block(ctx, plain, incr, plain);
    184    memcpy(out, plain, len * sizeof(uint8_t));
    185 }
    186 
    187 void
    188 Hacl_Impl_Chacha20_chacha20_update(uint32_t *ctx, uint32_t len, uint8_t *out, uint8_t *text)
    189 {
    190    uint32_t rem = len % (uint32_t)64U;
    191    uint32_t nb = len / (uint32_t)64U;
    192    uint32_t rem1 = len % (uint32_t)64U;
    193    for (uint32_t i = (uint32_t)0U; i < nb; i++) {
    194        chacha20_encrypt_block(ctx, out + i * (uint32_t)64U, i, text + i * (uint32_t)64U);
    195    }
    196    if (rem1 > (uint32_t)0U) {
    197        chacha20_encrypt_last(ctx, rem, out + nb * (uint32_t)64U, nb, text + nb * (uint32_t)64U);
    198    }
    199 }
    200 
    201 void
    202 Hacl_Chacha20_chacha20_encrypt(
    203    uint32_t len,
    204    uint8_t *out,
    205    uint8_t *text,
    206    uint8_t *key,
    207    uint8_t *n,
    208    uint32_t ctr)
    209 {
    210    uint32_t ctx[16U] = { 0U };
    211    Hacl_Impl_Chacha20_chacha20_init(ctx, key, n, ctr);
    212    Hacl_Impl_Chacha20_chacha20_update(ctx, len, out, text);
    213 }
    214 
    215 void
    216 Hacl_Chacha20_chacha20_decrypt(
    217    uint32_t len,
    218    uint8_t *out,
    219    uint8_t *cipher,
    220    uint8_t *key,
    221    uint8_t *n,
    222    uint32_t ctr)
    223 {
    224    uint32_t ctx[16U] = { 0U };
    225    Hacl_Impl_Chacha20_chacha20_init(ctx, key, n, ctr);
    226    Hacl_Impl_Chacha20_chacha20_update(ctx, len, out, cipher);
    227 }