1/*
2   BLAKE2 reference source code package - optimized C implementations
3
4   Written in 2012 by Samuel Neves <sneves@dei.uc.pt>
5
6   To the extent possible under law, the author(s) have dedicated all copyright
7   and related and neighboring rights to this software to the public domain
8   worldwide. This software is distributed without any warranty.
9
10   You should have received a copy of the CC0 Public Domain Dedication along with
11   this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
12*/
13#pragma once
14#ifndef __BLAKE2_IMPL_H__
15#define __BLAKE2_IMPL_H__
16
17#if defined(_WIN32) || defined(WIN32)
18#include <windows.h>
19#endif
20
21#include <stddef.h>
22#include <stdint.h>
23#include <string.h>
24
25#define BLAKE2_IMPL_CAT(x,y) x ## y
26#define BLAKE2_IMPL_EVAL(x,y)  BLAKE2_IMPL_CAT(x,y)
27#define BLAKE2_IMPL_NAME(fun)  BLAKE2_IMPL_EVAL(fun, SUFFIX)
28
29static inline uint32_t load32( const void *src )
30{
31#if defined(NATIVE_LITTLE_ENDIAN)
32  uint32_t w;
33  memcpy( &w, src, sizeof( w ) );
34  return w;
35#else
36  const uint8_t *p = ( uint8_t * )src;
37  uint32_t w = *p++;
38  w |= ( uint32_t )( *p++ ) <<  8;
39  w |= ( uint32_t )( *p++ ) << 16;
40  w |= ( uint32_t )( *p++ ) << 24;
41  return w;
42#endif
43}
44
45static inline uint64_t load64( const void *src )
46{
47#if defined(NATIVE_LITTLE_ENDIAN)
48  uint64_t w;
49  memcpy( &w, src, sizeof( w ) );
50  return w;
51#else
52  const uint8_t *p = ( uint8_t * )src;
53  uint64_t w = *p++;
54  w |= ( uint64_t )( *p++ ) <<  8;
55  w |= ( uint64_t )( *p++ ) << 16;
56  w |= ( uint64_t )( *p++ ) << 24;
57  w |= ( uint64_t )( *p++ ) << 32;
58  w |= ( uint64_t )( *p++ ) << 40;
59  w |= ( uint64_t )( *p++ ) << 48;
60  w |= ( uint64_t )( *p++ ) << 56;
61  return w;
62#endif
63}
64
65static inline void store32( void *dst, uint32_t w )
66{
67#if defined(NATIVE_LITTLE_ENDIAN)
68  memcpy( dst, &w, sizeof( w ) );
69#else
70  uint8_t *p = ( uint8_t * )dst;
71  *p++ = ( uint8_t )w; w >>= 8;
72  *p++ = ( uint8_t )w; w >>= 8;
73  *p++ = ( uint8_t )w; w >>= 8;
74  *p++ = ( uint8_t )w;
75#endif
76}
77
78static inline void store64( void *dst, uint64_t w )
79{
80#if defined(NATIVE_LITTLE_ENDIAN)
81  memcpy( dst, &w, sizeof( w ) );
82#else
83  uint8_t *p = ( uint8_t * )dst;
84  *p++ = ( uint8_t )w; w >>= 8;
85  *p++ = ( uint8_t )w; w >>= 8;
86  *p++ = ( uint8_t )w; w >>= 8;
87  *p++ = ( uint8_t )w; w >>= 8;
88  *p++ = ( uint8_t )w; w >>= 8;
89  *p++ = ( uint8_t )w; w >>= 8;
90  *p++ = ( uint8_t )w; w >>= 8;
91  *p++ = ( uint8_t )w;
92#endif
93}
94
95static inline uint64_t load48( const void *src )
96{
97  const uint8_t *p = ( const uint8_t * )src;
98  uint64_t w = *p++;
99  w |= ( uint64_t )( *p++ ) <<  8;
100  w |= ( uint64_t )( *p++ ) << 16;
101  w |= ( uint64_t )( *p++ ) << 24;
102  w |= ( uint64_t )( *p++ ) << 32;
103  w |= ( uint64_t )( *p++ ) << 40;
104  return w;
105}
106
107static inline void store48( void *dst, uint64_t w )
108{
109  uint8_t *p = ( uint8_t * )dst;
110  *p++ = ( uint8_t )w; w >>= 8;
111  *p++ = ( uint8_t )w; w >>= 8;
112  *p++ = ( uint8_t )w; w >>= 8;
113  *p++ = ( uint8_t )w; w >>= 8;
114  *p++ = ( uint8_t )w; w >>= 8;
115  *p++ = ( uint8_t )w;
116}
117
118static inline uint32_t rotl32( const uint32_t w, const unsigned c )
119{
120  return ( w << c ) | ( w >> ( 32 - c ) );
121}
122
123static inline uint64_t rotl64( const uint64_t w, const unsigned c )
124{
125  return ( w << c ) | ( w >> ( 64 - c ) );
126}
127
128static inline uint32_t rotr32( const uint32_t w, const unsigned c )
129{
130  return ( w >> c ) | ( w << ( 32 - c ) );
131}
132
133static inline uint64_t rotr64( const uint64_t w, const unsigned c )
134{
135  return ( w >> c ) | ( w << ( 64 - c ) );
136}
137
138/* prevents compiler optimizing out memset() */
139static inline void secure_zero_memory(void *v, size_t n)
140{
141#if defined(_WIN32) || defined(WIN32)
142  SecureZeroMemory(v, n);
143#elif defined(__hpux)
144  static void *(*const volatile memset_v)(void *, int, size_t) = &memset;
145  memset_v(v, 0, n);
146#else
147// prioritize first the general C11 call
148#if defined(HAVE_MEMSET_S)
149  memset_s(v, n, 0, n);
150#elif defined(HAVE_EXPLICIT_BZERO)
151  explicit_bzero(v, n);
152#elif defined(HAVE_EXPLICIT_MEMSET)
153  explicit_memset(v, 0, n);
154#else
155  memset(v, 0, n);
156  __asm__ __volatile__("" :: "r"(v) : "memory");
157#endif
158#endif
159}
160
161#endif
162
163