LCOV - code coverage report
Current view: top level - cipher - serpent.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 417 0.0 %
Date: 2016-12-15 12:59:22 Functions: 0 17 0.0 %

          Line data    Source code
       1             : /* serpent.c - Implementation of the Serpent encryption algorithm.
       2             :  *      Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
       3             :  *
       4             :  * This file is part of Libgcrypt.
       5             :  *
       6             :  * Libgcrypt is free software; you can redistribute it and/or modify
       7             :  * it under the terms of the GNU Lesser general Public License as
       8             :  * published by the Free Software Foundation; either version 2.1 of
       9             :  * the License, or (at your option) any later version.
      10             :  *
      11             :  * Libgcrypt is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :  * GNU Lesser General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU Lesser General Public
      17             :  * License along with this program; if not, write to the Free Software
      18             :  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
      19             :  * 02111-1307, USA.
      20             :  */
      21             : 
      22             : #include <config.h>
      23             : 
      24             : #include <string.h>
      25             : #include <stdio.h>
      26             : 
      27             : #include "types.h"
      28             : #include "g10lib.h"
      29             : #include "cipher.h"
      30             : #include "bithelp.h"
      31             : #include "bufhelp.h"
      32             : #include "cipher-internal.h"
      33             : #include "cipher-selftest.h"
      34             : 
      35             : 
      36             : /* USE_SSE2 indicates whether to compile with AMD64 SSE2 code. */
      37             : #undef USE_SSE2
      38             : #if defined(__x86_64__) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
      39             :     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
      40             : # define USE_SSE2 1
      41             : #endif
      42             : 
      43             : /* USE_AVX2 indicates whether to compile with AMD64 AVX2 code. */
      44             : #undef USE_AVX2
      45             : #if defined(__x86_64__) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \
      46             :     defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS))
      47             : # if defined(ENABLE_AVX2_SUPPORT)
      48             : #  define USE_AVX2 1
      49             : # endif
      50             : #endif
      51             : 
      52             : /* USE_NEON indicates whether to enable ARM NEON assembly code. */
      53             : #undef USE_NEON
      54             : #ifdef ENABLE_NEON_SUPPORT
      55             : # if defined(HAVE_ARM_ARCH_V6) && defined(__ARMEL__) \
      56             :      && defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) \
      57             :      && defined(HAVE_GCC_INLINE_ASM_NEON)
      58             : #  define USE_NEON 1
      59             : # endif
      60             : #endif /*ENABLE_NEON_SUPPORT*/
      61             : 
      62             : /* Number of rounds per Serpent encrypt/decrypt operation.  */
      63             : #define ROUNDS 32
      64             : 
      65             : /* Magic number, used during generating of the subkeys.  */
      66             : #define PHI 0x9E3779B9
      67             : 
      68             : /* Serpent works on 128 bit blocks.  */
      69             : typedef u32 serpent_block_t[4];
      70             : 
      71             : /* Serpent key, provided by the user.  If the original key is shorter
      72             :    than 256 bits, it is padded.  */
      73             : typedef u32 serpent_key_t[8];
      74             : 
      75             : /* The key schedule consists of 33 128 bit subkeys.  */
      76             : typedef u32 serpent_subkeys_t[ROUNDS + 1][4];
      77             : 
      78             : /* A Serpent context.  */
      79             : typedef struct serpent_context
      80             : {
      81             :   serpent_subkeys_t keys;       /* Generated subkeys.  */
      82             : 
      83             : #ifdef USE_AVX2
      84             :   int use_avx2;
      85             : #endif
      86             : #ifdef USE_NEON
      87             :   int use_neon;
      88             : #endif
      89             : } serpent_context_t;
      90             : 
      91             : 
      92             : /* Assembly implementations use SystemV ABI, ABI conversion and additional
      93             :  * stack to store XMM6-XMM15 needed on Win64. */
      94             : #undef ASM_FUNC_ABI
      95             : #if defined(USE_SSE2) || defined(USE_AVX2)
      96             : # ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
      97             : #  define ASM_FUNC_ABI __attribute__((sysv_abi))
      98             : # else
      99             : #  define ASM_FUNC_ABI
     100             : # endif
     101             : #endif
     102             : 
     103             : 
     104             : #ifdef USE_SSE2
     105             : /* Assembler implementations of Serpent using SSE2.  Process 8 block in
     106             :    parallel.
     107             :  */
     108             : extern void _gcry_serpent_sse2_ctr_enc(serpent_context_t *ctx,
     109             :                                        unsigned char *out,
     110             :                                        const unsigned char *in,
     111             :                                        unsigned char *ctr) ASM_FUNC_ABI;
     112             : 
     113             : extern void _gcry_serpent_sse2_cbc_dec(serpent_context_t *ctx,
     114             :                                        unsigned char *out,
     115             :                                        const unsigned char *in,
     116             :                                        unsigned char *iv) ASM_FUNC_ABI;
     117             : 
     118             : extern void _gcry_serpent_sse2_cfb_dec(serpent_context_t *ctx,
     119             :                                        unsigned char *out,
     120             :                                        const unsigned char *in,
     121             :                                        unsigned char *iv) ASM_FUNC_ABI;
     122             : 
     123             : extern void _gcry_serpent_sse2_ocb_enc(serpent_context_t *ctx,
     124             :                                        unsigned char *out,
     125             :                                        const unsigned char *in,
     126             :                                        unsigned char *offset,
     127             :                                        unsigned char *checksum,
     128             :                                        const u64 Ls[8]) ASM_FUNC_ABI;
     129             : 
     130             : extern void _gcry_serpent_sse2_ocb_dec(serpent_context_t *ctx,
     131             :                                        unsigned char *out,
     132             :                                        const unsigned char *in,
     133             :                                        unsigned char *offset,
     134             :                                        unsigned char *checksum,
     135             :                                        const u64 Ls[8]) ASM_FUNC_ABI;
     136             : 
     137             : extern void _gcry_serpent_sse2_ocb_auth(serpent_context_t *ctx,
     138             :                                         const unsigned char *abuf,
     139             :                                         unsigned char *offset,
     140             :                                         unsigned char *checksum,
     141             :                                         const u64 Ls[8]) ASM_FUNC_ABI;
     142             : #endif
     143             : 
     144             : #ifdef USE_AVX2
     145             : /* Assembler implementations of Serpent using AVX2.  Process 16 block in
     146             :    parallel.
     147             :  */
     148             : extern void _gcry_serpent_avx2_ctr_enc(serpent_context_t *ctx,
     149             :                                        unsigned char *out,
     150             :                                        const unsigned char *in,
     151             :                                        unsigned char *ctr) ASM_FUNC_ABI;
     152             : 
     153             : extern void _gcry_serpent_avx2_cbc_dec(serpent_context_t *ctx,
     154             :                                        unsigned char *out,
     155             :                                        const unsigned char *in,
     156             :                                        unsigned char *iv) ASM_FUNC_ABI;
     157             : 
     158             : extern void _gcry_serpent_avx2_cfb_dec(serpent_context_t *ctx,
     159             :                                        unsigned char *out,
     160             :                                        const unsigned char *in,
     161             :                                        unsigned char *iv) ASM_FUNC_ABI;
     162             : 
     163             : extern void _gcry_serpent_avx2_ocb_enc(serpent_context_t *ctx,
     164             :                                        unsigned char *out,
     165             :                                        const unsigned char *in,
     166             :                                        unsigned char *offset,
     167             :                                        unsigned char *checksum,
     168             :                                        const u64 Ls[16]) ASM_FUNC_ABI;
     169             : 
     170             : extern void _gcry_serpent_avx2_ocb_dec(serpent_context_t *ctx,
     171             :                                        unsigned char *out,
     172             :                                        const unsigned char *in,
     173             :                                        unsigned char *offset,
     174             :                                        unsigned char *checksum,
     175             :                                        const u64 Ls[16]) ASM_FUNC_ABI;
     176             : 
     177             : extern void _gcry_serpent_avx2_ocb_auth(serpent_context_t *ctx,
     178             :                                         const unsigned char *abuf,
     179             :                                         unsigned char *offset,
     180             :                                         unsigned char *checksum,
     181             :                                         const u64 Ls[16]) ASM_FUNC_ABI;
     182             : #endif
     183             : 
     184             : #ifdef USE_NEON
     185             : /* Assembler implementations of Serpent using ARM NEON.  Process 8 block in
     186             :    parallel.
     187             :  */
     188             : extern void _gcry_serpent_neon_ctr_enc(serpent_context_t *ctx,
     189             :                                        unsigned char *out,
     190             :                                        const unsigned char *in,
     191             :                                        unsigned char *ctr);
     192             : 
     193             : extern void _gcry_serpent_neon_cbc_dec(serpent_context_t *ctx,
     194             :                                        unsigned char *out,
     195             :                                        const unsigned char *in,
     196             :                                        unsigned char *iv);
     197             : 
     198             : extern void _gcry_serpent_neon_cfb_dec(serpent_context_t *ctx,
     199             :                                        unsigned char *out,
     200             :                                        const unsigned char *in,
     201             :                                        unsigned char *iv);
     202             : 
     203             : extern void _gcry_serpent_neon_ocb_enc(serpent_context_t *ctx,
     204             :                                        unsigned char *out,
     205             :                                        const unsigned char *in,
     206             :                                        unsigned char *offset,
     207             :                                        unsigned char *checksum,
     208             :                                        const void *Ls[8]);
     209             : 
     210             : extern void _gcry_serpent_neon_ocb_dec(serpent_context_t *ctx,
     211             :                                        unsigned char *out,
     212             :                                        const unsigned char *in,
     213             :                                        unsigned char *offset,
     214             :                                        unsigned char *checksum,
     215             :                                        const void *Ls[8]);
     216             : 
     217             : extern void _gcry_serpent_neon_ocb_auth(serpent_context_t *ctx,
     218             :                                         const unsigned char *abuf,
     219             :                                         unsigned char *offset,
     220             :                                         unsigned char *checksum,
     221             :                                         const void *Ls[8]);
     222             : #endif
     223             : 
     224             : 
     225             : /* A prototype.  */
     226             : static const char *serpent_test (void);
     227             : 
     228             : 
     229             : /*
     230             :  * These are the S-Boxes of Serpent from following research paper.
     231             :  *
     232             :  *  D. A. Osvik, “Speeding up Serpent,” in Third AES Candidate Conference,
     233             :  *   (New York, New York, USA), p. 317–329, National Institute of Standards and
     234             :  *   Technology, 2000.
     235             :  *
     236             :  * Paper is also available at: http://www.ii.uib.no/~osvik/pub/aes3.pdf
     237             :  *
     238             :  */
     239             : 
     240             : #define SBOX0(r0, r1, r2, r3, w, x, y, z) \
     241             :   { \
     242             :     u32 r4; \
     243             :     \
     244             :     r3 ^= r0; r4 =  r1; \
     245             :     r1 &= r3; r4 ^= r2; \
     246             :     r1 ^= r0; r0 |= r3; \
     247             :     r0 ^= r4; r4 ^= r3; \
     248             :     r3 ^= r2; r2 |= r1; \
     249             :     r2 ^= r4; r4 = ~r4; \
     250             :     r4 |= r1; r1 ^= r3; \
     251             :     r1 ^= r4; r3 |= r0; \
     252             :     r1 ^= r3; r4 ^= r3; \
     253             :     \
     254             :     w = r1; x = r4; y = r2; z = r0; \
     255             :   }
     256             : 
     257             : #define SBOX0_INVERSE(r0, r1, r2, r3, w, x, y, z) \
     258             :   { \
     259             :     u32 r4; \
     260             :     \
     261             :     r2 = ~r2; r4 =  r1; \
     262             :     r1 |= r0; r4 = ~r4; \
     263             :     r1 ^= r2; r2 |= r4; \
     264             :     r1 ^= r3; r0 ^= r4; \
     265             :     r2 ^= r0; r0 &= r3; \
     266             :     r4 ^= r0; r0 |= r1; \
     267             :     r0 ^= r2; r3 ^= r4; \
     268             :     r2 ^= r1; r3 ^= r0; \
     269             :     r3 ^= r1; \
     270             :     r2 &= r3; \
     271             :     r4 ^= r2; \
     272             :     \
     273             :     w = r0; x = r4; y = r1; z = r3; \
     274             :   }
     275             : 
     276             : #define SBOX1(r0, r1, r2, r3, w, x, y, z) \
     277             :   { \
     278             :     u32 r4; \
     279             :     \
     280             :     r0 = ~r0; r2 = ~r2; \
     281             :     r4 =  r0; r0 &= r1; \
     282             :     r2 ^= r0; r0 |= r3; \
     283             :     r3 ^= r2; r1 ^= r0; \
     284             :     r0 ^= r4; r4 |= r1; \
     285             :     r1 ^= r3; r2 |= r0; \
     286             :     r2 &= r4; r0 ^= r1; \
     287             :     r1 &= r2; \
     288             :     r1 ^= r0; r0 &= r2; \
     289             :     r0 ^= r4; \
     290             :     \
     291             :     w = r2; x = r0; y = r3; z = r1; \
     292             :   }
     293             : 
     294             : #define SBOX1_INVERSE(r0, r1, r2, r3, w, x, y, z) \
     295             :   { \
     296             :     u32 r4; \
     297             :     \
     298             :     r4 =  r1; r1 ^= r3; \
     299             :     r3 &= r1; r4 ^= r2; \
     300             :     r3 ^= r0; r0 |= r1; \
     301             :     r2 ^= r3; r0 ^= r4; \
     302             :     r0 |= r2; r1 ^= r3; \
     303             :     r0 ^= r1; r1 |= r3; \
     304             :     r1 ^= r0; r4 = ~r4; \
     305             :     r4 ^= r1; r1 |= r0; \
     306             :     r1 ^= r0; \
     307             :     r1 |= r4; \
     308             :     r3 ^= r1; \
     309             :     \
     310             :     w = r4; x = r0; y = r3; z = r2; \
     311             :   }
     312             : 
     313             : #define SBOX2(r0, r1, r2, r3, w, x, y, z) \
     314             :   { \
     315             :     u32 r4; \
     316             :     \
     317             :     r4 =  r0; r0 &= r2; \
     318             :     r0 ^= r3; r2 ^= r1; \
     319             :     r2 ^= r0; r3 |= r4; \
     320             :     r3 ^= r1; r4 ^= r2; \
     321             :     r1 =  r3; r3 |= r4; \
     322             :     r3 ^= r0; r0 &= r1; \
     323             :     r4 ^= r0; r1 ^= r3; \
     324             :     r1 ^= r4; r4 = ~r4; \
     325             :     \
     326             :     w = r2; x = r3; y = r1; z = r4; \
     327             :   }
     328             : 
     329             : #define SBOX2_INVERSE(r0, r1, r2, r3, w, x, y, z) \
     330             :   { \
     331             :     u32 r4; \
     332             :     \
     333             :     r2 ^= r3; r3 ^= r0; \
     334             :     r4 =  r3; r3 &= r2; \
     335             :     r3 ^= r1; r1 |= r2; \
     336             :     r1 ^= r4; r4 &= r3; \
     337             :     r2 ^= r3; r4 &= r0; \
     338             :     r4 ^= r2; r2 &= r1; \
     339             :     r2 |= r0; r3 = ~r3; \
     340             :     r2 ^= r3; r0 ^= r3; \
     341             :     r0 &= r1; r3 ^= r4; \
     342             :     r3 ^= r0; \
     343             :     \
     344             :     w = r1; x = r4; y = r2; z = r3; \
     345             :   }
     346             : 
     347             : #define SBOX3(r0, r1, r2, r3, w, x, y, z) \
     348             :   { \
     349             :     u32 r4; \
     350             :     \
     351             :     r4 =  r0; r0 |= r3; \
     352             :     r3 ^= r1; r1 &= r4; \
     353             :     r4 ^= r2; r2 ^= r3; \
     354             :     r3 &= r0; r4 |= r1; \
     355             :     r3 ^= r4; r0 ^= r1; \
     356             :     r4 &= r0; r1 ^= r3; \
     357             :     r4 ^= r2; r1 |= r0; \
     358             :     r1 ^= r2; r0 ^= r3; \
     359             :     r2 =  r1; r1 |= r3; \
     360             :     r1 ^= r0; \
     361             :     \
     362             :     w = r1; x = r2; y = r3; z = r4; \
     363             :   }
     364             : 
     365             : #define SBOX3_INVERSE(r0, r1, r2, r3, w, x, y, z) \
     366             :   { \
     367             :     u32 r4; \
     368             :     \
     369             :     r4 =  r2; r2 ^= r1; \
     370             :     r0 ^= r2; r4 &= r2; \
     371             :     r4 ^= r0; r0 &= r1; \
     372             :     r1 ^= r3; r3 |= r4; \
     373             :     r2 ^= r3; r0 ^= r3; \
     374             :     r1 ^= r4; r3 &= r2; \
     375             :     r3 ^= r1; r1 ^= r0; \
     376             :     r1 |= r2; r0 ^= r3; \
     377             :     r1 ^= r4; \
     378             :     r0 ^= r1; \
     379             :     \
     380             :     w = r2; x = r1; y = r3; z = r0; \
     381             :   }
     382             : 
     383             : #define SBOX4(r0, r1, r2, r3, w, x, y, z) \
     384             :   { \
     385             :     u32 r4; \
     386             :     \
     387             :     r1 ^= r3; r3 = ~r3; \
     388             :     r2 ^= r3; r3 ^= r0; \
     389             :     r4 =  r1; r1 &= r3; \
     390             :     r1 ^= r2; r4 ^= r3; \
     391             :     r0 ^= r4; r2 &= r4; \
     392             :     r2 ^= r0; r0 &= r1; \
     393             :     r3 ^= r0; r4 |= r1; \
     394             :     r4 ^= r0; r0 |= r3; \
     395             :     r0 ^= r2; r2 &= r3; \
     396             :     r0 = ~r0; r4 ^= r2; \
     397             :     \
     398             :     w = r1; x = r4; y = r0; z = r3; \
     399             :   }
     400             : 
     401             : #define SBOX4_INVERSE(r0, r1, r2, r3, w, x, y, z) \
     402             :   { \
     403             :     u32 r4; \
     404             :     \
     405             :     r4 =  r2; r2 &= r3; \
     406             :     r2 ^= r1; r1 |= r3; \
     407             :     r1 &= r0; r4 ^= r2; \
     408             :     r4 ^= r1; r1 &= r2; \
     409             :     r0 = ~r0; r3 ^= r4; \
     410             :     r1 ^= r3; r3 &= r0; \
     411             :     r3 ^= r2; r0 ^= r1; \
     412             :     r2 &= r0; r3 ^= r0; \
     413             :     r2 ^= r4; \
     414             :     r2 |= r3; r3 ^= r0; \
     415             :     r2 ^= r1; \
     416             :     \
     417             :     w = r0; x = r3; y = r2; z = r4; \
     418             :   }
     419             : 
     420             : #define SBOX5(r0, r1, r2, r3, w, x, y, z) \
     421             :   { \
     422             :     u32 r4; \
     423             :     \
     424             :     r0 ^= r1; r1 ^= r3; \
     425             :     r3 = ~r3; r4 =  r1; \
     426             :     r1 &= r0; r2 ^= r3; \
     427             :     r1 ^= r2; r2 |= r4; \
     428             :     r4 ^= r3; r3 &= r1; \
     429             :     r3 ^= r0; r4 ^= r1; \
     430             :     r4 ^= r2; r2 ^= r0; \
     431             :     r0 &= r3; r2 = ~r2; \
     432             :     r0 ^= r4; r4 |= r3; \
     433             :     r2 ^= r4; \
     434             :     \
     435             :     w = r1; x = r3; y = r0; z = r2; \
     436             :   }
     437             : 
     438             : #define SBOX5_INVERSE(r0, r1, r2, r3, w, x, y, z) \
     439             :   { \
     440             :     u32 r4; \
     441             :     \
     442             :     r1 = ~r1; r4 =  r3; \
     443             :     r2 ^= r1; r3 |= r0; \
     444             :     r3 ^= r2; r2 |= r1; \
     445             :     r2 &= r0; r4 ^= r3; \
     446             :     r2 ^= r4; r4 |= r0; \
     447             :     r4 ^= r1; r1 &= r2; \
     448             :     r1 ^= r3; r4 ^= r2; \
     449             :     r3 &= r4; r4 ^= r1; \
     450             :     r3 ^= r4; r4 = ~r4; \
     451             :     r3 ^= r0; \
     452             :     \
     453             :     w = r1; x = r4; y = r3; z = r2; \
     454             :   }
     455             : 
     456             : #define SBOX6(r0, r1, r2, r3, w, x, y, z) \
     457             :   { \
     458             :     u32 r4; \
     459             :     \
     460             :     r2 = ~r2; r4 =  r3; \
     461             :     r3 &= r0; r0 ^= r4; \
     462             :     r3 ^= r2; r2 |= r4; \
     463             :     r1 ^= r3; r2 ^= r0; \
     464             :     r0 |= r1; r2 ^= r1; \
     465             :     r4 ^= r0; r0 |= r3; \
     466             :     r0 ^= r2; r4 ^= r3; \
     467             :     r4 ^= r0; r3 = ~r3; \
     468             :     r2 &= r4; \
     469             :     r2 ^= r3; \
     470             :     \
     471             :     w = r0; x = r1; y = r4; z = r2; \
     472             :   }
     473             : 
     474             : #define SBOX6_INVERSE(r0, r1, r2, r3, w, x, y, z) \
     475             :   { \
     476             :     u32 r4; \
     477             :     \
     478             :     r0 ^= r2; r4 =  r2; \
     479             :     r2 &= r0; r4 ^= r3; \
     480             :     r2 = ~r2; r3 ^= r1; \
     481             :     r2 ^= r3; r4 |= r0; \
     482             :     r0 ^= r2; r3 ^= r4; \
     483             :     r4 ^= r1; r1 &= r3; \
     484             :     r1 ^= r0; r0 ^= r3; \
     485             :     r0 |= r2; r3 ^= r1; \
     486             :     r4 ^= r0; \
     487             :     \
     488             :     w = r1; x = r2; y = r4; z = r3; \
     489             :   }
     490             : 
     491             : #define SBOX7(r0, r1, r2, r3, w, x, y, z) \
     492             :   { \
     493             :     u32 r4; \
     494             :     \
     495             :     r4 =  r1; r1 |= r2; \
     496             :     r1 ^= r3; r4 ^= r2; \
     497             :     r2 ^= r1; r3 |= r4; \
     498             :     r3 &= r0; r4 ^= r2; \
     499             :     r3 ^= r1; r1 |= r4; \
     500             :     r1 ^= r0; r0 |= r4; \
     501             :     r0 ^= r2; r1 ^= r4; \
     502             :     r2 ^= r1; r1 &= r0; \
     503             :     r1 ^= r4; r2 = ~r2; \
     504             :     r2 |= r0; \
     505             :     r4 ^= r2; \
     506             :     \
     507             :     w = r4; x = r3; y = r1; z = r0; \
     508             :   }
     509             : 
     510             : #define SBOX7_INVERSE(r0, r1, r2, r3, w, x, y, z) \
     511             :   { \
     512             :     u32 r4; \
     513             :     \
     514             :     r4 =  r2; r2 ^= r0; \
     515             :     r0 &= r3; r4 |= r3; \
     516             :     r2 = ~r2; r3 ^= r1; \
     517             :     r1 |= r0; r0 ^= r2; \
     518             :     r2 &= r4; r3 &= r4; \
     519             :     r1 ^= r2; r2 ^= r0; \
     520             :     r0 |= r2; r4 ^= r1; \
     521             :     r0 ^= r3; r3 ^= r4; \
     522             :     r4 |= r0; r3 ^= r2; \
     523             :     r4 ^= r2; \
     524             :     \
     525             :     w = r3; x = r0; y = r1; z = r4; \
     526             :   }
     527             : 
     528             : /* XOR BLOCK1 into BLOCK0.  */
     529             : #define BLOCK_XOR(block0, block1) \
     530             :   {                               \
     531             :     block0[0] ^= block1[0];       \
     532             :     block0[1] ^= block1[1];       \
     533             :     block0[2] ^= block1[2];       \
     534             :     block0[3] ^= block1[3];       \
     535             :   }
     536             : 
     537             : /* Copy BLOCK_SRC to BLOCK_DST.  */
     538             : #define BLOCK_COPY(block_dst, block_src) \
     539             :   {                                      \
     540             :     block_dst[0] = block_src[0];         \
     541             :     block_dst[1] = block_src[1];         \
     542             :     block_dst[2] = block_src[2];         \
     543             :     block_dst[3] = block_src[3];         \
     544             :   }
     545             : 
     546             : /* Apply SBOX number WHICH to to the block found in ARRAY0, writing
     547             :    the output to the block found in ARRAY1.  */
     548             : #define SBOX(which, array0, array1)                         \
     549             :   SBOX##which (array0[0], array0[1], array0[2], array0[3],  \
     550             :                array1[0], array1[1], array1[2], array1[3]);
     551             : 
     552             : /* Apply inverse SBOX number WHICH to to the block found in ARRAY0, writing
     553             :    the output to the block found in ARRAY1.  */
     554             : #define SBOX_INVERSE(which, array0, array1)                           \
     555             :   SBOX##which##_INVERSE (array0[0], array0[1], array0[2], array0[3],  \
     556             :                          array1[0], array1[1], array1[2], array1[3]);
     557             : 
     558             : /* Apply the linear transformation to BLOCK.  */
     559             : #define LINEAR_TRANSFORMATION(block)                  \
     560             :   {                                                   \
     561             :     block[0] = rol (block[0], 13);                    \
     562             :     block[2] = rol (block[2], 3);                     \
     563             :     block[1] = block[1] ^ block[0] ^ block[2];        \
     564             :     block[3] = block[3] ^ block[2] ^ (block[0] << 3); \
     565             :     block[1] = rol (block[1], 1);                     \
     566             :     block[3] = rol (block[3], 7);                     \
     567             :     block[0] = block[0] ^ block[1] ^ block[3];        \
     568             :     block[2] = block[2] ^ block[3] ^ (block[1] << 7); \
     569             :     block[0] = rol (block[0], 5);                     \
     570             :     block[2] = rol (block[2], 22);                    \
     571             :   }
     572             : 
     573             : /* Apply the inverse linear transformation to BLOCK.  */
     574             : #define LINEAR_TRANSFORMATION_INVERSE(block)          \
     575             :   {                                                   \
     576             :     block[2] = ror (block[2], 22);                    \
     577             :     block[0] = ror (block[0] , 5);                    \
     578             :     block[2] = block[2] ^ block[3] ^ (block[1] << 7); \
     579             :     block[0] = block[0] ^ block[1] ^ block[3];        \
     580             :     block[3] = ror (block[3], 7);                     \
     581             :     block[1] = ror (block[1], 1);                     \
     582             :     block[3] = block[3] ^ block[2] ^ (block[0] << 3); \
     583             :     block[1] = block[1] ^ block[0] ^ block[2];        \
     584             :     block[2] = ror (block[2], 3);                     \
     585             :     block[0] = ror (block[0], 13);                    \
     586             :   }
     587             : 
     588             : /* Apply a Serpent round to BLOCK, using the SBOX number WHICH and the
     589             :    subkeys contained in SUBKEYS.  Use BLOCK_TMP as temporary storage.
     590             :    This macro increments `round'.  */
     591             : #define ROUND(which, subkeys, block, block_tmp) \
     592             :   {                                             \
     593             :     BLOCK_XOR (block, subkeys[round]);          \
     594             :     round++;                                    \
     595             :     SBOX (which, block, block_tmp);             \
     596             :     LINEAR_TRANSFORMATION (block_tmp);          \
     597             :     BLOCK_COPY (block, block_tmp);              \
     598             :   }
     599             : 
     600             : /* Apply the last Serpent round to BLOCK, using the SBOX number WHICH
     601             :    and the subkeys contained in SUBKEYS.  Use BLOCK_TMP as temporary
     602             :    storage.  The result will be stored in BLOCK_TMP.  This macro
     603             :    increments `round'.  */
     604             : #define ROUND_LAST(which, subkeys, block, block_tmp) \
     605             :   {                                                  \
     606             :     BLOCK_XOR (block, subkeys[round]);               \
     607             :     round++;                                         \
     608             :     SBOX (which, block, block_tmp);                  \
     609             :     BLOCK_XOR (block_tmp, subkeys[round]);           \
     610             :     round++;                                         \
     611             :   }
     612             : 
     613             : /* Apply an inverse Serpent round to BLOCK, using the SBOX number
     614             :    WHICH and the subkeys contained in SUBKEYS.  Use BLOCK_TMP as
     615             :    temporary storage.  This macro increments `round'.  */
     616             : #define ROUND_INVERSE(which, subkey, block, block_tmp) \
     617             :   {                                                    \
     618             :     LINEAR_TRANSFORMATION_INVERSE (block);             \
     619             :     SBOX_INVERSE (which, block, block_tmp);            \
     620             :     BLOCK_XOR (block_tmp, subkey[round]);              \
     621             :     round--;                                           \
     622             :     BLOCK_COPY (block, block_tmp);                     \
     623             :   }
     624             : 
     625             : /* Apply the first Serpent round to BLOCK, using the SBOX number WHICH
     626             :    and the subkeys contained in SUBKEYS.  Use BLOCK_TMP as temporary
     627             :    storage.  The result will be stored in BLOCK_TMP.  This macro
     628             :    increments `round'.  */
     629             : #define ROUND_FIRST_INVERSE(which, subkeys, block, block_tmp) \
     630             :   {                                                           \
     631             :     BLOCK_XOR (block, subkeys[round]);                        \
     632             :     round--;                                                  \
     633             :     SBOX_INVERSE (which, block, block_tmp);                   \
     634             :     BLOCK_XOR (block_tmp, subkeys[round]);                    \
     635             :     round--;                                                  \
     636             :   }
     637             : 
     638             : /* Convert the user provided key KEY of KEY_LENGTH bytes into the
     639             :    internally used format.  */
     640             : static void
     641           0 : serpent_key_prepare (const byte *key, unsigned int key_length,
     642             :                      serpent_key_t key_prepared)
     643             : {
     644             :   int i;
     645             : 
     646             :   /* Copy key.  */
     647           0 :   key_length /= 4;
     648           0 :   for (i = 0; i < key_length; i++)
     649           0 :     key_prepared[i] = buf_get_le32 (key + i * 4);
     650             : 
     651           0 :   if (i < 8)
     652             :     {
     653             :       /* Key must be padded according to the Serpent
     654             :          specification.  */
     655           0 :       key_prepared[i] = 0x00000001;
     656             : 
     657           0 :       for (i++; i < 8; i++)
     658           0 :         key_prepared[i] = 0;
     659             :     }
     660           0 : }
     661             : 
     662             : /* Derive the 33 subkeys from KEY and store them in SUBKEYS.  */
     663             : static void
     664           0 : serpent_subkeys_generate (serpent_key_t key, serpent_subkeys_t subkeys)
     665             : {
     666             :   u32 w[8];             /* The `prekey'.  */
     667             :   u32 ws[4];
     668             :   u32 wt[4];
     669             : 
     670             :   /* Initialize with key values.  */
     671           0 :   w[0] = key[0];
     672           0 :   w[1] = key[1];
     673           0 :   w[2] = key[2];
     674           0 :   w[3] = key[3];
     675           0 :   w[4] = key[4];
     676           0 :   w[5] = key[5];
     677           0 :   w[6] = key[6];
     678           0 :   w[7] = key[7];
     679             : 
     680             :   /* Expand to intermediate key using the affine recurrence.  */
     681             : #define EXPAND_KEY4(wo, r)                                                     \
     682             :   wo[0] = w[(r+0)%8] =                                                         \
     683             :     rol (w[(r+0)%8] ^ w[(r+3)%8] ^ w[(r+5)%8] ^ w[(r+7)%8] ^ PHI ^ (r+0), 11); \
     684             :   wo[1] = w[(r+1)%8] =                                                         \
     685             :     rol (w[(r+1)%8] ^ w[(r+4)%8] ^ w[(r+6)%8] ^ w[(r+0)%8] ^ PHI ^ (r+1), 11); \
     686             :   wo[2] = w[(r+2)%8] =                                                         \
     687             :     rol (w[(r+2)%8] ^ w[(r+5)%8] ^ w[(r+7)%8] ^ w[(r+1)%8] ^ PHI ^ (r+2), 11); \
     688             :   wo[3] = w[(r+3)%8] =                                                         \
     689             :     rol (w[(r+3)%8] ^ w[(r+6)%8] ^ w[(r+0)%8] ^ w[(r+2)%8] ^ PHI ^ (r+3), 11);
     690             : 
     691             : #define EXPAND_KEY(r)       \
     692             :   EXPAND_KEY4(ws, (r));     \
     693             :   EXPAND_KEY4(wt, (r + 4));
     694             : 
     695             :   /* Calculate subkeys via S-Boxes, in bitslice mode.  */
     696           0 :   EXPAND_KEY (0); SBOX (3, ws, subkeys[0]); SBOX (2, wt, subkeys[1]);
     697           0 :   EXPAND_KEY (8); SBOX (1, ws, subkeys[2]); SBOX (0, wt, subkeys[3]);
     698           0 :   EXPAND_KEY (16); SBOX (7, ws, subkeys[4]); SBOX (6, wt, subkeys[5]);
     699           0 :   EXPAND_KEY (24); SBOX (5, ws, subkeys[6]); SBOX (4, wt, subkeys[7]);
     700           0 :   EXPAND_KEY (32); SBOX (3, ws, subkeys[8]); SBOX (2, wt, subkeys[9]);
     701           0 :   EXPAND_KEY (40); SBOX (1, ws, subkeys[10]); SBOX (0, wt, subkeys[11]);
     702           0 :   EXPAND_KEY (48); SBOX (7, ws, subkeys[12]); SBOX (6, wt, subkeys[13]);
     703           0 :   EXPAND_KEY (56); SBOX (5, ws, subkeys[14]); SBOX (4, wt, subkeys[15]);
     704           0 :   EXPAND_KEY (64); SBOX (3, ws, subkeys[16]); SBOX (2, wt, subkeys[17]);
     705           0 :   EXPAND_KEY (72); SBOX (1, ws, subkeys[18]); SBOX (0, wt, subkeys[19]);
     706           0 :   EXPAND_KEY (80); SBOX (7, ws, subkeys[20]); SBOX (6, wt, subkeys[21]);
     707           0 :   EXPAND_KEY (88); SBOX (5, ws, subkeys[22]); SBOX (4, wt, subkeys[23]);
     708           0 :   EXPAND_KEY (96); SBOX (3, ws, subkeys[24]); SBOX (2, wt, subkeys[25]);
     709           0 :   EXPAND_KEY (104); SBOX (1, ws, subkeys[26]); SBOX (0, wt, subkeys[27]);
     710           0 :   EXPAND_KEY (112); SBOX (7, ws, subkeys[28]); SBOX (6, wt, subkeys[29]);
     711           0 :   EXPAND_KEY (120); SBOX (5, ws, subkeys[30]); SBOX (4, wt, subkeys[31]);
     712           0 :   EXPAND_KEY4 (ws, 128); SBOX (3, ws, subkeys[32]);
     713             : 
     714           0 :   wipememory (ws, sizeof (ws));
     715           0 :   wipememory (wt, sizeof (wt));
     716           0 :   wipememory (w, sizeof (w));
     717           0 : }
     718             : 
     719             : /* Initialize CONTEXT with the key KEY of KEY_LENGTH bits.  */
     720             : static void
     721           0 : serpent_setkey_internal (serpent_context_t *context,
     722             :                          const byte *key, unsigned int key_length)
     723             : {
     724             :   serpent_key_t key_prepared;
     725             : 
     726           0 :   serpent_key_prepare (key, key_length, key_prepared);
     727           0 :   serpent_subkeys_generate (key_prepared, context->keys);
     728             : 
     729             : #ifdef USE_AVX2
     730           0 :   context->use_avx2 = 0;
     731           0 :   if ((_gcry_get_hw_features () & HWF_INTEL_AVX2))
     732             :     {
     733           0 :       context->use_avx2 = 1;
     734             :     }
     735             : #endif
     736             : 
     737             : #ifdef USE_NEON
     738             :   context->use_neon = 0;
     739             :   if ((_gcry_get_hw_features () & HWF_ARM_NEON))
     740             :     {
     741             :       context->use_neon = 1;
     742             :     }
     743             : #endif
     744             : 
     745           0 :   wipememory (key_prepared, sizeof(key_prepared));
     746           0 : }
     747             : 
     748             : /* Initialize CTX with the key KEY of KEY_LENGTH bytes.  */
     749             : static gcry_err_code_t
     750           0 : serpent_setkey (void *ctx,
     751             :                 const byte *key, unsigned int key_length)
     752             : {
     753           0 :   serpent_context_t *context = ctx;
     754             :   static const char *serpent_test_ret;
     755             :   static int serpent_init_done;
     756           0 :   gcry_err_code_t ret = GPG_ERR_NO_ERROR;
     757             : 
     758           0 :   if (! serpent_init_done)
     759             :     {
     760             :       /* Execute a self-test the first time, Serpent is used.  */
     761           0 :       serpent_init_done = 1;
     762           0 :       serpent_test_ret = serpent_test ();
     763           0 :       if (serpent_test_ret)
     764           0 :         log_error ("Serpent test failure: %s\n", serpent_test_ret);
     765             :     }
     766             : 
     767           0 :   if (serpent_test_ret)
     768           0 :     ret = GPG_ERR_SELFTEST_FAILED;
     769             :   else
     770           0 :     serpent_setkey_internal (context, key, key_length);
     771             : 
     772           0 :   return ret;
     773             : }
     774             : 
     775             : static void
     776           0 : serpent_encrypt_internal (serpent_context_t *context,
     777             :                           const byte *input, byte *output)
     778             : {
     779             :   serpent_block_t b, b_next;
     780           0 :   int round = 0;
     781             : 
     782           0 :   b[0] = buf_get_le32 (input + 0);
     783           0 :   b[1] = buf_get_le32 (input + 4);
     784           0 :   b[2] = buf_get_le32 (input + 8);
     785           0 :   b[3] = buf_get_le32 (input + 12);
     786             : 
     787           0 :   ROUND (0, context->keys, b, b_next);
     788           0 :   ROUND (1, context->keys, b, b_next);
     789           0 :   ROUND (2, context->keys, b, b_next);
     790           0 :   ROUND (3, context->keys, b, b_next);
     791           0 :   ROUND (4, context->keys, b, b_next);
     792           0 :   ROUND (5, context->keys, b, b_next);
     793           0 :   ROUND (6, context->keys, b, b_next);
     794           0 :   ROUND (7, context->keys, b, b_next);
     795           0 :   ROUND (0, context->keys, b, b_next);
     796           0 :   ROUND (1, context->keys, b, b_next);
     797           0 :   ROUND (2, context->keys, b, b_next);
     798           0 :   ROUND (3, context->keys, b, b_next);
     799           0 :   ROUND (4, context->keys, b, b_next);
     800           0 :   ROUND (5, context->keys, b, b_next);
     801           0 :   ROUND (6, context->keys, b, b_next);
     802           0 :   ROUND (7, context->keys, b, b_next);
     803           0 :   ROUND (0, context->keys, b, b_next);
     804           0 :   ROUND (1, context->keys, b, b_next);
     805           0 :   ROUND (2, context->keys, b, b_next);
     806           0 :   ROUND (3, context->keys, b, b_next);
     807           0 :   ROUND (4, context->keys, b, b_next);
     808           0 :   ROUND (5, context->keys, b, b_next);
     809           0 :   ROUND (6, context->keys, b, b_next);
     810           0 :   ROUND (7, context->keys, b, b_next);
     811           0 :   ROUND (0, context->keys, b, b_next);
     812           0 :   ROUND (1, context->keys, b, b_next);
     813           0 :   ROUND (2, context->keys, b, b_next);
     814           0 :   ROUND (3, context->keys, b, b_next);
     815           0 :   ROUND (4, context->keys, b, b_next);
     816           0 :   ROUND (5, context->keys, b, b_next);
     817           0 :   ROUND (6, context->keys, b, b_next);
     818             : 
     819           0 :   ROUND_LAST (7, context->keys, b, b_next);
     820             : 
     821           0 :   buf_put_le32 (output + 0, b_next[0]);
     822           0 :   buf_put_le32 (output + 4, b_next[1]);
     823           0 :   buf_put_le32 (output + 8, b_next[2]);
     824           0 :   buf_put_le32 (output + 12, b_next[3]);
     825           0 : }
     826             : 
     827             : static void
     828           0 : serpent_decrypt_internal (serpent_context_t *context,
     829             :                           const byte *input, byte *output)
     830             : {
     831             :   serpent_block_t b, b_next;
     832           0 :   int round = ROUNDS;
     833             : 
     834           0 :   b_next[0] = buf_get_le32 (input + 0);
     835           0 :   b_next[1] = buf_get_le32 (input + 4);
     836           0 :   b_next[2] = buf_get_le32 (input + 8);
     837           0 :   b_next[3] = buf_get_le32 (input + 12);
     838             : 
     839           0 :   ROUND_FIRST_INVERSE (7, context->keys, b_next, b);
     840             : 
     841           0 :   ROUND_INVERSE (6, context->keys, b, b_next);
     842           0 :   ROUND_INVERSE (5, context->keys, b, b_next);
     843           0 :   ROUND_INVERSE (4, context->keys, b, b_next);
     844           0 :   ROUND_INVERSE (3, context->keys, b, b_next);
     845           0 :   ROUND_INVERSE (2, context->keys, b, b_next);
     846           0 :   ROUND_INVERSE (1, context->keys, b, b_next);
     847           0 :   ROUND_INVERSE (0, context->keys, b, b_next);
     848           0 :   ROUND_INVERSE (7, context->keys, b, b_next);
     849           0 :   ROUND_INVERSE (6, context->keys, b, b_next);
     850           0 :   ROUND_INVERSE (5, context->keys, b, b_next);
     851           0 :   ROUND_INVERSE (4, context->keys, b, b_next);
     852           0 :   ROUND_INVERSE (3, context->keys, b, b_next);
     853           0 :   ROUND_INVERSE (2, context->keys, b, b_next);
     854           0 :   ROUND_INVERSE (1, context->keys, b, b_next);
     855           0 :   ROUND_INVERSE (0, context->keys, b, b_next);
     856           0 :   ROUND_INVERSE (7, context->keys, b, b_next);
     857           0 :   ROUND_INVERSE (6, context->keys, b, b_next);
     858           0 :   ROUND_INVERSE (5, context->keys, b, b_next);
     859           0 :   ROUND_INVERSE (4, context->keys, b, b_next);
     860           0 :   ROUND_INVERSE (3, context->keys, b, b_next);
     861           0 :   ROUND_INVERSE (2, context->keys, b, b_next);
     862           0 :   ROUND_INVERSE (1, context->keys, b, b_next);
     863           0 :   ROUND_INVERSE (0, context->keys, b, b_next);
     864           0 :   ROUND_INVERSE (7, context->keys, b, b_next);
     865           0 :   ROUND_INVERSE (6, context->keys, b, b_next);
     866           0 :   ROUND_INVERSE (5, context->keys, b, b_next);
     867           0 :   ROUND_INVERSE (4, context->keys, b, b_next);
     868           0 :   ROUND_INVERSE (3, context->keys, b, b_next);
     869           0 :   ROUND_INVERSE (2, context->keys, b, b_next);
     870           0 :   ROUND_INVERSE (1, context->keys, b, b_next);
     871           0 :   ROUND_INVERSE (0, context->keys, b, b_next);
     872             : 
     873           0 :   buf_put_le32 (output + 0, b_next[0]);
     874           0 :   buf_put_le32 (output + 4, b_next[1]);
     875           0 :   buf_put_le32 (output + 8, b_next[2]);
     876           0 :   buf_put_le32 (output + 12, b_next[3]);
     877           0 : }
     878             : 
     879             : static unsigned int
     880           0 : serpent_encrypt (void *ctx, byte *buffer_out, const byte *buffer_in)
     881             : {
     882           0 :   serpent_context_t *context = ctx;
     883             : 
     884           0 :   serpent_encrypt_internal (context, buffer_in, buffer_out);
     885           0 :   return /*burn_stack*/ (2 * sizeof (serpent_block_t));
     886             : }
     887             : 
     888             : static unsigned int
     889           0 : serpent_decrypt (void *ctx, byte *buffer_out, const byte *buffer_in)
     890             : {
     891           0 :   serpent_context_t *context = ctx;
     892             : 
     893           0 :   serpent_decrypt_internal (context, buffer_in, buffer_out);
     894           0 :   return /*burn_stack*/ (2 * sizeof (serpent_block_t));
     895             : }
     896             : 
     897             : 
     898             : 
     899             : /* Bulk encryption of complete blocks in CTR mode.  This function is only
     900             :    intended for the bulk encryption feature of cipher.c.  CTR is expected to be
     901             :    of size sizeof(serpent_block_t). */
     902             : void
     903           0 : _gcry_serpent_ctr_enc(void *context, unsigned char *ctr,
     904             :                       void *outbuf_arg, const void *inbuf_arg,
     905             :                       size_t nblocks)
     906             : {
     907           0 :   serpent_context_t *ctx = context;
     908           0 :   unsigned char *outbuf = outbuf_arg;
     909           0 :   const unsigned char *inbuf = inbuf_arg;
     910             :   unsigned char tmpbuf[sizeof(serpent_block_t)];
     911           0 :   int burn_stack_depth = 2 * sizeof (serpent_block_t);
     912             :   int i;
     913             : 
     914             : #ifdef USE_AVX2
     915           0 :   if (ctx->use_avx2)
     916             :     {
     917           0 :       int did_use_avx2 = 0;
     918             : 
     919             :       /* Process data in 16 block chunks. */
     920           0 :       while (nblocks >= 16)
     921             :         {
     922           0 :           _gcry_serpent_avx2_ctr_enc(ctx, outbuf, inbuf, ctr);
     923             : 
     924           0 :           nblocks -= 16;
     925           0 :           outbuf += 16 * sizeof(serpent_block_t);
     926           0 :           inbuf  += 16 * sizeof(serpent_block_t);
     927           0 :           did_use_avx2 = 1;
     928             :         }
     929             : 
     930           0 :       if (did_use_avx2)
     931             :         {
     932             :           /* serpent-avx2 assembly code does not use stack */
     933           0 :           if (nblocks == 0)
     934           0 :             burn_stack_depth = 0;
     935             :         }
     936             : 
     937             :       /* Use generic/sse2 code to handle smaller chunks... */
     938             :       /* TODO: use caching instead? */
     939             :     }
     940             : #endif
     941             : 
     942             : #ifdef USE_SSE2
     943             :   {
     944           0 :     int did_use_sse2 = 0;
     945             : 
     946             :     /* Process data in 8 block chunks. */
     947           0 :     while (nblocks >= 8)
     948             :       {
     949           0 :         _gcry_serpent_sse2_ctr_enc(ctx, outbuf, inbuf, ctr);
     950             : 
     951           0 :         nblocks -= 8;
     952           0 :         outbuf += 8 * sizeof(serpent_block_t);
     953           0 :         inbuf  += 8 * sizeof(serpent_block_t);
     954           0 :         did_use_sse2 = 1;
     955             :       }
     956             : 
     957           0 :     if (did_use_sse2)
     958             :       {
     959             :         /* serpent-sse2 assembly code does not use stack */
     960           0 :         if (nblocks == 0)
     961           0 :           burn_stack_depth = 0;
     962             :       }
     963             : 
     964             :     /* Use generic code to handle smaller chunks... */
     965             :     /* TODO: use caching instead? */
     966             :   }
     967             : #endif
     968             : 
     969             : #ifdef USE_NEON
     970             :   if (ctx->use_neon)
     971             :     {
     972             :       int did_use_neon = 0;
     973             : 
     974             :       /* Process data in 8 block chunks. */
     975             :       while (nblocks >= 8)
     976             :         {
     977             :           _gcry_serpent_neon_ctr_enc(ctx, outbuf, inbuf, ctr);
     978             : 
     979             :           nblocks -= 8;
     980             :           outbuf += 8 * sizeof(serpent_block_t);
     981             :           inbuf  += 8 * sizeof(serpent_block_t);
     982             :           did_use_neon = 1;
     983             :         }
     984             : 
     985             :       if (did_use_neon)
     986             :         {
     987             :           /* serpent-neon assembly code does not use stack */
     988             :           if (nblocks == 0)
     989             :             burn_stack_depth = 0;
     990             :         }
     991             : 
     992             :       /* Use generic code to handle smaller chunks... */
     993             :       /* TODO: use caching instead? */
     994             :     }
     995             : #endif
     996             : 
     997           0 :   for ( ;nblocks; nblocks-- )
     998             :     {
     999             :       /* Encrypt the counter. */
    1000           0 :       serpent_encrypt_internal(ctx, ctr, tmpbuf);
    1001             :       /* XOR the input with the encrypted counter and store in output.  */
    1002           0 :       buf_xor(outbuf, tmpbuf, inbuf, sizeof(serpent_block_t));
    1003           0 :       outbuf += sizeof(serpent_block_t);
    1004           0 :       inbuf  += sizeof(serpent_block_t);
    1005             :       /* Increment the counter.  */
    1006           0 :       for (i = sizeof(serpent_block_t); i > 0; i--)
    1007             :         {
    1008           0 :           ctr[i-1]++;
    1009           0 :           if (ctr[i-1])
    1010           0 :             break;
    1011             :         }
    1012             :     }
    1013             : 
    1014           0 :   wipememory(tmpbuf, sizeof(tmpbuf));
    1015           0 :   _gcry_burn_stack(burn_stack_depth);
    1016           0 : }
    1017             : 
    1018             : /* Bulk decryption of complete blocks in CBC mode.  This function is only
    1019             :    intended for the bulk encryption feature of cipher.c. */
    1020             : void
    1021           0 : _gcry_serpent_cbc_dec(void *context, unsigned char *iv,
    1022             :                       void *outbuf_arg, const void *inbuf_arg,
    1023             :                       size_t nblocks)
    1024             : {
    1025           0 :   serpent_context_t *ctx = context;
    1026           0 :   unsigned char *outbuf = outbuf_arg;
    1027           0 :   const unsigned char *inbuf = inbuf_arg;
    1028             :   unsigned char savebuf[sizeof(serpent_block_t)];
    1029           0 :   int burn_stack_depth = 2 * sizeof (serpent_block_t);
    1030             : 
    1031             : #ifdef USE_AVX2
    1032           0 :   if (ctx->use_avx2)
    1033             :     {
    1034           0 :       int did_use_avx2 = 0;
    1035             : 
    1036             :       /* Process data in 16 block chunks. */
    1037           0 :       while (nblocks >= 16)
    1038             :         {
    1039           0 :           _gcry_serpent_avx2_cbc_dec(ctx, outbuf, inbuf, iv);
    1040             : 
    1041           0 :           nblocks -= 16;
    1042           0 :           outbuf += 16 * sizeof(serpent_block_t);
    1043           0 :           inbuf  += 16 * sizeof(serpent_block_t);
    1044           0 :           did_use_avx2 = 1;
    1045             :         }
    1046             : 
    1047           0 :       if (did_use_avx2)
    1048             :         {
    1049             :           /* serpent-avx2 assembly code does not use stack */
    1050           0 :           if (nblocks == 0)
    1051           0 :             burn_stack_depth = 0;
    1052             :         }
    1053             : 
    1054             :       /* Use generic/sse2 code to handle smaller chunks... */
    1055             :     }
    1056             : #endif
    1057             : 
    1058             : #ifdef USE_SSE2
    1059             :   {
    1060           0 :     int did_use_sse2 = 0;
    1061             : 
    1062             :     /* Process data in 8 block chunks. */
    1063           0 :     while (nblocks >= 8)
    1064             :       {
    1065           0 :         _gcry_serpent_sse2_cbc_dec(ctx, outbuf, inbuf, iv);
    1066             : 
    1067           0 :         nblocks -= 8;
    1068           0 :         outbuf += 8 * sizeof(serpent_block_t);
    1069           0 :         inbuf  += 8 * sizeof(serpent_block_t);
    1070           0 :         did_use_sse2 = 1;
    1071             :       }
    1072             : 
    1073           0 :     if (did_use_sse2)
    1074             :       {
    1075             :         /* serpent-sse2 assembly code does not use stack */
    1076           0 :         if (nblocks == 0)
    1077           0 :           burn_stack_depth = 0;
    1078             :       }
    1079             : 
    1080             :     /* Use generic code to handle smaller chunks... */
    1081             :   }
    1082             : #endif
    1083             : 
    1084             : #ifdef USE_NEON
    1085             :   if (ctx->use_neon)
    1086             :     {
    1087             :       int did_use_neon = 0;
    1088             : 
    1089             :       /* Process data in 8 block chunks. */
    1090             :       while (nblocks >= 8)
    1091             :         {
    1092             :           _gcry_serpent_neon_cbc_dec(ctx, outbuf, inbuf, iv);
    1093             : 
    1094             :           nblocks -= 8;
    1095             :           outbuf += 8 * sizeof(serpent_block_t);
    1096             :           inbuf  += 8 * sizeof(serpent_block_t);
    1097             :           did_use_neon = 1;
    1098             :         }
    1099             : 
    1100             :       if (did_use_neon)
    1101             :         {
    1102             :           /* serpent-neon assembly code does not use stack */
    1103             :           if (nblocks == 0)
    1104             :             burn_stack_depth = 0;
    1105             :         }
    1106             : 
    1107             :       /* Use generic code to handle smaller chunks... */
    1108             :     }
    1109             : #endif
    1110             : 
    1111           0 :   for ( ;nblocks; nblocks-- )
    1112             :     {
    1113             :       /* INBUF is needed later and it may be identical to OUTBUF, so store
    1114             :          the intermediate result to SAVEBUF.  */
    1115           0 :       serpent_decrypt_internal (ctx, inbuf, savebuf);
    1116             : 
    1117           0 :       buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, sizeof(serpent_block_t));
    1118           0 :       inbuf += sizeof(serpent_block_t);
    1119           0 :       outbuf += sizeof(serpent_block_t);
    1120             :     }
    1121             : 
    1122           0 :   wipememory(savebuf, sizeof(savebuf));
    1123           0 :   _gcry_burn_stack(burn_stack_depth);
    1124           0 : }
    1125             : 
    1126             : /* Bulk decryption of complete blocks in CFB mode.  This function is only
    1127             :    intended for the bulk encryption feature of cipher.c. */
    1128             : void
    1129           0 : _gcry_serpent_cfb_dec(void *context, unsigned char *iv,
    1130             :                       void *outbuf_arg, const void *inbuf_arg,
    1131             :                       size_t nblocks)
    1132             : {
    1133           0 :   serpent_context_t *ctx = context;
    1134           0 :   unsigned char *outbuf = outbuf_arg;
    1135           0 :   const unsigned char *inbuf = inbuf_arg;
    1136           0 :   int burn_stack_depth = 2 * sizeof (serpent_block_t);
    1137             : 
    1138             : #ifdef USE_AVX2
    1139           0 :   if (ctx->use_avx2)
    1140             :     {
    1141           0 :       int did_use_avx2 = 0;
    1142             : 
    1143             :       /* Process data in 16 block chunks. */
    1144           0 :       while (nblocks >= 16)
    1145             :         {
    1146           0 :           _gcry_serpent_avx2_cfb_dec(ctx, outbuf, inbuf, iv);
    1147             : 
    1148           0 :           nblocks -= 16;
    1149           0 :           outbuf += 16 * sizeof(serpent_block_t);
    1150           0 :           inbuf  += 16 * sizeof(serpent_block_t);
    1151           0 :           did_use_avx2 = 1;
    1152             :         }
    1153             : 
    1154           0 :       if (did_use_avx2)
    1155             :         {
    1156             :           /* serpent-avx2 assembly code does not use stack */
    1157           0 :           if (nblocks == 0)
    1158           0 :             burn_stack_depth = 0;
    1159             :         }
    1160             : 
    1161             :       /* Use generic/sse2 code to handle smaller chunks... */
    1162             :     }
    1163             : #endif
    1164             : 
    1165             : #ifdef USE_SSE2
    1166             :   {
    1167           0 :     int did_use_sse2 = 0;
    1168             : 
    1169             :     /* Process data in 8 block chunks. */
    1170           0 :     while (nblocks >= 8)
    1171             :       {
    1172           0 :         _gcry_serpent_sse2_cfb_dec(ctx, outbuf, inbuf, iv);
    1173             : 
    1174           0 :         nblocks -= 8;
    1175           0 :         outbuf += 8 * sizeof(serpent_block_t);
    1176           0 :         inbuf  += 8 * sizeof(serpent_block_t);
    1177           0 :         did_use_sse2 = 1;
    1178             :       }
    1179             : 
    1180           0 :     if (did_use_sse2)
    1181             :       {
    1182             :         /* serpent-sse2 assembly code does not use stack */
    1183           0 :         if (nblocks == 0)
    1184           0 :           burn_stack_depth = 0;
    1185             :       }
    1186             : 
    1187             :     /* Use generic code to handle smaller chunks... */
    1188             :   }
    1189             : #endif
    1190             : 
    1191             : #ifdef USE_NEON
    1192             :   if (ctx->use_neon)
    1193             :     {
    1194             :       int did_use_neon = 0;
    1195             : 
    1196             :       /* Process data in 8 block chunks. */
    1197             :       while (nblocks >= 8)
    1198             :         {
    1199             :           _gcry_serpent_neon_cfb_dec(ctx, outbuf, inbuf, iv);
    1200             : 
    1201             :           nblocks -= 8;
    1202             :           outbuf += 8 * sizeof(serpent_block_t);
    1203             :           inbuf  += 8 * sizeof(serpent_block_t);
    1204             :           did_use_neon = 1;
    1205             :         }
    1206             : 
    1207             :       if (did_use_neon)
    1208             :         {
    1209             :           /* serpent-neon assembly code does not use stack */
    1210             :           if (nblocks == 0)
    1211             :             burn_stack_depth = 0;
    1212             :         }
    1213             : 
    1214             :       /* Use generic code to handle smaller chunks... */
    1215             :     }
    1216             : #endif
    1217             : 
    1218           0 :   for ( ;nblocks; nblocks-- )
    1219             :     {
    1220           0 :       serpent_encrypt_internal(ctx, iv, iv);
    1221           0 :       buf_xor_n_copy(outbuf, iv, inbuf, sizeof(serpent_block_t));
    1222           0 :       outbuf += sizeof(serpent_block_t);
    1223           0 :       inbuf  += sizeof(serpent_block_t);
    1224             :     }
    1225             : 
    1226           0 :   _gcry_burn_stack(burn_stack_depth);
    1227           0 : }
    1228             : 
    1229             : /* Bulk encryption/decryption of complete blocks in OCB mode. */
    1230             : size_t
    1231           0 : _gcry_serpent_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
    1232             :                         const void *inbuf_arg, size_t nblocks, int encrypt)
    1233             : {
    1234             : #if defined(USE_AVX2) || defined(USE_SSE2) || defined(USE_NEON)
    1235           0 :   serpent_context_t *ctx = (void *)&c->context.c;
    1236           0 :   unsigned char *outbuf = outbuf_arg;
    1237           0 :   const unsigned char *inbuf = inbuf_arg;
    1238           0 :   int burn_stack_depth = 2 * sizeof (serpent_block_t);
    1239           0 :   u64 blkn = c->u_mode.ocb.data_nblocks;
    1240             : #else
    1241             :   (void)c;
    1242             :   (void)outbuf_arg;
    1243             :   (void)inbuf_arg;
    1244             :   (void)encrypt;
    1245             : #endif
    1246             : 
    1247             : #ifdef USE_AVX2
    1248           0 :   if (ctx->use_avx2)
    1249             :     {
    1250           0 :       int did_use_avx2 = 0;
    1251             :       u64 Ls[16];
    1252           0 :       unsigned int n = 16 - (blkn % 16);
    1253             :       u64 *l;
    1254             :       int i;
    1255             : 
    1256           0 :       if (nblocks >= 16)
    1257             :         {
    1258           0 :           for (i = 0; i < 16; i += 8)
    1259             :             {
    1260             :               /* Use u64 to store pointers for x32 support (assembly function
    1261             :                * assumes 64-bit pointers). */
    1262           0 :               Ls[(i + 0 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
    1263           0 :               Ls[(i + 1 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[1];
    1264           0 :               Ls[(i + 2 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
    1265           0 :               Ls[(i + 3 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[2];
    1266           0 :               Ls[(i + 4 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
    1267           0 :               Ls[(i + 5 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[1];
    1268           0 :               Ls[(i + 6 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
    1269             :             }
    1270             : 
    1271           0 :           Ls[(7 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[3];
    1272           0 :           l = &Ls[(15 + n) % 16];
    1273             : 
    1274             :           /* Process data in 16 block chunks. */
    1275           0 :           while (nblocks >= 16)
    1276             :             {
    1277           0 :               blkn += 16;
    1278           0 :               *l = (uintptr_t)(void *)ocb_get_l(c, blkn - blkn % 16);
    1279             : 
    1280           0 :               if (encrypt)
    1281           0 :                 _gcry_serpent_avx2_ocb_enc(ctx, outbuf, inbuf, c->u_iv.iv,
    1282           0 :                                           c->u_ctr.ctr, Ls);
    1283             :               else
    1284           0 :                 _gcry_serpent_avx2_ocb_dec(ctx, outbuf, inbuf, c->u_iv.iv,
    1285           0 :                                           c->u_ctr.ctr, Ls);
    1286             : 
    1287           0 :               nblocks -= 16;
    1288           0 :               outbuf += 16 * sizeof(serpent_block_t);
    1289           0 :               inbuf  += 16 * sizeof(serpent_block_t);
    1290           0 :               did_use_avx2 = 1;
    1291             :             }
    1292             :         }
    1293             : 
    1294           0 :       if (did_use_avx2)
    1295             :         {
    1296             :           /* serpent-avx2 assembly code does not use stack */
    1297           0 :           if (nblocks == 0)
    1298           0 :             burn_stack_depth = 0;
    1299             :         }
    1300             : 
    1301             :       /* Use generic code to handle smaller chunks... */
    1302             :     }
    1303             : #endif
    1304             : 
    1305             : #ifdef USE_SSE2
    1306             :   {
    1307           0 :     int did_use_sse2 = 0;
    1308             :     u64 Ls[8];
    1309           0 :     unsigned int n = 8 - (blkn % 8);
    1310             :     u64 *l;
    1311             : 
    1312           0 :     if (nblocks >= 8)
    1313             :       {
    1314             :         /* Use u64 to store pointers for x32 support (assembly function
    1315             :           * assumes 64-bit pointers). */
    1316           0 :         Ls[(0 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
    1317           0 :         Ls[(1 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[1];
    1318           0 :         Ls[(2 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
    1319           0 :         Ls[(3 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[2];
    1320           0 :         Ls[(4 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
    1321           0 :         Ls[(5 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[1];
    1322           0 :         Ls[(6 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
    1323           0 :         l = &Ls[(7 + n) % 8];
    1324             : 
    1325             :         /* Process data in 8 block chunks. */
    1326           0 :         while (nblocks >= 8)
    1327             :           {
    1328           0 :             blkn += 8;
    1329           0 :             *l = (uintptr_t)(void *)ocb_get_l(c, blkn - blkn % 8);
    1330             : 
    1331           0 :             if (encrypt)
    1332           0 :               _gcry_serpent_sse2_ocb_enc(ctx, outbuf, inbuf, c->u_iv.iv,
    1333           0 :                                           c->u_ctr.ctr, Ls);
    1334             :             else
    1335           0 :               _gcry_serpent_sse2_ocb_dec(ctx, outbuf, inbuf, c->u_iv.iv,
    1336           0 :                                           c->u_ctr.ctr, Ls);
    1337             : 
    1338           0 :             nblocks -= 8;
    1339           0 :             outbuf += 8 * sizeof(serpent_block_t);
    1340           0 :             inbuf  += 8 * sizeof(serpent_block_t);
    1341           0 :             did_use_sse2 = 1;
    1342             :           }
    1343             :       }
    1344             : 
    1345           0 :     if (did_use_sse2)
    1346             :       {
    1347             :         /* serpent-sse2 assembly code does not use stack */
    1348           0 :         if (nblocks == 0)
    1349           0 :           burn_stack_depth = 0;
    1350             :       }
    1351             : 
    1352             :     /* Use generic code to handle smaller chunks... */
    1353             :   }
    1354             : #endif
    1355             : 
    1356             : #ifdef USE_NEON
    1357             :   if (ctx->use_neon)
    1358             :     {
    1359             :       int did_use_neon = 0;
    1360             :       const void *Ls[8];
    1361             :       unsigned int n = 8 - (blkn % 8);
    1362             :       const void **l;
    1363             : 
    1364             :       if (nblocks >= 8)
    1365             :         {
    1366             :           Ls[(0 + n) % 8] = c->u_mode.ocb.L[0];
    1367             :           Ls[(1 + n) % 8] = c->u_mode.ocb.L[1];
    1368             :           Ls[(2 + n) % 8] = c->u_mode.ocb.L[0];
    1369             :           Ls[(3 + n) % 8] = c->u_mode.ocb.L[2];
    1370             :           Ls[(4 + n) % 8] = c->u_mode.ocb.L[0];
    1371             :           Ls[(5 + n) % 8] = c->u_mode.ocb.L[1];
    1372             :           Ls[(6 + n) % 8] = c->u_mode.ocb.L[0];
    1373             :           l = &Ls[(7 + n) % 8];
    1374             : 
    1375             :           /* Process data in 8 block chunks. */
    1376             :           while (nblocks >= 8)
    1377             :             {
    1378             :               blkn += 8;
    1379             :               *l = ocb_get_l(c,  blkn - blkn % 8);
    1380             : 
    1381             :               if (encrypt)
    1382             :                 _gcry_serpent_neon_ocb_enc(ctx, outbuf, inbuf, c->u_iv.iv,
    1383             :                                           c->u_ctr.ctr, Ls);
    1384             :               else
    1385             :                 _gcry_serpent_neon_ocb_dec(ctx, outbuf, inbuf, c->u_iv.iv,
    1386             :                                           c->u_ctr.ctr, Ls);
    1387             : 
    1388             :               nblocks -= 8;
    1389             :               outbuf += 8 * sizeof(serpent_block_t);
    1390             :               inbuf  += 8 * sizeof(serpent_block_t);
    1391             :               did_use_neon = 1;
    1392             :             }
    1393             :         }
    1394             : 
    1395             :       if (did_use_neon)
    1396             :         {
    1397             :           /* serpent-neon assembly code does not use stack */
    1398             :           if (nblocks == 0)
    1399             :             burn_stack_depth = 0;
    1400             :         }
    1401             : 
    1402             :       /* Use generic code to handle smaller chunks... */
    1403             :     }
    1404             : #endif
    1405             : 
    1406             : #if defined(USE_AVX2) || defined(USE_SSE2) || defined(USE_NEON)
    1407           0 :   c->u_mode.ocb.data_nblocks = blkn;
    1408             : 
    1409           0 :   if (burn_stack_depth)
    1410           0 :     _gcry_burn_stack (burn_stack_depth + 4 * sizeof(void *));
    1411             : #endif
    1412             : 
    1413           0 :   return nblocks;
    1414             : }
    1415             : 
    1416             : /* Bulk authentication of complete blocks in OCB mode. */
    1417             : size_t
    1418           0 : _gcry_serpent_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg,
    1419             :                         size_t nblocks)
    1420             : {
    1421             : #if defined(USE_AVX2) || defined(USE_SSE2) || defined(USE_NEON)
    1422           0 :   serpent_context_t *ctx = (void *)&c->context.c;
    1423           0 :   const unsigned char *abuf = abuf_arg;
    1424           0 :   int burn_stack_depth = 2 * sizeof(serpent_block_t);
    1425           0 :   u64 blkn = c->u_mode.ocb.aad_nblocks;
    1426             : #else
    1427             :   (void)c;
    1428             :   (void)abuf_arg;
    1429             : #endif
    1430             : 
    1431             : #ifdef USE_AVX2
    1432           0 :   if (ctx->use_avx2)
    1433             :     {
    1434           0 :       int did_use_avx2 = 0;
    1435             :       u64 Ls[16];
    1436           0 :       unsigned int n = 16 - (blkn % 16);
    1437             :       u64 *l;
    1438             :       int i;
    1439             : 
    1440           0 :       if (nblocks >= 16)
    1441             :         {
    1442           0 :           for (i = 0; i < 16; i += 8)
    1443             :             {
    1444             :               /* Use u64 to store pointers for x32 support (assembly function
    1445             :                * assumes 64-bit pointers). */
    1446           0 :               Ls[(i + 0 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
    1447           0 :               Ls[(i + 1 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[1];
    1448           0 :               Ls[(i + 2 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
    1449           0 :               Ls[(i + 3 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[2];
    1450           0 :               Ls[(i + 4 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
    1451           0 :               Ls[(i + 5 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[1];
    1452           0 :               Ls[(i + 6 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
    1453             :             }
    1454             : 
    1455           0 :           Ls[(7 + n) % 16] = (uintptr_t)(void *)c->u_mode.ocb.L[3];
    1456           0 :           l = &Ls[(15 + n) % 16];
    1457             : 
    1458             :           /* Process data in 16 block chunks. */
    1459           0 :           while (nblocks >= 16)
    1460             :             {
    1461           0 :               blkn += 16;
    1462           0 :               *l = (uintptr_t)(void *)ocb_get_l(c, blkn - blkn % 16);
    1463             : 
    1464           0 :               _gcry_serpent_avx2_ocb_auth(ctx, abuf, c->u_mode.ocb.aad_offset,
    1465           0 :                                           c->u_mode.ocb.aad_sum, Ls);
    1466             : 
    1467           0 :               nblocks -= 16;
    1468           0 :               abuf += 16 * sizeof(serpent_block_t);
    1469           0 :               did_use_avx2 = 1;
    1470             :             }
    1471             :         }
    1472             : 
    1473           0 :       if (did_use_avx2)
    1474             :         {
    1475             :           /* serpent-avx2 assembly code does not use stack */
    1476           0 :           if (nblocks == 0)
    1477           0 :             burn_stack_depth = 0;
    1478             :         }
    1479             : 
    1480             :       /* Use generic code to handle smaller chunks... */
    1481             :     }
    1482             : #endif
    1483             : 
    1484             : #ifdef USE_SSE2
    1485             :   {
    1486           0 :     int did_use_sse2 = 0;
    1487             :     u64 Ls[8];
    1488           0 :     unsigned int n = 8 - (blkn % 8);
    1489             :     u64 *l;
    1490             : 
    1491           0 :     if (nblocks >= 8)
    1492             :       {
    1493             :         /* Use u64 to store pointers for x32 support (assembly function
    1494             :         * assumes 64-bit pointers). */
    1495           0 :         Ls[(0 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
    1496           0 :         Ls[(1 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[1];
    1497           0 :         Ls[(2 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
    1498           0 :         Ls[(3 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[2];
    1499           0 :         Ls[(4 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
    1500           0 :         Ls[(5 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[1];
    1501           0 :         Ls[(6 + n) % 8] = (uintptr_t)(void *)c->u_mode.ocb.L[0];
    1502           0 :         l = &Ls[(7 + n) % 8];
    1503             : 
    1504             :         /* Process data in 8 block chunks. */
    1505           0 :         while (nblocks >= 8)
    1506             :           {
    1507           0 :             blkn += 8;
    1508           0 :             *l = (uintptr_t)(void *)ocb_get_l(c, blkn - blkn % 8);
    1509             : 
    1510           0 :             _gcry_serpent_sse2_ocb_auth(ctx, abuf, c->u_mode.ocb.aad_offset,
    1511           0 :                                         c->u_mode.ocb.aad_sum, Ls);
    1512             : 
    1513           0 :             nblocks -= 8;
    1514           0 :             abuf += 8 * sizeof(serpent_block_t);
    1515           0 :             did_use_sse2 = 1;
    1516             :           }
    1517             :       }
    1518             : 
    1519           0 :     if (did_use_sse2)
    1520             :       {
    1521             :         /* serpent-avx2 assembly code does not use stack */
    1522           0 :         if (nblocks == 0)
    1523           0 :           burn_stack_depth = 0;
    1524             :       }
    1525             : 
    1526             :     /* Use generic code to handle smaller chunks... */
    1527             :   }
    1528             : #endif
    1529             : 
    1530             : #ifdef USE_NEON
    1531             :   if (ctx->use_neon)
    1532             :     {
    1533             :       int did_use_neon = 0;
    1534             :       const void *Ls[8];
    1535             :       unsigned int n = 8 - (blkn % 8);
    1536             :       const void **l;
    1537             : 
    1538             :       if (nblocks >= 8)
    1539             :         {
    1540             :           Ls[(0 + n) % 8] = c->u_mode.ocb.L[0];
    1541             :           Ls[(1 + n) % 8] = c->u_mode.ocb.L[1];
    1542             :           Ls[(2 + n) % 8] = c->u_mode.ocb.L[0];
    1543             :           Ls[(3 + n) % 8] = c->u_mode.ocb.L[2];
    1544             :           Ls[(4 + n) % 8] = c->u_mode.ocb.L[0];
    1545             :           Ls[(5 + n) % 8] = c->u_mode.ocb.L[1];
    1546             :           Ls[(6 + n) % 8] = c->u_mode.ocb.L[0];
    1547             :           l = &Ls[(7 + n) % 8];
    1548             : 
    1549             :           /* Process data in 8 block chunks. */
    1550             :           while (nblocks >= 8)
    1551             :             {
    1552             :               blkn += 8;
    1553             :               *l = ocb_get_l(c, blkn - blkn % 8);
    1554             : 
    1555             :               _gcry_serpent_neon_ocb_auth(ctx, abuf, c->u_mode.ocb.aad_offset,
    1556             :                                           c->u_mode.ocb.aad_sum, Ls);
    1557             : 
    1558             :               nblocks -= 8;
    1559             :               abuf += 8 * sizeof(serpent_block_t);
    1560             :               did_use_neon = 1;
    1561             :             }
    1562             :         }
    1563             : 
    1564             :       if (did_use_neon)
    1565             :         {
    1566             :           /* serpent-neon assembly code does not use stack */
    1567             :           if (nblocks == 0)
    1568             :             burn_stack_depth = 0;
    1569             :         }
    1570             : 
    1571             :       /* Use generic code to handle smaller chunks... */
    1572             :     }
    1573             : #endif
    1574             : 
    1575             : #if defined(USE_AVX2) || defined(USE_SSE2) || defined(USE_NEON)
    1576           0 :   c->u_mode.ocb.aad_nblocks = blkn;
    1577             : 
    1578           0 :   if (burn_stack_depth)
    1579           0 :     _gcry_burn_stack (burn_stack_depth + 4 * sizeof(void *));
    1580             : #endif
    1581             : 
    1582           0 :   return nblocks;
    1583             : }
    1584             : 
    1585             : 
    1586             : 
    1587             : /* Run the self-tests for SERPENT-CTR-128, tests IV increment of bulk CTR
    1588             :    encryption.  Returns NULL on success. */
    1589             : static const char*
    1590           0 : selftest_ctr_128 (void)
    1591             : {
    1592           0 :   const int nblocks = 16+8+1;
    1593           0 :   const int blocksize = sizeof(serpent_block_t);
    1594           0 :   const int context_size = sizeof(serpent_context_t);
    1595             : 
    1596           0 :   return _gcry_selftest_helper_ctr("SERPENT", &serpent_setkey,
    1597             :            &serpent_encrypt, &_gcry_serpent_ctr_enc, nblocks, blocksize,
    1598             :            context_size);
    1599             : }
    1600             : 
    1601             : 
    1602             : /* Run the self-tests for SERPENT-CBC-128, tests bulk CBC decryption.
    1603             :    Returns NULL on success. */
    1604             : static const char*
    1605           0 : selftest_cbc_128 (void)
    1606             : {
    1607           0 :   const int nblocks = 16+8+2;
    1608           0 :   const int blocksize = sizeof(serpent_block_t);
    1609           0 :   const int context_size = sizeof(serpent_context_t);
    1610             : 
    1611           0 :   return _gcry_selftest_helper_cbc("SERPENT", &serpent_setkey,
    1612             :            &serpent_encrypt, &_gcry_serpent_cbc_dec, nblocks, blocksize,
    1613             :            context_size);
    1614             : }
    1615             : 
    1616             : 
    1617             : /* Run the self-tests for SERPENT-CBC-128, tests bulk CBC decryption.
    1618             :    Returns NULL on success. */
    1619             : static const char*
    1620           0 : selftest_cfb_128 (void)
    1621             : {
    1622           0 :   const int nblocks = 16+8+2;
    1623           0 :   const int blocksize = sizeof(serpent_block_t);
    1624           0 :   const int context_size = sizeof(serpent_context_t);
    1625             : 
    1626           0 :   return _gcry_selftest_helper_cfb("SERPENT", &serpent_setkey,
    1627             :            &serpent_encrypt, &_gcry_serpent_cfb_dec, nblocks, blocksize,
    1628             :            context_size);
    1629             : }
    1630             : 
    1631             : 
    1632             : /* Serpent test.  */
    1633             : 
    1634             : static const char *
    1635           0 : serpent_test (void)
    1636             : {
    1637             :   serpent_context_t context;
    1638             :   unsigned char scratch[16];
    1639             :   unsigned int i;
    1640             :   const char *r;
    1641             : 
    1642             :   static struct test
    1643             :   {
    1644             :     int key_length;
    1645             :     unsigned char key[32];
    1646             :     unsigned char text_plain[16];
    1647             :     unsigned char text_cipher[16];
    1648             :   } test_data[] =
    1649             :     {
    1650             :       {
    1651             :         16,
    1652             :         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
    1653             :         "\xD2\x9D\x57\x6F\xCE\xA3\xA3\xA7\xED\x90\x99\xF2\x92\x73\xD7\x8E",
    1654             :         "\xB2\x28\x8B\x96\x8A\xE8\xB0\x86\x48\xD1\xCE\x96\x06\xFD\x99\x2D"
    1655             :       },
    1656             :       {
    1657             :         24,
    1658             :         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
    1659             :         "\x00\x00\x00\x00\x00\x00\x00\x00",
    1660             :         "\xD2\x9D\x57\x6F\xCE\xAB\xA3\xA7\xED\x98\x99\xF2\x92\x7B\xD7\x8E",
    1661             :         "\x13\x0E\x35\x3E\x10\x37\xC2\x24\x05\xE8\xFA\xEF\xB2\xC3\xC3\xE9"
    1662             :       },
    1663             :       {
    1664             :         32,
    1665             :         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
    1666             :         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
    1667             :         "\xD0\x95\x57\x6F\xCE\xA3\xE3\xA7\xED\x98\xD9\xF2\x90\x73\xD7\x8E",
    1668             :         "\xB9\x0E\xE5\x86\x2D\xE6\x91\x68\xF2\xBD\xD5\x12\x5B\x45\x47\x2B"
    1669             :       },
    1670             :       {
    1671             :         32,
    1672             :         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
    1673             :         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
    1674             :         "\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00",
    1675             :         "\x20\x61\xA4\x27\x82\xBD\x52\xEC\x69\x1E\xC3\x83\xB0\x3B\xA7\x7C"
    1676             :       },
    1677             :       {
    1678             :         0
    1679             :       },
    1680             :     };
    1681             : 
    1682           0 :   for (i = 0; test_data[i].key_length; i++)
    1683             :     {
    1684           0 :       serpent_setkey_internal (&context, test_data[i].key,
    1685           0 :                                test_data[i].key_length);
    1686           0 :       serpent_encrypt_internal (&context, test_data[i].text_plain, scratch);
    1687             : 
    1688           0 :       if (memcmp (scratch, test_data[i].text_cipher, sizeof (serpent_block_t)))
    1689           0 :         switch (test_data[i].key_length)
    1690             :           {
    1691             :           case 16:
    1692           0 :             return "Serpent-128 test encryption failed.";
    1693             :           case  24:
    1694           0 :             return "Serpent-192 test encryption failed.";
    1695             :           case 32:
    1696           0 :             return "Serpent-256 test encryption failed.";
    1697             :           }
    1698             : 
    1699           0 :     serpent_decrypt_internal (&context, test_data[i].text_cipher, scratch);
    1700           0 :     if (memcmp (scratch, test_data[i].text_plain, sizeof (serpent_block_t)))
    1701           0 :       switch (test_data[i].key_length)
    1702             :         {
    1703             :         case 16:
    1704           0 :           return "Serpent-128 test decryption failed.";
    1705             :         case  24:
    1706           0 :           return "Serpent-192 test decryption failed.";
    1707             :         case 32:
    1708           0 :           return "Serpent-256 test decryption failed.";
    1709             :         }
    1710             :     }
    1711             : 
    1712           0 :   if ( (r = selftest_ctr_128 ()) )
    1713           0 :     return r;
    1714             : 
    1715           0 :   if ( (r = selftest_cbc_128 ()) )
    1716           0 :     return r;
    1717             : 
    1718           0 :   if ( (r = selftest_cfb_128 ()) )
    1719           0 :     return r;
    1720             : 
    1721           0 :   return NULL;
    1722             : }
    1723             : 
    1724             : 
    1725             : static gcry_cipher_oid_spec_t serpent128_oids[] =
    1726             :   {
    1727             :     {"1.3.6.1.4.1.11591.13.2.1", GCRY_CIPHER_MODE_ECB },
    1728             :     {"1.3.6.1.4.1.11591.13.2.2", GCRY_CIPHER_MODE_CBC },
    1729             :     {"1.3.6.1.4.1.11591.13.2.3", GCRY_CIPHER_MODE_OFB },
    1730             :     {"1.3.6.1.4.1.11591.13.2.4", GCRY_CIPHER_MODE_CFB },
    1731             :     { NULL }
    1732             :   };
    1733             : 
    1734             : static gcry_cipher_oid_spec_t serpent192_oids[] =
    1735             :   {
    1736             :     {"1.3.6.1.4.1.11591.13.2.21", GCRY_CIPHER_MODE_ECB },
    1737             :     {"1.3.6.1.4.1.11591.13.2.22", GCRY_CIPHER_MODE_CBC },
    1738             :     {"1.3.6.1.4.1.11591.13.2.23", GCRY_CIPHER_MODE_OFB },
    1739             :     {"1.3.6.1.4.1.11591.13.2.24", GCRY_CIPHER_MODE_CFB },
    1740             :     { NULL }
    1741             :   };
    1742             : 
    1743             : static gcry_cipher_oid_spec_t serpent256_oids[] =
    1744             :   {
    1745             :     {"1.3.6.1.4.1.11591.13.2.41", GCRY_CIPHER_MODE_ECB },
    1746             :     {"1.3.6.1.4.1.11591.13.2.42", GCRY_CIPHER_MODE_CBC },
    1747             :     {"1.3.6.1.4.1.11591.13.2.43", GCRY_CIPHER_MODE_OFB },
    1748             :     {"1.3.6.1.4.1.11591.13.2.44", GCRY_CIPHER_MODE_CFB },
    1749             :     { NULL }
    1750             :   };
    1751             : 
    1752             : static const char *serpent128_aliases[] =
    1753             :   {
    1754             :     "SERPENT",
    1755             :     "SERPENT-128",
    1756             :     NULL
    1757             :   };
    1758             : static const char *serpent192_aliases[] =
    1759             :   {
    1760             :     "SERPENT-192",
    1761             :     NULL
    1762             :   };
    1763             : static const char *serpent256_aliases[] =
    1764             :   {
    1765             :     "SERPENT-256",
    1766             :     NULL
    1767             :   };
    1768             : 
    1769             : gcry_cipher_spec_t _gcry_cipher_spec_serpent128 =
    1770             :   {
    1771             :     GCRY_CIPHER_SERPENT128, {0, 0},
    1772             :     "SERPENT128", serpent128_aliases, serpent128_oids, 16, 128,
    1773             :     sizeof (serpent_context_t),
    1774             :     serpent_setkey, serpent_encrypt, serpent_decrypt
    1775             :   };
    1776             : 
    1777             : gcry_cipher_spec_t _gcry_cipher_spec_serpent192 =
    1778             :   {
    1779             :     GCRY_CIPHER_SERPENT192, {0, 0},
    1780             :     "SERPENT192", serpent192_aliases, serpent192_oids, 16, 192,
    1781             :     sizeof (serpent_context_t),
    1782             :     serpent_setkey, serpent_encrypt, serpent_decrypt
    1783             :   };
    1784             : 
    1785             : gcry_cipher_spec_t _gcry_cipher_spec_serpent256 =
    1786             :   {
    1787             :     GCRY_CIPHER_SERPENT256, {0, 0},
    1788             :     "SERPENT256", serpent256_aliases, serpent256_oids, 16, 256,
    1789             :     sizeof (serpent_context_t),
    1790             :     serpent_setkey, serpent_encrypt, serpent_decrypt
    1791             :   };

Generated by: LCOV version 1.12