From 60d2c59d6ee4c2d721049a0a913d5dbc6b89cc11 Mon Sep 17 00:00:00 2001 From: Reece Date: Tue, 21 Sep 2021 02:54:47 +0100 Subject: [PATCH] [+] More crypto copypasta --- Include/Aurora/Crypto/ECC/ECC.hpp | 8 +- Include/Aurora/Crypto/ECC/IECCPrivate.hpp | 2 +- Include/Aurora/Crypto/RSA/IRSAPrivate.hpp | 4 +- Include/Aurora/Crypto/RSA/IRSAPublic.hpp | 6 +- Source/Compression/BlockDecompressor.cpp | 1 - Source/Crypto/ECC/ECC.cpp | 97 ++++++ Source/Crypto/ECC/ECCCurves.cpp | 57 +++ Source/Crypto/ECC/ECCCurves.hpp | 3 + Source/Crypto/ECC/ECCGeneric.cpp | 406 ++++++---------------- Source/Crypto/ECC/ECCGeneric.hpp | 81 +++++ Source/Crypto/ECC/PrivateECCImpl.cpp | 163 +++++++++ Source/Crypto/ECC/PrivateECCImpl.hpp | 31 ++ Source/Crypto/ECC/PublicECCImpl.cpp | 117 +++++++ Source/Crypto/ECC/PublicECCImpl.hpp | 31 ++ 14 files changed, 693 insertions(+), 314 deletions(-) create mode 100644 Source/Crypto/ECC/PrivateECCImpl.cpp create mode 100644 Source/Crypto/ECC/PrivateECCImpl.hpp create mode 100644 Source/Crypto/ECC/PublicECCImpl.cpp create mode 100644 Source/Crypto/ECC/PublicECCImpl.hpp diff --git a/Include/Aurora/Crypto/ECC/ECC.hpp b/Include/Aurora/Crypto/ECC/ECC.hpp index 7afa76c1..854d937e 100644 --- a/Include/Aurora/Crypto/ECC/ECC.hpp +++ b/Include/Aurora/Crypto/ECC/ECC.hpp @@ -7,14 +7,14 @@ ***/ #pragma once +#include "EECCCurve.hpp" #include "IECCPublic.hpp" #include "IECCPrivate.hpp" -#include "EECCCurve.hpp" namespace Aurora::Crypto::ECC { AUKN_SHARED_API(NewECC, IECCPrivate, EECCCurve curve); - AUKN_SHARED_API(OpenPrivateECC, IECCPrivate, EECCCurve curve, const Memory::MemoryViewRead &pk); - AUKN_SHARED_API(OpenPublicECC, IECCPublic, EECCCurve curve, const Memory::MemoryViewRead &pk); - AUKN_SHARED_API(OpenPublicECCFromCert, IECCPublic, EECCCurve curve, const Memory::MemoryViewRead &certificate); + AUKN_SHARED_API(OpenPrivateECC, IECCPrivate, const Memory::MemoryViewRead &pk); + AUKN_SHARED_API(OpenPublicECC, IECCPublic, const Memory::MemoryViewRead &pk); + AUKN_SHARED_API(OpenPublicECCFromCert, IECCPublic, const Memory::MemoryViewRead &certificate); } \ No newline at end of file diff --git a/Include/Aurora/Crypto/ECC/IECCPrivate.hpp b/Include/Aurora/Crypto/ECC/IECCPrivate.hpp index 60da8f35..90310b18 100644 --- a/Include/Aurora/Crypto/ECC/IECCPrivate.hpp +++ b/Include/Aurora/Crypto/ECC/IECCPrivate.hpp @@ -25,6 +25,6 @@ namespace Aurora::Crypto::ECC virtual bool AsPublicECC(AuList &out) = 0; virtual bool AsPrivateECC(AuList &out) = 0; - virtual EECCCurve GetType() override; + virtual EECCCurve GetType() = 0; }; } \ No newline at end of file diff --git a/Include/Aurora/Crypto/RSA/IRSAPrivate.hpp b/Include/Aurora/Crypto/RSA/IRSAPrivate.hpp index 784071ed..f2362077 100644 --- a/Include/Aurora/Crypto/RSA/IRSAPrivate.hpp +++ b/Include/Aurora/Crypto/RSA/IRSAPrivate.hpp @@ -13,12 +13,12 @@ namespace Aurora::Crypto::RSA class IRSAPrivate { public: - virtual bool Sign(const Memory::MemoryViewRead & payload, + virtual bool Sign(const Memory::MemoryViewRead &payload, EHashType method, EPaddingType type, AuList &out) = 0; - virtual bool Decrypt(const Memory::MemoryViewRead & payload, + virtual bool Decrypt(const Memory::MemoryViewRead &payload, EPaddingType type, AuList &out) = 0; diff --git a/Include/Aurora/Crypto/RSA/IRSAPublic.hpp b/Include/Aurora/Crypto/RSA/IRSAPublic.hpp index c92105d0..61514c44 100644 --- a/Include/Aurora/Crypto/RSA/IRSAPublic.hpp +++ b/Include/Aurora/Crypto/RSA/IRSAPublic.hpp @@ -13,12 +13,12 @@ namespace Aurora::Crypto::RSA class IRSAPublic { public: - virtual bool Verify(const Memory::MemoryViewRead & payload, - const Memory::MemoryViewRead & signature, + virtual bool Verify(const Memory::MemoryViewRead &plainText, + const Memory::MemoryViewRead &signature, EHashType method, EPaddingType type) = 0; - virtual bool Encrypt(const Memory::MemoryViewRead & plainText, + virtual bool Encrypt(const Memory::MemoryViewRead &plainText, EPaddingType type, AuList &out) = 0; diff --git a/Source/Compression/BlockDecompressor.cpp b/Source/Compression/BlockDecompressor.cpp index d01f0a7d..8a30b2d6 100644 --- a/Source/Compression/BlockDecompressor.cpp +++ b/Source/Compression/BlockDecompressor.cpp @@ -389,7 +389,6 @@ namespace Aurora::Compression AuStreamReadWrittenPair_t Ingest(AuUInt32 input) override { bool ret = true; - LZ4F_dctx *dctxPtr; AuUInt32 inputStat = 0, outputStat = 0; size_t bytesRemInFrame {}; LZ4F_decompressOptions_t opts {}; diff --git a/Source/Crypto/ECC/ECC.cpp b/Source/Crypto/ECC/ECC.cpp index 21bdd5ac..5a82a6ca 100644 --- a/Source/Crypto/ECC/ECC.cpp +++ b/Source/Crypto/ECC/ECC.cpp @@ -7,8 +7,105 @@ ***/ #include #include "ECC.hpp" +#include "ECCGeneric.hpp" +#include "ECCCurves.hpp" +#include "PublicECCImpl.hpp" +#include "PrivateECCImpl.hpp" + namespace Aurora::Crypto::ECC { + + static void ReleasePublicECC(IECCPublic *pub) + { + switch (pub->GetType()) + { + case EECCCurve::eCurveEd25519: + case EECCCurve::eCurveX25519: + return; + default: + SafeDelete(pub); + return; + } + } + + static void ReleasePrivateECC(IECCPrivate *priv) + { + switch (priv->GetType()) + { + case EECCCurve::eCurveEd25519: + case EECCCurve::eCurveX25519: + return; + default: + SafeDelete(priv); + return; + } + } + + AUKN_SYM IECCPrivate *NewECC(EECCCurve curve) + { + switch (curve) + { + case EECCCurve::eCurveEd25519: + case EECCCurve::eCurveX25519: + // TODO: Curve25519 is special + return {}; + default: + return GenerateNewGenericECC(curve).value_or(nullptr); + } + } + + AUKN_SYM IECCPrivate *OpenPrivateECC(const Memory::MemoryViewRead &pk) + { + if (auto ret = NewStdECC({}/*no curve assertion*/, pk, false)) + { + return ret; + } + + // TODO: Curve25519 is special + return {}; + } + + AUKN_SYM IECCPublic *OpenPublicECC(const Memory::MemoryViewRead &pk) + { + if (auto ret = NewStdECC({}/*no curve assertion*/, pk, false)) + { + return ret; + } + + // TODO: Curve25519 is special + return {}; + } + + AUKN_SYM IECCPublic *OpenPublicECCFromCert(const Memory::MemoryViewRead &certificate) + { + if (auto ret = NewStdECC({}/*no curve assertion*/, certificate, true)) + { + return ret; + } + + // TODO: Curve25519 is special + return {}; + } + + AUKN_SYM void NewECCRelease(IECCPrivate *priv) + { + ReleasePrivateECC(priv); + } + + AUKN_SYM void OpenPrivateECCRelease(IECCPrivate *priv) + { + ReleasePrivateECC(priv); + } + + AUKN_SYM void OpenPublicECCRelease(IECCPublic *pub) + { + ReleasePublicECC(pub); + } + + AUKN_SYM void OpenPublicECCFromCertRelease(IECCPublic *pub) + { + ReleasePublicECC(pub); + } } \ No newline at end of file diff --git a/Source/Crypto/ECC/ECCCurves.cpp b/Source/Crypto/ECC/ECCCurves.cpp index 59ee49cf..e33782d1 100644 --- a/Source/Crypto/ECC/ECCCurves.cpp +++ b/Source/Crypto/ECC/ECCCurves.cpp @@ -8,6 +8,7 @@ #include #include "ECC.hpp" #include "ECCCurves.hpp" +#include "ECCGeneric.hpp" #include namespace Aurora::Crypto::ECC @@ -47,9 +48,65 @@ namespace Aurora::Crypto::ECC /* cofactor */ 1, /* OID */ "1.3.132.0.35" }; + + static const EECCCurve kEccTypes[] = {EECCCurve::eCurve256, EECCCurve::eCurve384, EECCCurve::eCurve521}; + static const ltc_ecc_curve *kEccCurves[] = {&kNistp256, &kNistp384, &kNistp521}; + + AuOptional OIDToCurve(unsigned long *oid, unsigned long oidlen) + { + char tempAgain[256]; + unsigned long size = AuArraySize(tempAgain); + + if (pk_oid_num_to_str(oid, oidlen, tempAgain, &size) != CRYPT_OK) + { + return {}; + } + + // TODO: EVIL + auto evil = AuString(tempAgain, tempAgain + size); + + for (AU_ITERATE_ARRAY(i, kEccCurves)) + { + if (kEccCurves[i]->OID == evil) + { + return kEccTypes[i]; + } + } + + return {}; + } + + AuOptional GetECCCurve(unsigned long *oid, unsigned long oidlen) + { + char tempAgain[256]; + unsigned long size = AuArraySize(tempAgain); + + if (pk_oid_num_to_str(oid, oidlen, tempAgain, &size) != CRYPT_OK) + { + return {}; + } + + // TODO: EVIL + return GetECCCurve(AuString(tempAgain, tempAgain + size)); + } + + AuOptional GetECCCurve(const AuString &oid) + { + + for (AU_ITERATE_ARRAY(i, kEccCurves)) + { + if (kEccCurves[i]->OID == oid) + { + return kEccCurves[i]; + } + } + + return {}; + } AuOptional GetECCCurve(EECCCurve curve) { + // TODO: consider using ecc_find_curve, it's basically the same thing with strings switch (curve) { case EECCCurve::eCurve256: diff --git a/Source/Crypto/ECC/ECCCurves.hpp b/Source/Crypto/ECC/ECCCurves.hpp index 33774de3..2f6b4c2e 100644 --- a/Source/Crypto/ECC/ECCCurves.hpp +++ b/Source/Crypto/ECC/ECCCurves.hpp @@ -9,5 +9,8 @@ namespace Aurora::Crypto::ECC { + AuOptional GetECCCurve(unsigned long *oid, unsigned long oidlen); + AuOptional OIDToCurve(unsigned long *oid, unsigned long oidlen); + AuOptional GetECCCurve(const AuString &oid); AuOptional GetECCCurve(EECCCurve curve); } \ No newline at end of file diff --git a/Source/Crypto/ECC/ECCGeneric.cpp b/Source/Crypto/ECC/ECCGeneric.cpp index 4280f50c..45bff5ab 100644 --- a/Source/Crypto/ECC/ECCGeneric.cpp +++ b/Source/Crypto/ECC/ECCGeneric.cpp @@ -9,10 +9,99 @@ #include "ECC.hpp" #include "ECCGeneric.hpp" #include "ECCCurves.hpp" +#include "PrivateECCImpl.hpp" namespace Aurora::Crypto::ECC { - static bool ExportECCKey(const ecc_key &key, bool pub, DerBuffer &out) + int pk_oid_str_to_num(const char *OID, unsigned long *oid, unsigned long *oidlen) + { + unsigned long i, j, limit, oid_j; + size_t OID_len; + + LTC_ARGCHK(oidlen != NULL); + + limit = *oidlen; + *oidlen = 0; /* make sure that we return zero oidlen on error */ + for (i = 0; i < limit; i++) oid[i] = 0; + + if (OID == NULL) return CRYPT_OK; + + OID_len = XSTRLEN(OID); + if (OID_len == 0) return CRYPT_OK; + + for (i = 0, j = 0; i < OID_len; i++) + { + if (OID[i] == '.') + { + if (++j >= limit) continue; + } + else if ((OID[i] >= '0') && (OID[i] <= '9')) + { + if ((j >= limit) || (oid == NULL)) continue; + oid_j = oid[j]; + oid[j] = oid[j] * 10 + (OID[i] - '0'); + if (oid[j] < oid_j) return CRYPT_OVERFLOW; + } + else + { + return CRYPT_ERROR; + } + } + if (j == 0) return CRYPT_ERROR; + if (j >= limit) + { + *oidlen = j; + return CRYPT_BUFFER_OVERFLOW; + } + *oidlen = j + 1; + return CRYPT_OK; + } + + int pk_oid_num_to_str(const unsigned long *oid, unsigned long oidlen, char *OID, unsigned long *outlen) + { + int i; + unsigned long j, k; + char tmp[256] = {0}; + + LTC_ARGCHK(oid != NULL); + LTC_ARGCHK(OID != NULL); + LTC_ARGCHK(outlen != NULL); + + for (i = oidlen - 1, k = 0; i >= 0; i--) + { + j = oid[i]; + if (j == 0) + { + tmp[k] = '0'; + if (++k >= sizeof(tmp)) return CRYPT_ERROR; + } + else + { + while (j > 0) + { + tmp[k] = '0' + (j % 10); + if (++k >= sizeof(tmp)) return CRYPT_ERROR; + j /= 10; + } + } + if (i > 0) + { + tmp[k] = '.'; + if (++k >= sizeof(tmp)) return CRYPT_ERROR; + } + } + if (*outlen < k + 1) + { + *outlen = k + 1; + return CRYPT_BUFFER_OVERFLOW; + } + for (j = 0; j < k; j++) OID[j] = tmp[k - j - 1]; + OID[k] = '\0'; + *outlen = k; /* the length without terminating NUL byte */ + return CRYPT_OK; + } + + bool ExportECCKey(const ecc_key &key, bool pub, DerBuffer &out) { if (!AuTryResize(out, 4096)) { @@ -37,322 +126,33 @@ namespace Aurora::Crypto::ECC return true; } - class PublicECCImpl : public IECCPublic + std::optional GenerateNewGenericECC(EECCCurve curve) { - public: - PublicECCImpl(EECCCurve type, ecc_key &key); - ~PublicECCImpl(); + ecc_key key = {}; + const int prng_idx = register_prng(&sprng_desc); - bool Verify(const Memory::MemoryViewRead &hash, - const Memory::MemoryViewRead &signature) override; - - bool Verify(const Memory::MemoryViewRead &plaintext, - const Memory::MemoryViewRead &signature, - EHashType method) override; - - bool AsPublicECC(AuList &out) override; - - bool Export(bool pub, DerBuffer &out); - - - EECCCurve GetType() override; - - const ecc_key &GetKey(); - - private: - ecc_key _key; - EECCCurve _type; - }; - - PublicECCImpl::PublicECCImpl(EECCCurve type, ecc_key &key) : _key(key), _type(_type) - { - - } - - PublicECCImpl::~PublicECCImpl() - { - ecc_free(&_key); - } - - EECCCurve PublicECCImpl::GetType() - { - return _type; - } - - bool PublicECCImpl::Verify(const Memory::MemoryViewRead &hash, - const Memory::MemoryViewRead &signature) - { - int ok = 0; - - if (!hash.HasMemory()) + auto tc = GetECCCurve(curve); + if (!tc) { - SysPushErrorParam(); - return {}; - } - - if (!signature.HasMemory()) - { - SysPushErrorParam(); + SysPushErrorCrypt(); return {}; } - auto ret = ecc_verify_hash_ex(reinterpret_cast(hash.ptr), hash.length, - reinterpret_cast(signature.ptr), signature.length, - LTC_ECCSIG_ETH27, &ok, &_key); - if (ret != CRYPT_OK) + auto error = ecc_make_key_ex(NULL, prng_idx, &key, *tc); + if (error != CRYPT_OK) { - SysPushErrorCrypt("{}", ret); - return false; - } - - return ok == 1; - } - - bool PublicECCImpl::Verify(const Memory::MemoryViewRead &plaintext, - const Memory::MemoryViewRead &signature, - EHashType method) - { - if (!plaintext.HasMemory()) - { - SysPushErrorParam(); - return {}; - } - - if (!signature.HasMemory()) - { - SysPushErrorParam(); + SysPushErrorCrypt("{}", error); return {}; } - int hash = HashMethodToId(method); - if (hash == 0xFF) - { - SysPushErrorCrypt("invalid hash {}", method); - return false; - } - - AuList hashVec; - if (!AuTryResize(hashVec, 128)) + auto ret = _new PrivateECCImpl(curve, key); + if (!ret) { + ecc_free(&key); SysPushErrorMem(); - return false; - } - - unsigned long hashSize = hashVec.size(); - auto ret = hash_memory(hash, - reinterpret_cast(plaintext.ptr), plaintext.length, - reinterpret_cast(hashVec.data()), &hashSize); - if (ret != CRYPT_OK) - { - SysPushErrorCrypt("{}", ret); - return false; - } - - return Verify({hashVec}, signature); - } - - bool PublicECCImpl::AsPublicECC(AuList &out) - { - return Export(true, out); - } - - bool PublicECCImpl::Export(bool pub, DerBuffer &out) - { - return ExportECCKey(_key, pub, out); - } - - const ecc_key &PublicECCImpl::GetKey() - { - return _key; - } - - class PrivateECCImpl : public IECCPrivate - { - public: - PrivateECCImpl(EECCCurve type, ecc_key &key); - ~PrivateECCImpl(); - - bool Sign(const Memory::MemoryViewRead &plainText, - EHashType method, - AuList &out) override; - - bool Sign(const Memory::MemoryViewRead &hash, - AuList &out) override; - - bool ECDH(const AuSPtr &partnerPublic, - AuList &sharedKey) override; - - bool AsPublicECC(AuList &out) override; - - bool AsPrivateECC(AuList &out) override; - - EECCCurve GetType() override; - - private: - ecc_key _key; - EECCCurve _type; - }; - - PrivateECCImpl::PrivateECCImpl(EECCCurve type, ecc_key &key) : _key(key) - { - - } - - PrivateECCImpl::~PrivateECCImpl() - { - ecc_free(&_key); - } - - EECCCurve PrivateECCImpl::GetType() - { - return _type; - } - - bool PrivateECCImpl::Sign(const Memory::MemoryViewRead &plainText, - EHashType method, - AuList &out) - { - prng_state yarrow_prng; - const int salt = 0; - - if (!plainText.HasMemory()) - { - SysPushErrorParam(); - return {}; - } - - 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(plainText.ptr), plainText.length, - reinterpret_cast(hashVec.data()), &hashSize); - if (ret != CRYPT_OK) - { - SysPushErrorCrypt("{}", ret); - return false; - } - - return Sign(hashVec, out); - } - - bool PrivateECCImpl::Sign(const Memory::MemoryViewRead &hash, - AuList &out) - { - prng_state yarrow_prng; - const int salt = 0; - - if (!hash.HasMemory()) - { - SysPushErrorParam(); return {}; } - if (!AuTryResize(out, 1024)) - { - SysPushErrorMem(); - return false; - } - - unsigned long len = out.size(); - auto ret = ecc_sign_hash_ex(reinterpret_cast(hash.ptr), hash.length, - out.data(), &len, - &yarrow_prng, - ::Crypto::gPrngYarrow, - LTC_ECCSIG_ETH27, - nullptr, - &_key); - if (ret != CRYPT_OK) - { - SysPushErrorCrypt("{}", ret); - return false; - } - - if (!AuTryResize(out, len)) - { - SysPushErrorMem(); - return false; - } - - return true; - } - - bool PrivateECCImpl::ECDH(const AuSPtr &partnerPublic, - AuList &sharedKey) - { - AuList sharedSecret; - - if (!AuTryResize(sharedSecret, 128)) - { - SysPushErrorMem(); - return false; - } - - if (partnerPublic->GetType() == this->GetType()) - { - SysPushErrorCrypto("Can not EDCH with incompatible curve curve type (noting, ed25519 requires translation to x25519)"); - return false; - } - - unsigned long actualSize = sharedSecret.size(); - auto ret = ecc_shared_secret(&_key, &(std::reinterpret_pointer_cast(partnerPublic)->GetKey()), sharedSecret.data(), &actualSize); - if (ret != CRYPT_OK) - { - SysPushErrorCrypt("{}", ret); - return false; - } - - sharedSecret.resize(actualSize); - - return true; - } - - bool PrivateECCImpl::AsPublicECC(AuList &out) - { - return ExportECCKey(_key, true, out); - } - - bool PrivateECCImpl::AsPrivateECC(AuList &out) - { - return ExportECCKey(_key, false, out); - } - - template - static Type_t *NewECC(EECCCurve curve, const AuList &pub) - { - ecc_key in {}; - auto ret = ecc_import_openssl(pub.data(), pub.size(), &in); - if (ret != CRYPT_OK) - { - SysPushErrorCrypto("{}", ret); - return nullptr; - } - - auto out = _new Type_t(curve, in); - if (!out) - { - ecc_free(&in); - } - - return out; + return ret; } } \ No newline at end of file diff --git a/Source/Crypto/ECC/ECCGeneric.hpp b/Source/Crypto/ECC/ECCGeneric.hpp index 69c5cb7b..5a6daf47 100644 --- a/Source/Crypto/ECC/ECCGeneric.hpp +++ b/Source/Crypto/ECC/ECCGeneric.hpp @@ -7,7 +7,88 @@ ***/ #pragma once +#include "ECCCurves.hpp" + namespace Aurora::Crypto::ECC { + template + Type_t *NewECC(EECCCurve curve, const AuList &pub); + bool ExportECCKey(const ecc_key &key, bool pub, DerBuffer &out); + + int pk_oid_str_to_num(const char *OID, unsigned long *oid, unsigned long *oidlen); + int pk_oid_num_to_str(const unsigned long *oid, unsigned long oidlen, char *OID, unsigned long *outlen); + + template + static Type_t *NewStdECC(AuOptional curve, const Memory::MemoryViewRead &pk, bool cert = false) + { + ecc_key in {}; + AuOptional ref; + + if (curve) + { + ref = GetECCCurve(curve.value()); + if (!ref) + { + SysPushErrorParam("This curve isn't supported here"); + // wrong function, bucko + return nullptr; + } + } + + if (cert) + { + auto ret = ecc_import_x509(pk.Begin(), pk.length, &in); + if (ret != CRYPT_OK) + { + SysPushErrorCrypto("{}", ret); + return nullptr; + } + } + else + { + auto ret = ecc_import_openssl(pk.Begin(), pk.length, &in); + if (ret != CRYPT_OK) + { + SysPushErrorCrypto("{}", ret); + return nullptr; + } + } + + if (ref) + { + unsigned long oid[16] {}; + unsigned long oidLength = AuArraySize(oid); + + pk_oid_str_to_num(ref.value()->OID, oid, &oidLength); + + if (oidLength != in.dp.oidlen || + std::memcmp(in.dp.oid, oid, in.dp.oidlen * sizeof(unsigned long))) + { + SysPushErrorParam("Improper curve type, expected {}, got {}, for ECCCurveType: {}", ref.value()->OID, AuList(in.dp.oid, in.dp.oid + in.dp.oidlen), curve.value()); + ecc_free(&in); + return nullptr; + } + } + else + { + curve = OIDToCurve(in.dp.oid, in.dp.oidlen); + } + + if (!curve) + { + SysPushErrorCrypt("Couldn't find curve"); + return {}; + } + + Type_t *out = _new Type_t(curve.value(), in); + if (!out) + { + ecc_free(&in); + } + + return out; + } + + std::optional GenerateNewGenericECC(EECCCurve curve); } \ No newline at end of file diff --git a/Source/Crypto/ECC/PrivateECCImpl.cpp b/Source/Crypto/ECC/PrivateECCImpl.cpp new file mode 100644 index 00000000..77278e23 --- /dev/null +++ b/Source/Crypto/ECC/PrivateECCImpl.cpp @@ -0,0 +1,163 @@ +/*** + Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: ECCGeneric.cpp + Date: 2021-9-17 + Author: Reece +***/ +#include +#include "ECC.hpp" +#include "ECCGeneric.hpp" +#include "ECCCurves.hpp" +#include "PrivateECCImpl.hpp" +#include "PublicECCImpl.hpp" + +namespace Aurora::Crypto::ECC +{ + PrivateECCImpl::PrivateECCImpl(EECCCurve type, ecc_key &key) : _key(key) + { + + } + + PrivateECCImpl::~PrivateECCImpl() + { + ecc_free(&_key); + } + + EECCCurve PrivateECCImpl::GetType() + { + return _type; + } + + bool PrivateECCImpl::Sign(const Memory::MemoryViewRead &plainText, + EHashType method, + AuList &out) + { + prng_state yarrow_prng; + const int salt = 0; + + if (!plainText.HasMemory()) + { + SysPushErrorParam(); + return {}; + } + + 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(plainText.ptr), plainText.length, + reinterpret_cast(hashVec.data()), &hashSize); + if (ret != CRYPT_OK) + { + SysPushErrorCrypt("{}", ret); + return false; + } + + return Sign(hashVec, out); + } + + bool PrivateECCImpl::Sign(const Memory::MemoryViewRead &hash, + AuList &out) + { + prng_state yarrow_prng; + const int salt = 0; + + if (!hash.HasMemory()) + { + SysPushErrorParam(); + return {}; + } + + if (!AuTryResize(out, 1024)) + { + SysPushErrorMem(); + return false; + } + + unsigned long len = out.size(); + auto ret = ecc_sign_hash_ex(reinterpret_cast(hash.ptr), hash.length, + out.data(), &len, + &yarrow_prng, + ::Crypto::gPrngYarrow, + LTC_ECCSIG_ETH27, + nullptr, + &_key); + if (ret != CRYPT_OK) + { + SysPushErrorCrypt("{}", ret); + return false; + } + + if (!AuTryResize(out, len)) + { + SysPushErrorMem(); + return false; + } + + return true; + } + + bool PrivateECCImpl::ECDH(const AuSPtr &partnerPublic, + AuList &sharedKey) + { + AuList sharedSecret; + + if (!AuTryResize(sharedSecret, 128)) + { + SysPushErrorMem(); + return false; + } + + if (partnerPublic->GetType() == this->GetType()) + { + SysPushErrorCrypto("Can not EDCH with incompatible curve curve type (noting, ed25519 requires translation to x25519)"); + return false; + } + + unsigned long actualSize = sharedSecret.size(); + auto ret = ecc_shared_secret(&_key, &(std::reinterpret_pointer_cast(partnerPublic)->GetKey()), sharedSecret.data(), &actualSize); + if (ret != CRYPT_OK) + { + SysPushErrorCrypt("{}", ret); + return false; + } + + if (!AuTryResize(sharedSecret, actualSize)) + { + SysPushErrorMem(); + return false; + } + + return true; + } + + bool PrivateECCImpl::AsPublicECC(AuList &out) + { + return ExportECCKey(_key, true, out); + } + + bool PrivateECCImpl::AsPrivateECC(AuList &out) + { + return ExportECCKey(_key, false, out); + } +} \ No newline at end of file diff --git a/Source/Crypto/ECC/PrivateECCImpl.hpp b/Source/Crypto/ECC/PrivateECCImpl.hpp new file mode 100644 index 00000000..2ebb2709 --- /dev/null +++ b/Source/Crypto/ECC/PrivateECCImpl.hpp @@ -0,0 +1,31 @@ +#pragma once + +namespace Aurora::Crypto::ECC +{ + class PrivateECCImpl : public IECCPrivate + { + public: + PrivateECCImpl(EECCCurve type, ecc_key &key); + ~PrivateECCImpl(); + + bool Sign(const Memory::MemoryViewRead &plainText, + EHashType method, + AuList &out) override; + + bool Sign(const Memory::MemoryViewRead &hash, + AuList &out) override; + + bool ECDH(const AuSPtr &partnerPublic, + AuList &sharedKey) override; + + bool AsPublicECC(AuList &out) override; + + bool AsPrivateECC(AuList &out) override; + + EECCCurve GetType() override; + + private: + ecc_key _key; + EECCCurve _type; + }; +} \ No newline at end of file diff --git a/Source/Crypto/ECC/PublicECCImpl.cpp b/Source/Crypto/ECC/PublicECCImpl.cpp new file mode 100644 index 00000000..28a406eb --- /dev/null +++ b/Source/Crypto/ECC/PublicECCImpl.cpp @@ -0,0 +1,117 @@ +/*** + Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. + + File: ECCGeneric.cpp + Date: 2021-9-17 + Author: Reece +***/ +#include +#include "ECC.hpp" +#include "ECCGeneric.hpp" +#include "ECCCurves.hpp" +#include "PublicECCImpl.hpp" + +namespace Aurora::Crypto::ECC +{ + PublicECCImpl::PublicECCImpl(EECCCurve type, ecc_key &key) : _key(key), _type(_type) + { + + } + + PublicECCImpl::~PublicECCImpl() + { + ecc_free(&_key); + } + + EECCCurve PublicECCImpl::GetType() + { + return _type; + } + + bool PublicECCImpl::Verify(const Memory::MemoryViewRead &hash, + const Memory::MemoryViewRead &signature) + { + int ok = 0; + + if (!hash.HasMemory()) + { + SysPushErrorParam(); + return {}; + } + + if (!signature.HasMemory()) + { + SysPushErrorParam(); + return {}; + } + + auto ret = ecc_verify_hash_ex(reinterpret_cast(hash.ptr), hash.length, + reinterpret_cast(signature.ptr), signature.length, + LTC_ECCSIG_ETH27, &ok, &_key); + if (ret != CRYPT_OK) + { + SysPushErrorCrypt("{}", ret); + return false; + } + + return ok == 1; + } + + bool PublicECCImpl::Verify(const Memory::MemoryViewRead &plaintext, + const Memory::MemoryViewRead &signature, + EHashType method) + { + if (!plaintext.HasMemory()) + { + SysPushErrorParam(); + return {}; + } + + if (!signature.HasMemory()) + { + SysPushErrorParam(); + return {}; + } + + int hash = HashMethodToId(method); + if (hash == 0xFF) + { + SysPushErrorCrypt("invalid hash {}", method); + return false; + } + + AuList hashVec; + if (!AuTryResize(hashVec, 128)) + { + SysPushErrorMem(); + return false; + } + + unsigned long hashSize = hashVec.size(); + auto ret = hash_memory(hash, + reinterpret_cast(plaintext.ptr), plaintext.length, + reinterpret_cast(hashVec.data()), &hashSize); + if (ret != CRYPT_OK) + { + SysPushErrorCrypt("{}", ret); + return false; + } + + return Verify({hashVec}, signature); + } + + bool PublicECCImpl::AsPublicECC(AuList &out) + { + return Export(true, out); + } + + bool PublicECCImpl::Export(bool pub, DerBuffer &out) + { + return ExportECCKey(_key, pub, out); + } + + const ecc_key &PublicECCImpl::GetKey() + { + return _key; + } +} \ No newline at end of file diff --git a/Source/Crypto/ECC/PublicECCImpl.hpp b/Source/Crypto/ECC/PublicECCImpl.hpp new file mode 100644 index 00000000..14a8663e --- /dev/null +++ b/Source/Crypto/ECC/PublicECCImpl.hpp @@ -0,0 +1,31 @@ +#pragma once + +namespace Aurora::Crypto::ECC +{ + class PublicECCImpl : public IECCPublic + { + public: + PublicECCImpl(EECCCurve type, ecc_key &key); + ~PublicECCImpl(); + + bool Verify(const Memory::MemoryViewRead &hash, + const Memory::MemoryViewRead &signature) override; + + bool Verify(const Memory::MemoryViewRead &plaintext, + const Memory::MemoryViewRead &signature, + EHashType method) override; + + bool AsPublicECC(AuList &out) override; + + bool Export(bool pub, DerBuffer &out); + + + EECCCurve GetType() override; + + const ecc_key &GetKey(); + + private: + ecc_key _key; + EECCCurve _type; + }; +} \ No newline at end of file