127 lines
3.8 KiB
C++
127 lines
3.8 KiB
C++
//
|
|
// Created by Andrew on 09/04/2023.
|
|
//
|
|
|
|
#include "header.h"
|
|
|
|
/* Convert data between endianness types. */
|
|
void endian(byte *data, int length) {
|
|
for (int i = 0; i < length / 2; i++) {
|
|
byte temp = data[i];
|
|
data[i] = data[length - i - 1];
|
|
data[length - i - 1] = temp;
|
|
}
|
|
}
|
|
|
|
/* Generates a random 32-bit integer in range. */
|
|
DWORD randomRange(DWORD dwLow, DWORD dwHigh) {
|
|
return rand() % (dwHigh - dwLow) + dwLow;
|
|
}
|
|
|
|
/* Stops current asynchronously played audio. */
|
|
void stopAudio() {
|
|
PlaySoundW(nullptr, nullptr, 0);
|
|
}
|
|
|
|
/* Plays audio stored as a resource. */
|
|
bool playAudio(HINSTANCE hInstance, WCHAR *lpName, UINT bFlags) {
|
|
HANDLE hResInfo = FindResourceW(hInstance, lpName, L"WAVE");
|
|
|
|
if (hResInfo == nullptr)
|
|
return false;
|
|
|
|
HANDLE hRes = LoadResource(hInstance, (HRSRC)hResInfo);
|
|
|
|
if (hRes == nullptr)
|
|
return false;
|
|
|
|
WCHAR *lpRes = (WCHAR *)LockResource(hRes);
|
|
FreeResource(hRes);
|
|
|
|
return sndPlaySoundW(lpRes, SND_MEMORY | bFlags);
|
|
}
|
|
|
|
/* Initializes the elliptic curve. */
|
|
EC_GROUP *initializeEllipticCurve(
|
|
CONST CHAR *pSel,
|
|
CONST CHAR *aSel,
|
|
CONST CHAR *bSel,
|
|
CONST CHAR *generatorXSel,
|
|
CONST CHAR *generatorYSel,
|
|
CONST CHAR *publicKeyXSel,
|
|
CONST CHAR *publicKeyYSel,
|
|
EC_POINT **genPoint,
|
|
EC_POINT **pubPoint
|
|
) {
|
|
// Initialize BIGNUM and BIGNUMCTX structures.
|
|
// BIGNUM - Large numbers
|
|
// BN_CTX - Context variables (allow concurrency)
|
|
BIGNUM *a, *b, *p, *generatorX, *generatorY, *publicKeyX, *publicKeyY;
|
|
BN_CTX *context;
|
|
|
|
// Microsoft Product Key identification program uses a public key stored in pidgen.dll's BINK resource,
|
|
// which is an Elliptic Curve Cryptography (ECC) public key. It can be decomposed into a following mathematical task:
|
|
|
|
// We're presented with an elliptic curve, a multivariable function F(y; x; p; a; b), where
|
|
// y^2 = x^3 + ax + b (mod p).
|
|
a = BN_new();
|
|
b = BN_new();
|
|
p = BN_new();
|
|
|
|
// K(x; y) is the resulting point.
|
|
publicKeyX = BN_new();
|
|
publicKeyY = BN_new();
|
|
|
|
// G(x; y) is the base point.
|
|
generatorX = BN_new();
|
|
generatorY = BN_new();
|
|
|
|
// Context variable.
|
|
context = BN_CTX_new();
|
|
|
|
// Initialize public data from the BINK resource.
|
|
BN_hex2bn(&p, pSel);
|
|
BN_hex2bn(&a, aSel);
|
|
BN_hex2bn(&b, bSel);
|
|
BN_hex2bn(&generatorX, generatorXSel);
|
|
BN_hex2bn(&generatorY, generatorYSel);
|
|
|
|
BN_hex2bn(&publicKeyX, publicKeyXSel);
|
|
BN_hex2bn(&publicKeyY, publicKeyYSel);
|
|
|
|
// Elliptic Curve calculations.
|
|
// The abelian group is defined via Galois field Fp - all integers [0; p - 1], where p is prime.
|
|
EC_GROUP *eCurve = EC_GROUP_new_curve_GFp(p, a, b, context);
|
|
|
|
// Create new point for the generator on the elliptic curve and set its coordinates to (genX; genY).
|
|
*genPoint = EC_POINT_new(eCurve);
|
|
EC_POINT_set_affine_coordinates(eCurve, *genPoint, generatorX, generatorY, context);
|
|
|
|
// Create new point for the public key on the elliptic curve and set its coordinates to (pubX; pubY).
|
|
*pubPoint = EC_POINT_new(eCurve);
|
|
EC_POINT_set_affine_coordinates(eCurve, *pubPoint, publicKeyX, publicKeyY, context);
|
|
|
|
// If generator and public key points are not on the elliptic curve, either the generator or the public key values are incorrect.
|
|
assert(EC_POINT_is_on_curve(eCurve, *genPoint, context) == 1);
|
|
assert(EC_POINT_is_on_curve(eCurve, *pubPoint, context) == 1);
|
|
|
|
// Cleanup.
|
|
BN_CTX_free(context);
|
|
|
|
return eCurve;
|
|
}
|
|
|
|
int BN_bn2lebin(const BIGNUM *a, unsigned char *to, int tolen) {
|
|
if (a == nullptr || to == nullptr)
|
|
return 0;
|
|
|
|
int len = BN_bn2bin(a, to);
|
|
|
|
if (len > tolen)
|
|
return -1;
|
|
|
|
// Choke point inside BN_bn2lebinpad: OpenSSL uses len instead of tolen.
|
|
endian(to, tolen);
|
|
|
|
return len;
|
|
} |