/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: RSAPrivate.cpp Date: 2021-6-12 Author: Reece ***/ #include #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 &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 hashVec; if (!AuTryResize(hashVec, 128)) { SysPushErrorMem(); return false; } unsigned long hashSize = hashVec.size(); auto ret = hash_memory(hash, reinterpret_cast(payload.ptr), payload.length, reinterpret_cast(hashVec.data()), &hashSize); if (ret != CRYPT_OK) { SysPushErrorCrypt("{}", ret); return false; } unsigned long len = out.size(); ret = rsa_sign_hash_ex(reinterpret_cast(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 &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(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 PrivateRSA::ToPublic() { return AuMakeShared(key_, false); } bool PrivateRSA::ToKey(const RSAMeta &meta, AuList &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(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); } }