AuroraRuntime/Source/Crypto/ECC/ECC.cpp
2022-06-07 05:29:32 +01:00

256 lines
7.0 KiB
C++

/***
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: ECC.cpp
Date: 2021-9-17
Author: Reece
***/
#include <Source/RuntimeInternal.hpp>
#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<unsigned long, 16> &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<unsigned long, 16> 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<bool IsPublic, typename T>
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<const unsigned char>(), pk.length, &in) : ed25519_import_x509(pk.Begin<const unsigned char>(), pk.length, &in);
}
else
{
constexpr auto type = IsPublic ? PK_PUBLIC : PK_PRIVATE;
ret = isX25519 ? x25519_import_raw(pk.Begin<const unsigned char>(), pk.length, type, &in) : ed25519_import_raw(pk.Begin<const unsigned char>(), 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<PublicCurve25519Impl *>(pub);
return;
default:
AuSafeDelete<PublicECCImpl *>(pub);
return;
}
}
static void ReleasePrivateECC(IECCPrivate *priv)
{
switch (priv->GetType())
{
case EECCCurve::eCurveEd25519:
case EECCCurve::eCurveX25519:
AuSafeDelete<PrivateCurve25519Impl *>(priv);
return;
default:
AuSafeDelete<PrivateECCImpl *>(priv);
return;
}
}
AUKN_SYM IECCPrivate *NewECCNew(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 *OpenPrivateECCNew(const AuMemoryViewRead &pk)
{
auto type = GetEdECCCurveType(pk.ptr, pk.length);
if (type != EECCCurve::eEnumInvalid)
{
if (auto ret = NewStdECC<PrivateECCImpl>(type, pk, false))
{
return ret;
}
}
if (IsBlobCurveX25519(pk.ptr, pk.length))
{
return New25519ECC<false, IECCPrivate*>(true, pk, false);
}
if (IsBlobCurveEd25519(pk.ptr, pk.length))
{
return New25519ECC<false, IECCPrivate *>(false, pk, false);
}
return {};
}
AUKN_SYM IECCPublic *OpenPublicECCNew(const AuMemoryViewRead &pk)
{
auto type = GetEdECCCurveType(pk.ptr, pk.length);
if (type != EECCCurve::eEnumInvalid)
{
if (auto ret = NewStdECC<PublicECCImpl>(type, pk, false))
{
return ret;
}
}
if (IsBlobCurveX25519(pk.ptr, pk.length))
{
return New25519ECC<true, IECCPublic *>(true, pk, false);
}
if (IsBlobCurveEd25519(pk.ptr, pk.length))
{
return New25519ECC<true, IECCPublic *>(false, pk, false);
}
return {};
}
AUKN_SYM IECCPublic *OpenPublicECCFromCertNew(const AuMemoryViewRead &certificate)
{
auto type = GetEdECCCurveType(certificate.ptr, certificate.length);
if (type != EECCCurve::eEnumInvalid)
{
if (auto ret = NewStdECC<PublicECCImpl>(type, certificate, true))
{
return ret;
}
}
if (IsBlobCurveX25519(certificate.ptr, certificate.length))
{
return New25519ECC<true, IECCPublic *>(true, certificate, true);
}
if (IsBlobCurveEd25519(certificate.ptr, certificate.length))
{
return New25519ECC<true, IECCPublic *>(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);
}
}