From b65e9e71d5ee992db5c96793c6af999545daad28 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Thu, 14 May 2015 10:31:18 +0300 Subject: Enable AMD64 3DES implementation on WIN64 * cipher/des-amd64.S: Enable when HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined. (ELF): New macro to mask lines with ELF specific commands. * cipher/des.c (USE_AMD64_ASM): Enable when HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS defined. [HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS] (call_sysv_fn): New. (tripledes_ecb_crypt) [HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS]: Call assembly function through 'call_sysv_fn'. (tripledes_amd64_ctr_enc, tripledes_amd64_cbc_dec) (tripledes_amd64_cfb_dec): New wrapper functions for bulk assembly functions. -- Signed-off-by: Jussi Kivilinna --- cipher/des-amd64.S | 29 ++++++++++++++++---------- cipher/des.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 75 insertions(+), 15 deletions(-) diff --git a/cipher/des-amd64.S b/cipher/des-amd64.S index e8b2c568..307d2112 100644 --- a/cipher/des-amd64.S +++ b/cipher/des-amd64.S @@ -20,7 +20,8 @@ #ifdef __x86_64 #include -#if defined(USE_DES) && defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) +#if defined(USE_DES) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ + defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) #ifdef __PIC__ # define RIP (%rip) @@ -28,6 +29,12 @@ # define RIP #endif +#ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS +# define ELF(...) __VA_ARGS__ +#else +# define ELF(...) /*_*/ +#endif + .text #define s1 0 @@ -185,7 +192,7 @@ .align 8 .globl _gcry_3des_amd64_crypt_block -.type _gcry_3des_amd64_crypt_block,@function; +ELF(.type _gcry_3des_amd64_crypt_block,@function;) _gcry_3des_amd64_crypt_block: /* input: @@ -271,7 +278,7 @@ _gcry_3des_amd64_crypt_block: popq %rbp; ret; -.size _gcry_3des_amd64_crypt_block,.-_gcry_3des_amd64_crypt_block; +ELF(.size _gcry_3des_amd64_crypt_block,.-_gcry_3des_amd64_crypt_block;) /*********************************************************************** * 3-way 3DES @@ -458,7 +465,7 @@ _gcry_3des_amd64_crypt_block: movl right##d, 4(io); .align 8 -.type _gcry_3des_amd64_crypt_blk3,@function; +ELF(.type _gcry_3des_amd64_crypt_blk3,@function;) _gcry_3des_amd64_crypt_blk3: /* input: * %rdi: round keys, CTX @@ -528,11 +535,11 @@ _gcry_3des_amd64_crypt_blk3: final_permutation3(RR, RL); ret; -.size _gcry_3des_amd64_crypt_blk3,.-_gcry_3des_amd64_crypt_blk3; +ELF(.size _gcry_3des_amd64_crypt_blk3,.-_gcry_3des_amd64_crypt_blk3;) .align 8 .globl _gcry_3des_amd64_cbc_dec -.type _gcry_3des_amd64_cbc_dec,@function; +ELF(.type _gcry_3des_amd64_cbc_dec,@function;) _gcry_3des_amd64_cbc_dec: /* input: * %rdi: ctx, CTX @@ -604,11 +611,11 @@ _gcry_3des_amd64_cbc_dec: popq %rbp; ret; -.size _gcry_3des_amd64_cbc_dec,.-_gcry_3des_amd64_cbc_dec; +ELF(.size _gcry_3des_amd64_cbc_dec,.-_gcry_3des_amd64_cbc_dec;) .align 8 .globl _gcry_3des_amd64_ctr_enc -.type _gcry_3des_amd64_ctr_enc,@function; +ELF(.type _gcry_3des_amd64_ctr_enc,@function;) _gcry_3des_amd64_ctr_enc: /* input: * %rdi: ctx, CTX @@ -682,11 +689,11 @@ _gcry_3des_amd64_ctr_enc: popq %rbp; ret; -.size _gcry_3des_amd64_cbc_dec,.-_gcry_3des_amd64_cbc_dec; +ELF(.size _gcry_3des_amd64_cbc_dec,.-_gcry_3des_amd64_cbc_dec;) .align 8 .globl _gcry_3des_amd64_cfb_dec -.type _gcry_3des_amd64_cfb_dec,@function; +ELF(.type _gcry_3des_amd64_cfb_dec,@function;) _gcry_3des_amd64_cfb_dec: /* input: * %rdi: ctx, CTX @@ -757,7 +764,7 @@ _gcry_3des_amd64_cfb_dec: popq %rbx; popq %rbp; ret; -.size _gcry_3des_amd64_cfb_dec,.-_gcry_3des_amd64_cfb_dec; +ELF(.size _gcry_3des_amd64_cfb_dec,.-_gcry_3des_amd64_cfb_dec;) .data .align 16 diff --git a/cipher/des.c b/cipher/des.c index d4863d1b..be62763e 100644 --- a/cipher/des.c +++ b/cipher/des.c @@ -127,7 +127,8 @@ /* USE_AMD64_ASM indicates whether to use AMD64 assembly code. */ #undef USE_AMD64_ASM -#if defined(__x86_64__) && defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) +#if defined(__x86_64__) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ + defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) # define USE_AMD64_ASM 1 #endif @@ -771,6 +772,24 @@ extern void _gcry_3des_amd64_cfb_dec(const void *keys, byte *out, #define TRIPLEDES_ECB_BURN_STACK (8 * sizeof(void *)) +#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS +static inline void +call_sysv_fn (const void *fn, const void *arg1, const void *arg2, + const void *arg3, const void *arg4) +{ + /* Call SystemV ABI function without storing non-volatile XMM registers, + * as target function does not use vector instruction sets. */ + asm volatile ("callq *%0\n\t" + : "+a" (fn), + "+D" (arg1), + "+S" (arg2), + "+d" (arg3), + "+c" (arg4) + : + : "cc", "memory", "r8", "r9", "r10", "r11"); +} +#endif + /* * Electronic Codebook Mode Triple-DES encryption/decryption of data * according to 'mode'. Sometimes this mode is named 'EDE' mode @@ -784,11 +803,45 @@ tripledes_ecb_crypt (struct _tripledes_ctx *ctx, const byte * from, keys = mode ? ctx->decrypt_subkeys : ctx->encrypt_subkeys; +#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS + call_sysv_fn (_gcry_3des_amd64_crypt_block, keys, to, from, NULL); +#else _gcry_3des_amd64_crypt_block(keys, to, from); +#endif return 0; } +static inline void +tripledes_amd64_ctr_enc(const void *keys, byte *out, const byte *in, byte *ctr) +{ +#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS + call_sysv_fn (_gcry_3des_amd64_ctr_enc, keys, out, in, ctr); +#else + _gcry_3des_amd64_ctr_enc(keys, out, in, ctr); +#endif +} + +static inline void +tripledes_amd64_cbc_dec(const void *keys, byte *out, const byte *in, byte *iv) +{ +#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS + call_sysv_fn (_gcry_3des_amd64_cbc_dec, keys, out, in, iv); +#else + _gcry_3des_amd64_cbc_dec(keys, out, in, iv); +#endif +} + +static inline void +tripledes_amd64_cfb_dec(const void *keys, byte *out, const byte *in, byte *iv) +{ +#ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS + call_sysv_fn (_gcry_3des_amd64_cfb_dec, keys, out, in, iv); +#else + _gcry_3des_amd64_cfb_dec(keys, out, in, iv); +#endif +} + #else /*USE_AMD64_ASM*/ #define TRIPLEDES_ECB_BURN_STACK 32 @@ -871,7 +924,7 @@ _gcry_3des_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, /* Process data in 3 block chunks. */ while (nblocks >= 3) { - _gcry_3des_amd64_ctr_enc(ctx->encrypt_subkeys, outbuf, inbuf, ctr); + tripledes_amd64_ctr_enc(ctx->encrypt_subkeys, outbuf, inbuf, ctr); nblocks -= 3; outbuf += 3 * DES_BLOCKSIZE; @@ -926,7 +979,7 @@ _gcry_3des_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg, /* Process data in 3 block chunks. */ while (nblocks >= 3) { - _gcry_3des_amd64_cbc_dec(ctx->decrypt_subkeys, outbuf, inbuf, iv); + tripledes_amd64_cbc_dec(ctx->decrypt_subkeys, outbuf, inbuf, iv); nblocks -= 3; outbuf += 3 * DES_BLOCKSIZE; @@ -974,7 +1027,7 @@ _gcry_3des_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg, /* Process data in 3 block chunks. */ while (nblocks >= 3) { - _gcry_3des_amd64_cfb_dec(ctx->encrypt_subkeys, outbuf, inbuf, iv); + tripledes_amd64_cfb_dec(ctx->encrypt_subkeys, outbuf, inbuf, iv); nblocks -= 3; outbuf += 3 * DES_BLOCKSIZE; -- cgit v1.2.1