1/*
2 BLAKE2 reference source code package - optimized C implementations
3
4 Written in 2012 by Samuel Neves <[email protected]>
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