Home | History | Annotate | Line # | Download | only in dolbeau
      1 
      2 #include <stdint.h>
      3 #include <stdlib.h>
      4 #include <string.h>
      5 
      6 #include "core.h"
      7 #include "crypto_stream_chacha20.h"
      8 #include "private/common.h"
      9 #include "private/sse2_64_32.h"
     10 #include "utils.h"
     11 
     12 #if defined(HAVE_EMMINTRIN_H) && defined(HAVE_TMMINTRIN_H)
     13 
     14 # ifdef __GNUC__
     15 #  pragma GCC target("sse2")
     16 #  pragma GCC target("ssse3")
     17 # endif
     18 
     19 # include <emmintrin.h>
     20 # include <tmmintrin.h>
     21 
     22 # include "../stream_chacha20.h"
     23 # include "chacha20_dolbeau-ssse3.h"
     24 
     25 # define ROUNDS 20
     26 
     27 typedef struct chacha_ctx {
     28     uint32_t input[16];
     29 } chacha_ctx;
     30 
     31 static void
     32 chacha_keysetup(chacha_ctx *ctx, const uint8_t *k)
     33 {
     34     ctx->input[0]  = 0x61707865;
     35     ctx->input[1]  = 0x3320646e;
     36     ctx->input[2]  = 0x79622d32;
     37     ctx->input[3]  = 0x6b206574;
     38     ctx->input[4]  = LOAD32_LE(k + 0);
     39     ctx->input[5]  = LOAD32_LE(k + 4);
     40     ctx->input[6]  = LOAD32_LE(k + 8);
     41     ctx->input[7]  = LOAD32_LE(k + 12);
     42     ctx->input[8]  = LOAD32_LE(k + 16);
     43     ctx->input[9]  = LOAD32_LE(k + 20);
     44     ctx->input[10] = LOAD32_LE(k + 24);
     45     ctx->input[11] = LOAD32_LE(k + 28);
     46 }
     47 
     48 static void
     49 chacha_ivsetup(chacha_ctx *ctx, const uint8_t *iv, const uint8_t *counter)
     50 {
     51     ctx->input[12] = counter == NULL ? 0 : LOAD32_LE(counter + 0);
     52     ctx->input[13] = counter == NULL ? 0 : LOAD32_LE(counter + 4);
     53     ctx->input[14] = LOAD32_LE(iv + 0);
     54     ctx->input[15] = LOAD32_LE(iv + 4);
     55 }
     56 
     57 static void
     58 chacha_ietf_ivsetup(chacha_ctx *ctx, const uint8_t *iv, const uint8_t *counter)
     59 {
     60     ctx->input[12] = counter == NULL ? 0 : LOAD32_LE(counter);
     61     ctx->input[13] = LOAD32_LE(iv + 0);
     62     ctx->input[14] = LOAD32_LE(iv + 4);
     63     ctx->input[15] = LOAD32_LE(iv + 8);
     64 }
     65 
     66 static void
     67 chacha20_encrypt_bytes(chacha_ctx *ctx, const uint8_t *m, uint8_t *c,
     68                        unsigned long long bytes)
     69 {
     70     uint32_t * const x = &ctx->input[0];
     71 
     72     if (!bytes) {
     73         return; /* LCOV_EXCL_LINE */
     74     }
     75     if (bytes > crypto_stream_chacha20_MESSAGEBYTES_MAX) {
     76         sodium_misuse();
     77     }
     78 # include "u4.h"
     79 # include "u1.h"
     80 # include "u0.h"
     81 }
     82 
     83 static int
     84 stream_ref(unsigned char *c, unsigned long long clen, const unsigned char *n,
     85            const unsigned char *k)
     86 {
     87     struct chacha_ctx ctx;
     88 
     89     if (!clen) {
     90         return 0;
     91     }
     92     COMPILER_ASSERT(crypto_stream_chacha20_KEYBYTES == 256 / 8);
     93     chacha_keysetup(&ctx, k);
     94     chacha_ivsetup(&ctx, n, NULL);
     95     memset(c, 0, clen);
     96     chacha20_encrypt_bytes(&ctx, c, c, clen);
     97     sodium_memzero(&ctx, sizeof ctx);
     98 
     99     return 0;
    100 }
    101 
    102 static int
    103 stream_ietf_ref(unsigned char *c, unsigned long long clen,
    104                 const unsigned char *n, const unsigned char *k)
    105 {
    106     struct chacha_ctx ctx;
    107 
    108     if (!clen) {
    109         return 0;
    110     }
    111     COMPILER_ASSERT(crypto_stream_chacha20_KEYBYTES == 256 / 8);
    112     chacha_keysetup(&ctx, k);
    113     chacha_ietf_ivsetup(&ctx, n, NULL);
    114     memset(c, 0, clen);
    115     chacha20_encrypt_bytes(&ctx, c, c, clen);
    116     sodium_memzero(&ctx, sizeof ctx);
    117 
    118     return 0;
    119 }
    120 
    121 static int
    122 stream_ref_xor_ic(unsigned char *c, const unsigned char *m,
    123                   unsigned long long mlen, const unsigned char *n, uint64_t ic,
    124                   const unsigned char *k)
    125 {
    126     struct chacha_ctx ctx;
    127     uint8_t           ic_bytes[8];
    128     uint32_t          ic_high;
    129     uint32_t          ic_low;
    130 
    131     if (!mlen) {
    132         return 0;
    133     }
    134     ic_high = (uint32_t) (ic >> 32);
    135     ic_low  = (uint32_t) ic;
    136     STORE32_LE(&ic_bytes[0], ic_low);
    137     STORE32_LE(&ic_bytes[4], ic_high);
    138     chacha_keysetup(&ctx, k);
    139     chacha_ivsetup(&ctx, n, ic_bytes);
    140     chacha20_encrypt_bytes(&ctx, m, c, mlen);
    141     sodium_memzero(&ctx, sizeof ctx);
    142 
    143     return 0;
    144 }
    145 
    146 static int
    147 stream_ietf_ref_xor_ic(unsigned char *c, const unsigned char *m,
    148                        unsigned long long mlen, const unsigned char *n,
    149                        uint32_t ic, const unsigned char *k)
    150 {
    151     struct chacha_ctx ctx;
    152     uint8_t           ic_bytes[4];
    153 
    154     if (!mlen) {
    155         return 0;
    156     }
    157     STORE32_LE(ic_bytes, ic);
    158     chacha_keysetup(&ctx, k);
    159     chacha_ietf_ivsetup(&ctx, n, ic_bytes);
    160     chacha20_encrypt_bytes(&ctx, m, c, mlen);
    161     sodium_memzero(&ctx, sizeof ctx);
    162 
    163     return 0;
    164 }
    165 
    166 struct crypto_stream_chacha20_implementation
    167     crypto_stream_chacha20_dolbeau_ssse3_implementation = {
    168         SODIUM_C99(.stream =) stream_ref,
    169         SODIUM_C99(.stream_ietf =) stream_ietf_ref,
    170         SODIUM_C99(.stream_xor_ic =) stream_ref_xor_ic,
    171         SODIUM_C99(.stream_ietf_xor_ic =) stream_ietf_ref_xor_ic
    172     };
    173 
    174 #endif
    175