1 /*
   2  * Platform-specific definitions for Skein hash function.
   3  *
   4  * Source code author: Doug Whiting, 2008.
   5  *
   6  * This algorithm and source code is released to the public domain.
   7  *
   8  * Many thanks to Brian Gladman for his portable header files.
   9  *
  10  * To port Skein to an "unsupported" platform, change the definitions
  11  * in this file appropriately.
  12  */
  13 /* Copyright 2013 Doug Whiting. This code is released to the public domain. */
  14 
  15 #ifndef _SKEIN_PORT_H_
  16 #define _SKEIN_PORT_H_
  17 
  18 #include <sys/types.h>    /* get integer type definitions */
  19 #include <sys/systm.h>    /* for bcopy() */
  20 
  21 #ifndef RotL_64
  22 #define RotL_64(x, N)   (((x) << (N)) | ((x) >> (64 - (N))))
  23 #endif
  24 
  25 /*
  26  * Skein is "natively" little-endian (unlike SHA-xxx), for optimal
  27  * performance on x86 CPUs. The Skein code requires the following
  28  * definitions for dealing with endianness:
  29  *
  30  *    SKEIN_NEED_SWAP:  0 for little-endian, 1 for big-endian
  31  *    Skein_Put64_LSB_First
  32  *    Skein_Get64_LSB_First
  33  *    Skein_Swap64
  34  *
  35  * If SKEIN_NEED_SWAP is defined at compile time, it is used here
  36  * along with the portable versions of Put64/Get64/Swap64, which
  37  * are slow in general.
  38  *
  39  * Otherwise, an "auto-detect" of endianness is attempted below.
  40  * If the default handling doesn't work well, the user may insert
  41  * platform-specific code instead (e.g., for big-endian CPUs).
  42  *
  43  */
  44 #ifndef SKEIN_NEED_SWAP         /* compile-time "override" for endianness? */
  45 
  46 #ifndef _STANDALONE
  47 #include <sys/isa_defs.h> /* get endianness selection */
  48 #else
  49 #include <sys/param.h>            /* get endianness selection */
  50 #define _ALIGNMENT_REQUIRED     1
  51 #if (_BYTE_ORDER == _LITTLE_ENDIAN)
  52 #undef _BIG_ENDIAN
  53 #else
  54 #undef _LITTLE_ENDIAN
  55 #endif
  56 #endif
  57 
  58 #define PLATFORM_MUST_ALIGN     _ALIGNMENT_REQUIRED
  59 #if     defined(_BIG_ENDIAN)
  60 /* here for big-endian CPUs */
  61 #define SKEIN_NEED_SWAP   (1)
  62 #else
  63 /* here for x86 and x86-64 CPUs (and other detected little-endian CPUs) */
  64 #define SKEIN_NEED_SWAP   (0)
  65 #if     PLATFORM_MUST_ALIGN == 0        /* ok to use "fast" versions? */
  66 #define Skein_Put64_LSB_First(dst08, src64, bCnt) bcopy(src64, dst08, bCnt)
  67 #define Skein_Get64_LSB_First(dst64, src08, wCnt) \
  68         bcopy(src08, dst64, 8 * (wCnt))
  69 #endif
  70 #endif
  71 
  72 #endif                          /* ifndef SKEIN_NEED_SWAP */
  73 
  74 /*
  75  * Provide any definitions still needed.
  76  */
  77 #ifndef Skein_Swap64    /* swap for big-endian, nop for little-endian */
  78 #if     SKEIN_NEED_SWAP
  79 #define Skein_Swap64(w64)                               \
  80         (((((uint64_t)(w64)) & 0xFF) << 56) |         \
  81         (((((uint64_t)(w64)) >> 8) & 0xFF) << 48) |     \
  82         (((((uint64_t)(w64)) >> 16) & 0xFF) << 40) |    \
  83         (((((uint64_t)(w64)) >> 24) & 0xFF) << 32) |    \
  84         (((((uint64_t)(w64)) >> 32) & 0xFF) << 24) |    \
  85         (((((uint64_t)(w64)) >> 40) & 0xFF) << 16) |    \
  86         (((((uint64_t)(w64)) >> 48) & 0xFF) << 8) |     \
  87         (((((uint64_t)(w64)) >> 56) & 0xFF)))
  88 #else
  89 #define Skein_Swap64(w64)  (w64)
  90 #endif
  91 #endif                          /* ifndef Skein_Swap64 */
  92 
  93 #ifndef Skein_Put64_LSB_First
  94 void
  95 Skein_Put64_LSB_First(uint8_t *dst, const uint64_t *src, size_t bCnt)
  96 #ifdef  SKEIN_PORT_CODE         /* instantiate the function code here? */
  97 {
  98         /*
  99          * this version is fully portable (big-endian or little-endian),
 100          * but slow
 101          */
 102         size_t n;
 103 
 104         for (n = 0; n < bCnt; n++)
 105                 dst[n] = (uint8_t)(src[n >> 3] >> (8 * (n & 7)));
 106 }
 107 #else
 108 ;                               /* output only the function prototype */
 109 #endif
 110 #endif                          /* ifndef Skein_Put64_LSB_First */
 111 
 112 #ifndef Skein_Get64_LSB_First
 113 void
 114 Skein_Get64_LSB_First(uint64_t *dst, const uint8_t *src, size_t wCnt)
 115 #ifdef  SKEIN_PORT_CODE         /* instantiate the function code here? */
 116 {
 117         /*
 118          * this version is fully portable (big-endian or little-endian),
 119          * but slow
 120          */
 121         size_t n;
 122 
 123         for (n = 0; n < 8 * wCnt; n += 8)
 124                 dst[n / 8] = (((uint64_t)src[n])) +
 125                     (((uint64_t)src[n + 1]) << 8) +
 126                     (((uint64_t)src[n + 2]) << 16) +
 127                     (((uint64_t)src[n + 3]) << 24) +
 128                     (((uint64_t)src[n + 4]) << 32) +
 129                     (((uint64_t)src[n + 5]) << 40) +
 130                     (((uint64_t)src[n + 6]) << 48) +
 131                     (((uint64_t)src[n + 7]) << 56);
 132 }
 133 #else
 134 ;                               /* output only the function prototype */
 135 #endif
 136 #endif                          /* ifndef Skein_Get64_LSB_First */
 137 
 138 #endif  /* _SKEIN_PORT_H_ */