Refactor project structure
This commit is contained in:
17
core/anslicensing/CMakeLists.txt
Normal file
17
core/anslicensing/CMakeLists.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
# anslicensing — Licensing SDK (shared library, built from source)
|
||||
file(GLOB ANSLICENSING_SOURCES "*.cpp" "*.c")
|
||||
file(GLOB ANSLICENSING_HEADERS "*.h")
|
||||
|
||||
add_library(anslicensing SHARED ${ANSLICENSING_SOURCES} ${ANSLICENSING_HEADERS})
|
||||
|
||||
target_include_directories(anslicensing PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${SHARED_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
target_compile_definitions(anslicensing PRIVATE ANSLICENSING_EXPORTS LICENSING_EXPORTS _USRDLL)
|
||||
if(WIN32)
|
||||
target_link_libraries(anslicensing PRIVATE ${WIN_COMMON_LIBS} winhttp)
|
||||
else()
|
||||
target_link_libraries(anslicensing PRIVATE ${UNIX_COMMON_LIBS} curl ssl crypto)
|
||||
endif()
|
||||
395
core/anslicensing/base32.cpp
Normal file
395
core/anslicensing/base32.cpp
Normal file
@@ -0,0 +1,395 @@
|
||||
#include "precomp.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
#include "base32.h"
|
||||
|
||||
|
||||
const char BASE32::alphabet[] = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
|
||||
const char BASE32::values[] = {
|
||||
/* 0 1 2 3 4 5 6 7 8 9 */ /* 0123456789 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* - 00 -> 09 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* - 10 -> 19 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* - 20 -> 29 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* - 30 -> 39 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1, /* - 40 -> 47 */
|
||||
|
||||
-1,-1,24,25,26,27,28,29,30,31, /* 0123456789 - 48 -> 57 */
|
||||
-1,-1,-1,-1,-1,-1,-1, 0, 1, 2, /* :;<=>?@ABC - 58 -> 67 */
|
||||
3, 4, 5, 6, 7,-1, 8, 9,10,11, /* DEFGHIJKLM - 68 -> 77 */
|
||||
12,-1,13,14,15,16,17,18,19,20, /* NOPQRSTUVW - 78 -> 87 */
|
||||
21,22,23, /* XYZ - 88 -> 90 */
|
||||
|
||||
-1,-1,-1,-1,-1,-1, 0, 1, 2, 3, /* abcd - 91 -> 100 */
|
||||
4, 5, 6, 7,-1, 8, 9,10,11,12, /* efghijklmn - 101 -> 110 */
|
||||
-1,13,14,15,16,17,18,19,20,21, /* opqrstuvwx - 111 -> 120 */
|
||||
22,23,-1,-1,-1,-1,-1,-1,-1,-1, /* yz - 121 -> 130 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* - 131 -> 140 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* - 141 -> 150 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* - 151 -> 160 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* - 161 -> 170 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* - 171 -> 180 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* - 181 -> 190 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* - 191 -> 200 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* - 201 -> 210 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* - 211 -> 220 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* - 221 -> 230 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* - 231 -> 240 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* - 241 -> 250 */
|
||||
-1,-1,-1,-1,-1, /* - 251 -> 255 */
|
||||
};
|
||||
|
||||
BASE32::BASE32()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
BASE32::~BASE32()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
string BASE32::encode(unsigned char * buf, int len, bool padding)
|
||||
{
|
||||
int pad;
|
||||
int enclen = encode_pad_length(len, &pad);
|
||||
string encbuf;
|
||||
|
||||
if (!padding)
|
||||
pad = 0;
|
||||
|
||||
encbuf.resize(enclen + pad + 1); /* Allow for trailing NUL */
|
||||
|
||||
encode_exactly(buf, len, encbuf.data(), enclen);
|
||||
|
||||
if (pad)
|
||||
memset(encbuf.data() + enclen, '=', pad);
|
||||
|
||||
encbuf[enclen + pad] = '\0';
|
||||
|
||||
return encbuf;
|
||||
}
|
||||
|
||||
/*
|
||||
* encode_exactly
|
||||
*
|
||||
* Encode `len' bytes from `buf' into `enclen' bytes starting from `encbuf'.
|
||||
* Caller must have ensured that there was EXACTLY the needed room in encbuf.
|
||||
*/
|
||||
void BASE32::encode_exactly(const unsigned char *buf, int len, char *encbuf, int enclen)
|
||||
{
|
||||
int i = 0; /* Input accumulator, 0 for trailing pad */
|
||||
unsigned char const *ip = buf + len; /* Input pointer, one byte off end */
|
||||
char *op = encbuf + enclen; /* Output pointer, one byte off end */
|
||||
|
||||
assert(buf);
|
||||
assert(encbuf);
|
||||
assert(len > 0);
|
||||
assert(enclen >= len * 8 / 5);
|
||||
|
||||
/*
|
||||
* In the following picture, we represent how the 5 bytes of input
|
||||
* are split into groups of 5 bits, each group being encoded as a
|
||||
* single base32 digit.
|
||||
*
|
||||
* input byte 0 1 2 3 4
|
||||
* +--------+--------+--------+--------+--------+
|
||||
* |01234012|34012340|12340123|40123401|23401234|
|
||||
* +--------+--------+--------+--------+--------+
|
||||
* <---><----><---><----><----><---><----><--->
|
||||
* output digit 0 1 2 3 4 5 6 7
|
||||
*
|
||||
*
|
||||
* Because of possible padding, which must be done as if the input
|
||||
* was 0, and because the fractional part is at the end, we'll
|
||||
* start encoding from the end. The encoding loop is unrolled for
|
||||
* greater performance (using the infamous Duff's device to directly
|
||||
* switch at the proper stage within the do {} while loop).
|
||||
*/
|
||||
|
||||
switch (len % 5) {
|
||||
case 0:
|
||||
do {
|
||||
assert(op - encbuf >= 8);
|
||||
i = (unsigned char) *--ip; /* Input #4 */
|
||||
*--op = alphabet[i & 0x1f]; /* Ouput #7 */
|
||||
i >>= 5; /* upper <234>, input #4 */
|
||||
/* FALLTHROUGH */
|
||||
case 4:
|
||||
i |= ((unsigned char) *--ip) << 3; /* had 3 bits in `i' */
|
||||
*--op = alphabet[i & 0x1f]; /* Output #6 */
|
||||
i >>= 5; /* upper <401234>, input #3 */
|
||||
*--op = alphabet[i & 0x1f]; /* Output #5 */
|
||||
i >>= 5; /* upper <4>, input #3 */
|
||||
/* FALLTHROUGH */
|
||||
case 3:
|
||||
i |= ((unsigned char) *--ip) << 1; /* had 1 bits in `i' */
|
||||
*--op = alphabet[i & 0x1f]; /* Output #4 */
|
||||
i >>= 5; /* upper <1234>, input #2 */
|
||||
/* FALLTHROUGH */
|
||||
case 2:
|
||||
i |= ((unsigned char) *--ip) << 4; /* had 4 bits in `i' */
|
||||
*--op = alphabet[i & 0x1f]; /* Output #3 */
|
||||
i >>= 5; /* upper <3401234>, input #1 */
|
||||
*--op = alphabet[i & 0x1f]; /* Output #2 */
|
||||
i >>= 5; /* upper <34>, input #1 */
|
||||
/* FALLTHROUGH */
|
||||
case 1:
|
||||
i |= ((unsigned char) *--ip) << 2; /* had 2 bits in `i' */
|
||||
*--op = alphabet[i & 0x1f]; /* Output #1 */
|
||||
i >>= 5; /* upper <01234>, input #0 */
|
||||
*--op = alphabet[i & 0x1f]; /* Output #0 */
|
||||
i >>= 5; /* Holds nothing, MBZ */
|
||||
assert(i == 0);
|
||||
assert(op >= encbuf);
|
||||
} while (op > encbuf);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* encode_pad_length
|
||||
*
|
||||
* Compute the number of base32 digits and amount of padding necessary
|
||||
* to encode `len' bytes.
|
||||
*
|
||||
* Returns the number of base32 digits necessary.
|
||||
* Furthermore, if `pad' is a non-NULL pointer, it is filled with the amount
|
||||
* of padding chars that would be necessary.
|
||||
*/
|
||||
int BASE32::encode_pad_length(int len, int *pad)
|
||||
{
|
||||
int ndigits; /* Base32 digits necessary */
|
||||
int npad = 0; /* Final padding chars necessary */
|
||||
int qcount; /* Amount of full quintets */
|
||||
int remainder; /* Amount of input bytes in final quintet */
|
||||
|
||||
assert(len > 0);
|
||||
|
||||
qcount = len / 5;
|
||||
remainder = len - (qcount * 5);
|
||||
|
||||
assert(remainder >= 0);
|
||||
|
||||
switch (remainder) {
|
||||
case 0: npad = 0; break;
|
||||
case 1: npad = 6; break;
|
||||
case 2: npad = 4; break;
|
||||
case 3: npad = 3; break;
|
||||
case 4: npad = 1; break;
|
||||
default: assert(0); /* Not possible */
|
||||
}
|
||||
|
||||
ndigits = qcount * 8; /* Each full quintet encoded on 8 bytes */
|
||||
if (npad != 0)
|
||||
ndigits += (8 - npad);
|
||||
|
||||
if (pad)
|
||||
*pad = npad;
|
||||
|
||||
return ndigits;
|
||||
}
|
||||
|
||||
vector<unsigned char> BASE32::decode( const char * buf, int len, int * outlen )
|
||||
{
|
||||
int declen;
|
||||
vector<unsigned char> decbuf;
|
||||
int decoded;
|
||||
|
||||
if (len == 0 || (len & 0x7)) /* Empty, or padding bytes missing */
|
||||
{
|
||||
decbuf.clear();
|
||||
return decbuf;
|
||||
}
|
||||
|
||||
declen = (len >> 3) * 5;
|
||||
decbuf.resize(declen);
|
||||
|
||||
decoded = decode_into(buf, len, decbuf.data(), declen);
|
||||
|
||||
if (decoded == 0)
|
||||
decbuf.clear();
|
||||
|
||||
if (outlen != NULL)
|
||||
*outlen = decoded;
|
||||
|
||||
return decbuf;
|
||||
}
|
||||
|
||||
/*
|
||||
* decode_into
|
||||
*
|
||||
* Decode `len' bytes from `buf' into `declen' bytes starting from `decbuf',
|
||||
* faking the necessary amount of padding if necessary.
|
||||
* Caller must have ensured that there was sufficient room in decbuf.
|
||||
*
|
||||
* Returns the amount of bytes decoded (without trailing padding) if successful,
|
||||
* 0 if the input was not valid base32.
|
||||
*/
|
||||
int BASE32::decode_into(const char *buf, int len, unsigned char *decbuf, int declen)
|
||||
{
|
||||
int padding = 0;
|
||||
|
||||
if (len & 0x7)
|
||||
padding = 8 - (len & 0x7);
|
||||
|
||||
return decode_alphabet(values, buf, len + padding, decbuf, declen, padding);
|
||||
}
|
||||
|
||||
/*
|
||||
* decode_alphabet
|
||||
*
|
||||
* Decode `len' bytes from `buf' into `declen' bytes starting from `decbuf'.
|
||||
* Caller must have ensured that there was sufficient room in decbuf.
|
||||
* Uses the specified decoding alphabet.
|
||||
*
|
||||
* `padding', when non-zero, is the amount of padding that is missing from
|
||||
* the input buffer and which we must assume.
|
||||
*
|
||||
* Return decoded bytes if successful, 0 if the input was not valid base32.
|
||||
*/
|
||||
int BASE32::decode_alphabet(const char valmap[],
|
||||
const char *buf, int len, unsigned char *decbuf, int declen, int padding)
|
||||
{
|
||||
int i = 0; /* Input accumulator, 0 for trailing pad */
|
||||
char const *ip = buf + len; /* Input pointer, one byte off end */
|
||||
int dlen = (len >> 3) * 5; /* Exact decoded length */
|
||||
unsigned char *op; /* Output pointer, one byte off end */
|
||||
int bytes; /* bytes decoded without padding */
|
||||
char v;
|
||||
|
||||
assert(padding >= 0);
|
||||
assert(buf);
|
||||
assert(decbuf);
|
||||
assert(len > 0);
|
||||
assert((len & 0x7) == 0); /* `len' is a multiple of 8 bytes */
|
||||
//assert(declen >= dlen);
|
||||
|
||||
/*
|
||||
* If the last byte of input is '=', there is padding and we need to
|
||||
* zero the tail of the decoding buffer.
|
||||
*
|
||||
* Likewise, when `padding' is non-zero, act as if the '=' were there.
|
||||
*/
|
||||
|
||||
if (buf[len-1] == '=' || padding > 0) {
|
||||
int pad = 0;
|
||||
int n = 0; /* Amount of bytes to zero */
|
||||
int s = 0; /* Amount of bytes to zero */
|
||||
|
||||
/*
|
||||
* Remove and count trailing input padding bytes.
|
||||
*/
|
||||
|
||||
if (padding == 0) {
|
||||
while (*--ip == '=')
|
||||
pad++;
|
||||
ip++; /* Points one byte after real non-padding input */
|
||||
} else {
|
||||
pad = padding;
|
||||
ip -= padding;
|
||||
}
|
||||
|
||||
switch (pad) {
|
||||
case 1: n = 1; s = 0; break;
|
||||
case 3: n = 2; s = 1; break;
|
||||
case 4: n = 3; s = 2; break;
|
||||
case 6: n = 4; s = 3; break;
|
||||
default:
|
||||
return 0; /* Cannot be valid base32 */
|
||||
}
|
||||
|
||||
memset(decbuf + (dlen - n), 0, n);
|
||||
op = decbuf + (dlen - s);
|
||||
bytes = dlen - n;
|
||||
} else {
|
||||
op = decbuf + dlen;
|
||||
bytes = dlen;
|
||||
}
|
||||
|
||||
/*
|
||||
* In the following picture, we represent how the 8 bytes of input,
|
||||
* each consisting of only 5 bits of information forming a base32 digit,
|
||||
* are concatenated back into 5 bytes of binary information.
|
||||
*
|
||||
* input digit 0 1 2 3 4 5 6 7
|
||||
* <---><----><---><----><----><---><----><--->
|
||||
* +--------+--------+--------+--------+--------+
|
||||
* |01234012|34012340|12340123|40123401|23401234|
|
||||
* +--------+--------+--------+--------+--------+
|
||||
* output byte 0 1 2 3 4
|
||||
*
|
||||
*
|
||||
* Because of possible padding, which must be done as if the input
|
||||
* was 0, and because the fractional part is at the end, we'll
|
||||
* start decoding from the end. The decoding loop is unrolled for
|
||||
* greater performance (using the infamous Duff's device to directly
|
||||
* switch at the proper stage within the do {} while loop).
|
||||
*/
|
||||
|
||||
switch ((ip - buf) % 8) {
|
||||
case 0:
|
||||
do {
|
||||
i = valmap[(unsigned char) *--ip]; /* Input #7 */
|
||||
if (i < 0)
|
||||
return 0;
|
||||
/* FALLTHROUGH */
|
||||
case 7:
|
||||
v = valmap[(unsigned char) *--ip]; /* Input #6 */
|
||||
if (v < 0)
|
||||
return 0;
|
||||
i |= v << 5; /* had 5 bits */
|
||||
*--op = i & 0xff; /* Output #4 */
|
||||
i >>= 8; /* lower <01> of output #3 */
|
||||
/* FALLTHROUGH */
|
||||
case 6:
|
||||
v = valmap[(unsigned char) *--ip]; /* Input #5 */
|
||||
if (v < 0)
|
||||
return 0;
|
||||
i |= v << 2; /* had 2 bits */
|
||||
/* FALLTHROUGH */
|
||||
case 5:
|
||||
v = valmap[(unsigned char) *--ip]; /* Input #4 */
|
||||
if (v < 0)
|
||||
return 0;
|
||||
i |= v << 7; /* had 7 bits */
|
||||
*--op = i & 0xff; /* Output #3 */
|
||||
i >>= 8; /* lower <0123> of output #2 */
|
||||
/* FALLTHROUGH */
|
||||
case 4:
|
||||
v = valmap[(unsigned char) *--ip]; /* Input #3 */
|
||||
if (v < 0)
|
||||
return 0;
|
||||
i |= v << 4; /* had 4 bits */
|
||||
*--op = i & 0xff; /* Output #2 */
|
||||
i >>= 8; /* lower <0> of output #1 */
|
||||
/* FALLTHROUGH */
|
||||
case 3:
|
||||
v = valmap[(unsigned char) *--ip]; /* Input #2 */
|
||||
if (v < 0)
|
||||
return 0;
|
||||
i |= v << 1; /* had 1 bit */
|
||||
/* FALLTHROUGH */
|
||||
case 2:
|
||||
v = valmap[(unsigned char) *--ip]; /* Input #1 */
|
||||
if (v < 0)
|
||||
return 0;
|
||||
i |= v << 6; /* had 6 bits */
|
||||
*--op = i & 0xff; /* Output #1 */
|
||||
i >>= 8; /* lower <012> of output #0 */
|
||||
/* FALLTHROUGH */
|
||||
case 1:
|
||||
v = valmap[(unsigned char) *--ip]; /* Input #0 */
|
||||
if (v < 0)
|
||||
return 0;
|
||||
i |= v << 3; /* had 3 bits */
|
||||
*--op = i & 0xff; /* Output #0 */
|
||||
i >>= 8; /* Holds nothing, MBZ */
|
||||
assert(i == 0);
|
||||
assert(op >= decbuf);
|
||||
} while (op > decbuf);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
26
core/anslicensing/base32.h
Normal file
26
core/anslicensing/base32.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class BASE32 {
|
||||
public:
|
||||
BASE32();
|
||||
~BASE32();
|
||||
|
||||
string encode(unsigned char * input, int len, bool padding = false);
|
||||
vector<unsigned char> decode(const char * input, int len, int * outlen);
|
||||
|
||||
int encode_pad_length(int len, int *pad);
|
||||
|
||||
private:
|
||||
void encode_exactly(const unsigned char *buf, int len, char *encbuf, int enclen);
|
||||
|
||||
int decode_into(const char *buf, int len, unsigned char *decbuf, int declen);
|
||||
int decode_alphabet(const char valmap[], const char *buf, int len, unsigned char *decbuf, int declen, int padding);
|
||||
|
||||
static const char values[];
|
||||
static const char alphabet[];
|
||||
};
|
||||
378
core/anslicensing/base64.cpp
Normal file
378
core/anslicensing/base64.cpp
Normal file
@@ -0,0 +1,378 @@
|
||||
#include "precomp.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
#include "base64.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* The Base 64 Alphabet
|
||||
*
|
||||
* Value Encoding Value Encoding Value Encoding Value Encoding
|
||||
* 0 A 17 R 34 i 51 z
|
||||
* 1 B 18 S 35 j 52 0
|
||||
* 2 C 19 T 36 k 53 1
|
||||
* 3 D 20 U 37 l 54 2
|
||||
* 4 E 21 V 38 m 55 3
|
||||
* 5 F 22 W 39 n 56 4
|
||||
* 6 G 23 X 40 o 57 5
|
||||
* 7 H 24 Y 41 p 58 6
|
||||
* 8 I 25 Z 42 q 59 7
|
||||
* 9 J 26 a 43 r 60 8
|
||||
* 10 K 27 b 44 s 61 9
|
||||
* 11 L 28 c 45 t 62 +
|
||||
* 12 M 29 d 46 u 63 /
|
||||
* 13 N 30 e 47 v
|
||||
* 14 O 31 f 48 w (pad) =
|
||||
* 15 P 32 g 49 x
|
||||
* 16 Q 33 h 50 y
|
||||
*/
|
||||
|
||||
const char BASE64::alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
const char BASE64::values[] = {
|
||||
/* 0 1 2 3 4 5 6 7 8 9 */ /* 0123456789 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* - 00 -> 09 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* - 10 -> 19 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* - 20 -> 29 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* - 30 -> 39 */
|
||||
|
||||
-1,-1,-1,62,-1,-1,-1,63, /* ()*+'-./ - 40 -> 47 */
|
||||
52,53,54,55,56,57,58,59,60,61, /* 0123456789 - 48 -> 57 */
|
||||
-1,-1,-1,-1,-1,-1,-1, 0, 1, 2, /* :;<=>?@ABC - 58 -> 67 */
|
||||
3, 4, 5, 6, 7, 8, 9,10,11,12, /* DEFGHIJKLM - 68 -> 77 */
|
||||
13,14,15,16,17,18,19,20,21,22, /* NOPQRSTUVW - 78 -> 87 */
|
||||
23,24,25,-1,-1,-1,-1,-1,-1,26, /* XYZ[\]^_`a - 88 -> 97 */
|
||||
27,28,29,30,31,32,33,34,35,36, /* bcdefghijk - 98 -> 107 */
|
||||
37,38,39,40,41,42,43,44,45,46, /* lmnopqrstu - 108 -> 117 */
|
||||
47,48,49,50,51, /* vwxyz - 118 -> 122 */
|
||||
|
||||
-1,-1,-1,-1,-1,-1,-1,-1, /* - 123 -> 130 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* - 131 -> 140 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* - 141 -> 150 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* - 151 -> 160 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* - 161 -> 170 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* - 171 -> 180 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* - 181 -> 190 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* - 191 -> 200 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* - 201 -> 210 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* - 211 -> 220 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* - 221 -> 230 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* - 231 -> 240 */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* - 241 -> 250 */
|
||||
-1,-1,-1,-1,-1, /* - 251 -> 255 */
|
||||
};
|
||||
|
||||
BASE64::BASE64()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
BASE64::~BASE64()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
string BASE64::encode(unsigned char * buf, int len, bool padding)
|
||||
{
|
||||
int pad;
|
||||
int enclen = encode_pad_length(len, &pad);
|
||||
string encbuf;
|
||||
|
||||
if (!padding)
|
||||
pad = 0;
|
||||
|
||||
encbuf.resize(enclen + pad); /* Allow for trailing NUL */
|
||||
|
||||
encode_exactly(buf, len, encbuf.data(), enclen);
|
||||
|
||||
if (pad)
|
||||
memset(encbuf.data() + enclen, '=', pad);
|
||||
|
||||
return encbuf;
|
||||
}
|
||||
|
||||
/**
|
||||
* encode_exactly
|
||||
*
|
||||
* Encode `len' bytes from `buf' unsignedo `enclen' bytes starting from `encbuf'.
|
||||
* Caller must have ensured that there was EXACTLY the needed room in encbuf.
|
||||
*/
|
||||
void BASE64::encode_exactly(const unsigned char *buf, int len, char *encbuf, int enclen)
|
||||
{
|
||||
int i = 0; /* Input accumulator, 0 for trailing pad */
|
||||
unsigned char const *ip = buf + len; /* Input pounsigneder, one byte off end */
|
||||
char *op = encbuf + enclen; /* Output pounsigneder, one byte off end */
|
||||
|
||||
assert(buf);
|
||||
assert(encbuf);
|
||||
assert(len > 0);
|
||||
assert(enclen >= len * 4 / 3);
|
||||
|
||||
/*
|
||||
* In the following picture, we represent how the 3 bytes of input
|
||||
* are split unsignedo groups of 6 bits, each group being encoded as a
|
||||
* single base64 digit.
|
||||
*
|
||||
* input byte 0 1 2
|
||||
* +--------+--------+--------+
|
||||
* |01234501|23450123|45012345|
|
||||
* +--------+--------+--------+
|
||||
* <----><-----><-----><---->
|
||||
* output digit 0 1 2 3
|
||||
*
|
||||
*
|
||||
* Because of possible padding, which must be done as if the input
|
||||
* was 0, and because the fractional part is at the end, we'll
|
||||
* start encoding from the end. The encoding loop is unrolled for
|
||||
* greater performance (using the infamous Duff's device to directly
|
||||
* switch at the proper stage within the do {} while loop).
|
||||
*/
|
||||
|
||||
switch (len % 3) {
|
||||
case 0:
|
||||
do {
|
||||
assert(op - encbuf >= 4);
|
||||
i = (unsigned char) *--ip; /* Input #2 */
|
||||
*--op = alphabet[i & 0x3f]; /* Ouput #3 */
|
||||
i >>= 6; /* upper <45>, input #2 */
|
||||
/* FALLTHROUGH */
|
||||
case 2:
|
||||
i |= ((unsigned char) *--ip) << 2; /* had 2 bits in `i' */
|
||||
*--op = alphabet[i & 0x3f]; /* Output #2 */
|
||||
i >>= 6; /* upper <2345>, input #1 */
|
||||
/* FALLTHROUGH */
|
||||
case 1:
|
||||
i |= ((unsigned char) *--ip) << 4; /* had 4 bits in `i' */
|
||||
*--op = alphabet[i & 0x3f]; /* Output #1 */
|
||||
i >>= 6; /* upper <012345>, input #0 */
|
||||
*--op = alphabet[i & 0x3f]; /* Output #0 */
|
||||
i >>= 6; /* Holds nothing, MBZ */
|
||||
assert(i == 0);
|
||||
assert(op >= encbuf);
|
||||
} while (op > encbuf);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* encode_pad_length
|
||||
*
|
||||
* Compute the number of base64 digits and amount of padding necessary
|
||||
* to encode `len' bytes.
|
||||
*
|
||||
* Returns the number of base64 digits necessary.
|
||||
* Furthermore, if `pad' is a non-NULL pounsigneder, it is filled with the amount
|
||||
* of padding chars that would be necessary.
|
||||
*/
|
||||
int BASE64::encode_pad_length(int len, int *pad)
|
||||
{
|
||||
int ndigits; /* Base64 digits necessary */
|
||||
int npad = 0; /* Final padding chars necessary */
|
||||
int tcount; /* Amount of full triplets */
|
||||
int remainder; /* Amount of input bytes in final triplet */
|
||||
|
||||
assert(len > 0);
|
||||
|
||||
tcount = len / 3;
|
||||
remainder = len - (tcount * 3);
|
||||
|
||||
assert((unsigned) remainder >= 0);
|
||||
|
||||
switch (remainder) {
|
||||
case 0: npad = 0; break;
|
||||
case 1: npad = 2; break;
|
||||
case 2: npad = 1; break;
|
||||
default: assert(0); /* Not possible */
|
||||
}
|
||||
|
||||
ndigits = tcount * 4; /* Each full triplet encoded on 4 bytes */
|
||||
if (npad != 0)
|
||||
ndigits += (4 - npad);
|
||||
|
||||
if (pad)
|
||||
*pad = npad;
|
||||
|
||||
return ndigits;
|
||||
}
|
||||
|
||||
/**
|
||||
* base64_decode
|
||||
*
|
||||
* Decode `len' bytes starting at `buf' unsignedo new allocated buffer.
|
||||
*
|
||||
* Returns the new decoded buffer, or NULL if the input was not valid base64
|
||||
* encoding. The caller knows the length of the returned buffer: it's the
|
||||
* size of the input divided by 4 and multiplied by 3. If `outlen' is non-NULL,
|
||||
* it is filled with the amount of bytes decoded unsignedo the buffer (without
|
||||
* trailing padding).
|
||||
*/
|
||||
vector<unsigned char> BASE64::decode(const char * buf, int len, int * outlen)
|
||||
{
|
||||
int declen;
|
||||
vector<unsigned char> decbuf;
|
||||
int decoded;
|
||||
|
||||
if (len == -1)
|
||||
len = strlen(buf);
|
||||
|
||||
// if (len == 0 || (len & 0x3)) /* Empty, or padding bytes missing */
|
||||
// return NULL;
|
||||
|
||||
declen = (len >> 2) * 3;
|
||||
decbuf.resize(declen * sizeof(unsigned char));
|
||||
|
||||
decoded = decode_into(buf, len, decbuf.data(), declen);
|
||||
|
||||
if (decoded == 0)
|
||||
decbuf.clear();
|
||||
|
||||
if (outlen)
|
||||
*outlen = decoded;
|
||||
|
||||
return decbuf;
|
||||
}
|
||||
|
||||
/**
|
||||
* decode_into
|
||||
*
|
||||
* Decode `len' bytes from `buf' unsignedo `declen' bytes starting from `decbuf',
|
||||
* faking the necessary amount of padding if necessary.
|
||||
* Caller must have ensured that there was sufficient room in decbuf.
|
||||
*
|
||||
* Returns the amount of bytes decoded (without trailing padding) if successful,
|
||||
* 0 if the input was not valid base32.
|
||||
*/
|
||||
int BASE64::decode_into(const char *buf, int len, unsigned char *decbuf, int declen)
|
||||
{
|
||||
int padding = 0;
|
||||
|
||||
if (len & 0x3)
|
||||
padding = 4 - (len & 0x3);
|
||||
|
||||
return decode_alphabet(values, buf, len + padding, decbuf, declen, padding);
|
||||
}
|
||||
|
||||
/*
|
||||
* decode_alphabet
|
||||
*
|
||||
* Decode `len' bytes from `buf' unsignedo `declen' bytes starting from `decbuf'.
|
||||
* Caller must have ensured that there was sufficient room in decbuf.
|
||||
* Uses the specified decoding alphabet.
|
||||
*
|
||||
* `padding', when non-zero, is the amount of padding that is missing from
|
||||
* the input buffer and which we must assume.
|
||||
*
|
||||
* Return decoded bytes if successful, 0 if the input was not valid base32.
|
||||
*/
|
||||
int BASE64::decode_alphabet(const char valmap[],
|
||||
const char *buf, int len, unsigned char *decbuf, int declen, int padding)
|
||||
{
|
||||
int i = 0; /* Input accumulator, 0 for trailing pad */
|
||||
char const *ip = buf + len; /* Input pounsigneder, one byte off end */
|
||||
int dlen = (len >> 2) * 3; /* Exact decoded length */
|
||||
unsigned char *op; /* Output pounsigneder, one byte off end */
|
||||
int bytes; /* Bytes decoded without padding */
|
||||
char v;
|
||||
|
||||
assert(buf);
|
||||
assert(decbuf);
|
||||
assert(len > 0);
|
||||
assert((len & 0x3) == 0); /* `len' is a multiple of 4 bytes */
|
||||
//assert(declen >= dlen);
|
||||
|
||||
/*
|
||||
* If the last byte of input is '=', there is padding and we need to
|
||||
* zero the tail of the decoding buffer.
|
||||
*
|
||||
* Likewise, when `padding' is non-zero, act as if the '=' were there.
|
||||
*/
|
||||
|
||||
if (buf[len-1] == '=' || padding > 0) {
|
||||
int pad = 0;
|
||||
int n = 0; /* Amount of bytes to zero */
|
||||
int s = 0; /* Amount of bytes to zero */
|
||||
|
||||
/*
|
||||
* Remove and count trailing input padding bytes.
|
||||
*/
|
||||
|
||||
if (padding == 0) {
|
||||
while (*--ip == '=')
|
||||
pad++;
|
||||
ip++; /* Pounsigneds one byte after real non-padding input */
|
||||
} else {
|
||||
pad = padding;
|
||||
ip -= padding;
|
||||
}
|
||||
|
||||
switch (pad) {
|
||||
case 1: n = 1; s = 0; break;
|
||||
case 2: n = 2; s = 1; break;
|
||||
default:
|
||||
return 0; /* Cannot be valid base64 */
|
||||
}
|
||||
|
||||
memset(decbuf + (dlen - n), 0, n);
|
||||
op = decbuf + (dlen - s);
|
||||
bytes = dlen - n;
|
||||
} else {
|
||||
op = decbuf + dlen;
|
||||
bytes = dlen;
|
||||
}
|
||||
|
||||
/*
|
||||
* In the following picture, we represent how the 4 bytes of input,
|
||||
* each consisting of only 6 bits of information forming a base64 digit,
|
||||
* are concatenated back unsignedo 3 bytes of binary information.
|
||||
*
|
||||
* input digit 0 1 2 3
|
||||
* <----><-----><-----><---->
|
||||
* +--------+--------+--------+
|
||||
* |01234501|23450123|45012345|
|
||||
* +--------+--------+--------+
|
||||
* output byte 0 1 2
|
||||
*
|
||||
* Because of possible padding, which must be done as if the input
|
||||
* was 0, and because the fractional part is at the end, we'll
|
||||
* start decoding from the end. The decoding loop is unrolled for
|
||||
* greater performance (using the infamous Duff's device to directly
|
||||
* switch at the proper stage within the do {} while loop).
|
||||
*/
|
||||
|
||||
switch ((ip - buf) % 4) {
|
||||
case 0:
|
||||
do {
|
||||
v = valmap[(unsigned char) *--ip]; /* Input #3 */
|
||||
if (v < 0) return 0;
|
||||
i = v;
|
||||
/* FALLTHROUGH */
|
||||
case 3:
|
||||
v = valmap[(unsigned char) *--ip]; /* Input #2 */
|
||||
if (v < 0) return 0;
|
||||
i |= v << 6; /* had 6 bits */
|
||||
*--op = i & 0xff; /* Output #2 */
|
||||
i >>= 8; /* lower <0123> of output #1 */
|
||||
/* FALLTHROUGH */
|
||||
case 2:
|
||||
v = valmap[(unsigned char) *--ip]; /* Input #1 */
|
||||
if (v < 0) return 0;
|
||||
i |= v << 4; /* had 4 bits */
|
||||
*--op = i & 0xff; /* Output #1 */
|
||||
i >>= 8; /* lower <01> of output #0 */
|
||||
/* FALLTHROUGH */
|
||||
case 1:
|
||||
v = valmap[(unsigned char) *--ip]; /* Input #0 */
|
||||
if (v < 0) return 0;
|
||||
i |= v << 2; /* had 2 bits */
|
||||
*--op = i & 0xff; /* Output #0 */
|
||||
i >>= 8; /* Holds nothing, MBZ */
|
||||
assert(i == 0);
|
||||
assert(op >= decbuf);
|
||||
} while (op > decbuf);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
26
core/anslicensing/base64.h
Normal file
26
core/anslicensing/base64.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class BASE64 {
|
||||
public:
|
||||
BASE64();
|
||||
~BASE64();
|
||||
|
||||
string encode(unsigned char * input, int len, bool padding = false);
|
||||
vector<unsigned char> decode(const char * input, int len = -1, int * outlen = nullptr);
|
||||
|
||||
int encode_pad_length(int len, int *pad);
|
||||
|
||||
private:
|
||||
void encode_exactly(const unsigned char *buf, int len, char *encbuf, int enclen);
|
||||
|
||||
int decode_into(const char *buf, int len, unsigned char *decbuf, int declen);
|
||||
int decode_alphabet(const char valmap[], const char *buf, int len, unsigned char *decbuf, int declen, int padding);
|
||||
|
||||
static const char values[];
|
||||
static const char alphabet[];
|
||||
};
|
||||
1000
core/anslicensing/bigint.cpp
Normal file
1000
core/anslicensing/bigint.cpp
Normal file
File diff suppressed because it is too large
Load Diff
130
core/anslicensing/bigint.h
Normal file
130
core/anslicensing/bigint.h
Normal file
@@ -0,0 +1,130 @@
|
||||
#ifndef __BIGINT_H
|
||||
#define __BIGINT_H
|
||||
|
||||
class bigint;
|
||||
class bigint_value;
|
||||
|
||||
class bigint_unit // Provides storage allocation and index checking
|
||||
{
|
||||
friend class bigint_value;
|
||||
friend class bigint;
|
||||
|
||||
public:
|
||||
bigint_unit();
|
||||
~bigint_unit();
|
||||
|
||||
public:
|
||||
void clear(); // set n to zero
|
||||
unsigned get( unsigned i ) const; // get ith unsigned
|
||||
void set( unsigned i, unsigned x ); // set ith unsigned
|
||||
void reserve( unsigned x ); // storage hint
|
||||
void fast_mul( bigint_unit & x, bigint_unit & y, unsigned n ); // Time critical routine
|
||||
|
||||
private:
|
||||
unsigned n; // used units (read-only)
|
||||
unsigned * a; // array of units
|
||||
unsigned z; // units allocated
|
||||
};
|
||||
|
||||
class bigint_value : public bigint_unit
|
||||
{
|
||||
friend class bigint;
|
||||
|
||||
public:
|
||||
bigint_value();
|
||||
|
||||
public:
|
||||
int is_zero() const;
|
||||
unsigned bit( unsigned i ) const;
|
||||
void setbit( unsigned i );
|
||||
void clearbit( unsigned i );
|
||||
unsigned bits() const;
|
||||
int cf( bigint_value& x ) const;
|
||||
int product( bigint_value &x ) const;
|
||||
void shl();
|
||||
int shr(); // result is carry
|
||||
void shr( unsigned n );
|
||||
void add( bigint_value& x );
|
||||
void _xor( bigint_value& x );
|
||||
void _and( bigint_value& x );
|
||||
void subtract( bigint_value& x );
|
||||
void init( unsigned x );
|
||||
void copy( bigint_value& x );
|
||||
unsigned to_unsigned(); // Unsafe conversion to unsigned
|
||||
void mul( bigint_value& x, bigint_value& y );
|
||||
void divide( bigint_value& x, bigint_value& y, bigint_value& rem );
|
||||
|
||||
private:
|
||||
unsigned share; // share count, used by bigint to delay physical copying
|
||||
};
|
||||
|
||||
class bigint // very long integer - can be used like long
|
||||
{
|
||||
public:
|
||||
// Construction and
|
||||
bigint ( unsigned x = 0 );
|
||||
bigint ( const bigint & x );
|
||||
~bigint();
|
||||
|
||||
public:
|
||||
// Standard arithmetic operators
|
||||
friend bigint operator +( const bigint& x, const bigint& y );
|
||||
friend bigint operator -( const bigint& x, const bigint& y );
|
||||
friend bigint operator *( const bigint& x, const bigint& y );
|
||||
friend bigint operator /( const bigint& x, const bigint& y );
|
||||
friend bigint operator %( const bigint& x, const bigint& y );
|
||||
friend bigint operator ^( const bigint& x, const bigint& y );
|
||||
friend bigint pow2( unsigned n );
|
||||
friend bigint operator &( const bigint& x, const bigint& y );
|
||||
|
||||
friend bigint operator <<( const bigint& x, unsigned n );
|
||||
|
||||
bigint & operator +=( const bigint& x );
|
||||
bigint & operator -=( const bigint& x );
|
||||
bigint & operator >>=( unsigned n );
|
||||
|
||||
// Standard comparison operators
|
||||
friend int operator !=( const bigint& x, const bigint& y );
|
||||
friend int operator ==( const bigint& x, const bigint& y );
|
||||
friend int operator >=( const bigint& x, const bigint& y );
|
||||
friend int operator <=( const bigint& x, const bigint& y );
|
||||
friend int operator > ( const bigint& x, const bigint& y );
|
||||
friend int operator < ( const bigint& x, const bigint& y );
|
||||
|
||||
// Absolute value
|
||||
friend bigint abs( const bigint & x );
|
||||
|
||||
// conversion operations
|
||||
friend unsigned to_unsigned( const bigint &x );
|
||||
bigint & operator =(const bigint& x);
|
||||
|
||||
// Bit operations
|
||||
unsigned bits() const;
|
||||
unsigned bit(unsigned i) const;
|
||||
void setbit(unsigned i);
|
||||
void clearbit(unsigned i);
|
||||
bigint & operator ^=( const bigint& x );
|
||||
bigint & operator &=( const bigint& x );
|
||||
bigint & ror( unsigned n ); // single bit rotate
|
||||
bigint & rol( unsigned n ); // single bit rotate
|
||||
friend int product( const bigint & x, const bigint & y ); // parity of x&y
|
||||
|
||||
void load( const unsigned * a, unsigned n ); // load value, a[0] is lsw
|
||||
void store( unsigned * a, unsigned n ) const; // low level save, a[0] is lsw
|
||||
|
||||
private:
|
||||
bigint_value * value;
|
||||
int negative;
|
||||
int cf( const bigint & x ) const;
|
||||
void docopy();
|
||||
friend class monty;
|
||||
};
|
||||
|
||||
bigint modexp( const bigint & x, const bigint & e, const bigint & m ); // m must be odd
|
||||
bigint gcd( const bigint & X, const bigint & Y ); // greatest common denominator
|
||||
bigint modinv( const bigint & a, const bigint & m ); // modular inverse
|
||||
bigint lucas ( const bigint & P, const bigint & Z, const bigint & k, const bigint & p ); // P^2 - 4Z != 0
|
||||
bigint sqrt( const bigint & g, const bigint & p ); // square root mod p
|
||||
bigint pow2( unsigned n );
|
||||
|
||||
#endif
|
||||
232
core/anslicensing/bitstream.cpp
Normal file
232
core/anslicensing/bitstream.cpp
Normal file
@@ -0,0 +1,232 @@
|
||||
//
|
||||
// Copyright (c) ANSCENTER. All rights reserved.
|
||||
//
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <tchar.h>
|
||||
#endif
|
||||
|
||||
#include "bitstream.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
BitStream::BitStream(int bitSize)
|
||||
{
|
||||
Create(bitSize);
|
||||
}
|
||||
|
||||
BitStream::BitStream(vector<unsigned char>& buf, int bufBits)
|
||||
{
|
||||
Attach(buf, bufBits);
|
||||
}
|
||||
|
||||
bool BitStream::Create(int bitCount)
|
||||
{
|
||||
m_bufBits = bitCount;
|
||||
m_currentBitIndex = 0;
|
||||
|
||||
if (!bitCount)
|
||||
{
|
||||
m_buf.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
m_buf.resize((bitCount + 7) >> 3);
|
||||
|
||||
Clear();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void BitStream::Attach(vector<unsigned char>& buf, int bufBits)
|
||||
{
|
||||
m_buf = std::move(buf);
|
||||
m_bufBits = bufBits;
|
||||
m_currentBitIndex = 0;
|
||||
}
|
||||
|
||||
int BitStream::Read(void *bitPtr, int bitCount)
|
||||
{
|
||||
if(bitCount + m_currentBitIndex > m_bufBits)
|
||||
{
|
||||
bitCount = m_bufBits - m_currentBitIndex;
|
||||
}
|
||||
|
||||
if(!bitCount)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int readBitCount = bitCount;
|
||||
unsigned char lastByteMask = (unsigned char)((1 << (readBitCount & 7)) - 1);
|
||||
unsigned char * sourcePtr = m_buf.data() + (m_currentBitIndex >> 3);
|
||||
int byteCount = (bitCount + 7) >> 3;
|
||||
unsigned char * destPtr = (unsigned char *)bitPtr;
|
||||
|
||||
int downShift = m_currentBitIndex & 0x7;
|
||||
int upShift = 8 - downShift;
|
||||
|
||||
if (!downShift)
|
||||
{
|
||||
while(byteCount--)
|
||||
*destPtr++ = *sourcePtr++;
|
||||
|
||||
m_currentBitIndex += bitCount;
|
||||
|
||||
if (lastByteMask > 0)
|
||||
((unsigned char *)bitPtr)[readBitCount >> 3] &= lastByteMask;
|
||||
|
||||
return readBitCount;
|
||||
}
|
||||
|
||||
unsigned char sourceByte = *sourcePtr >> downShift;
|
||||
m_currentBitIndex += bitCount;
|
||||
|
||||
for (; bitCount > 8; bitCount -= 8)
|
||||
{
|
||||
unsigned char nextByte = *++sourcePtr;
|
||||
*destPtr++ = sourceByte | (nextByte << upShift);
|
||||
sourceByte = nextByte >> downShift;
|
||||
}
|
||||
|
||||
if (bitCount)
|
||||
{
|
||||
if (bitCount <= upShift)
|
||||
{
|
||||
*destPtr = sourceByte;
|
||||
return readBitCount;
|
||||
}
|
||||
|
||||
*destPtr = sourceByte | ( (*++sourcePtr) << upShift);
|
||||
}
|
||||
|
||||
if (lastByteMask > 0)
|
||||
((unsigned char *)bitPtr)[readBitCount >> 3] &= lastByteMask;
|
||||
|
||||
return readBitCount;
|
||||
}
|
||||
|
||||
int BitStream::Write(const void * bitPtr, int bitCount)
|
||||
{
|
||||
int maxBits = ((m_bufBits + 7) >> 3) << 3;
|
||||
|
||||
if (bitCount + m_currentBitIndex > maxBits)
|
||||
{
|
||||
bitCount = maxBits - m_currentBitIndex;
|
||||
}
|
||||
|
||||
if(!bitCount)
|
||||
return 0;
|
||||
|
||||
int writeBitCount = bitCount;
|
||||
int upShift = m_currentBitIndex & 0x7;
|
||||
int downShift = 8 - upShift;
|
||||
|
||||
const unsigned char * sourcePtr = (unsigned char *)bitPtr;
|
||||
unsigned char * destPtr = m_buf.data() + (m_currentBitIndex >> 3);
|
||||
|
||||
// if this write is for <= 1 byte, and it will all fit in the
|
||||
// first dest byte, then do some special masking.
|
||||
if (downShift >= bitCount)
|
||||
{
|
||||
unsigned char mask = (unsigned char)(((1 << bitCount) - 1) << upShift);
|
||||
*destPtr = (*destPtr & ~mask) | ((*sourcePtr << upShift) & mask);
|
||||
m_currentBitIndex += bitCount;
|
||||
return writeBitCount;
|
||||
}
|
||||
|
||||
// check for byte aligned writes -- this will be
|
||||
// much faster than the shifting writes.
|
||||
|
||||
if(!upShift)
|
||||
{
|
||||
m_currentBitIndex += bitCount;
|
||||
|
||||
for(; bitCount >= 8; bitCount -= 8)
|
||||
*destPtr++ = *sourcePtr++;
|
||||
|
||||
if(bitCount)
|
||||
{
|
||||
unsigned char mask = (unsigned char)((1 << bitCount) - 1);
|
||||
*destPtr = (*sourcePtr & mask) | (*destPtr & ~mask);
|
||||
}
|
||||
|
||||
return writeBitCount;
|
||||
}
|
||||
|
||||
// the write destination is not byte aligned.
|
||||
unsigned char sourceByte;
|
||||
unsigned char destByte = *destPtr & (0xFF >> downShift);
|
||||
unsigned char lastMask = (unsigned char)(0xFF >> (7 - ((m_currentBitIndex + bitCount - 1) & 0x7)));
|
||||
|
||||
m_currentBitIndex += bitCount;
|
||||
|
||||
for(;bitCount >= 8; bitCount -= 8)
|
||||
{
|
||||
sourceByte = *sourcePtr++;
|
||||
*destPtr++ = destByte | (sourceByte << upShift);
|
||||
destByte = sourceByte >> downShift;
|
||||
}
|
||||
|
||||
if(bitCount == 0)
|
||||
{
|
||||
*destPtr = (*destPtr & ~lastMask) | (destByte & lastMask);
|
||||
return writeBitCount;
|
||||
}
|
||||
|
||||
if(bitCount <= downShift)
|
||||
{
|
||||
*destPtr = (*destPtr & ~lastMask) | ((destByte | (*sourcePtr << upShift)) & lastMask);
|
||||
return writeBitCount;
|
||||
}
|
||||
|
||||
sourceByte = *sourcePtr;
|
||||
|
||||
*destPtr++ = destByte | (sourceByte << upShift);
|
||||
*destPtr = (*destPtr & ~lastMask) | ((sourceByte >> downShift) & lastMask);
|
||||
|
||||
return writeBitCount;
|
||||
}
|
||||
|
||||
void BitStream::ZeroPadToNextByte()
|
||||
{
|
||||
unsigned char zero = 0;
|
||||
|
||||
if(m_currentBitIndex & 0x7)
|
||||
Write(&zero, 8 - (m_currentBitIndex & 0x7));
|
||||
}
|
||||
|
||||
int BitStream::Seek(int offset, bool relative)
|
||||
{
|
||||
unsigned oldIndex = m_currentBitIndex;
|
||||
m_currentBitIndex = (relative) ? m_currentBitIndex + offset : offset;
|
||||
return oldIndex;
|
||||
}
|
||||
|
||||
int BitStream::GetSize()
|
||||
{
|
||||
return m_bufBits;
|
||||
}
|
||||
|
||||
void * BitStream::GetBuffer(int * sizeInBits)
|
||||
{
|
||||
if (sizeInBits != NULL)
|
||||
*sizeInBits = m_bufBits;
|
||||
|
||||
return m_buf.data();
|
||||
}
|
||||
|
||||
void BitStream::ReleaseBuffer(int bitCount)
|
||||
{
|
||||
m_currentBitIndex = bitCount;
|
||||
}
|
||||
|
||||
void BitStream::Clear()
|
||||
{
|
||||
memset(m_buf.data(), 0, m_buf.size());
|
||||
}
|
||||
29
core/anslicensing/bitstream.h
Normal file
29
core/anslicensing/bitstream.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class BitStream
|
||||
{
|
||||
public:
|
||||
BitStream(int bitSize = 0);
|
||||
BitStream(vector<unsigned char>& buf, int bitSize);
|
||||
|
||||
|
||||
bool Create(int sizeInBits);
|
||||
void Attach(vector<unsigned char>& buf, int sizeInBits);
|
||||
int Read(void *bitPtr, int countInBits);
|
||||
int Write(const void * bitPtr, int countInBits);
|
||||
int Seek(int offset, bool relative = false);
|
||||
int GetSize();
|
||||
void ZeroPadToNextByte();
|
||||
void * GetBuffer(int * sizeInBits = NULL);
|
||||
void ReleaseBuffer(int bitCount);
|
||||
void Clear();
|
||||
|
||||
protected:
|
||||
vector<unsigned char> m_buf;
|
||||
int m_bufBits;
|
||||
int m_currentBitIndex;
|
||||
};
|
||||
125
core/anslicensing/bitstream2.cpp
Normal file
125
core/anslicensing/bitstream2.cpp
Normal file
@@ -0,0 +1,125 @@
|
||||
#include "precomp.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "bitstream2.h"
|
||||
|
||||
const unsigned char BitStream2::hiMask[] = { 0, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF };
|
||||
|
||||
BitStream2::BitStream2() :
|
||||
ownMemory(false),
|
||||
currentBit(0),
|
||||
currentByte(0),
|
||||
buffer(NULL)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
BitStream2::BitStream2(int bitCount)
|
||||
{
|
||||
currentBit = 0;
|
||||
currentByte = 0;
|
||||
Create(bitCount);
|
||||
}
|
||||
|
||||
BitStream2::~BitStream2()
|
||||
{
|
||||
if (ownMemory)
|
||||
delete buffer;
|
||||
}
|
||||
|
||||
void BitStream2::Create(int bitCount)
|
||||
{
|
||||
bufSize = (bitCount + 7) >> 3;
|
||||
buffer = new unsigned char[(bitCount + 7) >> 3];
|
||||
ownMemory = true;
|
||||
memset(buffer, 0, bufSize);
|
||||
}
|
||||
|
||||
void BitStream2::Attach(void * buf, int bitCount)
|
||||
{
|
||||
buffer = (unsigned char *)buf;
|
||||
}
|
||||
|
||||
int BitStream2::Write(const unsigned char * buf, int bitCount)
|
||||
{
|
||||
unsigned char destByte;
|
||||
|
||||
int leftBits = currentBit & 7;
|
||||
int rightBits = 8 - leftBits;
|
||||
|
||||
int i = 0;
|
||||
int count = bitCount;
|
||||
while (count > 0)
|
||||
{
|
||||
destByte = (unsigned char)((buffer[currentByte] & hiMask[leftBits]) | (buf[i] >> leftBits));
|
||||
buffer[currentByte] = destByte;
|
||||
|
||||
count = (count > rightBits) ? count - rightBits : 0;
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
currentByte++;
|
||||
buffer[currentByte] = (unsigned char)(buf[i] << rightBits);
|
||||
count = (count > leftBits) ? count - leftBits : 0;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
currentBit += bitCount;
|
||||
|
||||
return bitCount;
|
||||
}
|
||||
|
||||
int BitStream2::WriteUInt16(unsigned short val)
|
||||
{
|
||||
unsigned char split[2]; split[0] = (unsigned char)(val >> 8); split[1] = (unsigned char)(val & 0xFF);
|
||||
return Write(split, 16);
|
||||
}
|
||||
|
||||
int BitStream2::Read(unsigned char * buf, int bitCount)
|
||||
{
|
||||
unsigned char destByte;
|
||||
int rightBits = 8 - (currentBit & 7);
|
||||
int leftBits = 8 - rightBits;
|
||||
|
||||
int count = bitCount;
|
||||
int i = 0;
|
||||
while (count > 0)
|
||||
{
|
||||
buf[i] = (unsigned char)(buffer[currentByte] << leftBits);
|
||||
count = (count > rightBits) ? count - rightBits : 0;
|
||||
if (count > 0)
|
||||
{
|
||||
currentByte++;
|
||||
destByte = buf[i];
|
||||
destByte = (unsigned char)(destByte | (buffer[currentByte] >> rightBits));
|
||||
buf[i] = destByte;
|
||||
|
||||
count = (count > leftBits) ? count - leftBits : 0;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
currentBit += bitCount;
|
||||
|
||||
return bitCount;
|
||||
}
|
||||
|
||||
int BitStream2::ReadUInt16(unsigned short * val)
|
||||
{
|
||||
unsigned char split[2];
|
||||
|
||||
int result = Read(split, 16);
|
||||
|
||||
*val = (unsigned short)(((unsigned short)split[0] << 8) | (unsigned short)split[1]);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned char * BitStream2::GetBuffer()
|
||||
{
|
||||
return buffer;
|
||||
}
|
||||
24
core/anslicensing/bitstream2.h
Normal file
24
core/anslicensing/bitstream2.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
class BitStream2
|
||||
{
|
||||
public:
|
||||
BitStream2();
|
||||
BitStream2(int bitCount);
|
||||
~BitStream2();
|
||||
|
||||
void Create(int bitCount);
|
||||
void Attach(void * buf, int bitCount);
|
||||
int Write(const unsigned char * buf, int bitCount);
|
||||
int WriteUInt16(unsigned short val);
|
||||
int Read(unsigned char * buf, int bitCount);
|
||||
int ReadUInt16(unsigned short * val);
|
||||
unsigned char * GetBuffer();
|
||||
|
||||
protected:
|
||||
bool ownMemory;
|
||||
unsigned char * buffer;
|
||||
int bufSize;
|
||||
int currentBit, currentByte;
|
||||
static const unsigned char hiMask[];
|
||||
};
|
||||
144
core/anslicensing/bitstream3.cpp
Normal file
144
core/anslicensing/bitstream3.cpp
Normal file
@@ -0,0 +1,144 @@
|
||||
#include "precomp.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "bitstream3.h"
|
||||
|
||||
const unsigned char BitStream3::hiMask[] = { 0, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF };
|
||||
|
||||
BitStream3::BitStream3() :
|
||||
ownMemory(false),
|
||||
currentBit(0),
|
||||
currentByte(0),
|
||||
buffer(NULL)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
BitStream3::BitStream3(int bitCount)
|
||||
{
|
||||
currentBit = 0;
|
||||
currentByte = 0;
|
||||
Create(bitCount);
|
||||
}
|
||||
|
||||
BitStream3::~BitStream3()
|
||||
{
|
||||
if (ownMemory)
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
void BitStream3::Create(int bitCount)
|
||||
{
|
||||
bufSize = (bitCount + 7) >> 3;
|
||||
bitSize = bitCount;
|
||||
buffer = (unsigned char*)malloc((bitCount + 7) >> 3);
|
||||
ownMemory = true;
|
||||
memset(buffer, 0, bufSize);
|
||||
}
|
||||
|
||||
void BitStream3::Attach(void * buf, int bitCount)
|
||||
{
|
||||
buffer = (unsigned char *)buf;
|
||||
bitSize = bitCount;
|
||||
currentBit = 0;
|
||||
currentByte = 0;
|
||||
}
|
||||
|
||||
int BitStream3::Write(const unsigned char * buf, int bitCount)
|
||||
{
|
||||
int i = 0, gap = 8 - (currentBit & 7);
|
||||
|
||||
if (bitCount >= gap)
|
||||
{
|
||||
if ((gap & 7) != 0)
|
||||
{
|
||||
buffer[currentByte] = (unsigned char)((buffer[currentByte] << gap) | (buf[0] >> (bitCount < 8 ? bitCount - gap : 8 - gap)));
|
||||
currentBit += gap; bitCount -= gap; currentByte++;
|
||||
|
||||
for (; bitCount >= 8; i++, currentByte++, currentBit += 8, bitCount -= 8)
|
||||
buffer[currentByte] = (unsigned char)((buf[i] << gap) | (buf[i + 1] >> (8 - gap)));
|
||||
}
|
||||
else
|
||||
for (; bitCount >= 8; currentByte++, i++, currentBit += 8, bitCount -= 8)
|
||||
buffer[currentByte] = buf[i];
|
||||
}
|
||||
|
||||
if (bitCount > 0)
|
||||
{
|
||||
buffer[currentByte] = (unsigned char)((buffer[currentByte] << bitCount) | (buf[i] & ((1 << bitCount) - 1)));
|
||||
currentBit += bitCount;
|
||||
}
|
||||
|
||||
return bitCount;
|
||||
}
|
||||
|
||||
int BitStream3::WriteUInt16(unsigned short val)
|
||||
{
|
||||
unsigned char split[2]; split[0] = (unsigned char)(val >> 8); split[1] = (unsigned char)(val & 0xFF);
|
||||
return Write(split, 16);
|
||||
}
|
||||
|
||||
int BitStream3::Read(unsigned char * readBuf, int bitCount)
|
||||
{
|
||||
int i = 0, gap = currentBit & 7;
|
||||
|
||||
if ((gap & 7) != 0)
|
||||
{
|
||||
for (; bitCount >= 8 + 8 - gap; bitCount -= 8, currentByte++, currentBit += 8, i++)
|
||||
readBuf[i] = (unsigned char)((buffer[currentByte] << gap) | (buffer[currentByte + 1] >> (8 - gap)));
|
||||
|
||||
// byte align
|
||||
if (bitCount > 0)
|
||||
{
|
||||
if (bitCount < 8 - gap)
|
||||
{
|
||||
readBuf[i] = (unsigned char)((buffer[currentByte] >> (8 - gap - bitCount)) & ((1 << bitCount) - 1));
|
||||
currentBit += bitCount;
|
||||
bitCount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
readBuf[i] = (unsigned char)(buffer[currentByte] & ((1 << (8 - gap)) - 1));
|
||||
|
||||
bitCount -= (8 - gap);
|
||||
currentBit += (8 - gap);
|
||||
currentByte++;
|
||||
|
||||
readBuf[i] <<= (bitCount < gap ? bitCount : gap);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
for (; bitCount >= 8; bitCount -= 8, currentByte++, currentBit += 8, i++)
|
||||
readBuf[i] = buffer[currentByte];
|
||||
|
||||
// already aligned
|
||||
if (bitCount > 0)
|
||||
{
|
||||
if (currentBit + 8 <= bitSize) // not last byte
|
||||
readBuf[i] |= (unsigned char)((buffer[currentByte] >> (8 - bitCount)) & ((1 << bitCount) - 1));
|
||||
else // last byte
|
||||
readBuf[i] = (unsigned char)((buffer[currentByte] >> ((bitSize & 7) - bitCount)) & ((1 << bitCount) - 1));
|
||||
|
||||
currentBit += bitCount;
|
||||
}
|
||||
|
||||
return bitCount;
|
||||
}
|
||||
|
||||
int BitStream3::ReadUInt16(unsigned short * val)
|
||||
{
|
||||
unsigned char split[2];
|
||||
|
||||
int result = Read(split, 16);
|
||||
|
||||
*val = (unsigned short)(((unsigned short)split[0] << 8) | (unsigned short)split[1]);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned char * BitStream3::GetBuffer()
|
||||
{
|
||||
return buffer;
|
||||
}
|
||||
24
core/anslicensing/bitstream3.h
Normal file
24
core/anslicensing/bitstream3.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
class BitStream3
|
||||
{
|
||||
public:
|
||||
BitStream3();
|
||||
BitStream3(int bitCount);
|
||||
~BitStream3();
|
||||
|
||||
void Create(int bitCount);
|
||||
void Attach(void * buf, int bitCount);
|
||||
int Write(const unsigned char * buf, int bitCount);
|
||||
int WriteUInt16(unsigned short val);
|
||||
int Read(unsigned char * buf, int bitCount);
|
||||
int ReadUInt16(unsigned short * val);
|
||||
unsigned char * GetBuffer();
|
||||
|
||||
protected:
|
||||
bool ownMemory;
|
||||
unsigned char * buffer;
|
||||
int bufSize, bitSize;
|
||||
int currentBit, currentByte;
|
||||
static const unsigned char hiMask[];
|
||||
};
|
||||
4
core/anslicensing/bitstruct.cpp
Normal file
4
core/anslicensing/bitstruct.cpp
Normal file
@@ -0,0 +1,4 @@
|
||||
#include "precomp.h"
|
||||
#include "bitstruct.h"
|
||||
|
||||
|
||||
378
core/anslicensing/bitstruct.h
Normal file
378
core/anslicensing/bitstruct.h
Normal file
@@ -0,0 +1,378 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <map>
|
||||
|
||||
#include "bitstream.h"
|
||||
#include "uniconv.h"
|
||||
#include "except.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <alloca.h>
|
||||
#else
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
class BitStruct {
|
||||
|
||||
public:
|
||||
enum FIELD_TYPE
|
||||
{
|
||||
RAW,
|
||||
INTEGER,
|
||||
STRING,
|
||||
DATE14,
|
||||
DATE13,
|
||||
DATE16,
|
||||
};
|
||||
|
||||
private:
|
||||
class Field {
|
||||
public:
|
||||
Field():
|
||||
m_fieldType(FIELD_TYPE::INTEGER),
|
||||
m_offset(0),
|
||||
m_size(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Field(FIELD_TYPE fieldType, int offset, int size)
|
||||
{
|
||||
m_fieldType = fieldType;
|
||||
m_offset = offset;
|
||||
m_size = size;
|
||||
}
|
||||
|
||||
public:
|
||||
FIELD_TYPE m_fieldType;
|
||||
int m_offset;
|
||||
int m_size;
|
||||
};
|
||||
|
||||
typedef std::map<string, Field> FieldMap;
|
||||
|
||||
public:
|
||||
BitStruct(int bitSize = 0) :
|
||||
m_bits(bitSize)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
BitStruct(vector<unsigned char>& buf, int bitSize):
|
||||
m_bits(buf, bitSize)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Create(int bitSize = 0)
|
||||
{
|
||||
m_bits.Create(bitSize);
|
||||
}
|
||||
|
||||
void Attach(vector<unsigned char>& buf, int bitSize)
|
||||
{
|
||||
m_bits.Attach(buf, bitSize);
|
||||
}
|
||||
|
||||
void AddField(const char * fieldName, FIELD_TYPE fieldType, int fieldBitSize, int offset = -1 )
|
||||
{
|
||||
if (offset == -1)
|
||||
offset = currentFieldOffset;
|
||||
|
||||
m_fieldMap.insert(FieldMap::value_type(fieldName, Field(fieldType, offset, fieldBitSize)));
|
||||
|
||||
currentFieldOffset = offset + fieldBitSize;
|
||||
}
|
||||
|
||||
bool GetField(const char * fieldName, FIELD_TYPE * fieldType, int * fieldSize, int * fieldOffset) const
|
||||
{
|
||||
FieldMap::const_iterator iter = m_fieldMap.find(fieldName);
|
||||
|
||||
if (iter == m_fieldMap.end())
|
||||
return false;
|
||||
|
||||
*fieldType = iter->second.m_fieldType;
|
||||
*fieldSize = iter->second.m_size;
|
||||
*fieldOffset = iter->second.m_offset;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EnumFields(void **enumHandle, const char **fieldName, FIELD_TYPE * fieldType, int * fieldSize, int * offset)
|
||||
{
|
||||
FieldMap::iterator * pIter;
|
||||
static string name;
|
||||
|
||||
if (*enumHandle == NULL)
|
||||
{
|
||||
pIter = new FieldMap::iterator(m_fieldMap.begin());
|
||||
if (!pIter)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
pIter = (FieldMap::iterator *)(*enumHandle);
|
||||
|
||||
if (*pIter == m_fieldMap.end())
|
||||
{
|
||||
delete pIter;
|
||||
return false;
|
||||
}
|
||||
|
||||
name = (*pIter)->first;
|
||||
*fieldName = name.c_str();
|
||||
|
||||
*fieldType = (*pIter)->second.m_fieldType;
|
||||
*fieldSize = (*pIter)->second.m_size;
|
||||
*offset = (*pIter)->second.m_offset;
|
||||
|
||||
pIter->operator ++(); // *Iter++ does not work. Think why :)
|
||||
|
||||
*enumHandle = pIter;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Set(const char * fieldName, const void * buf, unsigned len)
|
||||
{
|
||||
int offset = 0, size = m_bits.GetSize();
|
||||
|
||||
if (fieldName)
|
||||
{
|
||||
FieldMap::iterator iter;
|
||||
iter = m_fieldMap.find(fieldName);
|
||||
if (iter == m_fieldMap.end())
|
||||
throw new LicensingException(STATUS_FIELD_NOT_FOUND);
|
||||
|
||||
offset = iter->second.m_offset;
|
||||
size = iter->second.m_size;
|
||||
}
|
||||
|
||||
m_bits.Seek(offset);
|
||||
|
||||
int bitlen = len << 3;
|
||||
|
||||
if (bitlen >= size)
|
||||
m_bits.Write(buf, size);
|
||||
else
|
||||
{
|
||||
int bits = size - bitlen;
|
||||
unsigned char * zeroes = (unsigned char *)_alloca((bits + 7) >> 3);
|
||||
memset(zeroes, 0, (bits + 7) >> 3);
|
||||
m_bits.Write(buf, bitlen);
|
||||
m_bits.Write(zeroes, bits);
|
||||
}
|
||||
}
|
||||
|
||||
void Set(const char * fieldName, const char * data)
|
||||
{
|
||||
Set(fieldName, data, (unsigned)strlen(data));
|
||||
}
|
||||
|
||||
void Set(const char * fieldName, int data)
|
||||
{
|
||||
#ifndef LICENSING_BIG_ENDIAN
|
||||
Set(fieldName, &data, sizeof(data));
|
||||
#else
|
||||
unsigned char buf[sizeof(int)] = { 0, 0, 0, 0 };
|
||||
|
||||
buf[0] = (unsigned char)(data & 0xFF);
|
||||
buf[1] = (unsigned char)((data >> 8) & 0xFF);
|
||||
buf[2] = (unsigned char)((data >> 16) & 0xFF);
|
||||
buf[3] = (unsigned char)((data >> 24) & 0xFF);
|
||||
|
||||
Set(fieldName, buf, sizeof(data));
|
||||
#endif
|
||||
}
|
||||
|
||||
void Set(const char * fieldName, int year, int month, int day)
|
||||
{
|
||||
FieldMap::iterator iter;
|
||||
iter = m_fieldMap.find(fieldName);
|
||||
if (iter == m_fieldMap.end() )
|
||||
throw new LicensingException(STATUS_FIELD_NOT_FOUND);
|
||||
|
||||
int date;
|
||||
|
||||
switch (iter->second.m_fieldType)
|
||||
{
|
||||
case FIELD_TYPE_DATE13:
|
||||
date = PackDate13(year, month, day);
|
||||
break;
|
||||
|
||||
case FIELD_TYPE_DATE14:
|
||||
date = PackDate14(year, month, day);
|
||||
break;
|
||||
|
||||
case FIELD_TYPE_DATE16:
|
||||
date = PackDate16(year, month, day);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new LicensingException(STATUS_INVALID_PARAM, "A data value is being set to a non-date field");
|
||||
}
|
||||
|
||||
Set(fieldName, date);
|
||||
}
|
||||
|
||||
void Get(const char * dataField, void * buf, int * len)
|
||||
{
|
||||
if (dataField)
|
||||
{
|
||||
FieldMap::const_iterator iter;
|
||||
|
||||
iter = m_fieldMap.find(dataField);
|
||||
if ( iter == m_fieldMap.end() )
|
||||
throw new LicensingException(STATUS_FIELD_NOT_FOUND);
|
||||
|
||||
if ( *len < ( iter->second.m_size + 7 ) >> 3 )
|
||||
throw new LicensingException(STATUS_BUFFER_TOO_SMALL);
|
||||
|
||||
m_bits.Seek(iter->second.m_offset);
|
||||
m_bits.Read(buf, iter->second.m_size);
|
||||
|
||||
*len = (iter->second.m_size + 7) >> 3;
|
||||
} else
|
||||
{
|
||||
int validationDataLen = (m_bits.GetSize() + 7) >> 3;
|
||||
|
||||
if (*len < validationDataLen)
|
||||
{
|
||||
*len = validationDataLen;
|
||||
throw new LicensingException(STATUS_BUFFER_TOO_SMALL);
|
||||
}
|
||||
|
||||
memcpy(buf, m_bits.GetBuffer(), validationDataLen);
|
||||
*len = validationDataLen;
|
||||
}
|
||||
}
|
||||
|
||||
int GetInt(const char * dataField)
|
||||
{
|
||||
FieldMap::const_iterator iter;
|
||||
|
||||
iter = m_fieldMap.find(dataField);
|
||||
if ( iter == m_fieldMap.end() )
|
||||
throw new LicensingException(STATUS_FIELD_NOT_FOUND);
|
||||
|
||||
unsigned char buf[sizeof(int)] = {0, 0, 0, 0};
|
||||
|
||||
if ( sizeof(buf) < ( iter->second.m_size + 7 ) >> 3 )
|
||||
throw new LicensingException(STATUS_BUFFER_TOO_SMALL);
|
||||
|
||||
m_bits.Seek(iter->second.m_offset);
|
||||
m_bits.Read(buf, iter->second.m_size);
|
||||
|
||||
#ifndef LICENSING_BIG_ENDIAN
|
||||
return *(int *)buf;
|
||||
#else
|
||||
return ((int)buf[3] << 24) | ((int)buf[2] << 16) | ((int)buf[1] << 8) | (int)buf[0];
|
||||
#endif
|
||||
}
|
||||
|
||||
void GetDate(const char * dataField, int * year, int * month, int * day)
|
||||
{
|
||||
FieldMap::const_iterator iter;
|
||||
|
||||
iter = m_fieldMap.find(dataField);
|
||||
if ( iter == m_fieldMap.end() )
|
||||
throw new LicensingException(STATUS_FIELD_NOT_FOUND);
|
||||
|
||||
unsigned short packedDate = (unsigned short)GetInt(dataField);
|
||||
|
||||
switch (iter->second.m_fieldType)
|
||||
{
|
||||
case FIELD_TYPE_DATE13:
|
||||
UnpackDate13(packedDate, year, month, day);
|
||||
break;
|
||||
|
||||
case FIELD_TYPE_DATE14:
|
||||
UnpackDate14(packedDate, year, month, day);
|
||||
break;
|
||||
|
||||
case FIELD_TYPE_DATE16:
|
||||
UnpackDate16(packedDate, year, month, day);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new LicensingException(STATUS_INVALID_PARAM, "An attempt was made to query a date from a non-date field");
|
||||
}
|
||||
}
|
||||
|
||||
void * GetBuffer(int * sizeInBits = NULL)
|
||||
{
|
||||
return m_bits.GetBuffer(sizeInBits);
|
||||
}
|
||||
|
||||
BitStream& GetBitStream()
|
||||
{
|
||||
return m_bits;
|
||||
}
|
||||
|
||||
int GetCurrentFieldOffset()
|
||||
{
|
||||
return currentFieldOffset;
|
||||
}
|
||||
|
||||
void ResetFieldOffset()
|
||||
{
|
||||
currentFieldOffset = 0;
|
||||
}
|
||||
|
||||
int GetSize()
|
||||
{
|
||||
return m_bits.GetSize();
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned short PackDate13(int year, int month, int day)
|
||||
{
|
||||
if (year < 2012 || year > 2027)
|
||||
throw new LicensingException(STATUS_INVALID_PARAM, "Invalid year for a 13-bit date. Allowed values are 2012-2027");
|
||||
|
||||
return (unsigned short)(((month - 1) << 9) | ((day - 1) << 4) | (year - 2012));
|
||||
}
|
||||
|
||||
void UnpackDate13(unsigned short packedDate, int * year, int * month, int * day)
|
||||
{
|
||||
*year = 2012 + (packedDate & 0x0F);
|
||||
*month = 1 + (packedDate >> 9);
|
||||
*day = 1 + ((packedDate >> 4) & 0x1F);
|
||||
}
|
||||
|
||||
unsigned short PackDate14(int year, int month, int day)
|
||||
{
|
||||
if (year < 2010 || year > 2041)
|
||||
throw new LicensingException(STATUS_INVALID_PARAM, "Invalid year for a 14-bit date. Allowed values are 2010-2041");
|
||||
|
||||
return (unsigned short)(((month - 1) << 10) | ((day - 1) << 5) | (year - 2010));
|
||||
}
|
||||
|
||||
void UnpackDate14(unsigned short packedDate, int * year, int * month, int * day)
|
||||
{
|
||||
*year = 2010 + (packedDate & 0x1F);
|
||||
*month = 1 + (packedDate >> 10);
|
||||
*day = 1 + ((packedDate >> 5) & 0x1F);
|
||||
}
|
||||
|
||||
unsigned short PackDate16(int year, int month, int day)
|
||||
{
|
||||
if (year < 2000 || year > 2127)
|
||||
throw new LicensingException(STATUS_INVALID_PARAM, "Invalid year for a 16-bit date. Allowed values are 2010-2127");
|
||||
|
||||
return (unsigned short)(((year - 2000) << 9) | (month << 5) | day);
|
||||
}
|
||||
|
||||
void UnpackDate16(unsigned short packedDate, int * year, int * month, int * day)
|
||||
{
|
||||
*year = 2000 + (packedDate >> 9);
|
||||
*month = (packedDate & 0x01FF) >> 5;
|
||||
*day = packedDate & 0x001F;
|
||||
}
|
||||
|
||||
FieldMap m_fieldMap;
|
||||
BitStream m_bits;
|
||||
int currentFieldOffset;
|
||||
};
|
||||
2
core/anslicensing/certificate.cpp
Normal file
2
core/anslicensing/certificate.cpp
Normal file
@@ -0,0 +1,2 @@
|
||||
#include "precomp.h"
|
||||
#include "certificate.h"
|
||||
451
core/anslicensing/certificate.h
Normal file
451
core/anslicensing/certificate.h
Normal 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
|
||||
69
core/anslicensing/crc32.cpp
Normal file
69
core/anslicensing/crc32.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
#include "precomp.h"
|
||||
|
||||
#include "crc32.h"
|
||||
|
||||
const unsigned int Crc32::crcTable[256] =
|
||||
{
|
||||
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419,
|
||||
0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4,
|
||||
0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07,
|
||||
0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
|
||||
0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856,
|
||||
0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
|
||||
0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
|
||||
0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
|
||||
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3,
|
||||
0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A,
|
||||
0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599,
|
||||
0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
|
||||
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190,
|
||||
0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F,
|
||||
0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E,
|
||||
0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
|
||||
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED,
|
||||
0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
|
||||
0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3,
|
||||
0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
|
||||
0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A,
|
||||
0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5,
|
||||
0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010,
|
||||
0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
|
||||
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17,
|
||||
0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6,
|
||||
0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615,
|
||||
0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
|
||||
0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344,
|
||||
0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
|
||||
0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A,
|
||||
0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
|
||||
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1,
|
||||
0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C,
|
||||
0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF,
|
||||
0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
|
||||
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE,
|
||||
0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31,
|
||||
0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C,
|
||||
0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
|
||||
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B,
|
||||
0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
|
||||
0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1,
|
||||
0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
|
||||
0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278,
|
||||
0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7,
|
||||
0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66,
|
||||
0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
|
||||
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605,
|
||||
0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8,
|
||||
0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B,
|
||||
0x2D02EF8D
|
||||
};
|
||||
|
||||
unsigned int Crc32::Compute(const unsigned char * buffer, int count)
|
||||
{
|
||||
unsigned int crc = 0xFFFFFFFF;
|
||||
|
||||
while (count--)
|
||||
crc = (crc >> 8) ^ crcTable[(crc ^ *buffer++) & 0xFF];
|
||||
|
||||
return crc ^ 0xFFFFFFFF;
|
||||
}
|
||||
10
core/anslicensing/crc32.h
Normal file
10
core/anslicensing/crc32.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
class Crc32
|
||||
{
|
||||
public:
|
||||
static unsigned int Compute(const unsigned char * buffer, int count);
|
||||
|
||||
private:
|
||||
static const unsigned int crcTable[256];
|
||||
};
|
||||
2616
core/anslicensing/cwrap.cpp
Normal file
2616
core/anslicensing/cwrap.cpp
Normal file
File diff suppressed because it is too large
Load Diff
211
core/anslicensing/download.cpp
Normal file
211
core/anslicensing/download.cpp
Normal file
@@ -0,0 +1,211 @@
|
||||
#include "precomp.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "download.h"
|
||||
#include "uniconv.h"
|
||||
#include "except.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winhttp.h>
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#include <curl/curl.h>
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
class CurlWriteBuffer
|
||||
{
|
||||
public:
|
||||
CurlWriteBuffer(void * buffer, size_t size)
|
||||
{
|
||||
this->buffer = (char *)buffer;
|
||||
this->size = size;
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
int Append(void * buffer, size_t size)
|
||||
{
|
||||
if (this->offset + size > this->size)
|
||||
size = this->size - offset;
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
memcpy(this->buffer + offset, buffer, size);
|
||||
offset += size;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static size_t
|
||||
Callback(void *contents, size_t size, size_t nmemb, void *userp)
|
||||
{
|
||||
return ((CurlWriteBuffer *)userp)->Append(contents, size * nmemb);
|
||||
}
|
||||
|
||||
size_t offset;
|
||||
size_t size;
|
||||
char * buffer;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
void UrlDownloadToString(const char * url, char * buffer, int * len)
|
||||
{
|
||||
#ifndef LICENSING_NO_NETWORKING
|
||||
#ifdef _WIN32
|
||||
HRESULT result = ERROR_SUCCESS;
|
||||
|
||||
URL_COMPONENTS urlComponents;
|
||||
|
||||
do {
|
||||
ZeroMemory(&urlComponents, sizeof(urlComponents));
|
||||
urlComponents.dwStructSize = sizeof(urlComponents);
|
||||
|
||||
urlComponents.dwHostNameLength = (DWORD)-1;
|
||||
urlComponents.dwUrlPathLength = (DWORD)-1;
|
||||
|
||||
auto urlw = s2w(url);
|
||||
|
||||
if (!WinHttpCrackUrl(urlw.c_str(), urlw.size(), 0L, &urlComponents))
|
||||
{
|
||||
result = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
wstring hostName(urlComponents.lpszHostName, urlComponents.dwHostNameLength);
|
||||
|
||||
unique_ptr<VOID, decltype(&WinHttpCloseHandle)> internet_ptr(WinHttpOpen(L"ANSCENTER Licensing SDK", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0L), WinHttpCloseHandle);
|
||||
if (!internet_ptr)
|
||||
{
|
||||
result = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
unique_ptr<VOID, decltype(&WinHttpCloseHandle)> connection_ptr(WinHttpConnect(internet_ptr.get(), hostName.c_str(), urlComponents.nPort, 0L), WinHttpCloseHandle);
|
||||
if (connection_ptr == NULL)
|
||||
{
|
||||
result = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
wstring objectPath(urlComponents.lpszUrlPath, urlComponents.dwUrlPathLength);
|
||||
|
||||
DWORD requestFlags = WINHTTP_FLAG_BYPASS_PROXY_CACHE;
|
||||
if (urlComponents.nScheme == INTERNET_SCHEME_HTTPS)
|
||||
requestFlags |= WINHTTP_FLAG_SECURE;
|
||||
|
||||
unique_ptr<VOID, decltype(&WinHttpCloseHandle)> request_ptr(WinHttpOpenRequest(connection_ptr.get(), L"GET", objectPath.c_str(), NULL, NULL, NULL, requestFlags), WinHttpCloseHandle);
|
||||
if (!request_ptr)
|
||||
{
|
||||
result = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
if (!WinHttpSendRequest(request_ptr.get(), NULL, 0L, NULL, 0, 0L, NULL))
|
||||
{
|
||||
result = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
if (!WinHttpReceiveResponse(request_ptr.get(), NULL))
|
||||
{
|
||||
result = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
DWORD status;
|
||||
DWORD statusSize = sizeof(DWORD);
|
||||
|
||||
if (!WinHttpQueryHeaders(request_ptr.get(), WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, WINHTTP_HEADER_NAME_BY_INDEX, &status, &statusSize, WINHTTP_NO_HEADER_INDEX))
|
||||
{
|
||||
result = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
if (status != HTTP_STATUS_OK)
|
||||
{
|
||||
WCHAR buffer[1024];
|
||||
DWORD bufferSize = 1024;
|
||||
|
||||
if (!WinHttpQueryHeaders(request_ptr.get(), WINHTTP_QUERY_STATUS_TEXT, WINHTTP_HEADER_NAME_BY_INDEX, buffer, &bufferSize, WINHTTP_NO_HEADER_INDEX))
|
||||
{
|
||||
result = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
result = ERROR_WINHTTP_INVALID_URL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (status != HTTP_STATUS_OK)
|
||||
{
|
||||
result = GetLastError();
|
||||
break;
|
||||
}
|
||||
|
||||
DWORD offset = 0, count;
|
||||
char lbuf[0x100];
|
||||
|
||||
do {
|
||||
if (WinHttpReadData(request_ptr.get(), lbuf, 0x100, &count))
|
||||
{
|
||||
if (count == 0)
|
||||
{
|
||||
*len = offset;
|
||||
break;
|
||||
}
|
||||
|
||||
if (offset + count > *len)
|
||||
{
|
||||
result = ERROR_INSUFFICIENT_BUFFER;
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(buffer + offset, lbuf, count);
|
||||
offset += count;
|
||||
} else
|
||||
{
|
||||
result = GetLastError();
|
||||
break;
|
||||
}
|
||||
} while (true);
|
||||
} while (false);
|
||||
|
||||
if (result != ERROR_SUCCESS)
|
||||
throw new LicensingException(result, "networking error while downloading url contents");
|
||||
#else
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
|
||||
if ((curl = curl_easy_init()) == NULL)
|
||||
throw new LicensingException(STATUS_NET_ERROR, "cURL initalization failed");
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
|
||||
CurlWriteBuffer curlBuffer(buffer, *len);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteBuffer::Callback);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &curlBuffer);
|
||||
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
if(res != CURLE_OK)
|
||||
{
|
||||
curl_easy_cleanup(curl);
|
||||
throw new LicensingException(STATUS_NET_ERROR, curl_easy_strerror(res));
|
||||
}
|
||||
|
||||
*len = curlBuffer.offset;
|
||||
|
||||
curl_easy_cleanup(curl);
|
||||
#endif
|
||||
#else // !LICENSING_NO_NETWORKING
|
||||
throw new LicensingException(STATUS_GENERIC_ERROR, "networking support not built in");
|
||||
#endif
|
||||
}
|
||||
6
core/anslicensing/download.h
Normal file
6
core/anslicensing/download.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef __DOWNLOAD_H
|
||||
#define __DOWNLOAD_H
|
||||
|
||||
void UrlDownloadToString(const char * url, char * buffer, int * len);
|
||||
|
||||
#endif
|
||||
1473
core/anslicensing/ec2m.cpp
Normal file
1473
core/anslicensing/ec2m.cpp
Normal file
File diff suppressed because it is too large
Load Diff
256
core/anslicensing/ec2m.h
Normal file
256
core/anslicensing/ec2m.h
Normal file
@@ -0,0 +1,256 @@
|
||||
// elliptic curves over GF(2^(L*K))
|
||||
|
||||
#pragma once
|
||||
|
||||
#define MAXL 16
|
||||
#define MAXK 193
|
||||
|
||||
class field;
|
||||
class field_element;
|
||||
class curve;
|
||||
class full_curve_parameter;
|
||||
|
||||
class small_field
|
||||
{
|
||||
friend class field;
|
||||
#if MAXL > 16 // assumes that unsigned short is at least 16 bits
|
||||
typedef unsigned lunit;
|
||||
#else
|
||||
#if MAXL > 8
|
||||
typedef unsigned short lunit;
|
||||
#else
|
||||
typedef unsigned char lunit;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// construction
|
||||
public:
|
||||
small_field( unsigned L, unsigned root );
|
||||
~small_field();
|
||||
|
||||
// methods
|
||||
public:
|
||||
unsigned * curve_order();
|
||||
|
||||
// properties
|
||||
public:
|
||||
lunit * const alog; // index range is [0..(BASE-2)]
|
||||
lunit * const log; // index range is [1..(BASE-1)], but log[0] is set to (BASE-1)
|
||||
const unsigned L, BASE, BASE_M1;
|
||||
};
|
||||
|
||||
// elements are polynomials with coefficients in small_field
|
||||
class field : public small_field
|
||||
{
|
||||
friend class curve;
|
||||
friend class field_element;
|
||||
friend class full_curve_parameter;
|
||||
|
||||
// construction
|
||||
public:
|
||||
field( class full_curve_parameter & a );
|
||||
virtual unsigned rand( unsigned base );
|
||||
|
||||
// methods
|
||||
private:
|
||||
typedef unsigned poly[ 2 * MAXK ];
|
||||
|
||||
static void add( const poly a, const poly b, poly c );
|
||||
static void copy ( const poly a, poly b );
|
||||
static int equal( const poly a, const poly b );
|
||||
void div( poly a, unsigned b );
|
||||
void set_random( poly a );
|
||||
int set_K( unsigned K, unsigned T );
|
||||
void reduce( poly a );
|
||||
void mul( const poly a, const poly b, poly c );
|
||||
void square( const poly a, poly b );
|
||||
void inverse( const poly a, poly b );
|
||||
int trace( const poly a );
|
||||
int slow_trace( const poly a );
|
||||
void quad_solve( const poly a, poly b );
|
||||
void sqrt( const poly a, poly b );
|
||||
void addmul( poly a, unsigned alpha, unsigned j, const poly b );
|
||||
|
||||
friend field_element sqrt( const field_element x );
|
||||
void unpack( const bigint & x, poly a );
|
||||
bigint pack( const poly a );
|
||||
|
||||
// properties
|
||||
private:
|
||||
const unsigned M, K, T;
|
||||
unsigned prng;
|
||||
poly nzt; // element with non-zero trace
|
||||
poly tm; // trace mask ( trace(x) is number of bits in x & tm )
|
||||
};
|
||||
|
||||
class field_element
|
||||
{
|
||||
friend class field;
|
||||
friend class curve;
|
||||
friend class point;
|
||||
friend field_element sqrt( const field_element x );
|
||||
|
||||
// construction
|
||||
public:
|
||||
field_element( const field_element & x );
|
||||
field_element( field * F );
|
||||
field_element();
|
||||
|
||||
// methods
|
||||
public:
|
||||
int operator == ( const field_element & x ) const;
|
||||
int operator == ( unsigned x ) const;
|
||||
field_element operator + ( const field_element & x ) const;
|
||||
field_element operator * ( const field_element & x ) const;
|
||||
field_element operator / ( const field_element & x ) const;
|
||||
field_element & operator = ( const field_element & x );
|
||||
|
||||
// properties
|
||||
private:
|
||||
field * f;
|
||||
field::poly v;
|
||||
};
|
||||
|
||||
class point
|
||||
{
|
||||
friend class curve;
|
||||
friend class ec_crypt;
|
||||
friend point operator * ( const bigint & k, const point & P );
|
||||
|
||||
// construction
|
||||
public:
|
||||
point();
|
||||
point( const point & P );
|
||||
point( curve * C );
|
||||
|
||||
// methods
|
||||
public:
|
||||
point & operator = ( const point & P );
|
||||
point operator + ( const point & P ) const;
|
||||
point operator - ( const point & P ) const;
|
||||
|
||||
// properties
|
||||
private:
|
||||
curve * c;
|
||||
field_element x, y;
|
||||
};
|
||||
|
||||
struct curve_parameter
|
||||
{
|
||||
unsigned L;
|
||||
unsigned K;
|
||||
unsigned T;
|
||||
unsigned root;
|
||||
unsigned b;
|
||||
unsigned nso;
|
||||
unsigned ntf;
|
||||
};
|
||||
|
||||
class full_curve_parameter : public curve_parameter
|
||||
{
|
||||
// construction
|
||||
public:
|
||||
full_curve_parameter( const curve_parameter & bp );
|
||||
|
||||
// properties
|
||||
public:
|
||||
bigint tm, p0, P0;
|
||||
};
|
||||
|
||||
class curve : public field
|
||||
{
|
||||
friend class curve_factory;
|
||||
friend class point;
|
||||
friend point operator * ( const bigint & k, const point & P );
|
||||
|
||||
// construction
|
||||
public:
|
||||
curve( full_curve_parameter & a );
|
||||
|
||||
// methods
|
||||
public:
|
||||
point random_point();
|
||||
static bigint pack( const point & P );
|
||||
point unpack( const bigint & X );
|
||||
static bigint to_vlong( const point & P );
|
||||
|
||||
// methods
|
||||
private:
|
||||
void add( const point & P, const point & Q, point & R );
|
||||
void sub( const point & P, const point & Q, point & R );
|
||||
void mul( const point & P, const bigint & x, point & Q );
|
||||
int calc_y( point & R, unsigned ybit=0 );
|
||||
static int MOV( unsigned B, const bigint & q, const bigint & r );
|
||||
static bigint small_lucas( bigint P, bigint Z, unsigned ik );
|
||||
static unsigned ybit( const field_element & x );
|
||||
static field_element sq( const field_element & x );
|
||||
|
||||
// properties
|
||||
public:
|
||||
point PP; // point with prime order
|
||||
bigint p; // prime order of P
|
||||
|
||||
// properties
|
||||
private:
|
||||
field_element b;
|
||||
};
|
||||
|
||||
class curve_factory // Used for calculating curve_parameter but in practice
|
||||
// use pre-calculated table ncdata.hpp or equivalent
|
||||
{
|
||||
// construction
|
||||
public:
|
||||
curve_factory( unsigned L ); // can take a long time
|
||||
~curve_factory();
|
||||
|
||||
// methods
|
||||
public:
|
||||
int find( unsigned K, curve_parameter & result );
|
||||
|
||||
// properties
|
||||
private:
|
||||
unsigned L;
|
||||
unsigned root;
|
||||
unsigned so_min;
|
||||
unsigned so_max;
|
||||
unsigned *so_set;
|
||||
bigint comp;
|
||||
};
|
||||
|
||||
struct bigint_pair
|
||||
{
|
||||
bigint r;
|
||||
bigint s;
|
||||
};
|
||||
|
||||
class ECC_BASE : private curve
|
||||
{
|
||||
// construction
|
||||
public:
|
||||
ECC_BASE( full_curve_parameter & a );
|
||||
~ECC_BASE();
|
||||
|
||||
// methods
|
||||
public:
|
||||
virtual unsigned rand( unsigned base );
|
||||
|
||||
bigint create_private_key();
|
||||
bigint create_public_key( const bigint & private_key );
|
||||
|
||||
bigint encrypt( const bigint & public_key, bigint & message );
|
||||
bigint decrypt( const bigint & private_key, const bigint & message );
|
||||
|
||||
bigint_pair schnorr_sign( const bigint & msg, const bigint & private_key, bigint (*hash)(const bigint &, const bigint &) = 0, unsigned hashbits = 1 );
|
||||
bool schnorr_verify( const bigint & msg, const bigint_pair & sig, const bigint & public_key, bigint (*hash)(const bigint &, const bigint &) = 0, unsigned hashbits = 1 );
|
||||
|
||||
bigint_pair dsa_sign( const bigint & msg, const bigint & private_key, bigint (*hash)(const bigint &, const bigint &));
|
||||
bool dsa_verify( const bigint & msg, const bigint_pair & sig, const bigint & public_key, bigint (*hash)(const bigint &, const bigint &));
|
||||
|
||||
// properties
|
||||
public:
|
||||
const unsigned bits; // number of bits in prime order
|
||||
#ifdef WIN32
|
||||
HCRYPTPROV m_cryptProv;
|
||||
#endif
|
||||
};
|
||||
|
||||
596
core/anslicensing/ecc.cpp
Normal file
596
core/anslicensing/ecc.cpp
Normal file
@@ -0,0 +1,596 @@
|
||||
//
|
||||
// Copyright (c) 2014 ANSCENTER. All rights reserved.
|
||||
//
|
||||
|
||||
#include "precomp.h"
|
||||
#include "ecc.h"
|
||||
#include "bigint.h"
|
||||
#include "ec2m.h"
|
||||
#include "sha1.h"
|
||||
#include "except.h"
|
||||
#include "base64.h"
|
||||
#include "uniconv.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <alloca.h>
|
||||
#else
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
namespace ECC {
|
||||
|
||||
#if 0
|
||||
void biPrint( bigint & data )
|
||||
{
|
||||
int n;
|
||||
unsigned * u;
|
||||
|
||||
n = ( data.bits() + 31 ) / 32;
|
||||
|
||||
u = new unsigned[ n ];
|
||||
|
||||
data.store( u, n );
|
||||
|
||||
printf( "%d ", data.bits() );
|
||||
|
||||
for ( int i = n - 1; i >= 0; i-- )
|
||||
{
|
||||
printf( "%08X ", u[i] );
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
delete [] u;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const curve_parameter eccCurveTable[ 10 ] = { { 9, 7, 1, 17, 43, 48, 1},
|
||||
{ 12, 7, 1, 83, 2049, 10, 1 },
|
||||
{ 13, 7, 1, 27, 124, 52, 1},
|
||||
{ 15, 7, 1, 3, 977, 110, 1},
|
||||
{ 16, 7, 1, 45, 2902, 6, 1},
|
||||
{ 10, 11, 2, 9, 139, 34, 1},
|
||||
{ 12, 11, 2, 83, 2083, 66, 1},
|
||||
{ 13, 11, 2, 27, 773, 48, 1},
|
||||
{ 14, 11, 2, 43, 146, 40, 1},
|
||||
{ 10, 17, 3, 9, 48, 28, 1} };
|
||||
|
||||
static void UintArrayToByteArray(unsigned * srcArray, int bitCount, unsigned char * dstArray)
|
||||
{
|
||||
int dstLength = ((int)bitCount + 7) >> 3;
|
||||
int srcLength = (dstLength + 3) >> 2;
|
||||
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
unsigned currentUint;
|
||||
|
||||
if (dstLength > 3)
|
||||
{
|
||||
while (i < dstLength - 3)
|
||||
{
|
||||
currentUint = (j < srcLength) ? srcArray[j] : 0;
|
||||
|
||||
dstArray[i + 3] = (unsigned char)(currentUint >> 24);
|
||||
dstArray[i + 2] = (unsigned char)((currentUint >> 16) & 0xFF);
|
||||
dstArray[i + 1] = (unsigned char)((currentUint >> 8) & 0xFF);
|
||||
dstArray[i] = (unsigned char)(currentUint & 0xFF);
|
||||
i += 4;
|
||||
j += 1;
|
||||
}
|
||||
}
|
||||
|
||||
currentUint = (j < srcLength) ? srcArray[j] : 0;
|
||||
if (i < dstLength) dstArray[i] = (unsigned char)(currentUint & 0xFF); i++;
|
||||
if (i < dstLength) dstArray[i] = (unsigned char)((currentUint >> 8) & 0xFF); i++;
|
||||
if (i < dstLength) dstArray[i] = (unsigned char)((currentUint >> 16) & 0xFF);
|
||||
}
|
||||
|
||||
static void ByteArrayToUintArray(unsigned char * srcArray, int srcLength, unsigned * dstArray)
|
||||
{
|
||||
int roundedLen = (srcLength + sizeof(unsigned) - 1) / sizeof(unsigned);
|
||||
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
while (i < roundedLen - 1)
|
||||
{
|
||||
dstArray[i] = (unsigned)(((unsigned)srcArray[j + 3] << 24) | ((unsigned)srcArray[j + 2] << 16) | ((unsigned)srcArray[j + 1] << 8) | (unsigned)srcArray[j]);
|
||||
i += 1;
|
||||
j += 4;
|
||||
}
|
||||
|
||||
dstArray[roundedLen - 1] = 0;
|
||||
|
||||
if (j < srcLength) dstArray[roundedLen - 1] = (unsigned)(srcArray[j]); j++;
|
||||
if (j < srcLength) dstArray[roundedLen - 1] |= (unsigned)((unsigned)srcArray[j] << 8); j++;
|
||||
if (j < srcLength) dstArray[roundedLen - 1] |= (unsigned)((unsigned)srcArray[j] << 16); j++;
|
||||
if (j < srcLength) dstArray[roundedLen - 1] |= (unsigned)((unsigned)srcArray[j] << 24);
|
||||
}
|
||||
|
||||
class KeyImpl {
|
||||
friend class Key;
|
||||
friend class SignerImpl;
|
||||
friend class VerifierImpl;
|
||||
|
||||
friend void GenerateKeyPair(KEY_TYPE keyType, Key **privKey, Key **pubKey);
|
||||
|
||||
private:
|
||||
KeyImpl()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
KeyImpl(const void * keyBuf, int bufLen, KEY_TYPE keyType = ECC)
|
||||
{
|
||||
Load(keyBuf, bufLen, keyType);
|
||||
}
|
||||
|
||||
KeyImpl(const char * base64Key, KEY_TYPE keyType = ECC)
|
||||
{
|
||||
|
||||
BASE64 base64;
|
||||
|
||||
int len;
|
||||
|
||||
auto buf = base64.decode(base64Key, strlen(base64Key), &len);
|
||||
|
||||
if (buf.empty())
|
||||
throw new LicensingException(STATUS_INVALID_PARAM, "invalid base64 key");
|
||||
|
||||
Load(buf.data(), len, keyType);
|
||||
}
|
||||
|
||||
void Load(const void * keyBuf, int bufLen, KEY_TYPE keyType = ECC)
|
||||
{
|
||||
if (keyType == ECC)
|
||||
{
|
||||
unsigned char * keyBytes = (unsigned char *)keyBuf;
|
||||
|
||||
if ((keyBytes[0] >> 5) != 0)
|
||||
throw new LicensingException(STATUS_INVALID_PARAM, "unsupported key version");
|
||||
|
||||
if (keyBytes[1] + 2 != bufLen)
|
||||
throw new LicensingException(STATUS_INVALID_PARAM, "invalid key size");
|
||||
|
||||
isPrivate = ((keyBytes[0] & 0x10) != 0);
|
||||
SetKeyType((KEY_TYPE)(keyBytes[0] & 0x0F));
|
||||
|
||||
int roundedLen = sizeof(unsigned) * ((bufLen - 2 + sizeof(unsigned) - 1) / sizeof(unsigned));
|
||||
unsigned * buf = (unsigned *)calloc(roundedLen, 1);
|
||||
if (!buf) return;
|
||||
|
||||
ByteArrayToUintArray(keyBytes + 2, bufLen - 2, buf);
|
||||
|
||||
m_key.load(buf, (unsigned)(roundedLen / sizeof(unsigned)));
|
||||
|
||||
free(buf);
|
||||
} else
|
||||
{
|
||||
SetKeyType(keyType);
|
||||
|
||||
int roundedLen = sizeof(unsigned) * ((bufLen + sizeof(unsigned) - 1) / sizeof(unsigned));
|
||||
unsigned * buf = (unsigned *)calloc(roundedLen, 1);
|
||||
if (!buf) return;
|
||||
|
||||
ByteArrayToUintArray((unsigned char *)keyBuf, bufLen, buf);
|
||||
|
||||
m_key.load(buf, (unsigned)(roundedLen / sizeof(unsigned)));
|
||||
|
||||
free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
bool Store(void * buf, int * bufLen)
|
||||
{
|
||||
unsigned char * keyBytes = (unsigned char *)buf;
|
||||
|
||||
int numBits = m_key.bits();
|
||||
|
||||
int numBytes = (numBits + 7) >> 3;
|
||||
|
||||
if (*bufLen < 2 + numBytes)
|
||||
return false;
|
||||
|
||||
keyBytes[0] &= 0x1F; // set first 3 bits to 0 - version 1
|
||||
if (isPrivate) keyBytes[0] |= 0x10; else keyBytes[0] &= 0xEF; // the 4th bit is 1 if it's a private key
|
||||
keyBytes[0] = (keyBytes[0] & 0xF0) | (((unsigned char)m_keyType) & 0x0F); // the next 4 bits from 1st byte are the key type
|
||||
keyBytes[1] = numBytes; // the second byte specifies the key size
|
||||
|
||||
int numUints = (numBytes + sizeof(unsigned) - 1) / sizeof(unsigned);
|
||||
unsigned * temp = (unsigned int *)_alloca(numUints * sizeof(unsigned));
|
||||
m_key.store(temp, numUints);
|
||||
|
||||
UintArrayToByteArray(temp, numBits, keyBytes + 2);
|
||||
|
||||
*bufLen = numBytes + 2;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetKeyType(KEY_TYPE keyType)
|
||||
{
|
||||
m_keyType = keyType;
|
||||
switch (keyType)
|
||||
{
|
||||
case ECC_54: m_keySize = 54;break;
|
||||
case ECC_73: m_keySize = 73;break;
|
||||
case ECC_79: m_keySize = 79;break;
|
||||
case ECC_91: m_keySize = 91;break;
|
||||
case ECC_97: m_keySize = 97;break;
|
||||
case ECC_100: m_keySize = 100;break;
|
||||
case ECC_120: m_keySize = 120;break;
|
||||
case ECC_131: m_keySize = 131;break;
|
||||
case ECC_141: m_keySize = 141;break;
|
||||
case ECC_161: m_keySize = 161;break;
|
||||
}
|
||||
}
|
||||
|
||||
KEY_TYPE GetKeyType()
|
||||
{
|
||||
return m_keyType;
|
||||
}
|
||||
|
||||
KEY_TYPE m_keyType;
|
||||
int m_keySize;
|
||||
bigint m_key;
|
||||
bool isPrivate;
|
||||
};
|
||||
|
||||
class SignerImpl {
|
||||
public:
|
||||
SignerImpl()
|
||||
{
|
||||
m_hashBits = 0; // thus select ECDSA as the signing algorithm
|
||||
}
|
||||
|
||||
~SignerImpl()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static bigint Hash(const bigint & x, const bigint & p)
|
||||
{
|
||||
unsigned int n = ( x.bits() + ( ( sizeof(unsigned) << 3 ) - 1 ) ) / ( sizeof( unsigned ) << 3 );
|
||||
unsigned int * a = (unsigned *)_alloca(n * sizeof(unsigned));
|
||||
unsigned int h[ 5 ];
|
||||
|
||||
x.store(a, n);
|
||||
|
||||
SHA1 sha;
|
||||
|
||||
#ifndef LICENSING_BIG_ENDIAN
|
||||
sha.Update((unsigned char *)a, (x.bits() + 7) >> 3);
|
||||
#else
|
||||
int nb = (x.bits() + 7) >> 3;
|
||||
unsigned char * buf = (unsigned char *)_alloca(nb);
|
||||
UintArrayToByteArray(a, x.bits(), buf);
|
||||
sha.Update(buf, nb);
|
||||
#endif
|
||||
|
||||
sha.Final();
|
||||
|
||||
#ifndef LICENSING_BIG_ENDIAN
|
||||
sha.GetHash((unsigned char *)h);
|
||||
#else
|
||||
unsigned char bh[20];
|
||||
sha.GetHash(bh);
|
||||
ByteArrayToUintArray(bh, 20, h);
|
||||
#endif
|
||||
|
||||
bigint r;
|
||||
r.load( h, 5 );
|
||||
|
||||
return r % p;
|
||||
}
|
||||
|
||||
void SetHashSize(int hashBits)
|
||||
{
|
||||
m_hashBits = hashBits;
|
||||
}
|
||||
|
||||
void SetPrivateKey(const KeyImpl & privKey)
|
||||
{
|
||||
m_privateKey = privKey;
|
||||
}
|
||||
|
||||
void Sign(const void * msg, int msgLen, void * sigBuf, int * sigLen, int * sigLenBits)
|
||||
{
|
||||
full_curve_parameter param(eccCurveTable[ m_privateKey.m_keyType ]);
|
||||
ECC_BASE ecc(param);
|
||||
bigint message;
|
||||
bigint temp;
|
||||
bigint_pair signature;
|
||||
|
||||
*sigLenBits = (m_hashBits && m_hashBits < m_privateKey.m_keySize) ? m_hashBits + m_privateKey.m_keySize : m_privateKey.m_keySize << 1;
|
||||
*sigLen = (*sigLenBits + 7) >> 3;
|
||||
|
||||
unsigned * buf = (unsigned *)_alloca(msgLen + *sigLen + sizeof(unsigned) - 1);
|
||||
|
||||
// take care of endianess here, do not do just a memcpy()
|
||||
memcpy(buf, msg, msgLen);
|
||||
memset((char *)buf + msgLen, 0, sizeof(unsigned) - 1);
|
||||
|
||||
unsigned msgHash[5];
|
||||
|
||||
SHA1 sha;
|
||||
sha.Update((unsigned char *)msg, msgLen);
|
||||
sha.Final();
|
||||
|
||||
#ifndef LICENSING_BIG_ENDIAN
|
||||
sha.GetHash((unsigned char *)msgHash);
|
||||
#else
|
||||
unsigned char msgHashBuf[20];
|
||||
sha.GetHash(msgHashBuf);
|
||||
ByteArrayToUintArray(msgHashBuf, 20, msgHash);
|
||||
#endif
|
||||
|
||||
message.load(msgHash, 5);
|
||||
|
||||
signature = (m_hashBits && m_hashBits < m_privateKey.m_keySize) ? ecc.schnorr_sign(message, m_privateKey.m_key, Hash, m_hashBits) : ecc.dsa_sign(message, m_privateKey.m_key, Hash);
|
||||
|
||||
temp = (signature.r << m_privateKey.m_keySize); temp += signature.s;
|
||||
|
||||
unsigned int n = (unsigned)((*sigLen + sizeof(unsigned) - 1) / sizeof(unsigned));
|
||||
|
||||
temp.store(buf, n);
|
||||
|
||||
#ifndef LICENSING_BIG_ENDIAN
|
||||
// take care of endianess here
|
||||
memcpy(sigBuf, buf, *sigLen);
|
||||
#else
|
||||
UintArrayToByteArray(buf, *sigLenBits, (unsigned char *)sigBuf);
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
KeyImpl m_privateKey;
|
||||
int m_hashBits;
|
||||
};
|
||||
|
||||
class VerifierImpl {
|
||||
public:
|
||||
VerifierImpl()
|
||||
{
|
||||
m_hashBits = 0;
|
||||
}
|
||||
|
||||
~VerifierImpl()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static bigint Hash(const bigint & x, const bigint & p)
|
||||
{
|
||||
int n = ( x.bits() + ( ( sizeof(unsigned) << 3 ) - 1 ) ) / ( sizeof( unsigned ) << 3 );
|
||||
unsigned int * a = (unsigned *)_alloca(n * sizeof(unsigned));
|
||||
unsigned int h[ 5 ];
|
||||
|
||||
x.store(a, n);
|
||||
|
||||
SHA1 sha;
|
||||
|
||||
#ifndef LICENSING_BIG_ENDIAN
|
||||
sha.Update((unsigned char *)a, (x.bits() + 7) >> 3);
|
||||
#else
|
||||
int nb = (x.bits() + 7) >> 3;
|
||||
unsigned char * buf = (unsigned char *)_alloca(nb);
|
||||
UintArrayToByteArray(a, x.bits(), buf);
|
||||
sha.Update(buf, nb);
|
||||
#endif
|
||||
|
||||
sha.Final();
|
||||
|
||||
#ifndef LICENSING_BIG_ENDIAN
|
||||
sha.GetHash((unsigned char *)h);
|
||||
#else
|
||||
unsigned char bh[20];
|
||||
sha.GetHash(bh);
|
||||
ByteArrayToUintArray(bh, 20, h);
|
||||
#endif
|
||||
|
||||
bigint r;
|
||||
r.load( h, 5 );
|
||||
|
||||
return r % p;
|
||||
}
|
||||
|
||||
void SetHashSize(int hashBits)
|
||||
{
|
||||
m_hashBits = hashBits;
|
||||
}
|
||||
|
||||
void SetPublicKey(const KeyImpl & pubKey)
|
||||
{
|
||||
m_publicKey = pubKey;
|
||||
}
|
||||
|
||||
bool Verify(const void * msg, int msgLen, const void * sig, int sigLen, int sigLenBits)
|
||||
{
|
||||
full_curve_parameter param(eccCurveTable[ m_publicKey.m_keyType ]);
|
||||
ECC_BASE ecc(param);
|
||||
bigint message;
|
||||
bigint_pair signature;
|
||||
|
||||
int msgBufLen = (msgLen + sizeof(unsigned) - 1) / sizeof(unsigned);
|
||||
int sigBufLen = (sigLen + sizeof(unsigned) - 1) / sizeof(unsigned);
|
||||
|
||||
unsigned * msgBuf = (unsigned *)_alloca(msgBufLen * sizeof(unsigned));
|
||||
unsigned * sigBuf = (unsigned *)_alloca(sigBufLen * sizeof(unsigned));
|
||||
|
||||
#ifndef LICENSING_BIG_ENDIAN
|
||||
memset(msgBuf, 0, msgBufLen * sizeof(unsigned));
|
||||
memcpy(msgBuf, msg, msgLen);
|
||||
memset(sigBuf, 0, sigBufLen * sizeof(unsigned));
|
||||
memcpy(sigBuf, sig, sigLen);
|
||||
#else
|
||||
ByteArrayToUintArray((unsigned char *)msg, msgLen, msgBuf);
|
||||
ByteArrayToUintArray((unsigned char *)sig, sigLen, sigBuf);
|
||||
#endif
|
||||
|
||||
unsigned int msgHash[5];
|
||||
|
||||
SHA1 sha;
|
||||
sha.Update((unsigned char *)msg, msgLen);
|
||||
sha.Final();
|
||||
|
||||
#ifndef LICENSING_BIG_ENDIAN
|
||||
sha.GetHash((unsigned char *)msgHash);
|
||||
#else
|
||||
unsigned char byteHash[20];
|
||||
|
||||
sha.GetHash(byteHash);
|
||||
|
||||
ByteArrayToUintArray(byteHash, 20, msgHash);
|
||||
#endif
|
||||
message.load(msgHash, 5);
|
||||
|
||||
signature.r.load(sigBuf, sigBufLen);
|
||||
|
||||
signature.r >>= m_publicKey.m_keySize; signature.r &= (pow2((unsigned)(sigLenBits - m_publicKey.m_keySize)) - 1);
|
||||
|
||||
signature.s.load(sigBuf, sigBufLen);
|
||||
|
||||
signature.s &= (pow2(m_publicKey.m_keySize) - 1);
|
||||
|
||||
return (m_hashBits && m_hashBits < m_publicKey.m_keySize) ? ecc.schnorr_verify(message, signature, m_publicKey.m_key, Hash, m_hashBits) : ecc.dsa_verify(message, signature, m_publicKey.m_key, Hash);
|
||||
}
|
||||
|
||||
private:
|
||||
int m_hashBits;
|
||||
KeyImpl m_publicKey;
|
||||
};
|
||||
|
||||
void GenerateKeyPair(KEY_TYPE keyType, Key **privKey, Key **pubKey)
|
||||
{
|
||||
full_curve_parameter param(eccCurveTable[ keyType ]);
|
||||
ECC_BASE ecc(param);
|
||||
Key * privateKey = new Key(),
|
||||
* publicKey = new Key();
|
||||
|
||||
privateKey->m_Impl.m_key = ecc.create_private_key();
|
||||
privateKey->m_Impl.SetKeyType(keyType);
|
||||
privateKey->m_Impl.isPrivate = true;
|
||||
|
||||
publicKey->m_Impl.m_key = ecc.create_public_key(privateKey->m_Impl.m_key);
|
||||
publicKey->m_Impl.SetKeyType(keyType);
|
||||
|
||||
*privKey = privateKey;
|
||||
*pubKey = publicKey;
|
||||
}
|
||||
|
||||
Key::Key():
|
||||
m_Impl( *new KeyImpl() )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Key::Key(const void * keyBuf, int bufLen, KEY_TYPE keyType):
|
||||
m_Impl( *new KeyImpl(keyBuf, bufLen, keyType) )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Key::Key(const char * base64Key, KEY_TYPE keyType):
|
||||
m_Impl( *new KeyImpl(base64Key, keyType))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Key::~Key()
|
||||
{
|
||||
delete & m_Impl;
|
||||
}
|
||||
|
||||
void Key::Load(const void * keyData, int keyLen, KEY_TYPE keyType)
|
||||
{
|
||||
m_Impl.Load(keyData, keyLen, keyType);
|
||||
}
|
||||
|
||||
bool Key::Store(void * buf, int * bufLen) const
|
||||
{
|
||||
return m_Impl.Store(buf, bufLen);
|
||||
}
|
||||
|
||||
const char * Key::ToString()
|
||||
{
|
||||
|
||||
static string base64key;
|
||||
|
||||
int len = 2 + ((m_Impl.m_key.bits() + 7) >> 3);
|
||||
unsigned char * buf = (unsigned char *)_alloca(len);
|
||||
Store(buf, &len);
|
||||
|
||||
BASE64 base64;
|
||||
|
||||
auto base64Buf = base64.encode(buf, len, true);
|
||||
if (base64Buf.empty())
|
||||
throw new LicensingException(STATUS_GENERIC_ERROR, "could not encode buffer to base64");
|
||||
|
||||
base64key = base64Buf.c_str();
|
||||
|
||||
return base64key.c_str();
|
||||
}
|
||||
|
||||
KEY_TYPE Key::GetKeyType()
|
||||
{
|
||||
return m_Impl.GetKeyType();
|
||||
}
|
||||
|
||||
const Key & Key::operator = (const Key & key)
|
||||
{
|
||||
m_Impl = key.m_Impl;
|
||||
return (const Key &)(*this);
|
||||
}
|
||||
|
||||
Signer::Signer():
|
||||
m_Impl(*new SignerImpl())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Signer::~Signer()
|
||||
{
|
||||
delete & m_Impl;
|
||||
}
|
||||
|
||||
void Signer::SetHashSize(int hashBits)
|
||||
{
|
||||
m_Impl.SetHashSize(hashBits);
|
||||
}
|
||||
|
||||
void Signer::SetPrivateKey(const Key * privKey)
|
||||
{
|
||||
m_Impl.SetPrivateKey(privKey->m_Impl);
|
||||
}
|
||||
|
||||
void Signer::Sign(const void * msg, int msgLen, void * sigBuf, int * sigLen, int * sigLenBits)
|
||||
{
|
||||
m_Impl.Sign(msg, msgLen, sigBuf, sigLen, sigLenBits);
|
||||
}
|
||||
|
||||
Verifier::Verifier():
|
||||
m_Impl( *new VerifierImpl() )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Verifier::~Verifier()
|
||||
{
|
||||
delete & m_Impl;
|
||||
}
|
||||
|
||||
void Verifier::SetHashSize(int hashBits)
|
||||
{
|
||||
m_Impl.SetHashSize(hashBits);
|
||||
}
|
||||
|
||||
void Verifier::SetPublicKey(const Key * pubKey)
|
||||
{
|
||||
m_Impl.SetPublicKey(pubKey->m_Impl);
|
||||
}
|
||||
|
||||
bool Verifier::Verify(const void * msg, int msgLen, const void * sig, int sigLen, int sigLenBits)
|
||||
{
|
||||
return m_Impl.Verify(msg, msgLen, sig, sigLen, sigLenBits);
|
||||
}
|
||||
|
||||
}
|
||||
80
core/anslicensing/ecc.h
Normal file
80
core/anslicensing/ecc.h
Normal file
@@ -0,0 +1,80 @@
|
||||
#ifndef __ECC_H
|
||||
#define __ECC_H
|
||||
|
||||
namespace ECC {
|
||||
|
||||
enum KEY_TYPE {
|
||||
ECC_54,
|
||||
ECC_73,
|
||||
ECC_79,
|
||||
ECC_91,
|
||||
ECC_97,
|
||||
ECC_100,
|
||||
ECC_120,
|
||||
ECC_131,
|
||||
ECC_141,
|
||||
ECC_161,
|
||||
ECC
|
||||
};
|
||||
|
||||
class KeyImpl;
|
||||
|
||||
class Key {
|
||||
public:
|
||||
Key();
|
||||
Key(const void * keyData, int keyLen, KEY_TYPE keyType = ECC);
|
||||
Key(const char * base64Key, KEY_TYPE keyType = ECC);
|
||||
~Key();
|
||||
|
||||
void Load(const void * keyData, int keyLen, KEY_TYPE keyType = ECC);
|
||||
bool Store(void * buf, int * bufLen) const;
|
||||
const char * ToString();
|
||||
|
||||
KEY_TYPE GetKeyType();
|
||||
|
||||
const Key & operator = (const Key & key);
|
||||
|
||||
public:
|
||||
KeyImpl & m_Impl;
|
||||
};
|
||||
|
||||
typedef unsigned (*HashFunction)(const void *, int, void *, unsigned *);
|
||||
|
||||
class SignerImpl;
|
||||
|
||||
class Signer
|
||||
{
|
||||
public:
|
||||
Signer();
|
||||
~Signer();
|
||||
|
||||
void SetPrivateKey(const Key * privKey);
|
||||
void SetHashSize(int hashBits);
|
||||
|
||||
void Sign(const void * msg, int msgLen, void * sigBuf, int * sigLen, int *sigLenInBits = (int *)0);
|
||||
|
||||
private:
|
||||
SignerImpl & m_Impl;
|
||||
};
|
||||
|
||||
class VerifierImpl;
|
||||
|
||||
class Verifier {
|
||||
public:
|
||||
Verifier();
|
||||
~Verifier();
|
||||
|
||||
void SetPublicKey(const Key * pubKey);
|
||||
void SetHashSize(int hashBits);
|
||||
|
||||
bool Verify(const void * msg, int msgLen, const void * sig, int sigLen, int sigLenInBits = 0);
|
||||
|
||||
private:
|
||||
VerifierImpl & m_Impl;
|
||||
};
|
||||
|
||||
void GenerateKeyPair(KEY_TYPE keyType, Key **privKey, Key **pubKey);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
3
core/anslicensing/except.cpp
Normal file
3
core/anslicensing/except.cpp
Normal file
@@ -0,0 +1,3 @@
|
||||
#include "precomp.h"
|
||||
#include "except.h"
|
||||
|
||||
31
core/anslicensing/except.h
Normal file
31
core/anslicensing/except.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef __EXCEPT_H
|
||||
#define __EXCEPT_H
|
||||
|
||||
#include <string>
|
||||
#include "anslicensing.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class LicensingException : public ANSCENTER::Licensing::Exception {
|
||||
public:
|
||||
LicensingException( int code, const char * message = NULL)
|
||||
{
|
||||
SetCode(code);
|
||||
if (message)
|
||||
SetMessage(message);
|
||||
}
|
||||
|
||||
virtual ~LicensingException() {}
|
||||
|
||||
virtual int GetCode() { return m_code; }
|
||||
virtual const char * GetExceptionMessage() { return m_message.c_str(); }
|
||||
virtual void Destroy() { delete this; }
|
||||
void SetCode(int code) { m_code = code; }
|
||||
void SetMessage(const char * message) { m_message = message; }
|
||||
|
||||
protected:
|
||||
int m_code;
|
||||
string m_message;
|
||||
};
|
||||
|
||||
#endif
|
||||
207
core/anslicensing/generator.cpp
Normal file
207
core/anslicensing/generator.cpp
Normal file
@@ -0,0 +1,207 @@
|
||||
//
|
||||
// Copyright (c) 2014 ANSCENTER. All rights reserved.
|
||||
//
|
||||
|
||||
#include "precomp.h"
|
||||
#include "anslicensing.h"
|
||||
#include "template.h"
|
||||
#include "base32.h"
|
||||
#include "base64.h"
|
||||
#include "sha1.h"
|
||||
#include "except.h"
|
||||
#include "bitstream.h"
|
||||
#include "uniconv.h"
|
||||
#include "generator.h"
|
||||
|
||||
namespace ANSCENTER {
|
||||
namespace Licensing {
|
||||
template<>
|
||||
KeyGeneratorT<char>::KeyGeneratorT():
|
||||
m_Impl( *new KeyGeneratorImpl())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
template<>
|
||||
KeyGeneratorT<wchar_t>::KeyGeneratorT():
|
||||
m_Impl( *new KeyGeneratorImpl())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
template<>
|
||||
KeyGeneratorT<char>::KeyGeneratorT(const LicenseTemplateT<char> * templ):
|
||||
m_Impl( *new KeyGeneratorImpl(&templ->m_Impl) )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
template<>
|
||||
KeyGeneratorT<wchar_t>::KeyGeneratorT(const LicenseTemplateT<wchar_t> * templ):
|
||||
m_Impl( *new KeyGeneratorImpl(&templ->m_Impl) )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
template<>
|
||||
KeyGeneratorT<char>::~KeyGeneratorT()
|
||||
{
|
||||
delete & m_Impl;
|
||||
}
|
||||
|
||||
template<>
|
||||
KeyGeneratorT<wchar_t>::~KeyGeneratorT()
|
||||
{
|
||||
delete & m_Impl;
|
||||
}
|
||||
|
||||
template<>
|
||||
KeyGeneratorT<char> * KeyGeneratorT<char>::Create()
|
||||
{
|
||||
return new KeyGeneratorT<char>();
|
||||
}
|
||||
|
||||
template<>
|
||||
KeyGeneratorT<wchar_t> * KeyGeneratorT<wchar_t>::Create()
|
||||
{
|
||||
return new KeyGeneratorT<wchar_t>();
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyGeneratorT<char>::Destroy(KeyGeneratorT<char> * obj)
|
||||
{
|
||||
delete obj;
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyGeneratorT<wchar_t>::Destroy(KeyGeneratorT<wchar_t> * obj)
|
||||
{
|
||||
delete obj;
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyGeneratorT<char>::SetKeyData(const char * fieldName, const void * buf, int len)
|
||||
{
|
||||
m_Impl.KeyGeneratorImpl::SetKeyData(fieldName, buf, len);
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyGeneratorT<wchar_t>::SetKeyData(const wchar_t * fieldName, const void * buf, int len)
|
||||
{
|
||||
m_Impl.KeyGeneratorImpl::SetKeyData(w2s(fieldName).c_str(), buf, len);
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyGeneratorT<char>::SetKeyData(const char * fieldName, int data)
|
||||
{
|
||||
|
||||
m_Impl.SetKeyData(fieldName, data);
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyGeneratorT<wchar_t>::SetKeyData(const wchar_t * fieldName, int data)
|
||||
{
|
||||
m_Impl.SetKeyData(w2s(fieldName).c_str(), data);
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyGeneratorT<char>::SetKeyData(const char * fieldName, const char * data)
|
||||
{
|
||||
m_Impl.SetKeyData(fieldName, data);
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyGeneratorT<wchar_t>::SetKeyData(const wchar_t * fieldName, const wchar_t * data)
|
||||
{
|
||||
m_Impl.SetKeyData(w2s(fieldName).c_str(), w2s(data).c_str());
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyGeneratorT<char>::SetKeyData(const char * fieldName, int year, int month, int day)
|
||||
{
|
||||
m_Impl.SetKeyData(fieldName, year, month, day);
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyGeneratorT<wchar_t>::SetKeyData(const wchar_t * fieldName, int year, int month, int day)
|
||||
{
|
||||
m_Impl.SetKeyData(w2s(fieldName).c_str(), year, month, day);
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyGeneratorT<char>::SetValidationData(const char * fieldName, const void * buf, int len)
|
||||
{
|
||||
|
||||
m_Impl.SetValidationData(fieldName, buf, len);
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyGeneratorT<wchar_t>::SetValidationData(const wchar_t * fieldName, const void * buf, int len)
|
||||
{
|
||||
m_Impl.SetValidationData(w2s(fieldName).c_str(), buf, len);
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyGeneratorT<char>::SetValidationData(const char * fieldName, int data)
|
||||
{
|
||||
m_Impl.SetValidationData(fieldName, data);
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyGeneratorT<wchar_t>::SetValidationData(const wchar_t * fieldName, int data)
|
||||
{
|
||||
m_Impl.SetValidationData(w2s(fieldName).c_str(), data);
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyGeneratorT<char>::SetValidationData(const char * fieldName, const char * data)
|
||||
{
|
||||
m_Impl.SetValidationData(fieldName, data);
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyGeneratorT<wchar_t>::SetValidationData(const wchar_t * fieldName, const wchar_t * data)
|
||||
{
|
||||
m_Impl.SetValidationData(w2s(fieldName).c_str(), w2s(data).c_str());
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyGeneratorT<char>::SetKeyTemplate(const LicenseTemplateT<char> & templ)
|
||||
{
|
||||
m_Impl.SetKeyTemplate(&templ.m_Impl);
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyGeneratorT<wchar_t>::SetKeyTemplate(const LicenseTemplateT<wchar_t> & templ)
|
||||
{
|
||||
m_Impl.SetKeyTemplate(&templ.m_Impl);
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyGeneratorT<char>::SetKeyTemplate(const LicenseTemplateT<char> * templ)
|
||||
{
|
||||
m_Impl.SetKeyTemplate(&templ->m_Impl);
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyGeneratorT<wchar_t>::SetKeyTemplate(const LicenseTemplateT<wchar_t> * templ)
|
||||
{
|
||||
m_Impl.SetKeyTemplate(&templ->m_Impl);
|
||||
}
|
||||
|
||||
template<>
|
||||
const char * KeyGeneratorT<char>::GenerateKey()
|
||||
{
|
||||
return m_Impl.GenerateKey();
|
||||
}
|
||||
|
||||
template<>
|
||||
const wchar_t * KeyGeneratorT<wchar_t>::GenerateKey()
|
||||
{
|
||||
static wstring wstr1;
|
||||
|
||||
wstr1 = s2w(m_Impl.GenerateKey());
|
||||
return wstr1.c_str();
|
||||
}
|
||||
};
|
||||
};
|
||||
423
core/anslicensing/generator.h
Normal file
423
core/anslicensing/generator.h
Normal file
@@ -0,0 +1,423 @@
|
||||
#pragma once
|
||||
|
||||
#include "bitstream.h"
|
||||
#include "base32.h"
|
||||
#include "base64.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
#ifndef LICENSING_NO_NETWORKING
|
||||
#ifdef _WIN32
|
||||
#include <winhttp.h>
|
||||
#include <tchar.h>
|
||||
#else
|
||||
#include <curl/curl.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
class KeyGeneratorImpl {
|
||||
public:
|
||||
KeyGeneratorImpl():
|
||||
m_signingServiceStatusCode(-1)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
KeyGeneratorImpl(const LicenseTemplateImpl * templ):
|
||||
KeyGeneratorImpl()
|
||||
{
|
||||
SetKeyTemplate(templ);
|
||||
}
|
||||
|
||||
void SetKeyTemplate(const LicenseTemplateImpl * templ)
|
||||
{
|
||||
m_keyTemplate = templ;
|
||||
|
||||
m_keyData.Create(m_keyTemplate->m_numGroups * m_keyTemplate->m_charsPerGroup * m_keyTemplate->m_keyEncoding);
|
||||
m_keyData.GetBitStream().Clear();
|
||||
|
||||
for (const auto& field : m_keyTemplate->m_dataFields)
|
||||
m_keyData.AddField(field.first.c_str(), field.second.type, field.second.size, field.second.offset);
|
||||
|
||||
if (m_keyTemplate->m_validationDataSize)
|
||||
{
|
||||
m_validationData.Create(m_keyTemplate->m_validationDataSize);
|
||||
m_validationData.GetBitStream().Clear();
|
||||
|
||||
for (const auto& field : m_keyTemplate->m_validationFields)
|
||||
m_validationData.AddField(field.first.c_str(), field.second.type, field.second.size, field.second.offset);
|
||||
}
|
||||
}
|
||||
|
||||
void SetKeyData(const char * fieldName, const void * buf, int len)
|
||||
{
|
||||
m_keyData.Set(fieldName, buf, len);
|
||||
}
|
||||
|
||||
void SetKeyData(const char * fieldName, const char * data)
|
||||
{
|
||||
m_keyData.Set(fieldName, data);
|
||||
}
|
||||
|
||||
void SetKeyData(const char * fieldName, int data)
|
||||
{
|
||||
m_keyData.Set(fieldName, data);
|
||||
}
|
||||
|
||||
void SetKeyData(const char * fieldName, int year, int month, int day)
|
||||
{
|
||||
m_keyData.Set(fieldName, year, month, day);
|
||||
}
|
||||
|
||||
void SetValidationData(const char * fieldName, const void * buf, int len)
|
||||
{
|
||||
m_validationData.Set(fieldName, buf, len);
|
||||
}
|
||||
|
||||
void SetValidationData(const char * fieldName, const char * data)
|
||||
{
|
||||
m_validationData.Set(fieldName, data);
|
||||
}
|
||||
|
||||
void SetValidationData(const char * fieldName, int data)
|
||||
{
|
||||
m_validationData.Set(fieldName, data);
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
static size_t
|
||||
CurlWriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
|
||||
{
|
||||
KeyGeneratorImpl * pthis = (KeyGeneratorImpl *)userp;
|
||||
size_t realsize = size * nmemb;
|
||||
|
||||
if (realsize > 1024 || pthis->m_keyBuffer.length() > 1024)
|
||||
return realsize - 1; // signal error
|
||||
|
||||
if (realsize > 0)
|
||||
pthis->m_keyBuffer.append((char *)contents, realsize);
|
||||
|
||||
return realsize;
|
||||
}
|
||||
#endif
|
||||
|
||||
const char * GenerateKey()
|
||||
{
|
||||
BitStream signedData;
|
||||
BitStream signature;
|
||||
ECC::Signer signer;
|
||||
int sigLen, sigLenBits;
|
||||
|
||||
#ifndef LICENSING_NO_NETWORKING
|
||||
if (m_keyTemplate->m_signingKey == NULL)
|
||||
{
|
||||
|
||||
|
||||
m_signingServiceStatusCode = -1;
|
||||
|
||||
string activationQuery("Activate.ashx?");
|
||||
|
||||
//if (activationQuery[m_keyTemplate->m_signingServiceUrl.length() - 1] != '/')
|
||||
// activationQuery.append(1, '/');
|
||||
//activationQuery.append("Activate.ashx?");
|
||||
|
||||
unsigned char * buf = (unsigned char *)_alloca(1 + ((m_validationData.GetSize() + 7) >> 3));
|
||||
|
||||
void * enumHandle = NULL;
|
||||
const char * name;
|
||||
BitStruct::FIELD_TYPE type;
|
||||
int size, offset;
|
||||
|
||||
while (m_keyTemplate->EnumValidationFields(&enumHandle, &name, (int*)&type, &size, &offset))
|
||||
{
|
||||
m_validationData.GetBitStream().Seek(offset);
|
||||
m_validationData.GetBitStream().Read(buf, size);
|
||||
|
||||
activationQuery.append(name);
|
||||
activationQuery.append("=");
|
||||
|
||||
if ((int)type == FIELD_TYPE_STRING)
|
||||
{
|
||||
buf[(size + 7) >> 3] = '\0';
|
||||
activationQuery.append((char *)buf);
|
||||
} else
|
||||
{
|
||||
BASE64 base64;
|
||||
|
||||
string base64Value = base64.encode(buf, (size + 7) >> 3, true);
|
||||
|
||||
replace_all(base64Value, "+", "%2B");
|
||||
replace_all(base64Value, "/", "%2F");
|
||||
replace_all(base64Value, "=", "%3D");
|
||||
|
||||
activationQuery.append(base64Value.c_str());
|
||||
}
|
||||
|
||||
activationQuery.append("&");
|
||||
}
|
||||
|
||||
if (m_keyTemplate->m_licensingServiceParameters.length() > 0)
|
||||
{
|
||||
activationQuery.append(m_keyTemplate->m_licensingServiceParameters);
|
||||
activationQuery.append("&");
|
||||
}
|
||||
|
||||
activationQuery.erase(activationQuery.length() - 1, 1);
|
||||
|
||||
m_keyBuffer.clear();
|
||||
|
||||
#ifdef _WIN32
|
||||
URL_COMPONENTS urlComponents;
|
||||
|
||||
ZeroMemory(&urlComponents, sizeof(urlComponents));
|
||||
urlComponents.dwStructSize = sizeof(urlComponents);
|
||||
|
||||
urlComponents.dwHostNameLength = (DWORD)-1;
|
||||
urlComponents.dwUrlPathLength = (DWORD)-1;
|
||||
|
||||
auto licensingServiceUrl = s2w(m_keyTemplate->m_licensingServiceUrl);
|
||||
|
||||
if (!WinHttpCrackUrl(licensingServiceUrl.c_str(), m_keyTemplate->m_licensingServiceUrl.length(), 0L, &urlComponents))
|
||||
throw new LicensingException(STATUS_NET_ERROR, _T("networking error (1)"));
|
||||
|
||||
std::wstring hostName(urlComponents.lpszHostName, urlComponents.dwHostNameLength);
|
||||
|
||||
unique_ptr<VOID, decltype(&WinHttpCloseHandle)> internet_ptr(WinHttpOpen(L"ANSCENTER Licensing SDK 2.0", WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0L), WinHttpCloseHandle);
|
||||
|
||||
if (!internet_ptr)
|
||||
throw new LicensingException(STATUS_NET_ERROR, _T("networking error (2)"));
|
||||
|
||||
unique_ptr<VOID, decltype(&WinHttpCloseHandle)> connection_ptr(WinHttpConnect(internet_ptr.get(), hostName.c_str(), urlComponents.nPort, 0L), WinHttpCloseHandle);
|
||||
if (!connection_ptr)
|
||||
throw new LicensingException(STATUS_NET_ERROR, _T("networking error (3)"));
|
||||
|
||||
activationQuery.insert(0, w2s(urlComponents.lpszUrlPath, urlComponents.dwUrlPathLength));
|
||||
|
||||
DWORD requestFlags = WINHTTP_FLAG_BYPASS_PROXY_CACHE;
|
||||
if (urlComponents.nScheme == INTERNET_SCHEME_HTTPS)
|
||||
requestFlags |= WINHTTP_FLAG_SECURE;
|
||||
|
||||
unique_ptr<VOID, decltype(&WinHttpCloseHandle)> request_ptr(WinHttpOpenRequest(connection_ptr.get(), L"GET", s2w(activationQuery).c_str(), NULL, NULL, NULL, requestFlags), WinHttpCloseHandle);
|
||||
if (!request_ptr)
|
||||
throw new LicensingException(STATUS_NET_ERROR, _T("networking error (4)"));
|
||||
|
||||
if (!WinHttpSendRequest(request_ptr.get(), NULL, 0L, NULL, 0L, 0L, 0L))
|
||||
{
|
||||
DWORD result = GetLastError();
|
||||
throw new LicensingException(STATUS_NET_ERROR, _T("networking error (5)"));
|
||||
}
|
||||
|
||||
if (!WinHttpReceiveResponse(request_ptr.get(), NULL))
|
||||
throw new LicensingException(STATUS_NET_ERROR, _T("networking error (6)"));
|
||||
|
||||
DWORD status;
|
||||
DWORD statusSize = sizeof(DWORD);
|
||||
|
||||
if (!WinHttpQueryHeaders(request_ptr.get(), WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, WINHTTP_HEADER_NAME_BY_INDEX, &status, &statusSize, WINHTTP_NO_HEADER_INDEX))
|
||||
throw new LicensingException(STATUS_NET_ERROR, _T("networking error (7)"));
|
||||
|
||||
m_signingServiceStatusCode = status;
|
||||
|
||||
if (status != HTTP_STATUS_OK && status != HTTP_STATUS_ACCEPTED && status != HTTP_STATUS_CREATED)
|
||||
{
|
||||
WCHAR buffer[1024];
|
||||
DWORD bufferSize = 1024;
|
||||
|
||||
if (!WinHttpQueryHeaders(request_ptr.get(), WINHTTP_QUERY_STATUS_TEXT, WINHTTP_HEADER_NAME_BY_INDEX, buffer, &bufferSize, WINHTTP_NO_HEADER_INDEX))
|
||||
throw new LicensingException(STATUS_NET_ERROR, "networking error (8)");
|
||||
|
||||
throw new LicensingException(STATUS_NET_ERROR, w2s(buffer).c_str());
|
||||
}
|
||||
|
||||
DWORD dataSize, count;
|
||||
char buffer[0x100];
|
||||
|
||||
do {
|
||||
if (!WinHttpQueryDataAvailable(request_ptr.get(), &dataSize))
|
||||
break;
|
||||
|
||||
if (size > 0x100)
|
||||
size = 0x100;
|
||||
|
||||
if (WinHttpReadData(request_ptr.get(), buffer, dataSize, &count))
|
||||
m_keyBuffer.append(buffer, count);
|
||||
|
||||
} while (dataSize > 0);
|
||||
#else
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
|
||||
if ((curl = curl_easy_init()) == NULL)
|
||||
throw new LicensingException(STATUS_NET_ERROR, "cURL initalization failed");
|
||||
|
||||
if (*(m_keyTemplate->m_licensingServiceUrl.rbegin()) != '/')
|
||||
activationQuery.insert(0, "/");
|
||||
|
||||
activationQuery.insert(0, m_keyTemplate->m_licensingServiceUrl);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, activationQuery.c_str());
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWriteCallback);
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, this);
|
||||
|
||||
res = curl_easy_perform(curl);
|
||||
|
||||
if(res != CURLE_OK)
|
||||
throw new LicensingException(STATUS_NET_ERROR, curl_easy_strerror(res));
|
||||
|
||||
curl_easy_cleanup(curl);
|
||||
#endif
|
||||
|
||||
m_key = m_keyBuffer.c_str();
|
||||
|
||||
return m_key.c_str();
|
||||
}
|
||||
#else
|
||||
if (m_keyTemplate->m_signingKey == NULL)
|
||||
{
|
||||
throw new LicensingException(STATUS_NET_ERROR, "private key not provided");
|
||||
}
|
||||
#endif
|
||||
|
||||
// signed data is license key data followed by validation data
|
||||
signedData.Create(m_keyTemplate->m_dataSize + m_keyTemplate->m_validationDataSize);
|
||||
|
||||
if (m_keyTemplate->m_dataSize)
|
||||
signedData.Write(m_keyData.GetBuffer(), m_keyTemplate->m_dataSize);
|
||||
|
||||
if (m_keyTemplate->m_validationDataSize)
|
||||
signedData.Write(m_validationData.GetBuffer(), m_keyTemplate->m_validationDataSize);
|
||||
|
||||
signedData.ZeroPadToNextByte();
|
||||
|
||||
// create a bit stream to hold the signature
|
||||
signature.Create(m_keyTemplate->m_signatureSize);
|
||||
|
||||
// sign data
|
||||
|
||||
// we use a different algorithm than ECDSA when the signature size must be smaller than twice the key size
|
||||
if (m_keyTemplate->m_signatureSize < (m_keyTemplate->m_signatureKeySize << 1))
|
||||
signer.SetHashSize(m_keyTemplate->m_signatureSize - m_keyTemplate->m_signatureKeySize);
|
||||
else
|
||||
signer.SetHashSize(0);
|
||||
|
||||
signer.SetPrivateKey(m_keyTemplate->m_signingKey.get());
|
||||
|
||||
signer.Sign(signedData.GetBuffer(), (signedData.GetSize() + 7) >> 3,
|
||||
signature.GetBuffer(), &sigLen, &sigLenBits);
|
||||
|
||||
signature.ReleaseBuffer(sigLenBits);
|
||||
|
||||
// write the signature at the end of key data
|
||||
m_keyData.GetBitStream().Seek(m_keyTemplate->m_dataSize);
|
||||
m_keyData.GetBitStream().Write(signature.GetBuffer(), m_keyTemplate->m_signatureSize);
|
||||
|
||||
// text-encode the license key
|
||||
EncodeKey();
|
||||
|
||||
// success
|
||||
return m_key.c_str();
|
||||
}
|
||||
|
||||
int GetSigningServiceStatusCode()
|
||||
{
|
||||
return m_signingServiceStatusCode;
|
||||
}
|
||||
|
||||
void EncodeKey()
|
||||
{
|
||||
|
||||
string buf;
|
||||
|
||||
// set all bits to 0 until the next byte boundary
|
||||
//m_rawKey.ZeroPadToNextByte();
|
||||
|
||||
// reverse last byte from the stream,
|
||||
// so that we will not lose significant bits in the padless, truncated BAS32/64 encoding
|
||||
unsigned char * lastBytePtr = (unsigned char *)m_keyData.GetBuffer() + ((m_keyData.GetSize() + 7) >> 3) - 1;
|
||||
*lastBytePtr = (unsigned char)(((*lastBytePtr * 0x0802LU & 0x22110LU) | (*lastBytePtr * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16);
|
||||
|
||||
switch (m_keyTemplate->m_keyEncoding)
|
||||
{
|
||||
case ENCODING_BASE32X:
|
||||
{
|
||||
BASE32 base32;
|
||||
buf = base32.encode((unsigned char *)m_keyData.GetBuffer(), (m_keyData.GetSize() + 7) >> 3, true);
|
||||
}
|
||||
break;
|
||||
|
||||
case ENCODING_BASE64X:
|
||||
{
|
||||
BASE64 base64;
|
||||
buf = base64.encode((unsigned char *)m_keyData.GetBuffer(), (m_keyData.GetSize() + 7) >> 3, false);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new LicensingException(STATUS_INVALID_KEY_ENCODING);
|
||||
}
|
||||
|
||||
if (buf.empty())
|
||||
throw new LicensingException(STATUS_OUT_OF_MEMORY);
|
||||
|
||||
m_key = buf.c_str();
|
||||
|
||||
if ((int)m_key.length() > m_keyTemplate->m_numGroups * m_keyTemplate->m_charsPerGroup)
|
||||
m_key.resize(m_keyTemplate->m_numGroups * m_keyTemplate->m_charsPerGroup);
|
||||
|
||||
int i;
|
||||
int insertPos;
|
||||
// separate character groups
|
||||
for (i = 0, insertPos = m_keyTemplate->m_charsPerGroup; i < m_keyTemplate->m_numGroups - 1; i++)
|
||||
{
|
||||
m_key.insert(insertPos, m_keyTemplate->m_groupSeparator);
|
||||
insertPos += (unsigned)( m_keyTemplate->m_groupSeparator.length() + m_keyTemplate->m_charsPerGroup );
|
||||
}
|
||||
|
||||
// add header and footer (if any)
|
||||
if (!m_keyTemplate->m_header.empty())
|
||||
m_key.insert(0, m_keyTemplate->m_header + "\r\n");
|
||||
|
||||
if (!m_keyTemplate->m_footer.empty())
|
||||
m_key.append("\r\n" + m_keyTemplate->m_footer);
|
||||
}
|
||||
|
||||
std::size_t replace_all(std::string& inout, std::string_view what, std::string_view with)
|
||||
{
|
||||
std::size_t count{};
|
||||
|
||||
for (std::string::size_type pos{};
|
||||
inout.npos != (pos = inout.find(what.data(), pos, what.length()));
|
||||
pos += with.length(), ++count) {
|
||||
inout.replace(pos, what.length(), with.data(), with.length());
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void StrReplaceA(std::string& str, const std::string& oldStr, const std::string& newStr)
|
||||
{
|
||||
size_t pos = 0;
|
||||
while((pos = str.find(oldStr, pos)) != std::string::npos)
|
||||
{
|
||||
str.replace(pos, oldStr.length(), newStr);
|
||||
pos += newStr.length();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const LicenseTemplateImpl* m_keyTemplate;
|
||||
|
||||
string m_keyBuffer;
|
||||
string m_key;
|
||||
|
||||
BitStruct m_keyData;
|
||||
BitStruct m_validationData;
|
||||
|
||||
int m_signingServiceStatusCode;
|
||||
};
|
||||
169
core/anslicensing/helper.cpp
Normal file
169
core/anslicensing/helper.cpp
Normal file
@@ -0,0 +1,169 @@
|
||||
//
|
||||
// Copyright (c) 2014 ANSCENTER. All rights reserved.
|
||||
//
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "wmihelper.h"
|
||||
#endif
|
||||
|
||||
#include "anslicensing.h"
|
||||
#include "uniconv.h"
|
||||
#include "except.h"
|
||||
#include "hwid.h"
|
||||
#include "base64.h"
|
||||
|
||||
class KeyHelperImpl {
|
||||
|
||||
friend class KeyHelperT<char>;
|
||||
friend class KeyHelperT<wchar_t>;
|
||||
|
||||
private:
|
||||
static const char * GetCurrentHardwareId()
|
||||
{
|
||||
return HardwareId::GetCurrentHardwareId();
|
||||
}
|
||||
|
||||
static bool MatchCurrentHardwareId(const char * hwid)
|
||||
{
|
||||
return HardwareId::MatchCurrentHardwareId(hwid);
|
||||
}
|
||||
|
||||
static bool DetectClockManipulation(int year, int month, int day)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
FILETIME thresholdTime;
|
||||
SYSTEMTIME st;
|
||||
TCHAR path[MAX_PATH];
|
||||
|
||||
ZeroMemory(&st, sizeof(st));
|
||||
|
||||
st.wYear = year;
|
||||
st.wMonth = month;
|
||||
st.wDay = day;
|
||||
st.wHour = 23;
|
||||
st.wMinute = 59;
|
||||
st.wSecond = 59;
|
||||
|
||||
if (!SystemTimeToFileTime(&st, &thresholdTime))
|
||||
return false;
|
||||
|
||||
if (GetTempPath(MAX_PATH, path) > 0)
|
||||
{
|
||||
_tcsncat_s<MAX_PATH>(path, "*.*", _TRUNCATE);
|
||||
|
||||
WIN32_FIND_DATA findData;
|
||||
|
||||
HANDLE findHandle = FindFirstFile(path, &findData);
|
||||
if (findHandle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
while (FindNextFile(findHandle, &findData))
|
||||
{
|
||||
if (CompareFileTime(&findData.ftLastWriteTime, &thresholdTime) > 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
FindClose(findHandle);
|
||||
}
|
||||
}
|
||||
|
||||
WmiHelper wmi;
|
||||
list<string> propList;
|
||||
|
||||
char dmtfTime[100];
|
||||
char query[MAX_PATH];
|
||||
|
||||
_snprintf_s(query, MAX_PATH, _TRUNCATE, "SELECT EventIdentifier FROM Win32_NTLogEvent WHERE LogFile='system' AND TimeGenerated > '%04d%02d%02d000000.000000-000'", st.wYear, st.wMonth, st.wDay);
|
||||
|
||||
wmi.GetPropertyList(query, "EventIdentifier", &propList);
|
||||
|
||||
if (propList.size() > 0)
|
||||
return true;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
namespace ANSCENTER
|
||||
{
|
||||
namespace Licensing
|
||||
{
|
||||
|
||||
template<>
|
||||
const char * KeyHelperT<char>::GetCurrentHardwareId()
|
||||
{
|
||||
return KeyHelperImpl::GetCurrentHardwareId();
|
||||
}
|
||||
|
||||
template<>
|
||||
const wchar_t * KeyHelperT<wchar_t>::GetCurrentHardwareId()
|
||||
{
|
||||
static wstring wstr1;
|
||||
|
||||
wstr1 = s2w(KeyHelperImpl::GetCurrentHardwareId());
|
||||
return wstr1.c_str();
|
||||
}
|
||||
|
||||
template<>
|
||||
bool KeyHelperT<char>::MatchCurrentHardwareId(const char * hwid)
|
||||
{
|
||||
return KeyHelperImpl::MatchCurrentHardwareId(hwid);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool KeyHelperT<wchar_t>::MatchCurrentHardwareId(const wchar_t * hwid)
|
||||
{
|
||||
return KeyHelperImpl::MatchCurrentHardwareId(w2s(hwid).c_str());
|
||||
}
|
||||
|
||||
template<>
|
||||
bool KeyHelperT<char>::DetectClockManipulation(int thresholdYear, int thresholdMonth, int thresholdDay)
|
||||
{
|
||||
return KeyHelperImpl::DetectClockManipulation(thresholdYear, thresholdMonth, thresholdDay);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool KeyHelperT<wchar_t>::DetectClockManipulation(int thresholdYear, int thresholdMonth, int thresholdDay)
|
||||
{
|
||||
return KeyHelperImpl::DetectClockManipulation(thresholdYear, thresholdMonth, thresholdDay);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
namespace ANSCENTER
|
||||
{
|
||||
namespace Licensing
|
||||
{
|
||||
const char* ANSUtility::WString2String(const wchar_t * inputString) {
|
||||
string result = w2s(inputString);
|
||||
return result.c_str();
|
||||
|
||||
}
|
||||
const wchar_t* ANSUtility::String2WString(const char* inputString) {
|
||||
wstring result = s2w(inputString);
|
||||
return result.c_str();
|
||||
}
|
||||
|
||||
const char* ANSUtility::EncodeBase64Utility(unsigned char* buf, int len, bool padding) {
|
||||
BASE64 base64;
|
||||
string result= base64.encode(buf, len,padding);
|
||||
return result.c_str();
|
||||
}
|
||||
|
||||
const char* ANSUtility::DecodeBase64Utility(const char* input, int len, int* outlen) {
|
||||
BASE64 base64;
|
||||
vector<unsigned char> result = base64.decode(input, len, nullptr);
|
||||
string str(result.begin(), result.end());
|
||||
return str.c_str();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
562
core/anslicensing/hwid.cpp
Normal file
562
core/anslicensing/hwid.cpp
Normal file
@@ -0,0 +1,562 @@
|
||||
//
|
||||
// Copyright (c) 2014 ANSCENTER. All rights reserved.
|
||||
//
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include "wmihelper.h"
|
||||
|
||||
#else // !_WIN32
|
||||
|
||||
#if defined(__i386__) || defined(__amd64__)
|
||||
#include <cpuid.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <netinet/in.h>
|
||||
#include <net/if.h>
|
||||
#ifdef __linux__
|
||||
# include <sys/ioctl.h>
|
||||
# include <netinet/in.h>
|
||||
# include <unistd.h>
|
||||
# include <string.h>
|
||||
|
||||
// Match Linux to FreeBSD
|
||||
# define AF_LINK AF_PACKET
|
||||
#else
|
||||
# include <net/if_dl.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <stdio.h>
|
||||
#include <set>
|
||||
|
||||
#include "bitstream2.h"
|
||||
#include "bitstream3.h"
|
||||
#include "base32.h"
|
||||
#include "crc32.h"
|
||||
|
||||
#include "hwid.h"
|
||||
#include "except.h"
|
||||
#include "uniconv.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
string HardwareId::hardwareId;
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
const sockaddr_in* castToIP4(const sockaddr* addr) {
|
||||
if (addr == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
else if (addr->sa_family == AF_INET) {
|
||||
// An IPv4 address
|
||||
return reinterpret_cast<const sockaddr_in*>(addr);
|
||||
}
|
||||
else {
|
||||
// Not an IPv4 address
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void GetCPUIDPropertyList(std::list<std::string>* propList)
|
||||
{
|
||||
unsigned int level = 1, eax = 0, ebx, ecx, edx = 0;
|
||||
|
||||
#if defined(__i386__) || defined(__amd64__)
|
||||
__get_cpuid(level, &eax, &ebx, &ecx, &edx);
|
||||
#endif
|
||||
|
||||
char buf[17];
|
||||
sprintf(buf, "%08X%08X", edx, eax);
|
||||
propList->push_back(buf);
|
||||
}
|
||||
|
||||
void GetMACPropertyList(std::list<std::string>* propList, int maxCount)
|
||||
{
|
||||
// Head of the interface address linked list
|
||||
ifaddrs* ifap = NULL;
|
||||
|
||||
int r = getifaddrs(&ifap);
|
||||
|
||||
if (r != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ifaddrs* current = ifap;
|
||||
|
||||
if (current == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (current != NULL && maxCount > 0) {
|
||||
|
||||
const sockaddr_in* interfaceAddress = castToIP4(current->ifa_addr);
|
||||
const sockaddr_in* broadcastAddress = castToIP4(current->ifa_dstaddr);
|
||||
const sockaddr_in* subnetMask = castToIP4(current->ifa_netmask);
|
||||
|
||||
if ((current->ifa_addr != NULL) && (current->ifa_addr->sa_family == AF_LINK)) {
|
||||
#ifdef __linux__
|
||||
struct ifreq ifr;
|
||||
|
||||
int fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
|
||||
ifr.ifr_addr.sa_family = AF_INET;
|
||||
strcpy(ifr.ifr_name, current->ifa_name);
|
||||
ioctl(fd, SIOCGIFHWADDR, &ifr);
|
||||
close(fd);
|
||||
|
||||
uint8_t* MAC = reinterpret_cast<uint8_t*>(ifr.ifr_hwaddr.sa_data);
|
||||
|
||||
#else // Posix/FreeBSD/Mac OS
|
||||
|
||||
sockaddr_dl* sdl = (struct sockaddr_dl*)current->ifa_addr;
|
||||
uint8_t* MAC = reinterpret_cast<uint8_t*>(LLADDR(sdl));
|
||||
#endif
|
||||
if (MAC[0] != 0 || MAC[1] != 0 || MAC[2] != 0 || MAC[3] != 0 || MAC[4] != 0 || MAC[5] != 0)
|
||||
{
|
||||
char buf[18];
|
||||
sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", MAC[0], MAC[1], MAC[2], MAC[3], MAC[4], MAC[5]);
|
||||
propList->push_back(buf);
|
||||
maxCount--;
|
||||
}
|
||||
}
|
||||
|
||||
current = current->ifa_next;
|
||||
}
|
||||
|
||||
freeifaddrs(ifap);
|
||||
ifap = NULL;
|
||||
}
|
||||
|
||||
void GetHDDPropertyList(std::list<std::string>* propList, int maxCount)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
unsigned short HardwareId::HashString(const char* str)
|
||||
{
|
||||
unsigned int crc = Crc32::Compute((const unsigned char*)str, strlen(str));
|
||||
|
||||
return (unsigned short)(crc >> 16);
|
||||
}
|
||||
|
||||
unsigned short HardwareId::HashInt(int val)
|
||||
{
|
||||
unsigned char buf[4] = { (unsigned char)(val >> 24), (unsigned char)(val >> 16), (unsigned char)(val >> 8), (unsigned char)(val & 0xFF) };
|
||||
unsigned int crc = Crc32::Compute(buf, 4);
|
||||
|
||||
return (unsigned short)(crc >> 16);
|
||||
}
|
||||
|
||||
// LOCALE-INDEPENDENT trim from start (in place)
|
||||
static inline void ltrim(std::string& s) {
|
||||
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) {
|
||||
return ch != ' ' && ch != '\t' && ch != '\n' && ch != '\r' && ch != 0xA0;
|
||||
}));
|
||||
}
|
||||
|
||||
// LOCALE-INDEPENDENT trim from end (in place)
|
||||
static inline void rtrim(std::string& s) {
|
||||
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
|
||||
return ch != ' ' && ch != '\t' && ch != '\n' && ch != '\r' && ch != 0xA0;
|
||||
}).base(), s.end());
|
||||
}
|
||||
|
||||
// trim from both ends (in place)
|
||||
static inline void trim(std::string& s) {
|
||||
ltrim(s);
|
||||
rtrim(s);
|
||||
}
|
||||
|
||||
// LOCALE-INDEPENDENT uppercase conversion
|
||||
static inline void toUpperInvariant(std::string& s) {
|
||||
for (char& c : s) {
|
||||
if (c >= 'a' && c <= 'z') {
|
||||
c = c - 32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Normalize hardware string for consistent hashing
|
||||
static std::string NormalizeHardwareString(const std::string& input) {
|
||||
std::string s = input;
|
||||
|
||||
// Trim all types of whitespace
|
||||
trim(s);
|
||||
|
||||
// Remove all remaining whitespace characters
|
||||
s.erase(std::remove_if(s.begin(), s.end(), [](unsigned char c) {
|
||||
return c <= 32 || c == 0xA0; // Remove control chars and non-breaking space
|
||||
}), s.end());
|
||||
|
||||
// Locale-independent uppercase for ASCII
|
||||
toUpperInvariant(s);
|
||||
|
||||
// Remove non-ASCII characters (Korean text, etc.)
|
||||
s.erase(std::remove_if(s.begin(), s.end(), [](unsigned char c) {
|
||||
return c > 127;
|
||||
}), s.end());
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
const char* HardwareId::GetCurrentHardwareId()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
WmiHelper wmi;
|
||||
#endif
|
||||
|
||||
BitStream3 bits(125);
|
||||
list<string> propList;
|
||||
unsigned char version = 1;
|
||||
unsigned short hash1, hash2, hash3, hash4;
|
||||
unsigned short h0 = HashInt(0);
|
||||
|
||||
bits.Write(&version, 3);
|
||||
|
||||
propList.clear();
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
wmi.GetPropertyList("SELECT * FROM Win32_ComputerSystemProduct", "UUID", &propList);
|
||||
|
||||
hash1 = h0;
|
||||
|
||||
string s;
|
||||
|
||||
for (list<string>::iterator iter = propList.begin(); iter != propList.end(); iter++)
|
||||
{
|
||||
s = NormalizeHardwareString(*iter);
|
||||
|
||||
if ((s.length() > 1)
|
||||
&& (s != "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
|
||||
&& (s != "00000000000000000000000000000000"))
|
||||
{
|
||||
hash1 = HashString(s.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
propList.push_back("4294967296");
|
||||
#endif
|
||||
|
||||
bits.WriteUInt16(hash1);
|
||||
|
||||
// CPU IDs - get up to 4 for better resilience
|
||||
propList.clear();
|
||||
|
||||
#ifdef _WIN32
|
||||
wmi.GetPropertyList("SELECT ProcessorId FROM Win32_Processor", "ProcessorId", &propList, 4);
|
||||
#else
|
||||
GetCPUIDPropertyList(&propList);
|
||||
#endif
|
||||
|
||||
// Normalize CPU IDs
|
||||
for (auto& cpu : propList) {
|
||||
cpu = NormalizeHardwareString(cpu);
|
||||
}
|
||||
|
||||
hash1 = (propList.size() > 0) ? HashString(propList.front().c_str()) : h0;
|
||||
hash2 = (propList.size() > 1) ? HashString(propList.back().c_str()) : h0;
|
||||
|
||||
bits.WriteUInt16(hash1);
|
||||
bits.WriteUInt16(hash2);
|
||||
|
||||
// MAC Addresses - get MORE adapters and sort for consistency
|
||||
propList.clear();
|
||||
|
||||
#ifdef _WIN32
|
||||
// Try physical PCI adapters first
|
||||
wmi.GetPropertyList("SELECT MACAddress FROM Win32_NetworkAdapter WHERE (AdapterType = \"Ethernet 802.3\") AND (MACAddress IS NOT NULL) AND PNPDeviceId LIKE \"%PCI%\"", "MACAddress", &propList, 6);
|
||||
|
||||
// Fallback to VMBUS for VMs
|
||||
if (propList.size() == 0)
|
||||
{
|
||||
wmi.GetPropertyList("SELECT MACAddress FROM Win32_NetworkAdapter WHERE (AdapterType = \"Ethernet 802.3\") AND (MACAddress IS NOT NULL) AND PNPDeviceId LIKE \"%VMBUS%\"", "MACAddress", &propList, 6);
|
||||
}
|
||||
#else
|
||||
GetMACPropertyList(&propList, 6);
|
||||
#endif
|
||||
|
||||
// Normalize and sort MAC addresses for consistent ordering
|
||||
for (auto& mac : propList) {
|
||||
mac = NormalizeHardwareString(mac);
|
||||
}
|
||||
propList.sort();
|
||||
|
||||
// Store up to 4 MAC hashes
|
||||
auto macIter = propList.begin();
|
||||
hash1 = (propList.size() > 0 && macIter != propList.end()) ? HashString((macIter++)->c_str()) : h0;
|
||||
hash2 = (propList.size() > 1 && macIter != propList.end()) ? HashString((macIter++)->c_str()) : h0;
|
||||
hash3 = (propList.size() > 2 && macIter != propList.end()) ? HashString((macIter++)->c_str()) : h0;
|
||||
hash4 = (propList.size() > 3 && macIter != propList.end()) ? HashString((macIter++)->c_str()) : h0;
|
||||
|
||||
bits.WriteUInt16(hash1);
|
||||
bits.WriteUInt16(hash2);
|
||||
bits.WriteUInt16(hash3);
|
||||
bits.WriteUInt16(hash4);
|
||||
|
||||
// HDD Serial Numbers - get more drives and sort
|
||||
propList.clear();
|
||||
|
||||
#ifdef _WIN32
|
||||
wmi.GetPropertyList("SELECT SerialNumber FROM Win32_PhysicalMedia WHERE SerialNumber IS NOT NULL", "SerialNumber", &propList, 4);
|
||||
#else
|
||||
GetHDDPropertyList(&propList, 4);
|
||||
#endif
|
||||
|
||||
// Normalize and sort HDD serials
|
||||
for (auto& serial : propList) {
|
||||
serial = NormalizeHardwareString(serial);
|
||||
}
|
||||
propList.sort();
|
||||
|
||||
auto hddIter = propList.begin();
|
||||
hash1 = (propList.size() > 0 && hddIter != propList.end()) ? HashString((hddIter++)->c_str()) : h0;
|
||||
hash2 = (propList.size() > 1 && hddIter != propList.end()) ? HashString((hddIter++)->c_str()) : h0;
|
||||
|
||||
bits.WriteUInt16(hash1);
|
||||
bits.WriteUInt16(hash2);
|
||||
|
||||
unsigned char* rawHwid = bits.GetBuffer();
|
||||
|
||||
BASE32 base32;
|
||||
|
||||
auto encHwid = base32.encode(rawHwid, 16);
|
||||
|
||||
hardwareId = encHwid.c_str();
|
||||
|
||||
hardwareId.erase(hardwareId.length() - 1);
|
||||
|
||||
unsigned i;
|
||||
unsigned insertPos;
|
||||
// separate character groups
|
||||
for (i = 0, insertPos = 5; i < 4; i++)
|
||||
{
|
||||
hardwareId.insert(insertPos, "-");
|
||||
insertPos += 6;
|
||||
}
|
||||
|
||||
return hardwareId.c_str();
|
||||
}
|
||||
|
||||
bool HardwareId::MatchCurrentHardwareId(const char* hwid)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
WmiHelper wmi;
|
||||
#endif
|
||||
|
||||
unsigned short h0 = HashInt(0);
|
||||
string hardwareId((char*)hwid);
|
||||
|
||||
for (int i = 0, erasePos = 0; i < 4; i++)
|
||||
{
|
||||
erasePos += 5;
|
||||
hardwareId.erase(erasePos, 1);
|
||||
}
|
||||
|
||||
BASE32 base32;
|
||||
int bufLen;
|
||||
|
||||
int padLen;
|
||||
int len = base32.encode_pad_length(((int)hardwareId.length() * 5 + 7) >> 3, &padLen);
|
||||
|
||||
if (len > (int)hardwareId.length())
|
||||
hardwareId.append(len - hardwareId.length(), 'A');
|
||||
|
||||
if (padLen)
|
||||
hardwareId.append(padLen, '=');
|
||||
|
||||
auto buf = base32.decode(hardwareId.c_str(), hardwareId.length(), &bufLen);
|
||||
|
||||
BitStream3 bits;
|
||||
bits.Attach(buf.data(), 125);
|
||||
unsigned char version = 0;
|
||||
|
||||
bits.Read(&version, 3);
|
||||
|
||||
if ((version & 0x7) > 1)
|
||||
throw new LicensingException(STATUS_GENERIC_ERROR, "invalid hardware id version");
|
||||
|
||||
list<string> propList;
|
||||
set<unsigned short> storedHashes; // Store all hashes from license
|
||||
unsigned short hash1, hash2, hash3, hash4;
|
||||
|
||||
// Use a points-based matching system for resilience
|
||||
int matchPoints = 0;
|
||||
const int REQUIRED_POINTS = 2; // Need at least 2 components to match
|
||||
|
||||
// Read UUID hash
|
||||
bits.ReadUInt16(&hash1);
|
||||
|
||||
if (version == 0)
|
||||
{
|
||||
// Legacy version 0 support (memory size based)
|
||||
if (hash1 != h0)
|
||||
{
|
||||
unsigned long long memSize = 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
wmi.GetPropertyList("SELECT Capacity FROM Win32_PhysicalMemory", "Capacity", &propList);
|
||||
#else
|
||||
propList.push_back("4294967296");
|
||||
#endif
|
||||
|
||||
if (propList.size() > 0)
|
||||
{
|
||||
for (list<string>::iterator iter = propList.begin(); iter != propList.end(); iter++)
|
||||
{
|
||||
memSize += _atoi64(iter->c_str());
|
||||
}
|
||||
|
||||
memSize = memSize / (1024 * 1024);
|
||||
|
||||
if (hash1 != HashInt((int)memSize))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
matchPoints += 2; // UUID/Memory match gives 2 points
|
||||
}
|
||||
else
|
||||
{
|
||||
// Version 1+ - UUID based
|
||||
#ifdef _WIN32
|
||||
wmi.GetPropertyList("SELECT * FROM Win32_ComputerSystemProduct", "UUID", &propList);
|
||||
#endif
|
||||
if (propList.size() > 0)
|
||||
{
|
||||
string s = NormalizeHardwareString(propList.front());
|
||||
|
||||
if ((s.length() > 1)
|
||||
&& (s != "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
|
||||
&& (s != "00000000000000000000000000000000"))
|
||||
{
|
||||
if (hash1 != h0 && hash1 == HashString(s.c_str()))
|
||||
{
|
||||
matchPoints += 2; // UUID match is worth 2 points (most stable)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Read CPU hashes
|
||||
bits.ReadUInt16(&hash1);
|
||||
bits.ReadUInt16(&hash2);
|
||||
|
||||
storedHashes.clear();
|
||||
if (hash1 != h0) storedHashes.insert(hash1);
|
||||
if (hash2 != h0) storedHashes.insert(hash2);
|
||||
|
||||
propList.clear();
|
||||
|
||||
#ifdef _WIN32
|
||||
wmi.GetPropertyList("SELECT ProcessorId FROM Win32_Processor", "ProcessorId", &propList, 4);
|
||||
#else
|
||||
GetCPUIDPropertyList(&propList);
|
||||
#endif
|
||||
|
||||
// Check if ANY current CPU matches stored hashes
|
||||
int cpuMatches = 0;
|
||||
for (auto& cpu : propList) {
|
||||
string s = NormalizeHardwareString(cpu);
|
||||
unsigned short currentHash = HashString(s.c_str());
|
||||
if (storedHashes.find(currentHash) != storedHashes.end()) {
|
||||
cpuMatches++;
|
||||
}
|
||||
}
|
||||
|
||||
if (cpuMatches > 0) {
|
||||
matchPoints += 1; // CPU match is worth 1 point
|
||||
}
|
||||
|
||||
// Read MAC hashes (now 4 hashes for better resilience)
|
||||
bits.ReadUInt16(&hash1);
|
||||
bits.ReadUInt16(&hash2);
|
||||
bits.ReadUInt16(&hash3);
|
||||
bits.ReadUInt16(&hash4);
|
||||
|
||||
storedHashes.clear();
|
||||
if (hash1 != h0) storedHashes.insert(hash1);
|
||||
if (hash2 != h0) storedHashes.insert(hash2);
|
||||
if (hash3 != h0) storedHashes.insert(hash3);
|
||||
if (hash4 != h0) storedHashes.insert(hash4);
|
||||
|
||||
propList.clear();
|
||||
|
||||
#ifdef _WIN32
|
||||
wmi.GetPropertyList("SELECT MACAddress FROM Win32_NetworkAdapter WHERE (AdapterType = \"Ethernet 802.3\") AND (MACAddress IS NOT NULL) AND PNPDeviceId LIKE \"%PCI%\"", "MACAddress", &propList, 10);
|
||||
|
||||
if (propList.size() == 0)
|
||||
{
|
||||
wmi.GetPropertyList("SELECT MACAddress FROM Win32_NetworkAdapter WHERE (AdapterType = \"Ethernet 802.3\") AND (MACAddress IS NOT NULL) AND PNPDeviceId LIKE \"%VMBUS%\"", "MACAddress", &propList, 10);
|
||||
}
|
||||
#else
|
||||
GetMACPropertyList(&propList, 10);
|
||||
#endif
|
||||
|
||||
// Check if ANY current MAC address matches stored hashes
|
||||
int macMatches = 0;
|
||||
for (auto& mac : propList) {
|
||||
string s = NormalizeHardwareString(mac);
|
||||
unsigned short currentHash = HashString(s.c_str());
|
||||
if (storedHashes.find(currentHash) != storedHashes.end()) {
|
||||
macMatches++;
|
||||
}
|
||||
}
|
||||
|
||||
if (macMatches > 0) {
|
||||
matchPoints += 1; // MAC match is worth 1 point
|
||||
}
|
||||
|
||||
// Read HDD hashes
|
||||
bits.ReadUInt16(&hash1);
|
||||
bits.ReadUInt16(&hash2);
|
||||
|
||||
storedHashes.clear();
|
||||
if (hash1 != h0) storedHashes.insert(hash1);
|
||||
if (hash2 != h0) storedHashes.insert(hash2);
|
||||
|
||||
propList.clear();
|
||||
|
||||
#ifdef _WIN32
|
||||
wmi.GetPropertyList("SELECT SerialNumber FROM Win32_PhysicalMedia WHERE SerialNumber IS NOT NULL", "SerialNumber", &propList, 10);
|
||||
#else
|
||||
GetHDDPropertyList(&propList, 10);
|
||||
#endif
|
||||
|
||||
// Check if ANY current HDD serial matches stored hashes
|
||||
int hddMatches = 0;
|
||||
for (auto& serial : propList) {
|
||||
string s = NormalizeHardwareString(serial);
|
||||
unsigned short currentHash = HashString(s.c_str());
|
||||
if (storedHashes.find(currentHash) != storedHashes.end()) {
|
||||
hddMatches++;
|
||||
}
|
||||
}
|
||||
|
||||
if (hddMatches > 0) {
|
||||
matchPoints += 1; // HDD match is worth 1 point
|
||||
}
|
||||
|
||||
// Validation passes if we have enough matching points
|
||||
// Typical valid scenarios:
|
||||
// - UUID (2) + CPU (1) = 3 points ✓
|
||||
// - UUID (2) + MAC (1) = 3 points ✓
|
||||
// - UUID (2) + HDD (1) = 3 points ✓
|
||||
// - CPU (1) + MAC (1) + HDD (1) = 3 points ✓ (if UUID changed but hardware same)
|
||||
return matchPoints >= REQUIRED_POINTS;
|
||||
}
|
||||
16
core/anslicensing/hwid.h
Normal file
16
core/anslicensing/hwid.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef __HARDWARE_ID_H
|
||||
#define __HARDWARE_ID_H
|
||||
|
||||
class HardwareId
|
||||
{
|
||||
public:
|
||||
static const char * GetCurrentHardwareId();
|
||||
static bool MatchCurrentHardwareId(const char * hwid);
|
||||
|
||||
private:
|
||||
static unsigned short HashString(const char * str);
|
||||
static unsigned short HashInt(int val);
|
||||
static string hardwareId;
|
||||
};
|
||||
|
||||
#endif
|
||||
360
core/anslicensing/license.cpp
Normal file
360
core/anslicensing/license.cpp
Normal file
@@ -0,0 +1,360 @@
|
||||
#include "precomp.h"
|
||||
|
||||
#include "anslicensing.h"
|
||||
#include "license.h"
|
||||
#include "uniconv.h"
|
||||
#include "except.h"
|
||||
#include "tinyxml2.h"
|
||||
#include "picojson.h"
|
||||
#include "base64.h"
|
||||
|
||||
void LicenseImpl::LoadXml(const char * xmlTemplate)
|
||||
{
|
||||
tinyxml2::XMLDocument xml;
|
||||
tinyxml2::XMLElement * rootElement, *element;
|
||||
const char * attr;
|
||||
int version = 1;
|
||||
|
||||
if (xml.Parse(xmlTemplate) != tinyxml2::XML_NO_ERROR)
|
||||
throw new LicensingException(STATUS_INVALID_XML);
|
||||
|
||||
if ((element = rootElement = xml.FirstChildElement()) == NULL)
|
||||
throw new LicensingException(STATUS_INVALID_XML);
|
||||
|
||||
if ((attr = element->Attribute("version")) != NULL)
|
||||
version = atoi(attr);
|
||||
|
||||
if (version > 1)
|
||||
throw new LicensingException(STATUS_GENERIC_ERROR, "unsupported license version");
|
||||
|
||||
bool isLease = false;
|
||||
|
||||
if ((attr = element->Attribute("isLease")) != NULL)
|
||||
isLease = (_stricmp(attr, "1") == 0 || _stricmp(attr, "true") == 0);
|
||||
|
||||
m_isLease = isLease;
|
||||
|
||||
if ((element = rootElement->FirstChildElement("LicenseKey")) == NULL)
|
||||
throw new LicensingException(STATUS_GENERIC_ERROR, "license key not found");
|
||||
|
||||
m_licenseKey = element->GetText();
|
||||
|
||||
if ((element = rootElement->FirstChildElement("LicenseKeyValidationData")) != NULL)
|
||||
{
|
||||
BASE64 base64;
|
||||
|
||||
m_licenseKeyValidationData = base64.decode(element->GetText(), strlen(element->GetText()), nullptr);
|
||||
|
||||
if (!m_licenseKeyValidationData.empty())
|
||||
throw new LicensingException(STATUS_GENERIC_ERROR, "invalid BASE64 string");
|
||||
}
|
||||
|
||||
if ((element = rootElement->FirstChildElement("ActivationKey")) == NULL)
|
||||
throw new LicensingException(STATUS_GENERIC_ERROR, "license key not found");
|
||||
|
||||
m_activationKey = element->GetText();
|
||||
|
||||
if ((element = rootElement->FirstChildElement("HardwareId")) == NULL)
|
||||
throw new LicensingException(STATUS_GENERIC_ERROR, "license key not found");
|
||||
|
||||
m_hardwareId = element->GetText();
|
||||
}
|
||||
|
||||
#ifndef MAX_XML_BUFFER_SIZE
|
||||
#define MAX_XML_BUFFER_SIZE 4096
|
||||
#endif
|
||||
|
||||
const char * LicenseImpl::SaveXml()
|
||||
{
|
||||
BASE64 base64;
|
||||
char buffer[MAX_XML_BUFFER_SIZE];
|
||||
|
||||
m_xmlLicense.resize(0);
|
||||
|
||||
snprintf(buffer, MAX_XML_BUFFER_SIZE, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"); m_xmlLicense.append(buffer);
|
||||
snprintf(buffer, MAX_XML_BUFFER_SIZE, "<License version=\"%d\" isLease=\"%d\">\n", m_version, (m_isLease) ? 1 : 0); m_xmlLicense.append(buffer);
|
||||
snprintf(buffer, MAX_XML_BUFFER_SIZE, "\t<LicenseKey>%s</LicenseKey>\n", m_licenseKey.c_str()); m_xmlLicense.append(buffer);
|
||||
|
||||
if (!m_licenseKeyValidationData.empty())
|
||||
{
|
||||
BASE64 base64;
|
||||
|
||||
auto enc = base64.encode(m_licenseKeyValidationData.data(), m_licenseKeyValidationData.size(), true);
|
||||
|
||||
if (!enc.empty())
|
||||
{
|
||||
snprintf(buffer, MAX_XML_BUFFER_SIZE, "\t<LicenseKeyValidationData>"); m_xmlLicense.append(buffer);
|
||||
m_xmlLicense.append(enc);
|
||||
snprintf(buffer, MAX_XML_BUFFER_SIZE, "</LicenseKeyValidationData>\n"); m_xmlLicense.append(buffer);
|
||||
}
|
||||
else
|
||||
throw new LicensingException(STATUS_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
snprintf(buffer, MAX_XML_BUFFER_SIZE, "\t<ActivationKey>%s</ActivationKey>\n", m_activationKey.c_str()); m_xmlLicense.append(buffer);
|
||||
snprintf(buffer, MAX_XML_BUFFER_SIZE, "\t<HardwareId>%s</HardwareId>\n", m_hardwareId.c_str()); m_xmlLicense.append(buffer);
|
||||
snprintf(buffer, MAX_XML_BUFFER_SIZE, "</License>"); m_xmlLicense.append(buffer);
|
||||
|
||||
return m_xmlLicense.c_str();
|
||||
}
|
||||
|
||||
void LicenseImpl::LoadJson(const char * jsonLicense)
|
||||
{
|
||||
picojson::value json;
|
||||
|
||||
auto err = picojson::parse(json, jsonLicense);
|
||||
|
||||
if (!err.empty())
|
||||
throw new LicensingException(STATUS_INVALID_PARAM);
|
||||
|
||||
picojson::object license = json.get<picojson::object>();
|
||||
|
||||
auto version = license["version"].get<double>();
|
||||
|
||||
if (version > 1)
|
||||
throw new LicensingException(STATUS_GENERIC_ERROR, "unsupported license version");
|
||||
|
||||
m_isLease = license.count("is_lease") ? license["is_lease"].get<bool>() : false;
|
||||
|
||||
m_licenseKey = license["license_key"].get<string>();
|
||||
|
||||
if (license.count("license_key_validation_data"))
|
||||
{
|
||||
BASE64 base64;
|
||||
m_licenseKeyValidationData = base64.decode(license["license_key_validation_data"].get<string>().c_str());
|
||||
}
|
||||
|
||||
m_activationKey = license["activation_key"].get<string>();
|
||||
|
||||
m_hardwareId = license["hardware_id"].get<string>();
|
||||
}
|
||||
|
||||
#ifndef MAX_JSON_BUFFER_SIZE
|
||||
#define MAX_JSON_BUFFER_SIZE 4096
|
||||
#endif
|
||||
|
||||
const char * LicenseImpl::SaveJson()
|
||||
{
|
||||
picojson::object license;
|
||||
BASE64 base64;
|
||||
|
||||
license["version"] = picojson::value((double)1);
|
||||
license["is_lease"] = picojson::value(m_isLease);
|
||||
license["license_key"] = picojson::value(m_licenseKey);
|
||||
license["hardware_id"] = picojson::value(m_hardwareId);
|
||||
license["activation_key"] = picojson::value(m_activationKey);
|
||||
|
||||
if (!m_licenseKeyValidationData.empty())
|
||||
license["license_key_validation_data"] = picojson::value(base64.encode(m_licenseKeyValidationData.data(), m_licenseKeyValidationData.size(), true));
|
||||
|
||||
m_jsonLicense = picojson::value(license).serialize(true);
|
||||
|
||||
return m_jsonLicense.c_str();
|
||||
}
|
||||
|
||||
namespace ANSCENTER {
|
||||
namespace Licensing {
|
||||
template<>
|
||||
LicenseT<char>::LicenseT() :
|
||||
m_Impl(*new LicenseImpl())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
template<>
|
||||
LicenseT<wchar_t>::LicenseT() :
|
||||
m_Impl(*new LicenseImpl())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
template<>
|
||||
LicenseT<char>::~LicenseT()
|
||||
{
|
||||
delete& m_Impl;
|
||||
}
|
||||
|
||||
template<>
|
||||
LicenseT<wchar_t>::~LicenseT()
|
||||
{
|
||||
delete& m_Impl;
|
||||
}
|
||||
|
||||
template<>
|
||||
const char* LicenseT<char>::SaveXml()
|
||||
{
|
||||
return m_Impl.SaveXml();
|
||||
}
|
||||
|
||||
template<>
|
||||
const char* LicenseT<wchar_t>::SaveXml()
|
||||
{
|
||||
return m_Impl.SaveXml();
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicenseT<char>::LoadXml(const char* xml)
|
||||
{
|
||||
m_Impl.LoadXml(xml);
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicenseT<wchar_t>::LoadXml(const char* xml)
|
||||
{
|
||||
m_Impl.LoadXml(xml);
|
||||
}
|
||||
|
||||
template<>
|
||||
const char* LicenseT<char>::SaveJson()
|
||||
{
|
||||
return m_Impl.SaveJson();
|
||||
}
|
||||
|
||||
template<>
|
||||
const char* LicenseT<wchar_t>::SaveJson()
|
||||
{
|
||||
return m_Impl.SaveJson();
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicenseT<char>::LoadJson(const char* xml)
|
||||
{
|
||||
m_Impl.LoadJson(xml);
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicenseT<wchar_t>::LoadJson(const char* xml)
|
||||
{
|
||||
m_Impl.LoadJson(xml);
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicenseT<char>::SetLicenseKey(const char* licenseKey)
|
||||
{
|
||||
m_Impl.SetLicenseKey(licenseKey);
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicenseT<wchar_t>::SetLicenseKey(const wchar_t* licenseKey)
|
||||
{
|
||||
m_Impl.SetLicenseKey(w2s(licenseKey).c_str());
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicenseT<char>::SetLicenseKeyValidationData(void* validationData, int validationDataLen)
|
||||
{
|
||||
m_Impl.SetLicenseKeyValidationData((const unsigned char*)validationData, validationDataLen);
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicenseT<wchar_t>::SetLicenseKeyValidationData(void* validationData, int validationDataLen)
|
||||
{
|
||||
m_Impl.SetLicenseKeyValidationData((const unsigned char*)validationData, validationDataLen);
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicenseT<char>::GetLicenseKeyValidationData(void** buf, int* len)
|
||||
{
|
||||
m_Impl.GetLicenseKeyValidationData((const void**)buf, len);
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicenseT<wchar_t>::GetLicenseKeyValidationData(void** buf, int* len)
|
||||
{
|
||||
m_Impl.GetLicenseKeyValidationData((const void**)buf, len);
|
||||
}
|
||||
|
||||
template<>
|
||||
const char* LicenseT<char>::GetLicenseKey()
|
||||
{
|
||||
return m_Impl.GetLicenseKey();
|
||||
}
|
||||
|
||||
template<>
|
||||
const wchar_t* LicenseT<wchar_t>::GetLicenseKey()
|
||||
{
|
||||
static wstring wstr1;
|
||||
|
||||
wstr1 = s2w(m_Impl.GetLicenseKey());
|
||||
return wstr1.c_str();
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicenseT<char>::SetActivationKey(const char* activationKey)
|
||||
{
|
||||
m_Impl.SetActivationKey(activationKey);
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicenseT<wchar_t>::SetActivationKey(const wchar_t* activationKey)
|
||||
{
|
||||
m_Impl.SetActivationKey(w2s(activationKey).c_str());
|
||||
}
|
||||
|
||||
template<>
|
||||
const char* LicenseT<char>::GetActivationKey()
|
||||
{
|
||||
return m_Impl.GetActivationKey();
|
||||
}
|
||||
|
||||
template<>
|
||||
const wchar_t* LicenseT<wchar_t>::GetActivationKey()
|
||||
{
|
||||
static wstring wstr1;
|
||||
|
||||
wstr1 = s2w(m_Impl.GetActivationKey());
|
||||
return wstr1.c_str();
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicenseT<char>::SetHardwareId(const char* hardwareId)
|
||||
{
|
||||
m_Impl.SetHardwareId(hardwareId);
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicenseT<wchar_t>::SetHardwareId(const wchar_t* hardwareId)
|
||||
{
|
||||
m_Impl.SetHardwareId(w2s(hardwareId).c_str());
|
||||
}
|
||||
|
||||
template<>
|
||||
const char* LicenseT<char>::GetHardwareId()
|
||||
{
|
||||
return m_Impl.GetHardwareId();
|
||||
}
|
||||
|
||||
template<>
|
||||
const wchar_t* LicenseT<wchar_t>::GetHardwareId()
|
||||
{
|
||||
static wstring wstr1;
|
||||
|
||||
wstr1 = s2w(m_Impl.GetHardwareId());
|
||||
return wstr1.c_str();
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicenseT<char>::SetLease(bool isLease)
|
||||
{
|
||||
m_Impl.SetLease(isLease);
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicenseT<wchar_t>::SetLease(bool isLease)
|
||||
{
|
||||
m_Impl.SetLease(isLease);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool LicenseT<char>::IsLease()
|
||||
{
|
||||
return m_Impl.IsLease();
|
||||
}
|
||||
|
||||
template<>
|
||||
bool LicenseT<wchar_t>::IsLease()
|
||||
{
|
||||
return m_Impl.IsLease();
|
||||
}
|
||||
};
|
||||
}
|
||||
104
core/anslicensing/license.h
Normal file
104
core/anslicensing/license.h
Normal file
@@ -0,0 +1,104 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "except.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class LicenseImpl {
|
||||
|
||||
friend class LicenseValidationResultT<char>;
|
||||
friend class LicenseValidationResultT<wchar_t>;
|
||||
|
||||
public:
|
||||
LicenseImpl():
|
||||
m_isLease(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CopyFrom(const LicenseImpl * src)
|
||||
{
|
||||
m_activationKey = src->m_activationKey;
|
||||
m_hardwareId = src->m_hardwareId;
|
||||
m_isLease = src->m_isLease;
|
||||
m_licenseKey = src->m_licenseKey;
|
||||
m_xmlLicense = src->m_xmlLicense;
|
||||
SetLicenseKeyValidationData(src->m_licenseKeyValidationData.data(), src->m_licenseKeyValidationData.size());
|
||||
}
|
||||
|
||||
void LoadXml(const char * xml);
|
||||
const char * SaveXml();
|
||||
|
||||
void LoadJson(const char * json);
|
||||
const char * SaveJson();
|
||||
|
||||
const char * GetLicenseKey() const
|
||||
{
|
||||
return m_licenseKey.c_str();
|
||||
}
|
||||
|
||||
void SetLicenseKey(const char * licenseKey)
|
||||
{
|
||||
m_licenseKey = licenseKey;
|
||||
}
|
||||
|
||||
void GetLicenseKeyValidationData(const void ** buf, int * len) const
|
||||
{
|
||||
*buf = m_licenseKeyValidationData.data();
|
||||
*len = m_licenseKeyValidationData.size();
|
||||
}
|
||||
|
||||
void SetLicenseKeyValidationData(const void* buf, int len)
|
||||
{
|
||||
if (buf && len > 0)
|
||||
{
|
||||
m_licenseKeyValidationData.resize(len);
|
||||
memcpy(m_licenseKeyValidationData.data(), buf, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_licenseKeyValidationData.clear();
|
||||
}
|
||||
}
|
||||
|
||||
const char * GetActivationKey() const
|
||||
{
|
||||
return m_activationKey.c_str();
|
||||
}
|
||||
|
||||
void SetActivationKey(const char * activationKey)
|
||||
{
|
||||
m_activationKey = activationKey;
|
||||
}
|
||||
|
||||
const char * GetHardwareId() const
|
||||
{
|
||||
return m_hardwareId.c_str();
|
||||
}
|
||||
|
||||
void SetHardwareId(const char * hardwareId)
|
||||
{
|
||||
m_hardwareId = hardwareId;
|
||||
}
|
||||
|
||||
bool IsLease() const
|
||||
{
|
||||
return m_isLease;
|
||||
}
|
||||
|
||||
void SetLease(bool isLease)
|
||||
{
|
||||
m_isLease = isLease;
|
||||
}
|
||||
|
||||
private:
|
||||
string m_licenseKey;
|
||||
string m_activationKey;
|
||||
string m_hardwareId;
|
||||
vector<unsigned char> m_licenseKeyValidationData;
|
||||
bool m_isLease;
|
||||
string m_xmlLicense;
|
||||
string m_jsonLicense;
|
||||
static const int m_version = 1;
|
||||
};
|
||||
108
core/anslicensing/licensevalidationargs.cpp
Normal file
108
core/anslicensing/licensevalidationargs.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
#include "precomp.h"
|
||||
#include "anslicensing.h"
|
||||
#include "license.h"
|
||||
#include "uniconv.h"
|
||||
#include "licensevalidationargs.h"
|
||||
|
||||
namespace ANSCENTER {
|
||||
namespace Licensing {
|
||||
|
||||
template<>
|
||||
LicenseValidationArgsT<char>::LicenseValidationArgsT():
|
||||
m_Impl(*new LicenseValidationArgsImpl())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
template<>
|
||||
LicenseValidationArgsT<wchar_t>::LicenseValidationArgsT() :
|
||||
m_Impl(*new LicenseValidationArgsImpl())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
template<>
|
||||
LicenseValidationArgsT<char>::~LicenseValidationArgsT()
|
||||
{
|
||||
delete & m_Impl;
|
||||
}
|
||||
|
||||
template<>
|
||||
LicenseValidationArgsT<wchar_t>::~LicenseValidationArgsT()
|
||||
{
|
||||
delete & m_Impl;
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicenseValidationArgsT<char>::SetLicenseKey(const char * licenseKey)
|
||||
{
|
||||
m_Impl.SetLicenseKey(licenseKey);
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicenseValidationArgsT<wchar_t>::SetLicenseKey(const wchar_t * licenseKey)
|
||||
{
|
||||
m_Impl.SetLicenseKey(w2s(licenseKey).c_str());
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicenseValidationArgsT<char>::SetLicense(const LicenseT<char> * license)
|
||||
{
|
||||
m_Impl.SetLicense(&license->m_Impl);
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicenseValidationArgsT<wchar_t>::SetLicense(const LicenseT<wchar_t> * license)
|
||||
{
|
||||
m_Impl.SetLicense(&license->m_Impl);
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicenseValidationArgsT<char>::SetLicenseKeyValidationData(const char * fieldName, int fieldValue)
|
||||
{
|
||||
m_Impl.SetLicenseKeyValidationData(fieldName, fieldValue);
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicenseValidationArgsT<wchar_t>::SetLicenseKeyValidationData(const wchar_t * fieldName, int fieldValue)
|
||||
{
|
||||
m_Impl.SetLicenseKeyValidationData(w2s(fieldName).c_str(), fieldValue);
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicenseValidationArgsT<char>::SetLicenseKeyValidationData(const char * fieldName, const char * fieldValue)
|
||||
{
|
||||
m_Impl.SetLicenseKeyValidationData(fieldName, fieldValue);
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicenseValidationArgsT<wchar_t>::SetLicenseKeyValidationData(const wchar_t * fieldName, const wchar_t * fieldValue)
|
||||
{
|
||||
m_Impl.SetLicenseKeyValidationData(w2s(fieldName).c_str(), w2s(fieldValue).c_str());
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicenseValidationArgsT<char>::SetLicenseKeyValidationData(const char * fieldName, int year, int month, int day)
|
||||
{
|
||||
m_Impl.SetLicenseKeyValidationData(fieldName, year, month, day);
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicenseValidationArgsT<wchar_t>::SetLicenseKeyValidationData(const wchar_t * fieldName, int year, int month, int day)
|
||||
{
|
||||
m_Impl.SetLicenseKeyValidationData(w2s(fieldName).c_str(), year, month, day);
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicenseValidationArgsT<char>::SetLicenseKeyValidationData(const char * fieldName, void * data, int len)
|
||||
{
|
||||
m_Impl.SetLicenseKeyValidationData(fieldName, data, len);
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicenseValidationArgsT<wchar_t>::SetLicenseKeyValidationData(const wchar_t * fieldName, void * data, int len)
|
||||
{
|
||||
m_Impl.SetLicenseKeyValidationData(w2s(fieldName).c_str(), data, len);
|
||||
}
|
||||
};
|
||||
};
|
||||
109
core/anslicensing/licensevalidationargs.h
Normal file
109
core/anslicensing/licensevalidationargs.h
Normal file
@@ -0,0 +1,109 @@
|
||||
#pragma once
|
||||
|
||||
#include "license.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
|
||||
using namespace std;
|
||||
|
||||
struct NameValuePair {
|
||||
public:
|
||||
NameValuePair(const char* _name, const char* _value):
|
||||
name(_name),
|
||||
stringValue(_value)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
NameValuePair(const char* _name, int _value):
|
||||
name(_name),
|
||||
intValue(_value)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
NameValuePair(const char* _name, int _year, int _month, int _day):
|
||||
name(_name),
|
||||
dateValue { _year, _month, _day }
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
NameValuePair(const char* _name, const unsigned char* _value, int _len):
|
||||
name(_name),
|
||||
binaryValue(_value, _value + _len)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
string name;
|
||||
|
||||
int intValue;
|
||||
|
||||
string stringValue;
|
||||
|
||||
struct {
|
||||
int year, month, day;
|
||||
} dateValue;
|
||||
|
||||
vector<unsigned char> binaryValue;
|
||||
};
|
||||
|
||||
class LicenseValidationArgsImpl
|
||||
{
|
||||
friend LicensingClient;
|
||||
|
||||
public:
|
||||
LicenseValidationArgsImpl():
|
||||
m_license(nullptr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SetLicense(LicenseImpl * license)
|
||||
{
|
||||
m_license = license;
|
||||
}
|
||||
|
||||
const LicenseImpl * GetLicense()
|
||||
{
|
||||
return m_license;
|
||||
}
|
||||
|
||||
void SetLicenseKey(const char * licenseKey, int validationDataSize = 0)
|
||||
{
|
||||
m_licenseKey = licenseKey;
|
||||
}
|
||||
|
||||
void SetLicenseKeyValidationData(const char * fieldName, const char * fieldValue)
|
||||
{
|
||||
m_licenseKeyValidationData.emplace_back(fieldName, fieldValue);
|
||||
}
|
||||
|
||||
void SetLicenseKeyValidationData(const char * fieldName, int fieldValue)
|
||||
{
|
||||
m_licenseKeyValidationData.emplace_back(fieldName, fieldValue);
|
||||
}
|
||||
|
||||
void SetLicenseKeyValidationData(const char * fieldName, int year, int month, int day)
|
||||
{
|
||||
m_licenseKeyValidationData.emplace_back(fieldName, year, month, day);
|
||||
}
|
||||
|
||||
void SetLicenseKeyValidationData(const char * fieldName, void * data, int len)
|
||||
{
|
||||
m_licenseKeyValidationData.emplace_back(fieldName, (unsigned char*)data, len);
|
||||
}
|
||||
|
||||
const char * GetLicenseKey()
|
||||
{
|
||||
return m_licenseKey.c_str();
|
||||
}
|
||||
|
||||
public:
|
||||
const LicenseImpl* m_license;
|
||||
int m_validationDataSize;
|
||||
string m_licenseKey;
|
||||
list<NameValuePair> m_licenseKeyValidationData;
|
||||
};
|
||||
111
core/anslicensing/licensevalidationresult.cpp
Normal file
111
core/anslicensing/licensevalidationresult.cpp
Normal file
@@ -0,0 +1,111 @@
|
||||
#include "precomp.h"
|
||||
#include "anslicensing.h"
|
||||
#include "uniconv.h"
|
||||
#include "licensevalidationresult.h"
|
||||
|
||||
namespace ANSCENTER {
|
||||
namespace Licensing {
|
||||
|
||||
template<>
|
||||
LicenseValidationResultT<char>::LicenseValidationResultT() :
|
||||
m_Impl(*new LicenseValidationResultImpl())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
template<>
|
||||
LicenseValidationResultT<wchar_t>::LicenseValidationResultT() :
|
||||
m_Impl(*new LicenseValidationResultImpl())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
template<>
|
||||
LicenseValidationResultT<char>::~LicenseValidationResultT()
|
||||
{
|
||||
delete & m_Impl;
|
||||
}
|
||||
|
||||
template<>
|
||||
LicenseValidationResultT<wchar_t>::~LicenseValidationResultT()
|
||||
{
|
||||
delete & m_Impl;
|
||||
}
|
||||
|
||||
template<>
|
||||
LicenseT<char> * LicenseValidationResultT<char>::GetLicense()
|
||||
{
|
||||
static LicenseT<char> result;
|
||||
|
||||
LicenseImpl * resultImpl = m_Impl.GetLicense();
|
||||
|
||||
if (!resultImpl) return NULL;
|
||||
|
||||
result.m_Impl.CopyFrom(resultImpl);
|
||||
|
||||
return &result;
|
||||
}
|
||||
|
||||
template<>
|
||||
LicenseT<wchar_t> * LicenseValidationResultT<wchar_t>::GetLicense()
|
||||
{
|
||||
static LicenseT<wchar_t> result;
|
||||
|
||||
LicenseImpl * resultImpl = m_Impl.GetLicense();
|
||||
|
||||
if (!resultImpl) return NULL;
|
||||
|
||||
result.m_Impl.CopyFrom(resultImpl);
|
||||
|
||||
return &result;
|
||||
}
|
||||
|
||||
template<>
|
||||
bool LicenseValidationResultT<char>::IsLicenseExpired()
|
||||
{
|
||||
return m_Impl.IsLicenseExpired();
|
||||
}
|
||||
|
||||
template<>
|
||||
bool LicenseValidationResultT<wchar_t>::IsLicenseExpired()
|
||||
{
|
||||
return m_Impl.IsLicenseExpired();
|
||||
}
|
||||
|
||||
template<>
|
||||
bool LicenseValidationResultT<char>::IsPaymentRequired()
|
||||
{
|
||||
return m_Impl.IsPaymentRequired();
|
||||
}
|
||||
|
||||
template<>
|
||||
bool LicenseValidationResultT<wchar_t>::IsPaymentRequired()
|
||||
{
|
||||
return m_Impl.IsPaymentRequired();
|
||||
}
|
||||
|
||||
template<>
|
||||
int LicenseValidationResultT<char>::GetLicenseValidityDays()
|
||||
{
|
||||
return m_Impl.GetLicenseValidityDays();
|
||||
}
|
||||
|
||||
template<>
|
||||
int LicenseValidationResultT<wchar_t>::GetLicenseValidityDays()
|
||||
{
|
||||
return m_Impl.GetLicenseValidityDays();
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicenseValidationResultT<char>::GetLicenseExpirationDate(int * year, int * month, int * day)
|
||||
{
|
||||
m_Impl.GetLicenseExpirationDate(year, month, day);
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicenseValidationResultT<wchar_t>::GetLicenseExpirationDate(int * year, int * month, int * day)
|
||||
{
|
||||
m_Impl.GetLicenseExpirationDate(year, month, day);
|
||||
}
|
||||
};
|
||||
};
|
||||
118
core/anslicensing/licensevalidationresult.h
Normal file
118
core/anslicensing/licensevalidationresult.h
Normal file
@@ -0,0 +1,118 @@
|
||||
#ifndef __LICENSEVALIDATIONRESULT_H
|
||||
#define __LICENSEVALIDATIONRESULT_H
|
||||
|
||||
#include <memory>
|
||||
#include "license.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class LicensingClientImpl;
|
||||
|
||||
class LicenseValidationResultImpl
|
||||
{
|
||||
//friend class LicensingClientT<char>;
|
||||
//friend class LicensingClientT<wchar_t>;
|
||||
friend class LicensingClientImpl;
|
||||
friend class LicenseValidationResultT<char>;
|
||||
friend class LicenseValidationResultT<wchar_t>;
|
||||
|
||||
public:
|
||||
LicenseValidationResultImpl()
|
||||
{
|
||||
m_isLicenseExpired = false;
|
||||
m_isPaymentRequired = false;
|
||||
m_licenseValidityDays = 0;
|
||||
m_licenseExpirationYear = m_licenseExpirationMonth = m_licenseExpirationDay = 0;
|
||||
}
|
||||
|
||||
~LicenseValidationResultImpl()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void MoveFrom(LicenseValidationResultImpl& src)
|
||||
{
|
||||
m_isLicenseExpired = src.m_isLicenseExpired;
|
||||
m_isLicenseValid = src.m_isLicenseValid;
|
||||
m_isPaymentRequired = src.m_isPaymentRequired;
|
||||
m_license = std::move(src.m_license);
|
||||
m_licenseValidityDays = src.m_licenseValidityDays;
|
||||
m_licenseExpirationDay = src.m_licenseExpirationDay;
|
||||
m_licenseExpirationMonth = src.m_licenseExpirationMonth;
|
||||
m_licenseExpirationYear = src.m_licenseExpirationYear;
|
||||
}
|
||||
|
||||
LicenseImpl * GetLicense()
|
||||
{
|
||||
return m_license.get();
|
||||
}
|
||||
|
||||
void SetLicense(LicenseImpl * lic)
|
||||
{
|
||||
m_license.reset(lic);
|
||||
}
|
||||
|
||||
bool IsLicenseValid()
|
||||
{
|
||||
return m_isLicenseValid;
|
||||
}
|
||||
|
||||
void SetLicenseValid(bool isValid)
|
||||
{
|
||||
m_isLicenseValid = isValid;
|
||||
}
|
||||
|
||||
bool IsLicenseExpired()
|
||||
{
|
||||
return m_isLicenseExpired;
|
||||
}
|
||||
|
||||
void SetLicenseExpired(bool licenseExpired)
|
||||
{
|
||||
m_isLicenseExpired = licenseExpired;
|
||||
}
|
||||
|
||||
bool IsPaymentRequired()
|
||||
{
|
||||
return m_isPaymentRequired;
|
||||
}
|
||||
|
||||
void SetPaymentRequired(bool paymentRequired)
|
||||
{
|
||||
m_isPaymentRequired = paymentRequired;
|
||||
}
|
||||
|
||||
int GetLicenseValidityDays()
|
||||
{
|
||||
return m_licenseValidityDays;
|
||||
}
|
||||
|
||||
void SetLicenseValidityDays(int days)
|
||||
{
|
||||
m_licenseValidityDays = days;
|
||||
}
|
||||
|
||||
void GetLicenseExpirationDate(int * year, int * month, int * day)
|
||||
{
|
||||
*year = m_licenseExpirationYear;
|
||||
*month = m_licenseExpirationMonth;
|
||||
*day = m_licenseExpirationDay;
|
||||
}
|
||||
|
||||
void SetLicenseExpirationDate(int year, int month, int day)
|
||||
{
|
||||
m_licenseExpirationYear = year;
|
||||
m_licenseExpirationMonth = month;
|
||||
m_licenseExpirationDay = day;
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_isLicenseValid;
|
||||
bool m_isLicenseExpired;
|
||||
bool m_isPaymentRequired;
|
||||
int m_licenseValidityDays;
|
||||
int m_licenseExpirationYear, m_licenseExpirationMonth, m_licenseExpirationDay;
|
||||
unique_ptr<LicenseImpl> m_license;
|
||||
};
|
||||
|
||||
#endif
|
||||
289
core/anslicensing/licensingclient.cpp
Normal file
289
core/anslicensing/licensingclient.cpp
Normal file
@@ -0,0 +1,289 @@
|
||||
#include "precomp.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "licensingclient.h"
|
||||
#include "licensevalidationargs.h"
|
||||
#include "licensevalidationresult.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace ANSCENTER {
|
||||
namespace Licensing {
|
||||
|
||||
template<>
|
||||
LicensingClientT<wchar_t>::LicensingClientT():
|
||||
m_Impl(*(new LicensingClientImpl(this, true)))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
template<>
|
||||
LicensingClientT<char>::LicensingClientT():
|
||||
m_Impl(*(new LicensingClientImpl(this, false)))
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
template<>
|
||||
LicensingClientT<char>::~LicensingClientT()
|
||||
{
|
||||
delete & m_Impl;
|
||||
}
|
||||
|
||||
template<>
|
||||
LicensingClientT<wchar_t>::~LicensingClientT()
|
||||
{
|
||||
delete & m_Impl;
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicensingClientT<char>::SetLicenseTemplate(LicenseTemplateT<char> * tmpl)
|
||||
{
|
||||
m_Impl.SetLicenseTemplate(&tmpl->m_Impl);
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicensingClientT<wchar_t>::SetLicenseTemplate(LicenseTemplateT<wchar_t> * tmpl)
|
||||
{
|
||||
m_Impl.SetLicenseTemplate(&tmpl->m_Impl);
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicensingClientT<char>::SetLicenseKey(const char * key)
|
||||
{
|
||||
m_Impl.SetLicenseKey(key);
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicensingClientT<wchar_t>::SetLicenseKey(const wchar_t * key)
|
||||
{
|
||||
m_Impl.SetLicenseKey(w2s(key).c_str());
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicensingClientT<char>::SetActivationKey(const char * key)
|
||||
{
|
||||
m_Impl.SetActivationKey(key);
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicensingClientT<wchar_t>::SetActivationKey(const wchar_t * key)
|
||||
{
|
||||
m_Impl.SetActivationKey(w2s(key).c_str());
|
||||
}
|
||||
|
||||
template<>
|
||||
const char * LicensingClientT<char>::GetActivationKey()
|
||||
{
|
||||
return m_Impl.GetActivationKey();
|
||||
}
|
||||
|
||||
template<>
|
||||
const wchar_t * LicensingClientT<wchar_t>::GetActivationKey()
|
||||
{
|
||||
static wstring wstr1;
|
||||
|
||||
wstr1 = s2w(m_Impl.GetActivationKey());
|
||||
return wstr1.c_str();
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicensingClientT<char>::SetHardwareId(const char * hwid)
|
||||
{
|
||||
m_Impl.SetHardwareId(hwid);
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicensingClientT<wchar_t>::SetHardwareId(const wchar_t * hwid)
|
||||
{
|
||||
m_Impl.SetHardwareId(w2s(hwid).c_str());
|
||||
}
|
||||
|
||||
template<>
|
||||
const char * LicensingClientT<char>::GetHardwareId()
|
||||
{
|
||||
return m_Impl.GetHardwareId();
|
||||
}
|
||||
|
||||
template<>
|
||||
const wchar_t * LicensingClientT<wchar_t>::GetHardwareId()
|
||||
{
|
||||
static wstring wstr1;
|
||||
|
||||
wstr1 = s2w(m_Impl.GetHardwareId());
|
||||
return wstr1.c_str();
|
||||
}
|
||||
|
||||
template<>
|
||||
const wchar_t * LicensingClientT<wchar_t>::GetCurrentHardwareId()
|
||||
{
|
||||
static wstring wstr1;
|
||||
|
||||
wstr1 = s2w(m_Impl.GetCurrentHardwareId());
|
||||
return wstr1.c_str();
|
||||
}
|
||||
|
||||
template<>
|
||||
const char * LicensingClientT<char>::GetCurrentHardwareId()
|
||||
{
|
||||
return m_Impl.GetCurrentHardwareId();
|
||||
}
|
||||
|
||||
template<>
|
||||
bool LicensingClientT<char>::MatchCurrentHardwareId(const char * hwid)
|
||||
{
|
||||
return m_Impl.MatchCurrentHardwareId(hwid);
|
||||
}
|
||||
|
||||
template<>
|
||||
bool LicensingClientT<wchar_t>::MatchCurrentHardwareId(const wchar_t * hwid)
|
||||
{
|
||||
return m_Impl.MatchCurrentHardwareId(w2s(hwid).c_str());
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicensingClientT<char>::SetLicensingServiceUrl(const char * url)
|
||||
{
|
||||
|
||||
m_Impl.SetLicensingServiceUrl(url);
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicensingClientT<wchar_t>::SetLicensingServiceUrl(const wchar_t * url)
|
||||
{
|
||||
m_Impl.SetLicensingServiceUrl(w2s(url).c_str());
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicensingClientT<char>::SetLicenseTemplateId(const char * templateId)
|
||||
{
|
||||
m_Impl.SetLicenseTemplateId(templateId);
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicensingClientT<wchar_t>::SetLicenseTemplateId(const wchar_t * templateId)
|
||||
{
|
||||
m_Impl.SetLicenseTemplateId(w2s(templateId).c_str());
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicensingClientT<char>::AcquireLicense()
|
||||
{
|
||||
m_Impl.AcquireLicense();
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicensingClientT<wchar_t>::AcquireLicense()
|
||||
{
|
||||
m_Impl.AcquireLicense();
|
||||
}
|
||||
|
||||
template<>
|
||||
bool LicensingClientT<char>::IsLicenseValid()
|
||||
{
|
||||
return m_Impl.IsLicenseValid();
|
||||
}
|
||||
|
||||
template<>
|
||||
bool LicensingClientT<wchar_t>::IsLicenseValid()
|
||||
{
|
||||
return m_Impl.IsLicenseValid();
|
||||
}
|
||||
|
||||
template<>
|
||||
LicenseValidationResultT<char> * LicensingClientT<char>::ValidateLicense(LicenseValidationArgsT<char> * args)
|
||||
{
|
||||
static LicenseValidationResultT<char> result;
|
||||
|
||||
auto& resultImpl = m_Impl.ValidateLicense(&args->m_Impl);
|
||||
|
||||
result.m_Impl.MoveFrom(resultImpl);
|
||||
|
||||
return &result;
|
||||
}
|
||||
|
||||
template<>
|
||||
LicenseValidationResultT<wchar_t> * LicensingClientT<wchar_t>::ValidateLicense(LicenseValidationArgsT<wchar_t> * args)
|
||||
{
|
||||
static LicenseValidationResultT<wchar_t> result;
|
||||
|
||||
auto& resultImpl = m_Impl.ValidateLicense(&args->m_Impl);
|
||||
|
||||
result.m_Impl.MoveFrom(resultImpl);
|
||||
|
||||
return &result;
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicensingClientT<char>::SetLicenseKeyValidationData(void * data, int len)
|
||||
{
|
||||
return m_Impl.SetLicenseKeyValidationData(data, len);
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicensingClientT<wchar_t>::SetLicenseKeyValidationData(void * data, int len)
|
||||
{
|
||||
return m_Impl.SetLicenseKeyValidationData(data, len);
|
||||
}
|
||||
|
||||
template<>
|
||||
int LicensingClientT<char>::GetLicenseActivationStatus()
|
||||
{
|
||||
return m_Impl.GetLicenseActivationStatus();
|
||||
}
|
||||
|
||||
template<>
|
||||
int LicensingClientT<wchar_t>::GetLicenseActivationStatus()
|
||||
{
|
||||
return m_Impl.GetLicenseActivationStatus();
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicensingClientT<char>::GetLicenseExpirationDate(int * year, int * month, int * day)
|
||||
{
|
||||
m_Impl.GetLicenseExpirationDate(year, month, day);
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicensingClientT<wchar_t>::GetLicenseExpirationDate(int * year, int * month, int * day)
|
||||
{
|
||||
m_Impl.GetLicenseExpirationDate(year, month, day);
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicensingClientT<char>::SetTimeValidationMethod(int method)
|
||||
{
|
||||
return m_Impl.SetTimeValidationMethod(method);
|
||||
}
|
||||
|
||||
template<>
|
||||
void LicensingClientT<wchar_t>::SetTimeValidationMethod(int method)
|
||||
{
|
||||
return m_Impl.SetTimeValidationMethod(method);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const wchar_t * GetCurrentHardwareIdW(void * licensingClient)
|
||||
{
|
||||
|
||||
static std::wstring result = ((ANSCENTER::Licensing::LicensingClientT<wchar_t> *)licensingClient)->GetCurrentHardwareId();
|
||||
return result.c_str();
|
||||
}
|
||||
|
||||
const char * GetCurrentHardwareIdA(void * licensingClient)
|
||||
{
|
||||
return ((ANSCENTER::Licensing::LicensingClientT<char> *)licensingClient)->GetCurrentHardwareId();
|
||||
}
|
||||
|
||||
bool MatchCurrentHardwareIdW(void * licensingClient, const wchar_t * hwid)
|
||||
{
|
||||
|
||||
return ((ANSCENTER::Licensing::LicensingClientT<wchar_t> *)licensingClient)->MatchCurrentHardwareId(hwid);
|
||||
}
|
||||
|
||||
bool MatchCurrentHardwareIdA(void * licensingClient, const char * hwid)
|
||||
{
|
||||
return ((ANSCENTER::Licensing::LicensingClientT<char> *)licensingClient)->MatchCurrentHardwareId(hwid);
|
||||
}
|
||||
602
core/anslicensing/licensingclient.h
Normal file
602
core/anslicensing/licensingclient.h
Normal file
@@ -0,0 +1,602 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "except.h"
|
||||
#include "template.h"
|
||||
#include "generator.h"
|
||||
#include "validator.h"
|
||||
#include "ntpclient.h"
|
||||
#include "uniconv.h"
|
||||
#include "license.h"
|
||||
#include "licensevalidationargs.h"
|
||||
#include "licensevalidationresult.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winhttp.h>
|
||||
#include <tchar.h>
|
||||
#else
|
||||
#include <curl/curl.h>
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
// these methods are compiler workarounds to eliminate circular references.
|
||||
// They only call the corresponding LicensingClient::... methods
|
||||
// GCC complains of cross-references between LicensingClientImpl and LicensingClientT
|
||||
|
||||
const wchar_t * GetCurrentHardwareIdW(void *);
|
||||
const char * GetCurrentHardwareIdA(void *);
|
||||
bool MatchCurrentHardwareIdW(void *, const wchar_t *);
|
||||
bool MatchCurrentHardwareIdA(void *, const char *);
|
||||
|
||||
class LicensingClientImpl
|
||||
{
|
||||
public:
|
||||
LicensingClientImpl(void * licensingClient, bool usesWideChar)
|
||||
{
|
||||
licenseKeyValidationDataLen = 0;
|
||||
licenseTemplateId.clear();
|
||||
parentLicensingClient = licensingClient;
|
||||
parentUsesWideChar = usesWideChar;
|
||||
timeValidationMethod = PREFER_INTERNET_TIME;
|
||||
m_licenseValidityDays = 0;
|
||||
// GetCurrentHardwareIdCallback = GetCurrentHardwareId;
|
||||
// MatchCurrentHardwareIdCallback = MatchCurrentHardwareId;
|
||||
}
|
||||
|
||||
void SetLicenseTemplate(const LicenseTemplateImpl* tmpl)
|
||||
{
|
||||
licenseTemplate = tmpl;
|
||||
}
|
||||
|
||||
void SetLicenseKey(const char * key)
|
||||
{
|
||||
licenseKey = key;
|
||||
}
|
||||
|
||||
void SetActivationKey(const char * key)
|
||||
{
|
||||
activationKey = key;
|
||||
}
|
||||
|
||||
const char * GetActivationKey()
|
||||
{
|
||||
return activationKey.c_str();
|
||||
}
|
||||
|
||||
void SetHardwareId(const char * hwid)
|
||||
{
|
||||
hardwareId = hwid;
|
||||
}
|
||||
|
||||
const char * GetHardwareId()
|
||||
{
|
||||
return hardwareId.c_str();
|
||||
}
|
||||
|
||||
void SetLicenseTemplateId(const char * templateId)
|
||||
{
|
||||
licenseTemplateId = templateId;
|
||||
}
|
||||
|
||||
const char * GetLicenseTemplateId()
|
||||
{
|
||||
return licenseTemplateId.c_str();
|
||||
}
|
||||
|
||||
void SetLicenseKeyValidationData(const void* data, unsigned len)
|
||||
{
|
||||
licenseKeyValidationData.resize(len);
|
||||
|
||||
memcpy(licenseKeyValidationData.data(), data, len);
|
||||
|
||||
licenseKeyValidationDataLen = len;
|
||||
}
|
||||
|
||||
LicenseTemplateImpl * CreateActivationTemplate()
|
||||
{
|
||||
LicenseTemplateImpl * tmpl = new LicenseTemplateImpl();
|
||||
|
||||
tmpl->SetCharactersPerGroup(licenseTemplate->GetCharactersPerGroup());
|
||||
tmpl->SetNumberOfGroups(licenseTemplate->GetNumberOfGroups());
|
||||
tmpl->SetGroupSeparator(licenseTemplate->GetGroupSeparator());
|
||||
//activationKeyTemplate.SetDataSize(t.GetDataSize());
|
||||
tmpl->SetSignatureSize(licenseTemplate->GetSignatureSize());
|
||||
tmpl->SetEncoding(licenseTemplate->GetEncoding());
|
||||
tmpl->SetPublicKeyCertificate(licenseTemplate->GetPublicKeyCertificate());
|
||||
|
||||
int keyLen = tmpl->GetNumberOfGroups() * tmpl->GetCharactersPerGroup()
|
||||
+ (tmpl->GetNumberOfGroups() - 1) * strlen(tmpl->GetGroupSeparator());
|
||||
|
||||
int hwidLen = 29;
|
||||
|
||||
if (hardwareId.length() > 0)
|
||||
hwidLen = hardwareId.length();
|
||||
|
||||
tmpl->SetDataSize(tmpl->GetCharactersPerGroup() * tmpl->GetNumberOfGroups() * tmpl->GetEncoding() - tmpl->GetSignatureSize());
|
||||
tmpl->SetValidationDataSize((keyLen + hwidLen ) * 8 + licenseTemplate->GetValidationDataSize());
|
||||
|
||||
tmpl->AddDataField("ExpirationDate", FIELD_TYPE_RAW, 16, 0);
|
||||
tmpl->AddValidationField("LicenseKey", FIELD_TYPE_STRING, keyLen * 8, 0);
|
||||
tmpl->AddValidationField("HardwareId", FIELD_TYPE_STRING, hwidLen * 8, keyLen * 8);
|
||||
|
||||
if (!licenseKeyValidationData.empty())
|
||||
{
|
||||
tmpl->AddValidationField("LicenseKeyValidationData", FIELD_TYPE_RAW, licenseKeyValidationDataLen * 8, (keyLen + hwidLen) * 8);
|
||||
}
|
||||
|
||||
if (licensingServiceUrl.empty())
|
||||
tmpl->SetLicensingServiceUrl(licenseTemplate->GetLicensingServiceUrl());
|
||||
else
|
||||
tmpl->SetLicensingServiceUrl(licensingServiceUrl.c_str());
|
||||
|
||||
if (licenseTemplateId.empty())
|
||||
tmpl->SetTemplateId(licenseTemplate->GetTemplateId());
|
||||
else
|
||||
tmpl->SetTemplateId(licenseTemplateId.c_str());
|
||||
|
||||
return tmpl;
|
||||
}
|
||||
|
||||
bool ValidateHardwareId()
|
||||
{
|
||||
if (!MatchCurrentHardwareIdCallback(hardwareId.c_str()))
|
||||
{
|
||||
activationStatus = STATUS_INVALID_HARDWARE_ID;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ValidateActivationKey(LicenseTemplateImpl* activationTemplate = nullptr, bool validateExpirationDate = true)
|
||||
{
|
||||
bool ownActivationTemplate = false;
|
||||
|
||||
try {
|
||||
if (!activationTemplate)
|
||||
{
|
||||
activationTemplate = CreateActivationTemplate();
|
||||
ownActivationTemplate = true;
|
||||
}
|
||||
|
||||
KeyValidatorImpl validator(activationTemplate);
|
||||
|
||||
validator.SetValidationData("LicenseKey", licenseKey.c_str());
|
||||
validator.SetValidationData("HardwareId", hardwareId.c_str());
|
||||
|
||||
if (!licenseKeyValidationData.empty())
|
||||
validator.SetValidationData("LicenseKeyValidationData", licenseKeyValidationData.data(), (activationTemplate->GetValidationDataSize() + 7) >> 3);
|
||||
|
||||
try
|
||||
{
|
||||
validator.SetKey(activationKey.c_str());
|
||||
}
|
||||
catch (Exception * ex)
|
||||
{
|
||||
ex->Destroy();
|
||||
activationStatus = STATUS_INVALID_ACTIVATION_KEY;
|
||||
if (ownActivationTemplate) delete activationTemplate;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!validator.IsKeyValid())
|
||||
{
|
||||
activationStatus = STATUS_INVALID_ACTIVATION_KEY;
|
||||
if (ownActivationTemplate) delete activationTemplate;
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned char rawKeyData[2];
|
||||
int rawKeyDataBits = 16;
|
||||
|
||||
validator.QueryKeyData("ExpirationDate", rawKeyData, &rawKeyDataBits);
|
||||
|
||||
unsigned short keyData = (unsigned short)(((unsigned short)rawKeyData[0]) << 8 | rawKeyData[1]);
|
||||
|
||||
memset(&licenseExpirationTime, 0, sizeof(licenseExpirationTime));
|
||||
|
||||
if (keyData != 0)
|
||||
{
|
||||
licenseExpirationTime.tm_year = (2000 + (keyData >> 9)) - 1900;
|
||||
licenseExpirationTime.tm_mon = ((keyData & 0x01FF) >> 5) - 1;
|
||||
licenseExpirationTime.tm_mday = keyData & 0x001F;
|
||||
|
||||
if (!validateExpirationDate)
|
||||
{
|
||||
if (ownActivationTemplate) delete activationTemplate;
|
||||
return true;
|
||||
}
|
||||
|
||||
time_t currentTime;
|
||||
|
||||
if (timeValidationMethod != USE_LOCAL_TIME)
|
||||
{
|
||||
currentTime = NTPClient::GetCurrentTimeUTC();
|
||||
|
||||
if (currentTime == 0) // if couldn't obtain internet time
|
||||
{
|
||||
if (timeValidationMethod == USE_INTERNET_TIME) // internet time was mandatory
|
||||
{
|
||||
activationStatus = STATUS_NET_ERROR;
|
||||
if (ownActivationTemplate) delete activationTemplate;
|
||||
return false;
|
||||
}
|
||||
|
||||
// fallback to local time
|
||||
currentTime = time(NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
currentTime = time(NULL);
|
||||
|
||||
double diffSeconds = difftime(mktime(&licenseExpirationTime), currentTime);
|
||||
|
||||
if (diffSeconds < 0)
|
||||
{
|
||||
m_licenseValidityDays = licenseTemplate->GetLicenseGracePeriod() - (int)(((time_t)(-diffSeconds) + 86400 - 1) / 86400);
|
||||
|
||||
if (m_licenseValidityDays < 0)
|
||||
m_licenseValidityDays = 0;
|
||||
|
||||
activationStatus = STATUS_LICENSE_EXPIRED;
|
||||
|
||||
if (ownActivationTemplate) delete activationTemplate;
|
||||
|
||||
return false;
|
||||
} else
|
||||
m_licenseValidityDays = licenseTemplate->GetLicenseGracePeriod() + (int)(((time_t)diffSeconds + 86400 - 1) / 86400);
|
||||
}
|
||||
else
|
||||
m_licenseValidityDays = -1;
|
||||
|
||||
if (ownActivationTemplate) delete activationTemplate;
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
if (ownActivationTemplate && activationTemplate)
|
||||
delete activationTemplate;
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsLicenseValid()
|
||||
{
|
||||
activationStatus = STATUS_GENERIC_ERROR;
|
||||
|
||||
try
|
||||
{
|
||||
if (ValidateHardwareId() && ValidateActivationKey())
|
||||
{
|
||||
activationStatus = STATUS_SUCCESS;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
catch (Exception * ex)
|
||||
{
|
||||
ex->Destroy();
|
||||
|
||||
activationStatus = STATUS_GENERIC_ERROR;
|
||||
return false;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
activationStatus = STATUS_GENERIC_ERROR;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
LicenseValidationResultImpl& ValidateLicense(LicenseValidationArgsImpl * args)
|
||||
{
|
||||
const LicenseImpl * license = args->GetLicense();
|
||||
const char * lk = args->GetLicenseKey();
|
||||
|
||||
licenseKey = (lk) ? lk : "";
|
||||
|
||||
if (license == NULL && licenseKey.length() == 0)
|
||||
throw new LicensingException(STATUS_GENERIC_ERROR, "either a license or a license key must be provided");
|
||||
|
||||
if (license == NULL)
|
||||
{
|
||||
try {
|
||||
KeyValidatorImpl keyValidator;
|
||||
|
||||
keyValidator.SetKeyTemplate(licenseTemplate);
|
||||
|
||||
keyValidator.SetKey(lk);
|
||||
|
||||
if (licenseTemplate->GetValidationDataSize() > 0)
|
||||
{
|
||||
int fieldType, fieldSize, fieldOffset;
|
||||
|
||||
for (std::list<NameValuePair>::iterator iter = args->m_licenseKeyValidationData.begin(); iter != args->m_licenseKeyValidationData.end(); iter++)
|
||||
{
|
||||
if (!licenseTemplate->GetValidationField(iter->name.c_str(), &fieldType, &fieldSize, &fieldOffset))
|
||||
throw new LicensingException(STATUS_INVALID_LICENSE_KEY, "license key validation data is invalid");
|
||||
|
||||
switch (fieldType)
|
||||
{
|
||||
case FIELD_TYPE_INTEGER:
|
||||
keyValidator.SetValidationData(iter->name.c_str(), iter->intValue);
|
||||
break;
|
||||
|
||||
case FIELD_TYPE_STRING:
|
||||
keyValidator.SetValidationData(iter->name.c_str(), iter->stringValue.c_str());
|
||||
break;
|
||||
|
||||
case FIELD_TYPE_DATE13:
|
||||
case FIELD_TYPE_DATE14:
|
||||
case FIELD_TYPE_DATE16:
|
||||
keyValidator.SetValidationData(iter->name.c_str(), iter->dateValue.year, iter->dateValue.month, iter->dateValue.day);
|
||||
break;
|
||||
|
||||
case FIELD_TYPE_RAW:
|
||||
// keyValidator.SetValidationData(iter->name.c_str(), &(iter->value.binaryValue[0]), iter->value.binaryValue.size);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
licenseKeyValidationDataLen = (licenseTemplate->GetValidationDataSize() + 7) >> 3;
|
||||
|
||||
licenseKeyValidationData.resize(licenseKeyValidationDataLen);
|
||||
|
||||
keyValidator.QueryValidationData(NULL, licenseKeyValidationData.data(), &licenseKeyValidationDataLen);
|
||||
}
|
||||
|
||||
if (!keyValidator.IsKeyValid())
|
||||
{
|
||||
throw new LicensingException(STATUS_INVALID_LICENSE_KEY, "license key is not valid");
|
||||
}
|
||||
|
||||
AcquireLicense();
|
||||
}
|
||||
catch (LicensingException * ex)
|
||||
{
|
||||
if (ex->GetCode() == STATUS_PAYMENT_REQUIRED)
|
||||
{
|
||||
m_licenseValidationResult.SetPaymentRequired(true);
|
||||
ex->Destroy();
|
||||
}
|
||||
else
|
||||
throw;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
licenseKey = license->GetLicenseKey();
|
||||
hardwareId = license->GetHardwareId();
|
||||
activationKey = license->GetActivationKey();
|
||||
|
||||
const void* buf; int len;
|
||||
license->GetLicenseKeyValidationData(&buf, &len);
|
||||
|
||||
if (buf && (len > 0))
|
||||
SetLicenseKeyValidationData(buf, (unsigned int)len);
|
||||
|
||||
if (ValidateActivationKey(NULL, true))
|
||||
{
|
||||
m_licenseValidationResult.SetLicenseValid(true);
|
||||
m_licenseValidationResult.SetPaymentRequired(false);
|
||||
m_licenseValidationResult.SetLicenseExpired(false);
|
||||
m_licenseValidationResult.SetLicense(NULL);
|
||||
return m_licenseValidationResult;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (activationStatus == STATUS_LICENSE_EXPIRED)
|
||||
{
|
||||
m_licenseValidationResult.SetLicenseExpired(true);
|
||||
}
|
||||
|
||||
if ((activationStatus == STATUS_LICENSE_EXPIRED) && (m_licenseValidityDays > 0) && license->IsLease())
|
||||
{
|
||||
try
|
||||
{
|
||||
AcquireLicense();
|
||||
m_licenseValidationResult.SetLicenseExpired(false);
|
||||
}
|
||||
catch (LicensingException * ex)
|
||||
{
|
||||
if (ex->GetCode() == STATUS_PAYMENT_REQUIRED)
|
||||
{
|
||||
m_licenseValidationResult.SetPaymentRequired(true);
|
||||
ex->Destroy();
|
||||
}
|
||||
else
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (licenseExpirationTime.tm_year > 0)
|
||||
{
|
||||
m_licenseValidationResult.SetLicenseExpirationDate(
|
||||
1900 + licenseExpirationTime.tm_year,
|
||||
1 + licenseExpirationTime.tm_mon,
|
||||
licenseExpirationTime.tm_mday);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_licenseValidationResult.SetLicenseExpirationDate(0, 0, 0);
|
||||
}
|
||||
|
||||
return m_licenseValidationResult;
|
||||
}
|
||||
|
||||
void AcquireLicense()
|
||||
{
|
||||
if (hardwareId.empty())
|
||||
hardwareId = (parentLicensingClient) ? GetCurrentHardwareIdCallback() : GetCurrentHardwareId();
|
||||
|
||||
unique_ptr<LicenseTemplateImpl> activationTemplate(CreateActivationTemplate());
|
||||
|
||||
const char * templateId = activationTemplate->GetTemplateId();
|
||||
|
||||
if (templateId != NULL && templateId[0] != '\0')
|
||||
{
|
||||
char params[64] = "ProductId=";
|
||||
sprintf(params + sizeof("ProductId"), "%s", activationTemplate->GetTemplateId());
|
||||
activationTemplate->SetLicensingServiceParameters(params);
|
||||
}
|
||||
|
||||
KeyGeneratorImpl generator(activationTemplate.get());
|
||||
|
||||
generator.SetKeyData("ExpirationDate", (int)0);
|
||||
|
||||
generator.SetValidationData("LicenseKey", licenseKey.c_str());
|
||||
|
||||
generator.SetValidationData("HardwareId", hardwareId.c_str());
|
||||
|
||||
if (!licenseKeyValidationData.empty())
|
||||
{
|
||||
generator.SetValidationData("LicenseKeyValidationData", licenseKeyValidationData.data(), licenseKeyValidationDataLen * 8);
|
||||
}
|
||||
|
||||
try {
|
||||
activationKey = generator.GenerateKey();
|
||||
}
|
||||
catch (LicensingException * ex)
|
||||
{
|
||||
if ((ex->GetCode() == STATUS_NET_ERROR) && (generator.GetSigningServiceStatusCode() == 406))
|
||||
{
|
||||
m_licenseValidationResult.SetPaymentRequired(true);
|
||||
ex->Destroy();
|
||||
}
|
||||
else
|
||||
throw;
|
||||
}
|
||||
|
||||
if (ValidateActivationKey(activationTemplate.get(), false))
|
||||
{
|
||||
activationStatus = STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
throw new LicensingException(STATUS_GENERIC_ERROR, "internal error - invalid returned activation key");
|
||||
|
||||
m_licenseValidationResult.m_license = std::make_unique<LicenseImpl>();
|
||||
|
||||
m_licenseValidationResult.m_license->SetHardwareId(hardwareId.c_str());
|
||||
m_licenseValidationResult.m_license->SetActivationKey(activationKey.c_str());
|
||||
m_licenseValidationResult.m_license->SetLicenseKey(licenseKey.c_str());
|
||||
m_licenseValidationResult.m_license->SetLicenseKeyValidationData(licenseKeyValidationData.data(), licenseKeyValidationDataLen);
|
||||
|
||||
int status = generator.GetSigningServiceStatusCode();
|
||||
|
||||
if (status == 200 /* HTTP OK */)
|
||||
m_licenseValidationResult.m_license->SetLease(false);
|
||||
else
|
||||
if (status == 201 || status == 202)
|
||||
m_licenseValidationResult.m_license->SetLease(true);
|
||||
|
||||
m_licenseValidationResult.SetLicenseValid(true);
|
||||
}
|
||||
|
||||
void SetLicensingServiceUrl(const char * url)
|
||||
{
|
||||
licensingServiceUrl = url;
|
||||
}
|
||||
|
||||
int GetLicenseActivationStatus()
|
||||
{
|
||||
return activationStatus;
|
||||
}
|
||||
|
||||
void GetLicenseExpirationDate(int * year, int * month, int * day)
|
||||
{
|
||||
if (licenseExpirationTime.tm_year > 0)
|
||||
{
|
||||
*year = 1900 + licenseExpirationTime.tm_year;
|
||||
*month = 1 + licenseExpirationTime.tm_mon;
|
||||
*day = licenseExpirationTime.tm_mday;
|
||||
} else
|
||||
{
|
||||
*year = 0;
|
||||
*month = 0;
|
||||
*day = 0;
|
||||
}
|
||||
}
|
||||
|
||||
const char * GetCurrentHardwareIdCallback()
|
||||
{
|
||||
if (parentUsesWideChar)
|
||||
{
|
||||
static string hwid = w2s(GetCurrentHardwareIdW(parentLicensingClient));
|
||||
return hwid.c_str();
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetCurrentHardwareIdA(parentLicensingClient);
|
||||
}
|
||||
}
|
||||
|
||||
bool MatchCurrentHardwareIdCallback(const char * hwid)
|
||||
{
|
||||
if (parentUsesWideChar)
|
||||
{
|
||||
return MatchCurrentHardwareIdW(parentLicensingClient, s2w(hwid).c_str());
|
||||
}
|
||||
else
|
||||
return MatchCurrentHardwareIdA(parentLicensingClient, hwid);
|
||||
}
|
||||
|
||||
static const char * GetCurrentHardwareId()
|
||||
{
|
||||
return KeyHelper::GetCurrentHardwareId();
|
||||
}
|
||||
|
||||
static bool MatchCurrentHardwareId(const char * hwid)
|
||||
{
|
||||
return KeyHelper::MatchCurrentHardwareId(hwid);
|
||||
}
|
||||
|
||||
void SetTimeValidationMethod(int method)
|
||||
{
|
||||
timeValidationMethod = method;
|
||||
}
|
||||
|
||||
private:
|
||||
void StrReplaceA(std::string& str, const std::string& oldStr, const std::string& newStr)
|
||||
{
|
||||
size_t pos = 0;
|
||||
while ((pos = str.find(oldStr, pos)) != std::string::npos)
|
||||
{
|
||||
str.replace(pos, oldStr.length(), newStr);
|
||||
pos += newStr.length();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const LicenseTemplateImpl* licenseTemplate;
|
||||
|
||||
LicenseValidationResultImpl m_licenseValidationResult;
|
||||
|
||||
struct tm licenseExpirationTime;
|
||||
string licenseKey;
|
||||
string activationKey;
|
||||
string hardwareId;
|
||||
string licensingServiceUrl;
|
||||
|
||||
vector<unsigned char> licenseKeyValidationData;
|
||||
int licenseKeyValidationDataLen;
|
||||
int activationStatus;
|
||||
string licenseTemplateId;
|
||||
void * parentLicensingClient;
|
||||
bool parentUsesWideChar;
|
||||
int timeValidationMethod;
|
||||
int m_licenseValidityDays;
|
||||
//const char * (*GetCurrentHardwareIdCallback)(void * callerContext);
|
||||
//bool (*MatchCurrentHardwareIdCallback)(void * callerContext, const char * hwid);
|
||||
};
|
||||
2
core/anslicensing/ntpclient.cpp
Normal file
2
core/anslicensing/ntpclient.cpp
Normal file
@@ -0,0 +1,2 @@
|
||||
#include "precomp.h"
|
||||
#include "ntpclient.h"
|
||||
113
core/anslicensing/ntpclient.h
Normal file
113
core/anslicensing/ntpclient.h
Normal file
@@ -0,0 +1,113 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#define INVALID_SOCKET (-1)
|
||||
#define SOCKET int
|
||||
#define SOCKET_ERROR (-1)
|
||||
#define closesocket close
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
|
||||
class NTPClient
|
||||
{
|
||||
public:
|
||||
static time_t GetCurrentTimeUTC(const char * ntpserver = NULL)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
WSADATA w;
|
||||
int remote_length;
|
||||
#else
|
||||
socklen_t remote_length;
|
||||
#endif
|
||||
SOCKET sd = INVALID_SOCKET;
|
||||
char ntp_buffer[48];
|
||||
time_t current_time = 0;
|
||||
struct hostent *hp;
|
||||
struct sockaddr_in remote;
|
||||
struct sockaddr_in local;
|
||||
char host_name[256];
|
||||
hostent * host = NULL;
|
||||
|
||||
do {
|
||||
#ifdef _WIN32
|
||||
if (WSAStartup(MAKEWORD(2, 2), &w) != 0)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
if ((sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET)
|
||||
break;
|
||||
|
||||
memset((void *)&remote, '\0', sizeof(struct sockaddr_in));
|
||||
|
||||
remote.sin_family = AF_INET;
|
||||
remote.sin_port = htons(123);
|
||||
|
||||
if ((host = gethostbyname((ntpserver) ? ntpserver : "time.windows.com")) == NULL)
|
||||
break;
|
||||
|
||||
remote.sin_addr.s_addr = *(u_long *)host->h_addr_list[0];
|
||||
|
||||
memset((void *)&local, '\0', sizeof(local));
|
||||
|
||||
local.sin_family = AF_INET;
|
||||
local.sin_port = htons(0);
|
||||
local.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
if (::bind(sd, (struct sockaddr *)&local, sizeof(local)) == SOCKET_ERROR)
|
||||
break;
|
||||
|
||||
memset(ntp_buffer, 0, sizeof(ntp_buffer));
|
||||
ntp_buffer[0] = 0x1B;
|
||||
|
||||
remote_length = sizeof(struct sockaddr_in);
|
||||
|
||||
if (sendto(sd, ntp_buffer, sizeof(ntp_buffer), 0, (struct sockaddr *)&remote, remote_length) == -1)
|
||||
break;
|
||||
|
||||
fd_set fds;
|
||||
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(sd, &fds);
|
||||
|
||||
timeval timeout;
|
||||
timeout.tv_sec = 10;
|
||||
timeout.tv_usec = 0;
|
||||
|
||||
if (select(1, &fds, NULL, NULL, &timeout) != 1)
|
||||
break;
|
||||
|
||||
if (recvfrom(sd, ntp_buffer, sizeof(ntp_buffer), 0, (struct sockaddr *)&remote, &remote_length) < 0)
|
||||
break;
|
||||
|
||||
unsigned int int_part = *(unsigned int *)(ntp_buffer + 40);
|
||||
unsigned int fract_part = *(unsigned int *)(ntp_buffer + 44);
|
||||
|
||||
int_part = SwapEndianness(int_part);
|
||||
|
||||
current_time = (time_t)(int_part -= 2208988800U);
|
||||
}
|
||||
while (0);
|
||||
|
||||
if (sd != INVALID_SOCKET)
|
||||
closesocket(sd);
|
||||
|
||||
#ifdef _WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
|
||||
return current_time;
|
||||
}
|
||||
|
||||
static unsigned int SwapEndianness(unsigned int x)
|
||||
{
|
||||
return (unsigned int)(((x & 0x000000ff) << 24) +
|
||||
((x & 0x0000ff00) << 8) +
|
||||
((x & 0x00ff0000) >> 8) +
|
||||
((x & 0xff000000) >> 24));
|
||||
}
|
||||
};
|
||||
1200
core/anslicensing/picojson.h
Normal file
1200
core/anslicensing/picojson.h
Normal file
File diff suppressed because it is too large
Load Diff
6
core/anslicensing/precomp.cpp
Normal file
6
core/anslicensing/precomp.cpp
Normal file
@@ -0,0 +1,6 @@
|
||||
//
|
||||
// Copyright (c) ANSCENTER. All rights reserved.
|
||||
//
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
32
core/anslicensing/precomp.h
Normal file
32
core/anslicensing/precomp.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include "anslicensing.h"
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h> /* memset(), memcpy() */
|
||||
#include <assert.h>
|
||||
#include <string>
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#define _WIN32_WINNT 0x0501
|
||||
#define _CRT_SECURE_NO_DEPRECATE
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
|
||||
#include <crtdbg.h>
|
||||
#include <WinSock2.h>
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#define _alloca alloca
|
||||
#define _stricmp strcasecmp
|
||||
#define _snprintf snprintf
|
||||
#define _atoi64(s) strtoull(s, NULL, 10)
|
||||
|
||||
#endif
|
||||
285
core/anslicensing/prime.cpp
Normal file
285
core/anslicensing/prime.cpp
Normal file
@@ -0,0 +1,285 @@
|
||||
//
|
||||
// Copyright (c) ANSCENTER. All rights reserved.
|
||||
//
|
||||
|
||||
// prime factory implementation
|
||||
#include "precomp.h"
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "bigint.h"
|
||||
#include "prime.h"
|
||||
|
||||
extern void print( bigint x );
|
||||
|
||||
static int maybe_prime( const bigint & p )
|
||||
{
|
||||
return modexp( 2, p - 1, p ) == 1;
|
||||
}
|
||||
|
||||
static int fermat_is_probable_prime( const bigint & p )
|
||||
{
|
||||
// Test based on Fermats theorem a**(p-1) = 1 mod p for prime p
|
||||
// For 1000 bit numbers this can take quite a while
|
||||
const int rep = 4;
|
||||
const unsigned any[ rep ] = { 2,3,5,7 /*,11,13,17,19,23,29,31,37..*/ };
|
||||
|
||||
for ( unsigned i = 0; i < rep; i += 1 )
|
||||
if ( modexp( any[ i ], p - 1, p ) != 1 )
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bigint random( const bigint & n )
|
||||
{
|
||||
bigint x = 0;
|
||||
|
||||
while ( x < n )
|
||||
x = x * RAND_MAX + rand();
|
||||
|
||||
return x % n;
|
||||
}
|
||||
|
||||
static int miller_rabin_is_probable_prime( const bigint & n )
|
||||
{
|
||||
unsigned T = 100;
|
||||
unsigned v = 0;
|
||||
bigint w = n - 1;
|
||||
|
||||
srand( (unsigned) time( 0 ) );
|
||||
|
||||
while ( w % 2 != 0 )
|
||||
{
|
||||
v += 1;
|
||||
w = w / 2;
|
||||
}
|
||||
|
||||
for ( unsigned j = 1; j <= T; j += 1 )
|
||||
{
|
||||
bigint a = 1 + random( n );
|
||||
bigint b = modexp( a, w, n );
|
||||
|
||||
if ( b != 1 && b != n - 1 )
|
||||
{
|
||||
unsigned i = 1;
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
if ( i == v )
|
||||
return 0;
|
||||
|
||||
b = ( b * b ) % n;
|
||||
|
||||
if ( b == n - 1 )
|
||||
break;
|
||||
|
||||
if ( b == 1 )
|
||||
return 0;
|
||||
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int is_probable_prime( const bigint & n )
|
||||
{
|
||||
return fermat_is_probable_prime( n )
|
||||
&& miller_rabin_is_probable_prime( n );
|
||||
}
|
||||
|
||||
prime_factory::prime_factory( unsigned MP )
|
||||
{
|
||||
// Initialise pl
|
||||
unsigned p = 2;
|
||||
char * b = new char[ MP + 1 ]; // one extra to stop search
|
||||
|
||||
for ( unsigned i = 0; i <= MP; i += 1 )
|
||||
b[ i ] = 1;
|
||||
|
||||
np = 0;
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
// skip composites
|
||||
while ( b[ p ] == 0 )
|
||||
p += 1;
|
||||
|
||||
if ( p == MP )
|
||||
break;
|
||||
|
||||
np += 1;
|
||||
|
||||
// cross off multiples
|
||||
unsigned c = p * 2;
|
||||
|
||||
while ( c < MP )
|
||||
{
|
||||
b[ c ] = 0;
|
||||
c += p;
|
||||
}
|
||||
|
||||
p += 1;
|
||||
}
|
||||
|
||||
pl = new unsigned[ np ];
|
||||
np = 0;
|
||||
|
||||
for ( p = 2; p < MP; p += 1 )
|
||||
if ( b[ p ] )
|
||||
{
|
||||
pl[ np ] = p;
|
||||
np += 1;
|
||||
}
|
||||
|
||||
delete [] b;
|
||||
}
|
||||
|
||||
prime_factory::~prime_factory()
|
||||
{
|
||||
delete [] pl;
|
||||
}
|
||||
|
||||
bigint prime_factory::find_prime( bigint start )
|
||||
{
|
||||
unsigned SS = 1000; // should be enough unless we are unlucky
|
||||
char * b = new char[ SS ]; // bitset of candidate primes
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for ( i = 0; i < SS; i += 1 )
|
||||
b[ i ] = 1;
|
||||
|
||||
for ( i = 0; i < np; i += 1 )
|
||||
{
|
||||
unsigned p = pl[ i ];
|
||||
unsigned r = to_unsigned( start % p ); // not as fast as it should be - could do with special routine
|
||||
|
||||
if ( r )
|
||||
r = p - r;
|
||||
|
||||
// cross off multiples of p
|
||||
while ( r < SS )
|
||||
{
|
||||
b[ r ] = 0;
|
||||
r += p;
|
||||
}
|
||||
}
|
||||
|
||||
// now test candidates
|
||||
for ( i = 0; i < SS; i+=1 )
|
||||
{
|
||||
if ( b[ i ] )
|
||||
{
|
||||
if ( is_probable_prime( start ) )
|
||||
{
|
||||
delete [] b;
|
||||
return start;
|
||||
}
|
||||
}
|
||||
|
||||
start += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bigint prime_factory::find_special( bigint start, bigint base )
|
||||
{
|
||||
// Returns a (probable) prime number x > start such that
|
||||
// x and x*2+1 are both probable primes,
|
||||
// i.e. x is a probable Sophie-Germain prime
|
||||
unsigned SS = 40000; // should be enough unless we are unlucky
|
||||
char * b1 = new char[ SS ]; // bitset of candidate primes
|
||||
char * b2 = new char[ 2 * SS ];
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for ( i = 0; i < SS; i += 1 )
|
||||
b1[ i ] = 1;
|
||||
|
||||
for ( i = 0; i < 2 * SS; i += 1 )
|
||||
b2[ i ] = 1;
|
||||
|
||||
for ( i = 0; i < np; i += 1 )
|
||||
{
|
||||
unsigned p = pl[ i ];
|
||||
unsigned r = to_unsigned( start % p ); // not as fast as it should be - could do with special routine
|
||||
|
||||
if ( r )
|
||||
r = p - r;
|
||||
|
||||
// cross off multiples of p
|
||||
while ( r < SS )
|
||||
{
|
||||
b1[ r ] = 0;
|
||||
r += p;
|
||||
}
|
||||
|
||||
r = to_unsigned( ( start * 2 + 1 ) % p );
|
||||
|
||||
if ( r )
|
||||
r = p - r;
|
||||
|
||||
while ( r < 2 * SS )
|
||||
{
|
||||
b2[ r ] = 0;
|
||||
r += p;
|
||||
}
|
||||
}
|
||||
|
||||
// now test candidates
|
||||
for ( i = 0; i < SS; i += 1 )
|
||||
{
|
||||
if ( b1[ i ] && b2[ i * 2 ] )
|
||||
{
|
||||
printf("D=%u\n", to_unsigned( start * 2 + 1 - base ) );
|
||||
|
||||
if ( maybe_prime( start )
|
||||
&& maybe_prime( start * 2 + 1 )
|
||||
&& is_probable_prime( start )
|
||||
&& is_probable_prime( start * 2 + 1 )
|
||||
)
|
||||
{
|
||||
delete [] b1;
|
||||
delete [] b2;
|
||||
return start;
|
||||
}
|
||||
}
|
||||
|
||||
start += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int prime_factory::make_prime( bigint & r, bigint & k, const bigint & min_p )
|
||||
// Divide out small factors or r
|
||||
{
|
||||
k = 1;
|
||||
for ( unsigned i = 0; i < np; i += 1 )
|
||||
{
|
||||
unsigned p = pl[ i ];
|
||||
// maybe pre-computing product of several primes
|
||||
// and then GCD(r,p) would be faster ?
|
||||
while ( r % p == 0 )
|
||||
{
|
||||
if ( r == p )
|
||||
return 1; // can only happen if min_p is small
|
||||
|
||||
r = r / p;
|
||||
k = k * p;
|
||||
|
||||
if ( r < min_p )
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return is_probable_prime( r );
|
||||
}
|
||||
25
core/anslicensing/prime.h
Normal file
25
core/anslicensing/prime.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef __PRIME_H
|
||||
#define __PRIME_H
|
||||
|
||||
class prime_factory
|
||||
{
|
||||
// construction
|
||||
public:
|
||||
prime_factory( unsigned MP = 2000 ); // sieve size
|
||||
~prime_factory();
|
||||
|
||||
// methods
|
||||
public:
|
||||
bigint find_prime( bigint start );
|
||||
int make_prime( bigint & r, bigint &k, const bigint & rmin );
|
||||
bigint find_special( bigint start, bigint base=0 );
|
||||
|
||||
// properties
|
||||
public:
|
||||
unsigned np;
|
||||
unsigned *pl;
|
||||
};
|
||||
|
||||
int is_probable_prime( const bigint &p );
|
||||
|
||||
#endif
|
||||
353
core/anslicensing/propertycollection.h
Normal file
353
core/anslicensing/propertycollection.h
Normal file
@@ -0,0 +1,353 @@
|
||||
#pragma once
|
||||
|
||||
#include "precomp.h"
|
||||
#include "uniconv.h"
|
||||
#include "tinyxml2.h"
|
||||
#include "picojson.h"
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
#ifndef MAX_XML_BUFFER_SIZE
|
||||
#define MAX_XML_BUFFER_SIZE 4096
|
||||
#endif
|
||||
|
||||
class PathEntry
|
||||
{
|
||||
friend class PropertyCollection;
|
||||
|
||||
public:
|
||||
PathEntry()
|
||||
{
|
||||
processed = false;
|
||||
}
|
||||
|
||||
PathEntry(const PathEntry & copy)
|
||||
{
|
||||
processed = false;
|
||||
path = copy.path;
|
||||
nameValueCollection = copy.nameValueCollection;
|
||||
}
|
||||
|
||||
PathEntry(const PathEntry * copy)
|
||||
{
|
||||
processed = false;
|
||||
path = copy->path;
|
||||
nameValueCollection = copy->nameValueCollection;
|
||||
}
|
||||
|
||||
private:
|
||||
string path;
|
||||
std::map<string, string> nameValueCollection;
|
||||
bool processed;
|
||||
};
|
||||
|
||||
class PropertyCollection
|
||||
{
|
||||
public:
|
||||
PropertyCollection()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SetProperty(const char * path, const char * name, const char * value)
|
||||
{
|
||||
string propName = (name != NULL) ? name : "";
|
||||
std::map<string, PathEntry>::iterator entry;
|
||||
|
||||
if ((entry = m_properties.find(path)) == m_properties.end())
|
||||
{
|
||||
PathEntry entry;
|
||||
entry.path = path;
|
||||
entry.nameValueCollection.insert(std::map<string, string>::value_type(propName, value));
|
||||
m_properties.insert(std::map<string, PathEntry>::value_type(path, entry));
|
||||
} else
|
||||
entry->second.nameValueCollection.insert(std::map<string, string>::value_type(propName, value));
|
||||
}
|
||||
|
||||
const char * GetProperty(const char * path, const char * name) const
|
||||
{
|
||||
std::map<string, PathEntry>::const_iterator entry = m_properties.find(path);
|
||||
|
||||
if (entry == m_properties.end())
|
||||
return NULL;
|
||||
|
||||
std::map<string, string>::const_iterator nv = entry->second.nameValueCollection.find((name != NULL) ? name : "");
|
||||
|
||||
if (nv == entry->second.nameValueCollection.end())
|
||||
return NULL;
|
||||
|
||||
return nv->second.c_str();
|
||||
}
|
||||
|
||||
void LoadXml(tinyxml2::XMLElement * src)
|
||||
{
|
||||
XmlToPathList("", src);
|
||||
}
|
||||
|
||||
void SaveXml(std::string & xml)
|
||||
{
|
||||
PathListToXml("/", &m_properties, xml, 1);
|
||||
}
|
||||
|
||||
void LoadJson(picojson::object & json)
|
||||
{
|
||||
|
||||
string path;
|
||||
size_t pos;
|
||||
|
||||
for (picojson::object::iterator iter = json.begin(); iter != json.end(); iter++)
|
||||
{
|
||||
path = iter->first.c_str();
|
||||
|
||||
if ((pos = path.find_last_of('#')) == string::npos)
|
||||
SetProperty(path.c_str(), NULL, iter->second.get<std::string>().c_str());
|
||||
else
|
||||
{
|
||||
SetProperty(path.substr(0, pos).c_str(), path.substr(pos + 1).c_str(), iter->second.get<std::string>().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SaveJson(std::string & json, const char * indent = "")
|
||||
{
|
||||
|
||||
bool first = true;
|
||||
json.append("{");
|
||||
|
||||
for (std::map<string, PathEntry>::const_iterator item = m_properties.begin(); item != m_properties.end(); item++)
|
||||
{
|
||||
for (std::map<string, string>::const_iterator innerItem = item->second.nameValueCollection.begin(); innerItem != item->second.nameValueCollection.end(); innerItem++)
|
||||
{
|
||||
if (!first) json.append(",");
|
||||
json.append("\n");
|
||||
json.append(indent);
|
||||
json.append("\t");
|
||||
json.append("\"");
|
||||
json.append(item->first.c_str());
|
||||
if (innerItem->first.length() > 0)
|
||||
{
|
||||
json.append("#"); json.append(innerItem->first.c_str());
|
||||
}
|
||||
json.append("\":\""); json.append(innerItem->second.c_str()); json.append("\"");
|
||||
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
||||
json.append("\n"); json.append(indent); json.append("}");
|
||||
}
|
||||
|
||||
size_t GetSize() const
|
||||
{
|
||||
return m_properties.size();
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<string, PathEntry> m_properties;
|
||||
|
||||
void XmlToPathList(const std::string prefix, const tinyxml2::XMLElement * node)
|
||||
{
|
||||
const char * text = node->GetText();
|
||||
|
||||
if (text != NULL)
|
||||
SetProperty(prefix.c_str(), "", text);
|
||||
|
||||
const tinyxml2::XMLAttribute * attr = node->FirstAttribute();
|
||||
|
||||
// risk of stack overflow because _alloca is called in loop. However the current number of properties
|
||||
// is very low so it is acceptable
|
||||
while (attr)
|
||||
{
|
||||
SetProperty(prefix.c_str(), attr->Name(), attr->Value());
|
||||
|
||||
attr = attr->Next();
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement * child;
|
||||
|
||||
for (child = (tinyxml2::XMLElement *)node->FirstChildElement(); child != NULL; child = child->NextSiblingElement())
|
||||
{
|
||||
XmlToPathList(prefix + "/" + child->Name(), child);
|
||||
}
|
||||
}
|
||||
|
||||
void PathListToXml(const std::string pathPrefix, std::map<string, PathEntry> * sortedPathList, std::string & xml, int indent)
|
||||
{
|
||||
std::string elementValue;
|
||||
bool startElementClosed = false;
|
||||
|
||||
if (pathPrefix != "/")
|
||||
{
|
||||
if (indent > 0)
|
||||
xml.append(indent, '\t');
|
||||
|
||||
xml.append("<"); xml.append(1 + strrchr(pathPrefix.c_str(), '/'));
|
||||
}
|
||||
|
||||
for (std::map<string, PathEntry>::const_iterator item = sortedPathList->begin(); item != sortedPathList->end(); item++)
|
||||
{
|
||||
if (strcmp(item->second.path.c_str(), pathPrefix.c_str()) == 0)
|
||||
{
|
||||
for (std::map<string, string>::const_iterator nvItem = item->second.nameValueCollection.begin();
|
||||
nvItem != item->second.nameValueCollection.end();
|
||||
nvItem++)
|
||||
{
|
||||
if (nvItem->first.length() == 0)
|
||||
{
|
||||
elementValue = nvItem->second.c_str();
|
||||
} else
|
||||
{
|
||||
xml.append(" ");
|
||||
xml.append(nvItem->first.c_str());
|
||||
xml.append("=\"");
|
||||
xml.append(nvItem->second.c_str());
|
||||
xml.append("\"");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pathPrefix != "/")
|
||||
{
|
||||
xml.append(">");
|
||||
|
||||
if (elementValue.length() > 0)
|
||||
{
|
||||
xml.append(elementValue);
|
||||
} else
|
||||
if (indent >= 0)
|
||||
xml.append("\n");
|
||||
}
|
||||
|
||||
bool finished = false;
|
||||
|
||||
while (!finished)
|
||||
{
|
||||
finished = true;
|
||||
std::string firstUnprocessedPrefix;
|
||||
|
||||
std::map<string, PathEntry> innerPathList;
|
||||
|
||||
for (std::map<string, PathEntry>::iterator item = sortedPathList->begin(); item != sortedPathList->end(); item++)
|
||||
{
|
||||
if (!item->second.processed && item->second.path.length() > pathPrefix.length() && (firstUnprocessedPrefix.empty() || strncmp(item->second.path.c_str(), firstUnprocessedPrefix.c_str(), firstUnprocessedPrefix.length()) == 0))
|
||||
{
|
||||
if (firstUnprocessedPrefix.empty())
|
||||
{
|
||||
int nextSep = item->second.path.find('/', pathPrefix.length() + 1);
|
||||
firstUnprocessedPrefix = item->second.path.substr(0, (nextSep >= 0) ? nextSep : item->second.path.length()).c_str();
|
||||
}
|
||||
|
||||
innerPathList.insert(std::map<string, PathEntry>::value_type(item->first, item->second));
|
||||
|
||||
item->second.processed = true;
|
||||
finished = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!finished)
|
||||
PathListToXml(firstUnprocessedPrefix, &innerPathList, xml, (indent >= 0) ? indent + 1 : indent);
|
||||
}
|
||||
|
||||
if (pathPrefix != "/")
|
||||
{
|
||||
if (indent > 0 && elementValue.length() == 0)
|
||||
xml.append(indent, '\t');
|
||||
|
||||
xml.append("</"); xml.append(1 + strrchr(pathPrefix.c_str(), '/')); xml.append(">");
|
||||
|
||||
if (indent >= 0) xml.append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void PathListToJson(const std::string pathPrefix, std::map<string, PathEntry> * sortedPathList, std::string & xml, int indent)
|
||||
{
|
||||
std::string elementValue;
|
||||
bool startElementClosed = false;
|
||||
|
||||
if (pathPrefix != "/")
|
||||
{
|
||||
if (indent > 0)
|
||||
xml.append(indent, '\t');
|
||||
|
||||
xml.append("\""); xml.append(1 + strrchr(pathPrefix.c_str(), '/')); xml.append("\":");
|
||||
}
|
||||
|
||||
for (std::map<string, PathEntry>::const_iterator item = sortedPathList->begin(); item != sortedPathList->end(); item++)
|
||||
{
|
||||
if (strcmp(item->second.path.c_str(), pathPrefix.c_str()) == 0)
|
||||
{
|
||||
for (std::map<string, string>::const_iterator nvItem = item->second.nameValueCollection.begin();
|
||||
nvItem != item->second.nameValueCollection.end();
|
||||
nvItem++)
|
||||
{
|
||||
if (nvItem->first.length() == 0)
|
||||
{
|
||||
elementValue = nvItem->second.c_str();
|
||||
}
|
||||
else
|
||||
{
|
||||
xml.append(" ");
|
||||
xml.append(nvItem->first.c_str());
|
||||
xml.append("=\"");
|
||||
xml.append(nvItem->second.c_str());
|
||||
xml.append("\"");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pathPrefix != "/")
|
||||
{
|
||||
xml.append(">");
|
||||
|
||||
if (elementValue.length() > 0)
|
||||
{
|
||||
xml.append(elementValue);
|
||||
}
|
||||
else
|
||||
if (indent >= 0)
|
||||
xml.append("\n");
|
||||
}
|
||||
|
||||
bool finished = false;
|
||||
|
||||
while (!finished)
|
||||
{
|
||||
finished = true;
|
||||
std::string firstUnprocessedPrefix;
|
||||
|
||||
std::map<string, PathEntry> innerPathList;
|
||||
|
||||
for (std::map<string, PathEntry>::iterator item = sortedPathList->begin(); item != sortedPathList->end(); item++)
|
||||
{
|
||||
if (!item->second.processed && item->second.path.length() > pathPrefix.length() && (firstUnprocessedPrefix.empty() || strncmp(item->second.path.c_str(), firstUnprocessedPrefix.c_str(), firstUnprocessedPrefix.length()) == 0))
|
||||
{
|
||||
if (firstUnprocessedPrefix.empty())
|
||||
{
|
||||
int nextSep = item->second.path.find('/', pathPrefix.length() + 1);
|
||||
firstUnprocessedPrefix = item->second.path.substr(0, (nextSep >= 0) ? nextSep : item->second.path.length()).c_str();
|
||||
}
|
||||
|
||||
innerPathList.insert(std::map<string, PathEntry>::value_type(item->first, item->second));
|
||||
|
||||
item->second.processed = true;
|
||||
finished = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!finished)
|
||||
PathListToXml(firstUnprocessedPrefix, &innerPathList, xml, (indent >= 0) ? indent + 1 : indent);
|
||||
}
|
||||
|
||||
if (pathPrefix != "/")
|
||||
{
|
||||
if (indent > 0 && elementValue.length() == 0)
|
||||
xml.append(indent, '\t');
|
||||
|
||||
xml.append("}");
|
||||
|
||||
if (indent >= 0) xml.append("\n");
|
||||
}
|
||||
}
|
||||
};
|
||||
66
core/anslicensing/rand.cpp
Normal file
66
core/anslicensing/rand.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
#include "precomp.h"
|
||||
|
||||
#include "bigint.h"
|
||||
#include "rand.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <wincrypt.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
random::random()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if ( !CryptAcquireContext( (HCRYPTPROV *)&m_hCryptProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) )
|
||||
m_hCryptProv = NULL;
|
||||
#else
|
||||
::srand(time(NULL));
|
||||
#endif
|
||||
}
|
||||
|
||||
random::~random()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if ( m_hCryptProv )
|
||||
CryptReleaseContext( (HCRYPTPROV)m_hCryptProv, 0L );
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned random::rand( unsigned max )
|
||||
{
|
||||
unsigned rnd;
|
||||
|
||||
#ifdef _WIN32
|
||||
if ( m_hCryptProv )
|
||||
CryptGenRandom( (HCRYPTPROV)m_hCryptProv, sizeof( unsigned ), (BYTE *)&rnd );
|
||||
#else
|
||||
rnd = ::rand();
|
||||
#endif
|
||||
|
||||
return rnd % max;
|
||||
}
|
||||
|
||||
bigint random::rand( bigint & max )
|
||||
{
|
||||
unsigned n = ( max.bits() + ( ( sizeof( unsigned ) << 3 ) - 1 ) ) / ( sizeof( unsigned ) << 3 );
|
||||
unsigned * buf = (unsigned*)malloc(n * sizeof(unsigned));
|
||||
if ( !buf ) return max - 1;
|
||||
|
||||
bigint rnd;
|
||||
|
||||
#ifdef _WIN32
|
||||
if ( m_hCryptProv )
|
||||
CryptGenRandom( (HCRYPTPROV)m_hCryptProv, n * sizeof( unsigned ), (BYTE *)buf );
|
||||
#else
|
||||
for (unsigned i = 0; i < n; i++)
|
||||
*((unsigned *)buf + i) = ::rand();
|
||||
#endif
|
||||
|
||||
rnd.load( buf, n );
|
||||
|
||||
free(buf);
|
||||
|
||||
return rnd % max;
|
||||
}
|
||||
18
core/anslicensing/rand.h
Normal file
18
core/anslicensing/rand.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef __RAND_H
|
||||
#define __RAND_H
|
||||
|
||||
#include "bigint.h"
|
||||
|
||||
class random {
|
||||
public:
|
||||
random();
|
||||
~random();
|
||||
|
||||
unsigned rand( unsigned max );
|
||||
bigint rand( bigint & max );
|
||||
|
||||
protected:
|
||||
void * m_hCryptProv;
|
||||
};
|
||||
|
||||
#endif
|
||||
14
core/anslicensing/resource.h
Normal file
14
core/anslicensing/resource.h
Normal file
@@ -0,0 +1,14 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by licensing.rc
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
49
core/anslicensing/sdkregistration.cpp
Normal file
49
core/anslicensing/sdkregistration.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#include "precomp.h"
|
||||
#include "uniconv.h"
|
||||
#include "template.h"
|
||||
#include "validator.h"
|
||||
#include "sdkregistration.h"
|
||||
#include "version.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
bool SDKRegistrationImpl::isRegistered = true;
|
||||
bool SDKRegistrationImpl::isExpired = false;
|
||||
string SDKRegistrationImpl::licenseKey;
|
||||
|
||||
void SDKRegistrationImpl::SetLicenseKey(const char * key)
|
||||
{
|
||||
licenseKey = key;
|
||||
}
|
||||
|
||||
bool SDKRegistrationImpl::IsRegistered()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SDKRegistrationImpl::IsExpired()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const char * SDKRegistrationImpl::GetLicenseKey()
|
||||
{
|
||||
return licenseKey.c_str();
|
||||
}
|
||||
|
||||
namespace ANSCENTER {
|
||||
namespace Licensing {
|
||||
template<>
|
||||
void SDKRegistrationT<char>::SetLicenseKey(const char * key)
|
||||
{
|
||||
SDKRegistrationImpl::SetLicenseKey(key);
|
||||
}
|
||||
|
||||
template<>
|
||||
void SDKRegistrationT<wchar_t>::SetLicenseKey(const wchar_t * key)
|
||||
{
|
||||
string wkey = w2s(key);
|
||||
SDKRegistrationImpl::SetLicenseKey(wkey.c_str());
|
||||
}
|
||||
};
|
||||
};
|
||||
21
core/anslicensing/sdkregistration.h
Normal file
21
core/anslicensing/sdkregistration.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef __SDKREGISTRATION_H__
|
||||
#define __SDKREGISTRATION_H__
|
||||
|
||||
class SDKRegistrationImpl
|
||||
{
|
||||
public:
|
||||
static void SetLicenseKey(const char * key);
|
||||
|
||||
static const char * GetLicenseKey();
|
||||
|
||||
static bool IsRegistered();
|
||||
|
||||
static bool IsExpired();
|
||||
|
||||
private:
|
||||
static bool isRegistered;
|
||||
static bool isExpired;
|
||||
static string licenseKey;
|
||||
};
|
||||
|
||||
#endif
|
||||
160
core/anslicensing/sha1.cpp
Normal file
160
core/anslicensing/sha1.cpp
Normal file
@@ -0,0 +1,160 @@
|
||||
#include "precomp.h"
|
||||
#include "sha1.h"
|
||||
|
||||
#define MAX_FILE_READ_BUFFER 8000
|
||||
|
||||
// Rotate x bits to the left
|
||||
#ifndef ROL32
|
||||
#define ROL32(_val32, _nBits) (((_val32)<<(_nBits))|((_val32)>>(32-(_nBits))))
|
||||
#endif
|
||||
|
||||
#ifdef SHA1_LITTLE_ENDIAN
|
||||
#define SHABLK0(i) (m_block->l[i] = \
|
||||
(ROL32(m_block->l[i],24) & 0xFF00FF00) | (ROL32(m_block->l[i],8) & 0x00FF00FF))
|
||||
#else
|
||||
#define SHABLK0(i) (m_block->l[i])
|
||||
#endif
|
||||
|
||||
#define SHABLK(i) (m_block->l[i&15] = ROL32(m_block->l[(i+13)&15] ^ m_block->l[(i+8)&15] \
|
||||
^ m_block->l[(i+2)&15] ^ m_block->l[i&15],1))
|
||||
|
||||
// SHA-1 rounds
|
||||
#define _R0(v,w,x,y,z,i) { z+=((w&(x^y))^y)+SHABLK0(i)+0x5A827999+ROL32(v,5); w=ROL32(w,30); }
|
||||
#define _R1(v,w,x,y,z,i) { z+=((w&(x^y))^y)+SHABLK(i)+0x5A827999+ROL32(v,5); w=ROL32(w,30); }
|
||||
#define _R2(v,w,x,y,z,i) { z+=(w^x^y)+SHABLK(i)+0x6ED9EBA1+ROL32(v,5); w=ROL32(w,30); }
|
||||
#define _R3(v,w,x,y,z,i) { z+=(((w|x)&y)|(w&x))+SHABLK(i)+0x8F1BBCDC+ROL32(v,5); w=ROL32(w,30); }
|
||||
#define _R4(v,w,x,y,z,i) { z+=(w^x^y)+SHABLK(i)+0xCA62C1D6+ROL32(v,5); w=ROL32(w,30); }
|
||||
|
||||
SHA1::SHA1()
|
||||
{
|
||||
m_block = (SHA1_WORKSPACE_BLOCK *)m_workspace;
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
SHA1::~SHA1()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
void SHA1::Reset()
|
||||
{
|
||||
// SHA1 initialization constants
|
||||
m_state[0] = 0x67452301;
|
||||
m_state[1] = 0xEFCDAB89;
|
||||
m_state[2] = 0x98BADCFE;
|
||||
m_state[3] = 0x10325476;
|
||||
m_state[4] = 0xC3D2E1F0;
|
||||
|
||||
m_count[0] = 0;
|
||||
m_count[1] = 0;
|
||||
}
|
||||
|
||||
void SHA1::Transform(unsigned int state[5], unsigned char buffer[64])
|
||||
{
|
||||
unsigned int a = 0, b = 0, c = 0, d = 0, e = 0;
|
||||
|
||||
memcpy(m_block, buffer, 64);
|
||||
|
||||
// Copy state[] to working vars
|
||||
a = state[0];
|
||||
b = state[1];
|
||||
c = state[2];
|
||||
d = state[3];
|
||||
e = state[4];
|
||||
|
||||
// 4 rounds of 20 operations each. Loop unrolled.
|
||||
_R0(a,b,c,d,e, 0); _R0(e,a,b,c,d, 1); _R0(d,e,a,b,c, 2); _R0(c,d,e,a,b, 3);
|
||||
_R0(b,c,d,e,a, 4); _R0(a,b,c,d,e, 5); _R0(e,a,b,c,d, 6); _R0(d,e,a,b,c, 7);
|
||||
_R0(c,d,e,a,b, 8); _R0(b,c,d,e,a, 9); _R0(a,b,c,d,e,10); _R0(e,a,b,c,d,11);
|
||||
_R0(d,e,a,b,c,12); _R0(c,d,e,a,b,13); _R0(b,c,d,e,a,14); _R0(a,b,c,d,e,15);
|
||||
_R1(e,a,b,c,d,16); _R1(d,e,a,b,c,17); _R1(c,d,e,a,b,18); _R1(b,c,d,e,a,19);
|
||||
_R2(a,b,c,d,e,20); _R2(e,a,b,c,d,21); _R2(d,e,a,b,c,22); _R2(c,d,e,a,b,23);
|
||||
_R2(b,c,d,e,a,24); _R2(a,b,c,d,e,25); _R2(e,a,b,c,d,26); _R2(d,e,a,b,c,27);
|
||||
_R2(c,d,e,a,b,28); _R2(b,c,d,e,a,29); _R2(a,b,c,d,e,30); _R2(e,a,b,c,d,31);
|
||||
_R2(d,e,a,b,c,32); _R2(c,d,e,a,b,33); _R2(b,c,d,e,a,34); _R2(a,b,c,d,e,35);
|
||||
_R2(e,a,b,c,d,36); _R2(d,e,a,b,c,37); _R2(c,d,e,a,b,38); _R2(b,c,d,e,a,39);
|
||||
_R3(a,b,c,d,e,40); _R3(e,a,b,c,d,41); _R3(d,e,a,b,c,42); _R3(c,d,e,a,b,43);
|
||||
_R3(b,c,d,e,a,44); _R3(a,b,c,d,e,45); _R3(e,a,b,c,d,46); _R3(d,e,a,b,c,47);
|
||||
_R3(c,d,e,a,b,48); _R3(b,c,d,e,a,49); _R3(a,b,c,d,e,50); _R3(e,a,b,c,d,51);
|
||||
_R3(d,e,a,b,c,52); _R3(c,d,e,a,b,53); _R3(b,c,d,e,a,54); _R3(a,b,c,d,e,55);
|
||||
_R3(e,a,b,c,d,56); _R3(d,e,a,b,c,57); _R3(c,d,e,a,b,58); _R3(b,c,d,e,a,59);
|
||||
_R4(a,b,c,d,e,60); _R4(e,a,b,c,d,61); _R4(d,e,a,b,c,62); _R4(c,d,e,a,b,63);
|
||||
_R4(b,c,d,e,a,64); _R4(a,b,c,d,e,65); _R4(e,a,b,c,d,66); _R4(d,e,a,b,c,67);
|
||||
_R4(c,d,e,a,b,68); _R4(b,c,d,e,a,69); _R4(a,b,c,d,e,70); _R4(e,a,b,c,d,71);
|
||||
_R4(d,e,a,b,c,72); _R4(c,d,e,a,b,73); _R4(b,c,d,e,a,74); _R4(a,b,c,d,e,75);
|
||||
_R4(e,a,b,c,d,76); _R4(d,e,a,b,c,77); _R4(c,d,e,a,b,78); _R4(b,c,d,e,a,79);
|
||||
|
||||
// Add the working vars back into state[]
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
state[4] += e;
|
||||
|
||||
// Wipe variables
|
||||
a = b = c = d = e = 0;
|
||||
}
|
||||
|
||||
// Use this function to hash in binary data and strings
|
||||
void SHA1::Update(unsigned char *data, unsigned int len)
|
||||
{
|
||||
unsigned int i = 0, j;
|
||||
|
||||
j = (m_count[0] >> 3) & 63;
|
||||
|
||||
if((m_count[0] += len << 3) < (len << 3)) m_count[1]++;
|
||||
|
||||
m_count[1] += (len >> 29);
|
||||
|
||||
if((j + len) > 63)
|
||||
{
|
||||
memcpy(&m_buffer[j], data, (i = 64 - j));
|
||||
Transform(m_state, m_buffer);
|
||||
|
||||
for (; i+63 < len; i += 64)
|
||||
Transform(m_state, &data[i]);
|
||||
|
||||
j = 0;
|
||||
}
|
||||
else i = 0;
|
||||
|
||||
memcpy(&m_buffer[j], &data[i], len - i);
|
||||
}
|
||||
|
||||
void SHA1::Final()
|
||||
{
|
||||
unsigned int i = 0;
|
||||
unsigned char finalcount[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
finalcount[i] = (unsigned char)((m_count[(i >= 4 ? 0 : 1)]
|
||||
>> ((3 - (i & 3)) * 8) ) & 255); // Endian independent
|
||||
|
||||
Update((unsigned char *)"\200", 1);
|
||||
|
||||
while ((m_count[0] & 504) != 448)
|
||||
Update((unsigned char *)"\0", 1);
|
||||
|
||||
Update(finalcount, 8); // Cause a SHA1Transform()
|
||||
|
||||
for (i = 0; i < 20; i++)
|
||||
{
|
||||
m_digest[i] = (unsigned char)((m_state[i >> 2] >> ((3 - (i & 3)) * 8) ) & 255);
|
||||
}
|
||||
|
||||
// Wipe variables for security reasons
|
||||
i = 0;
|
||||
memset(m_buffer, 0, 64);
|
||||
memset(m_state, 0, 20);
|
||||
memset(m_count, 0, 8);
|
||||
memset(finalcount, 0, 8);
|
||||
|
||||
Transform(m_state, m_buffer);
|
||||
}
|
||||
|
||||
// Get the raw message digest
|
||||
void SHA1::GetHash(unsigned char *uDest)
|
||||
{
|
||||
memcpy(uDest, m_digest, 20);
|
||||
}
|
||||
58
core/anslicensing/sha1.h
Normal file
58
core/anslicensing/sha1.h
Normal file
@@ -0,0 +1,58 @@
|
||||
#ifndef ___SHA1_H___
|
||||
#define ___SHA1_H___
|
||||
|
||||
#include <stdio.h> // Needed for file access
|
||||
#include <memory.h> // Needed for memset and memcpy
|
||||
#include <string.h> // Needed for strcat and strcpy
|
||||
|
||||
#define SHA1_LITTLE_ENDIAN
|
||||
|
||||
#ifdef LICENSING_BIG_ENDIAN
|
||||
// If you're compiling big endian, just comment out the following line
|
||||
#undef SHA1_LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
typedef union
|
||||
{
|
||||
unsigned char c[64];
|
||||
unsigned int l[16];
|
||||
} SHA1_WORKSPACE_BLOCK;
|
||||
|
||||
class SHA1
|
||||
{
|
||||
public:
|
||||
// Two different formats for ReportHash(...)
|
||||
enum
|
||||
{
|
||||
REPORT_HEX = 0,
|
||||
REPORT_DIGIT = 1
|
||||
};
|
||||
|
||||
// Constructor and Destructor
|
||||
SHA1();
|
||||
virtual ~SHA1();
|
||||
|
||||
unsigned int m_state[5];
|
||||
unsigned int m_count[2];
|
||||
unsigned char m_buffer[64];
|
||||
unsigned char m_digest[20];
|
||||
|
||||
void Reset();
|
||||
|
||||
// Update the hash value
|
||||
void Update(unsigned char *data, unsigned int len);
|
||||
|
||||
// Finalize hash and report
|
||||
void Final();
|
||||
void GetHash(unsigned char *uDest);
|
||||
|
||||
private:
|
||||
// Private SHA-1 transformation
|
||||
void Transform(unsigned int state[5], unsigned char buffer[64]);
|
||||
|
||||
// Member variables
|
||||
unsigned char m_workspace[64];
|
||||
SHA1_WORKSPACE_BLOCK *m_block; // SHA1 pointer to the byte array above
|
||||
};
|
||||
|
||||
#endif
|
||||
1314
core/anslicensing/template.cpp
Normal file
1314
core/anslicensing/template.cpp
Normal file
File diff suppressed because it is too large
Load Diff
528
core/anslicensing/template.h
Normal file
528
core/anslicensing/template.h
Normal file
@@ -0,0 +1,528 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <map>
|
||||
|
||||
#include "ecc.h"
|
||||
#include "base64.h"
|
||||
#include "uniconv.h"
|
||||
#include "except.h"
|
||||
#include "sdkregistration.h"
|
||||
#include "certificate.h"
|
||||
#include "propertycollection.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class LicenseTemplateImpl {
|
||||
friend LicenseTemplate;
|
||||
|
||||
struct FieldInfo
|
||||
{
|
||||
FieldInfo(int _type, int _size, int _offset)
|
||||
{
|
||||
type = (BitStruct::FIELD_TYPE)_type;
|
||||
size = _size;
|
||||
offset = _offset;
|
||||
}
|
||||
|
||||
BitStruct::FIELD_TYPE type;
|
||||
int size;
|
||||
int offset;
|
||||
};
|
||||
|
||||
public:
|
||||
LicenseTemplateImpl(const char * xmlTemplate = NULL):
|
||||
m_defaultDataOffset(0),
|
||||
m_defaultValidationOffset(0)
|
||||
{
|
||||
Init();
|
||||
|
||||
if (xmlTemplate)
|
||||
LoadXml(xmlTemplate);
|
||||
}
|
||||
|
||||
void SetVersion(int version)
|
||||
{
|
||||
if (version > 3)
|
||||
throw new LicensingException(STATUS_UNSUPPORTED_VERSION);
|
||||
|
||||
m_version = version;
|
||||
}
|
||||
|
||||
unsigned GetVersion() const
|
||||
{
|
||||
return m_version;
|
||||
}
|
||||
|
||||
void SetNumberOfGroups(int numGroups)
|
||||
{
|
||||
m_numGroups = numGroups;
|
||||
}
|
||||
|
||||
unsigned GetNumberOfGroups() const
|
||||
{
|
||||
return m_numGroups;
|
||||
}
|
||||
|
||||
void SetCharactersPerGroup(int charsPerGroup)
|
||||
{
|
||||
m_charsPerGroup = charsPerGroup;
|
||||
}
|
||||
|
||||
unsigned GetCharactersPerGroup() const
|
||||
{
|
||||
return m_charsPerGroup;
|
||||
}
|
||||
|
||||
void SetGroupSeparator(const char * groupSep)
|
||||
{
|
||||
m_groupSeparator = groupSep;
|
||||
}
|
||||
|
||||
const char * GetGroupSeparator() const
|
||||
{
|
||||
return m_groupSeparator.c_str();
|
||||
}
|
||||
|
||||
void SetEncoding(int encoding)
|
||||
{
|
||||
m_keyEncoding = encoding;
|
||||
}
|
||||
|
||||
int GetEncoding() const
|
||||
{
|
||||
return m_keyEncoding;
|
||||
}
|
||||
|
||||
void SetHeader(const char * header)
|
||||
{
|
||||
m_header = header;
|
||||
}
|
||||
|
||||
const char * GetHeader() const
|
||||
{
|
||||
return m_header.c_str();
|
||||
}
|
||||
|
||||
void SetFooter(const char * footer)
|
||||
{
|
||||
m_footer = footer;
|
||||
}
|
||||
|
||||
const char * GetFooter() const
|
||||
{
|
||||
return m_footer.c_str();
|
||||
}
|
||||
|
||||
void SetDataSize(int sizeInBits)
|
||||
{
|
||||
m_dataSize = sizeInBits;
|
||||
}
|
||||
|
||||
unsigned GetDataSize() const
|
||||
{
|
||||
return m_dataSize;
|
||||
}
|
||||
|
||||
void AddDataField(const char * fieldName, int fieldType, int fieldSizeInBits, int fieldOffset = -1)
|
||||
{
|
||||
if (fieldOffset < 0)
|
||||
fieldOffset = m_defaultDataOffset;
|
||||
|
||||
m_dataFields.emplace(std::piecewise_construct, forward_as_tuple(fieldName), forward_as_tuple(fieldType, fieldSizeInBits, fieldOffset));
|
||||
|
||||
m_defaultDataOffset += fieldSizeInBits;
|
||||
}
|
||||
|
||||
bool GetDataField(const char * fieldName, int * fieldType, int * fieldSizeInBits, int * fieldOffset) const
|
||||
{
|
||||
auto info = m_dataFields.find(fieldName);
|
||||
|
||||
if (info == m_dataFields.end())
|
||||
return false;
|
||||
|
||||
*fieldType = info->second.type;
|
||||
*fieldSizeInBits = info->second.size;
|
||||
*fieldOffset = info->second.offset;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EnumDataFields(void **enumHandle, const char **fieldName, int * fieldType, int * fieldSizeInBits, int * fieldOffset) const
|
||||
{
|
||||
map<string, FieldInfo>::const_iterator* pIter;
|
||||
static string name;
|
||||
|
||||
if (*enumHandle == NULL)
|
||||
{
|
||||
pIter = new map<string, FieldInfo>::const_iterator(m_dataFields.begin());
|
||||
if (!pIter)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
pIter = (map<string, FieldInfo>::const_iterator*)(*enumHandle);
|
||||
|
||||
if (*pIter == m_dataFields.end())
|
||||
{
|
||||
delete pIter;
|
||||
return false;
|
||||
}
|
||||
|
||||
name = (*pIter)->first;
|
||||
*fieldName = name.c_str();
|
||||
|
||||
*fieldType = (*pIter)->second.type;
|
||||
*fieldSizeInBits = (*pIter)->second.size;
|
||||
*fieldOffset = (*pIter)->second.offset;
|
||||
|
||||
pIter->operator ++(); // *Iter++ does not work. Think why :)
|
||||
|
||||
*enumHandle = pIter;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetValidationDataSize(int sizeInBits)
|
||||
{
|
||||
m_validationDataSize = sizeInBits;
|
||||
}
|
||||
|
||||
unsigned GetValidationDataSize() const
|
||||
{
|
||||
return m_validationDataSize;
|
||||
}
|
||||
|
||||
void AddValidationField(const char * fieldName, int fieldType, int fieldBitSize, int fieldOffset = 0)
|
||||
{
|
||||
if (fieldOffset < 0)
|
||||
fieldOffset = m_defaultValidationOffset;
|
||||
|
||||
m_validationFields.emplace(piecewise_construct, forward_as_tuple(fieldName), forward_as_tuple(fieldType, fieldBitSize, fieldOffset));
|
||||
|
||||
m_defaultValidationOffset += fieldBitSize;
|
||||
}
|
||||
|
||||
bool GetValidationField(const char * fieldName, int * fieldType, int * fieldSizeInBits, int * fieldOffset) const
|
||||
{
|
||||
auto info = m_validationFields.find(fieldName);
|
||||
|
||||
if (info == m_validationFields.end())
|
||||
return false;
|
||||
|
||||
*fieldType = info->second.type;
|
||||
*fieldSizeInBits = info->second.size;
|
||||
*fieldOffset = info->second.offset;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EnumValidationFields(void **enumHandle, const char **fieldName, int * fieldType, int * fieldSize, int * fieldOffset) const
|
||||
{
|
||||
map<string, FieldInfo>::const_iterator* pIter;
|
||||
static string name;
|
||||
|
||||
if (*enumHandle == NULL)
|
||||
{
|
||||
pIter = new map<string, FieldInfo>::const_iterator(m_validationFields.begin());
|
||||
if (!pIter)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
pIter = (map<string, FieldInfo>::const_iterator*)(*enumHandle);
|
||||
|
||||
if (*pIter == m_validationFields.end())
|
||||
{
|
||||
delete pIter;
|
||||
return false;
|
||||
}
|
||||
|
||||
name = (*pIter)->first;
|
||||
*fieldName = name.c_str();
|
||||
|
||||
*fieldType = (*pIter)->second.type;
|
||||
*fieldSize = (*pIter)->second.size;
|
||||
*fieldOffset = (*pIter)->second.offset;
|
||||
|
||||
pIter->operator ++(); // *Iter++ does not work. Think why :)
|
||||
|
||||
*enumHandle = pIter;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetSignatureSize(int sizeInBits)
|
||||
{
|
||||
if (sizeInBits < 76 || sizeInBits > 322)
|
||||
throw new LicensingException(STATUS_INVALID_SIGNATURE_SIZE);
|
||||
|
||||
m_signatureSize = sizeInBits;
|
||||
|
||||
if (sizeInBits <= 108)
|
||||
{
|
||||
m_signatureKeyType = ECC::ECC_54;
|
||||
m_signatureKeySize = 54;
|
||||
} else
|
||||
if (sizeInBits <= 146)
|
||||
{
|
||||
m_signatureKeyType = ECC::ECC_73;
|
||||
m_signatureKeySize = 73;
|
||||
} else
|
||||
if (sizeInBits <= 158)
|
||||
{
|
||||
m_signatureKeyType = ECC::ECC_79;
|
||||
m_signatureKeySize = 79;
|
||||
} else
|
||||
if (sizeInBits <= 182)
|
||||
{
|
||||
m_signatureKeyType = ECC::ECC_91;
|
||||
m_signatureKeySize = 91;
|
||||
} else
|
||||
if (sizeInBits <= 200)
|
||||
{
|
||||
m_signatureKeyType = ECC::ECC_100;
|
||||
m_signatureKeySize = 100;
|
||||
} else
|
||||
if (sizeInBits <= 240)
|
||||
{
|
||||
m_signatureKeyType = ECC::ECC_120;
|
||||
m_signatureKeySize = 120;
|
||||
} else
|
||||
if (sizeInBits <= 262)
|
||||
{
|
||||
m_signatureKeyType = ECC::ECC_131;
|
||||
m_signatureKeySize = 131;
|
||||
} else
|
||||
if (sizeInBits <= 282)
|
||||
{
|
||||
m_signatureKeyType = ECC::ECC_141;
|
||||
m_signatureKeySize = 141;
|
||||
} else
|
||||
{
|
||||
m_signatureKeyType = ECC::ECC_161;
|
||||
m_signatureKeySize = 161;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned GetSignatureSize() const
|
||||
{
|
||||
return m_signatureSize;
|
||||
}
|
||||
|
||||
void LoadXml(const char * xmlTemplate);
|
||||
const char * SaveXml(bool savePrivateKey);
|
||||
|
||||
void LoadJson(const char * jsonTemplate);
|
||||
const char * SaveJson(bool savePrivateKey);
|
||||
|
||||
void SetLicensingServiceUrl(const char * url)
|
||||
{
|
||||
m_licensingServiceUrl = url;
|
||||
}
|
||||
|
||||
const char * GetLicensingServiceUrl() const
|
||||
{
|
||||
return m_licensingServiceUrl.c_str();
|
||||
}
|
||||
|
||||
void SetTemplateId(const char * templateId)
|
||||
{
|
||||
m_templateId = templateId;
|
||||
}
|
||||
|
||||
const char * GetTemplateId() const
|
||||
{
|
||||
return m_templateId.c_str();
|
||||
}
|
||||
|
||||
void SetLicensingServiceParameters(const char * params)
|
||||
{
|
||||
m_licensingServiceParameters = params;
|
||||
}
|
||||
|
||||
void SetLicenseGracePeriod(int days)
|
||||
{
|
||||
m_licenseGracePeriod = days;
|
||||
}
|
||||
|
||||
int GetLicenseGracePeriod() const
|
||||
{
|
||||
return m_licenseGracePeriod;
|
||||
}
|
||||
|
||||
void SetPublicKeyCertificate(const char * base64Certificate)
|
||||
{
|
||||
m_certificate = make_unique<Certificate>(base64Certificate);
|
||||
|
||||
ValidateCertificate();
|
||||
|
||||
unsigned char keyBuf[256]; int keyLen = 256;
|
||||
|
||||
m_certificate->GetPublicKey(keyBuf, &keyLen);
|
||||
|
||||
m_verificationKey = make_unique<ECC::Key>(keyBuf, keyLen);
|
||||
}
|
||||
|
||||
const char * GetPublicKeyCertificate() const
|
||||
{
|
||||
if (!m_certificate)
|
||||
throw new LicensingException(STATUS_GENERIC_ERROR, "the key template does not contain a certificate");
|
||||
|
||||
return m_certificate->ToString();
|
||||
}
|
||||
|
||||
void SetPrivateKey(const char * base64Key)
|
||||
{
|
||||
|
||||
BASE64 base64;
|
||||
int keyLen;
|
||||
int keyLenSizeT;
|
||||
|
||||
auto keyData = base64.decode(base64Key, (unsigned)strlen(base64Key), &keyLenSizeT);
|
||||
|
||||
if (keyData.empty())
|
||||
throw new LicensingException(STATUS_GENERIC_ERROR, "invalid base64 private key");
|
||||
|
||||
keyLen = (unsigned)keyLenSizeT;
|
||||
|
||||
SetPrivateKey(keyData.data(), keyLen);
|
||||
}
|
||||
|
||||
const char * GetPrivateKey() const
|
||||
{
|
||||
if (!m_signingKey)
|
||||
throw new LicensingException(STATUS_GENERIC_ERROR, "the key template does not contain a private key");
|
||||
|
||||
return m_signingKey->ToString();
|
||||
}
|
||||
|
||||
void GenerateSigningKeyPair()
|
||||
{
|
||||
Key * privateKey = NULL,
|
||||
* publicKey = NULL;
|
||||
|
||||
if (!SDKRegistrationImpl::IsRegistered())
|
||||
{
|
||||
privateKey = new Key(); privateKey->Load(&m_demoPrivateKeys[m_signatureKeyType][1], m_demoPrivateKeys[m_signatureKeyType][0], m_signatureKeyType);
|
||||
publicKey = new Key(); publicKey->Load(&m_demoPublicKeys[m_signatureKeyType][1], m_demoPublicKeys[m_signatureKeyType][0], m_signatureKeyType);
|
||||
} else
|
||||
{
|
||||
ECC::GenerateKeyPair(m_signatureKeyType, &privateKey, &publicKey);
|
||||
}
|
||||
|
||||
m_certificate.reset(Certificate::Generate(m_signatureSize, privateKey, publicKey, NULL, NULL, NULL, 0));
|
||||
|
||||
ValidateCertificate();
|
||||
|
||||
m_signingKey.reset(privateKey);
|
||||
|
||||
m_verificationKey.reset(publicKey);
|
||||
}
|
||||
|
||||
void SetProperty(const char * path, const char * name, const char * value)
|
||||
{
|
||||
m_properties.SetProperty(path, name, value);
|
||||
}
|
||||
|
||||
const char * GetProperty(const char * path, const char * name) const
|
||||
{
|
||||
return m_properties.GetProperty(path, name);
|
||||
}
|
||||
|
||||
public:
|
||||
// general
|
||||
int m_version;
|
||||
|
||||
// key format
|
||||
int m_numGroups;
|
||||
int m_charsPerGroup;
|
||||
int m_keyEncoding;
|
||||
string m_groupSeparator;
|
||||
string m_header;
|
||||
string m_footer;
|
||||
string m_licensingServiceUrl;
|
||||
string m_templateId;
|
||||
string m_licensingServiceParameters;
|
||||
|
||||
map<string, FieldInfo> m_dataFields;
|
||||
int m_defaultDataOffset;
|
||||
|
||||
map<string, FieldInfo> m_validationFields;
|
||||
int m_defaultValidationOffset;
|
||||
|
||||
// key signature
|
||||
unique_ptr<ECC::Key> m_verificationKey;
|
||||
unique_ptr<ECC::Key> m_signingKey;
|
||||
|
||||
unique_ptr<Certificate> m_certificate;
|
||||
bool m_hasPrivateKey;
|
||||
|
||||
ECC::KEY_TYPE m_signatureKeyType;
|
||||
int m_signatureKeySize;
|
||||
int m_signatureSize;
|
||||
int m_dataSize;
|
||||
int m_validationDataSize;
|
||||
|
||||
// buffer used to hold the xml representation of the template
|
||||
string m_xmlTemplate;
|
||||
|
||||
// other stuff
|
||||
int m_licenseGracePeriod;
|
||||
|
||||
PropertyCollection m_properties;
|
||||
|
||||
protected:
|
||||
static const unsigned char m_demoPublicKeys[10][23];
|
||||
static const unsigned char m_demoPrivateKeys[10][23];
|
||||
|
||||
private:
|
||||
void Init()
|
||||
{
|
||||
SetVersion(3);
|
||||
SetLicenseGracePeriod(0);
|
||||
SetGroupSeparator("-");
|
||||
SetNumberOfGroups(6);
|
||||
SetCharactersPerGroup(6);
|
||||
SetEncoding(ENCODING_BASE32X);
|
||||
SetSignatureSize(158);
|
||||
SetDataSize(22); // 6 groups * 6 chars per group * 5 bits per char - 158 signature size = 22 data size
|
||||
SetValidationDataSize(0);
|
||||
m_hasPrivateKey = false;
|
||||
}
|
||||
|
||||
void SetPrivateKey(const void * keyBuf, int keyLen)
|
||||
{
|
||||
ValidatePrivateKey(keyBuf, keyLen);
|
||||
|
||||
m_signingKey.reset(new Key(keyBuf, keyLen));
|
||||
|
||||
m_hasPrivateKey = true;
|
||||
}
|
||||
|
||||
void ValidatePrivateKey(const void * keyBuf, int keyLen)
|
||||
{
|
||||
if (keyLen <= 2)
|
||||
{
|
||||
throw new LicensingException(STATUS_INVALID_PARAM, "Invalid private key length");
|
||||
}
|
||||
|
||||
keyLen -= 2;
|
||||
keyBuf = (unsigned char *)keyBuf + 2;
|
||||
|
||||
if (!SDKRegistrationImpl::IsRegistered())
|
||||
{
|
||||
if (keyLen != m_demoPrivateKeys[m_signatureKeyType][0] || memcmp(keyBuf, &m_demoPrivateKeys[m_signatureKeyType][1], keyLen) != 0)
|
||||
{
|
||||
m_signingKey.reset();
|
||||
throw new LicensingException(STATUS_INVALID_PARAM, "Invalid public/private key. The SDK is in DEMO mode because a SDK license key was not set. In this mode, only certain public/private keys can be set. Did you set a valid SDK license key via ANSCENTER::Licensing::SDKRegistration::SetLicenseKey() ?");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ValidateCertificate()
|
||||
{
|
||||
unique_ptr<Certificate> validationCertificate = make_unique<Certificate>("AE4vDQELjMGgCJew5QSVMBWSAN2PaBa0zzYpjSYe0rcu88lYggE=");
|
||||
|
||||
if (!Certificate::VerifySignature(m_certificate.get(), validationCertificate.get()))
|
||||
throw new LicensingException(STATUS_GENERIC_ERROR, "certificate signature is not valid");
|
||||
}
|
||||
};
|
||||
2095
core/anslicensing/tinyxml2.cpp
Normal file
2095
core/anslicensing/tinyxml2.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1968
core/anslicensing/tinyxml2.h
Normal file
1968
core/anslicensing/tinyxml2.h
Normal file
File diff suppressed because it is too large
Load Diff
80
core/anslicensing/uniconv.h
Normal file
80
core/anslicensing/uniconv.h
Normal file
@@ -0,0 +1,80 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#ifdef _WIN32
|
||||
inline wstring s2w(const char* str, size_t size = -1)
|
||||
{
|
||||
if (size == -1)
|
||||
size = strlen(str);
|
||||
|
||||
if (size == 0)
|
||||
return wstring();
|
||||
|
||||
size_t req_size = ::MultiByteToWideChar(CP_UTF8, 0,
|
||||
str, (int)size, NULL, 0);
|
||||
|
||||
if (req_size == 0)
|
||||
throw runtime_error("Failed converting UTF-8 string to UTF-16");
|
||||
|
||||
wstring wstr(req_size, 0);
|
||||
|
||||
int conv_size = ::MultiByteToWideChar(CP_UTF8, 0,
|
||||
str, (int)size, wstr.data(), req_size);
|
||||
|
||||
if (conv_size == 0)
|
||||
throw runtime_error("Failed converting UTF-8 string to UTF-16");
|
||||
|
||||
return wstr;
|
||||
}
|
||||
|
||||
inline wstring s2w(const string& str)
|
||||
{
|
||||
return s2w(str.data(), str.size());
|
||||
}
|
||||
|
||||
inline string w2s(const wchar_t* wstr, size_t size = -1)
|
||||
{
|
||||
size_t req_size = WideCharToMultiByte(CP_UTF8, 0, wstr, size, nullptr, 0, nullptr, nullptr);
|
||||
|
||||
if (!req_size)
|
||||
throw runtime_error("wide to multibyte conversion failed");
|
||||
|
||||
string str(req_size, 0);
|
||||
|
||||
int conv_size = WideCharToMultiByte(CP_UTF8, 0L, wstr, size, str.data(), req_size, nullptr, nullptr);
|
||||
|
||||
if (!conv_size)
|
||||
throw runtime_error("wide to multibyte conversion failed");
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
inline string w2s(const wstring& wstr)
|
||||
{
|
||||
return w2s(wstr.data(), wstr.size());
|
||||
}
|
||||
#else
|
||||
inline wstring s2w(const char* str, size_t size = -1)
|
||||
{
|
||||
throw runtime_error("not implemented");
|
||||
}
|
||||
|
||||
inline wstring s2w(const string& str)
|
||||
{
|
||||
return s2w(str.data(), str.size());
|
||||
}
|
||||
|
||||
inline string w2s(const wchar_t* wstr, size_t size = -1)
|
||||
{
|
||||
throw runtime_error("not implemented");
|
||||
}
|
||||
|
||||
inline string w2s(const wstring& wstr)
|
||||
{
|
||||
return w2s(wstr.data(), wstr.size());
|
||||
}
|
||||
#endif
|
||||
205
core/anslicensing/validator.cpp
Normal file
205
core/anslicensing/validator.cpp
Normal file
@@ -0,0 +1,205 @@
|
||||
//
|
||||
// Copyright (c) ANSCENTER. All rights reserved.
|
||||
//
|
||||
|
||||
#include "precomp.h"
|
||||
#include "anslicensing.h"
|
||||
#include "template.h"
|
||||
#include "bitstream.h"
|
||||
#include "base32.h"
|
||||
#include "base64.h"
|
||||
#include "sha1.h"
|
||||
#include "except.h"
|
||||
#include "uniconv.h"
|
||||
#include "validator.h"
|
||||
|
||||
namespace ANSCENTER {
|
||||
namespace Licensing {
|
||||
template<>
|
||||
KeyValidatorT<char>::KeyValidatorT():
|
||||
m_Impl( *new KeyValidatorImpl() )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
template<>
|
||||
KeyValidatorT<wchar_t>::KeyValidatorT():
|
||||
m_Impl( *new KeyValidatorImpl() )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
template<>
|
||||
KeyValidatorT<char>::KeyValidatorT(const LicenseTemplateT<char> * keyTemplate):
|
||||
m_Impl( *new KeyValidatorImpl(&keyTemplate->m_Impl) )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
template<>
|
||||
KeyValidatorT<wchar_t>::KeyValidatorT(const LicenseTemplateT<wchar_t> * keyTemplate):
|
||||
m_Impl( *new KeyValidatorImpl(&keyTemplate->m_Impl) )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
template<>
|
||||
KeyValidatorT<char>::~KeyValidatorT()
|
||||
{
|
||||
delete & m_Impl;
|
||||
}
|
||||
|
||||
template<>
|
||||
KeyValidatorT<wchar_t>::~KeyValidatorT()
|
||||
{
|
||||
delete & m_Impl;
|
||||
}
|
||||
|
||||
template<>
|
||||
KeyValidatorT<char> * KeyValidatorT<char>::Create()
|
||||
{
|
||||
return new KeyValidatorT<char>();
|
||||
}
|
||||
|
||||
template<>
|
||||
KeyValidatorT<wchar_t> * KeyValidatorT<wchar_t>::Create()
|
||||
{
|
||||
return new KeyValidatorT<wchar_t>();
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyValidatorT<char>::Destroy(KeyValidatorT<char> * obj)
|
||||
{
|
||||
delete obj;
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyValidatorT<wchar_t>::Destroy(KeyValidatorT<wchar_t> * obj)
|
||||
{
|
||||
delete obj;
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyValidatorT<char>::SetKeyTemplate(const LicenseTemplateT<char> * templ)
|
||||
{
|
||||
m_Impl.SetKeyTemplate(&templ->m_Impl);
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyValidatorT<wchar_t>::SetKeyTemplate(const LicenseTemplateT<wchar_t> * templ)
|
||||
{
|
||||
m_Impl.SetKeyTemplate(&templ->m_Impl);
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyValidatorT<char>::SetValidationData(const char * fieldName, const void * buf, int len)
|
||||
{
|
||||
|
||||
m_Impl.SetValidationData(fieldName, buf, len);
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyValidatorT<wchar_t>::SetValidationData(const wchar_t * fieldName, const void * buf, int len)
|
||||
{
|
||||
m_Impl.SetValidationData(w2s(fieldName).c_str(), buf, len);
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyValidatorT<char>::SetValidationData(const char * fieldName, const char * data)
|
||||
{
|
||||
m_Impl.SetValidationData(fieldName, data);
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyValidatorT<wchar_t>::SetValidationData(const wchar_t * fieldName, const wchar_t * data)
|
||||
{
|
||||
|
||||
m_Impl.SetValidationData(w2s(fieldName).c_str(), w2s(data).c_str());
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyValidatorT<char>::SetValidationData(const char * fieldName, int data)
|
||||
{
|
||||
|
||||
m_Impl.SetValidationData(fieldName, data);
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyValidatorT<wchar_t>::SetValidationData(const wchar_t * fieldName, int data)
|
||||
{
|
||||
m_Impl.SetValidationData(w2s(fieldName).c_str(), data);
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyValidatorT<char>::SetKey(const char * key)
|
||||
{
|
||||
m_Impl.SetKey(key);
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyValidatorT<wchar_t>::SetKey(const wchar_t * key)
|
||||
{
|
||||
m_Impl.SetKey(w2s(key).c_str());
|
||||
}
|
||||
|
||||
template<>
|
||||
bool KeyValidatorT<char>::IsKeyValid()
|
||||
{
|
||||
return m_Impl.IsKeyValid();
|
||||
}
|
||||
|
||||
template<>
|
||||
bool KeyValidatorT<wchar_t>::IsKeyValid()
|
||||
{
|
||||
return m_Impl.IsKeyValid();
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyValidatorT<char>::QueryKeyData(const char * dataField, void * buf, int * len)
|
||||
{
|
||||
m_Impl.QueryKeyData(dataField, buf, len);
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyValidatorT<wchar_t>::QueryKeyData(const wchar_t * dataField, void * buf, int * len)
|
||||
{
|
||||
m_Impl.QueryKeyData(w2s(dataField).c_str(), buf, len);
|
||||
}
|
||||
|
||||
template<>
|
||||
int KeyValidatorT<char>::QueryIntKeyData(const char * dataField)
|
||||
{
|
||||
return m_Impl.QueryIntKeyData(dataField);
|
||||
}
|
||||
|
||||
template<>
|
||||
int KeyValidatorT<wchar_t>::QueryIntKeyData(const wchar_t * dataField)
|
||||
{
|
||||
return m_Impl.QueryIntKeyData(w2s(dataField).c_str());
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyValidatorT<char>::QueryDateKeyData(const char * dataField, int * year, int * month, int * day)
|
||||
{
|
||||
m_Impl.QueryDateKeyData(dataField, year, month, day);
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyValidatorT<wchar_t>::QueryDateKeyData(const wchar_t * dataField, int * year, int * month, int * day)
|
||||
{
|
||||
m_Impl.QueryDateKeyData(w2s(dataField).c_str(), year, month, day);
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyValidatorT<char>::QueryValidationData(const char * dataField, void * buf, int * len)
|
||||
{
|
||||
m_Impl.QueryValidationData(dataField, buf, len);
|
||||
}
|
||||
|
||||
template<>
|
||||
void KeyValidatorT<wchar_t>::QueryValidationData(const wchar_t * dataField, void * buf, int * len)
|
||||
{
|
||||
m_Impl.QueryValidationData((dataField) ? w2s(dataField).c_str() : NULL, buf, len);
|
||||
}
|
||||
};
|
||||
};
|
||||
224
core/anslicensing/validator.h
Normal file
224
core/anslicensing/validator.h
Normal file
@@ -0,0 +1,224 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "bitstream.h"
|
||||
#include "base64.h"
|
||||
#include "base32.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <tchar.h>
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
class KeyValidatorImpl {
|
||||
public:
|
||||
KeyValidatorImpl()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
KeyValidatorImpl(const LicenseTemplateImpl* templ, const char * key = NULL)
|
||||
{
|
||||
SetKeyTemplate(templ);
|
||||
|
||||
if (key)
|
||||
SetKey(key);
|
||||
}
|
||||
|
||||
~KeyValidatorImpl()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SetKeyTemplate(const LicenseTemplateImpl* templ)
|
||||
{
|
||||
m_keyTemplate = templ;
|
||||
|
||||
|
||||
if (templ->m_validationDataSize)
|
||||
{
|
||||
m_validationData.Create(templ->m_validationDataSize);
|
||||
|
||||
for (const auto& field : m_keyTemplate->m_validationFields)
|
||||
m_validationData.AddField(field.first.c_str(), field.second.type, field.second.size, field.second.offset);
|
||||
}
|
||||
else
|
||||
m_validationData.Create(0);
|
||||
}
|
||||
|
||||
void SetValidationData(const char * fieldName, const void * buf, int len)
|
||||
{
|
||||
m_validationData.Set(fieldName, buf, len);
|
||||
}
|
||||
|
||||
void SetValidationData(const char * fieldName, const char * data)
|
||||
{
|
||||
m_validationData.Set(fieldName, data);
|
||||
}
|
||||
|
||||
void SetValidationData(const char * fieldName, int data)
|
||||
{
|
||||
m_validationData.Set(fieldName, data);
|
||||
}
|
||||
|
||||
void SetValidationData(const char * fieldName, int year, int month, int day)
|
||||
{
|
||||
m_validationData.Set(fieldName, year, month, day);
|
||||
}
|
||||
|
||||
void SetKey(const char * licKey)
|
||||
{
|
||||
if (!licKey)
|
||||
throw new LicensingException(STATUS_INVALID_PARAM, "invalid license key");
|
||||
|
||||
string key(licKey);
|
||||
|
||||
if (key.length() < m_keyTemplate->GetCharactersPerGroup() * m_keyTemplate->GetNumberOfGroups() +
|
||||
strlen(m_keyTemplate->GetHeader()) +
|
||||
strlen(m_keyTemplate->GetFooter()) +
|
||||
strlen(m_keyTemplate->GetGroupSeparator()) * (m_keyTemplate->GetNumberOfGroups() - 1))
|
||||
{
|
||||
throw new LicensingException(STATUS_INVALID_LICENSE_KEY, "invalid license key (too short)");
|
||||
}
|
||||
|
||||
// remove header and footer (if any)
|
||||
if (!m_keyTemplate->m_header.empty())
|
||||
{
|
||||
key.erase(0, m_keyTemplate->m_header.length() + 2);
|
||||
}
|
||||
|
||||
if (!m_keyTemplate->m_footer.empty())
|
||||
{
|
||||
key.erase(key.length() - m_keyTemplate->m_footer.length() - 2, m_keyTemplate->m_footer.length() + 2);
|
||||
}
|
||||
|
||||
// ungroup license key
|
||||
for (int i = 0, erasePos = 0; i < m_keyTemplate->m_numGroups - 1; i++)
|
||||
{
|
||||
erasePos += m_keyTemplate->m_charsPerGroup;
|
||||
key.erase(erasePos, m_keyTemplate->m_groupSeparator.length());
|
||||
}
|
||||
|
||||
// decode license key
|
||||
switch ( m_keyTemplate->m_keyEncoding )
|
||||
{
|
||||
case ENCODING_BASE32X:
|
||||
{
|
||||
BASE32 base32;
|
||||
int padLen;
|
||||
int len = base32.encode_pad_length(((int)key.length() * 5 + 7) >> 3, &padLen);
|
||||
|
||||
if (len > (int)key.length())
|
||||
key.append(len - key.length(), 'A');
|
||||
|
||||
if (padLen)
|
||||
key.append(padLen,'=');
|
||||
|
||||
auto keyBuf = base32.decode(key.c_str(), (int)key.length(), &len );
|
||||
|
||||
if (keyBuf.empty())
|
||||
throw new LicensingException(STATUS_INVALID_LICENSE_KEY);
|
||||
|
||||
// reverse last byte
|
||||
keyBuf[ len - 1 ] = (unsigned char)(((keyBuf[ len - 1 ] * 0x0802LU & 0x22110LU) | (keyBuf[ len - 1 ] * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16);
|
||||
|
||||
m_keyData.Attach(keyBuf, m_keyTemplate->m_keyEncoding * m_keyTemplate->m_charsPerGroup * m_keyTemplate->m_numGroups);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case ENCODING_BASE64X:
|
||||
{
|
||||
BASE64 base64;
|
||||
int padLen;
|
||||
int len = base64.encode_pad_length(((int)key.length() * 6 + 7) >> 3, &padLen);
|
||||
|
||||
if (len > (int)key.length())
|
||||
key.append(len - key.length(), 'A');
|
||||
|
||||
if (padLen)
|
||||
key.append(padLen,'=');
|
||||
|
||||
auto keyBuf = base64.decode(key.c_str(), (int)key.length(), &len );
|
||||
|
||||
if (keyBuf.empty())
|
||||
throw new LicensingException(STATUS_INVALID_LICENSE_KEY);
|
||||
|
||||
// reverse last byte
|
||||
keyBuf[ len - 1 ] = (unsigned char)(((keyBuf[ len - 1 ] * 0x0802LU & 0x22110LU) | (keyBuf[ len - 1 ] * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16);
|
||||
|
||||
m_keyData.Attach(keyBuf, m_keyTemplate->m_keyEncoding * m_keyTemplate->m_charsPerGroup * m_keyTemplate->m_numGroups);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new LicensingException(STATUS_INVALID_KEY_ENCODING);
|
||||
}
|
||||
|
||||
for (const auto& field : m_keyTemplate->m_dataFields)
|
||||
m_keyData.AddField(field.first.c_str(), field.second.type, field.second.size, field.second.offset);
|
||||
}
|
||||
|
||||
bool IsKeyValid()
|
||||
{
|
||||
ECC::Verifier verifier;
|
||||
BitStream signedData,
|
||||
signature;
|
||||
|
||||
signedData.Create(m_keyTemplate->m_dataSize + m_keyTemplate->m_validationDataSize);
|
||||
signedData.Clear();
|
||||
|
||||
if (m_keyTemplate->m_dataSize)
|
||||
signedData.Write(m_keyData.GetBuffer(), m_keyTemplate->m_dataSize);
|
||||
|
||||
if (m_keyTemplate->m_validationDataSize)
|
||||
signedData.Write(m_validationData.GetBuffer(), m_keyTemplate->m_validationDataSize);
|
||||
|
||||
signature.Create(m_keyTemplate->m_signatureSize);
|
||||
m_keyData.GetBitStream().Seek(m_keyTemplate->m_dataSize);
|
||||
m_keyData.GetBitStream().Read(signature.GetBuffer(), m_keyTemplate->m_signatureSize);
|
||||
signature.ReleaseBuffer(m_keyTemplate->m_signatureSize);
|
||||
signature.Seek(m_keyTemplate->m_signatureSize);
|
||||
signature.ZeroPadToNextByte();
|
||||
|
||||
signature.ReleaseBuffer(m_keyTemplate->m_signatureSize);
|
||||
|
||||
// we use a different algorithm than ECDSA when the signature size must be smaller than twice the key size
|
||||
if (m_keyTemplate->m_signatureSize < (m_keyTemplate->m_signatureKeySize << 1))
|
||||
verifier.SetHashSize(m_keyTemplate->m_signatureSize - m_keyTemplate->m_signatureKeySize);
|
||||
else
|
||||
verifier.SetHashSize(0);
|
||||
|
||||
verifier.SetPublicKey(m_keyTemplate->m_verificationKey.get());
|
||||
|
||||
return verifier.Verify(signedData.GetBuffer(), (signedData.GetSize() + 7) >> 3, signature.GetBuffer(), (signature.GetSize() + 7) >> 3 , m_keyTemplate->m_signatureSize);
|
||||
}
|
||||
|
||||
void QueryKeyData(const char * fieldName, void * buf, int * len)
|
||||
{
|
||||
m_keyData.Get(fieldName, buf, len);
|
||||
}
|
||||
|
||||
int QueryIntKeyData(const char * fieldName)
|
||||
{
|
||||
return m_keyData.GetInt(fieldName);
|
||||
}
|
||||
|
||||
void QueryDateKeyData(const char * fieldName, int * year, int * month, int * day)
|
||||
{
|
||||
m_keyData.GetDate(fieldName, year, month, day);
|
||||
}
|
||||
|
||||
void QueryValidationData(const char * fieldName, void * buf, int * len)
|
||||
{
|
||||
return m_validationData.Get(fieldName, buf, len);
|
||||
}
|
||||
|
||||
public:
|
||||
const LicenseTemplateImpl* m_keyTemplate;
|
||||
BitStruct m_keyData;
|
||||
BitStruct m_validationData;
|
||||
};
|
||||
6
core/anslicensing/version.h
Normal file
6
core/anslicensing/version.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#define VERSION_MAJOR 3
|
||||
#define VERSION_MINOR 9
|
||||
#define VERSION_BUILD 52
|
||||
#define BUILD_TIMESTAMP 1479947203
|
||||
209
core/anslicensing/wmihelper.h
Normal file
209
core/anslicensing/wmihelper.h
Normal file
@@ -0,0 +1,209 @@
|
||||
#pragma once
|
||||
|
||||
#define _WIN32_DCOM
|
||||
#include <iostream>
|
||||
#include <comdef.h>
|
||||
#include <Wbemidl.h>
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
#include "uniconv.h"
|
||||
|
||||
#pragma comment(lib, "wbemuuid.lib")
|
||||
|
||||
using namespace std;
|
||||
|
||||
class WmiHelper
|
||||
{
|
||||
public:
|
||||
WmiHelper()
|
||||
{
|
||||
HRESULT hres;
|
||||
|
||||
wbemServices = NULL;
|
||||
wbemLocator = NULL;
|
||||
ownCoInitialize = false;
|
||||
|
||||
// Initialize COM.
|
||||
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
|
||||
if (hres == S_OK)
|
||||
{
|
||||
ownCoInitialize = true;
|
||||
}
|
||||
|
||||
// Initialize
|
||||
hres = CoInitializeSecurity(
|
||||
NULL,
|
||||
-1, // COM negotiates service
|
||||
NULL, // Authentication services
|
||||
NULL, // Reserved
|
||||
RPC_C_AUTHN_LEVEL_DEFAULT, // authentication
|
||||
RPC_C_IMP_LEVEL_IMPERSONATE, // Impersonation
|
||||
NULL, // Authentication info
|
||||
EOAC_NONE, // Additional capabilities
|
||||
NULL // Reserved
|
||||
);
|
||||
|
||||
hres = CoCreateInstance(
|
||||
CLSID_WbemLocator,
|
||||
0,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
IID_IWbemLocator, (LPVOID *) &wbemLocator);
|
||||
|
||||
if (FAILED(hres))
|
||||
{
|
||||
if (ownCoInitialize)
|
||||
CoUninitialize();
|
||||
|
||||
throw new exception("failed to create IWbemLocator", hres);
|
||||
}
|
||||
|
||||
// Connect to the root\cimv2 namespace with the
|
||||
// current user and obtain pointer pSvc
|
||||
// to make IWbemServices calls.
|
||||
|
||||
hres = wbemLocator->ConnectServer(
|
||||
|
||||
_bstr_t(L"ROOT\\CIMV2"), // WMI namespace
|
||||
NULL, // User name
|
||||
NULL, // User password
|
||||
0, // Locale
|
||||
NULL, // Security flags
|
||||
0, // Authority
|
||||
0, // Context object
|
||||
&wbemServices // IWbemServices proxy
|
||||
);
|
||||
|
||||
if (FAILED(hres))
|
||||
{
|
||||
wbemLocator->Release();
|
||||
|
||||
if (ownCoInitialize)
|
||||
CoUninitialize();
|
||||
|
||||
throw new exception("could not connect to WMI", hres);
|
||||
}
|
||||
|
||||
// Set the IWbemServices proxy so that impersonation
|
||||
// of the user (client) occurs.
|
||||
hres = CoSetProxyBlanket(
|
||||
wbemServices, // the proxy to set
|
||||
RPC_C_AUTHN_WINNT, // authentication service
|
||||
RPC_C_AUTHZ_NONE, // authorization service
|
||||
NULL, // Server principal name
|
||||
RPC_C_AUTHN_LEVEL_CALL, // authentication level
|
||||
RPC_C_IMP_LEVEL_IMPERSONATE, // impersonation level
|
||||
NULL, // client identity
|
||||
EOAC_NONE // proxy capabilities
|
||||
);
|
||||
|
||||
if (FAILED(hres))
|
||||
{
|
||||
wbemServices->Release();
|
||||
wbemLocator->Release();
|
||||
if (ownCoInitialize) CoUninitialize();
|
||||
throw new exception("could not connecto to WMI", hres);
|
||||
}
|
||||
}
|
||||
|
||||
~WmiHelper()
|
||||
{
|
||||
if (wbemServices) wbemServices->Release();
|
||||
if (wbemLocator) wbemLocator->Release();
|
||||
if (ownCoInitialize) CoUninitialize();
|
||||
}
|
||||
|
||||
void GetPropertyList(const char * wqlQuery, const char * propertyName, list<string> * propList, int maxElements = 0x7FFFFFFF)
|
||||
{
|
||||
HRESULT hres;
|
||||
|
||||
// For example, query for all the running processes
|
||||
IEnumWbemClassObject* pEnumerator = NULL;
|
||||
hres = wbemServices->ExecQuery(
|
||||
bstr_t("WQL"),
|
||||
bstr_t(wqlQuery),
|
||||
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
|
||||
NULL,
|
||||
&pEnumerator);
|
||||
|
||||
if (FAILED(hres))
|
||||
{
|
||||
throw new exception("WMI query failed");
|
||||
}
|
||||
else
|
||||
{
|
||||
IWbemClassObject *pclsObj;
|
||||
ULONG uReturn = 0;
|
||||
int numElements = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
hres = pEnumerator->Next(WBEM_INFINITE, 1,
|
||||
&pclsObj, &uReturn);
|
||||
|
||||
if(0 == uReturn)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
VARIANT vtProp;
|
||||
VariantInit(&vtProp);
|
||||
|
||||
// Get the value of the Name property
|
||||
hres = pclsObj->Get(_bstr_t(propertyName), 0, &vtProp, 0, 0);
|
||||
//
|
||||
if (SUCCEEDED(hres))
|
||||
{
|
||||
switch (vtProp.vt)
|
||||
{
|
||||
case VT_BSTR:
|
||||
propList->push_back(w2s(vtProp.bstrVal).c_str());
|
||||
numElements++;
|
||||
break;
|
||||
|
||||
case VT_I1:
|
||||
case VT_UI1:
|
||||
case VT_I2:
|
||||
case VT_UI2:
|
||||
case VT_I4:
|
||||
case VT_UI4:
|
||||
{
|
||||
char strVal[32];
|
||||
_itoa(vtProp.intVal, strVal, 10);
|
||||
propList->push_back(strVal);
|
||||
numElements++;
|
||||
}
|
||||
break;
|
||||
|
||||
case VT_I8:
|
||||
case VT_UI8:
|
||||
{
|
||||
char strVal[32];
|
||||
_i64toa(vtProp.llVal, strVal, 10);
|
||||
propList->push_back(strVal);
|
||||
numElements++;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
VariantClear(&vtProp);
|
||||
}
|
||||
|
||||
pclsObj->Release();
|
||||
|
||||
if (numElements >= maxElements)
|
||||
break;
|
||||
}
|
||||
|
||||
pEnumerator->Release();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool ownCoInitialize;
|
||||
IWbemServices * wbemServices;
|
||||
IWbemLocator * wbemLocator;
|
||||
};
|
||||
Reference in New Issue
Block a user