crypt32: Implement CERT_AUTHORITY_KEY_ID2_INFO encoding/decoding.
This commit is contained in:
parent
fc5582aef7
commit
2d00a4f0f5
@ -475,7 +475,8 @@ static BOOL CRYPT_AsnDecodeSequence(DWORD dwCertEncodingType,
|
||||
|
||||
/* tag:
|
||||
* The expected tag of the entire encoded array (usually a variant
|
||||
* of ASN_SETOF or ASN_SEQUENCEOF.)
|
||||
* of ASN_SETOF or ASN_SEQUENCEOF.) If tag is 0, decodeFunc is called
|
||||
* regardless of the tag seen.
|
||||
* decodeFunc:
|
||||
* used to decode each item in the array
|
||||
* itemSize:
|
||||
@ -515,7 +516,7 @@ static BOOL CRYPT_AsnDecodeArray(const struct AsnArrayDescriptor *arrayDesc,
|
||||
cbEncoded, dwFlags, pDecodePara, pvStructInfo, *pcbStructInfo,
|
||||
startingPointer);
|
||||
|
||||
if (pbEncoded[0] == arrayDesc->tag)
|
||||
if (!arrayDesc->tag || pbEncoded[0] == arrayDesc->tag)
|
||||
{
|
||||
DWORD dataLen;
|
||||
|
||||
@ -2038,7 +2039,7 @@ static BOOL WINAPI CRYPT_AsnDecodeAltNameInternal(DWORD dwCertEncodingType,
|
||||
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
|
||||
{
|
||||
BOOL ret = TRUE;
|
||||
struct AsnArrayDescriptor arrayDesc = { ASN_SEQUENCEOF,
|
||||
struct AsnArrayDescriptor arrayDesc = { 0,
|
||||
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;
|
||||
@ -2088,6 +2089,43 @@ static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId(DWORD dwCertEncodingType,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnDecodeAuthorityKeyId2(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_CONTEXT | 0, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId),
|
||||
CRYPT_AsnDecodeIntegerInternal, sizeof(CRYPT_DATA_BLOB),
|
||||
TRUE, TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO, KeyId.pbData), 0 },
|
||||
{ ASN_CONTEXT | ASN_CONSTRUCTOR| 1,
|
||||
offsetof(CERT_AUTHORITY_KEY_ID2_INFO, AuthorityCertIssuer),
|
||||
CRYPT_AsnDecodeAltNameInternal, sizeof(CERT_ALT_NAME_INFO), TRUE,
|
||||
TRUE, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
|
||||
AuthorityCertIssuer.rgAltEntry), 0 },
|
||||
{ ASN_CONTEXT | 2, offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
|
||||
AuthorityCertSerialNumber), CRYPT_AsnDecodeIntegerInternal,
|
||||
sizeof(CRYPT_INTEGER_BLOB), TRUE, TRUE,
|
||||
offsetof(CERT_AUTHORITY_KEY_ID2_INFO,
|
||||
AuthorityCertSerialNumber.pbData), 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_AsnDecodeAltName(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
|
||||
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
|
||||
@ -3551,6 +3589,9 @@ BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
|
||||
case (WORD)X509_CHOICE_OF_TIME:
|
||||
decodeFunc = CRYPT_AsnDecodeChoiceOfTime;
|
||||
break;
|
||||
case (WORD)X509_AUTHORITY_KEY_ID2:
|
||||
decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
|
||||
break;
|
||||
case (WORD)X509_SEQUENCE_OF_ANY:
|
||||
decodeFunc = CRYPT_AsnDecodeSequenceOfAny;
|
||||
break;
|
||||
@ -3576,6 +3617,8 @@ BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
|
||||
decodeFunc = CRYPT_AsnDecodeUtcTime;
|
||||
else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
|
||||
decodeFunc = CRYPT_AsnDecodeAuthorityKeyId;
|
||||
else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
|
||||
decodeFunc = CRYPT_AsnDecodeAuthorityKeyId2;
|
||||
else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
|
||||
decodeFunc = CRYPT_AsnDecodeEnumerated;
|
||||
else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
|
||||
|
@ -1941,6 +1941,62 @@ static BOOL WINAPI CRYPT_AsnEncodeAltName(DWORD dwCertEncodingType,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnEncodeAuthorityKeyId2(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
|
||||
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
__TRY
|
||||
{
|
||||
const CERT_AUTHORITY_KEY_ID2_INFO *info =
|
||||
(const CERT_AUTHORITY_KEY_ID2_INFO *)pvStructInfo;
|
||||
struct AsnEncodeSequenceItem items[3] = { { 0 } };
|
||||
struct AsnEncodeTagSwappedItem swapped[3] = { { 0 } };
|
||||
DWORD cItem = 0, cSwapped = 0;
|
||||
|
||||
if (info->KeyId.cbData)
|
||||
{
|
||||
swapped[cSwapped].tag = ASN_CONTEXT | 0;
|
||||
swapped[cSwapped].pvStructInfo = &info->KeyId;
|
||||
swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
|
||||
items[cItem].pvStructInfo = &swapped[cSwapped];
|
||||
items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
|
||||
cSwapped++;
|
||||
cItem++;
|
||||
}
|
||||
if (info->AuthorityCertIssuer.cAltEntry)
|
||||
{
|
||||
swapped[cSwapped].tag = ASN_CONTEXT | ASN_CONSTRUCTOR | 1;
|
||||
swapped[cSwapped].pvStructInfo = &info->AuthorityCertIssuer;
|
||||
swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeAltName;
|
||||
items[cItem].pvStructInfo = &swapped[cSwapped];
|
||||
items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
|
||||
cSwapped++;
|
||||
cItem++;
|
||||
}
|
||||
if (info->AuthorityCertSerialNumber.cbData)
|
||||
{
|
||||
swapped[cSwapped].tag = ASN_CONTEXT | 2;
|
||||
swapped[cSwapped].pvStructInfo = &info->AuthorityCertSerialNumber;
|
||||
swapped[cSwapped].encodeFunc = CRYPT_AsnEncodeInteger;
|
||||
items[cItem].pvStructInfo = &swapped[cSwapped];
|
||||
items[cItem].encodeFunc = CRYPT_AsnEncodeSwapTag;
|
||||
cSwapped++;
|
||||
cItem++;
|
||||
}
|
||||
ret = CRYPT_AsnEncodeSequence(X509_ASN_ENCODING, items, cItem, dwFlags,
|
||||
pEncodePara, pbEncoded, pcbEncoded);
|
||||
}
|
||||
__EXCEPT_PAGE_FAULT
|
||||
{
|
||||
SetLastError(STATUS_ACCESS_VIOLATION);
|
||||
ret = FALSE;
|
||||
}
|
||||
__ENDTRY
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnEncodeBasicConstraints(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
|
||||
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
|
||||
@ -2980,6 +3036,9 @@ BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
|
||||
case (WORD)X509_CHOICE_OF_TIME:
|
||||
encodeFunc = CRYPT_AsnEncodeChoiceOfTime;
|
||||
break;
|
||||
case (WORD)X509_AUTHORITY_KEY_ID2:
|
||||
encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
|
||||
break;
|
||||
case (WORD)X509_SEQUENCE_OF_ANY:
|
||||
encodeFunc = CRYPT_AsnEncodeSequenceOfAny;
|
||||
break;
|
||||
@ -3005,6 +3064,8 @@ BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
|
||||
encodeFunc = CRYPT_AsnEncodeUtcTime;
|
||||
else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER))
|
||||
encodeFunc = CRYPT_AsnEncodeAuthorityKeyId;
|
||||
else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
|
||||
encodeFunc = CRYPT_AsnEncodeAuthorityKeyId2;
|
||||
else if (!strcmp(lpszStructType, szOID_CRL_REASON_CODE))
|
||||
encodeFunc = CRYPT_AsnEncodeEnumerated;
|
||||
else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
|
||||
|
@ -4365,6 +4365,165 @@ static void test_decodeAuthorityKeyId(DWORD dwEncoding)
|
||||
}
|
||||
}
|
||||
|
||||
static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
|
||||
0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
|
||||
0x6f,0x72,0x67 };
|
||||
|
||||
static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
|
||||
{
|
||||
CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
|
||||
CERT_ALT_NAME_ENTRY entry = { 0 };
|
||||
BOOL ret;
|
||||
BYTE *buf = NULL;
|
||||
DWORD size = 0;
|
||||
|
||||
/* Test with empty id */
|
||||
ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
|
||||
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
|
||||
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
||||
if (buf)
|
||||
{
|
||||
ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
|
||||
ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
|
||||
LocalFree(buf);
|
||||
}
|
||||
/* With just a key id */
|
||||
info.KeyId.cbData = sizeof(serialNum);
|
||||
info.KeyId.pbData = (BYTE *)serialNum;
|
||||
ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
|
||||
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
|
||||
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
||||
if (buf)
|
||||
{
|
||||
ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
|
||||
size);
|
||||
ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
|
||||
LocalFree(buf);
|
||||
}
|
||||
/* With a bogus issuer name */
|
||||
info.KeyId.cbData = 0;
|
||||
info.AuthorityCertIssuer.cAltEntry = 1;
|
||||
info.AuthorityCertIssuer.rgAltEntry = &entry;
|
||||
ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
|
||||
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
/* With an issuer name */
|
||||
entry.dwAltNameChoice = CERT_ALT_NAME_URL;
|
||||
entry.pwszURL = (LPWSTR)url;
|
||||
ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
|
||||
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
|
||||
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
||||
if (buf)
|
||||
{
|
||||
ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
|
||||
size);
|
||||
ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
|
||||
"Unexpected value\n");
|
||||
LocalFree(buf);
|
||||
}
|
||||
/* With just a serial number */
|
||||
info.AuthorityCertIssuer.cAltEntry = 0;
|
||||
info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
|
||||
info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
|
||||
ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
|
||||
CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
|
||||
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
||||
if (buf)
|
||||
{
|
||||
ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
|
||||
size);
|
||||
ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
|
||||
LocalFree(buf);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
|
||||
{
|
||||
BOOL ret;
|
||||
LPBYTE buf = NULL;
|
||||
DWORD size = 0;
|
||||
|
||||
ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
|
||||
emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
|
||||
(BYTE *)&buf, &size);
|
||||
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
||||
if (buf)
|
||||
{
|
||||
CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
|
||||
|
||||
ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
|
||||
size);
|
||||
ok(info->KeyId.cbData == 0, "Expected no key id\n");
|
||||
ok(info->AuthorityCertIssuer.cAltEntry == 0,
|
||||
"Expected no issuer name entries\n");
|
||||
ok(info->AuthorityCertSerialNumber.cbData == 0,
|
||||
"Expected no serial number\n");
|
||||
LocalFree(buf);
|
||||
}
|
||||
ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
|
||||
authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
|
||||
CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
|
||||
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
||||
if (buf)
|
||||
{
|
||||
CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
|
||||
|
||||
ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
|
||||
size);
|
||||
ok(info->KeyId.cbData == sizeof(serialNum), "Unexpected key id len\n");
|
||||
ok(!memcmp(info->KeyId.pbData, serialNum, sizeof(serialNum)),
|
||||
"Unexpected key id\n");
|
||||
ok(info->AuthorityCertIssuer.cAltEntry == 0,
|
||||
"Expected no issuer name entries\n");
|
||||
ok(info->AuthorityCertSerialNumber.cbData == 0,
|
||||
"Expected no serial number\n");
|
||||
LocalFree(buf);
|
||||
}
|
||||
ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
|
||||
authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
|
||||
CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
|
||||
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
||||
if (buf)
|
||||
{
|
||||
CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
|
||||
|
||||
ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
|
||||
size);
|
||||
ok(info->KeyId.cbData == 0, "Expected no key id\n");
|
||||
ok(info->AuthorityCertIssuer.cAltEntry == 1,
|
||||
"Expected 1 issuer entry, got %d\n",
|
||||
info->AuthorityCertIssuer.cAltEntry);
|
||||
ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
|
||||
CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
|
||||
info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
|
||||
ok(!lstrcmpW(info->AuthorityCertIssuer.rgAltEntry[0].pwszURL,
|
||||
url), "Unexpected URL\n");
|
||||
ok(info->AuthorityCertSerialNumber.cbData == 0,
|
||||
"Expected no serial number\n");
|
||||
LocalFree(buf);
|
||||
}
|
||||
ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
|
||||
authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
|
||||
CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
|
||||
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
||||
if (buf)
|
||||
{
|
||||
CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
|
||||
|
||||
ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
|
||||
size);
|
||||
ok(info->KeyId.cbData == 0, "Expected no key id\n");
|
||||
ok(info->AuthorityCertIssuer.cAltEntry == 0,
|
||||
"Expected no issuer name entries\n");
|
||||
ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
|
||||
"Unexpected serial number len\n");
|
||||
ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
|
||||
sizeof(serialNum)), "Unexpected serial number\n");
|
||||
LocalFree(buf);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free *pInfo with HeapFree */
|
||||
static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
|
||||
{
|
||||
@ -4570,6 +4729,8 @@ START_TEST(encode)
|
||||
test_decodeEnhancedKeyUsage(encodings[i]);
|
||||
test_encodeAuthorityKeyId(encodings[i]);
|
||||
test_decodeAuthorityKeyId(encodings[i]);
|
||||
test_encodeAuthorityKeyId2(encodings[i]);
|
||||
test_decodeAuthorityKeyId2(encodings[i]);
|
||||
}
|
||||
testPortPublicKeyInfo();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user