blob: fa4929016c0bda51d7f83c23cb99a11e0cb79eb6 [file] [log] [blame]
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#include <stdint.h>
#include <stdlib.h>
#if defined(__i386__) || defined(__x86_64__)
void rust_crypto_aesni_aesimc(uint8_t* round_keys) {
#ifdef __SSE__
asm volatile(
" \
movdqu (%0), %%xmm1; \
aesimc %%xmm1, %%xmm1; \
movdqu %%xmm1, (%0); \
"
: // outputs
: "r" (round_keys) // inputs
: "xmm1", "memory" // clobbers
);
#else
exit(1);
#endif
}
void rust_crypto_aesni_setup_working_key_128(
uint8_t* key,
uint8_t* round_key) {
#ifdef __SSE__
asm volatile(
" \
movdqu (%1), %%xmm1; \
movdqu %%xmm1, (%0); \
add $0x10, %0; \
\
aeskeygenassist $0x01, %%xmm1, %%xmm2; \
call 1f; \
aeskeygenassist $0x02, %%xmm1, %%xmm2; \
call 1f; \
aeskeygenassist $0x04, %%xmm1, %%xmm2; \
call 1f; \
aeskeygenassist $0x08, %%xmm1, %%xmm2; \
call 1f; \
aeskeygenassist $0x10, %%xmm1, %%xmm2; \
call 1f; \
aeskeygenassist $0x20, %%xmm1, %%xmm2; \
call 1f; \
aeskeygenassist $0x40, %%xmm1, %%xmm2; \
call 1f; \
aeskeygenassist $0x80, %%xmm1, %%xmm2; \
call 1f; \
aeskeygenassist $0x1b, %%xmm1, %%xmm2; \
call 1f; \
aeskeygenassist $0x36, %%xmm1, %%xmm2; \
call 1f; \
\
jmp 2f; \
\
1: \
pshufd $0xff, %%xmm2, %%xmm2; \
vpslldq $0x04, %%xmm1, %%xmm3; \
pxor %%xmm3, %%xmm1; \
vpslldq $0x4, %%xmm1, %%xmm3; \
pxor %%xmm3, %%xmm1; \
vpslldq $0x04, %%xmm1, %%xmm3; \
pxor %%xmm3, %%xmm1; \
pxor %%xmm2, %%xmm1; \
movdqu %%xmm1, (%0); \
add $0x10, %0; \
ret; \
\
2: \
"
: "+r" (round_key)
: "r" (key)
: "xmm1", "xmm2", "xmm3", "memory"
);
#else
exit(1);
#endif
}
void rust_crypto_aesni_setup_working_key_192(
uint8_t* key,
uint8_t* round_key) {
#ifdef __SSE__
asm volatile(
" \
movdqu (%1), %%xmm1; \
movdqu 16(%1), %%xmm3; \
movdqu %%xmm1, (%0); \
movdqa %%xmm3, %%xmm5; \
\
aeskeygenassist $0x1, %%xmm3, %%xmm2; \
call 1f; \
shufpd $0, %%xmm1, %%xmm5; \
movdqu %%xmm5, 16(%0); \
movdqa %%xmm1, %%xmm6; \
shufpd $1, %%xmm3, %%xmm6; \
movdqu %%xmm6, 32(%0); \
\
aeskeygenassist $0x2, %%xmm3, %%xmm2; \
call 1f; \
movdqu %%xmm1, 48(%0); \
movdqa %%xmm3, %%xmm5; \
\
aeskeygenassist $0x4, %%xmm3, %%xmm2; \
call 1f; \
shufpd $0, %%xmm1, %%xmm5; \
movdqu %%xmm5, 64(%0); \
movdqa %%xmm1, %%xmm6; \
shufpd $1, %%xmm3, %%xmm6; \
movdqu %%xmm6, 80(%0); \
\
aeskeygenassist $0x8, %%xmm3, %%xmm2; \
call 1f; \
movdqu %%xmm1, 96(%0); \
movdqa %%xmm3, %%xmm5; \
\
aeskeygenassist $0x10, %%xmm3, %%xmm2; \
call 1f; \
shufpd $0, %%xmm1, %%xmm5; \
movdqu %%xmm5, 112(%0); \
movdqa %%xmm1, %%xmm6; \
shufpd $1, %%xmm3, %%xmm6; \
movdqu %%xmm6, 128(%0); \
\
aeskeygenassist $0x20, %%xmm3, %%xmm2; \
call 1f; \
movdqu %%xmm1, 144(%0); \
movdqa %%xmm3, %%xmm5; \
\
aeskeygenassist $0x40, %%xmm3, %%xmm2; \
call 1f; \
shufpd $0, %%xmm1, %%xmm5; \
movdqu %%xmm5, 160(%0); \
movdqa %%xmm1, %%xmm6; \
shufpd $1, %%xmm3, %%xmm6; \
movdqu %%xmm6, 176(%0); \
\
aeskeygenassist $0x80, %%xmm3, %%xmm2; \
call 1f; \
movdqu %%xmm1, 192(%0); \
\
jmp 2f; \
\
1: \
pshufd $0x55, %%xmm2, %%xmm2; \
movdqu %%xmm1, %%xmm4; \
pslldq $4, %%xmm4; \
pxor %%xmm4, %%xmm1; \
pslldq $4, %%xmm4; \
pxor %%xmm4, %%xmm1; \
pslldq $4, %%xmm4; \
pxor %%xmm4, %%xmm1; \
pxor %%xmm2, %%xmm1; \
pshufd $0xff, %%xmm1, %%xmm2; \
movdqu %%xmm3, %%xmm4; \
pslldq $4, %%xmm4; \
pxor %%xmm4, %%xmm3; \
pxor %%xmm2, %%xmm3; \
ret; \
\
2: \
"
: "+r" (round_key)
: "r" (key)
: "xmm1", "xmm2", "xmm3", "memory"
);
#else
exit(1);
#endif
}
void rust_crypto_aesni_setup_working_key_256(
uint8_t* key,
uint8_t* round_key) {
#ifdef __SSE__
asm volatile(
" \
movdqu (%1), %%xmm1; \
movdqu 16(%1), %%xmm3; \
movdqu %%xmm1, (%0); \
movdqu %%xmm3, 16(%0); \
\
aeskeygenassist $0x1, %%xmm3, %%xmm2; \
call 1f; \
movdqu %%xmm1, 32(%0); \
\
aeskeygenassist $0x0, %%xmm1, %%xmm2; \
call 2f; \
movdqu %%xmm3, 48(%0); \
\
aeskeygenassist $0x2, %%xmm3, %%xmm2; \
call 1f; \
movdqu %%xmm1, 64(%0); \
\
aeskeygenassist $0x0, %%xmm1, %%xmm2; \
call 2f; \
movdqu %%xmm3, 80(%0); \
\
aeskeygenassist $0x4, %%xmm3, %%xmm2; \
call 1f; \
movdqu %%xmm1, 96(%0); \
\
aeskeygenassist $0x0, %%xmm1, %%xmm2; \
call 2f; \
movdqu %%xmm3, 112(%0); \
\
aeskeygenassist $0x8, %%xmm3, %%xmm2; \
call 1f; \
movdqu %%xmm1, 128(%0); \
\
aeskeygenassist $0x0, %%xmm1, %%xmm2; \
call 2f; \
movdqu %%xmm3, 144(%0); \
\
aeskeygenassist $0x10, %%xmm3, %%xmm2; \
call 1f; \
movdqu %%xmm1, 160(%0); \
\
aeskeygenassist $0x0, %%xmm1, %%xmm2; \
call 2f; \
movdqu %%xmm3, 176(%0); \
\
aeskeygenassist $0x20, %%xmm3, %%xmm2; \
call 1f; \
movdqu %%xmm1, 192(%0); \
\
aeskeygenassist $0x0, %%xmm1, %%xmm2; \
call 2f; \
movdqu %%xmm3, 208(%0); \
\
aeskeygenassist $0x40, %%xmm3, %%xmm2; \
call 1f; \
movdqu %%xmm1, 224(%0); \
\
jmp 3f; \
\
1: \
pshufd $0xff, %%xmm2, %%xmm2; \
movdqa %%xmm1, %%xmm4; \
pslldq $4, %%xmm4; \
pxor %%xmm4, %%xmm1; \
pslldq $4, %%xmm4; \
pxor %%xmm4, %%xmm1; \
pslldq $4, %%xmm4; \
pxor %%xmm4, %%xmm1; \
pxor %%xmm2, %%xmm1; \
ret; \
\
2: \
pshufd $0xaa, %%xmm2, %%xmm2; \
movdqa %%xmm3, %%xmm4; \
pslldq $4, %%xmm4; \
pxor %%xmm4, %%xmm3; \
pslldq $4, %%xmm4; \
pxor %%xmm4, %%xmm3; \
pslldq $4, %%xmm4; \
pxor %%xmm4, %%xmm3; \
pxor %%xmm2, %%xmm3; \
ret; \
\
3: \
"
: "+r" (round_key)
: "r" (key)
: "xmm1", "xmm2", "xmm3", "memory"
);
#else
exit(1);
#endif
}
void rust_crypto_aesni_encrypt_block(
uint8_t rounds,
uint8_t* input,
uint8_t* round_keys,
uint8_t* output) {
#ifdef __SSE__
asm volatile(
" \
/* Copy the data to encrypt to xmm1 */ \
movdqu (%2), %%xmm1; \
\
/* Perform round 0 - the whitening step */ \
movdqu (%1), %%xmm0; \
add $0x10, %1; \
pxor %%xmm0, %%xmm1; \
\
/* Perform all remaining rounds (except the final one) */ \
1: \
movdqu (%1), %%xmm0; \
add $0x10, %1; \
aesenc %%xmm0, %%xmm1; \
sub $0x01, %0; \
cmp $0x01, %0; \
jne 1b; \
\
/* Perform the last round */ \
movdqu (%1), %%xmm0; \
aesenclast %%xmm0, %%xmm1; \
\
/* Finally, move the result from xmm1 to outp */ \
movdqu %%xmm1, (%3); \
"
: "+&r" (rounds), "+&r" (round_keys) // outputs
: "r" (input), "r" (output) // inputs
: "xmm0", "xmm1", "memory", "cc" // clobbers
);
#else
exit(1);
#endif
}
void rust_crypto_aesni_decrypt_block(
uint8_t rounds,
uint8_t* input,
uint8_t* round_keys,
uint8_t* output) {
#ifdef __SSE__
asm volatile(
" \
/* Copy the data to decrypt to xmm1 */ \
movdqu (%2), %%xmm1; \
\
/* Perform round 0 - the whitening step */ \
movdqu (%1), %%xmm0; \
sub $0x10, %1; \
pxor %%xmm0, %%xmm1; \
\
/* Perform all remaining rounds (except the final one) */ \
1: \
movdqu (%1), %%xmm0; \
sub $0x10, %1; \
aesdec %%xmm0, %%xmm1; \
sub $0x01, %0; \
cmp $0x01, %0; \
jne 1b; \
\
/* Perform the last round */ \
movdqu (%1), %%xmm0; \
aesdeclast %%xmm0, %%xmm1; \
\
/* Finally, move the result from xmm1 to outp */ \
movdqu %%xmm1, (%3); \
"
: "+&r" (rounds), "+&r" (round_keys) // outputs
: "r" (input), "r" (output) // inputs
: "xmm0", "xmm1", "memory", "cc" // clobbers
);
#else
exit(1);
#endif
}
#endif