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