crypt32: More encoding/decoding.
Add support for encoding/decoding basic constraints and enhanced key usage, with tests.
This commit is contained in:
parent
15e5dc29c1
commit
11fe62de8f
|
@ -70,6 +70,12 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(crypt);
|
||||
|
||||
struct GenericArray
|
||||
{
|
||||
DWORD cItems;
|
||||
BYTE *rgItems;
|
||||
};
|
||||
|
||||
typedef BOOL (WINAPI *CryptEncodeObjectFunc)(DWORD, LPCSTR, const void *,
|
||||
BYTE *, DWORD *);
|
||||
typedef BOOL (WINAPI *CryptEncodeObjectExFunc)(DWORD, LPCSTR, const void *,
|
||||
|
@ -91,6 +97,9 @@ static BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
|
|||
static BOOL WINAPI CRYPT_AsnEncodeExtensions(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
|
||||
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
|
||||
static BOOL WINAPI CRYPT_AsnEncodeSequenceOfAny(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
|
||||
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
|
||||
static BOOL WINAPI CRYPT_AsnEncodeBool(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
|
||||
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded);
|
||||
|
@ -1442,6 +1451,46 @@ static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
|
||||
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
__TRY
|
||||
{
|
||||
const CERT_BASIC_CONSTRAINTS_INFO *info =
|
||||
(const CERT_BASIC_CONSTRAINTS_INFO *)pvStructInfo;
|
||||
struct AsnEncodeSequenceItem items[3] = {
|
||||
{ &info->SubjectType, CRYPT_AsnEncodeBits, 0 },
|
||||
{ 0 }
|
||||
};
|
||||
DWORD cItem = 1;
|
||||
|
||||
if (info->fPathLenConstraint)
|
||||
{
|
||||
items[cItem].pvStructInfo = &info->dwPathLenConstraint;
|
||||
items[cItem].encodeFunc = CRYPT_AsnEncodeInt;
|
||||
cItem++;
|
||||
}
|
||||
if (info->cSubtreesConstraint)
|
||||
{
|
||||
items[cItem].pvStructInfo = &info->cSubtreesConstraint;
|
||||
items[cItem].encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
|
||||
cItem++;
|
||||
}
|
||||
ret = CRYPT_AsnEncodeSequence(dwCertEncodingType, items, cItem,
|
||||
dwFlags, pEncodePara, pbEncoded, pcbEncoded);
|
||||
}
|
||||
__EXCEPT_PAGE_FAULT
|
||||
{
|
||||
SetLastError(STATUS_ACCESS_VIOLATION);
|
||||
ret = FALSE;
|
||||
}
|
||||
__ENDTRY
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints2(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
|
||||
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
|
||||
|
@ -2191,6 +2240,70 @@ static BOOL WINAPI CRYPT_AsnEncodeCRLDistPoints(DWORD dwCertEncodingType,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnEncodeEnhancedKeyUsage(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
|
||||
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
__TRY
|
||||
{
|
||||
const CERT_ENHKEY_USAGE *usage =
|
||||
(const CERT_ENHKEY_USAGE *)pvStructInfo;
|
||||
DWORD bytesNeeded = 0, lenBytes, size, i;
|
||||
|
||||
ret = TRUE;
|
||||
for (i = 0; ret && i < usage->cUsageIdentifier; i++)
|
||||
{
|
||||
ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
|
||||
usage->rgpszUsageIdentifier[i],
|
||||
dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, NULL, &size);
|
||||
if (ret)
|
||||
bytesNeeded += size;
|
||||
}
|
||||
CRYPT_EncodeLen(bytesNeeded, NULL, &lenBytes);
|
||||
bytesNeeded += 1 + lenBytes;
|
||||
if (ret)
|
||||
{
|
||||
if (!pbEncoded)
|
||||
*pcbEncoded = bytesNeeded;
|
||||
else
|
||||
{
|
||||
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
|
||||
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 < usage->cUsageIdentifier; i++)
|
||||
{
|
||||
size = bytesNeeded;
|
||||
ret = CRYPT_AsnEncodeOid(dwCertEncodingType, NULL,
|
||||
usage->rgpszUsageIdentifier[i],
|
||||
dwFlags & ~CRYPT_ENCODE_ALLOC_FLAG, NULL, pbEncoded,
|
||||
&size);
|
||||
if (ret)
|
||||
{
|
||||
pbEncoded += size;
|
||||
bytesNeeded -= size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
__EXCEPT_PAGE_FAULT
|
||||
{
|
||||
SetLastError(STATUS_ACCESS_VIOLATION);
|
||||
ret = FALSE;
|
||||
}
|
||||
__ENDTRY
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
|
||||
const void *pvStructInfo, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara,
|
||||
void *pvEncoded, DWORD *pcbEncoded)
|
||||
|
@ -2244,6 +2357,9 @@ BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
|
|||
case (WORD)X509_ALTERNATE_NAME:
|
||||
encodeFunc = CRYPT_AsnEncodeAltName;
|
||||
break;
|
||||
case (WORD)X509_BASIC_CONSTRAINTS:
|
||||
encodeFunc = CRYPT_AsnEncodeBasicConstraints;
|
||||
break;
|
||||
case (WORD)X509_BASIC_CONSTRAINTS2:
|
||||
encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
|
||||
break;
|
||||
|
@ -2281,6 +2397,9 @@ BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
|
|||
case (WORD)X509_CRL_DIST_POINTS:
|
||||
encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
|
||||
break;
|
||||
case (WORD)X509_ENHANCED_KEY_USAGE:
|
||||
encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
|
||||
break;
|
||||
default:
|
||||
FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
|
||||
}
|
||||
|
@ -2295,6 +2414,8 @@ BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
|
|||
encodeFunc = CRYPT_AsnEncodeBits;
|
||||
else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
|
||||
encodeFunc = CRYPT_AsnEncodeOctets;
|
||||
else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
|
||||
encodeFunc = CRYPT_AsnEncodeBasicConstraints;
|
||||
else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
|
||||
encodeFunc = CRYPT_AsnEncodeBasicConstraints2;
|
||||
else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
|
||||
|
@ -2307,6 +2428,10 @@ BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
|
|||
encodeFunc = CRYPT_AsnEncodeAltName;
|
||||
else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
|
||||
encodeFunc = CRYPT_AsnEncodeAltName;
|
||||
else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
|
||||
encodeFunc = CRYPT_AsnEncodeCRLDistPoints;
|
||||
else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
|
||||
encodeFunc = CRYPT_AsnEncodeEnhancedKeyUsage;
|
||||
else
|
||||
TRACE("OID %s not found or unimplemented, looking for DLL\n",
|
||||
debugstr_a(lpszStructType));
|
||||
|
@ -2704,12 +2829,6 @@ struct AsnArrayItemSize
|
|||
DWORD size;
|
||||
};
|
||||
|
||||
struct GenericArray
|
||||
{
|
||||
DWORD cItems;
|
||||
BYTE *rgItems;
|
||||
};
|
||||
|
||||
/* Decodes an array of like types into a struct GenericArray.
|
||||
* The layout and decoding of the array are described by a struct
|
||||
* AsnArrayDescriptor.
|
||||
|
@ -3993,6 +4112,60 @@ static BOOL WINAPI CRYPT_AsnDecodePathLenConstraint(DWORD dwCertEncodingType,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnDecodeSubtreeConstraints(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
|
||||
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
|
||||
{
|
||||
BOOL ret;
|
||||
struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
|
||||
CRYPT_AsnDecodeCopyBytes, sizeof(CERT_NAME_BLOB), TRUE,
|
||||
offsetof(CERT_NAME_BLOB, pbData) };
|
||||
struct GenericArray *entries = (struct GenericArray *)pvStructInfo;
|
||||
|
||||
TRACE("%p, %ld, %08lx, %p, %p, %ld\n", pbEncoded, cbEncoded, dwFlags,
|
||||
pDecodePara, pvStructInfo, *pcbStructInfo);
|
||||
|
||||
ret = CRYPT_AsnDecodeArray(&arrayDesc, pbEncoded, cbEncoded, dwFlags,
|
||||
pDecodePara, pvStructInfo, pcbStructInfo,
|
||||
entries ? entries->rgItems : NULL);
|
||||
TRACE("Returning %d (%08lx)\n", ret, GetLastError());
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
|
||||
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
__TRY
|
||||
{
|
||||
struct AsnDecodeSequenceItem items[] = {
|
||||
{ ASN_BITSTRING, offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType),
|
||||
CRYPT_AsnDecodeBitsInternal, sizeof(CRYPT_BIT_BLOB), FALSE, TRUE,
|
||||
offsetof(CERT_BASIC_CONSTRAINTS_INFO, SubjectType.pbData), 0 },
|
||||
{ ASN_INTEGER, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
|
||||
fPathLenConstraint), CRYPT_AsnDecodePathLenConstraint,
|
||||
sizeof(struct PATH_LEN_CONSTRAINT), TRUE, FALSE, 0, 0 },
|
||||
{ ASN_SEQUENCEOF, offsetof(CERT_BASIC_CONSTRAINTS_INFO,
|
||||
cSubtreesConstraint), CRYPT_AsnDecodeSubtreeConstraints,
|
||||
sizeof(struct GenericArray), TRUE, TRUE,
|
||||
offsetof(CERT_BASIC_CONSTRAINTS_INFO, rgSubtreesConstraint), 0 },
|
||||
};
|
||||
|
||||
ret = CRYPT_AsnDecodeSequence(dwCertEncodingType, items,
|
||||
sizeof(items) / sizeof(items[0]), pbEncoded, cbEncoded, dwFlags,
|
||||
pDecodePara, pvStructInfo, pcbStructInfo, NULL);
|
||||
}
|
||||
__EXCEPT_PAGE_FAULT
|
||||
{
|
||||
SetLastError(STATUS_ACCESS_VIOLATION);
|
||||
ret = FALSE;
|
||||
}
|
||||
__ENDTRY
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnDecodeBasicConstraints2(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
|
||||
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
|
||||
|
@ -5078,6 +5251,32 @@ static BOOL WINAPI CRYPT_AsnDecodeCRLDistPoints(DWORD dwCertEncodingType,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnDecodeEnhancedKeyUsage(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_AsnDecodeOidWrapper, sizeof(LPSTR), TRUE, 0 };
|
||||
|
||||
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,
|
||||
const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
|
||||
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
|
||||
|
@ -5141,6 +5340,9 @@ BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
|
|||
case (WORD)X509_ALTERNATE_NAME:
|
||||
decodeFunc = CRYPT_AsnDecodeAltName;
|
||||
break;
|
||||
case (WORD)X509_BASIC_CONSTRAINTS:
|
||||
decodeFunc = CRYPT_AsnDecodeBasicConstraints;
|
||||
break;
|
||||
case (WORD)X509_BASIC_CONSTRAINTS2:
|
||||
decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
|
||||
break;
|
||||
|
@ -5178,6 +5380,9 @@ BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
|
|||
case (WORD)X509_CRL_DIST_POINTS:
|
||||
decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
|
||||
break;
|
||||
case (WORD)X509_ENHANCED_KEY_USAGE:
|
||||
decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
|
||||
break;
|
||||
default:
|
||||
FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
|
||||
}
|
||||
|
@ -5192,6 +5397,8 @@ BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
|
|||
decodeFunc = CRYPT_AsnDecodeBits;
|
||||
else if (!strcmp(lpszStructType, szOID_SUBJECT_KEY_IDENTIFIER))
|
||||
decodeFunc = CRYPT_AsnDecodeOctets;
|
||||
else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS))
|
||||
decodeFunc = CRYPT_AsnDecodeBasicConstraints;
|
||||
else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
|
||||
decodeFunc = CRYPT_AsnDecodeBasicConstraints2;
|
||||
else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
|
||||
|
@ -5204,6 +5411,10 @@ BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
|
|||
decodeFunc = CRYPT_AsnDecodeAltName;
|
||||
else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
|
||||
decodeFunc = CRYPT_AsnDecodeAltName;
|
||||
else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
|
||||
decodeFunc = CRYPT_AsnDecodeCRLDistPoints;
|
||||
else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
|
||||
decodeFunc = CRYPT_AsnDecodeEnhancedKeyUsage;
|
||||
else
|
||||
TRACE("OID %s not found or unimplemented, looking for DLL\n",
|
||||
debugstr_a(lpszStructType));
|
||||
|
|
|
@ -654,7 +654,7 @@ static const struct EncodedName names[] = {
|
|||
{ sizeof(bogusNumeric), (BYTE *)bogusNumeric } }, bin45 },
|
||||
};
|
||||
|
||||
static const BYTE emptyName[] = { 0x30, 0 };
|
||||
static const BYTE emptySequence[] = { 0x30, 0 };
|
||||
static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
|
||||
static const BYTE twoRDNs[] = {
|
||||
0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
|
||||
|
@ -731,7 +731,7 @@ static void test_encodeName(DWORD dwEncoding)
|
|||
ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
|
||||
if (buf)
|
||||
{
|
||||
ok(!memcmp(buf, emptyName, sizeof(emptyName)),
|
||||
ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
|
||||
"Got unexpected encoding for empty name\n");
|
||||
LocalFree(buf);
|
||||
}
|
||||
|
@ -921,8 +921,8 @@ static void test_decodeName(DWORD dwEncoding)
|
|||
}
|
||||
/* test empty name */
|
||||
bufSize = 0;
|
||||
ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptyName,
|
||||
emptyName[1] + 2,
|
||||
ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence,
|
||||
emptySequence[1] + 2,
|
||||
CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
|
||||
(BYTE *)&buf, &bufSize);
|
||||
ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
|
||||
|
@ -990,7 +990,6 @@ static void test_decodeName(DWORD dwEncoding)
|
|||
}
|
||||
}
|
||||
|
||||
static const BYTE emptyAltName[] = { 0x30, 0x00 };
|
||||
static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
|
||||
static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
|
||||
'h','q','.','o','r','g',0 };
|
||||
|
@ -1019,9 +1018,9 @@ static void test_encodeAltName(DWORD dwEncoding)
|
|||
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
|
||||
if (buf)
|
||||
{
|
||||
ok(size == sizeof(emptyAltName), "Expected size %d, got %ld\n",
|
||||
sizeof(emptyAltName), size);
|
||||
ok(!memcmp(buf, emptyAltName, size), "Unexpected value\n");
|
||||
ok(size == sizeof(emptySequence), "Expected size %d, got %ld\n",
|
||||
sizeof(emptySequence), size);
|
||||
ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
|
||||
LocalFree(buf);
|
||||
}
|
||||
/* Test with an empty entry */
|
||||
|
@ -1124,8 +1123,8 @@ static void test_decodeAltName(DWORD dwEncoding)
|
|||
ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
|
||||
"Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
|
||||
/* Now expected cases */
|
||||
ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyAltName,
|
||||
emptyAltName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
|
||||
ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
|
||||
emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
|
||||
&bufSize);
|
||||
ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
|
||||
if (buf)
|
||||
|
@ -1424,17 +1423,29 @@ static const struct Constraints2 constraints2[] = {
|
|||
{ { TRUE, TRUE, 1}, bin62 },
|
||||
};
|
||||
|
||||
static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
|
||||
static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
|
||||
0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
|
||||
0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
|
||||
0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
|
||||
static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
|
||||
0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
|
||||
0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
|
||||
0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
|
||||
0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
|
||||
|
||||
static void test_encodeBasicConstraints(DWORD dwEncoding)
|
||||
{
|
||||
DWORD i;
|
||||
DWORD i, bufSize = 0;
|
||||
CERT_BASIC_CONSTRAINTS_INFO info;
|
||||
CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
|
||||
(LPBYTE)encodedDomainName };
|
||||
BOOL ret;
|
||||
BYTE *buf = NULL;
|
||||
|
||||
/* First test with the simpler info2 */
|
||||
for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
|
||||
{
|
||||
BOOL ret;
|
||||
BYTE *buf = NULL;
|
||||
DWORD bufSize = 0;
|
||||
|
||||
ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
|
||||
&constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
|
||||
&bufSize);
|
||||
|
@ -1449,6 +1460,39 @@ static void test_encodeBasicConstraints(DWORD dwEncoding)
|
|||
LocalFree(buf);
|
||||
}
|
||||
}
|
||||
/* Now test with more complex basic constraints */
|
||||
info.SubjectType.cbData = 0;
|
||||
info.fPathLenConstraint = FALSE;
|
||||
info.cSubtreesConstraint = 0;
|
||||
ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
|
||||
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
|
||||
ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
|
||||
if (buf)
|
||||
{
|
||||
ok(bufSize == sizeof(emptyConstraint), "Expected %d bytes, got %ld\n",
|
||||
sizeof(emptyConstraint), bufSize);
|
||||
ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
|
||||
"Unexpected value\n");
|
||||
LocalFree(buf);
|
||||
}
|
||||
/* None of the certs I examined had any subtree constraint, but I test one
|
||||
* anyway just in case.
|
||||
*/
|
||||
info.cSubtreesConstraint = 1;
|
||||
info.rgSubtreesConstraint = &nameBlob;
|
||||
ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
|
||||
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
|
||||
ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
|
||||
if (buf)
|
||||
{
|
||||
ok(bufSize == sizeof(constraintWithDomainName),
|
||||
"Expected %d bytes, got %ld\n", sizeof(constraintWithDomainName),
|
||||
bufSize);
|
||||
ok(!memcmp(buf, constraintWithDomainName,
|
||||
sizeof(constraintWithDomainName)), "Unexpected value\n");
|
||||
LocalFree(buf);
|
||||
}
|
||||
/* FIXME: test encoding with subject type. */
|
||||
}
|
||||
|
||||
static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01,0 };
|
||||
|
@ -1507,6 +1551,41 @@ static void test_decodeBasicConstraints(DWORD dwEncoding)
|
|||
(BYTE *)&buf, &bufSize);
|
||||
ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
|
||||
"Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
|
||||
/* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
|
||||
ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
|
||||
emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
|
||||
(BYTE *)&buf, &bufSize);
|
||||
ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
|
||||
if (buf)
|
||||
{
|
||||
CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
|
||||
|
||||
ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
|
||||
ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
|
||||
ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
|
||||
LocalFree(buf);
|
||||
}
|
||||
ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
|
||||
constraintWithDomainName, sizeof(constraintWithDomainName),
|
||||
CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
|
||||
ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
|
||||
if (buf)
|
||||
{
|
||||
CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
|
||||
|
||||
ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
|
||||
ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
|
||||
ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
|
||||
if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
|
||||
{
|
||||
ok(info->rgSubtreesConstraint[0].cbData ==
|
||||
sizeof(encodedDomainName), "Expected %d bytes, got %ld\n",
|
||||
sizeof(encodedDomainName), info->rgSubtreesConstraint[0].cbData);
|
||||
ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
|
||||
sizeof(encodedDomainName)), "Unexpected value\n");
|
||||
}
|
||||
LocalFree(buf);
|
||||
}
|
||||
}
|
||||
|
||||
/* These are terrible public keys of course, I'm just testing encoding */
|
||||
|
@ -2761,6 +2840,92 @@ static void test_decodeCRLToBeSigned(DWORD dwEncoding)
|
|||
}
|
||||
}
|
||||
|
||||
static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
|
||||
szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
|
||||
static const BYTE encodedUsage[] = {
|
||||
0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
|
||||
0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
|
||||
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
|
||||
|
||||
static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
|
||||
{
|
||||
BOOL ret;
|
||||
BYTE *buf = NULL;
|
||||
DWORD size = 0;
|
||||
CERT_ENHKEY_USAGE usage;
|
||||
|
||||
/* Test with empty usage */
|
||||
usage.cUsageIdentifier = 0;
|
||||
ret = CryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
|
||||
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
|
||||
ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
|
||||
if (buf)
|
||||
{
|
||||
ok(size == sizeof(emptySequence), "Expected size %d, got %ld\n",
|
||||
sizeof(emptySequence), size);
|
||||
ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
|
||||
LocalFree(buf);
|
||||
}
|
||||
/* Test with a few usages */
|
||||
usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
|
||||
usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
|
||||
ret = CryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
|
||||
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
|
||||
ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
|
||||
if (buf)
|
||||
{
|
||||
ok(size == sizeof(encodedUsage), "Expected size %d, got %ld\n",
|
||||
sizeof(encodedUsage), size);
|
||||
ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
|
||||
LocalFree(buf);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
|
||||
{
|
||||
BOOL ret;
|
||||
LPBYTE buf = NULL;
|
||||
DWORD size = 0;
|
||||
|
||||
ret = CryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
|
||||
emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
|
||||
(BYTE *)&buf, &size);
|
||||
ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
|
||||
if (buf)
|
||||
{
|
||||
CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
|
||||
|
||||
ok(size >= sizeof(CERT_ENHKEY_USAGE),
|
||||
"Expected size at least %d, got %ld\n", sizeof(CERT_ENHKEY_USAGE),
|
||||
size);
|
||||
ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %ld\n",
|
||||
usage->cUsageIdentifier);
|
||||
LocalFree(buf);
|
||||
}
|
||||
ret = CryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
|
||||
encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
|
||||
(BYTE *)&buf, &size);
|
||||
ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
|
||||
if (buf)
|
||||
{
|
||||
CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
|
||||
DWORD i;
|
||||
|
||||
ok(size >= sizeof(CERT_ENHKEY_USAGE),
|
||||
"Expected size at least %d, got %ld\n", sizeof(CERT_ENHKEY_USAGE),
|
||||
size);
|
||||
ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
|
||||
"Expected %d CRL entries, got %ld\n",
|
||||
sizeof(keyUsages) / sizeof(keyUsages[0]),
|
||||
usage->cUsageIdentifier);
|
||||
for (i = 0; i < usage->cUsageIdentifier; i++)
|
||||
ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
|
||||
"Expected OID %s, got %s\n", keyUsages[i],
|
||||
usage->rgpszUsageIdentifier[i]);
|
||||
LocalFree(buf);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free *pInfo with HeapFree */
|
||||
static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
|
||||
{
|
||||
|
@ -2909,6 +3074,8 @@ START_TEST(encode)
|
|||
test_decodeCRLDistPoints(encodings[i]);
|
||||
test_encodeCRLToBeSigned(encodings[i]);
|
||||
test_decodeCRLToBeSigned(encodings[i]);
|
||||
test_encodeEnhancedKeyUsage(encodings[i]);
|
||||
test_decodeEnhancedKeyUsage(encodings[i]);
|
||||
}
|
||||
testPortPublicKeyInfo();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue