-
Notifications
You must be signed in to change notification settings - Fork 1
/
aes_siv.go
95 lines (87 loc) · 3.72 KB
/
aes_siv.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
package siv
import (
"crypto/subtle"
"errors"
"strconv"
)
var (
//ErrAesSIVGeneric indicates a generic error with AesSIV
ErrAesSIVGeneric = errors.New("AES SIV Generic error: Something went wrong")
//ErrSivWrapGeneric indicates that an error occurred during the Wrap() function of AesSIV
ErrSivWrapGeneric = errors.New("Siv Wrap error: error wrapping the message")
//ErrSivWrapUnsupportedPlaintext indicates that the plaintext supplied to the AesSIV wrap() function is longer than supported (size is platform specific)
ErrSivWrapUnsupportedPlaintext = errors.New("Siv Wrap error: plaintext size is longer than supported")
//ErrSivWrapUnsupportedAdditionalData indicates that the additionalData elements supplied exceed the maximum number supported
ErrSivWrapUnsupportedAdditionalData = errors.New("Siv Wrap error: additionalData elements more than than supported")
//ErrSivUnwrapGeneric indicates that an error occurred during unwrap() function of AesSIV
ErrSivUnwrapGeneric = errors.New("Siv Unwrap error: error unwrapping the ciphertext")
//ErrFailSivUnwrap indicates that the AesSIV unwrap() function failed for the combination of key, ciphertext and additionalData
ErrFailSivUnwrap = errors.New("Siv Unwrap: Unwrapping the ciphertext failed")
//ErrSivUnWrapSizeUnsupportedCiphertext indicates that the ciphertext supplied to the AesSIV unwrap() function is longer than supported (size is platform specific)
ErrSivUnWrapSizeUnsupportedCiphertext = errors.New("Siv Unwrap error: ciphertext size is longer than supported")
//ErrSivUnWrapUnsupportedAdditionalData indicates that the additionalData elements supplied exceed the maximum number supported
ErrSivUnWrapUnsupportedAdditionalData = errors.New("Siv Unwrap error: additionalData elements more than than supported")
//ErrSivUnWrapShortCipherLength indicates that the cipher text is too short
ErrSivUnWrapShortCipherLength = errors.New("Siv Unwrap error: ciphertext is too short")
)
const (
clearer = 0x7F
)
type aesSiv struct {
sivBlockPair
}
func (c *aesSiv) CMACBlockSize() int {
return c.sivBlockPair.CMACBlockSize()
}
func (c *aesSiv) CTRBlockSize() int {
return c.sivBlockPair.CTRBlockSize()
}
func (c *aesSiv) Wrap(plaintext []byte, additionalData ...[]byte) ([]byte, error) {
ctrBlockSize := c.CTRBlockSize()
cmacBlockSize := c.CMACBlockSize()
if len(plaintext) > (1 << (strconv.IntSize - 3)) {
return nil, ErrSivWrapUnsupportedPlaintext
}
if len(additionalData) > (cmacBlockSize*8)-2 {
return nil, ErrSivWrapUnsupportedAdditionalData
}
v, s2verror := s2v(c.sivBlockPair, plaintext, additionalData...)
if s2verror != nil {
return nil, s2verror
}
ciphertext := make([]byte, len(plaintext)+ctrBlockSize)
copy(ciphertext, v)
v[8] = v[8] & clearer
v[12] = v[12] & clearer
c.sivBlockPair.Ctr(ciphertext[ctrBlockSize:], v, plaintext)
return ciphertext, nil
}
func (c *aesSiv) Unwrap(ciphertext []byte, additionalData ...[]byte) ([]byte, error) {
ctrBlockSize := c.CTRBlockSize()
cmacBlockSize := c.CMACBlockSize()
if len(ciphertext)-ctrBlockSize > (1 << (strconv.IntSize - 3)) {
return nil, ErrSivUnWrapSizeUnsupportedCiphertext
}
if len(ciphertext) < cmacBlockSize {
return nil, ErrSivUnWrapShortCipherLength
}
if len(additionalData) > (cmacBlockSize*8)-2 {
return nil, ErrSivUnWrapUnsupportedAdditionalData
}
v := make([]byte, ctrBlockSize)
copy(v, ciphertext)
q := make([]byte, len(v))
copy(q, v)
q[8] = q[8] & clearer
q[12] = q[12] & clearer
plaintext := make([]byte, len(ciphertext)-ctrBlockSize)
c.sivBlockPair.Ctr(plaintext, q, ciphertext[ctrBlockSize:])
t, s2verror := s2v(c.sivBlockPair, plaintext, additionalData...)
if s2verror != nil {
return nil, s2verror
}
if subtle.ConstantTimeCompare(t, v) != 1 {
return nil, ErrFailSivUnwrap
}
return plaintext, nil
}