diff options
Diffstat (limited to 'vendor/golang.org/x/crypto/blake2b/blake2x.go')
-rw-r--r-- | vendor/golang.org/x/crypto/blake2b/blake2x.go | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/vendor/golang.org/x/crypto/blake2b/blake2x.go b/vendor/golang.org/x/crypto/blake2b/blake2x.go new file mode 100644 index 0000000..52c414d --- /dev/null +++ b/vendor/golang.org/x/crypto/blake2b/blake2x.go | |||
@@ -0,0 +1,177 @@ | |||
1 | // Copyright 2017 The Go Authors. All rights reserved. | ||
2 | // Use of this source code is governed by a BSD-style | ||
3 | // license that can be found in the LICENSE file. | ||
4 | |||
5 | package blake2b | ||
6 | |||
7 | import ( | ||
8 | "encoding/binary" | ||
9 | "errors" | ||
10 | "io" | ||
11 | ) | ||
12 | |||
13 | // XOF defines the interface to hash functions that | ||
14 | // support arbitrary-length output. | ||
15 | type XOF interface { | ||
16 | // Write absorbs more data into the hash's state. It panics if called | ||
17 | // after Read. | ||
18 | io.Writer | ||
19 | |||
20 | // Read reads more output from the hash. It returns io.EOF if the limit | ||
21 | // has been reached. | ||
22 | io.Reader | ||
23 | |||
24 | // Clone returns a copy of the XOF in its current state. | ||
25 | Clone() XOF | ||
26 | |||
27 | // Reset resets the XOF to its initial state. | ||
28 | Reset() | ||
29 | } | ||
30 | |||
31 | // OutputLengthUnknown can be used as the size argument to NewXOF to indicate | ||
32 | // the length of the output is not known in advance. | ||
33 | const OutputLengthUnknown = 0 | ||
34 | |||
35 | // magicUnknownOutputLength is a magic value for the output size that indicates | ||
36 | // an unknown number of output bytes. | ||
37 | const magicUnknownOutputLength = (1 << 32) - 1 | ||
38 | |||
39 | // maxOutputLength is the absolute maximum number of bytes to produce when the | ||
40 | // number of output bytes is unknown. | ||
41 | const maxOutputLength = (1 << 32) * 64 | ||
42 | |||
43 | // NewXOF creates a new variable-output-length hash. The hash either produce a | ||
44 | // known number of bytes (1 <= size < 2**32-1), or an unknown number of bytes | ||
45 | // (size == OutputLengthUnknown). In the latter case, an absolute limit of | ||
46 | // 256GiB applies. | ||
47 | // | ||
48 | // A non-nil key turns the hash into a MAC. The key must between | ||
49 | // zero and 32 bytes long. | ||
50 | func NewXOF(size uint32, key []byte) (XOF, error) { | ||
51 | if len(key) > Size { | ||
52 | return nil, errKeySize | ||
53 | } | ||
54 | if size == magicUnknownOutputLength { | ||
55 | // 2^32-1 indicates an unknown number of bytes and thus isn't a | ||
56 | // valid length. | ||
57 | return nil, errors.New("blake2b: XOF length too large") | ||
58 | } | ||
59 | if size == OutputLengthUnknown { | ||
60 | size = magicUnknownOutputLength | ||
61 | } | ||
62 | x := &xof{ | ||
63 | d: digest{ | ||
64 | size: Size, | ||
65 | keyLen: len(key), | ||
66 | }, | ||
67 | length: size, | ||
68 | } | ||
69 | copy(x.d.key[:], key) | ||
70 | x.Reset() | ||
71 | return x, nil | ||
72 | } | ||
73 | |||
74 | type xof struct { | ||
75 | d digest | ||
76 | length uint32 | ||
77 | remaining uint64 | ||
78 | cfg, root, block [Size]byte | ||
79 | offset int | ||
80 | nodeOffset uint32 | ||
81 | readMode bool | ||
82 | } | ||
83 | |||
84 | func (x *xof) Write(p []byte) (n int, err error) { | ||
85 | if x.readMode { | ||
86 | panic("blake2b: write to XOF after read") | ||
87 | } | ||
88 | return x.d.Write(p) | ||
89 | } | ||
90 | |||
91 | func (x *xof) Clone() XOF { | ||
92 | clone := *x | ||
93 | return &clone | ||
94 | } | ||
95 | |||
96 | func (x *xof) Reset() { | ||
97 | x.cfg[0] = byte(Size) | ||
98 | binary.LittleEndian.PutUint32(x.cfg[4:], uint32(Size)) // leaf length | ||
99 | binary.LittleEndian.PutUint32(x.cfg[12:], x.length) // XOF length | ||
100 | x.cfg[17] = byte(Size) // inner hash size | ||
101 | |||
102 | x.d.Reset() | ||
103 | x.d.h[1] ^= uint64(x.length) << 32 | ||
104 | |||
105 | x.remaining = uint64(x.length) | ||
106 | if x.remaining == magicUnknownOutputLength { | ||
107 | x.remaining = maxOutputLength | ||
108 | } | ||
109 | x.offset, x.nodeOffset = 0, 0 | ||
110 | x.readMode = false | ||
111 | } | ||
112 | |||
113 | func (x *xof) Read(p []byte) (n int, err error) { | ||
114 | if !x.readMode { | ||
115 | x.d.finalize(&x.root) | ||
116 | x.readMode = true | ||
117 | } | ||
118 | |||
119 | if x.remaining == 0 { | ||
120 | return 0, io.EOF | ||
121 | } | ||
122 | |||
123 | n = len(p) | ||
124 | if uint64(n) > x.remaining { | ||
125 | n = int(x.remaining) | ||
126 | p = p[:n] | ||
127 | } | ||
128 | |||
129 | if x.offset > 0 { | ||
130 | blockRemaining := Size - x.offset | ||
131 | if n < blockRemaining { | ||
132 | x.offset += copy(p, x.block[x.offset:]) | ||
133 | x.remaining -= uint64(n) | ||
134 | return | ||
135 | } | ||
136 | copy(p, x.block[x.offset:]) | ||
137 | p = p[blockRemaining:] | ||
138 | x.offset = 0 | ||
139 | x.remaining -= uint64(blockRemaining) | ||
140 | } | ||
141 | |||
142 | for len(p) >= Size { | ||
143 | binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset) | ||
144 | x.nodeOffset++ | ||
145 | |||
146 | x.d.initConfig(&x.cfg) | ||
147 | x.d.Write(x.root[:]) | ||
148 | x.d.finalize(&x.block) | ||
149 | |||
150 | copy(p, x.block[:]) | ||
151 | p = p[Size:] | ||
152 | x.remaining -= uint64(Size) | ||
153 | } | ||
154 | |||
155 | if todo := len(p); todo > 0 { | ||
156 | if x.remaining < uint64(Size) { | ||
157 | x.cfg[0] = byte(x.remaining) | ||
158 | } | ||
159 | binary.LittleEndian.PutUint32(x.cfg[8:], x.nodeOffset) | ||
160 | x.nodeOffset++ | ||
161 | |||
162 | x.d.initConfig(&x.cfg) | ||
163 | x.d.Write(x.root[:]) | ||
164 | x.d.finalize(&x.block) | ||
165 | |||
166 | x.offset = copy(p, x.block[:todo]) | ||
167 | x.remaining -= uint64(todo) | ||
168 | } | ||
169 | return | ||
170 | } | ||
171 | |||
172 | func (d *digest) initConfig(cfg *[Size]byte) { | ||
173 | d.offset, d.c[0], d.c[1] = 0, 0, 0 | ||
174 | for i := range d.h { | ||
175 | d.h[i] = iv[i] ^ binary.LittleEndian.Uint64(cfg[i*8:]) | ||
176 | } | ||
177 | } | ||