libkeepass 0.2.0
KeePass key database importer/exporter library
Loading...
Searching...
No Matches
cipher.hh
Go to the documentation of this file.
1/*
2 * libkeepass - KeePass key database importer/exporter
3 * Copyright (C) 2014 Christian Kindahl
4 * Copyright (C) 2024 Dominik Krümpelmann
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
22#pragma once
23#include <array>
24#include <cassert>
25#include <cstdint>
26#include <iostream>
27#include <memory>
28
29#include "libkeepass/export.hh"
30
31// Keep the public header independent of OpenSSL. The implementation files
32// include <openssl/evp.h> and use the complete type; consumers only need the
33// forward declaration to hold an AesCipher by value.
34struct evp_cipher_ctx_st;
35typedef struct evp_cipher_ctx_st EVP_CIPHER_CTX;
36
37namespace keepass {
38
39template <std::size_t N> class Cipher;
40
48LIBKEEPASS_API std::array<uint8_t, 32> encrypt_ecb(const std::array<uint8_t, 32>& src,
49 const Cipher<16>& cipher);
50
58LIBKEEPASS_API std::array<uint8_t, 32> decrypt_ecb(const std::array<uint8_t, 32>& src,
59 const Cipher<16>& cipher);
60
74LIBKEEPASS_API void encrypt_cbc(std::istream& src, std::ostream& dst, const Cipher<16>& cipher);
75
88LIBKEEPASS_API void decrypt_cbc(std::istream& src, std::ostream& dst, const Cipher<16>& cipher);
89
105LIBKEEPASS_API void decrypt_cbc_stream(std::istream& src, std::ostream& dst,
106 const Cipher<16>& cipher);
107
113template <std::size_t N> class Cipher {
114public:
115 virtual ~Cipher() = default;
116
121 virtual const std::array<uint8_t, N>& InitializationVector() const = 0;
122
129 virtual void Decrypt(const std::array<uint8_t, N>& src, std::array<uint8_t, N>& dst) const = 0;
130
137 virtual void Encrypt(const std::array<uint8_t, N>& src, std::array<uint8_t, N>& dst) const = 0;
138};
139
143class LIBKEEPASS_API AesCipher final : public Cipher<16> {
144private:
145 const std::array<uint8_t, 16> init_vec_;
146 EVP_CIPHER_CTX* ctx_dec_ = nullptr;
147 EVP_CIPHER_CTX* ctx_enc_ = nullptr;
148
149public:
155 explicit AesCipher(const uint8_t* key) : AesCipher(key, {0}) {}
156
164 AesCipher(const uint8_t* key, const std::array<uint8_t, 16>& init_vec);
165
168
170 const std::array<uint8_t, 16>& InitializationVector() const override { return init_vec_; }
171
178 void Decrypt(const std::array<uint8_t, 16>& src, std::array<uint8_t, 16>& dst) const override;
179
186 void Encrypt(const std::array<uint8_t, 16>& src, std::array<uint8_t, 16>& dst) const override;
187};
188
192class LIBKEEPASS_API TwofishCipher final : public Cipher<16> {
193private:
194 static const uint8_t kNumRounds = 16;
195
196 struct Key {
198 uint32_t sbox_keys[4];
200 uint32_t sub_keys[40];
201 } key_{};
202
203 const std::array<uint8_t, 16> init_vec_;
204
205 static inline uint32_t RotateLeft(uint32_t v, uint32_t n) {
206 return (v << (n & 0x1f)) | (v >> (32 - (n & 0x1f)));
207 }
208
209 static inline uint32_t RotateRight(uint32_t v, uint32_t n) {
210 return (v >> (n & 0x1f)) | (v << (32 - (n & 0x1f)));
211 }
212
220 static uint32_t ReedSolomonEncode(uint32_t k0, uint32_t k1);
221
229 static uint32_t F32(uint32_t x, const uint32_t* k32);
230
232 void InitializeKey(const uint8_t* key);
233
234public:
240 explicit TwofishCipher(const uint8_t* key) : TwofishCipher(key, {0}) {}
241
248 TwofishCipher(const uint8_t* key, const std::array<uint8_t, 16>& init_vec);
249
252
254 const std::array<uint8_t, 16>& InitializationVector() const override { return init_vec_; }
255
262 void Decrypt(const std::array<uint8_t, 16>& src, std::array<uint8_t, 16>& dst) const override;
263
270 void Encrypt(const std::array<uint8_t, 16>& src, std::array<uint8_t, 16>& dst) const override;
271};
272
277private:
278 std::array<uint32_t, 16> input_ = {{0}};
279
280 static inline uint32_t RotateLeft(uint32_t v, uint32_t n) {
281 return (v << (n & 0x1f)) | (v >> (32 - (n & 0x1f)));
282 }
283
290 static std::array<uint8_t, 64> WordToByte(const std::array<uint32_t, 16>& input);
291
292public:
298 explicit Salsa20Cipher(const uint8_t* key) : Salsa20Cipher(key, {0}) {}
299
306 Salsa20Cipher(const uint8_t* key, const std::array<uint8_t, 8>& init_vec);
307
310
320 void Process(const std::array<uint8_t, 64>& src, std::array<uint8_t, 64>& dst);
321};
322
327private:
328 std::array<uint32_t, 16> state_ = {{0}};
329
330 static inline uint32_t RotateLeft(uint32_t v, uint32_t n) {
331 return (v << (n & 0x1f)) | (v >> (32 - (n & 0x1f)));
332 }
333
340 static std::array<uint8_t, 64> BlockFunction(const std::array<uint32_t, 16>& state);
341
342public:
349 ChaCha20Cipher(const uint8_t* key, const std::array<uint8_t, 12>& init_vec);
350
353
363 void Process(const std::array<uint8_t, 64>& src, std::array<uint8_t, 64>& dst);
364};
365
366} // namespace keepass
LIBKEEPASS_API void encrypt_cbc(std::istream &src, std::ostream &dst, const Cipher< 16 > &cipher)
Encrypts a stream using CBC mode with PKCS #7 padding.
LIBKEEPASS_API std::array< uint8_t, 32 > decrypt_ecb(const std::array< uint8_t, 32 > &src, const Cipher< 16 > &cipher)
Decrypts a 32-byte block using ECB mode with the given cipher.
LIBKEEPASS_API void decrypt_cbc_stream(std::istream &src, std::ostream &dst, const Cipher< 16 > &cipher)
Decrypts a stream using CBC mode with PKCS #7 padding removal.
LIBKEEPASS_API void decrypt_cbc(std::istream &src, std::ostream &dst, const Cipher< 16 > &cipher)
Decrypts a stream using CBC mode with PKCS #7 padding removal.
LIBKEEPASS_API std::array< uint8_t, 32 > encrypt_ecb(const std::array< uint8_t, 32 > &src, const Cipher< 16 > &cipher)
Encrypts a 32-byte block using ECB mode with the given cipher.
AES-256-ECB block cipher using OpenSSL's EVP interface.
Definition cipher.hh:143
void Decrypt(const std::array< uint8_t, 16 > &src, std::array< uint8_t, 16 > &dst) const override
Decrypts a single 16-byte block using AES-256-ECB.
~AesCipher()
Destroys the cipher and frees the OpenSSL contexts.
void Encrypt(const std::array< uint8_t, 16 > &src, std::array< uint8_t, 16 > &dst) const override
Encrypts a single 16-byte block using AES-256-ECB.
AesCipher(const uint8_t *key)
Constructs an AES cipher with a zero initialization vector.
Definition cipher.hh:155
AesCipher(const uint8_t *key, const std::array< uint8_t, 16 > &init_vec)
Constructs an AES cipher with a given initialization vector.
const std::array< uint8_t, 16 > & InitializationVector() const override
Returns the initialization vector.
Definition cipher.hh:170
ChaCha20 stream cipher implementation (RFC 8439, 32-bit counter).
Definition cipher.hh:326
void Process(const std::array< uint8_t, 64 > &src, std::array< uint8_t, 64 > &dst)
Encrypts or decrypts a single 64-byte block.
~ChaCha20Cipher()
Zeroizes the cipher state holding the key.
ChaCha20Cipher(const uint8_t *key, const std::array< uint8_t, 12 > &init_vec)
Constructs a ChaCha20 cipher with the given key and nonce.
Abstract base class for 16-byte block ciphers.
Definition cipher.hh:113
virtual void Decrypt(const std::array< uint8_t, N > &src, std::array< uint8_t, N > &dst) const =0
Decrypts a single block.
virtual const std::array< uint8_t, N > & InitializationVector() const =0
Returns the initialization vector used by this cipher instance.
virtual void Encrypt(const std::array< uint8_t, N > &src, std::array< uint8_t, N > &dst) const =0
Encrypts a single block.
Salsa20 stream cipher implementation.
Definition cipher.hh:276
Salsa20Cipher(const uint8_t *key)
Constructs a Salsa20 cipher with a zero nonce.
Definition cipher.hh:298
Salsa20Cipher(const uint8_t *key, const std::array< uint8_t, 8 > &init_vec)
Constructs a Salsa20 cipher with a given 64-bit nonce.
~Salsa20Cipher()
Zeroizes the cipher state holding the key.
void Process(const std::array< uint8_t, 64 > &src, std::array< uint8_t, 64 > &dst)
Encrypts or decrypts a single 64-byte block.
Twofish-256 block cipher implementation.
Definition cipher.hh:192
~TwofishCipher()
Zeroizes the expanded key schedule.
void Decrypt(const std::array< uint8_t, 16 > &src, std::array< uint8_t, 16 > &dst) const override
Decrypts a single 16-byte block using Twofish-256.
const std::array< uint8_t, 16 > & InitializationVector() const override
Returns the initialization vector.
Definition cipher.hh:254
TwofishCipher(const uint8_t *key, const std::array< uint8_t, 16 > &init_vec)
Constructs a Twofish cipher with a given initialization vector.
TwofishCipher(const uint8_t *key)
Constructs a Twofish cipher with a zero initialization vector.
Definition cipher.hh:240
void Encrypt(const std::array< uint8_t, 16 > &src, std::array< uint8_t, 16 > &dst) const override
Encrypts a single 16-byte block using Twofish-256.
Visibility/export macro for the shared library.
#define LIBKEEPASS_API
Marks a class, function or variable as part of the public ABI.
Definition export.hh:43