windows-nt/Source/XPSP1/NT/ds/security/cryptoapi/pkitrust/mssip32/jvimage.cpp
2020-09-26 16:20:57 +08:00

977 lines
29 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: jvimage.cpp
//
// Contents: Microsoft SIP Provider (JAVA utilities)
//
// History: 15-Feb-1997 pberkman created
//
//--------------------------------------------------------------------------
#include "global.hxx"
BOOL SeekAndReadFile(HANDLE hFile, DWORD lFileOffset,BYTE *pb,
DWORD cb);
BOOL SeekAndWriteFile(HANDLE hFile, DWORD lFileOffset, BYTE *pb,
DWORD cb);
typedef void *HSHPDIGESTDATA;
typedef BOOL (WINAPI *PFN_SHP_DIGEST_DATA)(HSHPDIGESTDATA hDigestData,
BYTE *pbData,
DWORD cbData);
typedef void *HSHPSIGNFILE;
typedef struct _JAVA_OPEN_ARG
{
HANDLE hFile;
} JAVA_OPEN_ARG, *PJAVA_OPEN_ARG;
typedef struct _JAVA_FUNC_PARA
{
HANDLE hFile;
BYTE *pbSignedData;
} JAVA_FUNC_PARA, *PJAVA_FUNC_PARA;
typedef struct _JAVA_DIGEST_PARA
{
BOOL fDisableDigest;
PFN_SHP_DIGEST_DATA pfnDigestData;
HSHPDIGESTDATA hDigestData;
} JAVA_DIGEST_PARA, *PJAVA_DIGEST_PARA;
typedef struct _JAVA_SIGN_PARA
{
WORD wConstPoolCount;
WORD wSignConstPoolIndex;
LONG lSignConstPoolOffset;
WORD wAttrCount;
LONG lAttrCountOffset;
WORD wSignAttrIndex;
DWORD dwSignAttrLength;
LONG lSignAttrOffset;
LONG lEndOfFileOffset;
} JAVA_SIGN_PARA, *PJAVA_SIGN_PARA;
typedef struct _JAVA_READ_PARA
{
BOOL fResult;
DWORD dwLastError;
LONG lFileOffset;
DWORD cbCacheRead;
DWORD cbCacheRemain;
} JAVA_READ_PARA, *PJAVA_READ_PARA;
#define JAVA_READ_CACHE_LEN 512
typedef struct _JAVA_PARA
{
JAVA_FUNC_PARA Func;
JAVA_DIGEST_PARA Digest;
JAVA_SIGN_PARA Sign;
JAVA_READ_PARA Read;
BYTE rgbCache[JAVA_READ_CACHE_LEN];
} JAVA_PARA, *PJAVA_PARA;
#define JAVA_MAGIC 0xCAFEBABE
#define JAVA_MINOR_VERSION 3
#define JAVA_MAJOR_VERSION 45
// Constant Pool tags
//
// Note: CONSTANT_Long and CONSTANT_Double use two constant pool indexes.
enum
{
CONSTANT_Utf8 = 1,
CONSTANT_Unicode = 2,
CONSTANT_Integer = 3,
CONSTANT_Float = 4,
CONSTANT_Long = 5,
CONSTANT_Double = 6,
CONSTANT_Class = 7,
CONSTANT_String = 8,
CONSTANT_Fieldref = 9,
CONSTANT_Methodref = 10,
CONSTANT_InterfaceMethodref = 11,
CONSTANT_NameAndType = 12
};
// Constant Pool Info lengths (excludes the tag)
DWORD rgConstPoolLength[] =
{
0, // tag of zero not used
0, // CONSTANT_Utf8 (special case)
0, // CONSTANT_Unicode (special case)
4, // CONSTANT_Integer_info
4, // CONSTANT_Float_info
8, // CONSTANT_Long_info
8, // CONSTANT_Double_info
2, // CONSTANT_Class_info
2, // CONSTANT_String_info
4, // CONSTANT_Fieldref_info
4, // CONSTANT_Methodref_info
4, // CONSTANT_InterfaceMethodref_info
4 // CONSTANT_NameAndType_info
};
static inline void *ShpAlloc(DWORD cbytes)
{
void *pvRet;
pvRet = (void *)new BYTE[cbytes];
if (!(pvRet))
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
}
return(pvRet);
}
static inline void ShpFree(void *pv)
{
if (pv)
{
delete pv;
}
}
// The following functions convert to/from Java bytes which are big endian
static inline void ToJavaU2(WORD w, BYTE rgb[])
{
rgb[0] = HIBYTE(w);
rgb[1] = LOBYTE(w);
}
static inline WORD FromJavaU2(BYTE rgb[])
{
return ((WORD)rgb[0]<<8) | ((WORD)rgb[1]<<0);
}
static inline void ToJavaU4(DWORD dw, BYTE rgb[])
{
rgb[0] = HIBYTE(HIWORD(dw));
rgb[1] = LOBYTE(HIWORD(dw));
rgb[2] = HIBYTE(LOWORD(dw));
rgb[3] = LOBYTE(LOWORD(dw));
}
static inline DWORD FromJavaU4(BYTE rgb[])
{
return ((DWORD)rgb[0]<<24) |
((DWORD)rgb[1]<<16) |
((DWORD)rgb[2]<<8) |
((DWORD)rgb[3]<<0);
}
#define CONST_POOL_COUNT_OFFSET 8
#define UTF8_HDR_LENGTH (1+2)
#define ATTR_HDR_LENGTH (2+4)
#define SIGN_ATTR_NAME_LENGTH 19
#define SIGN_CONST_POOL_LENGTH (UTF8_HDR_LENGTH + SIGN_ATTR_NAME_LENGTH)
static const char rgchSignAttrName[SIGN_ATTR_NAME_LENGTH + 1] =
"_digital_signature_";
//+-------------------------------------------------------------------------
// Shift the bytes in the file.
//
// If lbShift is positive, the bytes are shifted toward the end of the file.
// If lbShift is negative, the bytes are shifted toward the start of the file.
//--------------------------------------------------------------------------
static
BOOL
JavaShiftFileBytes(
IN HANDLE hFile,
IN PBYTE pbCache,
IN LONG cbCache,
IN LONG lStartOffset,
IN LONG lEndOffset,
IN LONG lbShift
)
{
LONG cbTotalMove, cbMove;
cbTotalMove = lEndOffset - lStartOffset;
while (cbTotalMove) {
cbMove = min(cbTotalMove, cbCache);
if (lbShift > 0) {
if (!SeekAndReadFile(hFile, lEndOffset - cbMove,
pbCache, cbMove))
return FALSE;
if (!SeekAndWriteFile(hFile, (lEndOffset - cbMove) + lbShift,
pbCache, cbMove))
return FALSE;
lEndOffset -= cbMove;
} else if (lbShift < 0) {
if (!SeekAndReadFile(hFile, lStartOffset, pbCache, cbMove))
return FALSE;
if (!SeekAndWriteFile(hFile, lStartOffset + lbShift,
pbCache, cbMove))
return FALSE;
lStartOffset += cbMove;
}
cbTotalMove -= cbMove;
}
return TRUE;
}
//+-------------------------------------------------------------------------
// Low level functions for reading the Java Class File.
//
// If not disabled, the read bytes are also hashed.
//
// For an error, remaining unread values are zero'ed and
// pPara->Read.fResult = FALSE.
//--------------------------------------------------------------------------
static void ReadJavaBytes(
IN PJAVA_PARA pPara,
OUT OPTIONAL BYTE *pb, // if NULL, bytes are hashed and then skipped
IN DWORD cb
)
{
DWORD cbCacheRemain = pPara->Read.cbCacheRemain;
DWORD lFileOffset = pPara->Read.lFileOffset;
BOOL fDisableDigest = pPara->Digest.pfnDigestData == NULL ||
pPara->Digest.fDisableDigest;
if (!pPara->Read.fResult)
goto ErrorReturn;
while (cb > 0) {
DWORD cbCopy;
BYTE *pbCache;
if (cbCacheRemain == 0) {
if (!ReadFile(pPara->Func.hFile, pPara->rgbCache,
sizeof(pPara->rgbCache), &cbCacheRemain, NULL))
goto ErrorReturn;
if (cbCacheRemain == 0) goto ErrorReturn;
pPara->Read.cbCacheRead = cbCacheRemain;
}
cbCopy = min(cb, cbCacheRemain);
pbCache = &pPara->rgbCache[pPara->Read.cbCacheRead - cbCacheRemain];
if (!fDisableDigest) {
if (!pPara->Digest.pfnDigestData(
pPara->Digest.hDigestData,
pbCache,
cbCopy)) goto ErrorReturn;
}
if (pb) {
memcpy(pb, pbCache, cbCopy);
pb += cbCopy;
}
cb -= cbCopy;
cbCacheRemain -= cbCopy;
lFileOffset += cbCopy;
}
goto CommonReturn;
ErrorReturn:
if (pPara->Read.fResult) {
// First error
pPara->Read.fResult = FALSE;
pPara->Read.dwLastError = GetLastError();
}
if (pb && cb)
memset(pb, 0, cb);
CommonReturn:
pPara->Read.cbCacheRemain = cbCacheRemain;
pPara->Read.lFileOffset = lFileOffset;
}
static void SkipJavaBytes(IN PJAVA_PARA pPara, IN DWORD cb)
{
ReadJavaBytes(pPara, NULL, cb);
}
static BYTE ReadJavaU1(IN PJAVA_PARA pPara)
{
BYTE b;
ReadJavaBytes(pPara, &b, 1);
return b;
}
static WORD ReadJavaU2(IN PJAVA_PARA pPara)
{
BYTE rgb[2];
ReadJavaBytes(pPara, rgb, 2);
return FromJavaU2(rgb);
}
static DWORD ReadJavaU4(IN PJAVA_PARA pPara)
{
BYTE rgb[4];
ReadJavaBytes(pPara, rgb, 4);
return FromJavaU4(rgb);
}
//+-------------------------------------------------------------------------
// .
//--------------------------------------------------------------------------
static
BOOL
GetSignedDataFromJavaClassFile(
IN HSHPSIGNFILE hSignFile,
OUT BYTE **ppbSignedData,
OUT DWORD *pcbSignedData
)
{
BOOL fResult;
PJAVA_PARA pPara = (PJAVA_PARA) hSignFile;
BYTE *pbSignedData = NULL;
DWORD cbSignedData;
cbSignedData = pPara->Sign.dwSignAttrLength;
if (cbSignedData == 0) {
SetLastError((DWORD)TRUST_E_NOSIGNATURE);
goto ErrorReturn;
}
pbSignedData = pPara->Func.pbSignedData;
if (pbSignedData == NULL) {
if (NULL == (pbSignedData = (BYTE *) ShpAlloc(cbSignedData)))
goto ErrorReturn;
if (!SeekAndReadFile(
pPara->Func.hFile,
pPara->Sign.lSignAttrOffset + ATTR_HDR_LENGTH,
pbSignedData,
cbSignedData))
goto ErrorReturn;
pPara->Func.pbSignedData = pbSignedData;
}
fResult = TRUE;
goto CommonReturn;
ErrorReturn:
if (pbSignedData) {
ShpFree(pbSignedData);
pbSignedData = NULL;
}
cbSignedData = 0;
fResult = FALSE;
CommonReturn:
*ppbSignedData = pbSignedData;
*pcbSignedData = cbSignedData;
return fResult;
}
//+-------------------------------------------------------------------------
// .
//--------------------------------------------------------------------------
static
BOOL
SetSignedDataIntoJavaClassFile(
IN HSHPSIGNFILE hSignFile,
IN const BYTE *pbSignedData,
IN DWORD cbSignedData
)
{
PJAVA_PARA pPara = (PJAVA_PARA) hSignFile;
HANDLE hFile = pPara->Func.hFile;
if (pbSignedData == NULL || cbSignedData == 0)
// Length only
return TRUE;
if (pPara->Sign.wSignConstPoolIndex == pPara->Sign.wConstPoolCount) {
BYTE rgb[SIGN_CONST_POOL_LENGTH];
// Add a new constant pool entry for the name of the
// signed data attribute.
// First, make room in the file by shifting all the bytes that follow.
if (!JavaShiftFileBytes(
pPara->Func.hFile,
pPara->rgbCache,
sizeof(pPara->rgbCache),
pPara->Sign.lSignConstPoolOffset,
pPara->Sign.lEndOfFileOffset,
SIGN_CONST_POOL_LENGTH))
return FALSE;
// Update offsets that have been shifted
pPara->Sign.lAttrCountOffset += SIGN_CONST_POOL_LENGTH;
pPara->Sign.lSignAttrOffset += SIGN_CONST_POOL_LENGTH;
pPara->Sign.lEndOfFileOffset += SIGN_CONST_POOL_LENGTH;
// Increment u2 constant_pool_count and update in file
pPara->Sign.wConstPoolCount++;
ToJavaU2(pPara->Sign.wConstPoolCount, rgb);
if (!SeekAndWriteFile(hFile, CONST_POOL_COUNT_OFFSET, rgb, 2))
return FALSE;
// Add constant pool entry for the sign attr name and update in file
rgb[0] = CONSTANT_Utf8;
ToJavaU2(SIGN_ATTR_NAME_LENGTH, &rgb[1]);
memcpy(&rgb[1+2], rgchSignAttrName, SIGN_ATTR_NAME_LENGTH);
if (!SeekAndWriteFile(hFile, pPara->Sign.lSignConstPoolOffset, rgb,
SIGN_CONST_POOL_LENGTH))
return FALSE;
}
if (pPara->Sign.dwSignAttrLength == 0) {
// Add a new attribute for the signed data. The attribute will
// be added at the end of the file.
assert(pPara->Sign.lSignAttrOffset == pPara->Sign.lEndOfFileOffset);
pPara->Sign.lEndOfFileOffset += ATTR_HDR_LENGTH + cbSignedData;
// Increment u2 attribute_count and update in file
BYTE rgb[2];
pPara->Sign.wAttrCount++;
ToJavaU2(pPara->Sign.wAttrCount, rgb);
if (!SeekAndWriteFile(hFile, pPara->Sign.lAttrCountOffset, rgb, 2))
return FALSE;
} else {
// The file already has a signed data attribute.
// If its length is different from the new signed data
// then, the bytes that follow the attribute will
// need to be shifted by the difference in length of the old and new
// signed data
LONG lbShift = cbSignedData - pPara->Sign.dwSignAttrLength;
if (lbShift != 0) {
if (!JavaShiftFileBytes(
pPara->Func.hFile,
pPara->rgbCache,
sizeof(pPara->rgbCache),
pPara->Sign.lSignAttrOffset +
(ATTR_HDR_LENGTH + pPara->Sign.dwSignAttrLength),
pPara->Sign.lEndOfFileOffset,
lbShift))
return FALSE;
pPara->Sign.lEndOfFileOffset += lbShift;
}
}
pPara->Sign.dwSignAttrLength = cbSignedData;
{
// Update the file with the signed data attribute
BYTE rgb[ATTR_HDR_LENGTH];
DWORD cbWritten;
ToJavaU2(pPara->Sign.wSignConstPoolIndex, rgb); // u2 attribute_name
ToJavaU4(cbSignedData, &rgb[2]); // u4 attribute_length
if (!SeekAndWriteFile(hFile, pPara->Sign.lSignAttrOffset, rgb,
ATTR_HDR_LENGTH))
return FALSE;
if (!WriteFile(hFile, pbSignedData, cbSignedData, &cbWritten, NULL) ||
cbWritten != cbSignedData)
return FALSE;
}
// Set end of file
if (0xFFFFFFFF == SetFilePointer(
hFile,
pPara->Sign.lEndOfFileOffset,
NULL, // lpDistanceToMoveHigh
FILE_BEGIN))
return FALSE;
return SetEndOfFile(hFile);
}
//+-------------------------------------------------------------------------
// Reads and optionally digests the Java Class file. Locates the signed data.
//--------------------------------------------------------------------------
static
BOOL
ProcessJavaClassFile(
PJAVA_PARA pPara,
BOOL fInit
)
{
char rgchTmpSignAttrName[SIGN_ATTR_NAME_LENGTH];
WORD wLength;
DWORD dwLength;
WORD wCount;
WORD wConstPoolCount;
WORD wConstPoolIndex;
WORD wSignConstPoolIndex;
WORD wAttrCount;
WORD wAttrIndex;
WORD wAttrName;
WORD wSignAttrIndex;
LONG lAddConstPoolOffset;
int i;
memset(&pPara->Read, 0, sizeof(pPara->Read));
pPara->Read.fResult = TRUE;
if (0xFFFFFFFF == SetFilePointer(
pPara->Func.hFile,
0, // lDistanceToMove
NULL, // lpDistanceToMoveHigh
FILE_BEGIN))
return FALSE;
if (fInit) {
memset(&pPara->Digest, 0, sizeof(pPara->Digest));
memset(&pPara->Sign, 0, sizeof(pPara->Sign));
}
// Default is to be digested. We'll disable where appropriate. Note,
// skipped bytes are still digested.
pPara->Digest.fDisableDigest = FALSE;
// Read / skip the fields at the beginning of the class file
if (ReadJavaU4(pPara) != JAVA_MAGIC)
{ // u4 magic
SetLastError(ERROR_BAD_FORMAT);
return FALSE;
}
SkipJavaBytes(pPara, 2 + 2); // u2 minor_version
// u2 major_version
pPara->Digest.fDisableDigest = TRUE;
wConstPoolCount = ReadJavaU2(pPara); // u2 constant_pool_count
pPara->Digest.fDisableDigest = FALSE;
// For fInit, wSignConstPoolIndex has already been zeroed
wSignConstPoolIndex = pPara->Sign.wSignConstPoolIndex;
// Iterate through the constant pools. Don't digest the constant pool
// containing the _digital_signature_ name (wSignConstPoolIndex).
// For fInit, find the last "_digital_signature_".
//
// Note: constant pool index 0 isn't stored in the file.
wConstPoolIndex = 1;
while (wConstPoolIndex < wConstPoolCount) {
BYTE bTag;
if (wConstPoolIndex == wSignConstPoolIndex)
pPara->Digest.fDisableDigest = TRUE;
bTag = ReadJavaU1(pPara);
switch (bTag) {
case CONSTANT_Utf8:
wLength = ReadJavaU2(pPara);
if (fInit && wLength == SIGN_ATTR_NAME_LENGTH) {
ReadJavaBytes(pPara, (BYTE *) rgchTmpSignAttrName,
SIGN_ATTR_NAME_LENGTH);
if (memcmp(rgchSignAttrName, rgchTmpSignAttrName,
SIGN_ATTR_NAME_LENGTH) == 0) {
wSignConstPoolIndex = wConstPoolIndex;
pPara->Sign.lSignConstPoolOffset =
pPara->Read.lFileOffset - SIGN_CONST_POOL_LENGTH;
}
} else
SkipJavaBytes(pPara, wLength);
break;
case CONSTANT_Unicode:
wLength = ReadJavaU2(pPara);
SkipJavaBytes(pPara, ((DWORD) wLength) * 2);
break;
case CONSTANT_Integer:
case CONSTANT_Float:
case CONSTANT_Long:
case CONSTANT_Double:
case CONSTANT_Class:
case CONSTANT_String:
case CONSTANT_Fieldref:
case CONSTANT_Methodref:
case CONSTANT_InterfaceMethodref:
case CONSTANT_NameAndType:
SkipJavaBytes(pPara, rgConstPoolLength[bTag]);
break;
default:
SetLastError(ERROR_BAD_FORMAT);
return FALSE;
}
pPara->Digest.fDisableDigest = FALSE;
if (bTag == CONSTANT_Long || bTag == CONSTANT_Double)
wConstPoolIndex += 2;
else
wConstPoolIndex++;
}
if (fInit) {
lAddConstPoolOffset = pPara->Read.lFileOffset;
if (wSignConstPoolIndex == 0) {
// Didn't find a constant pool for the digital_signature. Update
// with where it will need to be added
wSignConstPoolIndex = wConstPoolCount;
pPara->Sign.lSignConstPoolOffset = lAddConstPoolOffset;
}
}
// Globble up and hash the bytes until we reach the attributes which are
// at the end of the file.
SkipJavaBytes(pPara, 2 + 2 + 2); // u2 access_flags
// u2 this_class
// u2 super_class
wCount = ReadJavaU2(pPara); // u2 interfaces_count
// u2 interfaces[interfaces_count]
SkipJavaBytes(pPara, ((DWORD) wCount) * 2);
// Since fields and methods have identical class file storage, do this
// twice.
i = 2;
while (i--) {
wCount = ReadJavaU2(pPara); // u2 fields_count | methods_count
while (wCount--) {
SkipJavaBytes(pPara, 2 + 2 + 2); // u2 access_flags
// u2 name_index
// u2 signature_index
wAttrCount = ReadJavaU2(pPara); // u2 attributes_count
while (wAttrCount--) {
SkipJavaBytes(pPara, 2); // u2 attribute_name
dwLength = ReadJavaU4(pPara); // u4 attribute_length
SkipJavaBytes(pPara, dwLength); // u1 info[attribute_length]
}
}
}
// Finally, the attributes. This is where the signed data is
pPara->Sign.lAttrCountOffset = pPara->Read.lFileOffset;
pPara->Digest.fDisableDigest = TRUE;
wAttrCount = ReadJavaU2(pPara); // u2 attributes_count
pPara->Digest.fDisableDigest = FALSE;
if (fInit) {
pPara->Sign.wAttrCount = wAttrCount;
wSignAttrIndex = 0xFFFF;
} else
wSignAttrIndex = pPara->Sign.wSignAttrIndex;
for (wAttrIndex = 0; wAttrIndex < wAttrCount; wAttrIndex++) {
if (wAttrIndex == wSignAttrIndex)
pPara->Digest.fDisableDigest = TRUE;
wAttrName = ReadJavaU2(pPara);
dwLength = ReadJavaU4(pPara); // u4 attribute_length
SkipJavaBytes(pPara, dwLength); // u1 info[attribute_length]
if (fInit && wAttrName == wSignConstPoolIndex && dwLength > 0 &&
wSignConstPoolIndex < wConstPoolCount) {
wSignAttrIndex = wAttrIndex;
pPara->Sign.lSignAttrOffset =
pPara->Read.lFileOffset - (ATTR_HDR_LENGTH + dwLength);
pPara->Sign.dwSignAttrLength = dwLength;
}
pPara->Digest.fDisableDigest = FALSE;
}
if (fInit) {
if (wSignAttrIndex == 0xFFFF) {
// Didn't find an attribute for the digital_signature. Update
// with where it will need to be added
wSignAttrIndex = wAttrCount;
pPara->Sign.lSignAttrOffset = pPara->Read.lFileOffset;
// Also, force us to use a new const pool for the name of the
// attribute
wSignConstPoolIndex = wConstPoolCount;
pPara->Sign.lSignConstPoolOffset = lAddConstPoolOffset;
}
pPara->Sign.wSignConstPoolIndex = wSignConstPoolIndex;
pPara->Sign.wConstPoolCount = wConstPoolCount;
pPara->Sign.wSignAttrIndex = wSignAttrIndex;
pPara->Sign.lEndOfFileOffset = pPara->Read.lFileOffset;
}
// Now check if we got any hash or file errors while processing the file
return pPara->Read.fResult;
}
//+-------------------------------------------------------------------------
// Digest the appropriate bytes from a java file, for a digital signature.
//--------------------------------------------------------------------------
BOOL
JavaGetDigestStream(
IN HANDLE FileHandle,
IN DWORD DigestLevel,
IN DIGEST_FUNCTION DigestFunction,
IN DIGEST_HANDLE DigestHandle
)
{
BOOL fRet;
JAVA_PARA Para;
memset( &Para.Func, 0, sizeof(Para.Func));
assert( DigestLevel == 0);
Para.Func.hFile = FileHandle;
if (!ProcessJavaClassFile( &Para, TRUE))
goto ProcessJavaClassFileTrueError;
Para.Digest.pfnDigestData = DigestFunction;
Para.Digest.hDigestData = DigestHandle;
if (!ProcessJavaClassFile( &Para, FALSE))
goto ProcessJavaClassFileFalseError;
fRet = TRUE;
CommonReturn:
if (Para.Func.pbSignedData)
ShpFree( Para.Func.pbSignedData);
return fRet;
ErrorReturn:
fRet = FALSE;
goto CommonReturn;
TRACE_ERROR_EX(DBG_SS,ProcessJavaClassFileTrueError)
TRACE_ERROR_EX(DBG_SS,ProcessJavaClassFileFalseError)
}
//+-------------------------------------------------------------------------
// Add a digital signature to a java file.
//--------------------------------------------------------------------------
BOOL
JavaAddCertificate(
IN HANDLE FileHandle,
IN LPWIN_CERTIFICATE Certificate,
OUT PDWORD Index
)
{
BOOL fRet;
JAVA_PARA Para;
memset( &Para.Func, 0, sizeof(Para.Func));
Para.Func.hFile = FileHandle;
if (!ProcessJavaClassFile( &Para, TRUE))
goto ProcessJavaClassFileTrueError;
if (!SetSignedDataIntoJavaClassFile(
(HSHPSIGNFILE)&Para,
(PBYTE)&(Certificate->bCertificate),
Certificate->dwLength - OFFSETOF(WIN_CERTIFICATE,bCertificate)))
goto SetSignedDataIntoJavaClassFileError;
fRet = TRUE;
CommonReturn:
if (Para.Func.pbSignedData)
ShpFree( Para.Func.pbSignedData);
return fRet;
ErrorReturn:
fRet = FALSE;
goto CommonReturn;
TRACE_ERROR_EX(DBG_SS,ProcessJavaClassFileTrueError)
TRACE_ERROR_EX(DBG_SS,SetSignedDataIntoJavaClassFileError)
}
//+-------------------------------------------------------------------------
// Remove a digital signature from a java file.
//--------------------------------------------------------------------------
BOOL
JavaRemoveCertificate(
IN HANDLE FileHandle,
IN DWORD Index
)
{
return FALSE;
}
//+-------------------------------------------------------------------------
// Enum the digital signatures in a java file.
//--------------------------------------------------------------------------
BOOL
JavaEnumerateCertificates(
IN HANDLE FileHandle,
IN WORD TypeFilter,
OUT PDWORD CertificateCount,
IN OUT PDWORD Indices OPTIONAL,
IN OUT DWORD IndexCount OPTIONAL
)
{
return FALSE;
}
//+-------------------------------------------------------------------------
// Get a digital signature from a java file.
//--------------------------------------------------------------------------
static
BOOL
I_JavaGetCertificate(
IN HANDLE FileHandle,
IN DWORD CertificateIndex,
OUT LPWIN_CERTIFICATE Certificate,
IN OUT OPTIONAL PDWORD RequiredLength
)
{
BOOL fRet;
JAVA_PARA Para;
memset( &Para.Func, 0, sizeof(Para.Func));
BYTE *pbSignedData = NULL;
DWORD cbSignedData;
DWORD cbCert;
DWORD dwError;
if (CertificateIndex != 0)
goto IndexNonZeroError;
Para.Func.hFile = FileHandle;
if (!ProcessJavaClassFile( &Para, TRUE))
goto ProcessJavaClassFileTrueError;
if (!GetSignedDataFromJavaClassFile(
(HSHPSIGNFILE)&Para,
&pbSignedData,
&cbSignedData))
goto GetSignedDataFromJavaClassFileError;
cbCert = OFFSETOF(WIN_CERTIFICATE,bCertificate) + cbSignedData;
dwError = 0;
__try {
if (RequiredLength) {
// RequiredLength non-NULL only if getting cert data
if (*RequiredLength < cbCert) {
*RequiredLength = cbCert;
dwError = ERROR_INSUFFICIENT_BUFFER;
} else {
memcpy( Certificate->bCertificate, pbSignedData, cbSignedData);
}
}
if (dwError == 0) {
Certificate->dwLength = cbCert;
Certificate->wRevision = WIN_CERT_REVISION_1_0;
Certificate->wCertificateType = WIN_CERT_TYPE_PKCS_SIGNED_DATA;
}
} __except(EXCEPTION_EXECUTE_HANDLER) {
dwError = ERROR_INVALID_PARAMETER;
}
if (dwError) {
SetLastError( dwError);
fRet = FALSE;
} else {
fRet = TRUE;
}
CommonReturn:
ShpFree( Para.Func.pbSignedData);
return fRet;
ErrorReturn:
fRet = FALSE;
goto CommonReturn;
TRACE_ERROR_EX(DBG_SS,IndexNonZeroError)
TRACE_ERROR_EX(DBG_SS,ProcessJavaClassFileTrueError)
TRACE_ERROR_EX(DBG_SS,GetSignedDataFromJavaClassFileError)
}
//+-------------------------------------------------------------------------
// Get a digital signature from a java file.
//--------------------------------------------------------------------------
BOOL
JavaGetCertificateData(
IN HANDLE FileHandle,
IN DWORD CertificateIndex,
OUT LPWIN_CERTIFICATE Certificate,
IN OUT PDWORD RequiredLength
)
{
BOOL fRet;
if (RequiredLength == NULL)
goto RequiredLengthNullError;
fRet = I_JavaGetCertificate(
FileHandle,
CertificateIndex,
Certificate,
RequiredLength
);
CommonReturn:
return fRet;
ErrorReturn:
fRet = FALSE;
goto CommonReturn;
SET_ERROR(RequiredLengthNullError, ERROR_INVALID_PARAMETER)
}
//+-------------------------------------------------------------------------
// Get the header of a digital signature from a java file.
//--------------------------------------------------------------------------
BOOL
JavaGetCertificateHeader(
IN HANDLE FileHandle,
IN DWORD CertificateIndex,
IN OUT LPWIN_CERTIFICATE Certificateheader
)
{
return I_JavaGetCertificate(
FileHandle,
CertificateIndex,
Certificateheader,
NULL
);
}
//+-------------------------------------------------------------------------
// Seeks and writes bytes to file
//--------------------------------------------------------------------------
BOOL
SeekAndWriteFile(
IN HANDLE hFile,
IN DWORD lFileOffset,
IN BYTE *pb,
IN DWORD cb
)
{
DWORD cbWritten;
if (0xFFFFFFFF == SetFilePointer(
hFile,
lFileOffset,
NULL, // lpDistanceToMoveHigh
FILE_BEGIN))
return FALSE;
if (!WriteFile(hFile, pb, cb, &cbWritten, NULL) || cbWritten != cb)
return FALSE;
return TRUE;
}
//+-------------------------------------------------------------------------
// Seeks and reads bytes from file
//--------------------------------------------------------------------------
BOOL
SeekAndReadFile(
IN HANDLE hFile,
IN DWORD lFileOffset,
OUT BYTE *pb,
IN DWORD cb
)
{
DWORD cbRead;
if (0xFFFFFFFF == SetFilePointer(
hFile,
lFileOffset,
NULL, // lpDistanceToMoveHigh
FILE_BEGIN))
return FALSE;
if (!ReadFile(hFile, pb, cb, &cbRead, NULL) || cbRead != cb)
return FALSE;
return TRUE;
}