256 lines
7.0 KiB
C++
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);
|
|
}
|
|
}
|