Commit 4e99be5b authored by Juan Lang's avatar Juan Lang Committed by Alexandre Julliard

- use exception handling in encoding

- consolidate integer encoders
parent e0813371
...@@ -36,10 +36,12 @@ ...@@ -36,10 +36,12 @@
#include <stdlib.h> #include <stdlib.h>
#include "windef.h" #include "windef.h"
#include "winbase.h" #include "winbase.h"
#include "excpt.h"
#include "wincrypt.h" #include "wincrypt.h"
#include "winreg.h" #include "winreg.h"
#include "snmp.h" #include "snmp.h"
#include "wine/debug.h" #include "wine/debug.h"
#include "wine/exception.h"
/* a few asn.1 tags we need */ /* a few asn.1 tags we need */
#define ASN_BOOL (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x01) #define ASN_BOOL (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x01)
...@@ -60,9 +62,23 @@ static const WCHAR szDllName[] = { 'D','l','l',0 }; ...@@ -60,9 +62,23 @@ static const WCHAR szDllName[] = { 'D','l','l',0 };
static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType, static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded); PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType, static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo); PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
/* filter for page-fault exceptions */
static WINE_EXCEPTION_FILTER(page_fault)
{
if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
return EXCEPTION_EXECUTE_HANDLER;
return EXCEPTION_CONTINUE_SEARCH;
}
static char *CRYPT_GetKeyName(DWORD dwEncodingType, LPCSTR pszFuncName, static char *CRYPT_GetKeyName(DWORD dwEncodingType, LPCSTR pszFuncName,
LPCSTR pszOID) LPCSTR pszOID)
...@@ -657,80 +673,83 @@ static int BLOBComp(const void *l, const void *r) ...@@ -657,80 +673,83 @@ static int BLOBComp(const void *l, const void *r)
static BOOL WINAPI CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, CERT_RDN *rdn, static BOOL WINAPI CRYPT_AsnEncodeRdn(DWORD dwCertEncodingType, CERT_RDN *rdn,
BYTE *pbEncoded, DWORD *pcbEncoded) BYTE *pbEncoded, DWORD *pcbEncoded)
{ {
DWORD bytesNeeded = 0, lenBytes, i;
BOOL ret; BOOL ret;
CRYPT_DER_BLOB *blobs = NULL; CRYPT_DER_BLOB *blobs = NULL;
ret = TRUE; __TRY
if (rdn->cRDNAttr)
{ {
if (!rdn->rgRDNAttr) DWORD bytesNeeded = 0, lenBytes, i;
{
SetLastError(STATUS_ACCESS_VIOLATION); ret = TRUE;
ret = FALSE; if (rdn->cRDNAttr)
}
else
{ {
blobs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, blobs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
rdn->cRDNAttr * sizeof(CRYPT_DER_BLOB)); rdn->cRDNAttr * sizeof(CRYPT_DER_BLOB));
if (!blobs) if (!blobs)
ret = FALSE; ret = FALSE;
} }
} for (i = 0; ret && i < rdn->cRDNAttr; i++)
for (i = 0; ret && i < rdn->cRDNAttr; i++) {
{ ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i],
ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType, &rdn->rgRDNAttr[i], NULL, &blobs[i].cbData);
NULL, &blobs[i].cbData); if (ret)
bytesNeeded += blobs[i].cbData;
}
if (ret) if (ret)
bytesNeeded += blobs[i].cbData;
}
CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
bytesNeeded += 1 + lenBytes;
if (ret)
{
if (pbEncoded)
{ {
if (*pcbEncoded < bytesNeeded) CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
{ bytesNeeded += 1 + lenBytes;
SetLastError(ERROR_MORE_DATA); if (pbEncoded)
ret = FALSE;
}
else
{ {
for (i = 0; ret && i < rdn->cRDNAttr; i++) if (*pcbEncoded < bytesNeeded)
{ {
blobs[i].pbData = HeapAlloc(GetProcessHeap(), 0, SetLastError(ERROR_MORE_DATA);
blobs[i].cbData); ret = FALSE;
if (!blobs[i].pbData)
ret = FALSE;
else
ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
&rdn->rgRDNAttr[i], blobs[i].pbData, &blobs[i].cbData);
} }
if (ret) else
{ {
qsort(blobs, rdn->cRDNAttr, sizeof(CRYPT_DER_BLOB),
BLOBComp);
*pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
&lenBytes);
pbEncoded += lenBytes;
for (i = 0; ret && i < rdn->cRDNAttr; i++) for (i = 0; ret && i < rdn->cRDNAttr; i++)
{ {
memcpy(pbEncoded, blobs[i].pbData, blobs[i].cbData); blobs[i].pbData = HeapAlloc(GetProcessHeap(), 0,
pbEncoded += blobs[i].cbData; blobs[i].cbData);
if (!blobs[i].pbData)
ret = FALSE;
else
ret = CRYPT_AsnEncodeRdnAttr(dwCertEncodingType,
&rdn->rgRDNAttr[i], blobs[i].pbData,
&blobs[i].cbData);
}
if (ret)
{
qsort(blobs, rdn->cRDNAttr, sizeof(CRYPT_DER_BLOB),
BLOBComp);
*pbEncoded++ = ASN_CONSTRUCTOR | ASN_SETOF;
CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
&lenBytes);
pbEncoded += lenBytes;
for (i = 0; ret && i < rdn->cRDNAttr; i++)
{
memcpy(pbEncoded, blobs[i].pbData, blobs[i].cbData);
pbEncoded += blobs[i].cbData;
}
} }
} }
} }
*pcbEncoded = bytesNeeded;
}
if (blobs)
{
for (i = 0; i < rdn->cRDNAttr; i++)
HeapFree(GetProcessHeap(), 0, blobs[i].pbData);
} }
*pcbEncoded = bytesNeeded;
} }
if (blobs) __EXCEPT(page_fault)
{ {
for (i = 0; i < rdn->cRDNAttr; i++) SetLastError(STATUS_ACCESS_VIOLATION);
HeapFree(GetProcessHeap(), 0, blobs[i].pbData); ret = FALSE;
HeapFree(GetProcessHeap(), 0, blobs);
} }
__ENDTRY
HeapFree(GetProcessHeap(), 0, blobs);
return ret; return ret;
} }
...@@ -738,58 +757,60 @@ static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType, ...@@ -738,58 +757,60 @@ static BOOL WINAPI CRYPT_AsnEncodeName(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
{ {
CERT_NAME_INFO *info = (CERT_NAME_INFO *)pvStructInfo;
DWORD bytesNeeded = 0, lenBytes, size, i;
BOOL ret; BOOL ret;
if (!pvStructInfo) __TRY
{
SetLastError(STATUS_ACCESS_VIOLATION);
return FALSE;
}
if (info->cRDN && !info->rgRDN)
{
SetLastError(STATUS_ACCESS_VIOLATION);
return FALSE;
}
TRACE("encoding name with %ld RDNs\n", info->cRDN);
ret = TRUE;
for (i = 0; ret && i < info->cRDN; i++)
{ {
ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i], NULL, CERT_NAME_INFO *info = (CERT_NAME_INFO *)pvStructInfo;
&size); DWORD bytesNeeded = 0, lenBytes, size, i;
if (ret)
bytesNeeded += size; TRACE("encoding name with %ld RDNs\n", info->cRDN);
} ret = TRUE;
CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
bytesNeeded += 1 + lenBytes;
if (ret)
{
if (!pbEncoded)
{
*pcbEncoded = bytesNeeded;
return TRUE;
}
if (!CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
pcbEncoded, bytesNeeded))
return FALSE;
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded, &size);
pbEncoded += size;
for (i = 0; ret && i < info->cRDN; i++) for (i = 0; ret && i < info->cRDN; i++)
{ {
size = bytesNeeded; ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i], NULL,
ret = CRYPT_AsnEncodeRdn(dwCertEncodingType, &info->rgRDN[i], &size);
pbEncoded, &size);
if (ret) if (ret)
bytesNeeded += size;
}
CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
bytesNeeded += 1 + lenBytes;
if (ret)
{
if (!pbEncoded)
*pcbEncoded = bytesNeeded;
else
{ {
pbEncoded += size; if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
bytesNeeded -= size; pbEncoded, pcbEncoded, bytesNeeded)))
{
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(bytesNeeded - lenBytes - 1, pbEncoded,
&lenBytes);
pbEncoded += lenBytes;
for (i = 0; ret && i < info->cRDN; i++)
{
size = bytesNeeded;
ret = CRYPT_AsnEncodeRdn(dwCertEncodingType,
&info->rgRDN[i], pbEncoded, &size);
if (ret)
{
pbEncoded += size;
bytesNeeded -= size;
}
}
}
} }
} }
} }
__EXCEPT(page_fault)
{
SetLastError(STATUS_ACCESS_VIOLATION);
ret = FALSE;
}
__ENDTRY
return ret; return ret;
} }
...@@ -817,57 +838,70 @@ static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType, ...@@ -817,57 +838,70 @@ static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
{ {
CERT_BASIC_CONSTRAINTS2_INFO *info = BOOL ret;
(CERT_BASIC_CONSTRAINTS2_INFO *)pvStructInfo;
DWORD bytesNeeded = 0, lenBytes, caLen = 0, pathConstraintLen = 0;
BOOL ret = TRUE;
if (!pvStructInfo) __TRY
{
SetLastError(STATUS_ACCESS_VIOLATION);
return FALSE;
}
if (info->fCA)
{
ret = CRYPT_EncodeBool(TRUE, NULL, &caLen);
if (ret)
bytesNeeded += caLen;
}
if (info->fPathLenConstraint)
{
ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER,
&info->dwPathLenConstraint, 0, NULL, NULL, &pathConstraintLen);
if (ret)
bytesNeeded += pathConstraintLen;
}
if (!ret)
return FALSE;
CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
bytesNeeded += 1 + lenBytes;
if (!pbEncoded)
{ {
*pcbEncoded = bytesNeeded; CERT_BASIC_CONSTRAINTS2_INFO *info =
return TRUE; (CERT_BASIC_CONSTRAINTS2_INFO *)pvStructInfo;
} DWORD bytesNeeded = 0, lenBytes, caLen = 0, pathConstraintLen = 0;
if (!CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, pcbEncoded,
bytesNeeded)) ret = TRUE;
return FALSE; if (info->fCA)
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) {
pbEncoded = *(BYTE **)pbEncoded; ret = CRYPT_EncodeBool(TRUE, NULL, &caLen);
*pbEncoded++ = ASN_SEQUENCE; if (ret)
CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded, &lenBytes); bytesNeeded += caLen;
pbEncoded += lenBytes; }
if (info->fCA) if (info->fPathLenConstraint)
{ {
ret = CRYPT_EncodeBool(TRUE, pbEncoded, &caLen); ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER,
&info->dwPathLenConstraint, 0, NULL, NULL, &pathConstraintLen);
if (ret)
bytesNeeded += pathConstraintLen;
}
if (ret) if (ret)
pbEncoded += caLen; {
CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
bytesNeeded += 1 + lenBytes;
if (!pbEncoded)
{
*pcbEncoded = bytesNeeded;
ret = TRUE;
}
else
{
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
pbEncoded, pcbEncoded, bytesNeeded)))
{
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_SEQUENCE;
CRYPT_EncodeLen(bytesNeeded - 1 - lenBytes, pbEncoded,
&lenBytes);
pbEncoded += lenBytes;
if (info->fCA)
{
ret = CRYPT_EncodeBool(TRUE, pbEncoded, &caLen);
if (ret)
pbEncoded += caLen;
}
if (info->fPathLenConstraint)
{
ret = CRYPT_AsnEncodeInt(dwCertEncodingType,
X509_INTEGER, &info->dwPathLenConstraint, 0, NULL,
pbEncoded, &pathConstraintLen);
}
}
}
}
} }
if (info->fPathLenConstraint) __EXCEPT(page_fault)
{ {
ret = CRYPT_AsnEncodeInt(dwCertEncodingType, X509_INTEGER, SetLastError(STATUS_ACCESS_VIOLATION);
&info->dwPathLenConstraint, 0, NULL, pbEncoded, &pathConstraintLen); ret = FALSE;
} }
__ENDTRY
return ret; return ret;
} }
...@@ -875,301 +909,275 @@ static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType, ...@@ -875,301 +909,275 @@ static BOOL WINAPI CRYPT_AsnEncodeOctets(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
{ {
CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)pvStructInfo; BOOL ret;
DWORD bytesNeeded, lenBytes;
if (!pvStructInfo) __TRY
{ {
SetLastError(STATUS_ACCESS_VIOLATION); CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)pvStructInfo;
return FALSE; DWORD bytesNeeded, lenBytes;
CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
bytesNeeded = 1 + lenBytes + blob->cbData;
if (!pbEncoded)
{
*pcbEncoded = bytesNeeded;
ret = TRUE;
}
else
{
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
pcbEncoded, bytesNeeded)))
{
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_OCTETSTRING;
CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
if (blob->cbData)
memcpy(pbEncoded, blob->pbData, blob->cbData);
}
}
} }
/* FIXME: use exception handling to catch bogus pointers */ __EXCEPT(page_fault)
CRYPT_EncodeLen(blob->cbData, NULL, &lenBytes);
bytesNeeded = 1 + lenBytes + blob->cbData;
if (!pbEncoded)
{ {
*pcbEncoded = bytesNeeded; SetLastError(STATUS_ACCESS_VIOLATION);
return TRUE; ret = FALSE;
} }
if (!CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, pcbEncoded, __ENDTRY
bytesNeeded)) return ret;
return FALSE;
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_OCTETSTRING;
CRYPT_EncodeLen(blob->cbData, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
if (blob->cbData)
memcpy(pbEncoded, blob->pbData, blob->cbData);
return TRUE;
} }
static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType, static BOOL WINAPI CRYPT_AsnEncodeBits(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
{ {
CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo; BOOL ret;
DWORD bytesNeeded, lenBytes, dataBytes;
BYTE unusedBits;
if (!pvStructInfo) __TRY
{
SetLastError(STATUS_ACCESS_VIOLATION);
return FALSE;
}
/* FIXME: use exception handling to catch bogus pointers */
/* yep, MS allows cUnusedBits to be >= 8 */
if (blob->cbData * 8 > blob->cUnusedBits)
{
dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
blob->cUnusedBits;
}
else
{
dataBytes = 0;
unusedBits = 0;
}
CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
bytesNeeded = 1 + lenBytes + dataBytes + 1;
if (!pbEncoded)
{
*pcbEncoded = bytesNeeded;
return TRUE;
}
if (!CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, pcbEncoded,
bytesNeeded))
return FALSE;
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_BITSTRING;
CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
*pbEncoded++ = unusedBits;
if (dataBytes)
{ {
BYTE mask = 0xff << unusedBits; CRYPT_BIT_BLOB *blob = (CRYPT_BIT_BLOB *)pvStructInfo;
DWORD bytesNeeded, lenBytes, dataBytes;
BYTE unusedBits;
if (dataBytes > 1) /* yep, MS allows cUnusedBits to be >= 8 */
if (blob->cbData * 8 > blob->cUnusedBits)
{
dataBytes = (blob->cbData * 8 - blob->cUnusedBits) / 8 + 1;
unusedBits = blob->cUnusedBits >= 8 ? blob->cUnusedBits / 8 :
blob->cUnusedBits;
}
else
{
dataBytes = 0;
unusedBits = 0;
}
CRYPT_EncodeLen(dataBytes + 1, NULL, &lenBytes);
bytesNeeded = 1 + lenBytes + dataBytes + 1;
if (!pbEncoded)
{ {
memcpy(pbEncoded, blob->pbData, dataBytes - 1); *pcbEncoded = bytesNeeded;
pbEncoded += dataBytes - 1; ret = TRUE;
}
else
{
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
pcbEncoded, bytesNeeded)))
{
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_BITSTRING;
CRYPT_EncodeLen(dataBytes + 1, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
*pbEncoded++ = unusedBits;
if (dataBytes)
{
BYTE mask = 0xff << unusedBits;
if (dataBytes > 1)
{
memcpy(pbEncoded, blob->pbData, dataBytes - 1);
pbEncoded += dataBytes - 1;
}
*pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
}
}
} }
*pbEncoded = *(blob->pbData + dataBytes - 1) & mask;
} }
return TRUE; __EXCEPT(page_fault)
{
SetLastError(STATUS_ACCESS_VIOLATION);
ret = FALSE;
}
__ENDTRY
return ret;
} }
static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType, static BOOL WINAPI CRYPT_AsnEncodeInt(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
{ {
INT val, i; CRYPT_INTEGER_BLOB blob = { sizeof(INT), (BYTE *)pvStructInfo };
BYTE significantBytes, padByte = 0, bytesNeeded;
BOOL neg = FALSE, pad = FALSE;
if (!pvStructInfo) return CRYPT_AsnEncodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
{ &blob, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
SetLastError(STATUS_ACCESS_VIOLATION);
return FALSE;
}
memcpy(&val, pvStructInfo, sizeof(val));
/* Count the number of significant bytes. Temporarily swap sign for
* negatives so I count the minimum number of bytes.
*/
if (val < 0)
{
neg = TRUE;
val = -val;
}
for (significantBytes = sizeof(val); significantBytes > 0 &&
!(val & 0xff000000); val <<= 8, significantBytes--)
;
if (significantBytes == 0)
significantBytes = 1;
if (neg)
{
val = -val;
if ((val & 0xff000000) < 0x80000000)
{
padByte = 0xff;
pad = TRUE;
}
}
else if ((val & 0xff000000) > 0x7f000000)
{
padByte = 0;
pad = TRUE;
}
bytesNeeded = 2 + significantBytes;
if (pad)
bytesNeeded++;
if (!pbEncoded)
{
*pcbEncoded = bytesNeeded;
return TRUE;
}
if (!CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, pcbEncoded,
bytesNeeded))
return FALSE;
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_INTEGER;
if (pad)
{
*pbEncoded++ = significantBytes + 1;
*pbEncoded++ = padByte;
}
else
*pbEncoded++ = significantBytes;
for (i = 0; i < significantBytes; i++, val <<= 8)
*(pbEncoded + i) = (BYTE)((val & 0xff000000) >> 24);
return TRUE;
} }
static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType, static BOOL WINAPI CRYPT_AsnEncodeInteger(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
{ {
DWORD significantBytes, lenBytes; BOOL ret;
BYTE padByte = 0, bytesNeeded;
BOOL pad = FALSE;
CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
if (!pvStructInfo) __TRY
{ {
SetLastError(STATUS_ACCESS_VIOLATION); DWORD significantBytes, lenBytes;
return FALSE; BYTE padByte = 0, bytesNeeded;
} BOOL pad = FALSE;
CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
/* FIXME: use exception handling to protect against bogus pointers */ significantBytes = blob->cbData;
significantBytes = blob->cbData; if (significantBytes)
if (significantBytes)
{
if (blob->pbData[significantBytes - 1] & 0x80)
{ {
/* negative, lop off leading (little-endian) 0xffs */ if (blob->pbData[significantBytes - 1] & 0x80)
for (; significantBytes > 0 &&
blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
;
if (significantBytes == 0)
significantBytes = 1;
if (blob->pbData[significantBytes - 1] < 0x80)
{ {
padByte = 0xff; /* negative, lop off leading (little-endian) 0xffs */
pad = TRUE; for (; significantBytes > 0 &&
blob->pbData[significantBytes - 1] == 0xff; significantBytes--)
;
if (blob->pbData[significantBytes - 1] < 0x80)
{
padByte = 0xff;
pad = TRUE;
}
}
else
{
/* positive, lop off leading (little-endian) zeroes */
for (; significantBytes > 0 &&
!blob->pbData[significantBytes - 1]; significantBytes--)
;
if (significantBytes == 0)
significantBytes = 1;
if (blob->pbData[significantBytes - 1] > 0x7f)
{
padByte = 0;
pad = TRUE;
}
} }
} }
if (pad)
CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
else else
CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
bytesNeeded = 1 + lenBytes + significantBytes;
if (pad)
bytesNeeded++;
if (!pbEncoded)
{ {
/* positive, lop off leading (little-endian) zeroes */ *pcbEncoded = bytesNeeded;
for (; significantBytes > 0 && !blob->pbData[significantBytes - 1]; ret = TRUE;
significantBytes--) }
; else
if (significantBytes == 0) {
significantBytes = 1; if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
if (blob->pbData[significantBytes - 1] > 0x7f) pcbEncoded, bytesNeeded)))
{ {
padByte = 0; if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pad = TRUE; pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_INTEGER;
if (pad)
{
CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
*pbEncoded++ = padByte;
}
else
{
CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
}
for (; significantBytes > 0; significantBytes--)
*(pbEncoded++) = blob->pbData[significantBytes - 1];
} }
} }
} }
if (pad) __EXCEPT(page_fault)
CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
else
CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
bytesNeeded = 1 + lenBytes + significantBytes;
if (pad)
bytesNeeded++;
if (!pbEncoded)
{ {
*pcbEncoded = bytesNeeded; SetLastError(STATUS_ACCESS_VIOLATION);
return TRUE; ret = FALSE;
}
if (!CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, pcbEncoded,
bytesNeeded))
return FALSE;
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_INTEGER;
if (pad)
{
CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
*pbEncoded++ = padByte;
}
else
{
CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
} }
for (; significantBytes > 0; significantBytes--) __ENDTRY
*(pbEncoded++) = blob->pbData[significantBytes - 1]; return ret;
return TRUE;
} }
static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType, static BOOL WINAPI CRYPT_AsnEncodeUnsignedInteger(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
{ {
DWORD significantBytes, lenBytes; BOOL ret;
BYTE bytesNeeded;
BOOL pad = FALSE;
CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
if (!pvStructInfo) __TRY
{ {
SetLastError(STATUS_ACCESS_VIOLATION); DWORD significantBytes, lenBytes;
return FALSE; BYTE bytesNeeded;
} BOOL pad = FALSE;
CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)pvStructInfo;
/* FIXME: use exception handling to protect against bogus pointers */ significantBytes = blob->cbData;
significantBytes = blob->cbData; if (significantBytes)
if (significantBytes) {
{ /* positive, lop off leading (little-endian) zeroes */
/* positive, lop off leading (little-endian) zeroes */ for (; significantBytes > 0 && !blob->pbData[significantBytes - 1];
for (; significantBytes > 0 && !blob->pbData[significantBytes - 1]; significantBytes--)
significantBytes--) ;
; if (significantBytes == 0)
if (significantBytes == 0) significantBytes = 1;
significantBytes = 1; if (blob->pbData[significantBytes - 1] > 0x7f)
if (blob->pbData[significantBytes - 1] > 0x7f) pad = TRUE;
pad = TRUE; }
} if (pad)
if (pad) CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes);
CRYPT_EncodeLen(significantBytes + 1, NULL, &lenBytes); else
else CRYPT_EncodeLen(significantBytes, NULL, &lenBytes);
CRYPT_EncodeLen(significantBytes, NULL, &lenBytes); bytesNeeded = 1 + lenBytes + significantBytes;
bytesNeeded = 1 + lenBytes + significantBytes; if (pad)
if (pad) bytesNeeded++;
bytesNeeded++; if (!pbEncoded)
if (!pbEncoded) {
{ *pcbEncoded = bytesNeeded;
*pcbEncoded = bytesNeeded; ret = TRUE;
return TRUE; }
} else
if (!CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, pcbEncoded, {
bytesNeeded)) if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
return FALSE; pcbEncoded, bytesNeeded)))
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG) {
pbEncoded = *(BYTE **)pbEncoded; if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
*pbEncoded++ = ASN_INTEGER; pbEncoded = *(BYTE **)pbEncoded;
if (pad) *pbEncoded++ = ASN_INTEGER;
{ if (pad)
CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes); {
pbEncoded += lenBytes; CRYPT_EncodeLen(significantBytes + 1, pbEncoded, &lenBytes);
*pbEncoded++ = 0; pbEncoded += lenBytes;
*pbEncoded++ = 0;
}
else
{
CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
}
for (; significantBytes > 0; significantBytes--)
*(pbEncoded++) = blob->pbData[significantBytes - 1];
}
}
} }
else __EXCEPT(page_fault)
{ {
CRYPT_EncodeLen(significantBytes, pbEncoded, &lenBytes); SetLastError(STATUS_ACCESS_VIOLATION);
pbEncoded += lenBytes; ret = FALSE;
} }
for (; significantBytes > 0; significantBytes--) __ENDTRY
*(pbEncoded++) = blob->pbData[significantBytes - 1]; return ret;
return TRUE;
} }
static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType, static BOOL WINAPI CRYPT_AsnEncodeEnumerated(DWORD dwCertEncodingType,
...@@ -1197,105 +1205,136 @@ static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType, ...@@ -1197,105 +1205,136 @@ static BOOL WINAPI CRYPT_AsnEncodeUtcTime(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
{ {
SYSTEMTIME sysTime; BOOL ret;
/* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
* temporary buffer because the output buffer is not NULL-terminated.
*/
char buf[16];
static const DWORD bytesNeeded = sizeof(buf) - 1;
if (!pvStructInfo) __TRY
{
SetLastError(STATUS_ACCESS_VIOLATION);
return FALSE;
}
/* Sanity check the year, this is a two-digit year format */
if (!FileTimeToSystemTime((const FILETIME *)pvStructInfo, &sysTime))
return FALSE;
if (sysTime.wYear < 1950 || sysTime.wYear > 2050)
{ {
SetLastError(CRYPT_E_BAD_ENCODE); SYSTEMTIME sysTime;
return FALSE; /* sorry, magic number: enough for tag, len, YYMMDDHHMMSSZ\0. I use a
* temporary buffer because the output buffer is not NULL-terminated.
*/
char buf[16];
static const DWORD bytesNeeded = sizeof(buf) - 1;
if (!pbEncoded)
{
*pcbEncoded = bytesNeeded;
ret = TRUE;
}
else
{
/* Sanity check the year, this is a two-digit year format */
ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
&sysTime);
if (ret && (sysTime.wYear < 1950 || sysTime.wYear > 2050))
{
SetLastError(CRYPT_E_BAD_ENCODE);
ret = FALSE;
}
if (ret)
{
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
pbEncoded, pcbEncoded, bytesNeeded)))
{
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
buf[0] = ASN_UTCTIME;
buf[1] = bytesNeeded - 2;
snprintf(buf + 2, sizeof(buf) - 2,
"%02d%02d%02d%02d%02d%02dZ", sysTime.wYear >= 2000 ?
sysTime.wYear - 2000 : sysTime.wYear - 1900,
sysTime.wDay, sysTime.wMonth, sysTime.wHour,
sysTime.wMinute, sysTime.wSecond);
memcpy(pbEncoded, buf, bytesNeeded);
}
}
}
} }
if (!pbEncoded) __EXCEPT(page_fault)
{ {
*pcbEncoded = bytesNeeded; SetLastError(STATUS_ACCESS_VIOLATION);
return TRUE; ret = FALSE;
} }
if (!CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, pcbEncoded, __ENDTRY
bytesNeeded)) return ret;
return FALSE;
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
buf[0] = ASN_UTCTIME;
buf[1] = bytesNeeded - 2;
snprintf(buf + 2, sizeof(buf) - 2, "%02d%02d%02d%02d%02d%02dZ",
sysTime.wYear >= 2000 ? sysTime.wYear - 2000 : sysTime.wYear - 1900,
sysTime.wDay, sysTime.wMonth, sysTime.wHour, sysTime.wMinute,
sysTime.wSecond);
memcpy(pbEncoded, buf, bytesNeeded);
return TRUE;
} }
static BOOL WINAPI CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType, static BOOL WINAPI CRYPT_AsnEncodeGeneralizedTime(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
{ {
SYSTEMTIME sysTime; BOOL ret;
/* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
* temporary buffer because the output buffer is not NULL-terminated.
*/
char buf[18];
static const DWORD bytesNeeded = sizeof(buf) - 1;
if (!pvStructInfo) __TRY
{ {
SetLastError(STATUS_ACCESS_VIOLATION); SYSTEMTIME sysTime;
return FALSE; /* sorry, magic number: enough for tag, len, YYYYMMDDHHMMSSZ\0. I use a
* temporary buffer because the output buffer is not NULL-terminated.
*/
char buf[18];
static const DWORD bytesNeeded = sizeof(buf) - 1;
if (!pbEncoded)
{
*pcbEncoded = bytesNeeded;
ret = TRUE;
}
else
{
ret = FileTimeToSystemTime((const FILETIME *)pvStructInfo,
&sysTime);
if (ret)
ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
pcbEncoded, bytesNeeded);
if (ret)
{
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
buf[0] = ASN_GENERALTIME;
buf[1] = bytesNeeded - 2;
snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
sysTime.wYear, sysTime.wDay, sysTime.wMonth, sysTime.wHour,
sysTime.wMinute, sysTime.wSecond);
memcpy(pbEncoded, buf, bytesNeeded);
}
}
} }
if (!pbEncoded) __EXCEPT(page_fault)
{ {
*pcbEncoded = bytesNeeded; SetLastError(STATUS_ACCESS_VIOLATION);
return TRUE; ret = FALSE;
} }
if (!FileTimeToSystemTime((const FILETIME *)pvStructInfo, &sysTime)) __ENDTRY
return FALSE; return ret;
if (!CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, pcbEncoded,
bytesNeeded))
return FALSE;
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
buf[0] = ASN_GENERALTIME;
buf[1] = bytesNeeded - 2;
snprintf(buf + 2, sizeof(buf) - 2, "%04d%02d%02d%02d%02d%02dZ",
sysTime.wYear, sysTime.wDay, sysTime.wMonth, sysTime.wHour,
sysTime.wMinute, sysTime.wSecond);
memcpy(pbEncoded, buf, bytesNeeded);
return TRUE;
} }
static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType, static BOOL WINAPI CRYPT_AsnEncodeChoiceOfTime(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
{ {
SYSTEMTIME sysTime;
BOOL ret; BOOL ret;
if (!pvStructInfo) __TRY
{
SYSTEMTIME sysTime;
/* Check the year, if it's in the UTCTime range call that encode func */
if (!FileTimeToSystemTime((const FILETIME *)pvStructInfo, &sysTime))
return FALSE;
if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
else
ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
pcbEncoded);
}
__EXCEPT(page_fault)
{ {
SetLastError(STATUS_ACCESS_VIOLATION); SetLastError(STATUS_ACCESS_VIOLATION);
return FALSE; ret = FALSE;
} }
/* Check the year, if it's in the UTCTime range call that encode func */ __ENDTRY
if (!FileTimeToSystemTime((const FILETIME *)pvStructInfo, &sysTime))
return FALSE;
if (sysTime.wYear >= 1950 && sysTime.wYear <= 2050)
ret = CRYPT_AsnEncodeUtcTime(dwCertEncodingType, lpszStructType,
pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
else
ret = CRYPT_AsnEncodeGeneralizedTime(dwCertEncodingType,
lpszStructType, pvStructInfo, dwFlags, pEncodePara, pbEncoded,
pcbEncoded);
return ret; return ret;
} }
...@@ -1303,38 +1342,48 @@ static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType, ...@@ -1303,38 +1342,48 @@ static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags, LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded) PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
{ {
DWORD bytesNeeded, dataLen, lenBytes, i; BOOL ret;
CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
if (!pvStructInfo) __TRY
{ {
SetLastError(STATUS_ACCESS_VIOLATION); DWORD bytesNeeded, dataLen, lenBytes, i;
return FALSE; CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)pvStructInfo;
}
/* FIXME: use exception handling to catch bogus pointers */ for (i = 0, dataLen = 0; i < seq->cValue; i++)
for (i = 0, dataLen = 0; i < seq->cValue; i++) dataLen += seq->rgValue[i].cbData;
dataLen += seq->rgValue[i].cbData; CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
CRYPT_EncodeLen(dataLen, NULL, &lenBytes); bytesNeeded = 1 + lenBytes + dataLen;
bytesNeeded = 1 + lenBytes + dataLen; if (!pbEncoded)
if (!pbEncoded) {
{ *pcbEncoded = bytesNeeded;
*pcbEncoded = bytesNeeded; ret = TRUE;
return TRUE; }
else
{
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
pcbEncoded, bytesNeeded)))
{
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
for (i = 0; i < seq->cValue; i++)
{
memcpy(pbEncoded, seq->rgValue[i].pbData,
seq->rgValue[i].cbData);
pbEncoded += seq->rgValue[i].cbData;
}
}
}
} }
if (!CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded, pcbEncoded, __EXCEPT(page_fault)
bytesNeeded))
return FALSE;
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
pbEncoded = *(BYTE **)pbEncoded;
*pbEncoded++ = ASN_SEQUENCEOF;
CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
for (i = 0; i < seq->cValue; i++)
{ {
memcpy(pbEncoded, seq->rgValue[i].pbData, seq->rgValue[i].cbData); SetLastError(STATUS_ACCESS_VIOLATION);
pbEncoded += seq->rgValue[i].cbData; ret = FALSE;
} }
return TRUE; __ENDTRY
return ret;
} }
typedef BOOL (WINAPI *CryptEncodeObjectExFunc)(DWORD, LPCSTR, const void *, typedef BOOL (WINAPI *CryptEncodeObjectExFunc)(DWORD, LPCSTR, const void *,
...@@ -2273,9 +2322,11 @@ static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType, ...@@ -2273,9 +2322,11 @@ static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{ {
int val, i; BYTE buf[sizeof(CRYPT_INTEGER_BLOB) + sizeof(int)];
DWORD size = sizeof(buf);
BOOL ret;
if (!pbEncoded || !cbEncoded) if (!pbEncoded)
{ {
SetLastError(CRYPT_E_ASN1_EOD); SetLastError(CRYPT_E_ASN1_EOD);
return FALSE; return FALSE;
...@@ -2285,45 +2336,37 @@ static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType, ...@@ -2285,45 +2336,37 @@ static BOOL WINAPI CRYPT_AsnDecodeInt(DWORD dwCertEncodingType,
*pcbStructInfo = sizeof(int); *pcbStructInfo = sizeof(int);
return TRUE; return TRUE;
} }
if (pbEncoded[0] != ASN_INTEGER) ret = CRYPT_AsnDecodeInteger(dwCertEncodingType, X509_MULTI_BYTE_INTEGER,
{ pbEncoded, cbEncoded, 0, NULL, &buf, &size);
SetLastError(CRYPT_E_ASN1_BADTAG); if (ret)
return FALSE;
}
if (cbEncoded <= 1)
{
SetLastError(CRYPT_E_ASN1_EOD);
return FALSE;
}
if (pbEncoded[1] == 0)
{ {
SetLastError(CRYPT_E_ASN1_CORRUPT); CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
return FALSE;
if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara,
pvStructInfo, pcbStructInfo, sizeof(int))))
{
int val, i;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
pvStructInfo = *(BYTE **)pvStructInfo;
if (blob->pbData[blob->cbData - 1] & 0x80)
{
/* initialize to a negative value to sign-extend */
val = -1;
}
else
val = 0;
for (i = 0; i < blob->cbData; i++)
{
val <<= 8;
val |= blob->pbData[blob->cbData - i - 1];
}
memcpy(pvStructInfo, &val, sizeof(int));
}
} }
if (pbEncoded[1] > sizeof(int)) else if (GetLastError() == ERROR_MORE_DATA)
{
SetLastError(CRYPT_E_ASN1_LARGE); SetLastError(CRYPT_E_ASN1_LARGE);
return FALSE; return ret;
}
if (pbEncoded[2] & 0x80)
{
/* initialize to a negative value to sign-extend */
val = -1;
}
else
val = 0;
for (i = 0; i < pbEncoded[1]; i++)
{
val <<= 8;
val |= pbEncoded[2 + i];
}
if (!CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
pcbStructInfo, sizeof(int)))
return FALSE;
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
pvStructInfo = *(BYTE **)pvStructInfo;
memcpy(pvStructInfo, &val, sizeof(int));
return TRUE;
} }
static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType, static BOOL WINAPI CRYPT_AsnDecodeInteger(DWORD dwCertEncodingType,
...@@ -2429,7 +2472,6 @@ static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType, ...@@ -2429,7 +2472,6 @@ static BOOL WINAPI CRYPT_AsnDecodeEnumerated(DWORD dwCertEncodingType,
{ {
unsigned int val = 0, i; unsigned int val = 0, i;
/* Based on CRYPT_AsnDecodeInt, but interprets as unsigned */
if (!pbEncoded || !cbEncoded) if (!pbEncoded || !cbEncoded)
{ {
SetLastError(CRYPT_E_ASN1_EOD); SetLastError(CRYPT_E_ASN1_EOD);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment