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