Windows2000/private/ispu/pkitrust/mssip32/jvimage.cpp
2020-09-30 17:12:32 +02:00

977 lines
27 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; // BUGBUG need to fill this in
}
// 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; // BUGBUG need to fill this in
}
// 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;
}