]> Cypherpunks.ru repositories - gostls13.git/blob - src/crypto/tls/gost.go
d60a5b82a3dc74a08f53c0f22349f8a136a116a8
[gostls13.git] / src / crypto / tls / gost.go
1 // Copyright (C) 2020-2023 Sergey Matveev <stargrave@rnd.stcnet.ru>
2 // Use of this source code is governed by GPLv3 licence.
3
4 package tls
5
6 import (
7         "crypto/cipher"
8         "encoding/binary"
9
10         "crypto/go.cypherpunks.ru/gogost/v5/gost34112012256"
11         "crypto/go.cypherpunks.ru/gogost/v5/gost3412128"
12         "crypto/go.cypherpunks.ru/gogost/v5/gost341264"
13         "crypto/go.cypherpunks.ru/gogost/v5/mgm"
14 )
15
16 const GOSTAEADNonceSize = 8
17
18 func reverseBytes(d []byte) {
19         for i, j := 0, len(d)-1; i < j; i, j = i+1, j-1 {
20                 d[i], d[j] = d[j], d[i]
21         }
22 }
23
24 type gostAEAD struct {
25         nonceMask []byte
26         tlsTree   *gost34112012256.TLSTree
27         cipherer  func([]byte) cipher.Block
28         aead      cipher.AEAD
29 }
30
31 func (g *gostAEAD) NonceSize() int        { return GOSTAEADNonceSize }
32 func (g *gostAEAD) Overhead() int         { return g.aead.Overhead() }
33 func (g *gostAEAD) explicitNonceLen() int { return 0 }
34
35 func (g *gostAEAD) keyRefresh(nonce []byte) {
36         if len(nonce) != GOSTAEADNonceSize {
37                 panic("64-bit nonce expected")
38         }
39         seqNum := binary.BigEndian.Uint64(nonce)
40         key, cached := g.tlsTree.DeriveCached(seqNum)
41         if cached {
42                 return
43         }
44         cipher := g.cipherer(key)
45         aead, err := mgm.NewMGM(cipher, cipher.BlockSize())
46         if err != nil {
47                 panic(err)
48         }
49         g.aead = aead
50 }
51
52 func (g *gostAEAD) xorNonce(nonce []byte) {
53         for i, b := range nonce {
54                 g.nonceMask[len(g.nonceMask)-GOSTAEADNonceSize+i] ^= b
55         }
56 }
57
58 func (g *gostAEAD) Seal(out, nonce, plaintext, additionalData []byte) []byte {
59         g.keyRefresh(nonce)
60         g.xorNonce(nonce)
61         ret := g.aead.Seal(out, g.nonceMask[:], plaintext, additionalData)
62         g.xorNonce(nonce)
63         return ret
64 }
65
66 func (g *gostAEAD) Open(out, nonce, ciphertext, additionalData []byte) ([]byte, error) {
67         g.keyRefresh(nonce)
68         g.xorNonce(nonce)
69         ret, err := g.aead.Open(out, g.nonceMask[:], ciphertext, additionalData)
70         g.xorNonce(nonce)
71         return ret, err
72 }
73
74 func aeadGOST(
75         blockSize int,
76         tlsTreeParams gost34112012256.TLSTreeParams,
77         cipherer func(key []byte) cipher.Block,
78         key, nonceMask []byte,
79 ) aead {
80         if len(nonceMask) != blockSize {
81                 panic("tls: internal error: wrong nonce length")
82         }
83         ret := gostAEAD{
84                 nonceMask: make([]byte, blockSize),
85                 tlsTree:   gost34112012256.NewTLSTree(tlsTreeParams, key),
86                 cipherer:  cipherer,
87         }
88         copy(ret.nonceMask, nonceMask)
89         ret.nonceMask[0] &= 0x7F
90         ret.keyRefresh([]byte{0, 0, 0, 0, 0, 0, 0, 0})
91         return &ret
92 }
93
94 func aeadGOSTR341112256WithKuznyechikMGML(key, nonceMask []byte) aead {
95         return aeadGOST(
96                 gost3412128.BlockSize,
97                 gost34112012256.TLSGOSTR341112256WithKuznyechikMGML,
98                 func(key []byte) cipher.Block { return gost3412128.NewCipher(key) },
99                 key, nonceMask,
100         )
101 }
102
103 func aeadGOSTR341112256WithMagmaMGML(key, nonceMask []byte) aead {
104         return aeadGOST(
105                 gost341264.BlockSize,
106                 gost34112012256.TLSGOSTR341112256WithMagmaMGML,
107                 func(key []byte) cipher.Block { return gost341264.NewCipher(key) },
108                 key, nonceMask,
109         )
110 }
111
112 func aeadGOSTR341112256WithKuznyechikMGMS(key, nonceMask []byte) aead {
113         return aeadGOST(
114                 gost3412128.BlockSize,
115                 gost34112012256.TLSGOSTR341112256WithKuznyechikMGMS,
116                 func(key []byte) cipher.Block { return gost3412128.NewCipher(key) },
117                 key, nonceMask,
118         )
119 }
120
121 func aeadGOSTR341112256WithMagmaMGMS(key, nonceMask []byte) aead {
122         return aeadGOST(
123                 gost341264.BlockSize,
124                 gost34112012256.TLSGOSTR341112256WithMagmaMGMS,
125                 func(key []byte) cipher.Block { return gost341264.NewCipher(key) },
126                 key, nonceMask,
127         )
128 }
129
130 var (
131         gostSavedDefaultSignatureAlgorithms       []SignatureScheme
132         gostSavedDefaultCipherSuites              []uint16
133         gostSavedDefaultCipherSuitesNoAES         []uint16
134         gostSavedCipherSuitesPreferenceOrder      []uint16
135         gostSavedCipherSuitesPreferenceOrderNoAES []uint16
136 )
137
138 func GOSTInstallSignatureAlgorithms(sigs []SignatureScheme) {
139         if gostSavedDefaultSignatureAlgorithms == nil {
140                 gostSavedDefaultSignatureAlgorithms = defaultSupportedSignatureAlgorithms
141         }
142         defaultSupportedSignatureAlgorithms = append(sigs, gostSavedDefaultSignatureAlgorithms...)
143 }
144
145 func GOSTInstallCipherSuites(suites []uint16) {
146         if gostSavedDefaultCipherSuites == nil {
147                 gostSavedDefaultCipherSuites = defaultCipherSuitesTLS13
148         }
149         if gostSavedDefaultCipherSuitesNoAES == nil {
150                 gostSavedDefaultCipherSuitesNoAES = defaultCipherSuitesTLS13NoAES
151         }
152         if gostSavedCipherSuitesPreferenceOrder == nil {
153                 gostSavedCipherSuitesPreferenceOrder = cipherSuitesPreferenceOrder
154         }
155         if gostSavedCipherSuitesPreferenceOrderNoAES == nil {
156                 gostSavedCipherSuitesPreferenceOrderNoAES = cipherSuitesPreferenceOrderNoAES
157         }
158         defaultCipherSuitesTLS13 = append(suites, gostSavedDefaultCipherSuites...)
159         defaultCipherSuitesTLS13NoAES = append(suites, gostSavedDefaultCipherSuitesNoAES...)
160         cipherSuitesPreferenceOrder = append(suites, gostSavedCipherSuitesPreferenceOrder...)
161         cipherSuitesPreferenceOrderNoAES = append(suites, gostSavedCipherSuitesPreferenceOrderNoAES...)
162 }
163
164 func GOSTInstall() {
165         GOSTInstallSignatureAlgorithms([]SignatureScheme{
166                 GOSTR34102012256A,
167                 GOSTR34102012256B,
168                 GOSTR34102012256C,
169                 GOSTR34102012256D,
170                 GOSTR34102012512A,
171                 GOSTR34102012512B,
172                 GOSTR34102012512C,
173         })
174         GOSTInstallCipherSuites([]uint16{
175                 TLS_GOSTR341112_256_WITH_KUZNYECHIK_MGM_L,
176                 TLS_GOSTR341112_256_WITH_MAGMA_MGM_L,
177                 TLS_GOSTR341112_256_WITH_KUZNYECHIK_MGM_S,
178                 TLS_GOSTR341112_256_WITH_MAGMA_MGM_S,
179         })
180 }