2020-04-09 02:39:48 +04:30
|
|
|
/*
|
2021-04-23 00:43:01 +04:30
|
|
|
* Copyright (c) 2020, Ali Mohammad Pur <mpfard@serenityos.org>
|
2020-04-09 02:39:48 +04:30
|
|
|
*
|
2021-04-22 01:24:48 -07:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
2020-04-09 02:39:48 +04:30
|
|
|
*/
|
|
|
|
|
|
2024-11-29 20:58:33 +01:00
|
|
|
#include <AK/ByteBuffer.h>
|
2021-01-15 21:46:23 +01:00
|
|
|
#include <AK/Debug.h>
|
2020-05-27 12:28:17 +02:00
|
|
|
#include <AK/Random.h>
|
2020-04-09 02:39:48 +04:30
|
|
|
#include <LibCrypto/ASN1/ASN1.h>
|
|
|
|
|
#include <LibCrypto/ASN1/DER.h>
|
|
|
|
|
#include <LibCrypto/ASN1/PEM.h>
|
2024-11-24 22:03:11 +01:00
|
|
|
#include <LibCrypto/Certificate/Certificate.h>
|
2020-04-09 02:39:48 +04:30
|
|
|
#include <LibCrypto/PK/RSA.h>
|
2024-12-20 10:32:11 -06:00
|
|
|
#include <LibCrypto/SecureRandom.h>
|
2020-04-09 02:39:48 +04:30
|
|
|
|
2023-07-11 13:49:08 -04:00
|
|
|
namespace Crypto::PK {
|
2020-04-09 02:39:48 +04:30
|
|
|
|
2024-11-29 18:28:18 +01:00
|
|
|
ErrorOr<RSA::KeyPairType> RSA::parse_rsa_key(ReadonlyBytes der, bool is_private, Vector<StringView> current_scope)
|
2020-04-23 03:03:05 +04:30
|
|
|
{
|
|
|
|
|
KeyPairType keypair;
|
2021-02-14 14:50:42 +03:30
|
|
|
|
|
|
|
|
ASN1::Decoder decoder(der);
|
2020-04-09 02:39:48 +04:30
|
|
|
|
2024-11-29 18:28:18 +01:00
|
|
|
if (is_private) {
|
|
|
|
|
// RSAPrivateKey ::= SEQUENCE {
|
|
|
|
|
// version Version,
|
|
|
|
|
// modulus INTEGER,
|
|
|
|
|
// publicExponent INTEGER,
|
|
|
|
|
// privateExponent INTEGER,
|
|
|
|
|
// prime1 INTEGER,
|
|
|
|
|
// prime2 INTEGER,
|
|
|
|
|
// exponent1 INTEGER,
|
|
|
|
|
// exponent2 INTEGER,
|
|
|
|
|
// coefficient INTEGER,
|
|
|
|
|
// otherPrimeInfos OtherPrimeInfos OPTIONAL
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
ENTER_TYPED_SCOPE(Sequence, "RSAPrivateKey"sv);
|
|
|
|
|
|
|
|
|
|
PUSH_SCOPE("version");
|
|
|
|
|
READ_OBJECT(Integer, Crypto::UnsignedBigInteger, version);
|
|
|
|
|
POP_SCOPE();
|
|
|
|
|
if (version != 0) {
|
|
|
|
|
ERROR_WITH_SCOPE(TRY(String::formatted("Invalid version value at {}", current_scope)));
|
2021-02-14 14:50:42 +03:30
|
|
|
}
|
2020-04-23 03:03:05 +04:30
|
|
|
|
2024-11-29 18:28:18 +01:00
|
|
|
PUSH_SCOPE("modulus");
|
|
|
|
|
READ_OBJECT(Integer, Crypto::UnsignedBigInteger, modulus);
|
|
|
|
|
POP_SCOPE();
|
2021-02-14 14:50:42 +03:30
|
|
|
|
2024-11-29 18:28:18 +01:00
|
|
|
PUSH_SCOPE("publicExponent");
|
|
|
|
|
READ_OBJECT(Integer, Crypto::UnsignedBigInteger, public_exponent);
|
|
|
|
|
POP_SCOPE();
|
|
|
|
|
|
|
|
|
|
PUSH_SCOPE("privateExponent");
|
|
|
|
|
READ_OBJECT(Integer, Crypto::UnsignedBigInteger, private_exponent);
|
|
|
|
|
POP_SCOPE();
|
|
|
|
|
|
|
|
|
|
PUSH_SCOPE("prime1");
|
|
|
|
|
READ_OBJECT(Integer, Crypto::UnsignedBigInteger, prime1);
|
|
|
|
|
POP_SCOPE();
|
|
|
|
|
|
|
|
|
|
PUSH_SCOPE("prime2");
|
|
|
|
|
READ_OBJECT(Integer, Crypto::UnsignedBigInteger, prime2);
|
|
|
|
|
POP_SCOPE();
|
|
|
|
|
|
|
|
|
|
PUSH_SCOPE("exponent1");
|
|
|
|
|
READ_OBJECT(Integer, Crypto::UnsignedBigInteger, exponent1);
|
|
|
|
|
POP_SCOPE();
|
|
|
|
|
|
|
|
|
|
PUSH_SCOPE("exponent2");
|
|
|
|
|
READ_OBJECT(Integer, Crypto::UnsignedBigInteger, exponent2);
|
|
|
|
|
POP_SCOPE();
|
|
|
|
|
|
|
|
|
|
PUSH_SCOPE("coefficient");
|
|
|
|
|
READ_OBJECT(Integer, Crypto::UnsignedBigInteger, coefficient);
|
|
|
|
|
POP_SCOPE();
|
2021-02-14 14:50:42 +03:30
|
|
|
|
2024-11-29 20:58:33 +01:00
|
|
|
keypair.private_key = {
|
2024-11-29 18:28:18 +01:00
|
|
|
modulus,
|
|
|
|
|
private_exponent,
|
|
|
|
|
public_exponent,
|
|
|
|
|
prime1,
|
|
|
|
|
prime2,
|
|
|
|
|
exponent1,
|
|
|
|
|
exponent2,
|
|
|
|
|
coefficient,
|
2024-11-29 20:58:33 +01:00
|
|
|
};
|
2024-11-29 18:28:18 +01:00
|
|
|
keypair.public_key = { modulus, public_exponent };
|
2021-02-14 14:50:42 +03:30
|
|
|
|
2024-11-29 18:28:18 +01:00
|
|
|
EXIT_SCOPE();
|
2024-03-13 12:30:59 +01:00
|
|
|
return keypair;
|
2024-11-29 18:28:18 +01:00
|
|
|
} else {
|
|
|
|
|
// RSAPublicKey ::= SEQUENCE {
|
|
|
|
|
// modulus INTEGER,
|
|
|
|
|
// publicExponent INTEGER
|
|
|
|
|
// }
|
2021-02-14 14:50:42 +03:30
|
|
|
|
2024-11-29 18:28:18 +01:00
|
|
|
ENTER_TYPED_SCOPE(Sequence, "RSAPublicKey"sv);
|
2021-02-14 14:50:42 +03:30
|
|
|
|
2024-11-29 18:28:18 +01:00
|
|
|
PUSH_SCOPE("modulus");
|
|
|
|
|
READ_OBJECT(Integer, Crypto::UnsignedBigInteger, modulus);
|
|
|
|
|
POP_SCOPE();
|
2021-02-14 14:50:42 +03:30
|
|
|
|
2024-11-29 18:28:18 +01:00
|
|
|
PUSH_SCOPE("publicExponent");
|
|
|
|
|
READ_OBJECT(Integer, Crypto::UnsignedBigInteger, public_exponent);
|
|
|
|
|
POP_SCOPE();
|
2024-03-13 12:30:59 +01:00
|
|
|
|
2024-11-29 18:28:18 +01:00
|
|
|
keypair.public_key = { move(modulus), move(public_exponent) };
|
2024-03-13 12:30:59 +01:00
|
|
|
|
2024-11-29 18:28:18 +01:00
|
|
|
EXIT_SCOPE();
|
|
|
|
|
return keypair;
|
|
|
|
|
}
|
2020-04-23 03:03:05 +04:30
|
|
|
}
|
2020-04-09 02:39:48 +04:30
|
|
|
|
2024-12-23 17:41:37 +01:00
|
|
|
ErrorOr<RSA::KeyPairType> RSA::generate_key_pair(size_t bits, IntegerType e)
|
|
|
|
|
{
|
|
|
|
|
IntegerType p;
|
|
|
|
|
IntegerType q;
|
|
|
|
|
IntegerType lambda;
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
p = NumberTheory::random_big_prime(bits / 2);
|
|
|
|
|
q = NumberTheory::random_big_prime(bits / 2);
|
|
|
|
|
lambda = NumberTheory::LCM(p.minus(1), q.minus(1));
|
|
|
|
|
} while (!(NumberTheory::GCD(e, lambda) == 1));
|
|
|
|
|
|
|
|
|
|
auto n = p.multiplied_by(q);
|
|
|
|
|
|
|
|
|
|
auto d = NumberTheory::ModularInverse(e, lambda);
|
|
|
|
|
RSAKeyPair<PublicKeyType, PrivateKeyType> keys {
|
|
|
|
|
{ n, e },
|
|
|
|
|
{ n, d, e, p, q }
|
|
|
|
|
};
|
|
|
|
|
return keys;
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-23 17:55:27 +01:00
|
|
|
ErrorOr<void> RSA::encrypt(ReadonlyBytes in, Bytes& out)
|
2020-04-23 03:03:05 +04:30
|
|
|
{
|
2021-02-07 15:33:24 +03:30
|
|
|
dbgln_if(CRYPTO_DEBUG, "in size: {}", in.size());
|
2020-04-23 03:03:05 +04:30
|
|
|
auto in_integer = UnsignedBigInteger::import_data(in.data(), in.size());
|
2024-12-23 17:55:27 +01:00
|
|
|
if (in_integer >= m_public_key.modulus())
|
|
|
|
|
return Error::from_string_literal("Data too large for key");
|
|
|
|
|
|
2020-04-23 03:03:05 +04:30
|
|
|
auto exp = NumberTheory::ModularPower(in_integer, m_public_key.public_exponent(), m_public_key.modulus());
|
2020-08-15 18:38:24 +02:00
|
|
|
auto size = exp.export_data(out);
|
2020-07-31 13:33:14 +04:30
|
|
|
auto outsize = out.size();
|
2024-12-23 17:55:27 +01:00
|
|
|
VERIFY(size == outsize);
|
|
|
|
|
return {};
|
2020-04-23 03:03:05 +04:30
|
|
|
}
|
2020-04-09 02:39:48 +04:30
|
|
|
|
2024-12-23 17:55:27 +01:00
|
|
|
ErrorOr<void> RSA::decrypt(ReadonlyBytes in, Bytes& out)
|
2020-04-23 03:03:05 +04:30
|
|
|
{
|
|
|
|
|
auto in_integer = UnsignedBigInteger::import_data(in.data(), in.size());
|
2020-04-09 02:39:48 +04:30
|
|
|
|
2024-12-15 16:16:17 +01:00
|
|
|
UnsignedBigInteger m;
|
|
|
|
|
if (m_private_key.prime1().is_zero() || m_private_key.prime2().is_zero()) {
|
|
|
|
|
m = NumberTheory::ModularPower(in_integer, m_private_key.private_exponent(), m_private_key.modulus());
|
|
|
|
|
} else {
|
|
|
|
|
auto m1 = NumberTheory::ModularPower(in_integer, m_private_key.exponent1(), m_private_key.prime1());
|
|
|
|
|
auto m2 = NumberTheory::ModularPower(in_integer, m_private_key.exponent2(), m_private_key.prime2());
|
2024-12-18 18:51:48 +01:00
|
|
|
while (m1 < m2)
|
2024-12-15 16:16:17 +01:00
|
|
|
m1 = m1.plus(m_private_key.prime1());
|
|
|
|
|
|
|
|
|
|
auto h = NumberTheory::Mod(m1.minus(m2).multiplied_by(m_private_key.coefficient()), m_private_key.prime1());
|
|
|
|
|
m = m2.plus(h.multiplied_by(m_private_key.prime2()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto size = m.export_data(out);
|
2020-04-23 03:03:05 +04:30
|
|
|
auto align = m_private_key.length();
|
|
|
|
|
auto aligned_size = (size + align - 1) / align * align;
|
2020-04-09 02:39:48 +04:30
|
|
|
|
2020-04-23 03:03:05 +04:30
|
|
|
for (auto i = size; i < aligned_size; ++i)
|
|
|
|
|
out[out.size() - i - 1] = 0; // zero the non-aligned values
|
|
|
|
|
out = out.slice(out.size() - aligned_size, aligned_size);
|
2024-12-23 17:55:27 +01:00
|
|
|
return {};
|
2020-04-23 03:03:05 +04:30
|
|
|
}
|
2020-04-09 02:39:48 +04:30
|
|
|
|
2024-12-23 17:55:27 +01:00
|
|
|
ErrorOr<void> RSA::sign(ReadonlyBytes in, Bytes& out)
|
2020-04-23 03:03:05 +04:30
|
|
|
{
|
|
|
|
|
auto in_integer = UnsignedBigInteger::import_data(in.data(), in.size());
|
|
|
|
|
auto exp = NumberTheory::ModularPower(in_integer, m_private_key.private_exponent(), m_private_key.modulus());
|
2020-08-15 18:38:24 +02:00
|
|
|
auto size = exp.export_data(out);
|
2020-04-23 03:03:05 +04:30
|
|
|
out = out.slice(out.size() - size, size);
|
2024-12-23 17:55:27 +01:00
|
|
|
return {};
|
2020-04-23 03:03:05 +04:30
|
|
|
}
|
2020-04-09 02:39:48 +04:30
|
|
|
|
2024-12-23 17:55:27 +01:00
|
|
|
ErrorOr<void> RSA::verify(ReadonlyBytes in, Bytes& out)
|
2020-04-23 03:03:05 +04:30
|
|
|
{
|
|
|
|
|
auto in_integer = UnsignedBigInteger::import_data(in.data(), in.size());
|
|
|
|
|
auto exp = NumberTheory::ModularPower(in_integer, m_public_key.public_exponent(), m_public_key.modulus());
|
2020-08-15 18:38:24 +02:00
|
|
|
auto size = exp.export_data(out);
|
2020-04-23 03:03:05 +04:30
|
|
|
out = out.slice(out.size() - size, size);
|
2024-12-23 17:55:27 +01:00
|
|
|
return {};
|
2020-04-23 03:03:05 +04:30
|
|
|
}
|
2020-04-09 02:39:48 +04:30
|
|
|
|
2020-07-27 15:28:38 +02:00
|
|
|
void RSA::import_private_key(ReadonlyBytes bytes, bool pem)
|
2020-04-23 03:03:05 +04:30
|
|
|
{
|
2024-11-29 20:58:33 +01:00
|
|
|
ByteBuffer decoded_bytes;
|
2020-07-27 15:28:38 +02:00
|
|
|
if (pem) {
|
2024-11-29 20:58:33 +01:00
|
|
|
auto decoded = decode_pem(bytes);
|
|
|
|
|
if (decoded.type == PEMType::RSAPrivateKey) {
|
|
|
|
|
decoded_bytes = decoded.data;
|
|
|
|
|
} else if (decoded.type == PEMType::PrivateKey) {
|
|
|
|
|
ASN1::Decoder decoder(decoded.data);
|
|
|
|
|
auto maybe_key = Certificate::parse_private_key_info(decoder, {});
|
|
|
|
|
if (maybe_key.is_error()) {
|
|
|
|
|
dbgln("Failed to parse private key info: {}", maybe_key.error());
|
|
|
|
|
VERIFY_NOT_REACHED();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_private_key = maybe_key.release_value().rsa;
|
|
|
|
|
return;
|
|
|
|
|
} else {
|
|
|
|
|
dbgln("Expected a PEM encoded private key");
|
|
|
|
|
VERIFY_NOT_REACHED();
|
|
|
|
|
}
|
2020-07-27 15:28:38 +02:00
|
|
|
}
|
|
|
|
|
|
2024-11-29 18:28:18 +01:00
|
|
|
auto maybe_key = parse_rsa_key(decoded_bytes, true, {});
|
|
|
|
|
if (maybe_key.is_error()) {
|
|
|
|
|
dbgln("Failed to parse RSA private key: {}", maybe_key.error());
|
2021-02-23 20:42:32 +01:00
|
|
|
VERIFY_NOT_REACHED();
|
2020-04-09 02:39:48 +04:30
|
|
|
}
|
2024-11-29 18:28:18 +01:00
|
|
|
m_private_key = maybe_key.release_value().private_key;
|
2020-04-23 03:03:05 +04:30
|
|
|
}
|
2020-04-09 02:39:48 +04:30
|
|
|
|
2020-07-27 15:28:38 +02:00
|
|
|
void RSA::import_public_key(ReadonlyBytes bytes, bool pem)
|
2020-04-23 03:03:05 +04:30
|
|
|
{
|
2024-11-29 20:58:33 +01:00
|
|
|
ByteBuffer decoded_bytes;
|
2020-07-27 15:28:38 +02:00
|
|
|
if (pem) {
|
2024-11-29 20:58:33 +01:00
|
|
|
auto decoded = decode_pem(bytes);
|
|
|
|
|
if (decoded.type == PEMType::RSAPublicKey) {
|
|
|
|
|
decoded_bytes = decoded.data;
|
|
|
|
|
} else if (decoded.type == PEMType::PublicKey) {
|
|
|
|
|
ASN1::Decoder decoder(decoded.data);
|
|
|
|
|
auto maybe_key = Certificate::parse_subject_public_key_info(decoder, {});
|
|
|
|
|
if (maybe_key.is_error()) {
|
|
|
|
|
dbgln("Failed to parse subject public key info: {}", maybe_key.error());
|
|
|
|
|
VERIFY_NOT_REACHED();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_public_key = maybe_key.release_value().rsa;
|
|
|
|
|
return;
|
|
|
|
|
} else {
|
|
|
|
|
dbgln("Expected a PEM encoded public key");
|
|
|
|
|
VERIFY_NOT_REACHED();
|
|
|
|
|
}
|
2020-07-27 15:28:38 +02:00
|
|
|
}
|
|
|
|
|
|
2024-11-29 18:28:18 +01:00
|
|
|
auto maybe_key = parse_rsa_key(decoded_bytes, false, {});
|
|
|
|
|
if (maybe_key.is_error()) {
|
|
|
|
|
dbgln("Failed to parse RSA public key: {}", maybe_key.error());
|
2021-02-23 20:42:32 +01:00
|
|
|
VERIFY_NOT_REACHED();
|
2020-04-09 02:39:48 +04:30
|
|
|
}
|
2024-11-29 18:28:18 +01:00
|
|
|
m_public_key = maybe_key.release_value().public_key;
|
2020-04-23 03:03:05 +04:30
|
|
|
}
|
2020-04-09 02:39:48 +04:30
|
|
|
|
2024-12-23 17:55:27 +01:00
|
|
|
ErrorOr<void> RSA_PKCS1_EME::encrypt(ReadonlyBytes in, Bytes& out)
|
2020-04-23 03:03:05 +04:30
|
|
|
{
|
|
|
|
|
auto mod_len = (m_public_key.modulus().trimmed_length() * sizeof(u32) * 8 + 7) / 8;
|
2021-02-07 15:33:24 +03:30
|
|
|
dbgln_if(CRYPTO_DEBUG, "key size: {}", mod_len);
|
2024-12-23 17:55:27 +01:00
|
|
|
if (in.size() > mod_len - 11)
|
|
|
|
|
return Error::from_string_literal("Message too long");
|
|
|
|
|
|
|
|
|
|
if (out.size() < mod_len)
|
|
|
|
|
return Error::from_string_literal("Output buffer too small");
|
2020-04-09 02:39:48 +04:30
|
|
|
|
2020-04-23 03:03:05 +04:30
|
|
|
auto ps_length = mod_len - in.size() - 3;
|
2021-05-13 12:13:11 +04:30
|
|
|
Vector<u8, 8096> ps;
|
|
|
|
|
ps.resize(ps_length);
|
2020-04-09 02:39:48 +04:30
|
|
|
|
2024-12-20 10:32:11 -06:00
|
|
|
fill_with_secure_random(ps);
|
2021-05-14 17:27:38 +02:00
|
|
|
// since fill_with_random can create zeros (shocking!)
|
2020-04-24 17:39:58 +04:30
|
|
|
// we have to go through and un-zero the zeros
|
2023-04-02 13:08:43 -04:00
|
|
|
for (size_t i = 0; i < ps_length; ++i) {
|
2020-07-31 13:33:14 +04:30
|
|
|
while (!ps[i])
|
2023-04-02 13:08:43 -04:00
|
|
|
ps[i] = get_random<u8>();
|
|
|
|
|
}
|
2020-04-24 17:39:58 +04:30
|
|
|
|
2020-04-23 03:03:05 +04:30
|
|
|
u8 paddings[] { 0x00, 0x02 };
|
2020-04-09 02:39:48 +04:30
|
|
|
|
2020-04-23 03:03:05 +04:30
|
|
|
out.overwrite(0, paddings, 2);
|
2021-05-13 12:13:11 +04:30
|
|
|
out.overwrite(2, ps.data(), ps_length);
|
2020-04-23 03:03:05 +04:30
|
|
|
out.overwrite(2 + ps_length, paddings, 1);
|
|
|
|
|
out.overwrite(3 + ps_length, in.data(), in.size());
|
2020-12-19 18:14:38 +01:00
|
|
|
out = out.trim(3 + ps_length + in.size()); // should be a single block
|
2020-04-09 02:39:48 +04:30
|
|
|
|
2021-02-07 15:33:24 +03:30
|
|
|
dbgln_if(CRYPTO_DEBUG, "padded output size: {} buffer size: {}", 3 + ps_length + in.size(), out.size());
|
2020-04-09 02:39:48 +04:30
|
|
|
|
2024-12-23 17:55:27 +01:00
|
|
|
TRY(RSA::encrypt(out, out));
|
|
|
|
|
return {};
|
2020-04-23 03:03:05 +04:30
|
|
|
}
|
2024-12-23 17:55:27 +01:00
|
|
|
|
|
|
|
|
ErrorOr<void> RSA_PKCS1_EME::decrypt(ReadonlyBytes in, Bytes& out)
|
2020-04-23 03:03:05 +04:30
|
|
|
{
|
|
|
|
|
auto mod_len = (m_public_key.modulus().trimmed_length() * sizeof(u32) * 8 + 7) / 8;
|
2024-12-23 17:55:27 +01:00
|
|
|
if (in.size() != mod_len)
|
|
|
|
|
return Error::from_string_literal("Invalid input size");
|
2020-04-09 02:39:48 +04:30
|
|
|
|
2024-12-23 17:55:27 +01:00
|
|
|
TRY(RSA::decrypt(in, out));
|
2020-04-09 02:39:48 +04:30
|
|
|
|
2024-12-23 17:55:27 +01:00
|
|
|
if (out.size() < RSA::output_size())
|
|
|
|
|
return Error::from_string_literal("Not enough data after decryption");
|
2020-04-09 02:39:48 +04:30
|
|
|
|
2024-12-23 17:55:27 +01:00
|
|
|
if (out[0] != 0x00 || out[1] != 0x02)
|
|
|
|
|
return Error::from_string_literal("Invalid padding");
|
2020-04-09 02:39:48 +04:30
|
|
|
|
2020-04-23 03:03:05 +04:30
|
|
|
size_t offset = 2;
|
|
|
|
|
while (offset < out.size() && out[offset])
|
2020-04-09 02:39:48 +04:30
|
|
|
++offset;
|
|
|
|
|
|
2024-12-23 17:55:27 +01:00
|
|
|
if (offset == out.size())
|
|
|
|
|
return Error::from_string_literal("Garbage data, no zero to split padding");
|
2020-04-09 02:39:48 +04:30
|
|
|
|
2020-04-23 03:03:05 +04:30
|
|
|
++offset;
|
|
|
|
|
|
2024-12-23 17:55:27 +01:00
|
|
|
if (offset - 3 < 8)
|
|
|
|
|
return Error::from_string_literal("PS too small");
|
2020-04-23 03:03:05 +04:30
|
|
|
|
|
|
|
|
out = out.slice(offset, out.size() - offset);
|
2024-12-23 17:55:27 +01:00
|
|
|
return {};
|
2020-04-23 03:03:05 +04:30
|
|
|
}
|
|
|
|
|
|
2024-12-23 17:55:27 +01:00
|
|
|
ErrorOr<void> RSA_PKCS1_EME::sign(ReadonlyBytes, Bytes&)
|
2020-04-23 03:03:05 +04:30
|
|
|
{
|
2024-12-23 17:55:27 +01:00
|
|
|
return Error::from_string_literal("FIXME: RSA_PKCS_EME::sign");
|
2020-04-23 03:03:05 +04:30
|
|
|
}
|
2024-12-23 17:55:27 +01:00
|
|
|
|
|
|
|
|
ErrorOr<void> RSA_PKCS1_EME::verify(ReadonlyBytes, Bytes&)
|
2020-04-23 03:03:05 +04:30
|
|
|
{
|
2024-12-23 17:55:27 +01:00
|
|
|
return Error::from_string_literal("FIXME: RSA_PKCS_EME::verify");
|
2020-04-23 03:03:05 +04:30
|
|
|
}
|
2020-04-09 02:39:48 +04:30
|
|
|
}
|