/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: ECC.cpp Date: 2021-9-17 Author: Reece ***/ #include #include "ECC.hpp" #include "ECCGeneric.hpp" #include "ECCCurves.hpp" #include "PublicECCImpl.hpp" #include "PrivateECCImpl.hpp" #include "ECCX25519Public.hpp" #include "ECCX25519Private.hpp" extern "C" int x509_decode_subject_public_key_info_2(const unsigned char *in, unsigned long inlen, const unsigned long *oid, void *parameters, unsigned long *parameters_len); namespace Aurora::Crypto::ECC { static bool IsKeyGeneric(const void *ptr, AuUInt length, AuArray &curveOidm, unsigned long &oidLen) { const unsigned long oid[16] { 1, 2, 840, 10045, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; return x509_decode_subject_public_key_info_2((const unsigned char *)ptr, length, oid, curveOidm.data(), &oidLen) == CRYPT_OK; } static EECCCurve GetEdECCCurveType(const void *ptr, AuUInt length) { AuArray ec; unsigned long ecLen; if (IsKeyGeneric(ptr, length, ec, ecLen)) { return OIDToCurve(ec.data(), ecLen); } return EECCCurve::kEnumInvalid; } static bool IsBlobCurveX25519(const void *ptr, AuUInt length) { const unsigned long oidX25519[16] { 1, 3, 101, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; return x509_decode_subject_public_key_info_2((const unsigned char *)ptr, length, oidX25519, NULL, 0) == CRYPT_OK; } static bool IsBlobCurveEd25519(const void *ptr, AuUInt length) { const unsigned long oidEd25519[16] { 1, 3, 101, 112, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; return x509_decode_subject_public_key_info_2((const unsigned char *)ptr, length, oidEd25519, NULL, 0) == CRYPT_OK; } template static T New25519ECC(bool isX25519, const Memory::MemoryViewRead &pk, bool cert = false) { curve25519_key in {}; int ret; if (cert) { if (!IsPublic) { SysPushErrorArg(); return nullptr; } ret = isX25519 ? x25519_import_x509(pk.Begin(), pk.length, &in) : ed25519_import_x509(pk.Begin(), pk.length, &in); } else { constexpr auto type = IsPublic ? PK_PUBLIC : PK_PRIVATE; ret = isX25519 ? x25519_import_raw(pk.Begin(), pk.length, type, &in) : ed25519_import_raw(pk.Begin(), pk.length, type, &in); } if (ret != CRYPT_OK) { SysPushErrorCrypto("{}", ret); return nullptr; } if constexpr (IsPublic) { return _new PublicCurve25519Impl(isX25519, AuMove(in)); } else { return _new PrivateCurve25519Impl(isX25519, AuMove(in)); } } static IECCPrivate *Gen25519ECC(bool isX25519) { curve25519_key in {}; int ret; const int prng_idx = register_prng(&sprng_desc); ret = isX25519 ? x25519_make_key(NULL, prng_idx, &in) : ed25519_make_key(NULL, prng_idx, &in); if (ret != CRYPT_OK) { SysPushErrorCrypto("{}", ret); return nullptr; } return _new PrivateCurve25519Impl(isX25519, AuMove(in)); } static void ReleasePublicECC(IECCPublic *pub) { switch (pub->GetType()) { case EECCCurve::eCurveEd25519: case EECCCurve::eCurveX25519: AuSafeDelete(pub); return; default: AuSafeDelete(pub); return; } } static void ReleasePrivateECC(IECCPrivate *priv) { switch (priv->GetType()) { case EECCCurve::eCurveEd25519: case EECCCurve::eCurveX25519: AuSafeDelete(priv); return; default: AuSafeDelete(priv); return; } } AUKN_SYM IECCPrivate *NewECC(EECCCurve curve) { switch (curve) { case EECCCurve::eCurveEd25519: return Gen25519ECC(false); case EECCCurve::eCurveX25519: return Gen25519ECC(true); default: return GenerateNewGenericECC(curve).value_or(nullptr); } } AUKN_SYM IECCPrivate *OpenPrivateECC(const AuMemoryViewRead &pk) { auto type = GetEdECCCurveType(pk.ptr, pk.length); if (type != EECCCurve::eEnumInvalid) { if (auto ret = NewStdECC(type, pk, false)) { return ret; } } if (IsBlobCurveX25519(pk.ptr, pk.length)) { return New25519ECC(true, pk, false); } if (IsBlobCurveEd25519(pk.ptr, pk.length)) { return New25519ECC(false, pk, false); } return {}; } AUKN_SYM IECCPublic *OpenPublicECC(const AuMemoryViewRead &pk) { auto type = GetEdECCCurveType(pk.ptr, pk.length); if (type != EECCCurve::eEnumInvalid) { if (auto ret = NewStdECC(type, pk, false)) { return ret; } } if (IsBlobCurveX25519(pk.ptr, pk.length)) { return New25519ECC(true, pk, false); } if (IsBlobCurveEd25519(pk.ptr, pk.length)) { return New25519ECC(false, pk, false); } return {}; } AUKN_SYM IECCPublic *OpenPublicECCFromCert(const AuMemoryViewRead &certificate) { auto type = GetEdECCCurveType(certificate.ptr, certificate.length); if (type != EECCCurve::eEnumInvalid) { if (auto ret = NewStdECC(type, certificate, true)) { return ret; } } if (IsBlobCurveX25519(certificate.ptr, certificate.length)) { return New25519ECC(true, certificate, true); } if (IsBlobCurveEd25519(certificate.ptr, certificate.length)) { return New25519ECC(false, certificate, true); } 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); } }