-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathutil.go
153 lines (138 loc) · 3.46 KB
/
util.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package luks
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"fmt"
"hash"
"os"
"syscall"
"github.com/dgryski/go-camellia"
"github.com/jzelinskie/whirlpool"
"golang.org/x/crypto/blake2b"
"golang.org/x/crypto/blake2s"
"golang.org/x/crypto/ripemd160"
"golang.org/x/crypto/sha3"
"golang.org/x/crypto/twofish"
"golang.org/x/sys/unix"
)
// default sector size
const storageSectorSize = 512
// default number of anti-forensic stripes
const stripesNum = 4000
// fileSize returns size of the file. This function works both with regular files and block devices
func fileSize(f *os.File) (uint64, error) {
st, err := f.Stat()
if err != nil {
return 0, err
}
sys, ok := st.Sys().(*syscall.Stat_t)
if !ok {
return 0, fmt.Errorf("unable to get stat for file %s", f.Name())
}
if sys.Mode&syscall.S_IFBLK == 0 {
return uint64(sys.Size), nil
}
sz, err := unix.IoctlGetInt(int(f.Fd()), unix.BLKGETSIZE64)
return uint64(sz), err
}
func isPowerOfTwo(x uint) bool {
return (x & (x - 1)) == 0
}
func roundUp(n int, divider int) int {
return (n + divider - 1) / divider * divider
}
func fixedArrayToString(buff []byte) string {
idx := bytes.IndexByte(buff, 0)
if idx != -1 {
buff = buff[:idx]
}
return string(buff)
}
func clearSlice(slice []byte) {
for i := range slice {
slice[i] = 0
}
}
// getHashAlgo gets hash implementation and the hash size by its name
// If hash is not found then it returns nil as a first argument
func getHashAlgo(name string) (func() hash.Hash, int) {
// Note that cryptsetup support a few more hash algorithms not implemented here: stribog256, stribog512, sm3
// golang lib does not implement those
// TODO use third-party implementations for other hashes and add its support to luks.go
switch name {
case "sha1":
return sha1.New, sha1.Size
case "sha224":
return sha256.New224, sha256.Size224
case "sha256":
return sha256.New, sha256.Size
case "sha384":
return sha512.New384, sha512.Size384
case "sha512":
return sha512.New, sha512.Size
case "sha3-224":
return sha3.New224, 224 / 8
case "sha3-256":
return sha3.New256, 256 / 8
case "sha3-384":
return sha3.New384, 384 / 8
case "sha3-512":
return sha3.New512, 512 / 8
case "ripemd160":
return ripemd160.New, ripemd160.Size
case "blake2b-160":
return blake2bConstructor(160)
case "blake2b-256":
return blake2bConstructor(256)
case "blake2b-384":
return blake2bConstructor(384)
case "blake2b-512":
return blake2bConstructor(512)
case "blake2s-256":
// blake2s-{128,160,224} are not supported by golang crypto library
return blake2s256Constructor()
case "whirlpool":
return whirlpool.New, 512 / 8
default:
return nil, 0
}
}
func getCipher(name string) (func(key []byte) (cipher.Block, error), error) {
switch name {
case "aes":
return aes.NewCipher, nil
case "camellia":
return camellia.New, nil
case "twofish":
f := func(key []byte) (cipher.Block, error) {
// twofish.NewCipher returns Cipher type, convert it to cipher.Block
return twofish.NewCipher(key)
}
return f, nil
default:
return nil, fmt.Errorf("Unknown cipher: %v", name)
}
}
func blake2bConstructor(size int) (func() hash.Hash, int) {
size = size / 8
return func() hash.Hash {
h, err := blake2b.New(size, nil)
if err != nil {
panic(err)
}
return h
}, size
}
func blake2s256Constructor() (func() hash.Hash, int) {
return func() hash.Hash {
h, err := blake2s.New256(nil)
if err != nil {
panic(err)
}
return h
}, 256 / 8
}