Added AES+GHASH implementation using AES-NI opcodes; also ARM-Thumb assembly for faster Montgomery multiplication on Cortex-M0+. Added selection functions for "default" implementations.

This commit is contained in:
Thomas Pornin 2017-01-29 21:46:33 +01:00
parent 556e525d62
commit 5f045c7599
58 changed files with 3012 additions and 395 deletions

View file

@ -41,6 +41,16 @@
#define BR_64 1
*/
/*
* When BR_LOMUL is enabled, then multiplications of 32-bit values whose
* result are truncated to the low 32 bits are assumed to be
* substantially more efficient than 32-bit multiplications that yield
* 64-bit results. This is typically the case on low-end ARM Cortex M
* systems (M0, M0+, M1, and arguably M3 and M4 as well).
*
#define BR_LOMUL 1
*/
/*
* When BR_SLOW_MUL is enabled, multiplications are assumed to be
* substantially slow with regards to other integer operations, thus
@ -127,4 +137,29 @@
#define BR_USE_WIN32_TIME 1
*/
/*
* When BR_ARMEL_CORTEXM_GCC is enabled, some operations are replaced with
* inline assembly which is shorter and/or faster. This should be used
* only when all of the following are true:
* - target architecture is ARM in Thumb mode
* - target endianness is little-endian
* - compiler is GCC (or GCC-compatible for inline assembly syntax)
*
* This is meant for the low-end cores (Cortex M0, M0+, M1, M3).
* Note: if BR_LOMUL is not explicitly enabled or disabled, then
* enabling BR_ARMEL_CORTEXM_GCC also enables BR_LOMUL.
*
#define BR_ARMEL_CORTEXM_GCC 1
*/
/*
* When BR_AES_X86NI is enabled, the AES implementation using the x86 "NI"
* instructions (dedicated AES opcodes) will be compiled. If this is not
* enabled explicitly, then that AES implementation will be compiled only
* if a compatible compiler is detected. If set explicitly to 0, the
* implementation will not be compiled at all.
*
#define BR_AES_X86NI 1
*/
#endif

36
src/ec/ec_default.c Normal file
View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/* see bearssl_ec.h */
const br_ec_impl *
br_ec_get_default(void)
{
#if BR_LOMUL
return &br_ec_all_m15;
#else
return &br_ec_all_m31;
#endif
}

View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/* see bearssl_ec.h */
br_ecdsa_sign
br_ecdsa_sign_asn1_get_default(void)
{
#if BR_LOMUL
return &br_ecdsa_i15_sign_asn1;
#else
return &br_ecdsa_i31_sign_asn1;
#endif
}

View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/* see bearssl_ec.h */
br_ecdsa_sign
br_ecdsa_sign_raw_get_default(void)
{
#if BR_LOMUL
return &br_ecdsa_i15_sign_raw;
#else
return &br_ecdsa_i31_sign_raw;
#endif
}

View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/* see bearssl_ec.h */
br_ecdsa_vrfy
br_ecdsa_vrfy_asn1_get_default(void)
{
#if BR_LOMUL
return &br_ecdsa_i15_vrfy_asn1;
#else
return &br_ecdsa_i31_vrfy_asn1;
#endif
}

View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/* see bearssl_ec.h */
br_ecdsa_vrfy
br_ecdsa_vrfy_raw_get_default(void)
{
#if BR_LOMUL
return &br_ecdsa_i15_vrfy_raw;
#else
return &br_ecdsa_i31_vrfy_raw;
#endif
}

253
src/hash/ghash_pclmul.c Normal file
View file

