blake2 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,45 @@
1
+ # BLAKE2 for Ruby
2
+
3
+ ## SUMMARY
4
+
5
+ This gem is a C-extension for using BLAKE2 in Ruby.
6
+
7
+ For a detailed explanation about BLAKE2, [here's the offical website](https://blake2.net/).
8
+
9
+ ## INSTALL
10
+
11
+ gem install blake2
12
+
13
+
14
+ ## USAGE
15
+
16
+ out_len = 32
17
+ input = "hello world"
18
+ key = Key.from_string("foo bar baz") # or `Key.none`, or `Key.from_hex("0xDEADBEAF")`
19
+
20
+ digestor = Blake2.new(out_len, key)
21
+
22
+ digestor.digest(input, :to_hex) # => 9567...b180
23
+ digestor.digest(input, :to_bytes) # => [0x95, 0x67, <28 bytes later...>, 0xb1, 0x80]
24
+
25
+
26
+ ## API
27
+
28
+ TODO
29
+
30
+ ## TODO
31
+
32
+ * [ ] Documentation
33
+ * [ ] Improve controls/type checks in the `digest` methods
34
+
35
+ ## CONTRIBUTE
36
+
37
+ 1. Fork it ( https://github.com/franckverrot/blake2/fork )
38
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
39
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
40
+ 4. Push to the branch (`git push origin my-new-feature`)
41
+ 5. Create new Pull Request
42
+
43
+ ## LICENSE
44
+
45
+ Franck Verrot, Copyright 2014. See LICENSE.txt.
@@ -0,0 +1,18 @@
1
+ require 'rake/extensiontask'
2
+ spec = Gem::Specification.load('blake2.gemspec')
3
+ Rake::ExtensionTask.new('blake2_ext', spec) do |ext|
4
+ ext.source_pattern = "*.{c,h}"
5
+ end
6
+
7
+ require 'rake/testtask'
8
+ Rake::TestTask.new do |t|
9
+ t.libs << "test"
10
+ t.pattern = "test/**/*_test.rb"
11
+ t.verbose = true
12
+ t.warning = true
13
+ end
14
+
15
+ task :default => :full
16
+
17
+ desc "Run the full spec suite"
18
+ task :full => ["clean", "compile", "test"]
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ Gem::Specification.new do |spec|
3
+ spec.name = "blake2"
4
+ spec.version = "0.1.0"
5
+ spec.authors = ["Franck Verrot"]
6
+ spec.email = ["franck@verrot.fr"]
7
+ spec.homepage = "https://github.com/franckverrot/blake2"
8
+ spec.license = "GPLv3"
9
+
10
+ spec.summary = "BLAKE2 - fast secure hashing - for Ruby"
11
+ spec.description = spec.summary
12
+ spec.files = `git ls-files -z`.split("\x0")
13
+
14
+ spec.extensions << "ext/blake2_ext/extconf.rb"
15
+
16
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
+ spec.require_paths = ["lib"]
18
+
19
+ spec.add_development_dependency "rake-compiler"
20
+ spec.add_development_dependency "bundler", "~> 1.5"
21
+ spec.add_development_dependency "rake"
22
+ spec.add_development_dependency "minitest"
23
+
24
+ spec.cert_chain = ['certs/franckverrot.pem']
25
+ spec.signing_key = File.expand_path(ENV['RUBYGEMS_CERT_PATH']) if $0 =~ /gem\z/
26
+ end
@@ -0,0 +1,21 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDaDCCAlCgAwIBAgIBATANBgkqhkiG9w0BAQUFADA9MQ8wDQYDVQQDDAZmcmFu
3
+ Y2sxFjAUBgoJkiaJk/IsZAEZFgZ2ZXJyb3QxEjAQBgoJkiaJk/IsZAEZFgJmcjAe
4
+ Fw0xNDA5MDcwODE4MDRaFw0xNTA5MDcwODE4MDRaMD0xDzANBgNVBAMMBmZyYW5j
5
+ azEWMBQGCgmSJomT8ixkARkWBnZlcnJvdDESMBAGCgmSJomT8ixkARkWAmZyMIIB
6
+ IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw8Sqy/b4OzhODXkAqv/Ve7hp
7
+ oH5irjrS20ebbzWqefcHCybwqcmePUs4BtWnGMkGl+fe4Dxfh55m7EXbmbcLBqPJ
8
+ 3Q5bqIgXqmkzHU6oBpkY/fdcP0dLyYBTAo8jZsx6XE1NoC5MBFfHQ8GFzEox7ca7
9
+ eoRPETTFkrlOU8fQQvRMZV8cO9XbzX8PFsJ9iE7CSrZ3+78oFBrj+WslkdU/pR5g
10
+ CYU7eNmWPBbJsgWy9T63K4QkwMElJRvlge3dzAZBEktaxdbiPTQeBtLugIZV2nWA
11
+ mNVMXQ9FzDeSFEhm3ICMuSjJdyEsl9/Su6WFFDaRW4ntRzThdh0+Zs5YEz3+swID
12
+ AQABo3MwcTAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUjJzR97Cw
13
+ I8juLYc/MgodFZPIVYkwGwYDVR0RBBQwEoEQZnJhbmNrQHZlcnJvdC5mcjAbBgNV
14
+ HRIEFDASgRBmcmFuY2tAdmVycm90LmZyMA0GCSqGSIb3DQEBBQUAA4IBAQAkNGfg
15
+ 9ysYJi/jrQ25GWgN3uJuvlscFYGPVmuyyOfsgm2NAkAV5Kn/rbeYxRecIRBU7HcZ
16
+ yVrHFaF36omjo5QIvNDNszHj4b/bwcW30QG0nNqzQlMTvAcsI9kwrDgoAd7qnSmb
17
+ Udf49ZrzniqaFR7OiBia2oXrYynD8Q4mRMzLTMdtdf8oy69DjCrrpzQvEcfHnxML
18
+ MY7zkhoLIwqbZ+/yfSm26+3h91WoEKEdK+caiHotdq1goqlBDIsLSR65siB2yna3
19
+ UeH0jxnbT6lYw622u74Z7Dd6iQfaOy1h+iJxnCQglf70rs9bS665Nr0QvvrbW8Hz
20
+ Vr/YT3S8RkdBsIdM
21
+ -----END CERTIFICATE-----
@@ -0,0 +1 @@
1
+ 4faf052c6018bd3f17ab23c2cc6f5e2e7c9beaadd3fbb85652fc70cac785b1a6886ffa1a0d0c164607acf5bbf43881f7a17b75a3eba5647784d7c67c274574c4
@@ -0,0 +1,136 @@
1
+ /*
2
+ BLAKE2 reference source code package - reference 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
+ #include <stdint.h>
18
+
19
+ static inline uint32_t load32( const void *src )
20
+ {
21
+ #if defined(NATIVE_LITTLE_ENDIAN)
22
+ uint32_t w;
23
+ memcpy(&w, src, sizeof w);
24
+ return w;
25
+ #else
26
+ const uint8_t *p = ( const uint8_t * )src;
27
+ uint32_t w = *p++;
28
+ w |= ( uint32_t )( *p++ ) << 8;
29
+ w |= ( uint32_t )( *p++ ) << 16;
30
+ w |= ( uint32_t )( *p++ ) << 24;
31
+ return w;
32
+ #endif
33
+ }
34
+
35
+ static inline uint64_t load64( const void *src )
36
+ {
37
+ #if defined(NATIVE_LITTLE_ENDIAN)
38
+ uint64_t w;
39
+ memcpy(&w, src, sizeof w);
40
+ return w;
41
+ #else
42
+ const uint8_t *p = ( const uint8_t * )src;
43
+ uint64_t w = *p++;
44
+ w |= ( uint64_t )( *p++ ) << 8;
45
+ w |= ( uint64_t )( *p++ ) << 16;
46
+ w |= ( uint64_t )( *p++ ) << 24;
47
+ w |= ( uint64_t )( *p++ ) << 32;
48
+ w |= ( uint64_t )( *p++ ) << 40;
49
+ w |= ( uint64_t )( *p++ ) << 48;
50
+ w |= ( uint64_t )( *p++ ) << 56;
51
+ return w;
52
+ #endif
53
+ }
54
+
55
+ static inline void store32( void *dst, uint32_t w )
56
+ {
57
+ #if defined(NATIVE_LITTLE_ENDIAN)
58
+ memcpy(dst, &w, sizeof w);
59
+ #else
60
+ uint8_t *p = ( uint8_t * )dst;
61
+ *p++ = ( uint8_t )w; w >>= 8;
62
+ *p++ = ( uint8_t )w; w >>= 8;
63
+ *p++ = ( uint8_t )w; w >>= 8;
64
+ *p++ = ( uint8_t )w;
65
+ #endif
66
+ }
67
+
68
+ static inline void store64( void *dst, uint64_t w )
69
+ {
70
+ #if defined(NATIVE_LITTLE_ENDIAN)
71
+ memcpy(dst, &w, sizeof w);
72
+ #else
73
+ uint8_t *p = ( uint8_t * )dst;
74
+ *p++ = ( uint8_t )w; w >>= 8;
75
+ *p++ = ( uint8_t )w; w >>= 8;
76
+ *p++ = ( uint8_t )w; w >>= 8;
77
+ *p++ = ( uint8_t )w; w >>= 8;
78
+ *p++ = ( uint8_t )w; w >>= 8;
79
+ *p++ = ( uint8_t )w; w >>= 8;
80
+ *p++ = ( uint8_t )w; w >>= 8;
81
+ *p++ = ( uint8_t )w;
82
+ #endif
83
+ }
84
+
85
+ static inline uint64_t load48( const void *src )
86
+ {
87
+ const uint8_t *p = ( const uint8_t * )src;
88
+ uint64_t w = *p++;
89
+ w |= ( uint64_t )( *p++ ) << 8;
90
+ w |= ( uint64_t )( *p++ ) << 16;
91
+ w |= ( uint64_t )( *p++ ) << 24;
92
+ w |= ( uint64_t )( *p++ ) << 32;
93
+ w |= ( uint64_t )( *p++ ) << 40;
94
+ return w;
95
+ }
96
+
97
+ static inline void store48( void *dst, uint64_t w )
98
+ {
99
+ uint8_t *p = ( uint8_t * )dst;
100
+ *p++ = ( uint8_t )w; w >>= 8;
101
+ *p++ = ( uint8_t )w; w >>= 8;
102
+ *p++ = ( uint8_t )w; w >>= 8;
103
+ *p++ = ( uint8_t )w; w >>= 8;
104
+ *p++ = ( uint8_t )w; w >>= 8;
105
+ *p++ = ( uint8_t )w;
106
+ }
107
+
108
+ static inline uint32_t rotl32( const uint32_t w, const unsigned c )
109
+ {
110
+ return ( w << c ) | ( w >> ( 32 - c ) );
111
+ }
112
+
113
+ static inline uint64_t rotl64( const uint64_t w, const unsigned c )
114
+ {
115
+ return ( w << c ) | ( w >> ( 64 - c ) );
116
+ }
117
+
118
+ static inline uint32_t rotr32( const uint32_t w, const unsigned c )
119
+ {
120
+ return ( w >> c ) | ( w << ( 32 - c ) );
121
+ }
122
+
123
+ static inline uint64_t rotr64( const uint64_t w, const unsigned c )
124
+ {
125
+ return ( w >> c ) | ( w << ( 64 - c ) );
126
+ }
127
+
128
+ /* prevents compiler optimizing out memset() */
129
+ static inline void secure_zero_memory( void *v, size_t n )
130
+ {
131
+ volatile uint8_t *p = ( volatile uint8_t * )v;
132
+ while( n-- ) *p++ = 0;
133
+ }
134
+
135
+ #endif
136
+
@@ -0,0 +1,156 @@
1
+ /*
2
+ BLAKE2 reference source code package - reference 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_H__
15
+ #define __BLAKE2_H__
16
+
17
+ #include <stddef.h>
18
+ #include <stdint.h>
19
+
20
+ #if defined(_MSC_VER)
21
+ #define ALIGN(x) __declspec(align(x))
22
+ #else
23
+ #define ALIGN(x) __attribute__((aligned(x)))
24
+ #endif
25
+
26
+ #if defined(__cplusplus)
27
+ extern "C" {
28
+ #endif
29
+
30
+ enum blake2s_constant
31
+ {
32
+ BLAKE2S_BLOCKBYTES = 64,
33
+ BLAKE2S_OUTBYTES = 32,
34
+ BLAKE2S_KEYBYTES = 32,
35
+ BLAKE2S_SALTBYTES = 8,
36
+ BLAKE2S_PERSONALBYTES = 8
37
+ };
38
+
39
+ enum blake2b_constant
40
+ {
41
+ BLAKE2B_BLOCKBYTES = 128,
42
+ BLAKE2B_OUTBYTES = 64,
43
+ BLAKE2B_KEYBYTES = 64,
44
+ BLAKE2B_SALTBYTES = 16,
45
+ BLAKE2B_PERSONALBYTES = 16
46
+ };
47
+
48
+ #pragma pack(push, 1)
49
+ typedef struct __blake2s_param
50
+ {
51
+ uint8_t digest_length; // 1
52
+ uint8_t key_length; // 2
53
+ uint8_t fanout; // 3
54
+ uint8_t depth; // 4
55
+ uint32_t leaf_length; // 8
56
+ uint8_t node_offset[6];// 14
57
+ uint8_t node_depth; // 15
58
+ uint8_t inner_length; // 16
59
+ // uint8_t reserved[0];
60
+ uint8_t salt[BLAKE2S_SALTBYTES]; // 24
61
+ uint8_t personal[BLAKE2S_PERSONALBYTES]; // 32
62
+ } blake2s_param;
63
+
64
+ ALIGN( 64 ) typedef struct __blake2s_state
65
+ {
66
+ uint32_t h[8];
67
+ uint32_t t[2];
68
+ uint32_t f[2];
69
+ uint8_t buf[2 * BLAKE2S_BLOCKBYTES];
70
+ size_t buflen;
71
+ uint8_t last_node;
72
+ } blake2s_state ;
73
+
74
+ typedef struct __blake2b_param
75
+ {
76
+ uint8_t digest_length; // 1
77
+ uint8_t key_length; // 2
78
+ uint8_t fanout; // 3
79
+ uint8_t depth; // 4
80
+ uint32_t leaf_length; // 8
81
+ uint64_t node_offset; // 16
82
+ uint8_t node_depth; // 17
83
+ uint8_t inner_length; // 18
84
+ uint8_t reserved[14]; // 32
85
+ uint8_t salt[BLAKE2B_SALTBYTES]; // 48
86
+ uint8_t personal[BLAKE2B_PERSONALBYTES]; // 64
87
+ } blake2b_param;
88
+
89
+ ALIGN( 64 ) typedef struct __blake2b_state
90
+ {
91
+ uint64_t h[8];
92
+ uint64_t t[2];
93
+ uint64_t f[2];
94
+ uint8_t buf[2 * BLAKE2B_BLOCKBYTES];
95
+ size_t buflen;
96
+ uint8_t last_node;
97
+ } blake2b_state;
98
+
99
+ typedef struct __blake2sp_state
100
+ {
101
+ blake2s_state S[8][1];
102
+ blake2s_state R[1];
103
+ uint8_t buf[8 * BLAKE2S_BLOCKBYTES];
104
+ size_t buflen;
105
+ } blake2sp_state;
106
+
107
+ typedef struct __blake2bp_state
108
+ {
109
+ blake2b_state S[4][1];
110
+ blake2b_state R[1];
111
+ uint8_t buf[4 * BLAKE2B_BLOCKBYTES];
112
+ size_t buflen;
113
+ } blake2bp_state;
114
+ #pragma pack(pop)
115
+
116
+ // Streaming API
117
+ int blake2s_init( blake2s_state *S, const uint8_t outlen );
118
+ int blake2s_init_key( blake2s_state *S, const uint8_t outlen, const void *key, const uint8_t keylen );
119
+ int blake2s_init_param( blake2s_state *S, const blake2s_param *P );
120
+ int blake2s_update( blake2s_state *S, const uint8_t *in, uint64_t inlen );
121
+ int blake2s_final( blake2s_state *S, uint8_t *out, uint8_t outlen );
122
+
123
+ int blake2b_init( blake2b_state *S, const uint8_t outlen );
124
+ int blake2b_init_key( blake2b_state *S, const uint8_t outlen, const void *key, const uint8_t keylen );
125
+ int blake2b_init_param( blake2b_state *S, const blake2b_param *P );
126
+ int blake2b_update( blake2b_state *S, const uint8_t *in, uint64_t inlen );
127
+ int blake2b_final( blake2b_state *S, uint8_t *out, uint8_t outlen );
128
+
129
+ int blake2sp_init( blake2sp_state *S, const uint8_t outlen );
130
+ int blake2sp_init_key( blake2sp_state *S, const uint8_t outlen, const void *key, const uint8_t keylen );
131
+ int blake2sp_update( blake2sp_state *S, const uint8_t *in, uint64_t inlen );
132
+ int blake2sp_final( blake2sp_state *S, uint8_t *out, uint8_t outlen );
133
+
134
+ int blake2bp_init( blake2bp_state *S, const uint8_t outlen );
135
+ int blake2bp_init_key( blake2bp_state *S, const uint8_t outlen, const void *key, const uint8_t keylen );
136
+ int blake2bp_update( blake2bp_state *S, const uint8_t *in, uint64_t inlen );
137
+ int blake2bp_final( blake2bp_state *S, uint8_t *out, uint8_t outlen );
138
+
139
+ // Simple API
140
+ int blake2s( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen );
141
+ int blake2b( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen );
142
+
143
+ int blake2sp( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen );
144
+ int blake2bp( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen );
145
+
146
+ static inline int blake2( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen )
147
+ {
148
+ return blake2b( out, in, key, outlen, inlen, keylen );
149
+ }
150
+
151
+ #if defined(__cplusplus)
152
+ }
153
+ #endif
154
+
155
+ #endif
156
+
@@ -0,0 +1,383 @@
1
+ /*
2
+ BLAKE2 reference source code package - reference 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
+
14
+ #include <stdint.h>
15
+ #include <string.h>
16
+ #include <stdio.h>
17
+
18
+ #include "blake2.h"
19
+ #include "blake2-impl.h"
20
+
21
+ static const uint32_t blake2s_IV[8] =
22
+ {
23
+ 0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
24
+ 0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
25
+ };
26
+
27
+ static const uint8_t blake2s_sigma[10][16] =
28
+ {
29
+ { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
30
+ { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
31
+ { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
32
+ { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
33
+ { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
34
+ { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
35
+ { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
36
+ { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
37
+ { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
38
+ { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
39
+ };
40
+
41
+ static inline int blake2s_set_lastnode( blake2s_state *S )
42
+ {
43
+ S->f[1] = ~0U;
44
+ return 0;
45
+ }
46
+
47
+ static inline int blake2s_clear_lastnode( blake2s_state *S )
48
+ {
49
+ S->f[1] = 0U;
50
+ return 0;
51
+ }
52
+
53
+ /* Some helper functions, not necessarily useful */
54
+ static inline int blake2s_set_lastblock( blake2s_state *S )
55
+ {
56
+ if( S->last_node ) blake2s_set_lastnode( S );
57
+
58
+ S->f[0] = ~0U;
59
+ return 0;
60
+ }
61
+
62
+ static inline int blake2s_clear_lastblock( blake2s_state *S )
63
+ {
64
+ if( S->last_node ) blake2s_clear_lastnode( S );
65
+
66
+ S->f[0] = 0U;
67
+ return 0;
68
+ }
69
+
70
+ static inline int blake2s_increment_counter( blake2s_state *S, const uint32_t inc )
71
+ {
72
+ S->t[0] += inc;
73
+ S->t[1] += ( S->t[0] < inc );
74
+ return 0;
75
+ }
76
+
77
+ // Parameter-related functions
78
+ static inline int blake2s_param_set_digest_length( blake2s_param *P, const uint8_t digest_length )
79
+ {
80
+ P->digest_length = digest_length;
81
+ return 0;
82
+ }
83
+
84
+ static inline int blake2s_param_set_fanout( blake2s_param *P, const uint8_t fanout )
85
+ {
86
+ P->fanout = fanout;
87
+ return 0;
88
+ }
89
+
90
+ static inline int blake2s_param_set_max_depth( blake2s_param *P, const uint8_t depth )
91
+ {
92
+ P->depth = depth;
93
+ return 0;
94
+ }
95
+
96
+ static inline int blake2s_param_set_leaf_length( blake2s_param *P, const uint32_t leaf_length )
97
+ {
98
+ store32( &P->leaf_length, leaf_length );
99
+ return 0;
100
+ }
101
+
102
+ static inline int blake2s_param_set_node_offset( blake2s_param *P, const uint64_t node_offset )
103
+ {
104
+ store48( P->node_offset, node_offset );
105
+ return 0;
106
+ }
107
+
108
+ static inline int blake2s_param_set_node_depth( blake2s_param *P, const uint8_t node_depth )
109
+ {
110
+ P->node_depth = node_depth;
111
+ return 0;
112
+ }
113
+
114
+ static inline int blake2s_param_set_inner_length( blake2s_param *P, const uint8_t inner_length )
115
+ {
116
+ P->inner_length = inner_length;
117
+ return 0;
118
+ }
119
+
120
+ static inline int blake2s_param_set_salt( blake2s_param *P, const uint8_t salt[BLAKE2S_SALTBYTES] )
121
+ {
122
+ memcpy( P->salt, salt, BLAKE2S_SALTBYTES );
123
+ return 0;
124
+ }
125
+
126
+ static inline int blake2s_param_set_personal( blake2s_param *P, const uint8_t personal[BLAKE2S_PERSONALBYTES] )
127
+ {
128
+ memcpy( P->personal, personal, BLAKE2S_PERSONALBYTES );
129
+ return 0;
130
+ }
131
+
132
+ static inline int blake2s_init0( blake2s_state *S )
133
+ {
134
+ memset( S, 0, sizeof( blake2s_state ) );
135
+
136
+ for( int i = 0; i < 8; ++i ) S->h[i] = blake2s_IV[i];
137
+
138
+ return 0;
139
+ }
140
+
141
+ /* init2 xors IV with input parameter block */
142
+ int blake2s_init_param( blake2s_state *S, const blake2s_param *P )
143
+ {
144
+ blake2s_init0( S );
145
+ const uint32_t *p = ( const uint32_t * )( P );
146
+
147
+ /* IV XOR ParamBlock */
148
+ for( size_t i = 0; i < 8; ++i )
149
+ S->h[i] ^= load32( &p[i] );
150
+
151
+ return 0;
152
+ }
153
+
154
+
155
+ // Sequential blake2s initialization
156
+ int blake2s_init( blake2s_state *S, const uint8_t outlen )
157
+ {
158
+ blake2s_param P[1];
159
+
160
+ /* Move interval verification here? */
161
+ if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1;
162
+
163
+ P->digest_length = outlen;
164
+ P->key_length = 0;
165
+ P->fanout = 1;
166
+ P->depth = 1;
167
+ store32( &P->leaf_length, 0 );
168
+ store48( &P->node_offset, 0 );
169
+ P->node_depth = 0;
170
+ P->inner_length = 0;
171
+ // memset(P->reserved, 0, sizeof(P->reserved) );
172
+ memset( P->salt, 0, sizeof( P->salt ) );
173
+ memset( P->personal, 0, sizeof( P->personal ) );
174
+ return blake2s_init_param( S, P );
175
+ }
176
+
177
+ int blake2s_init_key( blake2s_state *S, const uint8_t outlen, const void *key, const uint8_t keylen )
178
+ {
179
+ blake2s_param P[1];
180
+
181
+ if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1;
182
+
183
+ if ( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1;
184
+
185
+ P->digest_length = outlen;
186
+ P->key_length = keylen;
187
+ P->fanout = 1;
188
+ P->depth = 1;
189
+ store32( &P->leaf_length, 0 );
190
+ store48( &P->node_offset, 0 );
191
+ P->node_depth = 0;
192
+ P->inner_length = 0;
193
+ // memset(P->reserved, 0, sizeof(P->reserved) );
194
+ memset( P->salt, 0, sizeof( P->salt ) );
195
+ memset( P->personal, 0, sizeof( P->personal ) );
196
+
197
+ if( blake2s_init_param( S, P ) < 0 ) return -1;
198
+
199
+ {
200
+ uint8_t block[BLAKE2S_BLOCKBYTES];
201
+ memset( block, 0, BLAKE2S_BLOCKBYTES );
202
+ memcpy( block, key, keylen );
203
+ blake2s_update( S, block, BLAKE2S_BLOCKBYTES );
204
+ secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */
205
+ }
206
+ return 0;
207
+ }
208
+
209
+ static int blake2s_compress( blake2s_state *S, const uint8_t block[BLAKE2S_BLOCKBYTES] )
210
+ {
211
+ uint32_t m[16];
212
+ uint32_t v[16];
213
+
214
+ for( size_t i = 0; i < 16; ++i )
215
+ m[i] = load32( block + i * sizeof( m[i] ) );
216
+
217
+ for( size_t i = 0; i < 8; ++i )
218
+ v[i] = S->h[i];
219
+
220
+ v[ 8] = blake2s_IV[0];
221
+ v[ 9] = blake2s_IV[1];
222
+ v[10] = blake2s_IV[2];
223
+ v[11] = blake2s_IV[3];
224
+ v[12] = S->t[0] ^ blake2s_IV[4];
225
+ v[13] = S->t[1] ^ blake2s_IV[5];
226
+ v[14] = S->f[0] ^ blake2s_IV[6];
227
+ v[15] = S->f[1] ^ blake2s_IV[7];
228
+ #define G(r,i,a,b,c,d) \
229
+ do { \
230
+ a = a + b + m[blake2s_sigma[r][2*i+0]]; \
231
+ d = rotr32(d ^ a, 16); \
232
+ c = c + d; \
233
+ b = rotr32(b ^ c, 12); \
234
+ a = a + b + m[blake2s_sigma[r][2*i+1]]; \
235
+ d = rotr32(d ^ a, 8); \
236
+ c = c + d; \
237
+ b = rotr32(b ^ c, 7); \
238
+ } while(0)
239
+ #define ROUND(r) \
240
+ do { \
241
+ G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
242
+ G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
243
+ G(r,2,v[ 2],v[ 6],v[10],v[14]); \
244
+ G(r,3,v[ 3],v[ 7],v[11],v[15]); \
245
+ G(r,4,v[ 0],v[ 5],v[10],v[15]); \
246
+ G(r,5,v[ 1],v[ 6],v[11],v[12]); \
247
+ G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
248
+ G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
249
+ } while(0)
250
+ ROUND( 0 );
251
+ ROUND( 1 );
252
+ ROUND( 2 );
253
+ ROUND( 3 );
254
+ ROUND( 4 );
255
+ ROUND( 5 );
256
+ ROUND( 6 );
257
+ ROUND( 7 );
258
+ ROUND( 8 );
259
+ ROUND( 9 );
260
+
261
+ for( size_t i = 0; i < 8; ++i )
262
+ S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
263
+
264
+ #undef G
265
+ #undef ROUND
266
+ return 0;
267
+ }
268
+
269
+
270
+ int blake2s_update( blake2s_state *S, const uint8_t *in, uint64_t inlen )
271
+ {
272
+ while( inlen > 0 )
273
+ {
274
+ size_t left = S->buflen;
275
+ size_t fill = 2 * BLAKE2S_BLOCKBYTES - left;
276
+
277
+ if( inlen > fill )
278
+ {
279
+ memcpy( S->buf + left, in, fill ); // Fill buffer
280
+ S->buflen += fill;
281
+ blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );
282
+ blake2s_compress( S, S->buf ); // Compress
283
+ memcpy( S->buf, S->buf + BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES ); // Shift buffer left
284
+ S->buflen -= BLAKE2S_BLOCKBYTES;
285
+ in += fill;
286
+ inlen -= fill;
287
+ }
288
+ else // inlen <= fill
289
+ {
290
+ memcpy( S->buf + left, in, inlen );
291
+ S->buflen += inlen; // Be lazy, do not compress
292
+ in += inlen;
293
+ inlen -= inlen;
294
+ }
295
+ }
296
+
297
+ return 0;
298
+ }
299
+
300
+ int blake2s_final( blake2s_state *S, uint8_t *out, uint8_t outlen )
301
+ {
302
+ uint8_t buffer[BLAKE2S_OUTBYTES] = {0};
303
+
304
+ if( outlen > BLAKE2S_OUTBYTES )
305
+ return -1;
306
+
307
+ if( S->buflen > BLAKE2S_BLOCKBYTES )
308
+ {
309
+ blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES );
310
+ blake2s_compress( S, S->buf );
311
+ S->buflen -= BLAKE2S_BLOCKBYTES;
312
+ memcpy( S->buf, S->buf + BLAKE2S_BLOCKBYTES, S->buflen );
313
+ }
314
+
315
+ blake2s_increment_counter( S, ( uint32_t )S->buflen );
316
+ blake2s_set_lastblock( S );
317
+ memset( S->buf + S->buflen, 0, 2 * BLAKE2S_BLOCKBYTES - S->buflen ); /* Padding */
318
+ blake2s_compress( S, S->buf );
319
+
320
+ for( int i = 0; i < 8; ++i ) /* Output full hash to temp buffer */
321
+ store32( buffer + sizeof( S->h[i] ) * i, S->h[i] );
322
+
323
+ memcpy( out, buffer, outlen );
324
+ return 0;
325
+ }
326
+
327
+ int blake2s( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen )
328
+ {
329
+ blake2s_state S[1];
330
+
331
+ /* Verify parameters */
332
+ if ( NULL == in ) return -1;
333
+
334
+ if ( NULL == out ) return -1;
335
+
336
+ if ( NULL == key ) keylen = 0; /* Fail here instead if keylen != 0 and key == NULL? */
337
+
338
+ if( keylen > 0 )
339
+ {
340
+ if( blake2s_init_key( S, outlen, key, keylen ) < 0 ) return -1;
341
+ }
342
+ else
343
+ {
344
+ if( blake2s_init( S, outlen ) < 0 ) return -1;
345
+ }
346
+
347
+ blake2s_update( S, ( const uint8_t * )in, inlen );
348
+ blake2s_final( S, out, outlen );
349
+ return 0;
350
+ }
351
+
352
+ #if defined(BLAKE2S_SELFTEST)
353
+ #include <string.h>
354
+ #include "blake2-kat.h"
355
+ int main( int argc, char **argv )
356
+ {
357
+ uint8_t key[BLAKE2S_KEYBYTES];
358
+ uint8_t buf[KAT_LENGTH];
359
+
360
+ for( size_t i = 0; i < BLAKE2S_KEYBYTES; ++i )
361
+ key[i] = ( uint8_t )i;
362
+
363
+ for( size_t i = 0; i < KAT_LENGTH; ++i )
364
+ buf[i] = ( uint8_t )i;
365
+
366
+ for( size_t i = 0; i < KAT_LENGTH; ++i )
367
+ {
368
+ uint8_t hash[BLAKE2S_OUTBYTES];
369
+ blake2s( hash, buf, key, BLAKE2S_OUTBYTES, i, BLAKE2S_KEYBYTES );
370
+
371
+ if( 0 != memcmp( hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES ) )
372
+ {
373
+ puts( "error" );
374
+ return -1;
375
+ }
376
+ }
377
+
378
+ puts( "ok" );
379
+ return 0;
380
+ }
381
+ #endif
382
+
383
+