381 lines
9.9 KiB
C++
381 lines
9.9 KiB
C++
|
//-------------------------------------------------------------------------
|
||
|
//
|
||
|
// Microsoft Windows
|
||
|
//
|
||
|
// Copyright (C) Microsoft Corporation, 1995 - 1999
|
||
|
//
|
||
|
// File: tcrack.cpp
|
||
|
//
|
||
|
// Contents: API testing of CryptEncodeObject/CryptDecodeObject.
|
||
|
//
|
||
|
// History: 29-January-97 xiaohs created
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
#include "global.hxx"
|
||
|
|
||
|
//--------------------------------------------------------------------------
|
||
|
// See if the sequence "81 7f" is in the BLOB. If it is, we need to fix it
|
||
|
//--------------------------------------------------------------------------
|
||
|
BOOL BadCert(DWORD cbEncoded, BYTE *pbEncoded)
|
||
|
{
|
||
|
DWORD iIndex=0;
|
||
|
DWORD iLimit=cbEncoded-2;
|
||
|
BYTE rgByte[2];
|
||
|
|
||
|
|
||
|
assert(pbEncoded);
|
||
|
|
||
|
|
||
|
memset(rgByte, 0, 2);
|
||
|
|
||
|
//set the rgByte to be the patter of 0x81 0x7F, which is 10000001 and 01111111,
|
||
|
//whic his 129 and 127 in decimal
|
||
|
rgByte[0]=rgByte[0]|129;
|
||
|
rgByte[1]=rgByte[1]|127;
|
||
|
|
||
|
|
||
|
for(iIndex=0;iIndex<=iLimit;iIndex++)
|
||
|
{
|
||
|
if(memcmp(rgByte,&(pbEncoded[iIndex]),2)==0)
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------------------------------
|
||
|
// Copy the BLOBs
|
||
|
//--------------------------------------------------------------------------
|
||
|
void SetData(DWORD cbNewData, BYTE *pbNewData,
|
||
|
DWORD *pcbOldData, BYTE **ppbOldData)
|
||
|
{
|
||
|
assert(pcbOldData);
|
||
|
assert(ppbOldData);
|
||
|
|
||
|
*pcbOldData=cbNewData;
|
||
|
*ppbOldData=pbNewData;
|
||
|
}
|
||
|
|
||
|
|
||
|
///////////////////////////////////////////////////////////////////////////
|
||
|
//Certificate Manipulation Functions
|
||
|
//--------------------------------------------------------------------------
|
||
|
// This is the functions
|
||
|
//--------------------------------------------------------------------------
|
||
|
BOOL Fix7FCert(DWORD cbEncoded, BYTE *pbEncoded, DWORD *pcbEncoded,
|
||
|
BYTE **ppbEncoded)
|
||
|
{
|
||
|
|
||
|
//init
|
||
|
*pcbEncoded=0;
|
||
|
*ppbEncoded=NULL;
|
||
|
|
||
|
|
||
|
|
||
|
if(!BadCert(cbEncoded, pbEncoded))
|
||
|
return TRUE;
|
||
|
|
||
|
|
||
|
if(DecodeX509_CERT(cbEncoded, pbEncoded,pcbEncoded,
|
||
|
ppbEncoded))
|
||
|
return TRUE;
|
||
|
else
|
||
|
{
|
||
|
//release the memory
|
||
|
SAFE_FREE(*ppbEncoded)
|
||
|
*ppbEncoded=NULL;
|
||
|
*pcbEncoded=0;
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------------------------------
|
||
|
// A general routine to encode a struct based on lpszStructType
|
||
|
//--------------------------------------------------------------------------
|
||
|
BOOL EncodeStruct(LPCSTR lpszStructType, void *pStructInfo,DWORD *pcbEncoded,
|
||
|
BYTE **ppbEncoded)
|
||
|
{
|
||
|
BOOL fSucceeded=FALSE;
|
||
|
DWORD cbEncoded=NULL;
|
||
|
|
||
|
//init
|
||
|
*pcbEncoded=0;
|
||
|
*ppbEncoded=NULL;
|
||
|
|
||
|
assert(lpszStructType);
|
||
|
assert(pStructInfo);
|
||
|
|
||
|
|
||
|
//length only calculation
|
||
|
TESTC(CryptEncodeObject(CRYPT_ENCODE_TYPE,lpszStructType, pStructInfo,NULL,
|
||
|
&cbEncoded),TRUE)
|
||
|
|
||
|
//the struct has to be more than 0 byte
|
||
|
assert(cbEncoded);
|
||
|
|
||
|
//allocate the correct amount of memory
|
||
|
*ppbEncoded=(BYTE *)SAFE_ALLOC(cbEncoded);
|
||
|
CHECK_POINTER(*ppbEncoded);
|
||
|
|
||
|
//Encode the strcut with *pcbEncoded == the correct length
|
||
|
*pcbEncoded=cbEncoded;
|
||
|
|
||
|
//Encode the struct
|
||
|
TESTC(CryptEncodeObject(CRYPT_ENCODE_TYPE,lpszStructType,pStructInfo,*ppbEncoded,
|
||
|
pcbEncoded),TRUE)
|
||
|
|
||
|
fSucceeded=TRUE;
|
||
|
|
||
|
TCLEANUP:
|
||
|
|
||
|
return fSucceeded;
|
||
|
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------------------------------
|
||
|
// A general routine to decode a BLOB based on lpszStructType
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
BOOL DecodeBLOB(LPCSTR lpszStructType,DWORD cbEncoded, BYTE *pbEncoded,
|
||
|
DWORD *pcbStructInfo, void **ppvStructInfo)
|
||
|
{
|
||
|
BOOL fSucceeded=FALSE;
|
||
|
DWORD cbStructInfo=0;
|
||
|
|
||
|
//init
|
||
|
*pcbStructInfo=0;
|
||
|
*ppvStructInfo=NULL;
|
||
|
|
||
|
assert(lpszStructType);
|
||
|
assert(pbEncoded);
|
||
|
assert(cbEncoded);
|
||
|
|
||
|
//Decode. Length Only Calculation
|
||
|
TESTC(CryptDecodeObject(CRYPT_ENCODE_TYPE,lpszStructType,pbEncoded,cbEncoded,
|
||
|
CRYPT_DECODE_FLAG,NULL,&cbStructInfo),TRUE)
|
||
|
|
||
|
//the struct has to be more than 0 byte
|
||
|
assert(cbStructInfo);
|
||
|
|
||
|
*ppvStructInfo=(BYTE *)SAFE_ALLOC(cbStructInfo);
|
||
|
CHECK_POINTER(*ppvStructInfo);
|
||
|
|
||
|
//Decode the BLOB with *pcbStructInfo==correct length
|
||
|
*pcbStructInfo=cbStructInfo;
|
||
|
|
||
|
TESTC(CryptDecodeObject(CRYPT_ENCODE_TYPE,lpszStructType,pbEncoded,cbEncoded,
|
||
|
CRYPT_DECODE_FLAG,*ppvStructInfo,pcbStructInfo),TRUE)
|
||
|
|
||
|
|
||
|
fSucceeded=TRUE;
|
||
|
|
||
|
TCLEANUP:
|
||
|
|
||
|
return fSucceeded;
|
||
|
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------------------------------
|
||
|
// Decode X509_CERT BLOBs
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
BOOL DecodeX509_CERT(DWORD cbEncoded, BYTE *pbEncoded,DWORD *pcbEncoded,
|
||
|
BYTE **ppbEncoded)
|
||
|
{
|
||
|
BOOL fSucceeded=FALSE;
|
||
|
DWORD cbStructInfo=0;
|
||
|
void *pStructInfo=NULL;
|
||
|
LPCSTR lpszStructType=NULL;
|
||
|
DWORD cbToBeSigned=0;
|
||
|
BYTE *pbToBeSigned=NULL;
|
||
|
DWORD cbOldSigned=0;
|
||
|
BYTE *pbOldSigned=NULL;
|
||
|
|
||
|
//init
|
||
|
lpszStructType=X509_CERT;
|
||
|
|
||
|
|
||
|
//Decode the encoded BLOB
|
||
|
TESTC(DecodeBLOB(lpszStructType,cbEncoded, pbEncoded,&cbStructInfo,
|
||
|
&pStructInfo),TRUE)
|
||
|
|
||
|
//Further Decode the X509_CERT_TO_BE_SIGNED
|
||
|
//Notice we should use the original cbData and pbData passed in for Decode
|
||
|
//but use ToBeSigned in CERT_SIGNED_CONTENT_INFO for encode purpose
|
||
|
|
||
|
TESTC(DecodeX509_CERT_TO_BE_SIGNED(cbEncoded,
|
||
|
pbEncoded,&cbToBeSigned,&pbToBeSigned),TRUE);
|
||
|
|
||
|
//copy the new encoded BLOB
|
||
|
SetData((((PCERT_SIGNED_CONTENT_INFO)pStructInfo)->ToBeSigned).cbData,
|
||
|
(((PCERT_SIGNED_CONTENT_INFO)pStructInfo)->ToBeSigned).pbData,
|
||
|
&cbOldSigned, &pbOldSigned);
|
||
|
|
||
|
SetData(cbToBeSigned, pbToBeSigned,
|
||
|
&((((PCERT_SIGNED_CONTENT_INFO)pStructInfo)->ToBeSigned).cbData),
|
||
|
&((((PCERT_SIGNED_CONTENT_INFO)pStructInfo)->ToBeSigned).pbData));
|
||
|
|
||
|
|
||
|
//if requested, encode the BLOB back to what it was. Make sure no data is lost
|
||
|
//by checking the size of the encoded blob and do a memcmp.
|
||
|
TESTC(EncodeStruct(lpszStructType, pStructInfo,pcbEncoded, ppbEncoded),TRUE);
|
||
|
|
||
|
fSucceeded=TRUE;
|
||
|
|
||
|
TCLEANUP:
|
||
|
|
||
|
SetData(cbOldSigned, pbOldSigned,
|
||
|
&((((PCERT_SIGNED_CONTENT_INFO)pStructInfo)->ToBeSigned).cbData),
|
||
|
&((((PCERT_SIGNED_CONTENT_INFO)pStructInfo)->ToBeSigned).pbData));
|
||
|
|
||
|
|
||
|
SAFE_FREE(pStructInfo)
|
||
|
|
||
|
SAFE_FREE(pbToBeSigned)
|
||
|
|
||
|
return fSucceeded;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//--------------------------------------------------------------------------
|
||
|
// Decode X509_CERT_TO_BE_SIGNED BLOBs
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
BOOL DecodeX509_CERT_TO_BE_SIGNED(DWORD cbEncoded, BYTE *pbEncoded, DWORD *pcbEncoded,
|
||
|
BYTE **ppbEncoded)
|
||
|
{
|
||
|
|
||
|
BOOL fSucceeded=FALSE;
|
||
|
DWORD cbStructInfo=0;
|
||
|
void *pStructInfo=NULL;
|
||
|
LPCSTR lpszStructType=NULL;
|
||
|
|
||
|
|
||
|
DWORD cbOldIssuer=0;
|
||
|
BYTE *pbOldIssuer=NULL;
|
||
|
DWORD cbIssuer=0;
|
||
|
BYTE *pbIssuer=NULL;
|
||
|
|
||
|
|
||
|
DWORD cbOldSubject=0;
|
||
|
BYTE *pbOldSubject=NULL;
|
||
|
DWORD cbSubject=0;
|
||
|
BYTE *pbSubject=NULL;
|
||
|
|
||
|
|
||
|
//init
|
||
|
lpszStructType=X509_CERT_TO_BE_SIGNED;
|
||
|
|
||
|
|
||
|
//Decode the encoded BLOB
|
||
|
TESTC(DecodeBLOB(lpszStructType,cbEncoded, pbEncoded,&cbStructInfo,
|
||
|
&pStructInfo),TRUE)
|
||
|
|
||
|
|
||
|
//Decode Issuer in CERT_INFO struct
|
||
|
TESTC(DecodeX509_NAME((((PCERT_INFO)pStructInfo)->Issuer).cbData,
|
||
|
(((PCERT_INFO)pStructInfo)->Issuer).pbData,&cbIssuer,&pbIssuer),TRUE)
|
||
|
|
||
|
SetData((((PCERT_INFO)pStructInfo)->Issuer).cbData,
|
||
|
(((PCERT_INFO)pStructInfo)->Issuer).pbData,&cbOldIssuer,&pbOldIssuer);
|
||
|
|
||
|
SetData(cbIssuer, pbIssuer,
|
||
|
&((((PCERT_INFO)pStructInfo)->Issuer).cbData),
|
||
|
&((((PCERT_INFO)pStructInfo)->Issuer).pbData));
|
||
|
|
||
|
|
||
|
|
||
|
//Decode Subject in CERT_INFO struct
|
||
|
TESTC(DecodeX509_NAME((((PCERT_INFO)pStructInfo)->Subject).cbData,
|
||
|
(((PCERT_INFO)pStructInfo)->Subject).pbData,&cbSubject,&pbSubject),TRUE)
|
||
|
|
||
|
SetData((((PCERT_INFO)pStructInfo)->Subject).cbData,
|
||
|
(((PCERT_INFO)pStructInfo)->Subject).pbData,
|
||
|
&cbOldSubject, &pbOldSubject);
|
||
|
|
||
|
SetData(cbSubject, pbSubject,
|
||
|
&((((PCERT_INFO)pStructInfo)->Subject).cbData),
|
||
|
&((((PCERT_INFO)pStructInfo)->Subject).pbData));
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//if requested, encode the BLOB back to what it was. Make sure no data is lost
|
||
|
//by checking the size of the encoded blob and do a memcmp.
|
||
|
TESTC(EncodeStruct(lpszStructType, pStructInfo,pcbEncoded,
|
||
|
ppbEncoded),TRUE);
|
||
|
|
||
|
|
||
|
|
||
|
fSucceeded=TRUE;
|
||
|
|
||
|
TCLEANUP:
|
||
|
|
||
|
//copy back the old values
|
||
|
SetData(cbOldSubject, pbOldSubject,
|
||
|
&((((PCERT_INFO)pStructInfo)->Subject).cbData),
|
||
|
&((((PCERT_INFO)pStructInfo)->Subject).pbData));
|
||
|
|
||
|
|
||
|
SetData(cbOldIssuer, pbOldIssuer,
|
||
|
&((((PCERT_INFO)pStructInfo)->Issuer).cbData),
|
||
|
&((((PCERT_INFO)pStructInfo)->Issuer).pbData));
|
||
|
|
||
|
|
||
|
|
||
|
SAFE_FREE(pStructInfo)
|
||
|
|
||
|
SAFE_FREE(pbSubject)
|
||
|
|
||
|
SAFE_FREE(pbIssuer)
|
||
|
|
||
|
return fSucceeded;
|
||
|
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------------------------------
|
||
|
// Decode X509_NAME BLOBs
|
||
|
//
|
||
|
//--------------------------------------------------------------------------
|
||
|
BOOL DecodeX509_NAME(DWORD cbEncoded, BYTE *pbEncoded, DWORD *pcbEncoded,
|
||
|
BYTE **ppbEncoded)
|
||
|
{
|
||
|
|
||
|
BOOL fSucceeded=FALSE;
|
||
|
DWORD cbStructInfo=0;
|
||
|
void *pStructInfo=NULL;
|
||
|
LPCSTR lpszStructType=NULL;
|
||
|
|
||
|
|
||
|
//init
|
||
|
lpszStructType=X509_NAME;
|
||
|
|
||
|
|
||
|
//Decode the encoded BLOB
|
||
|
TESTC(DecodeBLOB(lpszStructType,cbEncoded, pbEncoded,&cbStructInfo,
|
||
|
&pStructInfo),TRUE)
|
||
|
|
||
|
|
||
|
//if requested, encode the BLOB back to what it was. Make sure no data is lost
|
||
|
//by checking the size of the encoded blob and do a memcmp.
|
||
|
TESTC(EncodeStruct(lpszStructType, pStructInfo,pcbEncoded, ppbEncoded),TRUE);
|
||
|
|
||
|
|
||
|
fSucceeded=TRUE;
|
||
|
|
||
|
TCLEANUP:
|
||
|
|
||
|
SAFE_FREE(pStructInfo)
|
||
|
|
||
|
return fSucceeded;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|