@ -0,0 +1,253 @@
/*
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/*
* This is the GHASH implementation that leverages the pclmulqdq opcode
* (from the AES-NI instructions).
*/
#if BR_AES_X86NI
#if BR_AES_X86NI_GCC
/* #pragma GCC target "sse2,ssse3,pclmul" */
#include <tmmintrin.h>
#include <wmmintrin.h>
#include <cpuid.h>
#endif
#if BR_AES_X86NI_MSC
#include <intrin.h>
#endif
/* see bearssl_hash.h */
BR_TARGET("ssse3,pclmul")
void
br_ghash_pclmul(void *y, const void *h, const void *data, size_t len)
{
/*
* TODO: loop below processes one 16-bit word at a time. We
* could parallelize, using:
* ((y+x0)*h+x1)*h = (y+x0)*(h^2) + x1*h
* i.e. precompute h^2, then handle two words at a time, mostly
* in parallel (this may extend to more words as well...).
*/
const unsigned char *buf;
__m128i yx, hx;
__m128i h0, h1, h2;
__m128i byteswap_index;
byteswap_index = _mm_set_epi8(
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
yx = _mm_loadu_si128(y);
hx = _mm_loadu_si128(h);
yx = _mm_shuffle_epi8(yx, byteswap_index);
hx = _mm_shuffle_epi8(hx, byteswap_index);
/*
* We byte-swap y and h for full big-endian interpretation
* (see below).
*/
h0 = hx;
h1 = _mm_shuffle_epi32(hx, 0x0E);
h2 = _mm_xor_si128(h0, h1);
buf = data;
while (len > 0) {
__m128i x;
__m128i t0, t1, t2, v0, v1, v2, v3;
__m128i y0, y1, y2;
/*
* Load next 128-bit word. If there are not enough bytes
* for the next word, we pad it with zeros (as per the
* API for this function; it's also what is useful for
* implementation of GCM).
*/
if (len >= 16) {
x = _mm_loadu_si128((const void *)buf);
buf += 16;
len -= 16;
} else {
unsigned char tmp[16];
memcpy(tmp, buf, len);
memset(tmp + len, 0, (sizeof tmp) - len);
x = _mm_loadu_si128((void *)tmp);
len = 0;
}
/*
* Specification of GCM is basically "full little-endian",
* i.e. leftmost bit is most significant; but decoding
* performed by _mm_loadu_si128 is "mixed endian" (leftmost
* _byte_ is least significant, but within each byte, the
* leftmost _bit_ is most significant). We could reverse
* bits in each byte; however, it is more efficient to
* swap the bytes and thus emulate full big-endian
* decoding.
*
* Big-endian works here because multiplication in
* GF[2](X) is "carry-less", thereby allowing reversal:
* if rev_n(x) consists in reversing the order of bits
* in x, then:
* rev_128(A)*rev_128(B) = rev_255(A*B)
* so we can compute A*B by using rev_128(A) and rev_128(B),
* and an extra shift at the end (because 255 != 256). Bit
* reversal is exactly what happens when converting from
* full little-endian to full big-endian.
*/
x = _mm_shuffle_epi8(x, byteswap_index);
yx = _mm_xor_si128(yx, x);
/*
* We want the product to be broken down into four
* 64-bit values, because there is no SSE* opcode that
* can do a shift on a 128-bit value.
*/
y0 = yx;
y1 = _mm_shuffle_epi32(yx, 0x0E);
y2 = _mm_xor_si128(y0, y1);
t0 = _mm_clmulepi64_si128(y0, h0, 0x00);
t1 = _mm_clmulepi64_si128(yx, hx, 0x11);
t2 = _mm_clmulepi64_si128(y2, h2, 0x00);
t2 = _mm_xor_si128(t2, _mm_xor_si128(t0, t1));
v0 = t0;
v1 = _mm_xor_si128(_mm_shuffle_epi32(t0, 0x0E), t2);
v2 = _mm_xor_si128(t1, _mm_shuffle_epi32(t2, 0x0E));
v3 = _mm_shuffle_epi32(t1, 0x0E);
/*
* Do the corrective 1-bit shift (255->256).
*/
v3 = _mm_or_si128(
_mm_slli_epi64(v3, 1),
_mm_srli_epi64(v2, 63));
v2 = _mm_or_si128(
_mm_slli_epi64(v2, 1),
_mm_srli_epi64(v1, 63));
v1 = _mm_or_si128(
_mm_slli_epi64(v1, 1),
_mm_srli_epi64(v0, 63));
v0 = _mm_slli_epi64(v0, 1);
/*
* Perform polynomial reduction into GF(2^128).
*/
v2 = _mm_xor_si128(
v2,
_mm_xor_si128(
_mm_xor_si128(
v0,
_mm_srli_epi64(v0, 1)),
_mm_xor_si128(
_mm_srli_epi64(v0, 2),
_mm_srli_epi64(v0, 7))));
v1 = _mm_xor_si128(
_mm_xor_si128(
v1,
_mm_slli_epi64(v0, 63)),
_mm_xor_si128(
_mm_slli_epi64(v0, 62),
_mm_slli_epi64(v0, 57)));
v3 = _mm_xor_si128(
v3,
_mm_xor_si128(
_mm_xor_si128(
v1,
_mm_srli_epi64(v1, 1)),
_mm_xor_si128(
_mm_srli_epi64(v1, 2),
_mm_srli_epi64(v1, 7))));
v2 = _mm_xor_si128(
_mm_xor_si128(
v2,
_mm_slli_epi64(v1, 63)),
_mm_xor_si128(
_mm_slli_epi64(v1, 62),
_mm_slli_epi64(v1, 57)));
/*
* We reduced toward the high words (v2 and v3), which
* are the new value for y.
*/
yx = _mm_unpacklo_epi64(v2, v3);
}
yx = _mm_shuffle_epi8(yx, byteswap_index);
_mm_storeu_si128(y, yx);
}
/*
* Test CPU support for PCLMULQDQ.
*/
static int
pclmul_supported(void)
{
/*
* Bit mask for features in ECX:
* 1 PCLMULQDQ support
*/
#define MASK 0x00000002
#if BR_AES_X86NI_GCC
unsigned eax, ebx, ecx, edx;
if (__get_cpuid(1, &eax, &ebx, &ecx, &edx)) {
return (ecx & MASK) == MASK;
} else {
return 0;
}
#elif BR_AES_X86NI_MSC
int info[4];
__cpuid(info, 1);
return ((uint32_t)info[2] & MASK) == MASK;
#else
return 0;
#endif
#undef MASK
}
/* see bearssl_hash.h */
br_ghash
br_ghash_pclmul_get(void)
{
return pclmul_supported() ? &br_ghash_pclmul : 0;
}
#else
/* see bearssl_hash.h */
br_ghash
br_ghash_pclmul_get(void)
{
return 0;
}
#endif

View file

@ -105,6 +105,55 @@
#endif
#endif
/*
* Set BR_LOMUL on platforms where it makes sense.
*/
#ifndef BR_LOMUL
#if BR_ARMEL_CORTEX_GCC
#define BR_LOMUL 1
#endif
#endif
/*
* Determine whether x86 AES instructions are understood by the compiler.
*/
#ifndef BR_AES_X86NI
#if (__i386__ || __x86_64__) \
&& ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) \
|| (__clang_major__ > 3 \
|| (__clang_major__ == 3 && __clang_minor__ >= 7)))
#define BR_AES_X86NI 1
#elif (_M_IX86 || _M_X64) && (_MSC_VER >= 1700)
#define BR_AES_X86NI 1
#endif
#endif
/*
* If we use x86 AES instruction, determine the compiler brand.
*/
#if BR_AES_X86NI
#ifndef BR_AES_X86NI_GCC
#if __GNUC__
#define BR_AES_X86NI_GCC 1
#endif
#endif
#ifndef BR_AES_X86NI_MSC
#if _MSC_VER >= 1700
#define BR_AES_X86NI_MSC 1
#endif
#endif
#endif
/*
* A macro to tag a function with a "target" attribute (for GCC and Clang).
*/
#if BR_AES_X86NI_GCC
#define BR_TARGET(x) __attribute__((target(x)))
#else
#define BR_TARGET(x)
#endif
/* ==================================================================== */
/*
* Encoding/decoding functions.
@ -1077,6 +1126,10 @@ void br_i31_mulacc(uint32_t *d, const uint32_t *a, const uint32_t *b);
/* ==================================================================== */
/*
* FIXME: document "i15" functions.
*/
static inline void
br_i15_zero(uint16_t *x, uint16_t bit_len)
{
@ -1424,6 +1477,27 @@ unsigned br_aes_ct64_keysched(uint64_t *comp_skey,
void br_aes_ct64_skey_expand(uint64_t *skey,
unsigned num_rounds, const uint64_t *comp_skey);
/*
* Test support for AES-NI opcodes.
*/
int br_aes_x86ni_supported(void);
/*
* AES key schedule, using x86 AES-NI instructions. This yields the
* subkeys in the encryption direction. Number of rounds is returned.
* Key size MUST be 16, 24 or 32 bytes; otherwise, 0 is returned.
*/
unsigned br_aes_x86ni_keysched_enc(unsigned char *skni,
const void *key, size_t len);
/*
* AES key schedule, using x86 AES-NI instructions. This yields the
* subkeys in the decryption direction. Number of rounds is returned.
* Key size MUST be 16, 24 or 32 bytes; otherwise, 0 is returned.
*/
unsigned br_aes_x86ni_keysched_dec(unsigned char *skni,
const void *key, size_t len);
/* ==================================================================== */
/*
* RSA.

View file

@ -41,6 +41,7 @@ br_i15_modpow_opt(uint16_t *x,
*/
mwlen = (m[0] + 31) >> 4;
mlen = mwlen * sizeof m[0];
mwlen += (mwlen & 1);
t1 = tmp;
t2 = tmp + mwlen;
@ -86,7 +87,7 @@ br_i15_modpow_opt(uint16_t *x,
* one word-sized shift.
*/
br_i15_zero(x, m[0]);
x[mwlen - 1] = 1;
x[(m[0] + 15) >> 4] = 1;
br_i15_muladd_small(x, 0, m);
/*

View file

@ -42,7 +42,99 @@ br_i15_montymul(uint16_t *d, const uint16_t *x, const uint16_t *y,
xu = x[u + 1];
f = MUL15((d[1] + MUL15(x[u + 1], y[1])) & 0x7FFF, m0i)
& 0x7FFF;
#if BR_ARMEL_CORTEXM_GCC
if (len4 != 0) {
uint16_t *limit;
limit = d + len4;
asm volatile (
"\n\
@ carry: r=r2 \n\
@ multipliers: xu=r3 f=r4 \n\
@ base registers: d+v=r5 y+v=r6 m+v=r7 \n\
@ r8 contains 0x7FFF \n\
@ r9 contains d+len4 \n\
ldr r0, %[limit] \n\
ldr r3, %[xu] \n\
mov r9, r0 \n\
ldr r4, %[f] \n\
eor r2, r2 \n\
ldr r5, %[d] \n\
sub r1, r2, #1 \n\
ldr r6, %[y] \n\
lsr r1, r1, #17 \n\
ldr r7, %[m] \n\
mov r8, r1 \n\
loop%=: \n\
ldrh r0, [r6, #2] \n\
ldrh r1, [r7, #2] \n\
mul r0, r3 \n\
mul r1, r4 \n\
add r2, r0, r2 \n\
ldrh r0, [r5, #2] \n\
add r2, r1, r2 \n\
mov r1, r8 \n\
add r2, r0, r2 \n\
and r1, r2 \n\
lsr r2, r2, #15 \n\
strh r1, [r5, #0] \n\
\n\
ldrh r0, [r6, #4] \n\
ldrh r1, [r7, #4] \n\
mul r0, r3 \n\
mul r1, r4 \n\
add r2, r0, r2 \n\
ldrh r0, [r5, #4] \n\
add r2, r1, r2 \n\
mov r1, r8 \n\
add r2, r0, r2 \n\
and r1, r2 \n\
lsr r2, r2, #15 \n\
strh r1, [r5, #2] \n\
\n\
ldrh r0, [r6, #6] \n\
ldrh r1, [r7, #6] \n\
mul r0, r3 \n\
mul r1, r4 \n\
add r2, r0, r2 \n\
ldrh r0, [r5, #6] \n\
add r2, r1, r2 \n\
mov r1, r8 \n\
add r2, r0, r2 \n\
and r1, r2 \n\
lsr r2, r2, #15 \n\
strh r1, [r5, #4] \n\
\n\
ldrh r0, [r6, #8] \n\
ldrh r1, [r7, #8] \n\
mul r0, r3 \n\
mul r1, r4 \n\
add r2, r0, r2 \n\
ldrh r0, [r5, #8] \n\
add r2, r1, r2 \n\
mov r1, r8 \n\
add r2, r0, r2 \n\
and r1, r2 \n\
lsr r2, r2, #15 \n\
strh r1, [r5, #6] \n\
\n\
add r5, r5, #8 \n\
add r6, r6, #8 \n\
add r7, r7, #8 \n\
cmp r5, r9 \n\
bne loop%= \n\
\n\
str r2, %[carry] \n\
"
: [carry] "=m" (r)
: [xu] "m" (xu), [f] "m" (f), [d] "m" (d), [y] "m" (y),
[m] "m" (m), [limit] "m" (limit)
: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
} else {
r = 0;
}
v = len4;
#else
r = 0;
for (v = 0; v < len4; v += 4) {
uint32_t z;
@ -64,6 +156,7 @@ br_i15_montymul(uint16_t *d, const uint16_t *x, const uint16_t *y,
r = z >> 15;
d[v + 3] = z & 0x7FFF;
}
#endif
for (; v < len; v ++) {
uint32_t z;

View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/* see bearssl_rsa.h */
br_rsa_pkcs1_sign
br_rsa_pkcs1_sign_get_default(void)
{
#if BR_LOMUL
return &br_rsa_i15_pkcs1_sign;
#else
return &br_rsa_i31_pkcs1_sign;
#endif
}

View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/* see bearssl_rsa.h */
br_rsa_pkcs1_vrfy
br_rsa_pkcs1_vrfy_get_default(void)
{
#if BR_LOMUL
return &br_rsa_i15_pkcs1_vrfy;
#else
return &br_rsa_i31_pkcs1_vrfy;
#endif
}

View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/* see bearssl_rsa.h */
br_rsa_private
br_rsa_private_get_default(void)
{
#if BR_LOMUL
return &br_rsa_i15_private;
#else
return &br_rsa_i31_private;
#endif
}

36
src/rsa/rsa_default_pub.c Normal file
View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/* see bearssl_rsa.h */
br_rsa_public
br_rsa_public_get_default(void)
{
#if BR_LOMUL
return &br_rsa_i15_public;
#else
return &br_rsa_i31_public;
#endif
}

View file

@ -24,7 +24,7 @@
#include "inner.h"
#define U (1 + ((BR_MAX_RSA_FACTOR + 14) / 15))
#define U (2 + ((BR_MAX_RSA_FACTOR + 14) / 15))
#define TLEN (8 * U)
/* obsolete
@ -54,7 +54,7 @@ br_rsa_i15_private(unsigned char *x, const br_rsa_private_key *sk)
size_t fwlen;
uint16_t p0i, q0i;
size_t xlen;
uint16_t tmp[TLEN];
uint16_t tmp[1 + TLEN];
long z;
uint16_t *mp, *mq, *s1, *s2, *t1, *t2, *t3;
uint32_t r;
@ -86,6 +86,10 @@ br_rsa_i15_private(unsigned char *x, const br_rsa_private_key *sk)
z -= 15;
fwlen ++;
}
/*
* Round up the word length to an even number.
*/
fwlen += (fwlen & 1);
/*
* We need to fit at least 6 values in the stack buffer.
@ -100,34 +104,41 @@ br_rsa_i15_private(unsigned char *x, const br_rsa_private_key *sk)
xlen = (sk->n_bitlen + 7) >> 3;
/*
* Decode q.
* Ensure 32-bit alignment for value words.
*/
mq = tmp;
if (((uintptr_t)mq & 2) == 0) {
mq ++;
}
/*
* Decode q.
*/
br_i15_decode(mq, q, qlen);
/*
* Compute s2 = x^dq mod q.
*/
q0i = br_i15_ninv15(mq[1]);
s2 = tmp + fwlen;
s2 = mq + fwlen;
br_i15_decode_reduce(s2, x, xlen, mq);
r = br_i15_modpow_opt(s2, sk->dq, sk->dqlen, mq, q0i,
tmp + 2 * fwlen, TLEN - 2 * fwlen);
mq + 2 * fwlen, TLEN - 2 * fwlen);
/*
* Decode p.
*/
mp = tmp + 2 * fwlen;
mp = mq + 2 * fwlen;
br_i15_decode(mp, p, plen);
/*
* Compute s1 = x^dq mod q.
*/
p0i = br_i15_ninv15(mp[1]);
s1 = tmp + 3 * fwlen;
s1 = mq + 3 * fwlen;
br_i15_decode_reduce(s1, x, xlen, mp);
r &= br_i15_modpow_opt(s1, sk->dp, sk->dplen, mp, p0i,
tmp + 4 * fwlen, TLEN - 4 * fwlen);
mq + 4 * fwlen, TLEN - 4 * fwlen);
/*
* Compute:
@ -142,8 +153,8 @@ br_rsa_i15_private(unsigned char *x, const br_rsa_private_key *sk)
* inverse of q modulo p), we also tolerate improperly large
* values for this parameter.
*/
t1 = tmp + 4 * fwlen;
t2 = tmp + 5 * fwlen;
t1 = mq + 4 * fwlen;
t2 = mq + 5 * fwlen;
br_i15_reduce(t2, s2, mp);
br_i15_add(s1, mp, br_i15_sub(s1, t2, 1));
br_i15_to_monty(s1, mp);

View file

@ -28,7 +28,7 @@
* As a strict minimum, we need four buffers that can hold a
* modular integer.
*/
#define TLEN (4 * (1 + ((BR_MAX_RSA_SIZE + 14) / 15)))
#define TLEN (4 * (2 + ((BR_MAX_RSA_SIZE + 14) / 15)))
/* see bearssl_rsa.h */
uint32_t
@ -37,7 +37,7 @@ br_rsa_i15_public(unsigned char *x, size_t xlen,
{
const unsigned char *n;
size_t nlen;
uint16_t tmp[TLEN];
uint16_t tmp[1 + TLEN];
uint16_t *m, *a, *t;
size_t fwlen;
long z;
@ -63,15 +63,25 @@ br_rsa_i15_public(unsigned char *x, size_t xlen,
z -= 15;
fwlen ++;
}
/*
* Round up length to an even number.
*/
fwlen += (fwlen & 1);
/*
* The modulus gets decoded into m[].
* The value to exponentiate goes into a[].
* The temporaries for modular exponentiations are in t[].
*
* We want the first value word of each integer to be aligned
* on a 32-bit boundary.
*/
m = tmp;
a = tmp + fwlen;
t = tmp + 2 * fwlen;
if (((uintptr_t)m & 2) == 0) {
m ++;
}
a = m + fwlen;
t = m + 2 * fwlen;
/*
* Decode the modulus.

View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/* see bearssl_ssl.h */
void
br_ssl_client_set_default_rsapub(br_ssl_client_context *cc)
{
#if BR_LOMUL
br_ssl_client_set_rsapub(cc, &br_rsa_i15_public);
#else
br_ssl_client_set_rsapub(cc, &br_rsa_i31_public);
#endif
}

View file

@ -125,13 +125,13 @@ br_ssl_client_init_full(br_ssl_client_context *cc,
*/
br_ssl_engine_set_suites(&cc->eng, suites,
(sizeof suites) / (sizeof suites[0]));
br_ssl_client_set_rsapub(cc, &br_rsa_i31_public);
br_ssl_engine_set_rsavrfy(&cc->eng, &br_rsa_i31_pkcs1_vrfy);
br_ssl_engine_set_ec(&cc->eng, &br_ec_all_m15);
br_ssl_engine_set_ecdsa(&cc->eng, &br_ecdsa_i31_vrfy_asn1);
br_x509_minimal_set_rsa(xc, &br_rsa_i31_pkcs1_vrfy);
br_ssl_client_set_default_rsapub(cc);
br_ssl_engine_set_default_rsavrfy(&cc->eng);
br_ssl_engine_set_default_ecdsa(&cc->eng);
br_x509_minimal_set_rsa(xc, br_ssl_engine_get_rsavrfy(&cc->eng));
br_x509_minimal_set_ecdsa(xc,
&br_ec_all_m15, &br_ecdsa_i31_vrfy_asn1);
br_ssl_engine_get_ec(&cc->eng),
br_ssl_engine_get_ecdsa(&cc->eng));
/*
* Set supported hash functions, for the SSL engine and for the
@ -158,47 +158,11 @@ br_ssl_client_init_full(br_ssl_client_context *cc,
br_ssl_engine_set_prf_sha384(&cc->eng, &br_tls12_sha384_prf);
/*
* Symmetric encryption. We use the "constant-time"
* implementations, which are the safest.
*
* On architectures detected as "64-bit", use the 64-bit
* versions (aes_ct64, ghash_ctmul64).
* Symmetric encryption. We use the "default" implementations
* (fastest among constant-time implementations).
*/
#if BR_64
br_ssl_engine_set_aes_cbc(&cc->eng,
&br_aes_ct64_cbcenc_vtable,
&br_aes_ct64_cbcdec_vtable);
br_ssl_engine_set_aes_ctr(&cc->eng,
&br_aes_ct64_ctr_vtable);
br_ssl_engine_set_ghash(&cc->eng,
&br_ghash_ctmul64);
#else
br_ssl_engine_set_aes_cbc(&cc->eng,
&br_aes_ct_cbcenc_vtable,
&br_aes_ct_cbcdec_vtable);
br_ssl_engine_set_aes_ctr(&cc->eng,
&br_aes_ct_ctr_vtable);
br_ssl_engine_set_ghash(&cc->eng,
&br_ghash_ctmul);
#endif
br_ssl_engine_set_des_cbc(&cc->eng,
&br_des_ct_cbcenc_vtable,
&br_des_ct_cbcdec_vtable);
br_ssl_engine_set_chacha20(&cc->eng,
&br_chacha20_ct_run);
br_ssl_engine_set_poly1305(&cc->eng,
&br_poly1305_ctmul_run);
/*
* Set the SSL record engines (CBC, GCM).
*/
br_ssl_engine_set_cbc(&cc->eng,
&br_sslrec_in_cbc_vtable,
&br_sslrec_out_cbc_vtable);
br_ssl_engine_set_gcm(&cc->eng,
&br_sslrec_in_gcm_vtable,
&br_sslrec_out_gcm_vtable);
br_ssl_engine_set_chapol(&cc->eng,
&br_sslrec_in_chapol_vtable,
&br_sslrec_out_chapol_vtable);
br_ssl_engine_set_default_aes_cbc(&cc->eng);
br_ssl_engine_set_default_aes_gcm(&cc->eng);
br_ssl_engine_set_default_des_cbc(&cc->eng);
br_ssl_engine_set_default_chapol(&cc->eng);
}

View file

@ -0,0 +1,56 @@
/*
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/* see bearssl_ssl.h */
void
br_ssl_engine_set_default_aes_cbc(br_ssl_engine_context *cc)
{
#if BR_AES_X86NI
const br_block_cbcenc_class *ienc;
const br_block_cbcdec_class *idec;
#endif
br_ssl_engine_set_cbc(cc,
&br_sslrec_in_cbc_vtable,
&br_sslrec_out_cbc_vtable);
#if BR_AES_X86NI
ienc = br_aes_x86ni_cbcenc_get_vtable();
idec = br_aes_x86ni_cbcdec_get_vtable();
if (ienc != NULL && idec != NULL) {
br_ssl_engine_set_aes_cbc(cc, ienc, idec);
return;
}
#endif
#if BR_64
br_ssl_engine_set_aes_cbc(cc,
&br_aes_ct64_cbcenc_vtable,
&br_aes_ct64_cbcdec_vtable);
#else
br_ssl_engine_set_aes_cbc(cc,
&br_aes_ct_cbcenc_vtable,
&br_aes_ct_cbcdec_vtable);
#endif
}

View file

@ -0,0 +1,71 @@
/*
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/* see bearssl_ssl.h */
void
br_ssl_engine_set_default_aes_gcm(br_ssl_engine_context *cc)
{
#if BR_AES_X86NI
const br_block_ctr_class *ictr;
br_ghash ighash;
#endif
br_ssl_engine_set_gcm(cc,
&br_sslrec_in_gcm_vtable,
&br_sslrec_out_gcm_vtable);
#if BR_AES_X86NI
ictr = br_aes_x86ni_ctr_get_vtable();
if (ictr != NULL) {
br_ssl_engine_set_aes_ctr(cc, ictr);
} else {
#if BR_64
br_ssl_engine_set_aes_ctr(cc, &br_aes_ct64_ctr_vtable);
#else
br_ssl_engine_set_aes_ctr(cc, &br_aes_ct_ctr_vtable);
#endif
}
#else
#if BR_64
br_ssl_engine_set_aes_ctr(cc, &br_aes_ct64_ctr_vtable);
#else
br_ssl_engine_set_aes_ctr(cc, &br_aes_ct_ctr_vtable);
#endif
#endif
#if BR_AES_X86NI
ighash = br_ghash_pclmul_get();
if (ighash != 0) {
br_ssl_engine_set_ghash(cc, ighash);
return;
}
#endif
#if BR_LOMUL
br_ssl_engine_set_ghash(cc, &br_ghash_ctmul32);
#elif BR_64
br_ssl_engine_set_ghash(cc, &br_ghash_ctmul64);
#else
br_ssl_engine_set_ghash(cc, &br_ghash_ctmul);
#endif
}

View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/* see bearssl_ssl.h */
void
br_ssl_engine_set_default_chapol(br_ssl_engine_context *cc)
{
br_ssl_engine_set_chapol(cc,
&br_sslrec_in_chapol_vtable,
&br_sslrec_out_chapol_vtable);
br_ssl_engine_set_chacha20(cc, &br_chacha20_ct_run);
#if BR_LOMUL
br_ssl_engine_set_poly1305(cc, &br_poly1305_ctmul32_run);
#else
br_ssl_engine_set_poly1305(cc, &br_poly1305_ctmul_run);
#endif
}

View file

@ -0,0 +1,37 @@
/*
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/* see bearssl_ssl.h */
void
br_ssl_engine_set_default_des_cbc(br_ssl_engine_context *cc)
{
br_ssl_engine_set_cbc(cc,
&br_sslrec_in_cbc_vtable,
&br_sslrec_out_cbc_vtable);
br_ssl_engine_set_des_cbc(cc,
&br_des_ct_cbcenc_vtable,
&br_des_ct_cbcdec_vtable);
}

View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/* see bearssl_ssl.h */
void
br_ssl_engine_set_default_ec(br_ssl_engine_context *cc)
{
#if BR_LOMUL
br_ssl_engine_set_ec(cc, &br_ec_all_m15);
#else
br_ssl_engine_set_ec(cc, &br_ec_all_m31);
#endif
}

View file

@ -0,0 +1,38 @@
/*
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/* see bearssl_ssl.h */
void
br_ssl_engine_set_default_ecdsa(br_ssl_engine_context *cc)
{
#if BR_LOMUL
br_ssl_engine_set_ec(cc, &br_ec_all_m15);
br_ssl_engine_set_ecdsa(cc, &br_ecdsa_i15_vrfy_asn1);
#else
br_ssl_engine_set_ec(cc, &br_ec_all_m31);
br_ssl_engine_set_ecdsa(cc, &br_ecdsa_i31_vrfy_asn1);
#endif
}

View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/* see bearssl_ssl.h */
void
br_ssl_engine_set_default_rsavrfy(br_ssl_engine_context *cc)
{
#if BR_LOMUL
br_ssl_engine_set_rsavrfy(cc, &br_rsa_i15_pkcs1_vrfy);
#else
br_ssl_engine_set_rsavrfy(cc, &br_rsa_i31_pkcs1_vrfy);
#endif
}

View file

@ -99,7 +99,7 @@ br_ssl_server_init_full_ec(br_ssl_server_context *cc,
*/
br_ssl_engine_set_suites(&cc->eng, suites,
(sizeof suites) / (sizeof suites[0]));
br_ssl_engine_set_ec(&cc->eng, &br_ec_all_m15);
br_ssl_engine_set_default_ec(&cc->eng);
/*
* Set the "server policy": handler for the certificate chain
@ -108,7 +108,13 @@ br_ssl_server_init_full_ec(br_ssl_server_context *cc,
br_ssl_server_set_single_ec(cc, chain, chain_len, sk,
BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN,
cert_issuer_key_type,
&br_ec_all_m15, br_ecdsa_i31_sign_asn1);
br_ssl_engine_get_ec(&cc->eng),
#if BR_LOMUL
br_ecdsa_i15_sign_asn1
#else
br_ecdsa_i31_sign_asn1
#endif
);
/*
* Set supported hash functions.
@ -128,47 +134,10 @@ br_ssl_server_init_full_ec(br_ssl_server_context *cc,
br_ssl_engine_set_prf_sha384(&cc->eng, &br_tls12_sha384_prf);
/*
* Symmetric encryption. We use the "constant-time"
* implementations, which are the safest.
*
* On architectures detected as "64-bit", use the 64-bit
* versions (aes_ct64, ghash_ctmul64).
* Symmetric encryption.
*/
#if BR_64
br_ssl_engine_set_aes_cbc(&cc->eng,
&br_aes_ct64_cbcenc_vtable,
&br_aes_ct64_cbcdec_vtable);
br_ssl_engine_set_aes_ctr(&cc->eng,
&br_aes_ct64_ctr_vtable);
br_ssl_engine_set_ghash(&cc->eng,
&br_ghash_ctmul64);
#else
br_ssl_engine_set_aes_cbc(&cc->eng,
&br_aes_ct_cbcenc_vtable,
&br_aes_ct_cbcdec_vtable);
br_ssl_engine_set_aes_ctr(&cc->eng,
&br_aes_ct_ctr_vtable);
br_ssl_engine_set_ghash(&cc->eng,
&br_ghash_ctmul);
#endif
br_ssl_engine_set_des_cbc(&cc->eng,
&br_des_ct_cbcenc_vtable,
&br_des_ct_cbcdec_vtable);
br_ssl_engine_set_chacha20(&cc->eng,
&br_chacha20_ct_run);
br_ssl_engine_set_poly1305(&cc->eng,
&br_poly1305_ctmul_run);
/*
* Set the SSL record engines (CBC, GCM).
*/
br_ssl_engine_set_cbc(&cc->eng,
&br_sslrec_in_cbc_vtable,
&br_sslrec_out_cbc_vtable);
br_ssl_engine_set_gcm(&cc->eng,
&br_sslrec_in_gcm_vtable,
&br_sslrec_out_gcm_vtable);
br_ssl_engine_set_chapol(&cc->eng,
&br_sslrec_in_chapol_vtable,
&br_sslrec_out_chapol_vtable);
br_ssl_engine_set_default_aes_cbc(&cc->eng);
br_ssl_engine_set_default_aes_gcm(&cc->eng);
br_ssl_engine_set_default_des_cbc(&cc->eng);
br_ssl_engine_set_default_chapol(&cc->eng);
}

View file

@ -89,7 +89,7 @@ br_ssl_server_init_full_rsa(br_ssl_server_context *cc,
*/
br_ssl_engine_set_suites(&cc->eng, suites,
(sizeof suites) / (sizeof suites[0]));
br_ssl_engine_set_ec(&cc->eng, &br_ec_all_m15);
br_ssl_engine_set_default_ec(&cc->eng);
/*
* Set the "server policy": handler for the certificate chain
@ -97,7 +97,12 @@ br_ssl_server_init_full_rsa(br_ssl_server_context *cc,
*/
br_ssl_server_set_single_rsa(cc, chain, chain_len, sk,
BR_KEYTYPE_KEYX | BR_KEYTYPE_SIGN,
br_rsa_i31_private, br_rsa_i31_pkcs1_sign);
#if BR_LOMUL
br_rsa_i15_private, br_rsa_i15_pkcs1_sign
#else
br_rsa_i31_private, br_rsa_i31_pkcs1_sign
#endif
);
/*
* Set supported hash functions.
@ -117,47 +122,10 @@ br_ssl_server_init_full_rsa(br_ssl_server_context *cc,
br_ssl_engine_set_prf_sha384(&cc->eng, &br_tls12_sha384_prf);
/*
* Symmetric encryption. We use the "constant-time"
* implementations, which are the safest.
*
* On architectures detected as "64-bit", use the 64-bit
* versions (aes_ct64, ghash_ctmul64).
* Symmetric encryption.
*/
#if BR_64
br_ssl_engine_set_aes_cbc(&cc->eng,
&br_aes_ct64_cbcenc_vtable,
&br_aes_ct64_cbcdec_vtable);
br_ssl_engine_set_aes_ctr(&cc->eng,
&br_aes_ct64_ctr_vtable);
br_ssl_engine_set_ghash(&cc->eng,
&br_ghash_ctmul64);
#else
br_ssl_engine_set_aes_cbc(&cc->eng,
&br_aes_ct_cbcenc_vtable,
&br_aes_ct_cbcdec_vtable);
br_ssl_engine_set_aes_ctr(&cc->eng,
&br_aes_ct_ctr_vtable);
br_ssl_engine_set_ghash(&cc->eng,
&br_ghash_ctmul);
#endif
br_ssl_engine_set_des_cbc(&cc->eng,
&br_des_ct_cbcenc_vtable,
&br_des_ct_cbcdec_vtable);
br_ssl_engine_set_chacha20(&cc->eng,
&br_chacha20_ct_run);
br_ssl_engine_set_poly1305(&cc->eng,
&br_poly1305_ctmul_run);
/*
* Set the SSL record engines (CBC, GCM, ChaCha20).
*/
br_ssl_engine_set_cbc(&cc->eng,
&br_sslrec_in_cbc_vtable,
&br_sslrec_out_cbc_vtable);
br_ssl_engine_set_gcm(&cc->eng,
&br_sslrec_in_gcm_vtable,
&br_sslrec_out_gcm_vtable);
br_ssl_engine_set_chapol(&cc->eng,
&br_sslrec_in_chapol_vtable,
&br_sslrec_out_chapol_vtable);
br_ssl_engine_set_default_aes_cbc(&cc->eng);
br_ssl_engine_set_default_aes_gcm(&cc->eng);
br_ssl_engine_set_default_des_cbc(&cc->eng);
br_ssl_engine_set_default_chapol(&cc->eng);
}

View file

@ -65,18 +65,7 @@ br_ssl_server_init_mine2c(br_ssl_server_context *cc,
br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf);
/*
* Symmetric encryption. We use the "constant-time"
* implementations, which are the safest.
* Symmetric encryption.
*/
br_ssl_engine_set_chacha20(&cc->eng,
&br_chacha20_ct_run);
br_ssl_engine_set_poly1305(&cc->eng,
&br_poly1305_ctmul_run);
/*
* Set the SSL record engines.
*/
br_ssl_engine_set_chapol(&cc->eng,
&br_sslrec_in_chapol_vtable,
&br_sslrec_out_chapol_vtable);
br_ssl_engine_set_default_chapol(&cc->eng);
}

View file

@ -65,28 +65,7 @@ br_ssl_server_init_mine2g(br_ssl_server_context *cc,
br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf);
/*
* Symmetric encryption. We use the "constant-time"
* implementations, which are the safest.
*
* On architectures detected as "64-bit", use the 64-bit
* versions (aes_ct64, ghash_ctmul64).
* Symmetric encryption.
*/
#if BR_64
br_ssl_engine_set_aes_ctr(&cc->eng,
&br_aes_ct64_ctr_vtable);
br_ssl_engine_set_ghash(&cc->eng,
&br_ghash_ctmul64);
#else
br_ssl_engine_set_aes_ctr(&cc->eng,
&br_aes_ct_ctr_vtable);
br_ssl_engine_set_ghash(&cc->eng,
&br_ghash_ctmul);
#endif
/*
* Set the SSL record engines (CBC, GCM).
*/
br_ssl_engine_set_gcm(&cc->eng,
&br_sslrec_in_gcm_vtable,
&br_sslrec_out_gcm_vtable);
br_ssl_engine_set_default_aes_gcm(&cc->eng);
}

View file

@ -65,21 +65,7 @@ br_ssl_server_init_minf2c(br_ssl_server_context *cc,
br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf);
/*
* Symmetric encryption. We use the "constant-time"
* implementations, which are the safest.
*
* On architectures detected as "64-bit", use the 64-bit
* versions (aes_ct64, ghash_ctmul64).
* Symmetric encryption.
*/
br_ssl_engine_set_chacha20(&cc->eng,
&br_chacha20_ct_run);
br_ssl_engine_set_poly1305(&cc->eng,
&br_poly1305_ctmul_run);
/*
* Set the SSL record engines.
*/
br_ssl_engine_set_chapol(&cc->eng,
&br_sslrec_in_chapol_vtable,
&br_sslrec_out_chapol_vtable);
br_ssl_engine_set_default_chapol(&cc->eng);
}

View file

@ -65,28 +65,7 @@ br_ssl_server_init_minf2g(br_ssl_server_context *cc,
br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf);
/*
* Symmetric encryption. We use the "constant-time"
* implementations, which are the safest.
*
* On architectures detected as "64-bit", use the 64-bit
* versions (aes_ct64, ghash_ctmul64).
* Symmetric encryption.
*/
#if BR_64
br_ssl_engine_set_aes_ctr(&cc->eng,
&br_aes_ct64_ctr_vtable);
br_ssl_engine_set_ghash(&cc->eng,
&br_ghash_ctmul64);
#else
br_ssl_engine_set_aes_ctr(&cc->eng,
&br_aes_ct_ctr_vtable);
br_ssl_engine_set_ghash(&cc->eng,
&br_ghash_ctmul);
#endif
/*
* Set the SSL record engines (CBC, GCM).
*/
br_ssl_engine_set_gcm(&cc->eng,
&br_sslrec_in_gcm_vtable,
&br_sslrec_out_gcm_vtable);
br_ssl_engine_set_default_aes_gcm(&cc->eng);
}

View file

@ -64,28 +64,7 @@ br_ssl_server_init_minr2g(br_ssl_server_context *cc,
br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf);
/*
* Symmetric encryption. We use the "constant-time"
* implementations, which are the safest.
*
* On architectures detected as "64-bit", use the 64-bit
* versions (aes_ct64, ghash_ctmul64).
* Symmetric encryption.
*/
#if BR_64
br_ssl_engine_set_aes_ctr(&cc->eng,
&br_aes_ct64_ctr_vtable);
br_ssl_engine_set_ghash(&cc->eng,
&br_ghash_ctmul64);
#else
br_ssl_engine_set_aes_ctr(&cc->eng,
&br_aes_ct_ctr_vtable);
br_ssl_engine_set_ghash(&cc->eng,
&br_ghash_ctmul);
#endif
/*
* Set the SSL record engines (CBC, GCM).
*/
br_ssl_engine_set_gcm(&cc->eng,
&br_sslrec_in_gcm_vtable,
&br_sslrec_out_gcm_vtable);
br_ssl_engine_set_default_aes_gcm(&cc->eng);
}

View file

@ -64,28 +64,7 @@ br_ssl_server_init_minu2g(br_ssl_server_context *cc,
br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf);
/*
* Symmetric encryption. We use the "constant-time"
* implementations, which are the safest.
*
* On architectures detected as "64-bit", use the 64-bit
* versions (aes_ct64, ghash_ctmul64).
* Symmetric encryption.
*/
#if BR_64
br_ssl_engine_set_aes_ctr(&cc->eng,
&br_aes_ct64_ctr_vtable);
br_ssl_engine_set_ghash(&cc->eng,
&br_ghash_ctmul64);
#else
br_ssl_engine_set_aes_ctr(&cc->eng,
&br_aes_ct_ctr_vtable);
br_ssl_engine_set_ghash(&cc->eng,
&br_ghash_ctmul);
#endif
/*
* Set the SSL record engines (CBC, GCM).
*/
br_ssl_engine_set_gcm(&cc->eng,
&br_sslrec_in_gcm_vtable,
&br_sslrec_out_gcm_vtable);
br_ssl_engine_set_default_aes_gcm(&cc->eng);
}

View file

@ -64,28 +64,7 @@ br_ssl_server_init_minv2g(br_ssl_server_context *cc,
br_ssl_engine_set_prf_sha256(&cc->eng, &br_tls12_sha256_prf);
/*
* Symmetric encryption. We use the "constant-time"
* implementations, which are the safest.
*
* On architectures detected as "64-bit", use the 64-bit
* versions (aes_ct64, ghash_ctmul64).
* Symmetric encryption.
*/
#if BR_64
br_ssl_engine_set_aes_ctr(&cc->eng,
&br_aes_ct64_ctr_vtable);
br_ssl_engine_set_ghash(&cc->eng,
&br_ghash_ctmul64);
#else
br_ssl_engine_set_aes_ctr(&cc->eng,
&br_aes_ct_ctr_vtable);
br_ssl_engine_set_ghash(&cc->eng,
&br_ghash_ctmul);
#endif
/*
* Set the SSL record engines (CBC, GCM).
*/
br_ssl_engine_set_gcm(&cc->eng,
&br_sslrec_in_gcm_vtable,
&br_sslrec_out_gcm_vtable);
br_ssl_engine_set_default_aes_gcm(&cc->eng);
}

263
src/symcipher/aes_x86ni.c Normal file
View file

@ -0,0 +1,263 @@
/*
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
/*
* This code contains the AES key schedule implementation using the
* AES-NI opcodes.
*/
#if BR_AES_X86NI
#if BR_AES_X86NI_GCC
#include <wmmintrin.h>
#include <cpuid.h>
#endif
#if BR_AES_X86NI_MSC
#include <intrin.h>
#endif
/* see inner.h */
int
br_aes_x86ni_supported(void)
{
/*
* Bit mask for features in ECX:
* 19 SSE4.1 (used for _mm_insert_epi32(), for AES-CTR)
* 25 AES-NI
*/
#define MASK 0x02080000
#if BR_AES_X86NI_GCC
unsigned eax, ebx, ecx, edx;
if (__get_cpuid(1, &eax, &ebx, &ecx, &edx)) {
return (ecx & MASK) == MASK;
} else {
return 0;
}
#elif BR_AES_X86NI_MSC
int info[4];
__cpuid(info, 1);
return ((uint32_t)info[2] & MASK) == MASK;
#else
return 0;
#endif
#undef MASK
}
BR_TARGET("sse2,aes")
static inline __m128i
expand_step128(__m128i k, __m128i k2)
{
k = _mm_xor_si128(k, _mm_slli_si128(k, 4));
k = _mm_xor_si128(k, _mm_slli_si128(k, 4));
k = _mm_xor_si128(k, _mm_slli_si128(k, 4));
k2 = _mm_shuffle_epi32(k2, 0xFF);
return _mm_xor_si128(k, k2);
}
BR_TARGET("sse2,aes")
static inline void
expand_step192(__m128i *t1, __m128i *t2, __m128i *t3)
{
__m128i t4;
*t2 = _mm_shuffle_epi32(*t2, 0x55);
t4 = _mm_slli_si128(*t1, 0x4);
*t1 = _mm_xor_si128(*t1, t4);
t4 = _mm_slli_si128(t4, 0x4);
*t1 = _mm_xor_si128(*t1, t4);
t4 = _mm_slli_si128(t4, 0x4);
*t1 = _mm_xor_si128(*t1, t4);
*t1 = _mm_xor_si128(*t1, *t2);
*t2 = _mm_shuffle_epi32(*t1, 0xFF);
t4 = _mm_slli_si128(*t3, 0x4);
*t3 = _mm_xor_si128(*t3, t4);
*t3 = _mm_xor_si128(*t3, *t2);
}
BR_TARGET("sse2,aes")
static inline void
expand_step256_1(__m128i *t1, __m128i *t2)
{
__m128i t4;
*t2 = _mm_shuffle_epi32(*t2, 0xFF);
t4 = _mm_slli_si128(*t1, 0x4);
*t1 = _mm_xor_si128(*t1, t4);
t4 = _mm_slli_si128(t4, 0x4);
*t1 = _mm_xor_si128(*t1, t4);
t4 = _mm_slli_si128(t4, 0x4);
*t1 = _mm_xor_si128(*t1, t4);
*t1 = _mm_xor_si128(*t1, *t2);
}
BR_TARGET("sse2,aes")
static inline void
expand_step256_2(__m128i *t1, __m128i *t3)
{
__m128i t2, t4;
t4 = _mm_aeskeygenassist_si128(*t1, 0x0);
t2 = _mm_shuffle_epi32(t4, 0xAA);
t4 = _mm_slli_si128(*t3, 0x4);
*t3 = _mm_xor_si128(*t3, t4);
t4 = _mm_slli_si128(t4, 0x4);
*t3 = _mm_xor_si128(*t3, t4);
t4 = _mm_slli_si128(t4, 0x4);
*t3 = _mm_xor_si128(*t3, t4);
*t3 = _mm_xor_si128(*t3, t2);
}
/*
* Perform key schedule for AES, encryption direction. Subkeys are written
* in sk[], and the number of rounds is returned. Key length MUST be 16,
* 24 or 32 bytes.
*/
BR_TARGET("sse2,aes")
static unsigned
x86ni_keysched(__m128i *sk, const void *key, size_t len)
{
const unsigned char *kb;
#define KEXP128(k, i, rcon) do { \
k = expand_step128(k, _mm_aeskeygenassist_si128(k, rcon)); \
sk[i] = k; \
} while (0)
#define KEXP192(i, rcon1, rcon2) do { \
sk[(i) + 0] = t1; \
sk[(i) + 1] = t3; \
t2 = _mm_aeskeygenassist_si128(t3, rcon1); \
expand_step192(&t1, &t2, &t3); \
sk[(i) + 1] = _mm_castpd_si128(_mm_shuffle_pd( \
_mm_castsi128_pd(sk[(i) + 1]), \
_mm_castsi128_pd(t1), 0)); \
sk[(i) + 2] = _mm_castpd_si128(_mm_shuffle_pd( \
_mm_castsi128_pd(t1), \
_mm_castsi128_pd(t3), 1)); \
t2 = _mm_aeskeygenassist_si128(t3, rcon2); \
expand_step192(&t1, &t2, &t3); \
} while (0)
#define KEXP256(i, rcon) do { \
sk[(i) + 0] = t3; \
t2 = _mm_aeskeygenassist_si128(t3, rcon); \
expand_step256_1(&t1, &t2); \
sk[(i) + 1] = t1; \
expand_step256_2(&t1, &t3); \
} while (0)
kb = key;
switch (len) {
__m128i t1, t2, t3;
case 16:
t1 = _mm_loadu_si128((const void *)kb);
sk[0] = t1;
KEXP128(t1, 1, 0x01);
KEXP128(t1, 2, 0x02);
KEXP128(t1, 3, 0x04);
KEXP128(t1, 4, 0x08);
KEXP128(t1, 5, 0x10);
KEXP128(t1, 6, 0x20);
KEXP128(t1, 7, 0x40);
KEXP128(t1, 8, 0x80);
KEXP128(t1, 9, 0x1B);
KEXP128(t1, 10, 0x36);
return 10;
case 24:
t1 = _mm_loadu_si128((const void *)kb);
t3 = _mm_loadu_si128((const void *)(kb + 8));
t3 = _mm_shuffle_epi32(t3, 0x4E);
KEXP192(0, 0x01, 0x02);
KEXP192(3, 0x04, 0x08);
KEXP192(6, 0x10, 0x20);
KEXP192(9, 0x40, 0x80);
sk[12] = t1;
return 12;
case 32:
t1 = _mm_loadu_si128((const void *)kb);
t3 = _mm_loadu_si128((const void *)(kb + 16));
sk[0] = t1;
KEXP256( 1, 0x01);
KEXP256( 3, 0x02);
KEXP256( 5, 0x04);
KEXP256( 7, 0x08);
KEXP256( 9, 0x10);
KEXP256(11, 0x20);
sk[13] = t3;
t2 = _mm_aeskeygenassist_si128(t3, 0x40);
expand_step256_1(&t1, &t2);
sk[14] = t1;
return 14;
default:
return 0;
}
#undef KEXP128
#undef KEXP192
#undef KEXP256
}
/* see inner.h */
BR_TARGET("sse2,aes")
unsigned
br_aes_x86ni_keysched_enc(unsigned char *skni, const void *key, size_t len)
{
__m128i sk[15];
unsigned num_rounds;
num_rounds = x86ni_keysched(sk, key, len);
memcpy(skni, sk, (num_rounds + 1) << 4);
return num_rounds;
}
/* see inner.h */
BR_TARGET("sse2,aes")
unsigned
br_aes_x86ni_keysched_dec(unsigned char *skni, const void *key, size_t len)
{
__m128i sk[15];
unsigned u, num_rounds;
num_rounds = x86ni_keysched(sk, key, len);
_mm_storeu_si128((void *)skni, sk[num_rounds]);
for (u = 1; u < num_rounds; u ++) {
_mm_storeu_si128((void *)(skni + (u << 4)),
_mm_aesimc_si128(sk[num_rounds - u]));
}
_mm_storeu_si128((void *)(skni + (num_rounds << 4)), sk[0]);
return num_rounds;
}
#endif

View file

@ -0,0 +1,224 @@
/*
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
#if BR_AES_X86NI
#if BR_AES_X86NI_GCC
#include <wmmintrin.h>
#endif
#if BR_AES_X86NI_MSC
#include <intrin.h>
#endif
/* see bearssl_block.h */
void
br_aes_x86ni_cbcdec_init(br_aes_x86ni_cbcdec_keys *ctx,
const void *key, size_t len)
{
ctx->vtable = &br_aes_x86ni_cbcdec_vtable;
ctx->num_rounds = br_aes_x86ni_keysched_dec(ctx->skey.skni, key, len);
}
/* see bearssl_block.h */
BR_TARGET("sse2,aes")
void
br_aes_x86ni_cbcdec_run(const br_aes_x86ni_cbcdec_keys *ctx,
void *iv, void *data, size_t len)
{
unsigned char *buf;
unsigned num_rounds;
__m128i sk[15], ivx;
unsigned u;
buf = data;
ivx = _mm_loadu_si128(iv);
num_rounds = ctx->num_rounds;
for (u = 0; u <= num_rounds; u ++) {
sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4)));
}
while (len > 0) {
__m128i x0, x1, x2, x3, e0, e1, e2, e3;
x0 = _mm_loadu_si128((void *)(buf + 0));
if (len >= 64) {
x1 = _mm_loadu_si128((void *)(buf + 16));
x2 = _mm_loadu_si128((void *)(buf + 32));
x3 = _mm_loadu_si128((void *)(buf + 48));
} else {
x0 = _mm_loadu_si128((void *)(buf + 0));
if (len >= 32) {
x1 = _mm_loadu_si128((void *)(buf + 16));
if (len >= 48) {
x2 = _mm_loadu_si128(
(void *)(buf + 32));
} else {
x2 = x0;
}
} else {
x1 = x0;
x2 = x0;
}
x3 = x0;
}
e0 = x0;
e1 = x1;
e2 = x2;
e3 = x3;
x0 = _mm_xor_si128(x0, sk[0]);
x1 = _mm_xor_si128(x1, sk[0]);
x2 = _mm_xor_si128(x2, sk[0]);
x3 = _mm_xor_si128(x3, sk[0]);
x0 = _mm_aesdec_si128(x0, sk[1]);
x1 = _mm_aesdec_si128(x1, sk[1]);
x2 = _mm_aesdec_si128(x2, sk[1]);
x3 = _mm_aesdec_si128(x3, sk[1]);
x0 = _mm_aesdec_si128(x0, sk[2]);
x1 = _mm_aesdec_si128(x1, sk[2]);
x2 = _mm_aesdec_si128(x2, sk[2]);
x3 = _mm_aesdec_si128(x3, sk[2]);
x0 = _mm_aesdec_si128(x0, sk[3]);
x1 = _mm_aesdec_si128(x1, sk[3]);
x2 = _mm_aesdec_si128(x2, sk[3]);
x3 = _mm_aesdec_si128(x3, sk[3]);
x0 = _mm_aesdec_si128(x0, sk[4]);
x1 = _mm_aesdec_si128(x1, sk[4]);
x2 = _mm_aesdec_si128(x2, sk[4]);
x3 = _mm_aesdec_si128(x3, sk[4]);
x0 = _mm_aesdec_si128(x0, sk[5]);
x1 = _mm_aesdec_si128(x1, sk[5]);
x2 = _mm_aesdec_si128(x2, sk[5]);
x3 = _mm_aesdec_si128(x3, sk[5]);
x0 = _mm_aesdec_si128(x0, sk[6]);
x1 = _mm_aesdec_si128(x1, sk[6]);
x2 = _mm_aesdec_si128(x2, sk[6]);
x3 = _mm_aesdec_si128(x3, sk[6]);
x0 = _mm_aesdec_si128(x0, sk[7]);
x1 = _mm_aesdec_si128(x1, sk[7]);
x2 = _mm_aesdec_si128(x2, sk[7]);
x3 = _mm_aesdec_si128(x3, sk[7]);
x0 = _mm_aesdec_si128(x0, sk[8]);
x1 = _mm_aesdec_si128(x1, sk[8]);
x2 = _mm_aesdec_si128(x2, sk[8]);
x3 = _mm_aesdec_si128(x3, sk[8]);
x0 = _mm_aesdec_si128(x0, sk[9]);
x1 = _mm_aesdec_si128(x1, sk[9]);
x2 = _mm_aesdec_si128(x2, sk[9]);
x3 = _mm_aesdec_si128(x3, sk[9]);
if (num_rounds == 10) {
x0 = _mm_aesdeclast_si128(x0, sk[10]);
x1 = _mm_aesdeclast_si128(x1, sk[10]);
x2 = _mm_aesdeclast_si128(x2, sk[10]);
x3 = _mm_aesdeclast_si128(x3, sk[10]);
} else if (num_rounds == 12) {
x0 = _mm_aesdec_si128(x0, sk[10]);
x1 = _mm_aesdec_si128(x1, sk[10]);
x2 = _mm_aesdec_si128(x2, sk[10]);
x3 = _mm_aesdec_si128(x3, sk[10]);
x0 = _mm_aesdec_si128(x0, sk[11]);
x1 = _mm_aesdec_si128(x1, sk[11]);
x2 = _mm_aesdec_si128(x2, sk[11]);
x3 = _mm_aesdec_si128(x3, sk[11]);
x0 = _mm_aesdeclast_si128(x0, sk[12]);
x1 = _mm_aesdeclast_si128(x1, sk[12]);
x2 = _mm_aesdeclast_si128(x2, sk[12]);
x3 = _mm_aesdeclast_si128(x3, sk[12]);
} else {
x0 = _mm_aesdec_si128(x0, sk[10]);
x1 = _mm_aesdec_si128(x1, sk[10]);
x2 = _mm_aesdec_si128(x2, sk[10]);
x3 = _mm_aesdec_si128(x3, sk[10]);
x0 = _mm_aesdec_si128(x0, sk[11]);
x1 = _mm_aesdec_si128(x1, sk[11]);
x2 = _mm_aesdec_si128(x2, sk[11]);
x3 = _mm_aesdec_si128(x3, sk[11]);
x0 = _mm_aesdec_si128(x0, sk[12]);
x1 = _mm_aesdec_si128(x1, sk[12]);
x2 = _mm_aesdec_si128(x2, sk[12]);
x3 = _mm_aesdec_si128(x3, sk[12]);
x0 = _mm_aesdec_si128(x0, sk[13]);
x1 = _mm_aesdec_si128(x1, sk[13]);
x2 = _mm_aesdec_si128(x2, sk[13]);
x3 = _mm_aesdec_si128(x3, sk[13]);
x0 = _mm_aesdeclast_si128(x0, sk[14]);
x1 = _mm_aesdeclast_si128(x1, sk[14]);
x2 = _mm_aesdeclast_si128(x2, sk[14]);
x3 = _mm_aesdeclast_si128(x3, sk[14]);
}
x0 = _mm_xor_si128(x0, ivx);
x1 = _mm_xor_si128(x1, e0);
x2 = _mm_xor_si128(x2, e1);
x3 = _mm_xor_si128(x3, e2);
ivx = e3;
_mm_storeu_si128((void *)(buf + 0), x0);
if (len >= 64) {
_mm_storeu_si128((void *)(buf + 16), x1);
_mm_storeu_si128((void *)(buf + 32), x2);
_mm_storeu_si128((void *)(buf + 48), x3);
buf += 64;
len -= 64;
} else {
if (len >= 32) {
_mm_storeu_si128((void *)(buf + 16), x1);
if (len >= 48) {
_mm_storeu_si128(
(void *)(buf + 32), x2);
}
}
break;
}
}
_mm_storeu_si128(iv, ivx);
}
/* see bearssl_block.h */
const br_block_cbcdec_class br_aes_x86ni_cbcdec_vtable = {
sizeof(br_aes_x86ni_cbcdec_keys),
16,
4,
(void (*)(const br_block_cbcdec_class **, const void *, size_t))
&br_aes_x86ni_cbcdec_init,
(void (*)(const br_block_cbcdec_class *const *, void *, void *, size_t))
&br_aes_x86ni_cbcdec_run
};
/* see bearssl_block.h */
const br_block_cbcdec_class *
br_aes_x86ni_cbcdec_get_vtable(void)
{
return br_aes_x86ni_supported() ? &br_aes_x86ni_cbcdec_vtable : NULL;
}
#else
/* see bearssl_block.h */
const br_block_cbcdec_class *
br_aes_x86ni_cbcdec_get_vtable(void)
{
return NULL;
}
#endif

View file

@ -0,0 +1,125 @@
/*
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
#if BR_AES_X86NI
#if BR_AES_X86NI_GCC
#include <wmmintrin.h>
#endif
#if BR_AES_X86NI_MSC
#include <intrin.h>
#endif
/* see bearssl_block.h */
void
br_aes_x86ni_cbcenc_init(br_aes_x86ni_cbcenc_keys *ctx,
const void *key, size_t len)
{
ctx->vtable = &br_aes_x86ni_cbcenc_vtable;
ctx->num_rounds = br_aes_x86ni_keysched_enc(ctx->skey.skni, key, len);
}
/* see bearssl_block.h */
BR_TARGET("sse2,aes")
void
br_aes_x86ni_cbcenc_run(const br_aes_x86ni_cbcenc_keys *ctx,
void *iv, void *data, size_t len)
{
unsigned char *buf;
unsigned num_rounds;
__m128i sk[15], ivx;
unsigned u;
buf = data;
ivx = _mm_loadu_si128(iv);
num_rounds = ctx->num_rounds;
for (u = 0; u <= num_rounds; u ++) {
sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4)));
}
while (len > 0) {
__m128i x;
x = _mm_xor_si128(_mm_loadu_si128((void *)buf), ivx);
x = _mm_xor_si128(x, sk[0]);
x = _mm_aesenc_si128(x, sk[1]);
x = _mm_aesenc_si128(x, sk[2]);
x = _mm_aesenc_si128(x, sk[3]);
x = _mm_aesenc_si128(x, sk[4]);
x = _mm_aesenc_si128(x, sk[5]);
x = _mm_aesenc_si128(x, sk[6]);
x = _mm_aesenc_si128(x, sk[7]);
x = _mm_aesenc_si128(x, sk[8]);
x = _mm_aesenc_si128(x, sk[9]);
if (num_rounds == 10) {
x = _mm_aesenclast_si128(x, sk[10]);
} else if (num_rounds == 12) {
x = _mm_aesenc_si128(x, sk[10]);
x = _mm_aesenc_si128(x, sk[11]);
x = _mm_aesenclast_si128(x, sk[12]);
} else {
x = _mm_aesenc_si128(x, sk[10]);
x = _mm_aesenc_si128(x, sk[11]);
x = _mm_aesenc_si128(x, sk[12]);
x = _mm_aesenc_si128(x, sk[13]);
x = _mm_aesenclast_si128(x, sk[14]);
}
ivx = x;
_mm_storeu_si128((void *)buf, x);
buf += 16;
len -= 16;
}
_mm_storeu_si128(iv, ivx);
}
/* see bearssl_block.h */
const br_block_cbcenc_class br_aes_x86ni_cbcenc_vtable = {
sizeof(br_aes_x86ni_cbcenc_keys),
16,
4,
(void (*)(const br_block_cbcenc_class **, const void *, size_t))
&br_aes_x86ni_cbcenc_init,
(void (*)(const br_block_cbcenc_class *const *, void *, void *, size_t))
&br_aes_x86ni_cbcenc_run
};
/* see bearssl_block.h */
const br_block_cbcenc_class *
br_aes_x86ni_cbcenc_get_vtable(void)
{
return br_aes_x86ni_supported() ? &br_aes_x86ni_cbcenc_vtable : NULL;
}
#else
/* see bearssl_block.h */
const br_block_cbcenc_class *
br_aes_x86ni_cbcenc_get_vtable(void)
{
return NULL;
}
#endif

