diff --git a/dlls/crypt32/tests/encode.c b/dlls/crypt32/tests/encode.c index 421b236c92d..14e155edce4 100644 --- a/dlls/crypt32/tests/encode.c +++ b/dlls/crypt32/tests/encode.c @@ -5468,6 +5468,235 @@ static void test_decodePKCSSignerInfo(DWORD dwEncoding) } } +static BYTE emptyDNSPermittedConstraints[] = { +0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 }; +static BYTE emptyDNSExcludedConstraints[] = { +0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 }; +static BYTE DNSExcludedConstraints[] = { +0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f, +0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 }; +static BYTE permittedAndExcludedConstraints[] = { +0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00, +0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77, +0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 }; +static BYTE permittedAndExcludedWithMinConstraints[] = { +0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00, +0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a, +0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 }; +static BYTE permittedAndExcludedWithMinMaxConstraints[] = { +0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00, +0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74, +0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 }; + +static void test_encodeNameConstraints(DWORD dwEncoding) +{ + BOOL ret; + CERT_NAME_CONSTRAINTS_INFO constraints = { 0 }; + CERT_GENERAL_SUBTREE permitted = { { 0 } }; + CERT_GENERAL_SUBTREE excluded = { { 0 } }; + LPBYTE buf; + DWORD size; + + ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints, + CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size); + todo_wine + ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); + if (ret) + { + ok(size == sizeof(emptySequence), "Unexpected size\n"); + ok(!memcmp(buf, emptySequence, size), "Unexpected value\n"); + LocalFree(buf); + } + constraints.cPermittedSubtree = 1; + constraints.rgPermittedSubtree = &permitted; + SetLastError(0xdeadbeef); + ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints, + CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size); + todo_wine + ok(!ret && GetLastError() == E_INVALIDARG, + "Expected E_INVALIDARG, got %08x\n", GetLastError()); + permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME; + ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints, + CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size); + todo_wine + ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); + if (ret) + { + ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n"); + ok(!memcmp(buf, emptyDNSPermittedConstraints, size), + "Unexpected value\n"); + LocalFree(buf); + } + constraints.cPermittedSubtree = 0; + constraints.cExcludedSubtree = 1; + constraints.rgExcludedSubtree = &excluded; + excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME; + ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints, + CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size); + todo_wine + ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); + if (ret) + { + ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n"); + ok(!memcmp(buf, emptyDNSExcludedConstraints, size), + "Unexpected value\n"); + LocalFree(buf); + } + excluded.Base.pwszURL = (LPWSTR)url; + ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints, + CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size); + todo_wine + ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); + if (ret) + { + ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n"); + ok(!memcmp(buf, DNSExcludedConstraints, size), + "Unexpected value\n"); + LocalFree(buf); + } + permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS; + permitted.Base.IPAddress.cbData = sizeof(encodedIPAddr); + permitted.Base.IPAddress.pbData = (LPBYTE)encodedIPAddr; + constraints.cPermittedSubtree = 1; + ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints, + CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size); + todo_wine + ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); + if (ret) + { + ok(size == sizeof(permittedAndExcludedConstraints), + "Unexpected size\n"); + ok(!memcmp(buf, permittedAndExcludedConstraints, size), + "Unexpected value\n"); + LocalFree(buf); + } + permitted.dwMinimum = 5; + ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints, + CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size); + todo_wine + ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); + if (ret) + { + ok(size == sizeof(permittedAndExcludedWithMinConstraints), + "Unexpected size\n"); + ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size), + "Unexpected value\n"); + LocalFree(buf); + } + permitted.fMaximum = TRUE; + permitted.dwMaximum = 3; + SetLastError(0xdeadbeef); + ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints, + CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size); + todo_wine + ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); + if (ret) + { + ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints), + "Unexpected size\n"); + ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size), + "Unexpected value\n"); + LocalFree(buf); + } +} + +struct EncodedNameConstraints +{ + CRYPT_DATA_BLOB encoded; + CERT_NAME_CONSTRAINTS_INFO constraints; +}; + +static CERT_GENERAL_SUBTREE emptyDNSSubtree = { + { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 }; +static CERT_GENERAL_SUBTREE DNSSubtree = { + { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 }; +static CERT_GENERAL_SUBTREE IPAddressSubtree = { + { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 }; +static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = { + { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 }; +static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = { + { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 }; + +struct EncodedNameConstraints encodedNameConstraints[] = { + { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } }, + { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints }, + { 1, &emptyDNSSubtree, 0, NULL } }, + { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints }, + { 0, NULL, 1, &emptyDNSSubtree } }, + { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints }, + { 0, NULL, 1, &DNSSubtree } }, + { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints }, + { 1, &IPAddressSubtree, 1, &DNSSubtree } }, + { { sizeof(permittedAndExcludedWithMinConstraints), + permittedAndExcludedWithMinConstraints }, + { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } }, + { { sizeof(permittedAndExcludedWithMinMaxConstraints), + permittedAndExcludedWithMinMaxConstraints }, + { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } }, +}; + +static void test_decodeNameConstraints(DWORD dwEncoding) +{ + BOOL ret; + DWORD i; + CERT_NAME_CONSTRAINTS_INFO *constraints; + + DNSSubtree.Base.pwszURL = (LPWSTR)url; + IPAddressSubtree.Base.IPAddress.cbData = sizeof(encodedIPAddr); + IPAddressSubtree.Base.IPAddress.pbData = (LPBYTE)encodedIPAddr; + IPAddressWithMinSubtree.Base.IPAddress.cbData = sizeof(encodedIPAddr); + IPAddressWithMinSubtree.Base.IPAddress.pbData = (LPBYTE)encodedIPAddr; + IPAddressWithMinMaxSubtree.Base.IPAddress.cbData = sizeof(encodedIPAddr); + IPAddressWithMinMaxSubtree.Base.IPAddress.pbData = (LPBYTE)encodedIPAddr; + for (i = 0; + i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]); + i++) + { + DWORD size; + + ret = CryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, + encodedNameConstraints[i].encoded.pbData, + encodedNameConstraints[i].encoded.cbData, + CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size); + todo_wine + ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError()); + if (ret) + { + DWORD j; + + if (constraints->cPermittedSubtree != + encodedNameConstraints[i].constraints.cPermittedSubtree) + fprintf(stderr, "%d: expected %d permitted, got %d\n", i, + encodedNameConstraints[i].constraints.cPermittedSubtree, + constraints->cPermittedSubtree); + if (constraints->cPermittedSubtree == + encodedNameConstraints[i].constraints.cPermittedSubtree) + { + for (j = 0; j < constraints->cPermittedSubtree; j++) + { + compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base, + &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base); + } + } + if (constraints->cExcludedSubtree != + encodedNameConstraints[i].constraints.cExcludedSubtree) + fprintf(stderr, "%d: expected %d excluded, got %d\n", i, + encodedNameConstraints[i].constraints.cExcludedSubtree, + constraints->cExcludedSubtree); + if (constraints->cExcludedSubtree == + encodedNameConstraints[i].constraints.cExcludedSubtree) + { + for (j = 0; j < constraints->cExcludedSubtree; j++) + { + compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base, + &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base); + } + } + LocalFree(constraints); + } + } +} + /* Free *pInfo with HeapFree */ static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo) { @@ -5683,6 +5912,8 @@ START_TEST(encode) test_decodePKCSAttributes(encodings[i]); test_encodePKCSSignerInfo(encodings[i]); test_decodePKCSSignerInfo(encodings[i]); + test_encodeNameConstraints(encodings[i]); + test_decodeNameConstraints(encodings[i]); } testPortPublicKeyInfo(); }