Commit 628ede47 authored by Juan Lang's avatar Juan Lang Committed by Alexandre Julliard

crypt32: Implement CRLDistPoints encoding/decoding.

- rewrite sequence decoding to support context-specific tags, and eliminate duplicated code - implement encoding and decoding of CRLDistPoints
parent a4af4b95
...@@ -134,10 +134,11 @@ static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType, ...@@ -134,10 +134,11 @@ static BOOL WINAPI CRYPT_AsnDecodeExtensionsInternal(DWORD dwCertEncodingType,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo); PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo);
static BOOL WINAPI CRYPT_AsnDecodeOid(const BYTE *pbEncoded, DWORD cbEncoded, static BOOL WINAPI CRYPT_AsnDecodeOid(const BYTE *pbEncoded, DWORD cbEncoded,
DWORD dwFlags, LPSTR pszObjId, DWORD *pcbObjId); DWORD dwFlags, LPSTR pszObjId, DWORD *pcbObjId);
/* Assumes algo->Parameters.pbData is set ahead of time */ /* Assumes algo->Parameters.pbData is set ahead of time. Internal func. */
static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType, static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(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);
/* Internal function */
static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType, static BOOL WINAPI CRYPT_AsnDecodeBool(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);
...@@ -402,6 +403,32 @@ static BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType, ...@@ -402,6 +403,32 @@ static BOOL WINAPI CRYPT_AsnEncodeConstructed(DWORD dwCertEncodingType,
return ret; return ret;
} }
struct AsnEncodeTagSwappedItem
{
BYTE tag;
const void *pvStructInfo;
CryptEncodeObjectExFunc encodeFunc;
};
/* Sort of a wacky hack, it encodes something using the struct
* AsnEncodeTagSwappedItem's encodeFunc, then replaces the tag byte with the tag
* given in the struct AsnEncodeTagSwappedItem.
*/
static BOOL WINAPI CRYPT_AsnEncodeSwapTag(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
{
BOOL ret;
const struct AsnEncodeTagSwappedItem *item =
(const struct AsnEncodeTagSwappedItem *)pvStructInfo;
ret = item->encodeFunc(dwCertEncodingType, lpszStructType,
item->pvStructInfo, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
if (ret && pbEncoded)
*pbEncoded = item->tag;
return ret;
}
static BOOL WINAPI CRYPT_AsnEncodeCertVersion(DWORD dwCertEncodingType, static BOOL WINAPI CRYPT_AsnEncodeCertVersion(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)
...@@ -2033,6 +2060,145 @@ static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType, ...@@ -2033,6 +2060,145 @@ static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
return ret; return ret;
} }
static BOOL CRYPT_AsnEncodeDistPoint(const CRL_DIST_POINT *distPoint,
BYTE *pbEncoded, DWORD *pcbEncoded)
{
BOOL ret = TRUE;
struct AsnEncodeSequenceItem items[3] = { { 0 } };
struct AsnConstructedItem constructed = { 0 };
struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
DWORD cItem = 0, cSwapped = 0;
switch (distPoint->DistPointName.dwDistPointNameChoice)
{
case CRL_DIST_POINT_NO_NAME:
/* do nothing */
break;
case CRL_DIST_POINT_FULL_NAME:
swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 0;
swapped[cSwapped].pvStructInfo = &distPoint->DistPointName.u.FullName;
swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
constructed.tag = 0;
constructed.pvStructInfo = &swapped[cSwapped];
constructed.encodeFunc = CRYPT_AsnEncodeSwapTag;
items[cItem].pvStructInfo = &constructed;
items[cItem].encodeFunc = CRYPT_AsnEncodeConstructed;
cSwapped++;
cItem++;
break;
case CRL_DIST_POINT_ISSUER_RDN_NAME:
FIXME("unimplemented for CRL_DIST_POINT_ISSUER_RDN_NAME\n");
ret = FALSE;
break;
default:
ret = FALSE;
}
if (ret && distPoint->ReasonFlags.cbData)
{
swapped[cSwapped].tag = ASN_CONTEXT | 1;
swapped[cSwapped].pvStructInfo = &distPoint->ReasonFlags;
swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeBits;
items[cItem].pvStructInfo = &swapped[cSwapped];
items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
cSwapped++;
cItem++;
}
if (ret && distPoint->CRLIssuer.cAltEntry)
{
swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 2;
swapped[cSwapped].pvStructInfo = &distPoint->CRLIssuer;
swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
items[cItem].pvStructInfo = &swapped[cSwapped];
items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
cSwapped++;
cItem++;
}
if (ret)
ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, 0, NULL,
pbEncoded, pcbEncoded);
return ret;
}
static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
{
BOOL ret;
__TRY
{
const CRL_DIST_POINTS_INFO *info =
(const CRL_DIST_POINTS_INFO *)pvStructInfo;
if (!info->cDistPoint)
{
SetLastError(HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER));
ret = FALSE;
}
else
{
DWORD bytesNeeded, dataLen, lenBytes, i;
ret = TRUE;
for (i = 0, dataLen = 0; ret && i < info->cDistPoint; i++)
{
DWORD len;
ret = CRYPT_AsnEncodeDistPoint(&info->rgDistPoint[i], NULL,
&len);
if (ret)
dataLen += len;
else if (GetLastError() == CRYPT_E_INVALID_IA5_STRING)
{
/* Have to propagate index of failing character */
*pcbEncoded = len;
}
}
if (ret)
{
CRYPT_EncodeLen(dataLen, NULL, &lenBytes);
bytesNeeded = 1 + lenBytes + dataLen;
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_SEQUENCEOF;
CRYPT_EncodeLen(dataLen, pbEncoded, &lenBytes);
pbEncoded += lenBytes;
for (i = 0; ret && i < info->cDistPoint; i++)
{
DWORD len = dataLen;
ret = CRYPT_AsnEncodeDistPoint(
&info->rgDistPoint[i], pbEncoded, &len);
if (ret)
{
pbEncoded += len;
dataLen -= len;
}
}
}
}
}
}
}
__EXCEPT(page_fault)
{
SetLastError(STATUS_ACCESS_VIOLATION);
ret = FALSE;
}
__ENDTRY
return ret;
}
BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType, BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
void *pvEncoded, DWORD *pcbEncoded) void *pvEncoded, DWORD *pcbEncoded)
...@@ -2120,6 +2286,9 @@ BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType, ...@@ -2120,6 +2286,9 @@ BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
case (WORD)PKCS_UTC_TIME: case (WORD)PKCS_UTC_TIME:
encodeFunc = CRYPT_AsnEncodeUtcTime; encodeFunc = CRYPT_AsnEncodeUtcTime;
break; break;
case (WORD)X509_CRL_DIST_POINTS:
encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
break;
default: default:
FIXME("%d: unimplemented\n", LOWORD(lpszStructType)); FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
} }
...@@ -2306,7 +2475,9 @@ static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags, ...@@ -2306,7 +2475,9 @@ static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
return ret; return ret;
} }
/* A few of the members need explanation: /* tag:
* The expected tag of the item. If tag is 0, decodeFunc is called
* regardless of the tag value seen.
* offset: * offset:
* A sequence is decoded into a struct. The offset member is the * A sequence is decoded into a struct. The offset member is the
* offset of this item within that struct. * offset of this item within that struct.
...@@ -2316,9 +2487,9 @@ static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags, ...@@ -2316,9 +2487,9 @@ static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
* minSize: * minSize:
* The minimum amount of space occupied after decoding. You must set this. * The minimum amount of space occupied after decoding. You must set this.
* optional: * optional:
* If true, and a decoding function fails with CRYPT_E_ASN1_BADTAG, then * If true, and the tag doesn't match the expected tag for this item,
* minSize space is filled with 0 for this member. (Any other failure * or the decodeFunc fails with CRYPT_E_ASN1_BADTAG, then minSize space is
* results in CRYPT_AsnDecodeSequence failing.) * filled with 0 for this member.
* hasPointer, pointerOffset, minSize: * hasPointer, pointerOffset, minSize:
* If the item has dynamic data, set hasPointer to TRUE, pointerOffset to * If the item has dynamic data, set hasPointer to TRUE, pointerOffset to
* the offset within the (outer) struct of the data pointer (or to the * the offset within the (outer) struct of the data pointer (or to the
...@@ -2328,6 +2499,7 @@ static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags, ...@@ -2328,6 +2499,7 @@ static BOOL CRYPT_DecodeEnsureSpace(DWORD dwFlags,
*/ */
struct AsnDecodeSequenceItem struct AsnDecodeSequenceItem
{ {
BYTE tag;
DWORD offset; DWORD offset;
CryptDecodeObjectExFunc decodeFunc; CryptDecodeObjectExFunc decodeFunc;
DWORD minSize; DWORD minSize;
...@@ -2337,6 +2509,114 @@ struct AsnDecodeSequenceItem ...@@ -2337,6 +2509,114 @@ struct AsnDecodeSequenceItem
DWORD size; DWORD size;
}; };
static BOOL CRYPT_AsnDecodeSequenceItems(DWORD dwCertEncodingType,
struct AsnDecodeSequenceItem items[], DWORD cItem, const BYTE *pbEncoded,
DWORD cbEncoded, DWORD dwFlags, void *pvStructInfo, BYTE *nextData)
{
BOOL ret;
DWORD i;
const BYTE *ptr;
ptr = pbEncoded + 1 + GET_LEN_BYTES(pbEncoded[1]);
for (i = 0, ret = TRUE; ret && i < cItem; i++)
{
if (cbEncoded - (ptr - pbEncoded) != 0)
{
DWORD nextItemLen;
if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
&nextItemLen)))
{
BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
if (ptr[0] == items[i].tag || !items[i].tag)
{
if (nextData && pvStructInfo && items[i].hasPointer)
{
TRACE("Setting next pointer to %p\n",
nextData);
*(BYTE **)((BYTE *)pvStructInfo +
items[i].pointerOffset) = nextData;
}
if (items[i].decodeFunc)
{
if (pvStructInfo)
TRACE("decoding item %ld\n", i);
else
TRACE("sizing item %ld\n", i);
ret = items[i].decodeFunc(dwCertEncodingType,
NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
pvStructInfo ? (BYTE *)pvStructInfo + items[i].offset
: NULL, &items[i].size);
if (ret)
{
if (nextData && items[i].hasPointer &&
items[i].size > items[i].minSize)
{
nextData += items[i].size - items[i].minSize;
/* align nextData to DWORD boundaries */
if (items[i].size % sizeof(DWORD))
nextData += sizeof(DWORD) - items[i].size %
sizeof(DWORD);
}
/* Account for alignment padding */
if (items[i].size % sizeof(DWORD))
items[i].size += sizeof(DWORD) -
items[i].size % sizeof(DWORD);
ptr += 1 + nextItemLenBytes + nextItemLen;
}
else if (items[i].optional &&
GetLastError() == CRYPT_E_ASN1_BADTAG)
{
TRACE("skipping optional item %ld\n", i);
items[i].size = items[i].minSize;
SetLastError(NOERROR);
ret = TRUE;
}
else
TRACE("item %ld failed: %08lx\n", i,
GetLastError());
}
else
items[i].size = items[i].minSize;
}
else if (items[i].optional)
{
TRACE("skipping optional item %ld\n", i);
items[i].size = items[i].minSize;
}
else
{
TRACE("tag %02x doesn't match expected %02x\n",
ptr[0], items[i].tag);
SetLastError(CRYPT_E_ASN1_BADTAG);
ret = FALSE;
}
}
}
else if (items[i].optional)
{
TRACE("missing optional item %ld, skipping\n", i);
items[i].size = items[i].minSize;
}
else
{
TRACE("not enough bytes for item %ld, failing\n", i);
SetLastError(CRYPT_E_ASN1_CORRUPT);
ret = FALSE;
}
}
if (cbEncoded - (ptr - pbEncoded) != 0)
{
TRACE("%ld remaining bytes, failing\n", cbEncoded -
(ptr - pbEncoded));
SetLastError(CRYPT_E_ASN1_CORRUPT);
ret = FALSE;
}
return ret;
}
/* This decodes an arbitrary sequence into a contiguous block of memory /* This decodes an arbitrary sequence into a contiguous block of memory
* (basically, a struct.) Each element being decoded is described by a struct * (basically, a struct.) Each element being decoded is described by a struct
* AsnDecodeSequenceItem, see above. * AsnDecodeSequenceItem, see above.
...@@ -2363,72 +2643,19 @@ static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType, ...@@ -2363,72 +2643,19 @@ static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
{ {
BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); DWORD i;
DWORD i, bytesNeeded = 0, minSize = 0;
const BYTE *ptr;
ptr = pbEncoded + 1 + lenBytes; ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem, pbEncoded,
for (i = 0; ret && i < cItem; i++) cbEncoded, dwFlags, NULL, NULL);
if (ret)
{ {
DWORD nextItemLen; DWORD bytesNeeded = 0, structSize = 0;
minSize += items[i].minSize; for (i = 0; i < cItem; i++)
if (cbEncoded - (ptr - pbEncoded) != 0)
{ {
if ((ret = CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded), bytesNeeded += items[i].size;
&nextItemLen))) structSize += items[i].minSize;
{
BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
if (items[i].decodeFunc)
{
TRACE("sizing item %ld\n", i);
ret = items[i].decodeFunc(dwCertEncodingType, NULL,
ptr, 1 + nextItemLenBytes + nextItemLen,
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL,
&items[i].size);
if (ret)
{
/* Account for alignment padding */
bytesNeeded += items[i].size;
if (items[i].size % sizeof(DWORD))
bytesNeeded += sizeof(DWORD) -
items[i].size % sizeof(DWORD);
ptr += 1 + nextItemLenBytes + nextItemLen;
}
else if (items[i].optional &&
GetLastError() == CRYPT_E_ASN1_BADTAG)
{
TRACE("skipping optional item %ld\n", i);
bytesNeeded += items[i].minSize;
SetLastError(NOERROR);
ret = TRUE;
}
else
TRACE("item %ld failed: %08lx\n", i,
GetLastError());
}
else
bytesNeeded += items[i].minSize;
}
} }
else if (items[i].optional)
bytesNeeded += items[i].minSize;
else
{
SetLastError(CRYPT_E_ASN1_CORRUPT);
ret = FALSE;
}
}
if (cbEncoded - (ptr - pbEncoded) != 0)
{
TRACE("%ld remaining bytes, failing\n", cbEncoded -
(ptr - pbEncoded));
SetLastError(CRYPT_E_ASN1_CORRUPT);
ret = FALSE;
}
if (ret)
{
if (!pvStructInfo) if (!pvStructInfo)
*pcbStructInfo = bytesNeeded; *pcbStructInfo = bytesNeeded;
else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags, else if ((ret = CRYPT_DecodeEnsureSpace(dwFlags,
...@@ -2441,69 +2668,10 @@ static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType, ...@@ -2441,69 +2668,10 @@ static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
if (startingPointer) if (startingPointer)
nextData = (BYTE *)startingPointer; nextData = (BYTE *)startingPointer;
else else
nextData = (BYTE *)pvStructInfo + minSize; nextData = (BYTE *)pvStructInfo + structSize;
memset(pvStructInfo, 0, minSize); memset(pvStructInfo, 0, structSize);
ptr = pbEncoded + 1 + lenBytes; ret = CRYPT_AsnDecodeSequenceItems(dwFlags, items, cItem,
for (i = 0; ret && i < cItem; i++) pbEncoded, cbEncoded, dwFlags, pvStructInfo, nextData);
{
if (cbEncoded - (ptr - pbEncoded) != 0)
{
DWORD nextItemLen;
BYTE nextItemLenBytes = GET_LEN_BYTES(ptr[1]);
CRYPT_GetLen(ptr, cbEncoded - (ptr - pbEncoded),
&nextItemLen);
if (items[i].hasPointer)
{
TRACE("Setting next pointer to %p\n", nextData);
*(BYTE **)((BYTE *)pvStructInfo +
items[i].pointerOffset) = nextData;
}
if (items[i].decodeFunc)
{
TRACE("decoding item %ld, offset %ld (%p)\n",
i, items[i].offset,
(BYTE *)pvStructInfo + items[i].offset);
ret = items[i].decodeFunc(dwCertEncodingType,
NULL, ptr, 1 + nextItemLenBytes + nextItemLen,
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL,
(BYTE *)pvStructInfo + items[i].offset,
&items[i].size);
if (!ret)
TRACE("item %ld failed: %08lx\n", i,
GetLastError());
}
else
items[i].size = items[i].minSize;
if (ret)
{
if (items[i].hasPointer &&
items[i].size > items[i].minSize)
{
nextData += items[i].size -
items[i].minSize;
/* align nextData to DWORD boundaries */
if (items[i].size % sizeof(DWORD))
{
nextData += sizeof(DWORD) -
items[i].size % sizeof(DWORD);
}
}
ptr += 1 + nextItemLenBytes + nextItemLen;
}
else if (items[i].optional &&
GetLastError() == CRYPT_E_ASN1_BADTAG)
{
SetLastError(NOERROR);
ret = TRUE;
}
}
else if (!items[i].optional)
{
SetLastError(CRYPT_E_ASN1_CORRUPT);
ret = FALSE;
}
}
} }
} }
} }
...@@ -2790,14 +2958,14 @@ static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType, ...@@ -2790,14 +2958,14 @@ static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
__TRY __TRY
{ {
struct AsnDecodeSequenceItem items[] = { struct AsnDecodeSequenceItem items[] = {
{ offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned), { 0, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned),
CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE, CRYPT_AsnDecodeDerBlob, sizeof(CRYPT_DER_BLOB), FALSE, TRUE,
offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 }, offsetof(CERT_SIGNED_CONTENT_INFO, ToBeSigned.pbData), 0 },
{ offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm), { ASN_SEQUENCEOF, offsetof(CERT_SIGNED_CONTENT_INFO,
CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER), SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId,
FALSE, TRUE, offsetof(CERT_SIGNED_CONTENT_INFO, sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE,
SignatureAlgorithm.pszObjId), 0 }, offsetof(CERT_SIGNED_CONTENT_INFO, SignatureAlgorithm.pszObjId), 0 },
{ offsetof(CERT_SIGNED_CONTENT_INFO, Signature), { ASN_BITSTRING, offsetof(CERT_SIGNED_CONTENT_INFO, Signature),
CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE, CRYPT_AsnDecodeBitsSwapBytes, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 }, offsetof(CERT_SIGNED_CONTENT_INFO, Signature.pbData), 0 },
}; };
...@@ -2817,29 +2985,21 @@ static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType, ...@@ -2817,29 +2985,21 @@ static BOOL WINAPI CRYPT_AsnDecodeCert(DWORD dwCertEncodingType,
return ret; return ret;
} }
/* Internal function */
static BOOL WINAPI CRYPT_AsnDecodeCertVersion(DWORD dwCertEncodingType, static BOOL WINAPI CRYPT_AsnDecodeCertVersion(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)
{ {
BOOL ret; BOOL ret;
DWORD dataLen;
if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR)) if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
{ {
DWORD dataLen; BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
{
BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER, ret = CRYPT_AsnDecodeInt(dwCertEncodingType, X509_INTEGER,
pbEncoded + 1 + lenBytes, dataLen, dwFlags, pDecodePara, pbEncoded + 1 + lenBytes, dataLen, dwFlags, pDecodePara,
pvStructInfo, pcbStructInfo); pvStructInfo, pcbStructInfo);
}
}
else
{
SetLastError(CRYPT_E_ASN1_BADTAG);
ret = FALSE;
} }
return ret; return ret;
} }
...@@ -2851,9 +3011,9 @@ static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType, ...@@ -2851,9 +3011,9 @@ static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType,
BOOL ret; BOOL ret;
struct AsnDecodeSequenceItem items[] = { struct AsnDecodeSequenceItem items[] = {
{ offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore), { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotBefore),
CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 }, CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
{ offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter), { 0, offsetof(CERT_PRIVATE_KEY_VALIDITY, NotAfter),
CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 }, CRYPT_AsnDecodeChoiceOfTime, sizeof(FILETIME), FALSE, FALSE, 0 },
}; };
...@@ -2863,29 +3023,21 @@ static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType, ...@@ -2863,29 +3023,21 @@ static BOOL WINAPI CRYPT_AsnDecodeValidity(DWORD dwCertEncodingType,
return ret; return ret;
} }
/* Internal function */
static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(DWORD dwCertEncodingType, static BOOL WINAPI CRYPT_AsnDecodeCertExtensions(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)
{ {
BOOL ret; BOOL ret;
DWORD dataLen;
if (pbEncoded[0] == (ASN_CONTEXT | ASN_CONSTRUCTOR | 3)) if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
{ {
DWORD dataLen; BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
{
BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType, ret = CRYPT_AsnDecodeExtensionsInternal(dwCertEncodingType,
X509_EXTENSIONS, pbEncoded + 1 + lenBytes, dataLen, dwFlags, X509_EXTENSIONS, pbEncoded + 1 + lenBytes, dataLen, dwFlags,
pDecodePara, pvStructInfo, pcbStructInfo); pDecodePara, pvStructInfo, pcbStructInfo);
}
}
else
{
SetLastError(CRYPT_E_ASN1_BADTAG);
ret = FALSE;
} }
return ret; return ret;
} }
...@@ -2902,34 +3054,39 @@ static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType, ...@@ -2902,34 +3054,39 @@ static BOOL WINAPI CRYPT_AsnDecodeCertInfo(DWORD dwCertEncodingType,
__TRY __TRY
{ {
struct AsnDecodeSequenceItem items[] = { struct AsnDecodeSequenceItem items[] = {
{ offsetof(CERT_INFO, dwVersion), CRYPT_AsnDecodeCertVersion, { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CERT_INFO, dwVersion),
sizeof(DWORD), TRUE, FALSE, 0, 0 }, CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
{ offsetof(CERT_INFO, SerialNumber), CRYPT_AsnDecodeIntegerInternal, { ASN_INTEGER, offsetof(CERT_INFO, SerialNumber),
sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE, offsetof(CERT_INFO, CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE,
SerialNumber.pbData), 0 }, TRUE, offsetof(CERT_INFO, SerialNumber.pbData), 0 },
{ offsetof(CERT_INFO, SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId, { ASN_SEQUENCEOF, offsetof(CERT_INFO, SignatureAlgorithm),
sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, offsetof(CERT_INFO, CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
SignatureAlgorithm.pszObjId), 0 }, FALSE, TRUE, offsetof(CERT_INFO, SignatureAlgorithm.pszObjId), 0 },
{ offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob, { 0, offsetof(CERT_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO, sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
Issuer.pbData) }, Issuer.pbData) },
{ offsetof(CERT_INFO, NotBefore), CRYPT_AsnDecodeValidity, { ASN_SEQUENCEOF, offsetof(CERT_INFO, NotBefore),
sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE, FALSE, 0 }, CRYPT_AsnDecodeValidity, sizeof(CERT_PRIVATE_KEY_VALIDITY), FALSE,
{ offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob, FALSE, 0 },
{ 0, offsetof(CERT_INFO, Subject), CRYPT_AsnDecodeDerBlob,
sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO, sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CERT_INFO,
Subject.pbData) }, Subject.pbData) },
{ offsetof(CERT_INFO, SubjectPublicKeyInfo), CRYPT_AsnDecodePubKeyInfo, /* jil FIXME: shouldn't this have an internal version, which expects
sizeof(CERT_PUBLIC_KEY_INFO), FALSE, TRUE, offsetof(CERT_INFO, * the pbData to be set?
*/
{ ASN_SEQUENCEOF, offsetof(CERT_INFO, SubjectPublicKeyInfo),
CRYPT_AsnDecodePubKeyInfo, sizeof(CERT_PUBLIC_KEY_INFO), FALSE,
TRUE, offsetof(CERT_INFO,
SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 }, SubjectPublicKeyInfo.Algorithm.Parameters.pbData), 0 },
{ offsetof(CERT_INFO, IssuerUniqueId), CRYPT_AsnDecodeBitsInternal, { ASN_BITSTRING, offsetof(CERT_INFO, IssuerUniqueId),
sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CERT_INFO, CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
IssuerUniqueId.pbData), 0 }, offsetof(CERT_INFO, IssuerUniqueId.pbData), 0 },
{ offsetof(CERT_INFO, SubjectUniqueId), CRYPT_AsnDecodeBitsInternal, { ASN_BITSTRING, offsetof(CERT_INFO, SubjectUniqueId),
sizeof(CRYPT_BIT_BLOB), TRUE, TRUE, offsetof(CERT_INFO, CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
SubjectUniqueId.pbData), 0 }, offsetof(CERT_INFO, SubjectUniqueId.pbData), 0 },
{ offsetof(CERT_INFO, cExtension), CRYPT_AsnDecodeCertExtensions, { ASN_CONTEXT | ASN_CONSTRUCTOR | 3, offsetof(CERT_INFO, cExtension),
sizeof(CERT_EXTENSIONS), TRUE, TRUE, offsetof(CERT_INFO, CRYPT_AsnDecodeCertExtensions, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
rgExtension), 0 }, offsetof(CERT_INFO, rgExtension), 0 },
}; };
ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items, ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
...@@ -2951,14 +3108,14 @@ static BOOL WINAPI CRYPT_AsnDecodeCRLEntry(DWORD dwCertEncodingType, ...@@ -2951,14 +3108,14 @@ static BOOL WINAPI CRYPT_AsnDecodeCRLEntry(DWORD dwCertEncodingType,
{ {
BOOL ret; BOOL ret;
struct AsnDecodeSequenceItem items[] = { struct AsnDecodeSequenceItem items[] = {
{ offsetof(CRL_ENTRY, SerialNumber), CRYPT_AsnDecodeIntegerInternal, { ASN_INTEGER, offsetof(CRL_ENTRY, SerialNumber),
sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE, offsetof(CRL_ENTRY, CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), FALSE, TRUE,
SerialNumber.pbData), 0 }, offsetof(CRL_ENTRY, SerialNumber.pbData), 0 },
{ offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTime, { 0, offsetof(CRL_ENTRY, RevocationDate), CRYPT_AsnDecodeChoiceOfTime,
sizeof(FILETIME), FALSE, FALSE, 0 }, sizeof(FILETIME), FALSE, FALSE, 0 },
{ offsetof(CRL_ENTRY, cExtension), CRYPT_AsnDecodeExtensionsInternal, { ASN_SEQUENCEOF, offsetof(CRL_ENTRY, cExtension),
sizeof(CERT_EXTENSIONS), TRUE, TRUE, offsetof(CRL_ENTRY, CRYPT_AsnDecodeExtensionsInternal, sizeof(CERT_EXTENSIONS), TRUE, TRUE,
rgExtension), 0 }, offsetof(CRL_ENTRY, rgExtension), 0 },
}; };
PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo; PCRL_ENTRY entry = (PCRL_ENTRY)pvStructInfo;
...@@ -2971,12 +3128,7 @@ static BOOL WINAPI CRYPT_AsnDecodeCRLEntry(DWORD dwCertEncodingType, ...@@ -2971,12 +3128,7 @@ static BOOL WINAPI CRYPT_AsnDecodeCRLEntry(DWORD dwCertEncodingType,
return ret; return ret;
} }
typedef struct _WINE_CRL_ENTRIES { /* Warning: assumes pvStructInfo is a struct GenericArray whose rgItems has
DWORD cCRLEntry;
PCRL_ENTRY rgCRLEntry;
} WINE_CRL_ENTRIES, *PWINE_CRL_ENTRIES;
/* Warning: assumes pvStructInfo is a WINE_CRL_ENTRIES whose rgCRLEntry has
* been set prior to calling. * been set prior to calling.
*/ */
static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType, static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType,
...@@ -2987,14 +3139,14 @@ static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType, ...@@ -2987,14 +3139,14 @@ static BOOL WINAPI CRYPT_AsnDecodeCRLEntries(DWORD dwCertEncodingType,
struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF, struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE, CRYPT_AsnDecodeCRLEntry, sizeof(CRL_ENTRY), TRUE,
offsetof(CRL_ENTRY, SerialNumber.pbData) }; offsetof(CRL_ENTRY, SerialNumber.pbData) };
PWINE_CRL_ENTRIES entries = (PWINE_CRL_ENTRIES)pvStructInfo; struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
pDecodePara, pvStructInfo, *pcbStructInfo); pDecodePara, pvStructInfo, *pcbStructInfo);
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags, ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
pDecodePara, pvStructInfo, pcbStructInfo, pDecodePara, pvStructInfo, pcbStructInfo,
entries ? entries->rgCRLEntry : NULL); entries ? entries->rgItems : NULL);
TRACE("Returning %d (%08lx)\n", ret, GetLastError()); TRACE("Returning %d (%08lx)\n", ret, GetLastError());
return ret; return ret;
} }
...@@ -3011,24 +3163,24 @@ static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType, ...@@ -3011,24 +3163,24 @@ static BOOL WINAPI CRYPT_AsnDecodeCRLInfo(DWORD dwCertEncodingType,
__TRY __TRY
{ {
struct AsnDecodeSequenceItem items[] = { struct AsnDecodeSequenceItem items[] = {
{ offsetof(CRL_INFO, dwVersion), CRYPT_AsnDecodeCertVersion, { ASN_CONTEXT | ASN_CONSTRUCTOR, offsetof(CRL_INFO, dwVersion),
sizeof(DWORD), TRUE, FALSE, 0, 0 }, CRYPT_AsnDecodeCertVersion, sizeof(DWORD), TRUE, FALSE, 0, 0 },
{ offsetof(CRL_INFO, SignatureAlgorithm), CRYPT_AsnDecodeAlgorithmId, { ASN_SEQUENCEOF, offsetof(CRL_INFO, SignatureAlgorithm),
sizeof(CRYPT_ALGORITHM_IDENTIFIER), FALSE, TRUE, offsetof(CRL_INFO, CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
SignatureAlgorithm.pszObjId), 0 }, FALSE, TRUE, offsetof(CRL_INFO, SignatureAlgorithm.pszObjId), 0 },
{ offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob, { 0, offsetof(CRL_INFO, Issuer), CRYPT_AsnDecodeDerBlob,
sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO, sizeof(CRYPT_DER_BLOB), FALSE, TRUE, offsetof(CRL_INFO,
Issuer.pbData) }, Issuer.pbData) },
{ offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTime, { 0, offsetof(CRL_INFO, ThisUpdate), CRYPT_AsnDecodeChoiceOfTime,
sizeof(FILETIME), FALSE, FALSE, 0 }, sizeof(FILETIME), FALSE, FALSE, 0 },
{ offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTime, { 0, offsetof(CRL_INFO, NextUpdate), CRYPT_AsnDecodeChoiceOfTime,
sizeof(FILETIME), TRUE, FALSE, 0 }, sizeof(FILETIME), TRUE, FALSE, 0 },
{ offsetof(CRL_INFO, cCRLEntry), CRYPT_AsnDecodeCRLEntries, { ASN_SEQUENCEOF, offsetof(CRL_INFO, cCRLEntry),
sizeof(WINE_CRL_ENTRIES), TRUE, TRUE, offsetof(CRL_INFO, CRYPT_AsnDecodeCRLEntries, sizeof(struct GenericArray), TRUE, TRUE,
rgCRLEntry), 0 }, offsetof(CRL_INFO, rgCRLEntry), 0 },
/* Note that the extensions are ignored by MS, so I'll ignore them too /* Note that the extensions are ignored by MS, so I'll ignore them too
*/ */
{ offsetof(CRL_INFO, cExtension), NULL, { 0, offsetof(CRL_INFO, cExtension), NULL,
sizeof(CERT_EXTENSIONS), TRUE, FALSE, 0 }, sizeof(CERT_EXTENSIONS), TRUE, FALSE, 0 },
}; };
...@@ -3079,13 +3231,14 @@ static BOOL WINAPI CRYPT_AsnDecodeExtension(DWORD dwCertEncodingType, ...@@ -3079,13 +3231,14 @@ static BOOL WINAPI CRYPT_AsnDecodeExtension(DWORD dwCertEncodingType,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{ {
struct AsnDecodeSequenceItem items[] = { struct AsnDecodeSequenceItem items[] = {
{ offsetof(CERT_EXTENSION, pszObjId), CRYPT_AsnDecodeOidWrapper, { ASN_OBJECTIDENTIFIER, offsetof(CERT_EXTENSION, pszObjId),
sizeof(LPSTR), FALSE, TRUE, offsetof(CERT_EXTENSION, pszObjId), 0 }, CRYPT_AsnDecodeOidWrapper, sizeof(LPSTR), FALSE, TRUE,
{ offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool, offsetof(CERT_EXTENSION, pszObjId), 0 },
{ ASN_BOOL, offsetof(CERT_EXTENSION, fCritical), CRYPT_AsnDecodeBool,
sizeof(BOOL), TRUE, FALSE, 0, 0 }, sizeof(BOOL), TRUE, FALSE, 0, 0 },
{ offsetof(CERT_EXTENSION, Value), CRYPT_AsnDecodeOctetsInternal, { ASN_OCTETSTRING, offsetof(CERT_EXTENSION, Value),
sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE, offsetof(CERT_EXTENSION, CRYPT_AsnDecodeOctetsInternal, sizeof(CRYPT_OBJID_BLOB), FALSE, TRUE,
Value.pbData) }, offsetof(CERT_EXTENSION, Value.pbData) },
}; };
BOOL ret = TRUE; BOOL ret = TRUE;
PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo; PCERT_EXTENSION ext = (PCERT_EXTENSION)pvStructInfo;
...@@ -3394,9 +3547,10 @@ static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(DWORD dwCertEncodingType, ...@@ -3394,9 +3547,10 @@ static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(DWORD dwCertEncodingType,
__TRY __TRY
{ {
struct AsnDecodeSequenceItem items[] = { struct AsnDecodeSequenceItem items[] = {
{ offsetof(CERT_RDN_ATTR, pszObjId), CRYPT_AsnDecodeOidWrapper, { ASN_OBJECTIDENTIFIER, offsetof(CERT_RDN_ATTR, pszObjId),
sizeof(LPSTR), FALSE, TRUE, offsetof(CERT_RDN_ATTR, pszObjId), 0 }, CRYPT_AsnDecodeOidWrapper, sizeof(LPSTR), FALSE, TRUE,
{ offsetof(CERT_RDN_ATTR, dwValueType), CRYPT_AsnDecodeNameValue, offsetof(CERT_RDN_ATTR, pszObjId), 0 },
{ 0, offsetof(CERT_RDN_ATTR, dwValueType), CRYPT_AsnDecodeNameValue,
sizeof(CERT_NAME_VALUE), FALSE, TRUE, offsetof(CERT_RDN_ATTR, sizeof(CERT_NAME_VALUE), FALSE, TRUE, offsetof(CERT_RDN_ATTR,
Value.pbData), 0 }, Value.pbData), 0 },
}; };
...@@ -3514,10 +3668,10 @@ static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType, ...@@ -3514,10 +3668,10 @@ static BOOL WINAPI CRYPT_AsnDecodeAlgorithmId(DWORD dwCertEncodingType,
(CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo; (CRYPT_ALGORITHM_IDENTIFIER *)pvStructInfo;
BOOL ret = TRUE; BOOL ret = TRUE;
struct AsnDecodeSequenceItem items[] = { struct AsnDecodeSequenceItem items[] = {
{ offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), { ASN_OBJECTIDENTIFIER, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId),
CRYPT_AsnDecodeOidWrapper, sizeof(LPSTR), FALSE, TRUE, CRYPT_AsnDecodeOidWrapper, sizeof(LPSTR), FALSE, TRUE,
offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 }, offsetof(CRYPT_ALGORITHM_IDENTIFIER, pszObjId), 0 },
{ offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters), { 0, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters),
CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE, CRYPT_AsnDecodeCopyBytes, sizeof(CRYPT_OBJID_BLOB), TRUE, TRUE,
offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 }, offsetof(CRYPT_ALGORITHM_IDENTIFIER, Parameters.pbData), 0 },
}; };
...@@ -3545,11 +3699,11 @@ static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType, ...@@ -3545,11 +3699,11 @@ static BOOL WINAPI CRYPT_AsnDecodePubKeyInfo(DWORD dwCertEncodingType,
__TRY __TRY
{ {
struct AsnDecodeSequenceItem items[] = { struct AsnDecodeSequenceItem items[] = {
{ offsetof(CERT_PUBLIC_KEY_INFO, Algorithm), { ASN_SEQUENCEOF, offsetof(CERT_PUBLIC_KEY_INFO, Algorithm),
CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER), CRYPT_AsnDecodeAlgorithmId, sizeof(CRYPT_ALGORITHM_IDENTIFIER),
FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO, FALSE, TRUE, offsetof(CERT_PUBLIC_KEY_INFO,
Algorithm.pszObjId) }, Algorithm.pszObjId) },
{ offsetof(CERT_PUBLIC_KEY_INFO, PublicKey), { ASN_BITSTRING, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey),
CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE, CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) }, offsetof(CERT_PUBLIC_KEY_INFO, PublicKey.pbData) },
}; };
...@@ -3578,11 +3732,6 @@ static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType, ...@@ -3578,11 +3732,6 @@ static BOOL WINAPI CRYPT_AsnDecodeBool(DWORD dwCertEncodingType,
SetLastError(CRYPT_E_ASN1_CORRUPT); SetLastError(CRYPT_E_ASN1_CORRUPT);
return FALSE; return FALSE;
} }
if (pbEncoded[0] != ASN_BOOL)
{
SetLastError(CRYPT_E_ASN1_BADTAG);
return FALSE;
}
if (GET_LEN_BYTES(pbEncoded[1]) > 1) if (GET_LEN_BYTES(pbEncoded[1]) > 1)
{ {
SetLastError(CRYPT_E_ASN1_CORRUPT); SetLastError(CRYPT_E_ASN1_CORRUPT);
...@@ -3696,6 +3845,8 @@ static BOOL WINAPI CRYPT_AsnDecodeAltNameEntry(DWORD dwCertEncodingType, ...@@ -3696,6 +3845,8 @@ static BOOL WINAPI CRYPT_AsnDecodeAltNameEntry(DWORD dwCertEncodingType,
entry->u.pwszURL[i] = entry->u.pwszURL[i] =
(WCHAR)pbEncoded[1 + lenBytes + i]; (WCHAR)pbEncoded[1 + lenBytes + i];
entry->u.pwszURL[i] = 0; entry->u.pwszURL[i] = 0;
TRACE("URL is %p (%s)\n", entry->u.pwszURL,
debugstr_w(entry->u.pwszURL));
break; break;
} }
case 7: /* iPAddress */ case 7: /* iPAddress */
...@@ -3714,6 +3865,26 @@ static BOOL WINAPI CRYPT_AsnDecodeAltNameEntry(DWORD dwCertEncodingType, ...@@ -3714,6 +3865,26 @@ static BOOL WINAPI CRYPT_AsnDecodeAltNameEntry(DWORD dwCertEncodingType,
return ret; return ret;
} }
static BOOL WINAPI CRYPT_AsnDecodeAltNameInternal(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{
BOOL ret = TRUE;
struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
CRYPT_AsnDecodeAltNameEntry, sizeof(CERT_ALT_NAME_ENTRY), TRUE,
offsetof(CERT_ALT_NAME_ENTRY, u.pwszURL) };
PCERT_ALT_NAME_INFO info = (PCERT_ALT_NAME_INFO)pvStructInfo;
TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
pDecodePara, pvStructInfo, *pcbStructInfo);
if (info)
TRACE("info->rgAltEntry is %p\n", info->rgAltEntry);
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
pDecodePara, pvStructInfo, pcbStructInfo, info ? info->rgAltEntry : NULL);
return ret;
}
static BOOL WINAPI CRYPT_AsnDecodeAltName(DWORD dwCertEncodingType, static BOOL WINAPI CRYPT_AsnDecodeAltName(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)
...@@ -3753,6 +3924,9 @@ static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType, ...@@ -3753,6 +3924,9 @@ static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType,
{ {
BOOL ret = TRUE; BOOL ret = TRUE;
TRACE("%p, %ld, %08lx, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
pvStructInfo, *pcbStructInfo);
if (cbEncoded) if (cbEncoded)
{ {
if (pbEncoded[0] == ASN_INTEGER) if (pbEncoded[0] == ASN_INTEGER)
...@@ -3801,11 +3975,11 @@ static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType, ...@@ -3801,11 +3975,11 @@ static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
__TRY __TRY
{ {
struct AsnDecodeSequenceItem items[] = { struct AsnDecodeSequenceItem items[] = {
{ offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA), CRYPT_AsnDecodeBool, { ASN_BOOL, offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fCA),
sizeof(BOOL), TRUE, FALSE, 0, 0 }, CRYPT_AsnDecodeBool, sizeof(BOOL), TRUE, FALSE, 0, 0 },
{ offsetof(CERT_BASIC_CONSTRAINTS2_INFO, fPathLenConstraint), { ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS2_INFO,
CRYPT_AsnDecodePathLenConstraint, sizeof(struct PATH_LEN_CONSTRAINT), fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
TRUE, FALSE, 0, 0 }, sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
}; };
ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items, ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
...@@ -3838,11 +4012,11 @@ static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType, ...@@ -3838,11 +4012,11 @@ static BOOL WINAPI CRYPT_AsnDecodeRsaPubKey(DWORD dwCertEncodingType,
__TRY __TRY
{ {
struct AsnDecodeSequenceItem items[] = { struct AsnDecodeSequenceItem items[] = {
{ offsetof(struct DECODED_RSA_PUB_KEY, modulus), { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, modulus),
CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB), CRYPT_AsnDecodeUnsignedIntegerInternal, sizeof(CRYPT_INTEGER_BLOB),
FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData), FALSE, TRUE, offsetof(struct DECODED_RSA_PUB_KEY, modulus.pbData),
0 }, 0 },
{ offsetof(struct DECODED_RSA_PUB_KEY, pubexp), { ASN_INTEGER, offsetof(struct DECODED_RSA_PUB_KEY, pubexp),
CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 }, CRYPT_AsnDecodeInt, sizeof(DWORD), FALSE, FALSE, 0, 0 },
}; };
struct DECODED_RSA_PUB_KEY *decodedKey = NULL; struct DECODED_RSA_PUB_KEY *decodedKey = NULL;
...@@ -3900,52 +4074,43 @@ static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType, ...@@ -3900,52 +4074,43 @@ static BOOL WINAPI CRYPT_AsnDecodeOctetsInternal(DWORD dwCertEncodingType,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{ {
BOOL ret; BOOL ret;
DWORD bytesNeeded, dataLen;
TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags, TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
pDecodePara, pvStructInfo, *pcbStructInfo); pDecodePara, pvStructInfo, *pcbStructInfo);
if (pbEncoded[0] == ASN_OCTETSTRING) if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
{ {
DWORD bytesNeeded, dataLen; if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
bytesNeeded = sizeof(CRYPT_DATA_BLOB);
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen))) else
bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
if (!pvStructInfo)
*pcbStructInfo = bytesNeeded;
else if (*pcbStructInfo < bytesNeeded)
{ {
SetLastError(ERROR_MORE_DATA);
*pcbStructInfo = bytesNeeded;
ret = FALSE;
}
else
{
CRYPT_DATA_BLOB *blob;
BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
blob = (CRYPT_DATA_BLOB *)pvStructInfo;
blob->cbData = dataLen;
if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG) if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
bytesNeeded = sizeof(CRYPT_DATA_BLOB); blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
else
bytesNeeded = dataLen + sizeof(CRYPT_DATA_BLOB);
if (!pvStructInfo)
*pcbStructInfo = bytesNeeded;
else if (*pcbStructInfo < bytesNeeded)
{
SetLastError(ERROR_MORE_DATA);
*pcbStructInfo = bytesNeeded;
ret = FALSE;
}
else else
{ {
CRYPT_DATA_BLOB *blob; assert(blob->pbData);
BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]); if (blob->cbData)
memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
blob = (CRYPT_DATA_BLOB *)pvStructInfo; blob->cbData);
blob->cbData = dataLen;
if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
blob->pbData = (BYTE *)pbEncoded + 1 + lenBytes;
else
{
assert(blob->pbData);
if (blob->cbData)
memcpy(blob->pbData, pbEncoded + 1 + lenBytes,
blob->cbData);
}
} }
} }
} }
else
{
SetLastError(CRYPT_E_ASN1_BADTAG);
ret = FALSE;
}
return ret; return ret;
} }
...@@ -3962,7 +4127,17 @@ static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType, ...@@ -3962,7 +4127,17 @@ static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
{ {
DWORD bytesNeeded; DWORD bytesNeeded;
if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType, if (!cbEncoded)
{
SetLastError(CRYPT_E_ASN1_CORRUPT);
ret = FALSE;
}
else if (pbEncoded[0] != ASN_OCTETSTRING)
{
SetLastError(CRYPT_E_ASN1_BADTAG);
ret = FALSE;
}
else if ((ret = CRYPT_AsnDecodeOctetsInternal(dwCertEncodingType,
lpszStructType, pbEncoded, cbEncoded, lpszStructType, pbEncoded, cbEncoded,
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded))) dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, &bytesNeeded)))
{ {
...@@ -3983,11 +4158,6 @@ static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType, ...@@ -3983,11 +4158,6 @@ static BOOL WINAPI CRYPT_AsnDecodeOctets(DWORD dwCertEncodingType,
&bytesNeeded); &bytesNeeded);
} }
} }
else
{
SetLastError(CRYPT_E_ASN1_BADTAG);
ret = FALSE;
}
} }
__EXCEPT(page_fault) __EXCEPT(page_fault)
{ {
...@@ -4830,6 +5000,57 @@ static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType, ...@@ -4830,6 +5000,57 @@ static BOOL WINAPI CRYPT_AsnDecodeSequenceOfAny(DWORD dwCertEncodingType,
return ret; return ret;
} }
static BOOL WINAPI CRYPT_AsnDecodeDistPoint(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{
struct AsnDecodeSequenceItem items[] = {
{ ASN_CONTEXT | ASN_CONSTRUCTOR | 0, offsetof(CRL_DIST_POINT,
DistPointName), CRYPT_AsnDecodeAltNameInternal,
sizeof(CRL_DIST_POINT_NAME), TRUE, TRUE, offsetof(CRL_DIST_POINT,
DistPointName.u.FullName.rgAltEntry), 0 },
{ ASN_CONTEXT | 1, offsetof(CRL_DIST_POINT, ReasonFlags),
CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), TRUE, TRUE,
offsetof(CRL_DIST_POINT, ReasonFlags.pbData), 0 },
{ ASN_CONTEXT | ASN_CONSTRUCTOR | 2, offsetof(CRL_DIST_POINT, CRLIssuer),
CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE, TRUE,
offsetof(CRL_DIST_POINT, CRLIssuer.rgAltEntry), 0 },
};
BOOL ret;
ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded,
dwFlags, pDecodePara, pvStructInfo, pcbStructInfo, NULL);
return ret;
}
static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
{
BOOL ret;
TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
pDecodePara, pvStructInfo, *pcbStructInfo);
__TRY
{
struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
CRYPT_AsnDecodeDistPoint, sizeof(CRL_DIST_POINT), TRUE,
offsetof(CRL_DIST_POINT, DistPointName.u.FullName.rgAltEntry) };
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
pDecodePara, pvStructInfo, pcbStructInfo, NULL);
}
__EXCEPT(page_fault)
{
SetLastError(STATUS_ACCESS_VIOLATION);
ret = FALSE;
}
__ENDTRY
return ret;
}
BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType, BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo) PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
...@@ -4927,6 +5148,9 @@ BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType, ...@@ -4927,6 +5148,9 @@ BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
case (WORD)PKCS_UTC_TIME: case (WORD)PKCS_UTC_TIME:
decodeFunc = CRYPT_AsnDecodeUtcTime; decodeFunc = CRYPT_AsnDecodeUtcTime;
break; break;
case (WORD)X509_CRL_DIST_POINTS:
decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
break;
default: default:
FIXME("%d: unimplemented\n", LOWORD(lpszStructType)); FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
} }
......
...@@ -1379,14 +1379,15 @@ static void test_decodeBasicConstraints(DWORD dwEncoding) ...@@ -1379,14 +1379,15 @@ static void test_decodeBasicConstraints(DWORD dwEncoding)
ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2, ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
constraints2[i].encoded, constraints2[i].encoded[1] + 2, constraints2[i].encoded, constraints2[i].encoded[1] + 2,
CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize); CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError()); ok(ret, "CryptDecodeObjectEx failed for item %ld: %08lx\n", i,
GetLastError());
if (buf) if (buf)
{ {
CERT_BASIC_CONSTRAINTS2_INFO *info = CERT_BASIC_CONSTRAINTS2_INFO *info =
(CERT_BASIC_CONSTRAINTS2_INFO *)buf; (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
ok(!memcmp(info, &constraints2[i].info, sizeof(*info)), ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
"Unexpected value\n"); "Unexpected value for item %ld\n", i);
LocalFree(buf); LocalFree(buf);
} }
} }
...@@ -2222,6 +2223,227 @@ static void test_decodeCert(DWORD dwEncoding) ...@@ -2222,6 +2223,227 @@ static void test_decodeCert(DWORD dwEncoding)
} }
} }
static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
0x00, 0x03 };
static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
0x2e, 0x6f, 0x72, 0x67 };
static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
CRL_REASON_AFFILIATION_CHANGED;
static void test_encodeCRLDistPoints(DWORD dwEncoding)
{
CRL_DIST_POINTS_INFO info = { 0 };
CRL_DIST_POINT point = { { 0 } };
CERT_ALT_NAME_ENTRY entry = { 0 };
BOOL ret;
BYTE *buf = NULL;
DWORD size = 0;
/* Test with an empty info */
ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
"Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
GetLastError());
/* Test with one empty dist point */
info.cDistPoint = 1;
info.rgDistPoint = &point;
ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
if (buf)
{
ok(size == sizeof(emptyDistPoint), "Expected size %d, got %ld\n",
sizeof(emptyDistPoint), size);
ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
LocalFree(buf);
}
/* A dist point with an invalid name */
point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
entry.dwAltNameChoice = CERT_ALT_NAME_URL;
entry.pwszURL = (LPWSTR)nihongoURL;
point.DistPointName.FullName.cAltEntry = 1;
point.DistPointName.FullName.rgAltEntry = &entry;
ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
"Expected CRYPT_E_INVALID_IA5_STRING, got %08lx\n", GetLastError());
/* The first invalid character is at index 7 */
ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
"Expected invalid char at index 7, got %ld\n",
GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
/* A dist point with (just) a valid name */
entry.pwszURL = (LPWSTR)url;
ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
if (buf)
{
ok(size == sizeof(distPointWithUrl), "Expected size %d, got %ld\n",
sizeof(distPointWithUrl), size);
ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
LocalFree(buf);
}
/* A dist point with (just) reason flags */
point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
point.ReasonFlags.cbData = sizeof(crlReason);
point.ReasonFlags.pbData = (LPBYTE)&crlReason;
ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
if (buf)
{
ok(size == sizeof(distPointWithReason), "Expected size %d, got %ld\n",
sizeof(distPointWithReason), size);
ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
LocalFree(buf);
}
/* A dist point with just an issuer */
point.ReasonFlags.cbData = 0;
point.CRLIssuer.cAltEntry = 1;
point.CRLIssuer.rgAltEntry = &entry;
ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
if (buf)
{
ok(size == sizeof(distPointWithIssuer), "Expected size %d, got %ld\n",
sizeof(distPointWithIssuer), size);
ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
LocalFree(buf);
}
/* A dist point with both a name and an issuer */
point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
if (buf)
{
ok(size == sizeof(distPointWithUrlAndIssuer),
"Expected size %d, got %ld\n", sizeof(distPointWithUrlAndIssuer),
size);
ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
LocalFree(buf);
}
}
static void test_decodeCRLDistPoints(DWORD dwEncoding)
{
BOOL ret;
BYTE *buf = NULL;
DWORD size = 0;
PCRL_DIST_POINTS_INFO info;
PCRL_DIST_POINT point;
PCERT_ALT_NAME_ENTRY entry;
ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
(BYTE *)&buf, &size);
if (ret)
{
info = (PCRL_DIST_POINTS_INFO)buf;
ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
"Expected size at least %d, got %ld\n",
sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT), size);
ok(info->cDistPoint == 1, "Expected 1 dist points, got %ld\n",
info->cDistPoint);
point = info->rgDistPoint;
ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
"Expected CRL_DIST_POINT_NO_NAME, got %ld\n",
point->DistPointName.dwDistPointNameChoice);
ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
LocalFree(buf);
}
ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
(BYTE *)&buf, &size);
if (ret)
{
info = (PCRL_DIST_POINTS_INFO)buf;
ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
"Expected size at least %d, got %ld\n",
sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT), size);
ok(info->cDistPoint == 1, "Expected 1 dist points, got %ld\n",
info->cDistPoint);
point = info->rgDistPoint;
ok(point->DistPointName.dwDistPointNameChoice ==
CRL_DIST_POINT_FULL_NAME,
"Expected CRL_DIST_POINT_FULL_NAME, got %ld\n",
point->DistPointName.dwDistPointNameChoice);
ok(point->DistPointName.FullName.cAltEntry == 1,
"Expected 1 name entry, got %ld\n",
point->DistPointName.FullName.cAltEntry);
entry = point->DistPointName.FullName.rgAltEntry;
ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
"Expected CERT_ALT_NAME_URL, got %ld\n", entry->dwAltNameChoice);
ok(!lstrcmpW(entry->pwszURL, url), "Unexpected name\n");
ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
LocalFree(buf);
}
ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
NULL, (BYTE *)&buf, &size);
if (ret)
{
info = (PCRL_DIST_POINTS_INFO)buf;
ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
"Expected size at least %d, got %ld\n",
sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT), size);
ok(info->cDistPoint == 1, "Expected 1 dist points, got %ld\n",
info->cDistPoint);
point = info->rgDistPoint;
ok(point->DistPointName.dwDistPointNameChoice ==
CRL_DIST_POINT_NO_NAME,
"Expected CRL_DIST_POINT_NO_NAME, got %ld\n",
point->DistPointName.dwDistPointNameChoice);
ok(point->ReasonFlags.cbData == sizeof(crlReason),
"Expected reason length\n");
ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
"Unexpected reason\n");
ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
LocalFree(buf);
}
ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
if (ret)
{
info = (PCRL_DIST_POINTS_INFO)buf;
ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
"Expected size at least %d, got %ld\n",
sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT), size);
ok(info->cDistPoint == 1, "Expected 1 dist points, got %ld\n",
info->cDistPoint);
point = info->rgDistPoint;
ok(point->DistPointName.dwDistPointNameChoice ==
CRL_DIST_POINT_FULL_NAME,
"Expected CRL_DIST_POINT_FULL_NAME, got %ld\n",
point->DistPointName.dwDistPointNameChoice);
ok(point->DistPointName.FullName.cAltEntry == 1,
"Expected 1 name entry, got %ld\n",
point->DistPointName.FullName.cAltEntry);
entry = point->DistPointName.FullName.rgAltEntry;
ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
"Expected CERT_ALT_NAME_URL, got %ld\n", entry->dwAltNameChoice);
ok(!lstrcmpW(entry->pwszURL, url), "Unexpected name\n");
ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
ok(point->CRLIssuer.cAltEntry == 1,
"Expected 1 issuer entry, got %ld\n", point->CRLIssuer.cAltEntry);
entry = point->CRLIssuer.rgAltEntry;
ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
"Expected CERT_ALT_NAME_URL, got %ld\n", entry->dwAltNameChoice);
ok(!lstrcmpW(entry->pwszURL, url), "Unexpected name\n");
LocalFree(buf);
}
}
static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f, static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x5a }; 0x30, 0x5a };
...@@ -2594,6 +2816,8 @@ START_TEST(encode) ...@@ -2594,6 +2816,8 @@ START_TEST(encode)
test_decodeCertToBeSigned(encodings[i]); test_decodeCertToBeSigned(encodings[i]);
test_encodeCert(encodings[i]); test_encodeCert(encodings[i]);
test_decodeCert(encodings[i]); test_decodeCert(encodings[i]);
test_encodeCRLDistPoints(encodings[i]);
test_decodeCRLDistPoints(encodings[i]);
test_encodeCRLToBeSigned(encodings[i]); test_encodeCRLToBeSigned(encodings[i]);
test_decodeCRLToBeSigned(encodings[i]); test_decodeCRLToBeSigned(encodings[i]);
} }
......
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