1/*
2   BLAKE2 reference source code package - reference C implementations
3
4   Copyright 2012, Samuel Neves <sneves@dei.uc.pt>.  You may use this under the
5   terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
6   your option.  The terms of these licenses can be found at:
7
8   - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
9   - OpenSSL license   : https://www.openssl.org/source/license.html
10   - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0
11
12   More information about the BLAKE2 hash function can be found at
13   https://blake2.net.
14*/
15
16#ifndef ARCHIVE_BLAKE2_IMPL_H
17#define ARCHIVE_BLAKE2_IMPL_H
18
19#include <stdint.h>
20#include <string.h>
21
22#if !defined(__cplusplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L)
23  #if   defined(_MSC_VER)
24    #define BLAKE2_INLINE __inline
25  #elif defined(__GNUC__)
26    #define BLAKE2_INLINE __inline__
27  #else
28    #define BLAKE2_INLINE
29  #endif
30#else
31  #define BLAKE2_INLINE inline
32#endif
33
34static BLAKE2_INLINE uint32_t load32( const void *src )
35{
36#if defined(NATIVE_LITTLE_ENDIAN)
37  uint32_t w;
38  memcpy(&w, src, sizeof w);
39  return w;
40#else
41  const uint8_t *p = ( const uint8_t * )src;
42  return (( uint32_t )( p[0] ) <<  0) |
43         (( uint32_t )( p[1] ) <<  8) |
44         (( uint32_t )( p[2] ) << 16) |
45         (( uint32_t )( p[3] ) << 24) ;
46#endif
47}
48
49static BLAKE2_INLINE uint64_t load64( const void *src )
50{
51#if defined(NATIVE_LITTLE_ENDIAN)
52  uint64_t w;
53  memcpy(&w, src, sizeof w);
54  return w;
55#else
56  const uint8_t *p = ( const uint8_t * )src;
57  return (( uint64_t )( p[0] ) <<  0) |
58         (( uint64_t )( p[1] ) <<  8) |
59         (( uint64_t )( p[2] ) << 16) |
60         (( uint64_t )( p[3] ) << 24) |
61         (( uint64_t )( p[4] ) << 32) |
62         (( uint64_t )( p[5] ) << 40) |
63         (( uint64_t )( p[6] ) << 48) |
64         (( uint64_t )( p[7] ) << 56) ;
65#endif
66}
67
68static BLAKE2_INLINE uint16_t load16( const void *src )
69{
70#if defined(NATIVE_LITTLE_ENDIAN)
71  uint16_t w;
72  memcpy(&w, src, sizeof w);
73  return w;
74#else
75  const uint8_t *p = ( const uint8_t * )src;
76  return ( uint16_t )((( uint32_t )( p[0] ) <<  0) |
77                      (( uint32_t )( p[1] ) <<  8));
78#endif
79}
80
81static BLAKE2_INLINE void store16( void *dst, uint16_t w )
82{
83#if defined(NATIVE_LITTLE_ENDIAN)
84  memcpy(dst, &w, sizeof w);
85#else
86  uint8_t *p = ( uint8_t * )dst;
87  *p++ = ( uint8_t )w; w >>= 8;
88  *p++ = ( uint8_t )w;
89#endif
90}
91
92static BLAKE2_INLINE void store32( void *dst, uint32_t w )
93{
94#if defined(NATIVE_LITTLE_ENDIAN)
95  memcpy(dst, &w, sizeof w);
96#else
97  uint8_t *p = ( uint8_t * )dst;
98  p[0] = (uint8_t)(w >>  0);
99  p[1] = (uint8_t)(w >>  8);
100  p[2] = (uint8_t)(w >> 16);
101  p[3] = (uint8_t)(w >> 24);
102#endif
103}
104
105static BLAKE2_INLINE void store64( void *dst, uint64_t w )
106{
107#if defined(NATIVE_LITTLE_ENDIAN)
108  memcpy(dst, &w, sizeof w);
109#else
110  uint8_t *p = ( uint8_t * )dst;
111  p[0] = (uint8_t)(w >>  0);
112  p[1] = (uint8_t)(w >>  8);
113  p[2] = (uint8_t)(w >> 16);
114  p[3] = (uint8_t)(w >> 24);
115  p[4] = (uint8_t)(w >> 32);
116  p[5] = (uint8_t)(w >> 40);
117  p[6] = (uint8_t)(w >> 48);
118  p[7] = (uint8_t)(w >> 56);
119#endif
120}
121
122static BLAKE2_INLINE uint64_t load48( const void *src )
123{
124  const uint8_t *p = ( const uint8_t * )src;
125  return (( uint64_t )( p[0] ) <<  0) |
126         (( uint64_t )( p[1] ) <<  8) |
127         (( uint64_t )( p[2] ) << 16) |
128         (( uint64_t )( p[3] ) << 24) |
129         (( uint64_t )( p[4] ) << 32) |
130         (( uint64_t )( p[5] ) << 40) ;
131}
132
133static BLAKE2_INLINE void store48( void *dst, uint64_t w )
134{
135  uint8_t *p = ( uint8_t * )dst;
136  p[0] = (uint8_t)(w >>  0);
137  p[1] = (uint8_t)(w >>  8);
138  p[2] = (uint8_t)(w >> 16);
139  p[3] = (uint8_t)(w >> 24);
140  p[4] = (uint8_t)(w >> 32);
141  p[5] = (uint8_t)(w >> 40);
142}
143
144static BLAKE2_INLINE uint32_t rotr32( const uint32_t w, const unsigned c )
145{
146  return ( w >> c ) | ( w << ( 32 - c ) );
147}
148
149static BLAKE2_INLINE uint64_t rotr64( const uint64_t w, const unsigned c )
150{
151  return ( w >> c ) | ( w << ( 64 - c ) );
152}
153
154/* prevents compiler optimizing out memset() */
155static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n)
156{
157  static void *(*const volatile memset_v)(void *, int, size_t) = &memset;
158  memset_v(v, 0, n);
159}
160
161#endif
162