📄 pgplicensenumber.c
字号:
/* single entry for calculating the hash of the license number to be used in
signature generation (license authorization) and verification (license verification).
*/
static PGPError calculateLNHash(
PGPContextRef context, const PGPLicenseNumberRef licenseNumber,
const PGPByte *customerName, const PGPByte *companyName, PGPUInt16 issuanceDate,
PGPHashContextRef hashContext )
{
PGPError err;
LICENSENUMBER ln;
PGPByte ln_buf[LICENSENUMBER_BIN_SIZE];
err=pgpDecryptLicenseNumber(context,licenseNumber,&ln);
lnToStream( &ln, ln_buf );
if(IsPGPError(err))
return err;
/* hash LN */
err=PGPContinueHash(hashContext, ln_buf, LICENSENUMBER_BIN_SIZE);
CLEAR_LICENSENUMBER( &ln );
pgpClearMemory( ln_buf, sizeof(ln_buf) );
/* hash customerName and companyName */
if( IsntPGPError(err) )
err = calculateNameHash( context, customerName, companyName, hashContext );
/* hash date */
if(IsntPGPError(err)) {
const PGPByte two[2] = { (PGPByte)(issuanceDate>>8), (PGPByte)issuanceDate };
err=PGPContinueHash(hashContext, two, sizeof(two));
}
return err;
}
/* Creates license number based on LN and entry fields (using
hard coded private key). For use by web tools.
Creates an output buffer and writes PGP DSA signature in binary form, sets size.
*/
PGPError pgpLACreateLocal(PGPContextRef context, const PGPLicenseNumberRef licenseNumber,
const PGPByte *customerName, const PGPByte *companyName, PGPLicenseAuthorizationRef *buffer)
{
#ifndef PGP_LICENSE_SERVER // Must have the private key
(void)context;
(void)licenseNumber;
(void)customerName;
(void)companyName;
(void)buffer;
return kPGPError_LazyProgrammer;
#else //PGP_LICENSE_SERVER
PGPError err;
PGPKeyDBRef keyDB = kInvalidPGPKeyDBRef;
PGPKeyDBObjRef key = kInvalidPGPKeyDBObjRef;
PGPHashContextRef shaContext = kInvalidPGPHashContextRef;
PGPPrivateKeyContextRef privContext = kInvalidPGPPrivateKeyContextRef;
PGPSize sigSize=0;
PGPLicenseAuthorization *la = NULL;
PGPUInt32 issuanceDate;
*buffer = NULL;
err=PGPNewHashContext(context, kPGPHashAlgorithm_SHA, &shaContext);
if(IsPGPError(err))
return err;
issuanceDate = daysElapsed( PGPGetTime(), TRUE ); // since PGP epoch
err = calculateLNHash( context, licenseNumber,
customerName, companyName, (PGPUInt16)issuanceDate, shaContext );
if(IsntPGPError(err)) {
PGPKeyIterRef keyIter = kInvalidPGPKeyIterRef;
if(IsntPGPError(err))
err = PGPImport (context, &keyDB,
PGPOInputBuffer (context, DSSPrivKey, sizeof(DSSPrivKey)),
PGPOLastOption (context));
if(IsntPGPError(err))
err=PGPNewKeyIterFromKeyDB (keyDB, &keyIter);
if(IsntPGPError(err))
err = PGPKeyIterNextKeyDBObj (keyIter, kPGPKeyDBObjType_Key, &key);
if( PGPKeyIterRefIsValid(keyIter) )
PGPFreeKeyIter(keyIter);
}
if(IsntPGPError(err))
err = PGPNewPrivateKeyContext( key, kPGPPublicKeyMessageFormat_PGP,
&privContext, PGPOLastOption(context) );
if(IsntPGPError(err))
err = PGPGetPrivateKeyOperationSizes( privContext, NULL, NULL, &sigSize );
if( sigSize ) {
*buffer = (PGPLicenseAuthorizationRef)PGPNewData(PGPPeekContextMemoryMgr(context),
sigSize + sizeof(PGPLicenseAuthorization) - 1, 0 );
la = (PGPLicenseAuthorization*)(*buffer);
}
if( *buffer ) {
PGPSize size=0;
err = PGPPrivateKeySign( privContext, shaContext, la->signature, &size );
la->signatureSize = size;
la->type = 0; /* first DSA key */
la->issuanceDate = (PGPUInt16)issuanceDate;
shaContext = NULL; /* hash context is freed in PGPPrivateKeySign */
}
if( PGPHashContextRefIsValid(shaContext) )
PGPFreeHashContext( shaContext );
if( PGPPrivateKeyContextRefIsValid(privContext) )
PGPFreePrivateKeyContext( privContext );
if( PGPKeyDBRefIsValid(keyDB) )
PGPFreeKeyDB (keyDB);
return err;
#endif // PGP_LICENSE_SERVER
}
static PGPBoolean isEmptyString( const PGPByte *s ) {
const PGPByte *whiteChars = " \t\n\r";
PGPUInt32 i;
if( s==NULL )
return TRUE;
i = strlen(s);
while( i-- ) {
if( strchr(whiteChars, *(s++))==NULL )
return FALSE;
}
return TRUE;
}
PGPError PGPLACreate(PGPContextRef context, const PGPByte *url,
const PGPLicenseNumberRef licenseNumber,
const PGPByte *customerName, const PGPByte *companyName, PGPLicenseAuthorizationRef *buffer)
{
if( isEmptyString(customerName) )
customerName = emptyCustomerName;
if( isEmptyString(companyName) )
companyName = emptyCompanyName;
if( isEmptyString( licenseNumber ) )
return kPGPError_LazyProgrammer;
#if PGP_LICENSE_NET
return (url == NULL || url[0]=='\0') ?
pgpLACreateLocal(context, licenseNumber, customerName, companyName, buffer) :
pgpLACreateNet(context, url, licenseNumber, customerName, companyName, buffer);
#else
return pgpLACreateLocal(context, licenseNumber, customerName, companyName, buffer);
#endif
}
/* exports LA into base64 format (serialization). This is analog to base32 for LN format */
PGPError PGPLAExportBase64( PGPContextRef context,
const PGPLicenseAuthorizationRef licenseAuthorization, PGPByte **b64 )
{
PGPSize b64_size;
PGPError err;
PGPLicenseAuthorization *la = (PGPLicenseAuthorization*)licenseAuthorization;
const PGPSize la_buf_size = laToStreamSize( la );
PGPByte *la_buf = PGPNewData( PGPPeekContextMemoryMgr(context), la_buf_size, 0 );
if( la_buf==NULL )
return kPGPError_OutOfMemory;
laToStream( la, la_buf );
err = tc_encode_base64( PGPPeekContextMemoryMgr(context), b64, &b64_size,
la_buf, la_buf_size );
PGPFreeData( la_buf );
return err;
}
/* imports LA from base64 format */
PGPError PGPLAImportBase64( PGPContextRef context,
const PGPByte *b64, PGPLicenseAuthorizationRef *licenseAuthorization )
{
PGPError err;
PGPLicenseAuthorization *la = NULL;
PGPByte *la_buf = NULL;
PGPSize la_buf_size;
if (!b64 || !licenseAuthorization)
return kPGPError_BadParams;
*licenseAuthorization = NULL;
err = tc_decode_base64( PGPPeekContextMemoryMgr(context), &la_buf, &la_buf_size, b64 );
if( IsPGPError(err) )
return kPGPError_LACorrupt;
if( la_buf_size <= sizeof(PGPLicenseAuthorization) || laFromStreamSize( la_buf ) != la_buf_size ) {
PGPFreeData( la_buf );
return kPGPError_LACorrupt;
}
la = (PGPLicenseAuthorization*)PGPNewData( PGPPeekContextMemoryMgr(context),
la_buf_size + sizeof(PGPLicenseAuthorization)-1 /* count packed header twice */, 0 );
if( la ) {
laFromStream( la_buf, la );
if( la->type != 0 ) {
PGPFreeData( la_buf );
PGPFreeData( la );
return kPGPError_LACorrupt;
}
}
if( la_buf != NULL )
PGPFreeData( la_buf );
*licenseAuthorization = la;
return err;
}
// Takes a blocked license auth. number and imports it into internal opaque structure
// Returns kPGPError_CorruptData for the error in the ascii armor and
// kPGPError_CorruptLicenseAuth for the error in LA, among others
PGPError PGPLAImportBlocked(PGPContextRef context,
const PGPByte *licenseAuthorizationBlocked,
PGPLicenseAuthorizationRef *buffer)
{
PGPError err;
PGPByte *pStart,*pEnd;
static const PGPByte mailWhiteSpace[] = "\t \r\n>:-";
err=kPGPError_NoErr;
pStart=strstr(licenseAuthorizationBlocked,beginLicense); // assume the header of armor is not broken
if(pStart==0)
return kPGPError_CorruptData;
pStart+=sizeof(beginLicense)-1;
if( *pStart=='\0' )
return kPGPError_CorruptData;
/* advance to the begining of base64 LA */
while( strchr( mailWhiteSpace, *pStart ) )
pStart++;
{
PGPByte b[256];
strncpy( b, endLicense, sizeof(endLicense)/2 );
b[sizeof(endLicense)/2] = '\0';
pEnd = strstr( pStart, b ); /* look for only half of an armor end for reliability */
if( pEnd ) {
PGPSize i, j=0, size = pEnd-pStart;
if( sizeof(b)-1 < size )
size = sizeof(b)-1;
for( i=0; i<size; i++ ) {
if( strchr( mailWhiteSpace, pStart[i] ) )
continue;
b[j++] = pStart[i];
}
b[j] ='\0';
err = PGPLAImportBase64( context, b, buffer );
}
else
err = kPGPError_CorruptData;
}
return err;
}
// Exports internal opaque structure to base64. To be used on the server.
// Client should use PGPLAExportBase64
PGPError PGPLAExportBlocked(PGPContextRef context,
PGPLicenseAuthorizationRef licenseAuthorization,
PGPByte **blocked )
{
PGPError err;
PGPUInt32 memamt;
PGPByte *b64 = NULL;
err=kPGPError_NoErr;
err = PGPLAExportBase64( context, licenseAuthorization, &b64 );
if( IsPGPError(err) )
return err;
memamt=strlen(beginLicense)+sizeof('\n')+
strlen( b64 )+sizeof('\n') +
strlen(endLicense)+1;
*blocked=(PGPByte *)PGPNewData(PGPPeekContextMemoryMgr(context),memamt,0);
if(*blocked==0)
{
err=kPGPError_OutOfMemory;
}
else
{
strcpy(*blocked,beginLicense);
strcat(*blocked,"\n");
strcat(*blocked,b64);
strcat(*blocked,"\n");
strcat(*blocked,endLicense);
}
PGPFreeData( b64 );
return err;
}
// Free internal opaque structure
void PGPLAFree(PGPLicenseAuthorizationRef licenseAuthorization)
{
pgpClearMemory(licenseAuthorization,laToStreamSize((PGPLicenseAuthorization*)licenseAuthorization));
PGPFreeData(licenseAuthorization);
}
/* Compares imported LN and AN and determines if valid. Error if not.
*/
PGPError PGPLAVerify(PGPContextRef context,
PGPLicenseNumberRef licenseNumber,
PGPLicenseAuthorizationRef licenseAuthorization,
const PGPByte *customerName,
const PGPByte *companyName)
{
PGPError err;
PGPKeyDBRef keyDB = kInvalidPGPKeyDBRef;
PGPKeyDBObjRef key = kInvalidPGPKeyDBObjRef;
PGPHashContextRef shaContext = kInvalidPGPHashContextRef;
PGPPublicKeyContextRef pubContext = kInvalidPGPPublicKeyContextRef;
PGPLicenseAuthorization *la = (PGPLicenseAuthorization*)licenseAuthorization;
PGPInt32 daysLeft;
if( isEmptyString(customerName) )
customerName = emptyCustomerName;
if( isEmptyString(companyName) )
companyName = emptyCompanyName;
err=PGPNewHashContext(context, kPGPHashAlgorithm_SHA, &shaContext);
if(IsPGPError(err))
return err;
err = calculateLNHash( context, licenseNumber,
customerName, companyName, la->issuanceDate, shaContext );
if(IsPGPError(err)) {
PGPFreeHashContext( shaContext );
return err;
}
if(IsntPGPError(err)) {
PGPKeyIterRef keyIter = kInvalidPGPKeyIterRef;
if(IsntPGPError(err))
err = PGPImport (context, &keyDB,
PGPOInputBuffer (context, DSSPubKey, sizeof(DSSPubKey)),
PGPOLastOption (context));
if(IsntPGPError(err))
err=PGPNewKeyIterFromKeyDB (keyDB, &keyIter);
if(IsntPGPError(err))
err = PGPKeyIterNextKeyDBObj (keyIter, kPGPKeyDBObjType_Key, &key);
if( PGPKeyIterRefIsValid(keyIter) )
PGPFreeKeyIter(keyIter);
}
if(IsntPGPError(err))
err = PGPNewPublicKeyContext( key, kPGPPublicKeyMessageFormat_PGP, &pubContext );
if(IsntPGPError(err)) {
err = PGPPublicKeyVerifySignature( pubContext, shaContext, la->signature, la->signatureSize );
shaContext = kInvalidPGPHashContextRef;
}
if(IsntPGPError(err))
err = PGPLADaysLeft( context, licenseNumber, licenseAuthorization, &daysLeft );
if(IsntPGPError(err))
{
if (daysLeft <= 0)
err = kPGPError_KeyExpired;
}
if( PGPHashContextRefIsValid(shaContext) )
PGPFreeHashContext( shaContext );
if( PGPPublicKeyContextRefIsValid(pubContext) )
PGPFreePublicKeyContext( pubContext );
if( PGPKeyDBRefIsValid(keyDB) )
PGPFreeKeyDB (keyDB);
return err;
}
/*
Sets daysLeft to huge positive number (0x7fffffff) to indicate unexpiring product.
Sets to huge negative number (-0x7fffffff) in case the error is returned.
Otherwise, sets to number of days left, possibly negative number.
*/
PGPError PGPLADaysLeft(PGPContextRef context, PGPLicenseNumberRef ln_ref,
PGPLicenseAuthorizationRef la_ref, PGPInt32 *daysLeft)
{
PGPError err = kPGPError_NoErr;
PGPUInt16 evalPeriod;
PGPUInt32 daysUsed;
PGPLicenseAuthorization *la = (PGPLicenseAuthorization*)la_ref;
err = PGPLNGetEvalPeriod( context, ln_ref, &evalPeriod );
if( IsPGPError(err) ) {
*daysLeft = -(0x7fffffff);
return err;
}
if( evalPeriod==0 ) {
*daysLeft = 0x7fffffff; // plus infinity
return err;
}
daysUsed = daysElapsed( PGPGetTime(), TRUE ); // since PGP epoch
if( daysUsed == (PGPUInt32)(-1) || daysUsed < la->issuanceDate ) {
*daysLeft = -(0x7fffffff); // error
return kPGPError_UnknownError;
}
daysUsed -= la->issuanceDate; // days product used
*daysLeft = evalPeriod - daysUsed;
return err;
}
/* Returns hash of customerName and companyName in the form of null-terminated string in base64 encoding.
* Application that needs to compare two pairs of (companyName,customerName) must compare these hashes.
* For the purpose of LA it is insufficient to compare customer/company name by other methods, such as strcmp,
* to determine that the strings are the same
*/
PGPError PGPLAGetNameHash( PGPContextRef context, const PGPByte *customerName, const PGPByte *companyName, PGPByte **hashb64 )
{
PGPError err = kPGPError_NoErr;
PGPHashContextRef shaContext = kInvalidPGPHashContextRef;
PGPByte binaryHash[80];
PGPSize binaryHashSize;
*hashb64 = NULL;
err=PGPNewHashContext(context, kPGPHashAlgorithm_SHA, &shaContext);
if(IsPGPError(err))
return err;
PGPGetHashSize( shaContext, &binaryHashSize );
err = calculateNameHash( context, customerName, companyName, shaContext );
/* base64 encoding of the hash must fit into static buffer */
pgpAssert( sizeof(binaryHash) > (binaryHashSize + 1)*4/3 );
if( IsntPGPError(err) )
err = PGPFinalizeHash( shaContext, binaryHash );
if( IsntPGPError(err) ) {
PGPSize hashb64_size;
err = tc_encode_base64( PGPPeekContextMemoryMgr(context),
hashb64, &hashb64_size, binaryHash, binaryHashSize );
}
if( PGPHashContextRefIsValid(shaContext) )
PGPFreeHashContext( shaContext );
return err;
}
/*__Editor_settings____
Local Variables:
tab-width: 4
End:
vi: ts=4 sw=4
vim: si
_____________________*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -