Commit 2d00a4f0 authored by Juan Lang's avatar Juan Lang Committed by Alexandre Julliard

crypt32: Implement CERT_AUTHORITY_KEY_ID2_INFO encoding/decoding.

parent fc5582ae
......@@ -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();
}
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