"Fossies" - the Fresh Open Source Software Archive

Member "rspamd-1.8.3/contrib/libottery/aes_cryptobox.c" (3 Dec 2018, 6057 Bytes) of package /linux/misc/rspamd-1.8.3.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "aes_cryptobox.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright (c) 2017, Vsevolod Stakhov
    3  * Copyright (c) 2017, Frank Denis
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions are met:
    8  *   * Redistributions of source code must retain the above copyright
    9  *     notice, this list of conditions and the following disclaimer.
   10  *   * Redistributions in binary form must reproduce the above copyright
   11  *     notice, this list of conditions and the following disclaimer in the
   12  *     documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY AUTHOR ''AS IS'' AND ANY
   15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   17  * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
   18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   23  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   24  */
   25 
   26 #include "config.h"
   27 #include "ottery-internal.h"
   28 #include "cryptobox.h"
   29 
   30 #if defined(__x86_64__) && defined(RSPAMD_HAS_TARGET_ATTR)
   31 #pragma GCC push_options
   32 #pragma GCC target("aes")
   33 #ifndef __SSE2__
   34 #define __SSE2__
   35 #endif
   36 #ifndef __SSE__
   37 #define __SSE__
   38 #endif
   39 #ifndef __AES__
   40 #define __AES__
   41 #endif
   42 #include <immintrin.h>
   43 #define ROUNDS 10
   44 
   45 typedef struct RSPAMD_ALIGNED(16) aes_rng_state {
   46     __m128i round_keys[ROUNDS + 1];
   47     __m128i counter;
   48 } aes_stream_state;
   49 
   50 
   51 #define STATE_LEN   sizeof(aes_stream_state)
   52 #define STATE_BYTES 16
   53 
   54 #define OUTPUT_LEN  1024
   55 
   56 static void
   57 aes_key_expand (__m128i round_keys[ROUNDS + 1], __m128i t) __attribute__((target("aes")));
   58 
   59 static void
   60 aes_key_expand (__m128i round_keys[ROUNDS + 1], __m128i t)
   61 {
   62     __m128i t1;
   63 
   64 #define DO_ROUND_KEY(ROUND, RC)                           \
   65     do {                                                   \
   66         t1 = _mm_aeskeygenassist_si128(t, (RC));           \
   67         round_keys[ROUND] = t;                             \
   68         t = _mm_xor_si128(t, _mm_slli_si128(t, 4));        \
   69         t = _mm_xor_si128(t, _mm_slli_si128(t, 8));        \
   70         t = _mm_xor_si128(t, _mm_shuffle_epi32(t1, 0xff)); \
   71     } while (0)
   72 
   73     DO_ROUND_KEY(0, 1);
   74     DO_ROUND_KEY(1, 2);
   75     DO_ROUND_KEY(2, 4);
   76     DO_ROUND_KEY(3, 8);
   77     DO_ROUND_KEY(4, 16);
   78     DO_ROUND_KEY(5, 32);
   79     DO_ROUND_KEY(6, 64);
   80     DO_ROUND_KEY(7, 128);
   81     DO_ROUND_KEY(8, 27);
   82     DO_ROUND_KEY(9, 54);
   83     round_keys[10] = t;
   84 }
   85 
   86 /*
   87  * Computes one 128 bytes block and refresh keys
   88  */
   89 static void
   90 aes_round(unsigned char *buf, struct aes_rng_state *st) __attribute__((target("aes")));
   91 static void
   92 aes_round(unsigned char *buf, struct aes_rng_state *st)
   93 {
   94     const __m128i  one = _mm_set_epi64x(0, 1);
   95     __m128i *round_keys = st->round_keys;
   96     __m128i c0, c1, c2, c3, c4, c5, c6, c7;
   97     __m128i r0, r1, r2, r3, r4, r5, r6, r7;
   98     __m128i s0, s1, s2, s3, s4, s5, s6, s7;
   99     size_t i;
  100 
  101 #define COMPUTE_ROUNDS(N)                                                              \
  102     do {                                                                               \
  103         r##N = _mm_aesenc_si128(   _mm_xor_si128(c##N, round_keys[0]), round_keys[1]); \
  104         r##N = _mm_aesenc_si128(_mm_aesenc_si128(r##N, round_keys[2]), round_keys[3]); \
  105         r##N = _mm_aesenc_si128(_mm_aesenc_si128(r##N, round_keys[4]), round_keys[5]); \
  106         s##N = r##N;                                                                   \
  107         r##N = _mm_aesenc_si128(_mm_aesenc_si128(r##N, round_keys[6]), round_keys[7]); \
  108         r##N = _mm_aesenc_si128(_mm_aesenc_si128(r##N, round_keys[8]), round_keys[9]); \
  109         r##N = _mm_xor_si128(s##N, _mm_aesenclast_si128(r##N, round_keys[10]));        \
  110     } while (0)
  111 
  112     c0 = st->counter;
  113 
  114     for (i = 0; i < OUTPUT_LEN / 128; i ++) {
  115         c1 = _mm_add_epi64 (c0, one);
  116         c2 = _mm_add_epi64 (c1, one);
  117         c3 = _mm_add_epi64 (c2, one);
  118         c4 = _mm_add_epi64 (c3, one);
  119         c5 = _mm_add_epi64 (c4, one);
  120         c6 = _mm_add_epi64 (c5, one);
  121         c7 = _mm_add_epi64 (c6, one);
  122         COMPUTE_ROUNDS(0);
  123         COMPUTE_ROUNDS(1);
  124         COMPUTE_ROUNDS(2);
  125         COMPUTE_ROUNDS(3);
  126         COMPUTE_ROUNDS(4);
  127         COMPUTE_ROUNDS(5);
  128         COMPUTE_ROUNDS(6);
  129         COMPUTE_ROUNDS(7);
  130         c0 = _mm_add_epi64 (c7, one);
  131         _mm_storeu_si128 ((__m128i *) (void *) (buf + 0), r0);
  132         _mm_storeu_si128 ((__m128i *) (void *) (buf + 16), r1);
  133         _mm_storeu_si128 ((__m128i *) (void *) (buf + 32), r2);
  134         _mm_storeu_si128 ((__m128i *) (void *) (buf + 48), r3);
  135         _mm_storeu_si128 ((__m128i *) (void *) (buf + 64), r4);
  136         _mm_storeu_si128 ((__m128i *) (void *) (buf + 80), r5);
  137         _mm_storeu_si128 ((__m128i *) (void *) (buf + 96), r6);
  138         _mm_storeu_si128 ((__m128i *) (void *) (buf + 112), r7);
  139         buf += 128;
  140     }
  141 
  142     st->counter = c0;
  143     c0 = _mm_setzero_si128();
  144     COMPUTE_ROUNDS(0);
  145     aes_key_expand(round_keys, r0);
  146 }
  147 
  148 
  149 static void
  150 aes_cryptobox_state_setup (void *state_, const uint8_t *bytes)
  151 {
  152     struct aes_rng_state *x = state_;
  153 
  154     aes_key_expand (x->round_keys,
  155             _mm_loadu_si128((const __m128i *) (const void *)bytes));
  156 }
  157 
  158 static void
  159 aes_cryptobox_generate (void *state_, uint8_t *output, uint32_t idx)
  160 {
  161     struct aes_rng_state *x = state_;
  162 
  163     aes_round(output, x);
  164 }
  165 
  166 #define PRF_AES(r) {                         \
  167   "AES-" #r,                                  \
  168   "AES-" #r "-NOSIMD",                        \
  169   "AES-" #r "-NOSIMD-DEFAULT",                \
  170   STATE_LEN,                                    \
  171   STATE_BYTES,                                  \
  172   OUTPUT_LEN,                                   \
  173   OTTERY_CPUCAP_AES,                                            \
  174   aes_cryptobox_state_setup,                    \
  175   aes_cryptobox_generate               \
  176 }
  177 
  178 const struct ottery_prf ottery_prf_aes_cryptobox_ = PRF_AES(128);
  179 #endif /* x86_64 */