Refactor project structure

This commit is contained in:
2026-03-28 19:56:39 +11:00
parent 1d267378b2
commit 8a2e721058
511 changed files with 59 additions and 48 deletions

View File

@@ -0,0 +1,451 @@
#ifndef __CERTIFICATE_H
#define __CERTIFICATE_H
#include "ecc.h"
#include "bitstruct.h"
#include "except.h"
#include "base64.h"
#include "sdkregistration.h"
#include "download.h"
#include <time.h>
using namespace ECC;
class Certificate
{
public:
Certificate()
{
}
Certificate(const char * base64Certificate)
{
BASE64 base64;
int len;
auto buf = base64.decode(base64Certificate, strlen(base64Certificate), &len);
if (buf.empty())
throw new LicensingException(STATUS_GENERIC_ERROR, "invalid base64 encoding for certificate");
Attach(buf, len);
}
Certificate(vector<unsigned char>& buf, int len)
{
Attach(buf, len);
}
void* GetBuffer(int * len)
{
int size;
void * buf = m_certBits.GetBuffer(&size);
size = (size + 7) >> 3;
*len = size;
return buf;
}
const char * ToString()
{
BASE64 base64;
int len;
static string base64cert;
unsigned char * buf = (unsigned char *)m_certBits.GetBuffer(&len);
len = (len + 7) >> 3;
auto base64Buf = base64.encode(buf, len, true);
if (base64Buf.empty())
throw new LicensingException(STATUS_GENERIC_ERROR, "could not encode buffer to base64");
base64cert = base64Buf.c_str();
return base64cert.c_str();
}
/*
static Certificate * Generate(int signatureSize, time_t expirationDate = 0)
{
return Generate(signatureSize, (ECC::Key *)NULL, NULL, NULL, NULL, expirationDate);
}
static Certificate * Generate(int signatureSize, Certificate * signingCertificate, time_t expirationDate = 0)
{
return Generate(signatureSize, NULL, NULL, signingCertificate, NULL, expirationDate);
}
static Certificate * Generate(int signatureSize, const char * certificateAuthorityUrl, time_t expirationDate = 0)
{
return Generate(signatureSize, (ECC::Key *)NULL, NULL, NULL, certificateAuthorityUrl, expirationDate);
}
*/
static bool VerifySignature(Certificate * cert, Certificate * validationCert)
{
unsigned char rawPublicKey[256]; int rawPublicKeyLen = 256;
if (validationCert == NULL || cert->m_certBits.GetInt("IsSelfSigned") != 0)
cert->m_certBits.Get("PublicKey", rawPublicKey, &rawPublicKeyLen);
else
validationCert->m_certBits.Get("PublicKey", rawPublicKey, &rawPublicKeyLen);
Key key(rawPublicKey, rawPublicKeyLen);
Verifier verifier;
verifier.SetPublicKey(&key);
unsigned char * certBuffer = (unsigned char *)cert->m_certBits.GetBuffer();
int signedPartLen = 4 + cert->m_certBits.GetInt("PublicKeyLen"),
signatureOffset = 2 + signedPartLen,
signatureBitLen = cert->m_certBits.GetInt("SignatureSizeBits");
if (!verifier.Verify(certBuffer, signedPartLen, certBuffer + signatureOffset, (signatureBitLen + 7) >> 3, signatureBitLen))
return false;
return true;
}
void GetPublicKey(void * buf, int * len)
{
m_certBits.Get("PublicKey", buf, len);
}
static Certificate * Generate(int signatureSize, const char * base64PrivateKey, const char * base64PublicKey, const char * base64SigningPrivateKey, const char * base64SigningCertificate, const char * certificateAuthorityUrl, time_t expirationDate)
{
Key * privateKey = NULL,
* publicKey = NULL,
* privateSigningKey;
Certificate * signingCertificate = NULL;
Certificate * result;
try {
if (base64PublicKey != NULL)
publicKey = new Key(base64PublicKey);
if (base64PrivateKey != NULL)
privateKey = new Key(base64PrivateKey);
if (base64SigningPrivateKey != NULL)
privateSigningKey = new Key(base64SigningPrivateKey);
if (base64SigningCertificate != NULL)
signingCertificate = new Certificate(base64SigningCertificate);
result = Generate(signatureSize, privateKey, publicKey, privateSigningKey, signingCertificate, certificateAuthorityUrl, expirationDate);
} catch (...)
{
if (privateKey) delete privateKey;
if (publicKey) delete publicKey;
if (privateSigningKey) delete privateSigningKey;
if (signingCertificate) delete signingCertificate;
throw;
}
if (privateKey) delete privateKey;
if (publicKey) delete publicKey;
if (privateSigningKey) delete privateSigningKey;
if (signingCertificate) delete signingCertificate;
return result;
}
static Certificate * Generate(int signatureSize, Key * privateKey, Key * publicKey, Key * signingPrivateKey, Certificate * signingCertificate, const char * certificateAuthorityUrl, time_t expirationDate)
{
if (publicKey == NULL)
{
throw new LicensingException(STATUS_GENERIC_ERROR, "public key must be provided for the certificate");
}
Key * signingKey = NULL;
bool selfSigned;
if (signingPrivateKey == NULL && certificateAuthorityUrl == NULL)
{
selfSigned = true;
signingKey = privateKey;
}
else
{
selfSigned = false;
if (signingPrivateKey != NULL)
signingKey = signingPrivateKey;
// else use certificate authority url for signing
}
unsigned char rawPublicKey[256]; int rawPublicKeyLen = 256;
publicKey->Store(rawPublicKey, &rawPublicKeyLen);
// unsigned char rawPrivateKey[256]; int rawPrivateKeyLen = 256;
// signingKey->Store(rawPrivateKey, &rawPrivateKeyLen);
int certBitsLen = 4 * 8 + rawPublicKeyLen * 8;
BitStruct certBits(certBitsLen);
certBits.ResetFieldOffset();
certBits.AddField("Version", BitStruct::INTEGER, 4);
certBits.AddField("IsSelfSigned", BitStruct::INTEGER, 1);
certBits.AddField("ReservedFlags", BitStruct::INTEGER, 3);
certBits.AddField("ExpirationDate", BitStruct::DATE16, 16);
certBits.AddField("PublicKeyLen", BitStruct::INTEGER, 8);
certBits.AddField("PublicKey", BitStruct::RAW, rawPublicKeyLen * 8);
certBits.Set("Version", 0);
certBits.Set("IsSelfSigned", (selfSigned) ? 1 : 0);
certBits.Set("ReservedFlags", 0);
expirationDate = time(NULL);
struct tm * t = gmtime(&expirationDate);
certBits.Set("ExpirationDate", t->tm_year + 1900, t->tm_mon, t->tm_mday);
certBits.Set("PublicKeyLen", rawPublicKeyLen);
certBits.Set("PublicKey", rawPublicKey, rawPublicKeyLen);
unsigned char certSignature[256];
int sigSizeBytes = 256;
int sigSizeBits;
if (signingKey != NULL)
{
Signer signer;
signer.SetPrivateKey(signingKey);
signer.Sign(certBits.GetBuffer(), (certBitsLen + 7) >> 3, certSignature, &sigSizeBytes, &sigSizeBits);
}
else
{
#ifndef LICENSING_NO_NETWORKING
if (!certificateAuthorityUrl)
throw new LicensingException(STATUS_GENERIC_ERROR, "no means for certificate signing were provided");
string certificateAuthorityRequest(certificateAuthorityUrl);
certificateAuthorityRequest.append("?csr=");
BASE64 base64;
int len = 4096;
char buffer[4096];
auto base64csr = base64.encode((unsigned char *)certBits.GetBuffer(), (certBits.GetSize() + 7) >> 3, true);
string escapedBase64csr(base64csr.c_str());
StrReplace(escapedBase64csr, "+", "%2B");
StrReplace(escapedBase64csr, "/", "%2F");
StrReplace(escapedBase64csr, "=", "%3D");
certificateAuthorityRequest.append(escapedBase64csr);
const char * sdkLicenseKey = SDKRegistrationImpl::GetLicenseKey();
if (sdkLicenseKey && strlen(sdkLicenseKey) > 0)
{
certificateAuthorityRequest.append("&sdklicensekey=");
certificateAuthorityRequest.append(sdkLicenseKey);
}
UrlDownloadToString(certificateAuthorityRequest.c_str(), buffer, &len);
auto rawBuffer = base64.decode(buffer, len, &len);
if (rawBuffer.empty())
throw new LicensingException(STATUS_GENERIC_ERROR, "invalid base64 string");
auto certBuffer = rawBuffer;
unique_ptr<Certificate> issuedCert = std::make_unique<Certificate>(certBuffer, len);
sigSizeBits = issuedCert->m_certBits.GetInt("SignatureSizeBits");
sigSizeBytes = (sigSizeBits + 7) >> 3;
issuedCert->m_certBits.Get("Signature", certSignature, &sigSizeBytes);
memcpy(certBits.GetBuffer(), rawBuffer.data(), 4 + rawPublicKeyLen);
#else
throw new LicensingException(STATUS_GENERIC_ERROR, "certificate signing private key not provided");
#endif
}
int certBufLen = ((certBitsLen + 7) >> 3) // header + public key
+ 2 // signature size in bits
+ ((sigSizeBits + 7) >> 3); // signature
vector<unsigned char> certBuf;
certBuf.resize(certBufLen);
memcpy(certBuf.data(), certBits.GetBuffer(), (certBitsLen + 7) >> 3);
certBits.Attach(certBuf, certBufLen * 8);
certBits.AddField("SignatureSizeBits", BitStruct::INTEGER, 16);
certBits.AddField("Signature", BitStruct::RAW, ((sigSizeBits + 7) >> 3) << 3);
certBits.Set("SignatureSizeBits", sigSizeBits);
certBits.Set("Signature", certSignature, (sigSizeBits + 7) >> 3);
Certificate * cert = new Certificate();
cert->m_certBits = std::move(certBits);
return cert;
}
static const char * Sign(const char * csr, const char * privateKey, const char * signingPrivateKey, const char * signingCertificate, const char * certificateAuthorityUrl, int expYear, int expMonth, int expDay)
{
Certificate * _csr = new Certificate(csr);
Key * _privateKey = (privateKey) ? new Key(privateKey) : NULL;
Key * _signingPrivateKey = (signingPrivateKey) ? new Key(signingPrivateKey) : NULL;
Certificate * _signingCertificate = (signingCertificate) ? new Certificate(signingCertificate) : NULL;
struct tm _expTm;
time_t _expTime = 0;
if (expYear >= 1900 && expMonth >= 1 && expMonth <= 12 && expDay >= 1 && expDay <= 31)
{
memset(&_expTm, 0, sizeof(_expTm));
_expTm.tm_year = expYear - 1900;
_expTm.tm_mon = expMonth - 1;
_expTm.tm_mday = expDay;
_expTime = mktime(&_expTm);
}
else
if (expYear != 0 || expMonth != 0 || expDay != 0)
throw new LicensingException(STATUS_GENERIC_ERROR, "Invalid certificate expiration date");
Certificate * _signedCert = Sign(_csr, _privateKey, _signingPrivateKey, _signingCertificate, certificateAuthorityUrl, 0);
if (_csr) delete _csr;
if (_privateKey) delete _privateKey;
if (_signingPrivateKey) delete _signingPrivateKey;
if (_signingCertificate) delete _signingCertificate;
const char * signedCert = _signedCert->ToString();
delete _signedCert;
return signedCert;
}
static Certificate * Sign(Certificate * csr, Key * privateKey, Key * signingPrivateKey, Certificate * signingCertificate, const char * certificateAuthorityUrl, time_t expirationDate)
{
unsigned char buf[1024];
int len = 1024;
Key * publicKey;
csr->GetPublicKey(buf, &len);
publicKey = new Key(buf, len);
Certificate * cert = Certificate::Generate(0, privateKey, publicKey, signingPrivateKey, signingCertificate, certificateAuthorityUrl, expirationDate);
delete publicKey;
return cert;
}
private:
void Attach(vector<unsigned char>& buf, int len)
{
m_certBits.Attach(buf, len << 3);
m_certBits.ResetFieldOffset();
m_certBits.AddField("Version", BitStruct::INTEGER, 4);
m_certBits.AddField("IsSelfSigned", BitStruct::INTEGER, 1);
m_certBits.AddField("ReservedFlags", BitStruct::INTEGER, 3);
m_certBits.AddField("ExpirationDate", BitStruct::DATE16, 16);
m_certBits.AddField("PublicKeyLen", BitStruct::INTEGER, 8);
m_certBits.AddField("PublicKey", BitStruct::RAW, m_certBits.GetInt("PublicKeyLen") * 8);
int signedPartLen = (m_certBits.GetCurrentFieldOffset() + 7) >> 3;
if (len <= signedPartLen)
return;
m_certBits.AddField("SignatureSizeBits", BitStruct::INTEGER, 16);
int signatureBitLen = m_certBits.GetInt("SignatureSizeBits");
int signatureLen = (signatureBitLen + 7) >> 3;
int signatureOffset = m_certBits.GetCurrentFieldOffset() >> 3;
m_certBits.AddField("Signature", BitStruct::RAW, signatureLen << 3);
}
static ECC::KEY_TYPE GetKeyType(int sigSize)
{
if (sigSize < 76 || sigSize > 322)
throw new LicensingException(STATUS_INVALID_SIGNATURE_SIZE);
ECC::KEY_TYPE keyType;
int keySize;
if (sigSize <= 108)
{
keyType = ECC::ECC_54;
keySize = 54;
} else
if (sigSize <= 146)
{
keyType = ECC::ECC_73;
keySize = 73;
} else
if (sigSize <= 158)
{
keyType = ECC::ECC_79;
keySize = 79;
} else
if (sigSize <= 182)
{
keyType = ECC::ECC_91;
keySize = 91;
} else
if (sigSize <= 200)
{
keyType = ECC::ECC_100;
keySize = 100;
} else
if (sigSize <= 240)
{
keyType = ECC::ECC_120;
keySize = 120;
} else
if (sigSize <= 262)
{
keyType = ECC::ECC_131;
keySize = 131;
} else
if (sigSize <= 282)
{
keyType = ECC::ECC_141;
keySize = 141;
} else
{
keyType = ECC::ECC_161;
keySize = 161;
}
return keyType;
}
static void StrReplace(string& str, const string& oldStr, const string& newStr)
{
size_t pos = 0;
while((pos = str.find(oldStr, pos)) != std::string::npos)
{
str.replace(pos, oldStr.length(), newStr);
pos += newStr.length();
}
}
BitStruct m_certBits;
};
#endif