Line data Source code
1 : /**
2 : Copyright (c) 2021-2022 Roman Katuntsev <sbkarr@stappler.org>
3 : Copyright (c) 2023-2024 Stappler LLC <admin@stappler.dev>
4 :
5 : Permission is hereby granted, free of charge, to any person obtaining a copy
6 : of this software and associated documentation files (the "Software"), to deal
7 : in the Software without restriction, including without limitation the rights
8 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 : copies of the Software, and to permit persons to whom the Software is
10 : furnished to do so, subject to the following conditions:
11 :
12 : The above copyright notice and this permission notice shall be included in
13 : all copies or substantial portions of the Software.
14 :
15 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 : THE SOFTWARE.
22 : **/
23 :
24 : #ifndef STAPPLER_CRYPTO_SPCRYPTO_H_
25 : #define STAPPLER_CRYPTO_SPCRYPTO_H_
26 :
27 : #include "SPIO.h"
28 : #include "SPBytesView.h"
29 : #include "SPCoreCrypto.h"
30 :
31 : namespace STAPPLER_VERSIONIZED stappler::crypto {
32 :
33 : // Гарантирует единственность шифротекста для разных бэкэндов в блочных шифрах
34 : // ценой производетльности. Если выключено - шифротексты могут различаться
35 : // (при этом сохраняется интероперабельность)
36 : #if DEBUG
37 : constexpr bool SafeBlockEncoding = true;
38 : #else
39 : constexpr bool SafeBlockEncoding = false;
40 : #endif
41 :
42 : constexpr size_t BlockKeySize256 = 32; // 256-bit
43 :
44 : class PublicKey;
45 :
46 : enum class Backend : uint32_t {
47 : Default,
48 : MbedTLS,
49 : OpenSSL,
50 : GnuTLS,
51 : Custom = 32,
52 : Embedded = maxOf<uint32_t>() - 1
53 : };
54 :
55 : enum class BackendFlags {
56 : None = 0,
57 : SecureLibrary = 1 << 0,
58 : SupportsPKCS1 = 1 << 1,
59 : SupportsPKCS8 = 1 << 2,
60 : SupportsECDSA = 1 << 3,
61 : SupportsAes = 1 << 4,
62 : SupportsGost3412_2015 = 1 << 5,
63 : SupportsGost3410_2012 = 1 << 6, // ЭЦП
64 : };
65 :
66 : SP_DEFINE_ENUM_AS_MASK(BackendFlags)
67 :
68 : enum class BlockCipher : uint16_t {
69 : AES_CBC,
70 : AES_CFB8,
71 : Gost3412_2015_CTR_ACPKM
72 : };
73 :
74 : enum class KeyType : uint32_t {
75 : Unknown,
76 : RSA,
77 : DSA,
78 : ECDSA,
79 : GOST3410_2012_256,
80 : GOST3410_2012_512,
81 : EDDSA_ED448,
82 : };
83 :
84 : enum class HashFunction {
85 : SHA_2,
86 : GOST_3411,
87 : };
88 :
89 : enum class SignAlgorithm {
90 : RSA_SHA256,
91 : RSA_SHA512,
92 : ECDSA_SHA256,
93 : ECDSA_SHA512,
94 : GOST_256, // GOST R 34.11-2012 256 bit
95 : GOST_512, // GOST R 34.11-2012 512 bit
96 : };
97 :
98 : enum class KeyBits {
99 : _1024,
100 : _2048,
101 : _4096
102 : };
103 :
104 : enum class KeyFormat {
105 : PKCS1,
106 : PKCS8,
107 : RSA = PKCS1,
108 : };
109 :
110 : struct KeyContext {
111 : void *cryptoCtx = nullptr;
112 : void *keyCtx = nullptr;
113 : uint32_t padding = 0;
114 : KeyType type = KeyType::Unknown;
115 : void *backendCtx = nullptr;
116 : };
117 :
118 : struct BlockKey256 {
119 125 : uint16_t version = 0; // keygen version
120 125 : BlockCipher cipher = BlockCipher::AES_CBC;
121 125 : std::array<uint8_t, BlockKeySize256> data = { 0 };
122 :
123 125 : bool operator==(const BlockKey256 &) const = default;
124 125 : bool operator!=(const BlockKey256 &) const = default;
125 : };
126 :
127 : struct BlockCryptoHeader {
128 : uint64_t size;
129 : uint16_t version;
130 : uint16_t cipher;
131 : uint32_t padding;
132 : };
133 :
134 : struct BlockInfo {
135 : uint64_t dataSize = 0;
136 : uint16_t version = 0; // keygen version
137 : BlockCipher cipher = BlockCipher::AES_CBC;
138 : };
139 :
140 : class PrivateKey {
141 : public:
142 : PrivateKey(Backend = Backend::Default);
143 : PrivateKey(Backend, BytesView, const CoderSource & passwd = CoderSource());
144 : PrivateKey(BytesView, const CoderSource & passwd = CoderSource());
145 : ~PrivateKey();
146 :
147 : PrivateKey(const PrivateKey &) = delete;
148 : PrivateKey& operator=(const PrivateKey &) = delete;
149 :
150 : PrivateKey(PrivateKey &&);
151 : PrivateKey& operator=(PrivateKey &&);
152 :
153 : bool generate(KeyType type = KeyType::RSA);
154 : bool generate(KeyBits = KeyBits::_2048, KeyType type = KeyType::RSA);
155 :
156 : bool import(BytesView, const CoderSource & passwd = CoderSource());
157 :
158 : PublicKey exportPublic() const;
159 :
160 : Backend getBackend() const;
161 1425 : KeyContext getKey() const { return _key; }
162 2000 : KeyType getType() const { return _key.type; }
163 :
164 1250 : explicit operator bool () const { return _valid && _loaded; }
165 :
166 : bool exportPem(const Callback<void(BytesView)> &, KeyFormat = KeyFormat::PKCS8, const CoderSource &passPhrase = StringView()) const;
167 : bool exportPem(const Callback<void(BytesView)> &, const CoderSource &passPhrase) const;
168 :
169 : bool exportDer(const Callback<void(BytesView)> &, KeyFormat = KeyFormat::PKCS8, const CoderSource &passPhrase = StringView()) const;
170 : bool exportDer(const Callback<void(BytesView)> &, const CoderSource &passPhrase) const;
171 :
172 : bool sign(const Callback<void(BytesView)> &, const CoderSource &, SignAlgorithm = SignAlgorithm::RSA_SHA512) const;
173 : bool verify(const CoderSource &data, BytesView signature, SignAlgorithm) const;
174 :
175 : bool fingerprint(const Callback<void(BytesView)> &, const CoderSource &) const;
176 :
177 : bool isGenerateSupported(KeyType) const;
178 : bool isSupported(KeyFormat) const;
179 :
180 : bool encrypt(const Callback<void(BytesView)> &, const CoderSource &);
181 : bool decrypt(const Callback<void(BytesView)> &, const CoderSource &);
182 :
183 : protected:
184 : bool _loaded = false;
185 : bool _valid = false;
186 : KeyContext _key;
187 : };
188 :
189 : class PublicKey {
190 : public:
191 : PublicKey(Backend = Backend::Default);
192 : PublicKey(Backend, BytesView);
193 : PublicKey(BytesView);
194 : PublicKey(const PrivateKey &);
195 : ~PublicKey();
196 :
197 : PublicKey(const PublicKey &) = delete;
198 : PublicKey& operator=(const PublicKey &) = delete;
199 :
200 : PublicKey(PublicKey &&);
201 : PublicKey& operator=(PublicKey &&);
202 :
203 : bool import(BytesView);
204 : bool importOpenSSH(StringView);
205 :
206 : Backend getBackend() const;
207 : KeyContext getKey() const { return _key; }
208 50 : KeyType getType() const { return _key.type; }
209 :
210 925 : explicit operator bool () const { return _valid && _loaded; }
211 :
212 : bool exportPem(const Callback<void(BytesView)> &) const; // only pkcs8
213 : bool exportDer(const Callback<void(BytesView)> &) const; // only pkcs8
214 :
215 : bool verify(const CoderSource &data, BytesView signature, SignAlgorithm) const;
216 :
217 : bool encrypt(const Callback<void(BytesView)> &, const CoderSource &);
218 :
219 : protected:
220 : bool _loaded = false;
221 : bool _valid = false;
222 : KeyContext _key;
223 : };
224 :
225 975 : inline constexpr size_t getBlockSize(BlockCipher c) {
226 975 : switch (c) {
227 475 : case BlockCipher::AES_CBC:
228 : case BlockCipher::AES_CFB8:
229 475 : return 16;
230 : break;
231 500 : case BlockCipher::Gost3412_2015_CTR_ACPKM:
232 500 : return 16;
233 : break;
234 : }
235 0 : return 16;
236 : }
237 :
238 : void listBackends(const Callback<void(Backend, StringView, BackendFlags)> &);
239 :
240 : bool isPemKey(BytesView data);
241 :
242 : bool encryptBlock(const BlockKey256 &, BytesView, const Callback<void(BytesView)> &);
243 : bool encryptBlock(Backend b, const BlockKey256 &, BytesView, const Callback<void(BytesView)> &);
244 :
245 : bool decryptBlock(const BlockKey256 &, BytesView, const Callback<void(BytesView)> &);
246 : bool decryptBlock(Backend b, const BlockKey256 &, BytesView, const Callback<void(BytesView)> &);
247 :
248 : BlockKey256 makeBlockKey(Backend, BytesView pkey, BytesView hash, BlockCipher = BlockCipher::AES_CBC, uint32_t version = 2);
249 : BlockKey256 makeBlockKey(BytesView pkey, BytesView hash, BlockCipher = BlockCipher::AES_CBC, uint32_t version = 2);
250 : BlockKey256 makeBlockKey(const PrivateKey &pkey, BytesView hash, uint32_t version = 2);
251 : BlockKey256 makeBlockKey(const PrivateKey &pkey, BytesView hash, BlockCipher, uint32_t version = 2);
252 :
253 : // get keygen version from encrypted block
254 : BlockInfo getBlockInfo(BytesView);
255 :
256 : using HashCoderCallback = const Callback<bool(const CoderSource &)>;
257 :
258 : Sha256::Buf hash256(Backend, const Callback<void( const HashCoderCallback &upd )> &, HashFunction func = HashFunction::SHA_2);
259 : Sha256::Buf hash256(const Callback<void( const HashCoderCallback &upd )> &, HashFunction func = HashFunction::SHA_2);
260 : Sha256::Buf hash256(Backend, const CoderSource &, HashFunction func = HashFunction::SHA_2);
261 : Sha256::Buf hash256(const CoderSource &, HashFunction func = HashFunction::SHA_2);
262 :
263 : Sha512::Buf hash512(Backend, const Callback<void( const HashCoderCallback &upd )> &, HashFunction func = HashFunction::SHA_2);
264 : Sha512::Buf hash512(const Callback<void( const HashCoderCallback &upd )> &, HashFunction func = HashFunction::SHA_2);
265 : Sha512::Buf hash512(Backend, const CoderSource &, HashFunction func = HashFunction::SHA_2);
266 : Sha512::Buf hash512(const CoderSource &, HashFunction func = HashFunction::SHA_2);
267 :
268 : }
269 :
270 : #endif /* STAPPLER_CRYPTO_SPCRYPTO_H_ */
|