[+] Added the old RSA wrappers

[*] Prepare for implementing ECC (again)
This commit is contained in:
Reece Wilson 2021-07-01 10:18:42 +01:00
parent f87c2b47a6
commit 9a93d4ec8d
27 changed files with 685 additions and 76 deletions

View File

@ -10,31 +10,19 @@
namespace Aurora::Crypto
{
using DerBuffer = AuList<AuUInt8>;
using PrivateRSAKey = DerBuffer; // a/k/a "RSA", OpenSSL, private key in mbedtls, PKCS1
using PublicRSAKey = DerBuffer;
using PrivateECCKey = DerBuffer;
using PublicECCKey = DerBuffer;
using PrivateKey = DerBuffer; // PKCS8
using PublicKey = DerBuffer;
namespace X509
{
using Certificate = AuList<AuUInt8>;
}
struct RSAPair
{
X509::Certificate pub;
PrivateRSAKey priv;
};
}
#include "EHashType.hpp"
#include "EKeyType.hpp"
#include "EPaddingType.hpp"
#include "AES/AES.hpp"
#include "X509/X509.hpp"
#include "CA/CA.hpp"
#include "ECC25519/ECC25519.hpp"
#include "ECCNIST/ECCNIST.hpp"
#include "ECC/ECC.hpp"
#include "PEM/PEM.hpp"
#include "RSA/RSA.hpp"

View File

@ -1,7 +1,7 @@
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: ECC25519.hpp
File: 25519.hpp
Date: 2021-6-11
Author: Reece
***/

View File

@ -1,7 +1,11 @@
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: EccX25519Private.cpp
Date: 2021-6-12
File: ECC.hpp
Date: 2021-7-1
Author: Reece
***/
#pragma once
#include "25519/25519.hpp"
#include "NIST/NIST.hpp"

View File

@ -1,7 +1,7 @@
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: ECCNIST.hpp
File: NIST.hpp
Date: 2021-6-11
Author: Reece
***/

View File

@ -0,0 +1,17 @@
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: EKeyType.hpp
Date: 2021-7-1
Author: Reece
***/
#pragma once
namespace Aurora::Crypto
{
enum class EKeyType
{
eKeyPublic,
eKeyPrivate
};
}

View File

