libQuotient
A Qt library for building matrix clients
Loading...
Searching...
No Matches
cryptoutils.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2023 Tobias Fella <tobias.fella@kde.org>
2// SPDX-License-Identifier: LGPL-2.0-or-later
3
4#pragma once
5
6#include "e2ee_common.h"
7
8namespace Quotient {
9
10// Common remark: OpenSSL is a private dependency of libQuotient, meaning that
11// headers of libQuotient can't include OpenSSL headers. Instead, alias
12// the value or type along with a comment (see SslErrorCode e.g.) and add
13// static_assert in the .cpp file to check it against the OpenSSL definition.
14
15constexpr auto DefaultPbkdf2KeyLength = 32u;
16constexpr auto Aes256KeySize = 32u;
17constexpr auto AesBlockSize = 16u; // AES_BLOCK_SIZE
18constexpr auto HmacKeySize = 32u;
19
22 //! \brief Key to be used for AES encryption / decryption
23 auto aes() const { return asCBytes(*this).first<Aes256KeySize>(); }
24 //! \brief Key to be used for MAC creation / verification
25 auto mac() const { return asCBytes(*this).last<HmacKeySize>(); }
26};
27
32};
33
34// NOLINTNEXTLINE(google-runtime-int): the type is copied from OpenSSL
35using SslErrorCode = unsigned long; // decltype(ERR_get_error())
36
37template <size_t Size = DefaultPbkdf2KeyLength>
38using key_material_t = std::array<byte_t, Size>;
39using key_view_t = byte_view_t<DefaultPbkdf2KeyLength>;
40
42 SslErrorUserOffset = 128, // ERR_LIB_USER; never use this bare
45};
46
47//! Same as QOlmExpected but for wrapping OpenSSL instead of Olm calls
48template <typename T>
49using SslExpected = std::expected<T, SslErrorCode>;
50
51// TODO, 0.9: merge zeroedByteArray() into zeroes() and replace const QByteArray& with
52// QByteArrayView where OpenSSL/Olm expect an array of signed chars
53
54inline QByteArray zeroedByteArray(QByteArray::size_type n = 32) { return { n, '\0' }; }
55
56template <size_t N, typename T = uint8_t> consteval std::array<T, N> zeroes() { return {}; }
57
58namespace _impl {
59 QUOTIENT_API SslExpected<std::monostate> pbkdf2HmacSha512(const QByteArray &passphrase,
60 const QByteArray &salt,
61 int iterations, byte_span_t<> output);
62}
63
64//! Generate a key out of the given passphrase
65template <size_t Size = DefaultPbkdf2KeyLength>
66QUOTIENT_API inline SslExpected<key_material_t<Size>> pbkdf2HmacSha512(const QByteArray& passphrase,
67 const QByteArray& salt,
68 int iterations)
69{
70 static_assert(Size > 0 && Size < std::numeric_limits<int>::max()); // OpenSSL limitation
71 key_material_t<Size> result;
72 return _impl::pbkdf2HmacSha512(passphrase, salt, iterations, result).transform([&result](auto) {
73 return result;
74 });
75}
76
77//! \brief Derive a key from the input data using HKDF-SHA256
78//!
79//! The info parameter should be either 0 or 32 bytes long
80QUOTIENT_API SslExpected<HkdfKeys> hkdfSha256(key_view_t key, byte_view_t<32> salt,
81 byte_view_t<> info);
82
83//! Calculate a MAC from the given key and data
84QUOTIENT_API SslExpected<QByteArray> hmacSha256(
85 byte_view_t<HmacKeySize> hmacKey,
86 const QByteArray& data);
87
88//! \brief Decrypt the data using Curve25519-AES-Sha256
89//! \note ciphertext must be given as base64
90QUOTIENT_API QOlmExpected<QByteArray> curve25519AesSha2Decrypt(
91 QByteArray ciphertext, const QByteArray& privateKey,
92 const QByteArray& ephemeral, const QByteArray& mac);
93
94//! \brief Encrypt the data using Curve25519-AES-Sha256
95//! \note publicKey must be given as base64
96QUOTIENT_API QOlmExpected<Curve25519Encrypted> curve25519AesSha2Encrypt(
97 const QByteArray& plaintext, const QByteArray& publicKey);
98
99//! \brief Encrypt data using AES-CTR-256
100//!
101//! key and iv have a length of 32 bytes
102QUOTIENT_API SslExpected<QByteArray> aesCtr256Encrypt(
103 const QByteArray& plaintext, byte_view_t<Aes256KeySize> key,
104 byte_view_t<AesBlockSize> iv);
105
106//! \brief Decrypt data using AES-CTR-256
107//!
108//! key and iv have a length of 32 bytes
109QUOTIENT_API SslExpected<QByteArray> aesCtr256Decrypt(
110 const QByteArray& ciphertext, byte_view_t<Aes256KeySize> key,
111 byte_view_t<AesBlockSize> iv);
112
113QUOTIENT_API std::vector<byte_t> base58Decode(const QByteArray& encoded);
114
115QUOTIENT_API QByteArray sign(const QByteArray &key, const QByteArray &data);
116
117} // namespace Quotient
consteval std::array< T, N > zeroes()
Definition cryptoutils.h:56
constexpr auto DefaultPbkdf2KeyLength
Definition cryptoutils.h:15
@ SslPayloadTooLong
Definition cryptoutils.h:44
@ WrongDerivedKeyLength
Definition cryptoutils.h:43
@ SslErrorUserOffset
Definition cryptoutils.h:42
constexpr auto AesBlockSize
Definition cryptoutils.h:17
constexpr auto HmacKeySize
Definition cryptoutils.h:18
QByteArray zeroedByteArray(QByteArray::size_type n=32)
Definition cryptoutils.h:54
constexpr auto Aes256KeySize
Definition cryptoutils.h:16
#define QUOTIENT_API