source sync 20190409
[platform/core/system/edge-orchestration.git] / vendor / golang.org / x / crypto / blake2s / blake2s.go
1 // Copyright 2016 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 blake2s implements the BLAKE2s hash algorithm defined by RFC 7693
6 // and the extendable output function (XOF) BLAKE2Xs.
7 //
8 // For a detailed specification of BLAKE2s see https://blake2.net/blake2.pdf
9 // and for BLAKE2Xs see https://blake2.net/blake2x.pdf
10 //
11 // If you aren't sure which function you need, use BLAKE2s (Sum256 or New256).
12 // If you need a secret-key MAC (message authentication code), use the New256
13 // function with a non-nil key.
14 //
15 // BLAKE2X is a construction to compute hash values larger than 32 bytes. It
16 // can produce hash values between 0 and 65535 bytes.
17 package blake2s // import "golang.org/x/crypto/blake2s"
18
19 import (
20         "encoding/binary"
21         "errors"
22         "hash"
23 )
24
25 const (
26         // The blocksize of BLAKE2s in bytes.
27         BlockSize = 64
28
29         // The hash size of BLAKE2s-256 in bytes.
30         Size = 32
31
32         // The hash size of BLAKE2s-128 in bytes.
33         Size128 = 16
34 )
35
36 var errKeySize = errors.New("blake2s: invalid key size")
37
38 var iv = [8]uint32{
39         0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
40         0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
41 }
42
43 // Sum256 returns the BLAKE2s-256 checksum of the data.
44 func Sum256(data []byte) [Size]byte {
45         var sum [Size]byte
46         checkSum(&sum, Size, data)
47         return sum
48 }
49
50 // New256 returns a new hash.Hash computing the BLAKE2s-256 checksum. A non-nil
51 // key turns the hash into a MAC. The key must between zero and 32 bytes long.
52 // When the key is nil, the returned hash.Hash implements BinaryMarshaler
53 // and BinaryUnmarshaler for state (de)serialization as documented by hash.Hash.
54 func New256(key []byte) (hash.Hash, error) { return newDigest(Size, key) }
55
56 // New128 returns a new hash.Hash computing the BLAKE2s-128 checksum given a
57 // non-empty key. Note that a 128-bit digest is too small to be secure as a
58 // cryptographic hash and should only be used as a MAC, thus the key argument
59 // is not optional.
60 func New128(key []byte) (hash.Hash, error) {
61         if len(key) == 0 {
62                 return nil, errors.New("blake2s: a key is required for a 128-bit hash")
63         }
64         return newDigest(Size128, key)
65 }
66
67 func newDigest(hashSize int, key []byte) (*digest, error) {
68         if len(key) > Size {
69                 return nil, errKeySize
70         }
71         d := &digest{
72                 size:   hashSize,
73                 keyLen: len(key),
74         }
75         copy(d.key[:], key)
76         d.Reset()
77         return d, nil
78 }
79
80 func checkSum(sum *[Size]byte, hashSize int, data []byte) {
81         var (
82                 h [8]uint32
83                 c [2]uint32
84         )
85
86         h = iv
87         h[0] ^= uint32(hashSize) | (1 << 16) | (1 << 24)
88
89         if length := len(data); length > BlockSize {
90                 n := length &^ (BlockSize - 1)
91                 if length == n {
92                         n -= BlockSize
93                 }
94                 hashBlocks(&h, &c, 0, data[:n])
95                 data = data[n:]
96         }
97
98         var block [BlockSize]byte
99         offset := copy(block[:], data)
100         remaining := uint32(BlockSize - offset)
101
102         if c[0] < remaining {
103                 c[1]--
104         }
105         c[0] -= remaining
106
107         hashBlocks(&h, &c, 0xFFFFFFFF, block[:])
108
109         for i, v := range h {
110                 binary.LittleEndian.PutUint32(sum[4*i:], v)
111         }
112 }
113
114 type digest struct {
115         h      [8]uint32
116         c      [2]uint32
117         size   int
118         block  [BlockSize]byte
119         offset int
120
121         key    [BlockSize]byte
122         keyLen int
123 }
124
125 const (
126         magic         = "b2s"
127         marshaledSize = len(magic) + 8*4 + 2*4 + 1 + BlockSize + 1
128 )
129
130 func (d *digest) MarshalBinary() ([]byte, error) {
131         if d.keyLen != 0 {
132                 return nil, errors.New("crypto/blake2s: cannot marshal MACs")
133         }
134         b := make([]byte, 0, marshaledSize)
135         b = append(b, magic...)
136         for i := 0; i < 8; i++ {
137                 b = appendUint32(b, d.h[i])
138         }
139         b = appendUint32(b, d.c[0])
140         b = appendUint32(b, d.c[1])
141         // Maximum value for size is 32
142         b = append(b, byte(d.size))
143         b = append(b, d.block[:]...)
144         b = append(b, byte(d.offset))
145         return b, nil
146 }
147
148 func (d *digest) UnmarshalBinary(b []byte) error {
149         if len(b) < len(magic) || string(b[:len(magic)]) != magic {
150                 return errors.New("crypto/blake2s: invalid hash state identifier")
151         }
152         if len(b) != marshaledSize {
153                 return errors.New("crypto/blake2s: invalid hash state size")
154         }
155         b = b[len(magic):]
156         for i := 0; i < 8; i++ {
157                 b, d.h[i] = consumeUint32(b)
158         }
159         b, d.c[0] = consumeUint32(b)
160         b, d.c[1] = consumeUint32(b)
161         d.size = int(b[0])
162         b = b[1:]
163         copy(d.block[:], b[:BlockSize])
164         b = b[BlockSize:]
165         d.offset = int(b[0])
166         return nil
167 }
168
169 func (d *digest) BlockSize() int { return BlockSize }
170
171 func (d *digest) Size() int { return d.size }
172
173 func (d *digest) Reset() {
174         d.h = iv
175         d.h[0] ^= uint32(d.size) | (uint32(d.keyLen) << 8) | (1 << 16) | (1 << 24)
176         d.offset, d.c[0], d.c[1] = 0, 0, 0
177         if d.keyLen > 0 {
178                 d.block = d.key
179                 d.offset = BlockSize
180         }
181 }
182
183 func (d *digest) Write(p []byte) (n int, err error) {
184         n = len(p)
185
186         if d.offset > 0 {
187                 remaining := BlockSize - d.offset
188                 if n <= remaining {
189                         d.offset += copy(d.block[d.offset:], p)
190                         return
191                 }
192                 copy(d.block[d.offset:], p[:remaining])
193                 hashBlocks(&d.h, &d.c, 0, d.block[:])
194                 d.offset = 0
195                 p = p[remaining:]
196         }
197
198         if length := len(p); length > BlockSize {
199                 nn := length &^ (BlockSize - 1)
200                 if length == nn {
201                         nn -= BlockSize
202                 }
203                 hashBlocks(&d.h, &d.c, 0, p[:nn])
204                 p = p[nn:]
205         }
206
207         d.offset += copy(d.block[:], p)
208         return
209 }
210
211 func (d *digest) Sum(sum []byte) []byte {
212         var hash [Size]byte
213         d.finalize(&hash)
214         return append(sum, hash[:d.size]...)
215 }
216
217 func (d *digest) finalize(hash *[Size]byte) {
218         var block [BlockSize]byte
219         h := d.h
220         c := d.c
221
222         copy(block[:], d.block[:d.offset])
223         remaining := uint32(BlockSize - d.offset)
224         if c[0] < remaining {
225                 c[1]--
226         }
227         c[0] -= remaining
228
229         hashBlocks(&h, &c, 0xFFFFFFFF, block[:])
230         for i, v := range h {
231                 binary.LittleEndian.PutUint32(hash[4*i:], v)
232         }
233 }
234
235 func appendUint32(b []byte, x uint32) []byte {
236         var a [4]byte
237         binary.BigEndian.PutUint32(a[:], x)
238         return append(b, a[:]...)
239 }
240
241 func consumeUint32(b []byte) ([]byte, uint32) {
242         x := binary.BigEndian.Uint32(b)
243         return b[4:], x
244 }