@ -10,10 +10,10 @@
namespace Aurora::Crypto::PEM
{
AUKN_SYM AuString ToString(const Aurora::Crypto::X509::Certificate &in);
AUKN_SYM AuString PublicToString(const PublicKey &in);
AUKN_SYM AuString PrivateToString(const PrivateKey &in);
AUKN_SYM AuString PublicRSAToString(const PrivateRSAKey &in);
AUKN_SYM AuString PrivateRSAToString(const PublicRSAKey &in);
AUKN_SYM AuString PublicToString(const DerBuffer &in);
AUKN_SYM AuString PrivateToString(const DerBuffer &in);
AUKN_SYM AuString PublicRSAToString(const DerBuffer &in);
AUKN_SYM AuString PrivateRSAToString(const DerBuffer &in);
AUKN_SYM bool FromString(const AuString &in, Aurora::Crypto::X509::Certificate &out);
AUKN_SYM bool PublicFromString(const AuString &in, PublicKey &out);

View File

@ -0,0 +1,21 @@
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: ERSAKeyType.hpp
Date: 2021-7-1
Author: Reece
***/
#pragma once
namespace Aurora::Crypto::RSA
{
enum class ERSAKeyType
{
/// pkcs1
eRsaKey,
/// pkcs8
eKey,
/// x509
eCert
};
}

View File

@ -0,0 +1,30 @@
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: IRSAPrivate.hpp
Date: 2021-7-1
Author: Reece
***/
#pragma once
namespace Aurora::Crypto::RSA
{
// Remember: there is no such thing as private encryption
class IRSAPrivate
{
public:
virtual bool Sign(const void *buffer, AuUInt length,
EHashType method, EPaddingType type,
AuList<AuUInt8> &out) = 0;
virtual bool Sign(const AuList<AuUInt8> &in,
EHashType method, EPaddingType type,
AuList<AuUInt8> &out) = 0;
virtual bool Decrypt(const void *buffer, AuUInt length, EPaddingType type, AuList<AuUInt8> &out) = 0;
virtual bool Decrypt(const AuList<AuUInt8> &in, EPaddingType type, AuList<AuUInt8> &out) = 0;
virtual AuSPtr<IRSAPublic> ToPublic() = 0;
virtual bool ToKey(const RSAMeta &meta, AuList<AuUInt8> &out) = 0;
};
}

View File

@ -0,0 +1,29 @@
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: IRSAPublic.hpp
Date: 2021-7-1
Author: Reece
***/
#pragma once
namespace Aurora::Crypto::RSA
{
// Rememeber: there is no such thing as public decryption
class IRSAPublic
{
public:
virtual bool Verify(const void *buffer, AuUInt length,
const void *sigBuffer, AuUInt sigLength,
EHashType method,
EPaddingType type) = 0;
virtual bool Verify(const AuList<AuUInt8> &buffer, const AuList<AuUInt8> &sig,
EHashType method, EPaddingType type) = 0;
virtual bool Encrypt(const void *buffer, AuUInt length, EPaddingType type, AuList<AuUInt8> &out) = 0;
virtual bool Encrypt(const AuList<AuUInt8> &in, EPaddingType type, AuList<AuUInt8> &out) = 0;
virtual bool ToKey(ERSAKeyType type, AuList<AuUInt8> &out) = 0;
};
}

View File

@ -7,7 +7,15 @@
***/
#pragma once
#include "ERSAKeyType.hpp"
#include "RSAMeta.hpp"
#include "RSAKey.hpp"
#include "IRSAPublic.hpp"
#include "IRSAPrivate.hpp"
namespace Aurora::Crypto::RSA
{
AUKN_SHARED_API(OpenRSAPublic, IRSAPublic, const RSAKey &key);
AUKN_SHARED_API(OpenRSAPrivate, IRSAPrivate, const RSAKey &key);
AUKN_SHARED_API(NewRSAKey, IRSAPrivate, AuUInt16 keySize);
}

View File

@ -0,0 +1,17 @@
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: RSAKey.hpp
Date: 2021-7-1
Author: Reece
***/
#pragma once
namespace Aurora::Crypto::RSA
{
struct RSAKey
{
RSAMeta meta;
DerBuffer blob;
};
}

View File

@ -0,0 +1,17 @@
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: RSAMeta.hpp
Date: 2021-7-1
Author: Reece
***/
#pragma once
namespace Aurora::Crypto::RSA
{
struct RSAMeta
{
ERSAKeyType type;
EKeyType side;
};
}

View File

@ -16,7 +16,7 @@ namespace Aurora::Async
InitSched();
}
void ShutdownSync()
void ShutdownAsync()
{
ShutdownSched();
}

View File

@ -43,5 +43,5 @@ namespace Aurora::Async
};
void InitAsync();
void ShutdownSync();
void ShutdownAsync();
}

View File

@ -1,7 +0,0 @@
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: EccX25519Private.hpp
Date: 2021-6-12
Author: Reece
***/

View File

@ -1,7 +0,0 @@
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: EccX25519Public.cpp
Date: 2021-6-12
Author: Reece
***/

View File

@ -1,7 +0,0 @@
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: EccX25519Public.hpp
Date: 2021-6-12
Author: Reece
***/

View File

@ -1,7 +0,0 @@
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: EccNISTPrivate.cpp
Date: 2021-6-12
Author: Reece
***/

View File

@ -1,7 +0,0 @@
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: EccNISTPrivate.hpp
Date: 2021-6-12
Author: Reece
***/

View File

@ -1,7 +0,0 @@
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: EccNISTPublic.cpp
Date: 2021-6-12
Author: Reece
***/

View File

@ -1,7 +0,0 @@
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: EccNISTPublic.hpp
Date: 2021-6-12
Author: Reece
***/

124
Source/Crypto/RSA/RSA.hpp Normal file
View File

@ -0,0 +1,124 @@
/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: RSA.hpp
Date: 2021-7-1
Author: Reece
***/
#pragma once
#include <tomcrypt.h>
#include <Crypto.hpp>
#include <Extensions/LTC/LTCExtensions.hpp>
namespace Aurora::Crypto::RSA
{
static bool ExportRSAKey(const rsa_key &key, EKeyType side, ERSAKeyType type, AuList<AuUInt8> &out)
{
int flags = 0;
if (type == ERSAKeyType::eRsaKey)
{
flags |= kRsaFlagPKCS1;
}
if (side == EKeyType::eKeyPublic)
{
flags |= kRsaFlagPublic;
}
if (!TryResize(out, 4096))
{
return false;
}
unsigned long actualSize = out.size();
auto ret = rsa_pkcs8_export(out.data(), &actualSize, &key, flags);
if (ret != CRYPT_OK)
{
SysPushErrorCrypt("{}", ret);
return false;
}
out.resize(actualSize);
return true;
}
static bool ImportRSAKey(rsa_key &in, const RSAKey &rsakey)
{
int flags{};
if (rsakey.meta.type == ERSAKeyType::eCert)
{
if (rsakey.meta.side == EKeyType::eKeyPrivate)
{
SysPushErrorArg("Attempted to import a certificate as a private key.");
return false;
}
auto ret = rsa_import_x509(rsakey.blob.data(), rsakey.blob.size(), &in);
if (ret != CRYPT_OK)
{
SysPushErrorCrypt("{}", ret);
return false;
}
return true;
}
if (rsakey.meta.type == ERSAKeyType::eRsaKey)
{
flags |= kRsaFlagPKCS1;
}
if (rsakey.meta.side == EKeyType::eKeyPublic)
{
flags |= kRsaFlagPublic;
}
auto ret = rsa_import_ex(rsakey.blob.data(), rsakey.blob.size(), &in, flags);
if (ret != CRYPT_OK)
{
SysPushErrorCrypt("{}", ret);
return false;
}
return true;
}
static int PaddingToType(EPaddingType type)
{
switch (type)
{
case EPaddingType::ePaddingNone:
return 0;
case EPaddingType::ePKCS_1_5:
return LTC_PKCS_1_V1_5;
case EPaddingType::ePKCS_1_5_NA1:
return LTC_PKCS_1_V1_5_NA1;
case EPaddingType::ePKCS_OAEP:
return LTC_PKCS_1_OAEP;
case EPaddingType::ePKCS_1_PSS:
return LTC_PKCS_1_PSS;
default:
return 0xFF;
}
}
static int HashMethodToId(EHashType type)
{
switch (type)
{
case EHashType::eTiger_24_192:
return ::Crypto::gHashTiger;
case EHashType::eSHA1_20_160:
return ::Crypto::gHashSha1;
case EHashType::eSHA2_32_256:
return ::Crypto::gHashSha256;
case EHashType::eSHA2_64_512:
return ::Crypto::gHashSha512;
default:
return 0xFF;
}
}
}

View File

@ -7,4 +7,205 @@
***/
#include <RuntimeInternal.hpp>
#include "../Crypto.hpp"
#include "RSA.hpp"
#include "RSAPrivate.hpp"
#include "RSAPublic.hpp"
namespace Aurora::Crypto::RSA
{
PrivateRSA::PrivateRSA(rsa_key &key) : key_(key)
{
}
PrivateRSA::~PrivateRSA()
{
rsa_free(&key_);
}
bool PrivateRSA::Sign(const void *buffer, AuUInt length,
EHashType method, EPaddingType type,
AuList<AuUInt8> &out)
{
prng_state yarrow_prng;
const int salt = 0;
int padding = PaddingToType(type);
if (padding == 0xFF)
{
SysPushErrorCrypt("invalid pad {}", type);
return false;
}
int hash = HashMethodToId(method);
if (hash == 0xFF)
{
SysPushErrorCrypt("invalid hash {}", method);
return false;
}
if (!TryResize(out, 1024))
{
SysPushErrorMem();
return false;
}
AuList<AuUInt8> hashVec;
if (!TryResize(hashVec, 128))
{
SysPushErrorMem();
return false;
}
unsigned long hashSize = hashVec.size();
auto ret = hash_memory(hash,
reinterpret_cast<const unsigned char *>(buffer), length,
reinterpret_cast<unsigned char *>(hashVec.data()), &hashSize);
if (ret != CRYPT_OK)
{
SysPushErrorCrypt("{}", ret);
return false;
}
unsigned long len = out.size();
ret = rsa_sign_hash_ex(reinterpret_cast<const unsigned char *>(hashVec.data()), hashSize,
out.data(), &len,
padding,
&yarrow_prng,
::Crypto::gPrngYarrow,
hash,
salt,
&key_);
if (ret != CRYPT_OK)
{
SysPushErrorCrypt("{}", ret);
return false;
}
out.resize(len);
return true;
}
bool PrivateRSA::Sign(const AuList<AuUInt8> &in,
EHashType method, EPaddingType type,
AuList<AuUInt8> &out)
{
return Sign(in.data(), in.size(), method, type, out);
}
bool PrivateRSA::Decrypt(const void *buffer, AuUInt length, EPaddingType type, AuList<AuUInt8> &out)
{
int padding = PaddingToType(type);
if (padding == 0xFF)
{
SysPushErrorCrypt("invalid pad {}", type);
return false;
}
const int prng_idx = padding == LTC_PKCS_1_PSS ? ::Crypto::gPrngYarrow : 0;
if (prng_idx < 0)
{
SysPushErrorCrypt("{}", prng_idx);
return false;
}
if (!TryResize(out, length))
{
SysPushErrorMem();
return false;
}
unsigned long len = out.size();
int stat = 0;
auto ret = rsa_decrypt_key_ex(reinterpret_cast<const unsigned char *>(buffer), length,
out.data(), &len,
NULL, 0,
0, // hash? excuse me?
padding,
&stat,
&key_);
if (ret != CRYPT_OK)
{
SysPushErrorCrypt("{}", ret);
return false;
}
out.resize(len);
return stat == 1;
}
bool PrivateRSA::Decrypt(const AuList<AuUInt8> &in, EPaddingType type, AuList<AuUInt8> &out)
{
return Decrypt(in.data(), in.size(), type, out);
}
AuSPtr<IRSAPublic> PrivateRSA::ToPublic()
{
return std::make_shared<PublicRSA>(key_);
}
bool PrivateRSA::ToKey(const RSAMeta &meta, AuList<AuUInt8> &out)
{
return ExportRSAKey(key_, meta.side, meta.type, out);
}
AUKN_SYM IRSAPrivate *OpenRSAPrivateNew(const RSAKey &key)
{
rsa_key in {};
if (key.meta.side == EKeyType::eKeyPublic)
{
SysPushErrorArg("Attempted to import a public key as a private key.");
return false;
}
if (!ImportRSAKey(in, key))
{
return nullptr;
}
auto ret = _new PrivateRSA(in);
if (!ret)
{
rsa_free(&in);
return nullptr;
}
return ret;
}
AUKN_SYM void OpenRSAPrivateRelease(IRSAPrivate *re)
{
SafeDelete<PrivateRSA *>(re);
}
AUKN_SYM IRSAPrivate *NewRSAKeyNew(AuUInt16 keySize)
{
prng_state yarrow_prng {};
rsa_key key {};
const int prng_idx = register_prng(&sprng_desc);
auto error = rsa_make_key(NULL, prng_idx, keySize / 8, 65537, &key);
if (error != CRYPT_OK)
{
SysPushErrorCrypt("{}", error);
return nullptr;
}
auto ret = _new PrivateRSA(key);
if (!ret)
{
rsa_free(&key);
return nullptr;
}
return ret;
}
AUKN_SYM void NewRSAKeyRelease(IRSAPrivate *re)
{
return OpenRSAPrivateRelease(re);
}
}

View File

@ -6,3 +6,33 @@
Author: Reece
***/
#pragma once
namespace Aurora::Crypto::RSA
{
class PrivateRSA : public IRSAPrivate
{
public:
PrivateRSA(rsa_key &key);
~PrivateRSA();
bool Sign(const void *buffer, AuUInt length,
EHashType method, EPaddingType type,
AuList<AuUInt8> &out) override;
bool Sign(const AuList<AuUInt8> &in,
EHashType method, EPaddingType type,
AuList<AuUInt8> &out) override;
bool Decrypt(const void *buffer, AuUInt length, EPaddingType type, AuList<AuUInt8> &out) override;
bool Decrypt(const AuList<AuUInt8> &in, EPaddingType type, AuList<AuUInt8> &out) override;
AuSPtr<IRSAPublic> ToPublic() override;
bool ToKey(const RSAMeta &meta, AuList<AuUInt8> &out) override;
private:
rsa_key key_;
};
}

View File

@ -7,4 +7,151 @@
***/
#include <RuntimeInternal.hpp>
#include "../Crypto.hpp"
#include "RSA.hpp"
#include "RSAPublic.hpp"
namespace Aurora::Crypto::RSA
{
PublicRSA::PublicRSA(rsa_key &key) : key_(key)
{
}
PublicRSA::~PublicRSA()
{
}
bool PublicRSA::Verify(const void *buffer, AuUInt length,
const void *sigBuffer, AuUInt sigLength,
EHashType method,
EPaddingType type)
{
int padding = PaddingToType(type);
if (padding == 0xFF)
{
SysPushErrorCrypt("invalid pad {}", type);
return false;
}
int hash = HashMethodToId(method);
if (hash == 0xFF)
{
SysPushErrorCrypt("invalid hash {}", method);
return false;
}
AuList<AuUInt8> hashVec;
if (!TryResize(hashVec, 128))
{
SysPushErrorMem();
return false;
}
unsigned long hashSize = hashVec.size();
auto ret = hash_memory(hash,
reinterpret_cast<const unsigned char *>(buffer), length,
reinterpret_cast<unsigned char *>(hashVec.data()), &hashSize);
if (ret != CRYPT_OK)
{
SysPushErrorCrypt("{}", ret);
return false;
}
int ok = 0;
ret = rsa_verify_hash_ex(reinterpret_cast<const unsigned char *>(sigBuffer), sigLength,
reinterpret_cast<const unsigned char *>(hashVec.data()), hashSize,
padding, hash, 0, &ok, &key_);
if (ret != CRYPT_OK)
{
SysPushErrorCrypt("{}", ret);
return false;
}
return ok == 1;
}
bool PublicRSA::Verify(const AuList<AuUInt8> &buffer, const AuList<AuUInt8> &sig,
EHashType method, EPaddingType type)
{
return Verify(buffer.data(), buffer.size(), sig.data(), sig.size(), method, type);
}
bool PublicRSA::Encrypt(const void *buffer, AuUInt length, EPaddingType type, AuList<AuUInt8> &out)
{
prng_state yarrow_prng;
int padding = PaddingToType(type);
if (padding == 0xFF)
{
SysPushErrorCrypt("invalid pad {}", type);
return false;
}
const int prng_idx = padding == LTC_PKCS_1_PSS ? ::Crypto::gPrngYarrow : 0;
if (prng_idx < 0)
{
SysPushErrorCrypt("{}", prng_idx);
return false;
}
if (!TryResize(out, length + 1024))
{
SysPushErrorMem();
return false;
}
unsigned long len = out.size();
auto ret = rsa_encrypt_key_ex(reinterpret_cast<const unsigned char *>(buffer), length,
out.data(), &len,
NULL, 0,
&yarrow_prng, prng_idx,
0,
padding,
&key_);
if (ret != CRYPT_OK)
{
SysPushErrorCrypt("{}", ret);
return false;
}
out.resize(len);
return true;
}
bool PublicRSA::Encrypt(const AuList<AuUInt8> &in, EPaddingType type, AuList<AuUInt8> &out)
{
return Encrypt(in.data(), in.size(), type, out);
}
bool PublicRSA::ToKey(ERSAKeyType type, AuList<AuUInt8> &out)
{
return ExportRSAKey(key_, EKeyType::eKeyPublic, type, out);
}
AUKN_SYM IRSAPublic *OpenRSAPublicNew(const RSAKey &key)
{
rsa_key in {};
if (!ImportRSAKey(in, key))
{
return nullptr;
}
auto ret = _new PublicRSA(in);
if (!ret)
{
rsa_free(&in);
return nullptr;
}
return ret;
}
AUKN_SYM void OpenRSAPublicRelease(IRSAPublic *re)
{
SafeDelete<PublicRSA *>(re);
}
}

View File

@ -7,3 +7,29 @@
***/
#pragma once
namespace Aurora::Crypto::RSA
{
class PublicRSA : public IRSAPublic
{
public:
PublicRSA(rsa_key &key);
~PublicRSA();
bool Verify(const void *buffer, AuUInt length,
const void *sigBuffer, AuUInt sigLength,
EHashType method,
EPaddingType type) override;
bool Verify(const AuList<AuUInt8> &buffer, const AuList<AuUInt8> &sig,
EHashType method, EPaddingType type) override;
bool Encrypt(const void *buffer, AuUInt length, EPaddingType type, AuList<AuUInt8> &out) override;
bool Encrypt(const AuList<AuUInt8> &in, EPaddingType type, AuList<AuUInt8> &out) override;
bool ToKey(ERSAKeyType type, AuList<AuUInt8> &out) override;
private:
rsa_key key_;
};
}

View File

@ -18,7 +18,6 @@
#include "Debug/Debug.hpp"
#include "Async/Async.hpp"
static void Init()
{
Crypto::InitCrypto();
@ -42,7 +41,7 @@ static void Deinit()
{
Aurora::RNG::Release();
Aurora::Console::Exit();
Aurora::Async::ShutdownSync();
Aurora::Async::ShutdownAsync();
}
namespace Aurora