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 #include <sys/isa_defs.h> /* get endianness selection */
  47 
  48 #define PLATFORM_MUST_ALIGN     _ALIGNMENT_REQUIRED
  49 #if     defined(_BIG_ENDIAN)
  50 /* here for big-endian CPUs */
  51 #define SKEIN_NEED_SWAP   (1)
  52 #else
  53 /* here for x86 and x86-64 CPUs (and other detected little-endian CPUs) */
  54 #define SKEIN_NEED_SWAP   (0)
  55 #if     PLATFORM_MUST_ALIGN == 0        /* ok to use "fast" versions? */
  56 #define Skein_Put64_LSB_First(dst08, src64, bCnt) bcopy(src64, dst08, bCnt)
  57 #define Skein_Get64_LSB_First(dst64, src08, wCnt) \
  58         bcopy(src08, dst64, 8 * (wCnt))
  59 #endif
  60 #endif
  61 
  62 #endif                          /* ifndef SKEIN_NEED_SWAP */
  63 
  64 /*
  65  * Provide any definitions still needed.
  66  */
  67 #ifndef Skein_Swap64    /* swap for big-endian, nop for little-endian */
  68 #if     SKEIN_NEED_SWAP
  69 #define Skein_Swap64(w64)                               \
  70         (((((uint64_t)(w64)) & 0xFF) << 56) |         \
  71         (((((uint64_t)(w64)) >> 8) & 0xFF) << 48) |     \
  72         (((((uint64_t)(w64)) >> 16) & 0xFF) << 40) |    \
  73         (((((uint64_t)(w64)) >> 24) & 0xFF) << 32) |    \
  74         (((((uint64_t)(w64)) >> 32) & 0xFF) << 24) |    \
  75         (((((uint64_t)(w64)) >> 40) & 0xFF) << 16) |    \
  76         (((((uint64_t)(w64)) >> 48) & 0xFF) << 8) |     \
  77         (((((uint64_t)(w64)) >> 56) & 0xFF)))
  78 #else
  79 #define Skein_Swap64(w64)  (w64)
  80 #endif
  81 #endif                          /* ifndef Skein_Swap64 */
  82 
  83 #ifndef Skein_Put64_LSB_First
  84 void
  85 Skein_Put64_LSB_First(uint8_t *dst, const uint64_t *src, size_t bCnt)
  86 #ifdef  SKEIN_PORT_CODE         /* instantiate the function code here? */
  87 {
  88         /*
  89          * this version is fully portable (big-endian or little-endian),
  90          * but slow
  91          */
  92         size_t n;
  93 
  94         for (n = 0; n < bCnt; n++)
  95                 dst[n] = (uint8_t)(src[n >> 3] >> (8 * (n & 7)));
  96 }
  97 #else
  98 ;                               /* output only the function prototype */
  99 #endif
 100 #endif                          /* ifndef Skein_Put64_LSB_First */
 101 
 102 #ifndef Skein_Get64_LSB_First
 103 void
 104 Skein_Get64_LSB_First(uint64_t *dst, const uint8_t *src, size_t wCnt)
 105 #ifdef  SKEIN_PORT_CODE         /* instantiate the function code here? */
 106 {
 107         /*
 108          * this version is fully portable (big-endian or little-endian),
 109          * but slow
 110          */
 111         size_t n;
 112 
 113         for (n = 0; n < 8 * wCnt; n += 8)
 114                 dst[n / 8] = (((uint64_t)src[n])) +
 115                     (((uint64_t)src[n + 1]) << 8) +
 116                     (((uint64_t)src[n + 2]) << 16) +
 117                     (((uint64_t)src[n + 3]) << 24) +
 118                     (((uint64_t)src[n + 4]) << 32) +
 119                     (((uint64_t)src[n + 5]) << 40) +
 120                     (((uint64_t)src[n + 6]) << 48) +
 121                     (((uint64_t)src[n + 7]) << 56);
 122 }
 123 #else
 124 ;                               /* output only the function prototype */
 125 #endif
 126 #endif                          /* ifndef Skein_Get64_LSB_First */
 127 
 128 #endif  /* _SKEIN_PORT_H_ */