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 27typedef struct chacha_ctx { 28 uint32_t input[16]; 29} chacha_ctx; 30 31static void 32chacha_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 48static void 49chacha_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 57static void 58chacha_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 66static void 67chacha20_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 83static int 84stream_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 102static int 103stream_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 121static int 122stream_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 146static int 147stream_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 166struct 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