📄 pgplicensenumber.c
字号:
/*____________________________________________________________________________
Copyright (C) 2002 PGP Corporation
All rights reserved.
$Id: pgpLicenseNumber.c,v 1.27 2002/11/25 05:45:59 jason Exp $
____________________________________________________________________________*/
#include <ctype.h>
#include <string.h>
/* We need to include this in order to get the PGP_BETA flag before its use in the license# file */
#if PGP_OSX
#include "pgpBuild.h"
#endif
#include "pgpLicenseNumber.h"
#include "pgpLicenseNumberNet.h"
#include "pgpUtilities.h"
#include "pgpPublicKey.h"
#include "pgpMem.h"
#include "pgpHash.h"
#include "pgpSymmetricCipher.h"
#include "pgpKeys.h"
#include "pgpEncode.h"
#include "string.h"
#include "pgpErrors.h"
#include "pgpStrings.h"
#include "pgpEndianConversion.h"
#include "pgpUnicode.h"
#include "pgpLNClientKeys.h" /* keys that are needed for a client */
#ifdef PGP_LICENSE_SERVER
/* additional private or secret keys that are needed by a server only */
#include "pgpLNServerKeys.h"
#endif
#include "stdio.h"
#ifndef PGP_LICENSE_NET
#define PGP_LICENSE_NET 1 /* Enable network LA by default */
#endif
#ifdef PGP_WIN32
#pragma warning (disable: 4057)
#pragma intrinsic(memset)
#define CLEAR_LICENSENUMBER(ppn) memset( ppn, 0, sizeof(LICENSENUMBER) )
#else
#define CLEAR_LICENSENUMBER(ppn) pgpClearMemory( ppn,sizeof(LICENSENUMBER) )
#endif
static const PGPByte beginLicense[]={"-----BEGIN PGP LICENSE AUTHORIZATION-----"};
static const PGPByte endLicense[]={"-----END PGP LICENSE AUTHORIZATION-----"};
static PGPUInt8 base32chars[]={
"ACDEFGHJKLMNPQRT" "UVWXYZ234679B015"
"________________" "____________8OIS" /* similiar looking duplicates */
};
static const PGPByte emptyCustomerName[] = "<blank>";
static const PGPByte * const emptyCompanyName = emptyCustomerName;
// for each field corresponding parameter name is given -- check pgplng and server code
typedef struct _LICENSENUMBER
{
PGPUInt8 version; // "version"
PGPUInt8 productID; // "prodid"
PGPUInt16 evalPeriod; // 0 - is never expires, "evaldays"
PGPUInt32 numLicenses; // 24 bit, 0 - reserved, "licenses"
PGPUInt8 flags; // "flags" = {"eval","enterprise","disk","mail"}
PGPUInt32 serialNumber; // "sn"
PGPUInt8 shaHash[2];
} LICENSENUMBER;
#define LICENSENUMBER_BIN_SIZE 17 /* serialization size, sizeof(LICENSENUMBER) can be more because of alignment */
#define LICENSENUMBER_BASE32_SIZE (LICENSENUMBER_BIN_SIZE*8/5+1)
/*upper bound, used for memory allocation only*/
typedef struct PGPLicenseNumber {
PGPByte ln_encr[LICENSENUMBER_BIN_SIZE];
} PGPLicenseNumber; // Exported: [17 bytes ln], ln has a version that will tell the size
typedef struct PGPLicenseAuthorization {
PGPByte type;
PGPUInt16 issuanceDate; // days since 9/1/2002
PGPSize signatureSize;
PGPByte signature[1];
// + signatureSize-1 bytes // Exported: [2 bytes total size] [1 byte type] [2 bytes issuanceDate] [reserved=0] [signature]
} PGPLicenseAuthorization;
static void lnToStream( const LICENSENUMBER *ln, PGPByte ln_stream[LICENSENUMBER_BIN_SIZE] ) {
PGPUInt32 u;
PGPByte *p = ln_stream;
p[0] = ln->version;
p[1] = ln->productID;
u = ln->evalPeriod;
p[2] = (PGPByte)(u >> 8);
p[3] = (PGPByte)u;
u = ln->numLicenses;
p[4] = (PGPByte)(u >> 16);
p[5] = (PGPByte)(u >> 8);
p[6] = (PGPByte)u;
p[7] = ln->flags;
u = ln->serialNumber;
p[8] = (PGPByte)(u >> 24);
p[9] = (PGPByte)(u >> 16);
p[10] = (PGPByte)(u >> 8);
p[11] = (PGPByte)u;
p[12] = p[13] = p[14] = 0;
p[15] = ln->shaHash[0];
p[16] = ln->shaHash[1];
}
static void lnFromStream( const PGPByte ln_stream[LICENSENUMBER_BIN_SIZE], LICENSENUMBER *ln ) {
const PGPByte *p = ln_stream;
ln->version = p[0];
ln->productID = p[1];
ln->evalPeriod = (PGPUInt16)(p[2] << 8 | p[3]);
ln->numLicenses = p[4] << 16 | p[5] << 8 | p[6];
ln->flags = p[7];
ln->serialNumber = p[8] << 24 | p[9] << 16 | p[10] << 8 | p[11];
// ln->unused[0] = p[12]; ln->unused[1] = p[13]; ln->unused[2] = p[14];
ln->shaHash[0] = p[15];
ln->shaHash[1] = p[16];
}
static void laToStream( const PGPLicenseAuthorization *la, PGPByte *stream ) {
PGPUInt32 u;
u = la->signatureSize + 6;
stream[0] = (PGPByte)(u >> 8);
stream[1] = (PGPByte)u;
stream[2] = la->type;
u = la->issuanceDate;
stream[3] = (PGPByte)(u >> 8);
stream[4] = (PGPByte)u;
stream[5] = 0; // reserved
pgpCopyMemory( la->signature, stream+6, la->signatureSize );
}
// exact size required to serialize the object
static PGPUInt16 laToStreamSize( const PGPLicenseAuthorization *la ) {
return (PGPUInt16)(la->signatureSize + 6);
}
// size of the serialized object read from the stream
static PGPUInt16 laFromStreamSize( const PGPByte *stream ) {
const PGPUInt16 size = (PGPUInt16)(stream[0] << 8 | stream[1]);
return (PGPUInt16)( size > 128+6 ? 0 : size);
}
/* la should be already allocated, use laPeekSize */
static void laFromStream( const PGPByte *stream, PGPLicenseAuthorization *la ) {
const PGPUInt16 size = laFromStreamSize( stream );
if( !size ) {
la->signatureSize = 0;
la->type = 0;
la->issuanceDate = 0;
return;
}
la->signatureSize = size-6;
la->type = stream[2];
la->issuanceDate = (PGPUInt16)(stream[3] << 8 | stream[4]);
pgpCopyMemory( stream+6, la->signature, la->signatureSize );
}
// number of days from the 9/1/02 to the 'curr' time
static const time_t Sep_1_2002_time_t = 0x3d71c901; // time_t for Sun Sep 01 00:00:01 2002, no DST
static PGPUInt32 daysElapsed( PGPTime curr, PGPBoolean roundUp ) {
time_t curr_time_t = PGPGetStdTimeFromPGPTime( curr );
PGPUInt32 days = (PGPUInt32)(-1);
if( !curr )
return (PGPUInt32)(-1);
if( curr_time_t > Sep_1_2002_time_t ) {
days = ( curr_time_t - Sep_1_2002_time_t ) / 3600;
days = (days + (roundUp ? 23 : 0))/24;
}
else {
// 37779 (0x9393) days from the Sep_1_2002_time_t left to overlap 0xffffffff
// allow one overlap
curr_time_t /= 3600;
curr_time_t = (curr_time_t+(roundUp ? 23 : 0)) / 24;
days = 37779 + curr_time_t;
}
return days;
}
#if 0 /* not used, but working */
static PGPTime daysElapsedToTime( PGPUInt32 daysElapsed ) {
time_t t;
if( daysElapsed > 37779 )
return (PGPTime)(-1); // need to fix after 2037
t = Sep_1_2002_time_t + daysElapsed*24*3600;
return PGPGetPGPTimeFromStdTime( t );
}
#endif
#if 0 /* not used, but working */
static void daysElapsedToStr( PGPUInt32 daysElapsed, PGPByte str[16] ) {
PGPTime t = daysElapsedToTime(daysElapsed);
struct tm *tm;
tm = gmtime(&t);
(void)strftime( str, 16, "%Y%m%d", tm);
}
#endif
#if 0 /* not used, but working */
static PGPUInt32 strToDaysElapsed( const PGPByte str[16] ) {
struct tm tm;
PGPByte s[10] = { '\0', '\0', '\0', '\0', '\0' };
time_t t;
pgpClearMemory( &tm, sizeof(tm) );
s[0] = str[4]; s[1] = str[5];
tm.tm_mon = atoi(s)-1;
s[0] = str[6]; s[1] = str[7];
tm.tm_mday = atoi(s);
s[0] = str[0]; s[1] = str[1]; s[2] = str[2]; s[3] = str[3];
tm.tm_year = atoi(s)-1900;
tm.tm_sec = 1;
t = mktime( &tm );
if( t == (time_t)-1 )
return (PGPUInt32)(-1);
return daysElapsed( PGPGetPGPTimeFromStdTime( t ), FALSE );
}
#endif
// Base32 encode binary license data
static PGPError pgpEncode32(
const PGPByte *inBytes, PGPSize inSize,
PGPByte outBytes[kPGPLicenseNumberMaxSize])
{
PGPUInt32 bits,bitcnt,value,bytenum,shift,memamt;
PGPError err;
err=kPGPError_NoErr;
bits=inSize*8;
memamt=((bits+4)/5)+1; // +1 for convenience NULL terminate
if( memamt > kPGPLicenseNumberMaxSize ) {
outBytes[0] = '\0';
return kPGPError_OutOfMemory;
}
pgpClearMemory(outBytes,memamt);
for(bitcnt=0;bitcnt<bits;bitcnt+=5)
{
bytenum=bitcnt/8;
shift=bitcnt%8;
value = inBytes[bytenum];
if( bytenum < inSize-1 )
value |= (inBytes[bytenum+1] << 8);
value = (value >> shift) & 0x1f;
outBytes[bitcnt/5]=base32chars[value];
}
return err;
}
// Base32 decode license data
static PGPError pgpDecode32(const PGPByte *inBytes,
PGPByte outBytes[kPGPLicenseNumberMaxSize], PGPSize *outSize )
{
PGPUInt32 chcnt,numbits,memamt,place,bytenum,shift,value;
PGPError err;
PGPSize inSize;
PGPByte *pc;
if (!inBytes)
return kPGPError_BadParams;
inSize = strlen( inBytes );
err=kPGPError_NoErr;
outBytes[0] = '\0';
*outSize = 0;
numbits=inSize*5;
memamt=(numbits+7)/8;
if(memamt+1 > kPGPLicenseNumberMaxSize)
return kPGPError_BufferTooSmall;
/* check that last base 32 character carries the value no greater then needed */
pc = strchr( base32chars, inBytes[inSize-1] );
if( pc==NULL || *pc == '_' ) /* wrong character */
return kPGPError_CorruptData;
value=(PGPUInt32)(pc - base32chars) / sizeof(base32chars[0]);
if( value > 32 )
value -= 32; /* we hit duplicate */
shift = (inSize*5) % 8; /* extra bits that must be zero */
if( shift > 5 )
return kPGPError_CorruptData;
shift = 5 - shift; /* now shift is number of bits that last base char encodes */
if( shift > 0 && value > ~((PGPUInt32)(-1)<<shift) )
return kPGPError_CorruptData;
pgpClearMemory( outBytes, memamt+1 );
for(chcnt=0;chcnt<inSize;chcnt++)
{
place=chcnt*5;
bytenum=place/8;
shift=place%8;
pc = strchr( base32chars, inBytes[chcnt] );
if( pc==NULL || *pc == '_' ) /* wrong character */
return kPGPError_CorruptData;
value=(PGPUInt32)(pc - base32chars) / sizeof(base32chars[0]);
if( value > 32 )
value -= 32; /* we hit duplicate */
outBytes[bytenum] |= (PGPByte)(value << shift);
if( shift > 8-5 ) {
outBytes[bytenum+1] |= (value >> (8-shift));
*outSize = bytenum + 1;
}
else
*outSize = bytenum;
}
return err;
}
#define TC_E_PARSE kPGPError_CorruptData
#define SKIPWS(c) while (isspace ((int) (*(c)))) c++
static const unsigned char BaseChars[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
#define BaseChar(c) BaseChars[c]
static const unsigned char BaseVals[] = {
0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,62, 0xff,0xff,0xff,63,
52,53,54,55, 56,57,58,59, 60,61,0xff,0xff, 0xff,0xff,0xff,0xff,
0xff, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14,
15,16,17,18, 19,20,21,22, 23,24,25,0xff, 0xff,0xff,0xff,0xff,
0xff,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
41,42,43,44, 45,46,47,48, 49,50,51,0xff, 0xff,0xff,0xff,0xff
};
#define BaseVal(c) BaseVals[c]
PGPError
tc_encode_base64 (PGPMemoryMgrRef mem, unsigned char **out, size_t *outlen,
const unsigned char *in, size_t inlen )
{
unsigned char *curpos;
unsigned char a, b, c;
/* determine how long the output will be. if it is not a multple of 3
* bytes, increase length so that it is so that the pad characters are
* accounted for.
*/
if (inlen % 3 != 0)
*outlen = inlen + 3 - inlen % 3;
else
*outlen = inlen;
/* base64 encoding creates 4 output chars for every 3 input chars */
*outlen = 4 * (*outlen) / 3;
if ((*out = PGPNewData(mem, *outlen + 1, 0)) == NULL)
return kPGPError_OutOfMemory;
curpos = *out;
while (inlen)
{
a = *in++;
inlen--;
*curpos++ = BaseChar (a >> 2);
if (inlen)
b = *in++;
else
b = 0;
*curpos++ = BaseChar (((a & 0x03) << 4) | (b >> 4));
if (!inlen)
{
*curpos++ = '=';
*curpos++ = '=';
break;
}
inlen--;
if (inlen)
c = *in++;
else
c = 0;
*curpos++ = BaseChar (((b & 0x0f) << 2) | (c >> 6));
if (!inlen)
{
*curpos++ = '=';
break;
}
inlen--;
*curpos++ = BaseChar (c & 0x3f);
}
*curpos = 0;
return kPGPError_NoErr;
}
PGPError
tc_decode_base64 (PGPMemoryMgrRef mem, unsigned char **out,
size_t *outlen, const unsigned char *in )
{
unsigned char *curpos;
unsigned char a, b;
PGPError err = kPGPError_NoErr;
*outlen = (3 * strlen ((PGPByte *) in)) / 4; /* maximum length */
if ((*out = PGPNewData(mem, *outlen, 0)) == NULL)
return kPGPError_OutOfMemory;
curpos = *out;
SKIPWS (in);
while (*in)
{
a = *in++;
SKIPWS (in);
if (!*in) {
err = TC_E_PARSE;
break;
}
b = *in++;
SKIPWS (in);
if (!*in) {
err = TC_E_PARSE;
break;
}
*curpos++ = (BaseVal (a) << 2) | (BaseVal (b) >> 4);
a = b;
b = *in++;
SKIPWS (in);
if (!*in) {
err = TC_E_PARSE;
break;
}
if (b == '=')
break;
*curpos++ = (BaseVal (a) << 4) | (BaseVal (b) >> 2);
a = b;
b = *in++;
SKIPWS (in);
if (b == '=')
break;
*curpos++ = (BaseVal (a) << 6) | BaseVal (b);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -