mirror of
https://github.com/reactos/reactos.git
synced 2025-04-21 12:40:33 +00:00
sync crypt32 winetest with wine 1.1.33
svn path=/trunk/; revision=44185
This commit is contained in:
parent
86d5f9981c
commit
9cd4c81c17
9 changed files with 3251 additions and 373 deletions
|
@ -1015,6 +1015,10 @@ static void testFindCert(void)
|
||||||
CERT_INFO certInfo = { 0 };
|
CERT_INFO certInfo = { 0 };
|
||||||
CRYPT_HASH_BLOB blob;
|
CRYPT_HASH_BLOB blob;
|
||||||
BYTE otherSerialNumber[] = { 2 };
|
BYTE otherSerialNumber[] = { 2 };
|
||||||
|
DWORD count;
|
||||||
|
static const WCHAR juan[] = { 'j','u','a','n',0 };
|
||||||
|
static const WCHAR lang[] = { 'L','A','N','G',0 };
|
||||||
|
static const WCHAR malcolm[] = { 'm','a','l','c','o','l','m',0 };
|
||||||
|
|
||||||
store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
||||||
CERT_STORE_CREATE_NEW_FLAG, NULL);
|
CERT_STORE_CREATE_NEW_FLAG, NULL);
|
||||||
|
@ -1085,7 +1089,7 @@ static void testFindCert(void)
|
||||||
* the issuer, not the subject
|
* the issuer, not the subject
|
||||||
*/
|
*/
|
||||||
context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
|
context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
|
||||||
CERT_FIND_SUBJECT_CERT, &certInfo.Subject, NULL);
|
CERT_FIND_SUBJECT_CERT, &certInfo, NULL);
|
||||||
ok(context == NULL, "Expected no certificate\n");
|
ok(context == NULL, "Expected no certificate\n");
|
||||||
certInfo.Subject.pbData = NULL;
|
certInfo.Subject.pbData = NULL;
|
||||||
certInfo.Subject.cbData = 0;
|
certInfo.Subject.cbData = 0;
|
||||||
|
@ -1098,7 +1102,7 @@ static void testFindCert(void)
|
||||||
if (context)
|
if (context)
|
||||||
{
|
{
|
||||||
context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
|
context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
|
||||||
CERT_FIND_SUBJECT_CERT, &certInfo.Subject, context);
|
CERT_FIND_SUBJECT_CERT, &certInfo, context);
|
||||||
ok(context == NULL, "Expected one cert only\n");
|
ok(context == NULL, "Expected one cert only\n");
|
||||||
}
|
}
|
||||||
/* A non-matching serial number will not match. */
|
/* A non-matching serial number will not match. */
|
||||||
|
@ -1135,6 +1139,41 @@ static void testFindCert(void)
|
||||||
ok(context == NULL, "Expected one cert only\n");
|
ok(context == NULL, "Expected one cert only\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Searching for NULL string matches any context. */
|
||||||
|
count = 0;
|
||||||
|
context = NULL;
|
||||||
|
do {
|
||||||
|
context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
|
||||||
|
CERT_FIND_ISSUER_STR, NULL, context);
|
||||||
|
if (context)
|
||||||
|
count++;
|
||||||
|
} while (context);
|
||||||
|
ok(count == 3, "expected 3 contexts\n");
|
||||||
|
count = 0;
|
||||||
|
context = NULL;
|
||||||
|
do {
|
||||||
|
context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
|
||||||
|
CERT_FIND_ISSUER_STR, juan, context);
|
||||||
|
if (context)
|
||||||
|
count++;
|
||||||
|
} while (context);
|
||||||
|
ok(count == 2, "expected 2 contexts\n");
|
||||||
|
count = 0;
|
||||||
|
context = NULL;
|
||||||
|
do {
|
||||||
|
context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
|
||||||
|
CERT_FIND_ISSUER_STR, lang, context);
|
||||||
|
if (context)
|
||||||
|
count++;
|
||||||
|
} while (context);
|
||||||
|
ok(count == 3, "expected 3 contexts\n");
|
||||||
|
SetLastError(0xdeadbeef);
|
||||||
|
context = CertFindCertificateInStore(store, X509_ASN_ENCODING, 0,
|
||||||
|
CERT_FIND_ISSUER_STR, malcolm, NULL);
|
||||||
|
ok(!context, "expected no certs\n");
|
||||||
|
ok(GetLastError() == CRYPT_E_NOT_FOUND,
|
||||||
|
"expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
|
||||||
|
|
||||||
CertCloseStore(store, 0);
|
CertCloseStore(store, 0);
|
||||||
|
|
||||||
/* Another subject cert search, using iTunes's certs */
|
/* Another subject cert search, using iTunes's certs */
|
||||||
|
@ -1624,12 +1663,14 @@ static void testSignCert(HCRYPTPROV csp, const CRYPT_DATA_BLOB *toBeSigned,
|
||||||
algoID.pszObjId = (LPSTR)sigOID;
|
algoID.pszObjId = (LPSTR)sigOID;
|
||||||
ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
|
ret = CryptSignCertificate(0, 0, 0, toBeSigned->pbData, toBeSigned->cbData,
|
||||||
&algoID, NULL, NULL, &size);
|
&algoID, NULL, NULL, &size);
|
||||||
ok(!ret && (GetLastError() == ERROR_INVALID_PARAMETER || NTE_BAD_ALGID),
|
ok(!ret &&
|
||||||
|
(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == NTE_BAD_ALGID),
|
||||||
"Expected ERROR_INVALID_PARAMETER or NTE_BAD_ALGID, got %08x\n",
|
"Expected ERROR_INVALID_PARAMETER or NTE_BAD_ALGID, got %08x\n",
|
||||||
GetLastError());
|
GetLastError());
|
||||||
ret = CryptSignCertificate(0, AT_SIGNATURE, 0, toBeSigned->pbData,
|
ret = CryptSignCertificate(0, AT_SIGNATURE, 0, toBeSigned->pbData,
|
||||||
toBeSigned->cbData, &algoID, NULL, NULL, &size);
|
toBeSigned->cbData, &algoID, NULL, NULL, &size);
|
||||||
ok(!ret && (GetLastError() == ERROR_INVALID_PARAMETER || NTE_BAD_ALGID),
|
ok(!ret &&
|
||||||
|
(GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == NTE_BAD_ALGID),
|
||||||
"Expected ERROR_INVALID_PARAMETER or NTE_BAD_ALGID, got %08x\n",
|
"Expected ERROR_INVALID_PARAMETER or NTE_BAD_ALGID, got %08x\n",
|
||||||
GetLastError());
|
GetLastError());
|
||||||
|
|
||||||
|
@ -1851,7 +1892,10 @@ static void testSignAndEncodeCert(void)
|
||||||
algID.pszObjId = oid_rsa_md5rsa;
|
algID.pszObjId = oid_rsa_md5rsa;
|
||||||
ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
|
ret = CryptSignAndEncodeCertificate(0, 0, X509_ASN_ENCODING,
|
||||||
X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
|
X509_CERT_TO_BE_SIGNED, &info, &algID, NULL, NULL, &size);
|
||||||
ok(!ret && (GetLastError() == ERROR_INVALID_PARAMETER || NTE_BAD_ALGID),
|
ok(!ret &&
|
||||||
|
(GetLastError() == ERROR_INVALID_PARAMETER ||
|
||||||
|
GetLastError() == NTE_BAD_ALGID ||
|
||||||
|
GetLastError() == OSS_BAD_PTR), /* Win9x */
|
||||||
"Expected ERROR_INVALID_PARAMETER or NTE_BAD_ALGID, got %08x\n",
|
"Expected ERROR_INVALID_PARAMETER or NTE_BAD_ALGID, got %08x\n",
|
||||||
GetLastError());
|
GetLastError());
|
||||||
algID.pszObjId = oid_rsa_md5;
|
algID.pszObjId = oid_rsa_md5;
|
||||||
|
@ -2021,6 +2065,54 @@ static void testCreateSelfSignCert(void)
|
||||||
CRYPT_DELETEKEYSET);
|
CRYPT_DELETEKEYSET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void testIntendedKeyUsage(void)
|
||||||
|
{
|
||||||
|
BOOL ret;
|
||||||
|
CERT_INFO info = { 0 };
|
||||||
|
static char oid_key_usage[] = szOID_KEY_USAGE;
|
||||||
|
/* A couple "key usages". Really they're just encoded bits which aren't
|
||||||
|
* necessarily restricted to the defined key usage values.
|
||||||
|
*/
|
||||||
|
static BYTE usage1[] = { 0x03,0x03,0x00,0xff,0xff };
|
||||||
|
static BYTE usage2[] = { 0x03,0x03,0x01,0xff,0xfe };
|
||||||
|
static const BYTE expected_usage1[] = { 0xff,0xff,0x00,0x00 };
|
||||||
|
static const BYTE expected_usage2[] = { 0xff,0xfe,0x00,0x00 };
|
||||||
|
CERT_EXTENSION ext = { oid_key_usage, TRUE, { sizeof(usage1), usage1 } };
|
||||||
|
BYTE usage_bytes[4];
|
||||||
|
|
||||||
|
if (0)
|
||||||
|
{
|
||||||
|
/* Crash */
|
||||||
|
ret = CertGetIntendedKeyUsage(0, NULL, NULL, 0);
|
||||||
|
}
|
||||||
|
ret = CertGetIntendedKeyUsage(0, &info, NULL, 0);
|
||||||
|
ok(!ret, "expected failure\n");
|
||||||
|
ret = CertGetIntendedKeyUsage(0, &info, usage_bytes, sizeof(usage_bytes));
|
||||||
|
ok(!ret, "expected failure\n");
|
||||||
|
ret = CertGetIntendedKeyUsage(X509_ASN_ENCODING, &info, NULL, 0);
|
||||||
|
ok(!ret, "expected failure\n");
|
||||||
|
ret = CertGetIntendedKeyUsage(X509_ASN_ENCODING, &info, usage_bytes,
|
||||||
|
sizeof(usage_bytes));
|
||||||
|
info.cExtension = 1;
|
||||||
|
info.rgExtension = &ext;
|
||||||
|
ret = CertGetIntendedKeyUsage(X509_ASN_ENCODING, &info, NULL, 0);
|
||||||
|
ok(!ret, "expected failure\n");
|
||||||
|
/* The unused bytes are filled with 0. */
|
||||||
|
ret = CertGetIntendedKeyUsage(X509_ASN_ENCODING, &info, usage_bytes,
|
||||||
|
sizeof(usage_bytes));
|
||||||
|
ok(ret, "CertGetIntendedKeyUsage failed: %08x\n", GetLastError());
|
||||||
|
ok(!memcmp(usage_bytes, expected_usage1, sizeof(expected_usage1)),
|
||||||
|
"unexpected value\n");
|
||||||
|
/* The usage bytes are copied in big-endian order. */
|
||||||
|
ext.Value.cbData = sizeof(usage2);
|
||||||
|
ext.Value.pbData = usage2;
|
||||||
|
ret = CertGetIntendedKeyUsage(X509_ASN_ENCODING, &info, usage_bytes,
|
||||||
|
sizeof(usage_bytes));
|
||||||
|
ok(ret, "CertGetIntendedKeyUsage failed: %08x\n", GetLastError());
|
||||||
|
ok(!memcmp(usage_bytes, expected_usage2, sizeof(expected_usage2)),
|
||||||
|
"unexpected value\n");
|
||||||
|
}
|
||||||
|
|
||||||
static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
|
static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
|
||||||
szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
|
szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
|
||||||
|
|
||||||
|
@ -3138,7 +3230,8 @@ static void testGetPublicKeyLength(void)
|
||||||
ret, GetLastError());
|
ret, GetLastError());
|
||||||
SetLastError(0xdeadbeef);
|
SetLastError(0xdeadbeef);
|
||||||
ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
|
ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
|
||||||
ok(ret == 56, "Expected length 56, got %d\n", ret);
|
ok(ret == 56 || broken(ret == 0 && GetLastError() == NTE_BAD_LEN) /* Win7 */,
|
||||||
|
"Expected length 56, got %d\n", ret);
|
||||||
/* An RSA key with the DH OID */
|
/* An RSA key with the DH OID */
|
||||||
info.Algorithm.pszObjId = oid_rsa_dh;
|
info.Algorithm.pszObjId = oid_rsa_dh;
|
||||||
SetLastError(0xdeadbeef);
|
SetLastError(0xdeadbeef);
|
||||||
|
@ -3152,12 +3245,14 @@ static void testGetPublicKeyLength(void)
|
||||||
info.Algorithm.pszObjId = oid_rsa_rsa;
|
info.Algorithm.pszObjId = oid_rsa_rsa;
|
||||||
SetLastError(0xdeadbeef);
|
SetLastError(0xdeadbeef);
|
||||||
ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
|
ret = CertGetPublicKeyLength(X509_ASN_ENCODING, &info);
|
||||||
ok(ret == 56, "Expected length 56, got %d\n", ret);
|
ok(ret == 56 || broken(ret == 0 && GetLastError() == NTE_BAD_LEN) /* Win7 */,
|
||||||
|
"Expected length 56, got %d\n", ret);
|
||||||
/* With the RSA OID and a message encoding */
|
/* With the RSA OID and a message encoding */
|
||||||
info.Algorithm.pszObjId = oid_rsa_rsa;
|
info.Algorithm.pszObjId = oid_rsa_rsa;
|
||||||
SetLastError(0xdeadbeef);
|
SetLastError(0xdeadbeef);
|
||||||
ret = CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &info);
|
ret = CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &info);
|
||||||
ok(ret == 56, "Expected length 56, got %d\n", ret);
|
ok(ret == 56 || broken(ret == 0 && GetLastError() == NTE_BAD_LEN) /* Win7 */,
|
||||||
|
"Expected length 56, got %d\n", ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
START_TEST(cert)
|
START_TEST(cert)
|
||||||
|
@ -3175,6 +3270,7 @@ START_TEST(cert)
|
||||||
testCertSigs();
|
testCertSigs();
|
||||||
testSignAndEncodeCert();
|
testSignAndEncodeCert();
|
||||||
testCreateSelfSignCert();
|
testCreateSelfSignCert();
|
||||||
|
testIntendedKeyUsage();
|
||||||
testKeyUsage();
|
testKeyUsage();
|
||||||
testGetValidUsages();
|
testGetValidUsages();
|
||||||
testCompareCertName();
|
testCompareCertName();
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -118,6 +118,21 @@ static void testCreateCRL(void)
|
||||||
CertFreeCRLContext(context);
|
CertFreeCRLContext(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void testDupCRL(void)
|
||||||
|
{
|
||||||
|
PCCRL_CONTEXT context, dupContext;
|
||||||
|
|
||||||
|
context = CertDuplicateCRLContext(NULL);
|
||||||
|
ok(context == NULL, "expected NULL\n");
|
||||||
|
context = CertCreateCRLContext(X509_ASN_ENCODING, signedCRL,
|
||||||
|
sizeof(signedCRL));
|
||||||
|
dupContext = CertDuplicateCRLContext(context);
|
||||||
|
ok(dupContext != NULL, "expected a context\n");
|
||||||
|
ok(dupContext == context, "expected identical context addresses\n");
|
||||||
|
CertFreeCRLContext(dupContext);
|
||||||
|
CertFreeCRLContext(context);
|
||||||
|
}
|
||||||
|
|
||||||
static void testAddCRL(void)
|
static void testAddCRL(void)
|
||||||
{
|
{
|
||||||
HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
||||||
|
@ -722,6 +737,7 @@ START_TEST(crl)
|
||||||
init_function_pointers();
|
init_function_pointers();
|
||||||
|
|
||||||
testCreateCRL();
|
testCreateCRL();
|
||||||
|
testDupCRL();
|
||||||
testAddCRL();
|
testAddCRL();
|
||||||
testFindCRL();
|
testFindCRL();
|
||||||
testGetCRLFromStore();
|
testGetCRLFromStore();
|
||||||
|
|
|
@ -187,6 +187,21 @@ static void testCreateCTL(void)
|
||||||
CertFreeCTLContext(ctl);
|
CertFreeCTLContext(ctl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void testDupCTL(void)
|
||||||
|
{
|
||||||
|
PCCTL_CONTEXT context, dupContext;
|
||||||
|
|
||||||
|
context = CertDuplicateCTLContext(NULL);
|
||||||
|
ok(context == NULL, "expected NULL\n");
|
||||||
|
context = CertCreateCTLContext(X509_ASN_ENCODING,
|
||||||
|
signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent));
|
||||||
|
dupContext = CertDuplicateCTLContext(context);
|
||||||
|
ok(dupContext != NULL, "expected a context\n");
|
||||||
|
ok(dupContext == context, "expected identical context addresses\n");
|
||||||
|
CertFreeCTLContext(dupContext);
|
||||||
|
CertFreeCTLContext(context);
|
||||||
|
}
|
||||||
|
|
||||||
static void checkHash(const BYTE *data, DWORD dataLen, ALG_ID algID,
|
static void checkHash(const BYTE *data, DWORD dataLen, ALG_ID algID,
|
||||||
PCCTL_CONTEXT context, DWORD propID)
|
PCCTL_CONTEXT context, DWORD propID)
|
||||||
{
|
{
|
||||||
|
@ -444,6 +459,7 @@ static void testAddCTLToStore(void)
|
||||||
START_TEST(ctl)
|
START_TEST(ctl)
|
||||||
{
|
{
|
||||||
testCreateCTL();
|
testCreateCTL();
|
||||||
|
testDupCTL();
|
||||||
testCTLProperties();
|
testCTLProperties();
|
||||||
testAddCTLToStore();
|
testAddCTLToStore();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1264,6 +1264,9 @@ static BYTE bmpCommonNameValue[] = {
|
||||||
0x61,0x00,0x6e,0x00,0x67,0x00,0x00 };
|
0x61,0x00,0x6e,0x00,0x67,0x00,0x00 };
|
||||||
static BYTE utf8CommonNameValue[] = {
|
static BYTE utf8CommonNameValue[] = {
|
||||||
0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
|
0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
|
||||||
|
static char embedded_null[] = "foo\0com";
|
||||||
|
static BYTE ia5EmbeddedNull[] = {
|
||||||
|
0x16,0x07,0x66,0x6f,0x6f,0x00,0x63,0x6f,0x6d };
|
||||||
|
|
||||||
static struct EncodedNameValue nameValues[] = {
|
static struct EncodedNameValue nameValues[] = {
|
||||||
{ { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
|
{ { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
|
||||||
|
@ -1299,6 +1302,12 @@ static struct EncodedNameValue nameValues[] = {
|
||||||
{ { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
|
{ { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
|
||||||
bin44, sizeof(bin44) },
|
bin44, sizeof(bin44) },
|
||||||
};
|
};
|
||||||
|
/* This is kept separate, because the decoding doesn't return to the original
|
||||||
|
* value.
|
||||||
|
*/
|
||||||
|
static struct EncodedNameValue embeddedNullNameValue = {
|
||||||
|
{ CERT_RDN_IA5_STRING, { sizeof(embedded_null) - 1, (BYTE *)embedded_null } },
|
||||||
|
ia5EmbeddedNull, sizeof(ia5EmbeddedNull) };
|
||||||
|
|
||||||
static void test_encodeNameValue(DWORD dwEncoding)
|
static void test_encodeNameValue(DWORD dwEncoding)
|
||||||
{
|
{
|
||||||
|
@ -1337,6 +1346,19 @@ static void test_encodeNameValue(DWORD dwEncoding)
|
||||||
LocalFree(buf);
|
LocalFree(buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
|
||||||
|
&embeddedNullNameValue.value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
||||||
|
ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH) /* NT4/Win9x */,
|
||||||
|
"Type %d: CryptEncodeObjectEx failed: %08x\n",
|
||||||
|
embeddedNullNameValue.value.dwValueType, GetLastError());
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
ok(size == embeddedNullNameValue.encodedSize,
|
||||||
|
"Expected size %d, got %d\n", embeddedNullNameValue.encodedSize, size);
|
||||||
|
ok(!memcmp(buf, embeddedNullNameValue.encoded, size),
|
||||||
|
"Got unexpected encoding\n");
|
||||||
|
LocalFree(buf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_decodeNameValue(DWORD dwEncoding)
|
static void test_decodeNameValue(DWORD dwEncoding)
|
||||||
|
@ -1361,6 +1383,45 @@ static void test_decodeNameValue(DWORD dwEncoding)
|
||||||
LocalFree(buf);
|
LocalFree(buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
|
||||||
|
embeddedNullNameValue.encoded, embeddedNullNameValue.encodedSize,
|
||||||
|
CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
|
||||||
|
&buf, &bufSize);
|
||||||
|
ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
|
||||||
|
embeddedNullNameValue.value.dwValueType, GetLastError());
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
CERT_NAME_VALUE rdnEncodedValue = { CERT_RDN_ENCODED_BLOB,
|
||||||
|
{ sizeof(ia5EmbeddedNull), ia5EmbeddedNull } };
|
||||||
|
CERT_NAME_VALUE embeddedNullValue = { CERT_RDN_IA5_STRING,
|
||||||
|
{ sizeof(embedded_null) - 1, (BYTE *)embedded_null } };
|
||||||
|
const CERT_NAME_VALUE *got = (const CERT_NAME_VALUE *)buf,
|
||||||
|
*expected = NULL;
|
||||||
|
|
||||||
|
/* Some Windows versions decode name values with embedded NULLs,
|
||||||
|
* others leave them encoded, even with the same version of crypt32.
|
||||||
|
* Accept either.
|
||||||
|
*/
|
||||||
|
ok(got->dwValueType == CERT_RDN_ENCODED_BLOB ||
|
||||||
|
got->dwValueType == CERT_RDN_IA5_STRING,
|
||||||
|
"Expected CERT_RDN_ENCODED_BLOB or CERT_RDN_IA5_STRING, got %d\n",
|
||||||
|
got->dwValueType);
|
||||||
|
if (got->dwValueType == CERT_RDN_ENCODED_BLOB)
|
||||||
|
expected = &rdnEncodedValue;
|
||||||
|
else if (got->dwValueType == CERT_RDN_IA5_STRING)
|
||||||
|
expected = &embeddedNullValue;
|
||||||
|
if (expected)
|
||||||
|
{
|
||||||
|
ok(got->Value.cbData == expected->Value.cbData,
|
||||||
|
"String type %d: unexpected data size, got %d, expected %d\n",
|
||||||
|
got->dwValueType, got->Value.cbData, expected->Value.cbData);
|
||||||
|
if (got->Value.cbData && got->Value.pbData)
|
||||||
|
ok(!memcmp(got->Value.pbData, expected->Value.pbData,
|
||||||
|
min(got->Value.cbData, expected->Value.cbData)),
|
||||||
|
"String type %d: unexpected value\n", expected->dwValueType);
|
||||||
|
}
|
||||||
|
LocalFree(buf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
|
static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
|
||||||
|
@ -1504,6 +1565,12 @@ static void test_decodeAltName(DWORD dwEncoding)
|
||||||
0x00, 0x00, 0x01 };
|
0x00, 0x00, 0x01 };
|
||||||
static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
|
static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
|
||||||
0x01 };
|
0x01 };
|
||||||
|
static const BYTE dns_embedded_null[] = { 0x30,0x10,0x82,0x0e,0x66,0x6f,
|
||||||
|
0x6f,0x2e,0x63,0x6f,0x6d,0x00,0x62,0x61,0x64,0x64,0x69,0x65 };
|
||||||
|
static const BYTE dns_embedded_bell[] = { 0x30,0x10,0x82,0x0e,0x66,0x6f,
|
||||||
|
0x6f,0x2e,0x63,0x6f,0x6d,0x07,0x62,0x61,0x64,0x64,0x69,0x65 };
|
||||||
|
static const BYTE url_embedded_null[] = { 0x30,0x10,0x86,0x0e,0x66,0x6f,
|
||||||
|
0x6f,0x2e,0x63,0x6f,0x6d,0x00,0x62,0x61,0x64,0x64,0x69,0x65 };
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
BYTE *buf = NULL;
|
BYTE *buf = NULL;
|
||||||
DWORD bufSize = 0;
|
DWORD bufSize = 0;
|
||||||
|
@ -1642,6 +1709,40 @@ static void test_decodeAltName(DWORD dwEncoding)
|
||||||
"Unexpected directory name value\n");
|
"Unexpected directory name value\n");
|
||||||
LocalFree(buf);
|
LocalFree(buf);
|
||||||
}
|
}
|
||||||
|
ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
|
||||||
|
dns_embedded_null, sizeof(dns_embedded_null), CRYPT_DECODE_ALLOC_FLAG,
|
||||||
|
NULL, &buf, &bufSize);
|
||||||
|
/* Fails on WinXP with CRYPT_E_ASN1_RULE. I'm not too concerned about the
|
||||||
|
* particular failure, just that it doesn't decode.
|
||||||
|
* It succeeds on (broken) Windows versions that haven't addressed
|
||||||
|
* embedded NULLs in alternate names.
|
||||||
|
*/
|
||||||
|
ok(!ret || broken(ret), "expected failure\n");
|
||||||
|
/* An embedded bell character is allowed, however. */
|
||||||
|
ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
|
||||||
|
dns_embedded_bell, sizeof(dns_embedded_bell), CRYPT_DECODE_ALLOC_FLAG,
|
||||||
|
NULL, &buf, &bufSize);
|
||||||
|
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
info = (CERT_ALT_NAME_INFO *)buf;
|
||||||
|
|
||||||
|
ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
|
||||||
|
info->cAltEntry);
|
||||||
|
ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
|
||||||
|
"Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
|
||||||
|
info->rgAltEntry[0].dwAltNameChoice);
|
||||||
|
LocalFree(buf);
|
||||||
|
}
|
||||||
|
ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
|
||||||
|
url_embedded_null, sizeof(dns_embedded_null), CRYPT_DECODE_ALLOC_FLAG,
|
||||||
|
NULL, &buf, &bufSize);
|
||||||
|
/* Again, fails on WinXP with CRYPT_E_ASN1_RULE. I'm not too concerned
|
||||||
|
* about the particular failure, just that it doesn't decode.
|
||||||
|
* It succeeds on (broken) Windows versions that haven't addressed
|
||||||
|
* embedded NULLs in alternate names.
|
||||||
|
*/
|
||||||
|
ok(!ret || broken(ret), "expected failure\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UnicodeExpectedError
|
struct UnicodeExpectedError
|
||||||
|
@ -2613,8 +2714,8 @@ static void test_decodeExtensions(DWORD dwEncoding)
|
||||||
|
|
||||||
/* MS encodes public key info with a NULL if the algorithm identifier's
|
/* MS encodes public key info with a NULL if the algorithm identifier's
|
||||||
* parameters are empty. However, when encoding an algorithm in a CERT_INFO,
|
* parameters are empty. However, when encoding an algorithm in a CERT_INFO,
|
||||||
* it encodes them by omitting the algorithm parameters. This latter approach
|
* it encodes them by omitting the algorithm parameters. It accepts either
|
||||||
* seems more correct, so accept either form.
|
* form for decoding.
|
||||||
*/
|
*/
|
||||||
struct encodedPublicKey
|
struct encodedPublicKey
|
||||||
{
|
{
|
||||||
|
@ -2692,16 +2793,11 @@ static void test_encodePublicKeyInfo(DWORD dwEncoding)
|
||||||
"CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
"CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
||||||
if (buf)
|
if (buf)
|
||||||
{
|
{
|
||||||
ok(bufSize == pubKeys[i].encoded[1] + 2 ||
|
ok(bufSize == pubKeys[i].encoded[1] + 2,
|
||||||
bufSize == pubKeys[i].encodedNoNull[1] + 2,
|
"Expected %d bytes, got %d\n", pubKeys[i].encoded[1] + 2, bufSize);
|
||||||
"Expected %d or %d bytes, got %d\n", pubKeys[i].encoded[1] + 2,
|
|
||||||
pubKeys[i].encodedNoNull[1] + 2, bufSize);
|
|
||||||
if (bufSize == pubKeys[i].encoded[1] + 2)
|
if (bufSize == pubKeys[i].encoded[1] + 2)
|
||||||
ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
|
ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
|
||||||
"Unexpected value\n");
|
"Unexpected value\n");
|
||||||
else if (bufSize == pubKeys[i].encodedNoNull[1] + 2)
|
|
||||||
ok(!memcmp(buf, pubKeys[i].encodedNoNull,
|
|
||||||
pubKeys[i].encodedNoNull[1] + 2), "Unexpected value\n");
|
|
||||||
LocalFree(buf);
|
LocalFree(buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2789,6 +2885,11 @@ static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
|
||||||
0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
|
0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 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, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
|
0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
|
||||||
|
static const BYTE v4Cert[] = {
|
||||||
|
0x30,0x38,0xa0,0x03,0x02,0x01,0x03,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,
|
||||||
|
0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
|
||||||
|
0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,
|
||||||
|
0x30,0x30,0x30,0x5a,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00 };
|
||||||
static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
|
static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
|
||||||
0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
|
0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
|
||||||
0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
|
0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
|
||||||
|
@ -2846,6 +2947,35 @@ static const BYTE v1CertWithSubjectKeyId[] = {
|
||||||
0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
|
0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
|
||||||
0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
|
0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
|
||||||
0x4c,0x61,0x6e,0x67,0x00 };
|
0x4c,0x61,0x6e,0x67,0x00 };
|
||||||
|
static const BYTE v1CertWithIssuerUniqueId[] = {
|
||||||
|
0x30,0x38,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
|
||||||
|
0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,
|
||||||
|
0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
|
||||||
|
0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x81,0x02,0x00,0x01 };
|
||||||
|
static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueId[] = {
|
||||||
|
0x30,0x81,0x99,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
|
||||||
|
0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
|
||||||
|
0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
|
||||||
|
0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
|
||||||
|
0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
|
||||||
|
0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
|
||||||
|
0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
|
||||||
|
0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
|
||||||
|
0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,
|
||||||
|
0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,
|
||||||
|
0x01,0x01,0xff,0x02,0x01,0x01 };
|
||||||
|
static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull[] = {
|
||||||
|
0x30,0x81,0x97,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
|
||||||
|
0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
|
||||||
|
0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
|
||||||
|
0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
|
||||||
|
0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
|
||||||
|
0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
|
||||||
|
0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
|
||||||
|
0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
|
||||||
|
0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,
|
||||||
|
0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
|
||||||
|
0xff,0x02,0x01,0x01 };
|
||||||
|
|
||||||
static const BYTE serialNum[] = { 0x01 };
|
static const BYTE serialNum[] = { 0x01 };
|
||||||
|
|
||||||
|
@ -2903,6 +3033,16 @@ static void test_encodeCertToBeSigned(DWORD dwEncoding)
|
||||||
ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
|
ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
|
||||||
LocalFree(buf);
|
LocalFree(buf);
|
||||||
}
|
}
|
||||||
|
/* A v4 cert? */
|
||||||
|
info.dwVersion = 3; /* Not a typo, CERT_V3 is 2 */
|
||||||
|
ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
|
||||||
|
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
||||||
|
if (buf)
|
||||||
|
{
|
||||||
|
ok(size == sizeof(v4Cert), "Wrong size %d\n", size);
|
||||||
|
ok(!memcmp(buf, v4Cert, size), "Unexpected value\n");
|
||||||
|
LocalFree(buf);
|
||||||
|
}
|
||||||
/* see if a V1 cert can have basic constraints set (RFC3280 says no, but
|
/* see if a V1 cert can have basic constraints set (RFC3280 says no, but
|
||||||
* API doesn't prevent it)
|
* API doesn't prevent it)
|
||||||
*/
|
*/
|
||||||
|
@ -2930,7 +3070,27 @@ static void test_encodeCertToBeSigned(DWORD dwEncoding)
|
||||||
ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
|
ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
|
||||||
LocalFree(buf);
|
LocalFree(buf);
|
||||||
}
|
}
|
||||||
|
/* Test v1 cert with an issuer name, serial number, and issuer unique id */
|
||||||
|
info.dwVersion = CERT_V1;
|
||||||
|
info.cExtension = 0;
|
||||||
|
info.IssuerUniqueId.cbData = sizeof(serialNum);
|
||||||
|
info.IssuerUniqueId.pbData = (BYTE *)serialNum;
|
||||||
|
ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
|
||||||
|
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
||||||
|
ok(ret || broken(GetLastError() == OSS_BAD_PTR /* Win98 */),
|
||||||
|
"CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
||||||
|
if (buf)
|
||||||
|
{
|
||||||
|
ok(size == sizeof(v1CertWithIssuerUniqueId), "Wrong size %d\n", size);
|
||||||
|
ok(!memcmp(buf, v1CertWithIssuerUniqueId, size),
|
||||||
|
"Got unexpected value\n");
|
||||||
|
LocalFree(buf);
|
||||||
|
}
|
||||||
/* Test v1 cert with an issuer name, a subject name, and a serial number */
|
/* Test v1 cert with an issuer name, a subject name, and a serial number */
|
||||||
|
info.IssuerUniqueId.cbData = 0;
|
||||||
|
info.IssuerUniqueId.pbData = NULL;
|
||||||
|
info.cExtension = 1;
|
||||||
|
info.rgExtension = &criticalExt;
|
||||||
info.Issuer.cbData = sizeof(encodedCommonName);
|
info.Issuer.cbData = sizeof(encodedCommonName);
|
||||||
info.Issuer.pbData = (BYTE *)encodedCommonName;
|
info.Issuer.pbData = (BYTE *)encodedCommonName;
|
||||||
info.Subject.cbData = sizeof(encodedCommonName);
|
info.Subject.cbData = sizeof(encodedCommonName);
|
||||||
|
@ -2960,7 +3120,30 @@ static void test_encodeCertToBeSigned(DWORD dwEncoding)
|
||||||
"Got unexpected value\n");
|
"Got unexpected value\n");
|
||||||
LocalFree(buf);
|
LocalFree(buf);
|
||||||
}
|
}
|
||||||
|
/* Again add an issuer unique id */
|
||||||
|
info.IssuerUniqueId.cbData = sizeof(serialNum);
|
||||||
|
info.IssuerUniqueId.pbData = (BYTE *)serialNum;
|
||||||
|
ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
|
||||||
|
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
||||||
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
||||||
|
if (buf)
|
||||||
|
{
|
||||||
|
ok(size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId) ||
|
||||||
|
size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull),
|
||||||
|
"Wrong size %d\n", size);
|
||||||
|
if (size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId))
|
||||||
|
ok(!memcmp(buf, v1CertWithSubjectIssuerSerialAndIssuerUniqueId,
|
||||||
|
size), "unexpected value\n");
|
||||||
|
else if (size ==
|
||||||
|
sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull))
|
||||||
|
ok(!memcmp(buf,
|
||||||
|
v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull, size),
|
||||||
|
"unexpected value\n");
|
||||||
|
LocalFree(buf);
|
||||||
|
}
|
||||||
/* Remove the public key, and add a subject key identifier extension */
|
/* Remove the public key, and add a subject key identifier extension */
|
||||||
|
info.IssuerUniqueId.cbData = 0;
|
||||||
|
info.IssuerUniqueId.pbData = NULL;
|
||||||
info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
|
info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
|
||||||
info.SubjectPublicKeyInfo.PublicKey.cbData = 0;
|
info.SubjectPublicKeyInfo.PublicKey.cbData = 0;
|
||||||
info.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
|
info.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
|
||||||
|
@ -2982,8 +3165,8 @@ static void test_encodeCertToBeSigned(DWORD dwEncoding)
|
||||||
|
|
||||||
static void test_decodeCertToBeSigned(DWORD dwEncoding)
|
static void test_decodeCertToBeSigned(DWORD dwEncoding)
|
||||||
{
|
{
|
||||||
static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
|
static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert, v4Cert,
|
||||||
v1CertWithConstraints, v1CertWithSerial };
|
v1CertWithConstraints, v1CertWithSerial, v1CertWithIssuerUniqueId };
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
BYTE *buf = NULL;
|
BYTE *buf = NULL;
|
||||||
DWORD size = 0, i;
|
DWORD size = 0, i;
|
||||||
|
@ -3002,9 +3185,9 @@ static void test_decodeCertToBeSigned(DWORD dwEncoding)
|
||||||
ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
|
ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
|
||||||
"Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
|
"Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
|
||||||
}
|
}
|
||||||
/* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
|
/* The following certs all fail with CRYPT_E_ASN1_CORRUPT or
|
||||||
* minimum a cert must have a non-zero serial number, an issuer, and a
|
* CRYPT_E_ASN1_BADTAG, because at a minimum a cert must have a non-zero
|
||||||
* subject.
|
* serial number, an issuer, a subject, and a public key.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
|
for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
|
||||||
{
|
{
|
||||||
|
@ -3013,6 +3196,45 @@ static void test_decodeCertToBeSigned(DWORD dwEncoding)
|
||||||
&buf, &size);
|
&buf, &size);
|
||||||
ok(!ret, "Expected failure\n");
|
ok(!ret, "Expected failure\n");
|
||||||
}
|
}
|
||||||
|
/* The following succeeds, even though v1 certs are not allowed to have
|
||||||
|
* extensions.
|
||||||
|
*/
|
||||||
|
ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
|
||||||
|
v1CertWithSubjectKeyId, sizeof(v1CertWithSubjectKeyId),
|
||||||
|
CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
|
||||||
|
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
CERT_INFO *info = (CERT_INFO *)buf;
|
||||||
|
|
||||||
|
ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
|
||||||
|
ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
|
||||||
|
info->dwVersion);
|
||||||
|
ok(info->cExtension == 1, "expected 1 extension, got %d\n",
|
||||||
|
info->cExtension);
|
||||||
|
LocalFree(buf);
|
||||||
|
}
|
||||||
|
/* The following also succeeds, even though V1 certs are not allowed to
|
||||||
|
* have issuer unique ids.
|
||||||
|
*/
|
||||||
|
ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
|
||||||
|
v1CertWithSubjectIssuerSerialAndIssuerUniqueId,
|
||||||
|
sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId),
|
||||||
|
CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
|
||||||
|
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
CERT_INFO *info = (CERT_INFO *)buf;
|
||||||
|
|
||||||
|
ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
|
||||||
|
ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
|
||||||
|
info->dwVersion);
|
||||||
|
ok(info->IssuerUniqueId.cbData == sizeof(serialNum),
|
||||||
|
"unexpected issuer unique id size %d\n", info->IssuerUniqueId.cbData);
|
||||||
|
ok(!memcmp(info->IssuerUniqueId.pbData, serialNum, sizeof(serialNum)),
|
||||||
|
"unexpected issuer unique id value\n");
|
||||||
|
LocalFree(buf);
|
||||||
|
}
|
||||||
/* Now check with serial number, subject and issuer specified */
|
/* Now check with serial number, subject and issuer specified */
|
||||||
ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
|
ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
|
||||||
sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
|
sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
|
||||||
|
@ -5520,7 +5742,10 @@ static void test_decodeCTL(DWORD dwEncoding)
|
||||||
SetLastError(0xdeadbeef);
|
SetLastError(0xdeadbeef);
|
||||||
ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry,
|
ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry,
|
||||||
sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
|
sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
|
||||||
ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD || CRYPT_E_ASN1_CORRUPT),
|
ok(!ret &&
|
||||||
|
(GetLastError() == CRYPT_E_ASN1_EOD ||
|
||||||
|
GetLastError() == CRYPT_E_ASN1_CORRUPT ||
|
||||||
|
GetLastError() == OSS_MORE_INPUT), /* Win9x */
|
||||||
"expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08x\n",
|
"expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08x\n",
|
||||||
GetLastError());
|
GetLastError());
|
||||||
info.SubjectAlgorithm.Parameters.cbData = 0;
|
info.SubjectAlgorithm.Parameters.cbData = 0;
|
||||||
|
@ -7302,6 +7527,305 @@ static void test_decodeCertPolicies(DWORD dwEncoding)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const BYTE policyMappingWithOneMapping[] = {
|
||||||
|
0x30,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04 };
|
||||||
|
static const BYTE policyMappingWithTwoMappings[] = {
|
||||||
|
0x30,0x14,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04,0x30,0x08,0x06,
|
||||||
|
0x02,0x2b,0x04,0x06,0x02,0x55,0x06 };
|
||||||
|
static const LPCSTR mappingOids[] = { X509_POLICY_MAPPINGS,
|
||||||
|
szOID_POLICY_MAPPINGS, szOID_LEGACY_POLICY_MAPPINGS };
|
||||||
|
|
||||||
|
static void test_encodeCertPolicyMappings(DWORD dwEncoding)
|
||||||
|
{
|
||||||
|
static char oid2[] = "2.3.4";
|
||||||
|
static char oid3[] = "1.3.4";
|
||||||
|
static char oid4[] = "2.5.6";
|
||||||
|
BOOL ret;
|
||||||
|
CERT_POLICY_MAPPINGS_INFO info = { 0 };
|
||||||
|
CERT_POLICY_MAPPING mapping[2];
|
||||||
|
LPBYTE buf;
|
||||||
|
DWORD size, i;
|
||||||
|
|
||||||
|
/* Each of the mapping OIDs is equivalent, so check with all of them */
|
||||||
|
for (i = 0; i < sizeof(mappingOids) / sizeof(mappingOids[0]); i++)
|
||||||
|
{
|
||||||
|
memset(&info, 0, sizeof(info));
|
||||||
|
ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
|
||||||
|
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
||||||
|
ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
|
||||||
|
"CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
||||||
|
if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
|
||||||
|
{
|
||||||
|
win_skip("no policy mappings support\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
|
||||||
|
ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
|
||||||
|
"unexpected value\n");
|
||||||
|
LocalFree(buf);
|
||||||
|
}
|
||||||
|
mapping[0].pszIssuerDomainPolicy = NULL;
|
||||||
|
mapping[0].pszSubjectDomainPolicy = NULL;
|
||||||
|
info.cPolicyMapping = 1;
|
||||||
|
info.rgPolicyMapping = mapping;
|
||||||
|
SetLastError(0xdeadbeef);
|
||||||
|
ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
|
||||||
|
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
||||||
|
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||||
|
"expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||||
|
mapping[0].pszIssuerDomainPolicy = oid1;
|
||||||
|
mapping[0].pszSubjectDomainPolicy = oid2;
|
||||||
|
ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
|
||||||
|
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
||||||
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
ok(size == sizeof(policyMappingWithOneMapping),
|
||||||
|
"unexpected size %d\n", size);
|
||||||
|
ok(!memcmp(buf, policyMappingWithOneMapping, size),
|
||||||
|
"unexpected value\n");
|
||||||
|
LocalFree(buf);
|
||||||
|
}
|
||||||
|
mapping[1].pszIssuerDomainPolicy = oid3;
|
||||||
|
mapping[1].pszSubjectDomainPolicy = oid4;
|
||||||
|
info.cPolicyMapping = 2;
|
||||||
|
ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
|
||||||
|
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
||||||
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
ok(size == sizeof(policyMappingWithTwoMappings),
|
||||||
|
"unexpected size %d\n", size);
|
||||||
|
ok(!memcmp(buf, policyMappingWithTwoMappings, size),
|
||||||
|
"unexpected value\n");
|
||||||
|
LocalFree(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_decodeCertPolicyMappings(DWORD dwEncoding)
|
||||||
|
{
|
||||||
|
DWORD size, i;
|
||||||
|
CERT_POLICY_MAPPINGS_INFO *info;
|
||||||
|
BOOL ret;
|
||||||
|
|
||||||
|
/* Each of the mapping OIDs is equivalent, so check with all of them */
|
||||||
|
for (i = 0; i < sizeof(mappingOids) / sizeof(mappingOids[0]); i++)
|
||||||
|
{
|
||||||
|
ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
|
||||||
|
emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
|
||||||
|
&info, &size);
|
||||||
|
ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
|
||||||
|
"CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
||||||
|
if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
|
||||||
|
{
|
||||||
|
win_skip("no policy mappings support\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
ok(info->cPolicyMapping == 0,
|
||||||
|
"expected 0 policy mappings, got %d\n", info->cPolicyMapping);
|
||||||
|
LocalFree(info);
|
||||||
|
}
|
||||||
|
ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
|
||||||
|
policyMappingWithOneMapping, sizeof(policyMappingWithOneMapping),
|
||||||
|
CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
|
||||||
|
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
ok(info->cPolicyMapping == 1,
|
||||||
|
"expected 1 policy mappings, got %d\n", info->cPolicyMapping);
|
||||||
|
ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"),
|
||||||
|
"unexpected issuer policy %s\n",
|
||||||
|
info->rgPolicyMapping[0].pszIssuerDomainPolicy);
|
||||||
|
ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy,
|
||||||
|
"2.3.4"), "unexpected subject policy %s\n",
|
||||||
|
info->rgPolicyMapping[0].pszSubjectDomainPolicy);
|
||||||
|
LocalFree(info);
|
||||||
|
}
|
||||||
|
ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
|
||||||
|
policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings),
|
||||||
|
CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
|
||||||
|
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
ok(info->cPolicyMapping == 2,
|
||||||
|
"expected 2 policy mappings, got %d\n", info->cPolicyMapping);
|
||||||
|
ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"),
|
||||||
|
"unexpected issuer policy %s\n",
|
||||||
|
info->rgPolicyMapping[0].pszIssuerDomainPolicy);
|
||||||
|
ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy,
|
||||||
|
"2.3.4"), "unexpected subject policy %s\n",
|
||||||
|
info->rgPolicyMapping[0].pszSubjectDomainPolicy);
|
||||||
|
ok(!strcmp(info->rgPolicyMapping[1].pszIssuerDomainPolicy, "1.3.4"),
|
||||||
|
"unexpected issuer policy %s\n",
|
||||||
|
info->rgPolicyMapping[1].pszIssuerDomainPolicy);
|
||||||
|
ok(!strcmp(info->rgPolicyMapping[1].pszSubjectDomainPolicy,
|
||||||
|
"2.5.6"), "unexpected subject policy %s\n",
|
||||||
|
info->rgPolicyMapping[1].pszSubjectDomainPolicy);
|
||||||
|
LocalFree(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const BYTE policyConstraintsWithRequireExplicit[] = {
|
||||||
|
0x30,0x03,0x80,0x01,0x00 };
|
||||||
|
static const BYTE policyConstraintsWithInhibitMapping[] = {
|
||||||
|
0x30,0x03,0x81,0x01,0x01 };
|
||||||
|
static const BYTE policyConstraintsWithBoth[] = {
|
||||||
|
0x30,0x06,0x80,0x01,0x01,0x81,0x01,0x01 };
|
||||||
|
|
||||||
|
static void test_encodeCertPolicyConstraints(DWORD dwEncoding)
|
||||||
|
{
|
||||||
|
CERT_POLICY_CONSTRAINTS_INFO info = { 0 };
|
||||||
|
LPBYTE buf;
|
||||||
|
DWORD size;
|
||||||
|
BOOL ret;
|
||||||
|
|
||||||
|
/* Even though RFC 5280 explicitly states CAs must not issue empty
|
||||||
|
* policy constraints (section 4.2.1.11), the API doesn't prevent it.
|
||||||
|
*/
|
||||||
|
ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
|
||||||
|
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
||||||
|
ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
|
||||||
|
"CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
||||||
|
if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
|
||||||
|
{
|
||||||
|
win_skip("no policy constraints support\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
|
||||||
|
ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
|
||||||
|
"unexpected value\n");
|
||||||
|
LocalFree(buf);
|
||||||
|
}
|
||||||
|
/* If fRequireExplicitPolicy is set but dwRequireExplicitPolicySkipCerts
|
||||||
|
* is not, then a skip of 0 is encoded.
|
||||||
|
*/
|
||||||
|
info.fRequireExplicitPolicy = TRUE;
|
||||||
|
ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
|
||||||
|
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
||||||
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
ok(size == sizeof(policyConstraintsWithRequireExplicit),
|
||||||
|
"unexpected size %d\n", size);
|
||||||
|
ok(!memcmp(buf, policyConstraintsWithRequireExplicit,
|
||||||
|
sizeof(policyConstraintsWithRequireExplicit)), "unexpected value\n");
|
||||||
|
LocalFree(buf);
|
||||||
|
}
|
||||||
|
/* With inhibit policy mapping */
|
||||||
|
info.fRequireExplicitPolicy = FALSE;
|
||||||
|
info.dwRequireExplicitPolicySkipCerts = 0;
|
||||||
|
info.fInhibitPolicyMapping = TRUE;
|
||||||
|
info.dwInhibitPolicyMappingSkipCerts = 1;
|
||||||
|
ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
|
||||||
|
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
||||||
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
ok(size == sizeof(policyConstraintsWithInhibitMapping),
|
||||||
|
"unexpected size %d\n", size);
|
||||||
|
ok(!memcmp(buf, policyConstraintsWithInhibitMapping,
|
||||||
|
sizeof(policyConstraintsWithInhibitMapping)), "unexpected value\n");
|
||||||
|
LocalFree(buf);
|
||||||
|
}
|
||||||
|
/* And with both */
|
||||||
|
info.fRequireExplicitPolicy = TRUE;
|
||||||
|
info.dwRequireExplicitPolicySkipCerts = 1;
|
||||||
|
ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
|
||||||
|
CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
|
||||||
|
ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
ok(size == sizeof(policyConstraintsWithBoth), "unexpected size %d\n",
|
||||||
|
size);
|
||||||
|
ok(!memcmp(buf, policyConstraintsWithBoth,
|
||||||
|
sizeof(policyConstraintsWithBoth)), "unexpected value\n");
|
||||||
|
LocalFree(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_decodeCertPolicyConstraints(DWORD dwEncoding)
|
||||||
|
{
|
||||||
|
CERT_POLICY_CONSTRAINTS_INFO *info;
|
||||||
|
DWORD size;
|
||||||
|
BOOL ret;
|
||||||
|
|
||||||
|
/* Again, even though CAs must not issue such constraints, they can be
|
||||||
|
* decoded.
|
||||||
|
*/
|
||||||
|
ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
|
||||||
|
emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
|
||||||
|
&info, &size);
|
||||||
|
ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
|
||||||
|
"CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
||||||
|
if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
|
||||||
|
{
|
||||||
|
win_skip("no policy mappings support\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
ok(!info->fRequireExplicitPolicy,
|
||||||
|
"expected require explicit = FALSE\n");
|
||||||
|
ok(!info->fInhibitPolicyMapping,
|
||||||
|
"expected implicit mapping = FALSE\n");
|
||||||
|
LocalFree(info);
|
||||||
|
}
|
||||||
|
ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
|
||||||
|
policyConstraintsWithRequireExplicit,
|
||||||
|
sizeof(policyConstraintsWithRequireExplicit), CRYPT_DECODE_ALLOC_FLAG,
|
||||||
|
NULL, &info, &size);
|
||||||
|
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
ok(info->fRequireExplicitPolicy,
|
||||||
|
"expected require explicit = TRUE\n");
|
||||||
|
ok(info->dwRequireExplicitPolicySkipCerts == 0, "expected 0, got %d\n",
|
||||||
|
info->dwRequireExplicitPolicySkipCerts);
|
||||||
|
ok(!info->fInhibitPolicyMapping,
|
||||||
|
"expected implicit mapping = FALSE\n");
|
||||||
|
LocalFree(info);
|
||||||
|
}
|
||||||
|
ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
|
||||||
|
policyConstraintsWithInhibitMapping,
|
||||||
|
sizeof(policyConstraintsWithInhibitMapping), CRYPT_DECODE_ALLOC_FLAG,
|
||||||
|
NULL, &info, &size);
|
||||||
|
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
ok(!info->fRequireExplicitPolicy,
|
||||||
|
"expected require explicit = FALSE\n");
|
||||||
|
ok(info->fInhibitPolicyMapping,
|
||||||
|
"expected implicit mapping = TRUE\n");
|
||||||
|
ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n",
|
||||||
|
info->dwInhibitPolicyMappingSkipCerts);
|
||||||
|
LocalFree(info);
|
||||||
|
}
|
||||||
|
ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
|
||||||
|
policyConstraintsWithBoth, sizeof(policyConstraintsWithBoth),
|
||||||
|
CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
|
||||||
|
ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
ok(info->fRequireExplicitPolicy,
|
||||||
|
"expected require explicit = TRUE\n");
|
||||||
|
ok(info->dwRequireExplicitPolicySkipCerts == 1, "expected 1, got %d\n",
|
||||||
|
info->dwRequireExplicitPolicySkipCerts);
|
||||||
|
ok(info->fInhibitPolicyMapping,
|
||||||
|
"expected implicit mapping = TRUE\n");
|
||||||
|
ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n",
|
||||||
|
info->dwInhibitPolicyMappingSkipCerts);
|
||||||
|
LocalFree(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Free *pInfo with HeapFree */
|
/* Free *pInfo with HeapFree */
|
||||||
static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
|
static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
|
||||||
{
|
{
|
||||||
|
@ -7572,6 +8096,10 @@ START_TEST(encode)
|
||||||
test_decodePolicyQualifierUserNotice(encodings[i]);
|
test_decodePolicyQualifierUserNotice(encodings[i]);
|
||||||
test_encodeCertPolicies(encodings[i]);
|
test_encodeCertPolicies(encodings[i]);
|
||||||
test_decodeCertPolicies(encodings[i]);
|
test_decodeCertPolicies(encodings[i]);
|
||||||
|
test_encodeCertPolicyMappings(encodings[i]);
|
||||||
|
test_decodeCertPolicyMappings(encodings[i]);
|
||||||
|
test_encodeCertPolicyConstraints(encodings[i]);
|
||||||
|
test_decodeCertPolicyConstraints(encodings[i]);
|
||||||
}
|
}
|
||||||
testPortPublicKeyInfo();
|
testPortPublicKeyInfo();
|
||||||
}
|
}
|
||||||
|
|
|
@ -98,16 +98,8 @@ static void testOIDToAlgID(void)
|
||||||
DWORD alg;
|
DWORD alg;
|
||||||
|
|
||||||
/* Test with a bogus one */
|
/* Test with a bogus one */
|
||||||
SetLastError(0xdeadbeef);
|
|
||||||
alg = CertOIDToAlgId("1.2.3");
|
alg = CertOIDToAlgId("1.2.3");
|
||||||
ok(!alg, "Expected failure, got %d\n", alg);
|
ok(!alg, "Expected failure, got %d\n", alg);
|
||||||
ok(GetLastError() == 0xdeadbeef ||
|
|
||||||
GetLastError() == ERROR_RESOURCE_NAME_NOT_FOUND ||
|
|
||||||
GetLastError() == ERROR_INVALID_PARAMETER || /* Vista */
|
|
||||||
GetLastError() == ERROR_SUCCESS || /* win2k */
|
|
||||||
GetLastError() == ERROR_FILE_INVALID, /* another Vista */
|
|
||||||
"Expected ERROR_RESOURCE_NAME_NOT_FOUND, ERROR_INVALID_PARAMETER, "
|
|
||||||
"ERROR_SUCCESS or no error set, got %08x\n", GetLastError());
|
|
||||||
|
|
||||||
for (i = 0; i < sizeof(oidToAlgID) / sizeof(oidToAlgID[0]); i++)
|
for (i = 0; i < sizeof(oidToAlgID) / sizeof(oidToAlgID[0]); i++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -213,6 +213,40 @@ static void test_cryptunprotectdata(void)
|
||||||
plain.cbData=0;
|
plain.cbData=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_simpleroundtrip(const char *plaintext, int wine_fails)
|
||||||
|
{
|
||||||
|
DATA_BLOB input;
|
||||||
|
DATA_BLOB encrypted;
|
||||||
|
DATA_BLOB output;
|
||||||
|
int res;
|
||||||
|
WCHAR emptyW[1];
|
||||||
|
|
||||||
|
emptyW[0] = 0;
|
||||||
|
input.pbData = (unsigned char *)plaintext;
|
||||||
|
input.cbData = strlen(plaintext);
|
||||||
|
res = pCryptProtectData(&input, emptyW, NULL, NULL, NULL, 0, &encrypted);
|
||||||
|
ok(res != 0 || broken(!res), "can't protect\n");
|
||||||
|
if (!res)
|
||||||
|
{
|
||||||
|
/* Fails on Win9x, NT4 */
|
||||||
|
win_skip("CryptProtectData failed\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = pCryptUnprotectData(&encrypted, NULL, NULL, NULL, NULL, 0, &output);
|
||||||
|
if (wine_fails) {
|
||||||
|
todo_wine
|
||||||
|
ok(res != 0, "can't unprotect; last error %u\n", GetLastError());
|
||||||
|
} else {
|
||||||
|
ok(res != 0, "can't unprotect; last error %u\n", GetLastError());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res) {
|
||||||
|
ok(output.cbData == strlen(plaintext), "output wrong length %d for input '%s', wanted %d\n", output.cbData, plaintext, strlen(plaintext));
|
||||||
|
ok(!memcmp(plaintext, (char *)output.pbData, output.cbData), "output wrong contents for input '%s'\n", plaintext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
START_TEST(protectdata)
|
START_TEST(protectdata)
|
||||||
{
|
{
|
||||||
HMODULE hCrypt32 = GetModuleHandleA("crypt32.dll");
|
HMODULE hCrypt32 = GetModuleHandleA("crypt32.dll");
|
||||||
|
@ -228,6 +262,8 @@ START_TEST(protectdata)
|
||||||
protected=FALSE;
|
protected=FALSE;
|
||||||
test_cryptprotectdata();
|
test_cryptprotectdata();
|
||||||
test_cryptunprotectdata();
|
test_cryptunprotectdata();
|
||||||
|
test_simpleroundtrip("", 1);
|
||||||
|
test_simpleroundtrip("hello", 0);
|
||||||
|
|
||||||
/* deinit globals here */
|
/* deinit globals here */
|
||||||
if (cipher.pbData) LocalFree(cipher.pbData);
|
if (cipher.pbData) LocalFree(cipher.pbData);
|
||||||
|
|
|
@ -181,8 +181,10 @@ static void test_SIPRetrieveSubjectGUID(void)
|
||||||
memset(&subject, 1, sizeof(GUID));
|
memset(&subject, 1, sizeof(GUID));
|
||||||
ret = CryptSIPRetrieveSubjectGuid(deadbeef, NULL, &subject);
|
ret = CryptSIPRetrieveSubjectGuid(deadbeef, NULL, &subject);
|
||||||
ok ( !ret, "Expected CryptSIPRetrieveSubjectGuid to fail\n");
|
ok ( !ret, "Expected CryptSIPRetrieveSubjectGuid to fail\n");
|
||||||
ok (GetLastError() == ERROR_FILE_NOT_FOUND,
|
ok (GetLastError() == ERROR_FILE_NOT_FOUND ||
|
||||||
"Expected ERROR_FILE_NOT_FOUND, got %d.\n", GetLastError());
|
GetLastError() == ERROR_PATH_NOT_FOUND,
|
||||||
|
"Expected ERROR_FILE_NOT_FOUND or ERROR_PATH_NOT_FOUND, got %d.\n",
|
||||||
|
GetLastError());
|
||||||
ok ( !memcmp(&subject, &nullSubject, sizeof(GUID)),
|
ok ( !memcmp(&subject, &nullSubject, sizeof(GUID)),
|
||||||
"Expected a NULL GUID for c:\\deadbeef.dbf, not %s\n", show_guid(&subject, guid1));
|
"Expected a NULL GUID for c:\\deadbeef.dbf, not %s\n", show_guid(&subject, guid1));
|
||||||
|
|
||||||
|
|
|
@ -277,11 +277,53 @@ static void testMemStore(void)
|
||||||
CertCloseStore(store1, 0);
|
CertCloseStore(store1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void compareFile(LPCWSTR filename, const BYTE *pb, DWORD cb)
|
||||||
|
{
|
||||||
|
HANDLE h;
|
||||||
|
BYTE buf[200];
|
||||||
|
BOOL ret;
|
||||||
|
DWORD cbRead = 0, totalRead = 0;
|
||||||
|
|
||||||
|
h = CreateFileW(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING,
|
||||||
|
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
if (h == INVALID_HANDLE_VALUE)
|
||||||
|
return;
|
||||||
|
do {
|
||||||
|
ret = ReadFile(h, buf, sizeof(buf), &cbRead, NULL);
|
||||||
|
if (ret && cbRead)
|
||||||
|
{
|
||||||
|
ok(totalRead + cbRead <= cb, "Expected total count %d, see %d\n",
|
||||||
|
cb, totalRead + cbRead);
|
||||||
|
ok(!memcmp(pb + totalRead, buf, cbRead),
|
||||||
|
"Unexpected data in file\n");
|
||||||
|
totalRead += cbRead;
|
||||||
|
}
|
||||||
|
} while (ret && cbRead);
|
||||||
|
CloseHandle(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const BYTE serializedStoreWithCert[] = {
|
||||||
|
0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x20,0x00,0x00,0x00,0x01,0x00,0x00,
|
||||||
|
0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,
|
||||||
|
0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
|
||||||
|
0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,
|
||||||
|
0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,
|
||||||
|
0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,
|
||||||
|
0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
|
||||||
|
0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,
|
||||||
|
0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,
|
||||||
|
0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00 };
|
||||||
|
|
||||||
static void testCollectionStore(void)
|
static void testCollectionStore(void)
|
||||||
{
|
{
|
||||||
HCERTSTORE store1, store2, collection, collection2;
|
HCERTSTORE store1, store2, collection, collection2;
|
||||||
PCCERT_CONTEXT context;
|
PCCERT_CONTEXT context;
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
|
static const WCHAR szPrefix[] = { 'c','e','r',0 };
|
||||||
|
static const WCHAR szDot[] = { '.',0 };
|
||||||
|
WCHAR filename[MAX_PATH];
|
||||||
|
HANDLE file;
|
||||||
|
|
||||||
if (!pCertAddStoreToCollection)
|
if (!pCertAddStoreToCollection)
|
||||||
{
|
{
|
||||||
|
@ -573,6 +615,86 @@ static void testCollectionStore(void)
|
||||||
CertCloseStore(collection, 0);
|
CertCloseStore(collection, 0);
|
||||||
CertCloseStore(store2, 0);
|
CertCloseStore(store2, 0);
|
||||||
CertCloseStore(store1, 0);
|
CertCloseStore(store1, 0);
|
||||||
|
|
||||||
|
/* Test adding certificates to and deleting certificates from collections.
|
||||||
|
*/
|
||||||
|
store1 = CertOpenSystemStoreA(0, "My");
|
||||||
|
collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
|
||||||
|
CERT_STORE_CREATE_NEW_FLAG, NULL);
|
||||||
|
|
||||||
|
ret = CertAddEncodedCertificateToStore(store1, X509_ASN_ENCODING,
|
||||||
|
bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
|
||||||
|
ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
|
||||||
|
CertDeleteCertificateFromStore(context);
|
||||||
|
|
||||||
|
CertAddStoreToCollection(collection, store1,
|
||||||
|
CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
|
||||||
|
|
||||||
|
ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
|
||||||
|
bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, &context);
|
||||||
|
ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n", GetLastError());
|
||||||
|
CertDeleteCertificateFromStore(context);
|
||||||
|
|
||||||
|
CertCloseStore(collection, 0);
|
||||||
|
CertCloseStore(store1, 0);
|
||||||
|
|
||||||
|
/* Test whether a collection store can be committed */
|
||||||
|
if (!pCertControlStore)
|
||||||
|
{
|
||||||
|
win_skip("CertControlStore() is not available\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
collection = CertOpenStore(CERT_STORE_PROV_COLLECTION, 0, 0,
|
||||||
|
CERT_STORE_CREATE_NEW_FLAG, NULL);
|
||||||
|
|
||||||
|
SetLastError(0xdeadbeef);
|
||||||
|
ret = pCertControlStore(collection, 0, CERT_STORE_CTRL_COMMIT, NULL);
|
||||||
|
ok(ret, "CertControlStore failed: %08x\n", GetLastError());
|
||||||
|
|
||||||
|
/* Adding a mem store that can't be committed prevents a successful commit.
|
||||||
|
*/
|
||||||
|
store1 = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
||||||
|
CERT_STORE_CREATE_NEW_FLAG, NULL);
|
||||||
|
pCertAddStoreToCollection(collection, store1, 0, 0);
|
||||||
|
SetLastError(0xdeadbeef);
|
||||||
|
ret = pCertControlStore(collection, 0, CERT_STORE_CTRL_COMMIT, NULL);
|
||||||
|
ok(!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED,
|
||||||
|
"expected ERROR_CALL_NOT_IMPLEMENTED, got %d\n", GetLastError());
|
||||||
|
pCertRemoveStoreFromCollection(collection, store1);
|
||||||
|
CertCloseStore(store1, 0);
|
||||||
|
|
||||||
|
/* Test adding a cert to a collection with a file store, committing the
|
||||||
|
* change to the collection, and comparing the resulting file.
|
||||||
|
*/
|
||||||
|
if (!GetTempFileNameW(szDot, szPrefix, 0, filename))
|
||||||
|
return;
|
||||||
|
|
||||||
|
DeleteFileW(filename);
|
||||||
|
file = CreateFileW(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
|
||||||
|
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
|
if (file == INVALID_HANDLE_VALUE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
store1 = CertOpenStore(CERT_STORE_PROV_FILE, 0, 0,
|
||||||
|
CERT_FILE_STORE_COMMIT_ENABLE_FLAG, file);
|
||||||
|
ok(store1 != NULL, "CertOpenStore failed: %08x\n", GetLastError());
|
||||||
|
CloseHandle(file);
|
||||||
|
pCertAddStoreToCollection(collection, store1,
|
||||||
|
CERT_PHYSICAL_STORE_ADD_ENABLE_FLAG, 0);
|
||||||
|
CertCloseStore(store1, 0);
|
||||||
|
|
||||||
|
ret = CertAddEncodedCertificateToStore(collection, X509_ASN_ENCODING,
|
||||||
|
bigCert, sizeof(bigCert), CERT_STORE_ADD_ALWAYS, NULL);
|
||||||
|
ok(ret, "CertAddEncodedCertificateToStore failed: %08x\n",
|
||||||
|
GetLastError());
|
||||||
|
ret = pCertControlStore(collection, 0, CERT_STORE_CTRL_COMMIT, NULL);
|
||||||
|
ok(ret, "CertControlStore failed: %d\n", ret);
|
||||||
|
|
||||||
|
CertCloseStore(collection, 0);
|
||||||
|
|
||||||
|
compareFile(filename, serializedStoreWithCert,
|
||||||
|
sizeof(serializedStoreWithCert));
|
||||||
|
DeleteFileW(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Looks for the property with ID propID in the buffer buf. Returns a pointer
|
/* Looks for the property with ID propID in the buffer buf. Returns a pointer
|
||||||
|
@ -1046,18 +1168,6 @@ static void testSystemStore(void)
|
||||||
RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
|
RegDeleteKeyW(HKEY_CURRENT_USER, BogusPathW);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const BYTE serializedStoreWithCert[] = {
|
|
||||||
0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x20,0x00,0x00,0x00,0x01,0x00,0x00,
|
|
||||||
0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,
|
|
||||||
0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
|
|
||||||
0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,
|
|
||||||
0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,
|
|
||||||
0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,
|
|
||||||
0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
|
|
||||||
0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,
|
|
||||||
0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,
|
|
||||||
0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
||||||
0x00,0x00,0x00,0x00,0x00,0x00 };
|
|
||||||
static const BYTE serializedStoreWithCertAndCRL[] = {
|
static const BYTE serializedStoreWithCertAndCRL[] = {
|
||||||
0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x20,0x00,0x00,0x00,0x01,0x00,0x00,
|
0x00,0x00,0x00,0x00,0x43,0x45,0x52,0x54,0x20,0x00,0x00,0x00,0x01,0x00,0x00,
|
||||||
0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,
|
0x00,0x7c,0x00,0x00,0x00,0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,
|
||||||
|
@ -1076,31 +1186,6 @@ static const BYTE serializedStoreWithCertAndCRL[] = {
|
||||||
0x00,0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,
|
0x00,0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02,
|
||||||
0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
|
0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
|
||||||
|
|
||||||
static void compareFile(LPCWSTR filename, const BYTE *pb, DWORD cb)
|
|
||||||
{
|
|
||||||
HANDLE h;
|
|
||||||
BYTE buf[200];
|
|
||||||
BOOL ret;
|
|
||||||
DWORD cbRead = 0, totalRead = 0;
|
|
||||||
|
|
||||||
h = CreateFileW(filename, GENERIC_READ, 0, NULL, OPEN_EXISTING,
|
|
||||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
|
||||||
if (h == INVALID_HANDLE_VALUE)
|
|
||||||
return;
|
|
||||||
do {
|
|
||||||
ret = ReadFile(h, buf, sizeof(buf), &cbRead, NULL);
|
|
||||||
if (ret && cbRead)
|
|
||||||
{
|
|
||||||
ok(totalRead + cbRead <= cb, "Expected total count %d, see %d\n",
|
|
||||||
cb, totalRead + cbRead);
|
|
||||||
ok(!memcmp(pb + totalRead, buf, cbRead),
|
|
||||||
"Unexpected data in file\n");
|
|
||||||
totalRead += cbRead;
|
|
||||||
}
|
|
||||||
} while (ret && cbRead);
|
|
||||||
CloseHandle(h);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void testFileStore(void)
|
static void testFileStore(void)
|
||||||
{
|
{
|
||||||
static const WCHAR szPrefix[] = { 'c','e','r',0 };
|
static const WCHAR szPrefix[] = { 'c','e','r',0 };
|
||||||
|
@ -2074,7 +2159,6 @@ static void test_I_UpdateStore(void)
|
||||||
certs = countCertsInStore(store1);
|
certs = countCertsInStore(store1);
|
||||||
ok(certs == 0, "Expected 0 certs, got %d\n", certs);
|
ok(certs == 0, "Expected 0 certs, got %d\n", certs);
|
||||||
|
|
||||||
CertFreeCertificateContext(cert);
|
|
||||||
CertCloseStore(store1, 0);
|
CertCloseStore(store1, 0);
|
||||||
CertCloseStore(store2, 0);
|
CertCloseStore(store2, 0);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue