AuroraRuntime/Source/Crypto/RSA/RSAPrivate.cpp

214 lines
5.3 KiB
C++

/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: RSAPrivate.cpp
Date: 2021-6-12
Author: Reece
***/
#include <Source/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 Memory::MemoryViewRead & payload,
EHashType method,
EPaddingType type,
AuList<AuUInt8> &out)
{
prng_state yarrow_prng;
const int salt = 0;
if (!payload.HasMemory())
{
SysPushErrorParam();
return {};
}
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 (!AuTryResize(out, 1024))
{
SysPushErrorMem();
return false;
}
AuList<AuUInt8> hashVec;
if (!AuTryResize(hashVec, 128))
{
SysPushErrorMem();
return false;
}
unsigned long hashSize = hashVec.size();
auto ret = hash_memory(hash,
reinterpret_cast<const unsigned char *>(payload.ptr), payload.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::Decrypt(const Memory::MemoryViewRead &payload,
EPaddingType type,
AuList<AuUInt8> &out)
{
if (!payload.HasMemory())
{
SysPushErrorParam();
return {};
}
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 (!AuTryResize(out, payload.length))
{
SysPushErrorMem();
return false;
}
unsigned long len = out.size();
int stat = 0;
auto ret = rsa_decrypt_key_ex(reinterpret_cast<const unsigned char *>(payload.ptr), payload.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;
}
AuSPtr<IRSAPublic> PrivateRSA::ToPublic()
{
return AuMakeShared<PublicRSA>(key_, false);
}
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 nullptr;
}
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);
}
}