View file

@ -0,0 +1,218 @@
/*
* Copyright (c) 2017 Thomas Pornin <pornin@bolet.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "inner.h"
#if BR_AES_X86NI
#if BR_AES_X86NI_GCC
#include <smmintrin.h>
#include <wmmintrin.h>
#define bswap32 __builtin_bswap32
#endif
#if BR_AES_X86NI_MSC
#include <stdlib.h>
#include <intrin.h>
#define bswap32 _byteswap_ulong
#endif
/* see bearssl_block.h */
void
br_aes_x86ni_ctr_init(br_aes_x86ni_ctr_keys *ctx,
const void *key, size_t len)
{
ctx->vtable = &br_aes_x86ni_ctr_vtable;
ctx->num_rounds = br_aes_x86ni_keysched_enc(ctx->skey.skni, key, len);
}
/* see bearssl_block.h */
BR_TARGET("sse2,sse4.1,aes")
uint32_t
br_aes_x86ni_ctr_run(const br_aes_x86ni_ctr_keys *ctx,
const void *iv, uint32_t cc, void *data, size_t len)
{
unsigned char *buf;
unsigned char ivbuf[16];
unsigned num_rounds;
__m128i sk[15];
__m128i ivx;
unsigned u;
buf = data;
memcpy(ivbuf, iv, 12);
num_rounds = ctx->num_rounds;
for (u = 0; u <= num_rounds; u ++) {
sk[u] = _mm_loadu_si128((void *)(ctx->skey.skni + (u << 4)));
}
ivx = _mm_loadu_si128((void *)ivbuf);
while (len > 0) {
__m128i x0, x1, x2, x3;
x0 = _mm_insert_epi32(ivx, bswap32(cc + 0), 3);
x1 = _mm_insert_epi32(ivx, bswap32(cc + 1), 3);
x2 = _mm_insert_epi32(ivx, bswap32(cc + 2), 3);
x3 = _mm_insert_epi32(ivx, bswap32(cc + 3), 3);
x0 = _mm_xor_si128(x0, sk[0]);
x1 = _mm_xor_si128(x1, sk[0]);
x2 = _mm_xor_si128(x2, sk[0]);
x3 = _mm_xor_si128(x3, sk[0]);
x0 = _mm_aesenc_si128(x0, sk[1]);
x1 = _mm_aesenc_si128(x1, sk[1]);
x2 = _mm_aesenc_si128(x2, sk[1]);
x3 = _mm_aesenc_si128(x3, sk[1]);
x0 = _mm_aesenc_si128(x0, sk[2]);
x1 = _mm_aesenc_si128(x1, sk[2]);
x2 = _mm_aesenc_si128(x2, sk[2]);
x3 = _mm_aesenc_si128(x3, sk[2]);
x0 = _mm_aesenc_si128(x0, sk[3]);
x1 = _mm_aesenc_si128(x1, sk[3]);
x2 = _mm_aesenc_si128(x2, sk[3]);
x3 = _mm_aesenc_si128(x3, sk[3]);
x0 = _mm_aesenc_si128(x0, sk[4]);
x1 = _mm_aesenc_si128(x1, sk[4]);
x2 = _mm_aesenc_si128(x2, sk[4]);
x3 = _mm_aesenc_si128(x3, sk[4]);
x0 = _mm_aesenc_si128(x0, sk[5]);
x1 = _mm_aesenc_si128(x1, sk[5]);
x2 = _mm_aesenc_si128(x2, sk[5]);
x3 = _mm_aesenc_si128(x3, sk[5]);
x0 = _mm_aesenc_si128(x0, sk[6]);
x1 = _mm_aesenc_si128(x1, sk[6]);
x2 = _mm_aesenc_si128(x2, sk[6]);
x3 = _mm_aesenc_si128(x3, sk[6]);
x0 = _mm_aesenc_si128(x0, sk[7]);
x1 = _mm_aesenc_si128(x1, sk[7]);
x2 = _mm_aesenc_si128(x2, sk[7]);
x3 = _mm_aesenc_si128(x3, sk[7]);
x0 = _mm_aesenc_si128(x0, sk[8]);
x1 = _mm_aesenc_si128(x1, sk[8]);
x2 = _mm_aesenc_si128(x2, sk[8]);
x3 = _mm_aesenc_si128(x3, sk[8]);
x0 = _mm_aesenc_si128(x0, sk[9]);
x1 = _mm_aesenc_si128(x1, sk[9]);
x2 = _mm_aesenc_si128(x2, sk[9]);
x3 = _mm_aesenc_si128(x3, sk[9]);
if (num_rounds == 10) {
x0 = _mm_aesenclast_si128(x0, sk[10]);
x1 = _mm_aesenclast_si128(x1, sk[10]);
x2 = _mm_aesenclast_si128(x2, sk[10]);
x3 = _mm_aesenclast_si128(x3, sk[10]);
} else if (num_rounds == 12) {
x0 = _mm_aesenc_si128(x0, sk[10]);
x1 = _mm_aesenc_si128(x1, sk[10]);
x2 = _mm_aesenc_si128(x2, sk[10]);
x3 = _mm_aesenc_si128(x3, sk[10]);
x0 = _mm_aesenc_si128(x0, sk[11]);
x1 = _mm_aesenc_si128(x1, sk[11]);
x2 = _mm_aesenc_si128(x2, sk[11]);
x3 = _mm_aesenc_si128(x3, sk[11]);
x0 = _mm_aesenclast_si128(x0, sk[12]);
x1 = _mm_aesenclast_si128(x1, sk[12]);
x2 = _mm_aesenclast_si128(x2, sk[12]);
x3 = _mm_aesenclast_si128(x3, sk[12]);
} else {
x0 = _mm_aesenc_si128(x0, sk[10]);
x1 = _mm_aesenc_si128(x1, sk[10]);
x2 = _mm_aesenc_si128(x2, sk[10]);
x3 = _mm_aesenc_si128(x3, sk[10]);
x0 = _mm_aesenc_si128(x0, sk[11]);
x1 = _mm_aesenc_si128(x1, sk[11]);
x2 = _mm_aesenc_si128(x2, sk[11]);
x3 = _mm_aesenc_si128(x3, sk[11]);
x0 = _mm_aesenc_si128(x0, sk[12]);
x1 = _mm_aesenc_si128(x1, sk[12]);
x2 = _mm_aesenc_si128(x2, sk[12]);
x3 = _mm_aesenc_si128(x3, sk[12]);
x0 = _mm_aesenc_si128(x0, sk[13]);
x1 = _mm_aesenc_si128(x1, sk[13]);
x2 = _mm_aesenc_si128(x2, sk[13]);
x3 = _mm_aesenc_si128(x3, sk[13]);
x0 = _mm_aesenclast_si128(x0, sk[14]);
x1 = _mm_aesenclast_si128(x1, sk[14]);
x2 = _mm_aesenclast_si128(x2, sk[14]);
x3 = _mm_aesenclast_si128(x3, sk[14]);
}
if (len >= 64) {
x0 = _mm_xor_si128(x0,
_mm_loadu_si128((void *)(buf + 0)));
x1 = _mm_xor_si128(x1,
_mm_loadu_si128((void *)(buf + 16)));
x2 = _mm_xor_si128(x2,
_mm_loadu_si128((void *)(buf + 32)));
x3 = _mm_xor_si128(x3,
_mm_loadu_si128((void *)(buf + 48)));
_mm_storeu_si128((void *)(buf + 0), x0);
_mm_storeu_si128((void *)(buf + 16), x1);
_mm_storeu_si128((void *)(buf + 32), x2);
_mm_storeu_si128((void *)(buf + 48), x3);
buf += 64;
len -= 64;
cc += 4;
} else {
unsigned char tmp[64];
_mm_storeu_si128((void *)(tmp + 0), x0);
_mm_storeu_si128((void *)(tmp + 16), x1);
_mm_storeu_si128((void *)(tmp + 32), x2);
_mm_storeu_si128((void *)(tmp + 48), x3);
for (u = 0; u < len; u ++) {
buf[u] ^= tmp[u];
}
cc += (uint32_t)len >> 4;
break;
}
}
return cc;
}
/* see bearssl_block.h */
const br_block_ctr_class br_aes_x86ni_ctr_vtable = {
sizeof(br_aes_x86ni_ctr_keys),
16,
4,
(void (*)(const br_block_ctr_class **, const void *, size_t))
&br_aes_x86ni_ctr_init,
(uint32_t (*)(const br_block_ctr_class *const *,
const void *, uint32_t, void *, size_t))
&br_aes_x86ni_ctr_run
};
/* see bearssl_block.h */
const br_block_ctr_class *
br_aes_x86ni_ctr_get_vtable(void)
{
return br_aes_x86ni_supported() ? &br_aes_x86ni_ctr_vtable : NULL;
}
#else
/* see bearssl_block.h */
const br_block_ctr_class *
br_aes_x86ni_ctr_get_vtable(void)
{
return NULL;
}
#endif