mirror of
https://github.com/reactos/reactos.git
synced 2025-06-03 16:30:26 +00:00
add crypt32 winetest from wine 1.1.11
svn path=/trunk/; revision=38449
This commit is contained in:
parent
fbe14c277d
commit
ca3c085687
18 changed files with 22954 additions and 0 deletions
458
rostests/winetests/crypt32/base64.c
Normal file
458
rostests/winetests/crypt32/base64.c
Normal file
|
@ -0,0 +1,458 @@
|
|||
/*
|
||||
* Unit test suite for crypt32.dll's CryptStringToBinary and CryptBinaryToString
|
||||
* functions.
|
||||
*
|
||||
* Copyright 2006 Juan Lang
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#include <winerror.h>
|
||||
#include <wincrypt.h>
|
||||
|
||||
#include "wine/test.h"
|
||||
|
||||
#define CERT_HEADER "-----BEGIN CERTIFICATE-----\r\n"
|
||||
#define CERT_TRAILER "-----END CERTIFICATE-----\r\n"
|
||||
#define CERT_REQUEST_HEADER "-----BEGIN NEW CERTIFICATE REQUEST-----\r\n"
|
||||
#define CERT_REQUEST_TRAILER "-----END NEW CERTIFICATE REQUEST-----\r\n"
|
||||
#define X509_HEADER "-----BEGIN X509 CRL-----\r\n"
|
||||
#define X509_TRAILER "-----END X509 CRL-----\r\n"
|
||||
#define CERT_HEADER_NOCR "-----BEGIN CERTIFICATE-----\n"
|
||||
#define CERT_TRAILER_NOCR "-----END CERTIFICATE-----\n"
|
||||
#define CERT_REQUEST_HEADER_NOCR "-----BEGIN NEW CERTIFICATE REQUEST-----\n"
|
||||
#define CERT_REQUEST_TRAILER_NOCR "-----END NEW CERTIFICATE REQUEST-----\n"
|
||||
#define X509_HEADER_NOCR "-----BEGIN X509 CRL-----\n"
|
||||
#define X509_TRAILER_NOCR "-----END X509 CRL-----\n"
|
||||
|
||||
typedef BOOL (WINAPI *CryptBinaryToStringAFunc)(const BYTE *pbBinary,
|
||||
DWORD cbBinary, DWORD dwFlags, LPSTR pszString, DWORD *pcchString);
|
||||
typedef BOOL (WINAPI *CryptStringToBinaryAFunc)(LPCSTR pszString,
|
||||
DWORD cchString, DWORD dwFlags, BYTE *pbBinary, DWORD *pcbBinary,
|
||||
DWORD *pdwSkip, DWORD *pdwFlags);
|
||||
|
||||
CryptBinaryToStringAFunc pCryptBinaryToStringA;
|
||||
CryptStringToBinaryAFunc pCryptStringToBinaryA;
|
||||
|
||||
struct BinTests
|
||||
{
|
||||
const BYTE *toEncode;
|
||||
DWORD toEncodeLen;
|
||||
const char *base64;
|
||||
};
|
||||
|
||||
static const BYTE toEncode1[] = { 0 };
|
||||
static const BYTE toEncode2[] = { 1,2 };
|
||||
static const BYTE toEncode3[] = { 1,2,3 };
|
||||
static const BYTE toEncode4[] =
|
||||
"abcdefghijlkmnopqrstuvwxyz01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890"
|
||||
"abcdefghijlkmnopqrstuvwxyz01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890"
|
||||
"abcdefghijlkmnopqrstuvwxyz01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890";
|
||||
|
||||
struct BinTests tests[] = {
|
||||
{ toEncode1, sizeof(toEncode1), "AA==\r\n", },
|
||||
{ toEncode2, sizeof(toEncode2), "AQI=\r\n", },
|
||||
/* { toEncode3, sizeof(toEncode3), "AQID\r\n", }, This test fails on Vista. */
|
||||
{ toEncode4, sizeof(toEncode4),
|
||||
"YWJjZGVmZ2hpamxrbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5MEFCQ0RFRkdISUpL\r\n"
|
||||
"TE1OT1BRUlNUVVZXWFlaMDEyMzQ1Njc4OTBhYmNkZWZnaGlqbGttbm9wcXJzdHV2\r\n"
|
||||
"d3h5ejAxMjM0NTY3ODkwQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVowMTIzNDU2\r\n"
|
||||
"Nzg5MGFiY2RlZmdoaWpsa21ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OTBBQkNERUZH\r\n"
|
||||
"SElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NTY3ODkwAA==\r\n" },
|
||||
};
|
||||
|
||||
struct BinTests testsNoCR[] = {
|
||||
{ toEncode1, sizeof(toEncode1), "AA==\n", },
|
||||
{ toEncode2, sizeof(toEncode2), "AQI=\n", },
|
||||
/* { toEncode3, sizeof(toEncode3), "AQID\n", }, This test fails on Vista. */
|
||||
{ toEncode4, sizeof(toEncode4),
|
||||
"YWJjZGVmZ2hpamxrbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5MEFCQ0RFRkdISUpL\n"
|
||||
"TE1OT1BRUlNUVVZXWFlaMDEyMzQ1Njc4OTBhYmNkZWZnaGlqbGttbm9wcXJzdHV2\n"
|
||||
"d3h5ejAxMjM0NTY3ODkwQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVowMTIzNDU2\n"
|
||||
"Nzg5MGFiY2RlZmdoaWpsa21ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OTBBQkNERUZH\n"
|
||||
"SElKS0xNTk9QUVJTVFVWV1hZWjAxMjM0NTY3ODkwAA==\n" },
|
||||
};
|
||||
|
||||
static void encodeAndCompareBase64_A(const BYTE *toEncode, DWORD toEncodeLen,
|
||||
DWORD format, const char *expected, const char *header, const char *trailer)
|
||||
{
|
||||
DWORD strLen = 0;
|
||||
LPSTR str = NULL;
|
||||
BOOL ret;
|
||||
|
||||
ret = pCryptBinaryToStringA(toEncode, toEncodeLen, format, NULL, &strLen);
|
||||
ok(ret, "CryptBinaryToStringA failed: %d\n", GetLastError());
|
||||
str = HeapAlloc(GetProcessHeap(), 0, strLen);
|
||||
if (str)
|
||||
{
|
||||
DWORD strLen2 = strLen;
|
||||
LPCSTR ptr = str;
|
||||
|
||||
ret = pCryptBinaryToStringA(toEncode, toEncodeLen, format, str,
|
||||
&strLen2);
|
||||
ok(ret, "CryptBinaryToStringA failed: %d\n", GetLastError());
|
||||
ok(strLen2 == strLen - 1, "Expected length %d, got %d\n",
|
||||
strLen - 1, strLen);
|
||||
if (header)
|
||||
{
|
||||
ok(!strncmp(header, ptr, strlen(header)),
|
||||
"Expected header %s, got %s\n", header, ptr);
|
||||
ptr += strlen(header);
|
||||
}
|
||||
ok(!strncmp(expected, ptr, strlen(expected)),
|
||||
"Expected %s, got %s\n", expected, ptr);
|
||||
ptr += strlen(expected);
|
||||
if (trailer)
|
||||
{
|
||||
ok(!strncmp(trailer, ptr, strlen(trailer)),
|
||||
"Expected trailer %s, got %s\n", trailer, ptr);
|
||||
ptr += strlen(trailer);
|
||||
}
|
||||
HeapFree(GetProcessHeap(), 0, str);
|
||||
}
|
||||
}
|
||||
|
||||
static void testBinaryToStringA(void)
|
||||
{
|
||||
BOOL ret;
|
||||
DWORD strLen = 0, i;
|
||||
|
||||
ret = pCryptBinaryToStringA(NULL, 0, 0, NULL, NULL);
|
||||
ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
||||
ret = pCryptBinaryToStringA(NULL, 0, 0, NULL, &strLen);
|
||||
ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
||||
for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
|
||||
{
|
||||
DWORD strLen = 0;
|
||||
LPSTR str = NULL;
|
||||
BOOL ret;
|
||||
|
||||
ret = pCryptBinaryToStringA(tests[i].toEncode, tests[i].toEncodeLen,
|
||||
CRYPT_STRING_BINARY, NULL, &strLen);
|
||||
ok(ret, "CryptBinaryToStringA failed: %d\n", GetLastError());
|
||||
str = HeapAlloc(GetProcessHeap(), 0, strLen);
|
||||
if (str)
|
||||
{
|
||||
DWORD strLen2 = strLen;
|
||||
|
||||
ret = pCryptBinaryToStringA(tests[i].toEncode, tests[i].toEncodeLen,
|
||||
CRYPT_STRING_BINARY, str, &strLen2);
|
||||
ok(strLen == strLen2, "Expected length %d, got %d\n", strLen,
|
||||
strLen2);
|
||||
ok(!memcmp(str, tests[i].toEncode, tests[i].toEncodeLen),
|
||||
"Unexpected value\n");
|
||||
HeapFree(GetProcessHeap(), 0, str);
|
||||
}
|
||||
encodeAndCompareBase64_A(tests[i].toEncode, tests[i].toEncodeLen,
|
||||
CRYPT_STRING_BASE64, tests[i].base64, NULL, NULL);
|
||||
encodeAndCompareBase64_A(tests[i].toEncode, tests[i].toEncodeLen,
|
||||
CRYPT_STRING_BASE64HEADER, tests[i].base64, CERT_HEADER,
|
||||
CERT_TRAILER);
|
||||
encodeAndCompareBase64_A(tests[i].toEncode, tests[i].toEncodeLen,
|
||||
CRYPT_STRING_BASE64REQUESTHEADER, tests[i].base64,
|
||||
CERT_REQUEST_HEADER, CERT_REQUEST_TRAILER);
|
||||
encodeAndCompareBase64_A(tests[i].toEncode, tests[i].toEncodeLen,
|
||||
CRYPT_STRING_BASE64X509CRLHEADER, tests[i].base64, X509_HEADER,
|
||||
X509_TRAILER);
|
||||
}
|
||||
for (i = 0; i < sizeof(testsNoCR) / sizeof(testsNoCR[0]); i++)
|
||||
{
|
||||
DWORD strLen = 0;
|
||||
LPSTR str = NULL;
|
||||
BOOL ret;
|
||||
|
||||
ret = pCryptBinaryToStringA(testsNoCR[i].toEncode,
|
||||
testsNoCR[i].toEncodeLen, CRYPT_STRING_BINARY | CRYPT_STRING_NOCR,
|
||||
NULL, &strLen);
|
||||
ok(ret, "CryptBinaryToStringA failed: %d\n", GetLastError());
|
||||
str = HeapAlloc(GetProcessHeap(), 0, strLen);
|
||||
if (str)
|
||||
{
|
||||
DWORD strLen2 = strLen;
|
||||
|
||||
ret = pCryptBinaryToStringA(testsNoCR[i].toEncode,
|
||||
testsNoCR[i].toEncodeLen, CRYPT_STRING_BINARY | CRYPT_STRING_NOCR,
|
||||
str, &strLen2);
|
||||
ok(strLen == strLen2, "Expected length %d, got %d\n", strLen,
|
||||
strLen2);
|
||||
ok(!memcmp(str, testsNoCR[i].toEncode, testsNoCR[i].toEncodeLen),
|
||||
"Unexpected value\n");
|
||||
HeapFree(GetProcessHeap(), 0, str);
|
||||
}
|
||||
encodeAndCompareBase64_A(testsNoCR[i].toEncode,
|
||||
testsNoCR[i].toEncodeLen, CRYPT_STRING_BASE64 | CRYPT_STRING_NOCR,
|
||||
testsNoCR[i].base64, NULL, NULL);
|
||||
encodeAndCompareBase64_A(testsNoCR[i].toEncode,
|
||||
testsNoCR[i].toEncodeLen,
|
||||
CRYPT_STRING_BASE64HEADER | CRYPT_STRING_NOCR, testsNoCR[i].base64,
|
||||
CERT_HEADER_NOCR, CERT_TRAILER_NOCR);
|
||||
encodeAndCompareBase64_A(testsNoCR[i].toEncode,
|
||||
testsNoCR[i].toEncodeLen,
|
||||
CRYPT_STRING_BASE64REQUESTHEADER | CRYPT_STRING_NOCR,
|
||||
testsNoCR[i].base64, CERT_REQUEST_HEADER_NOCR,
|
||||
CERT_REQUEST_TRAILER_NOCR);
|
||||
encodeAndCompareBase64_A(testsNoCR[i].toEncode,
|
||||
testsNoCR[i].toEncodeLen,
|
||||
CRYPT_STRING_BASE64X509CRLHEADER | CRYPT_STRING_NOCR,
|
||||
testsNoCR[i].base64, X509_HEADER_NOCR, X509_TRAILER_NOCR);
|
||||
}
|
||||
}
|
||||
|
||||
static void decodeAndCompareBase64_A(LPCSTR toDecode, LPCSTR header,
|
||||
LPCSTR trailer, DWORD useFormat, DWORD expectedFormat, const BYTE *expected,
|
||||
DWORD expectedLen)
|
||||
{
|
||||
static const char garbage[] = "garbage\r\n";
|
||||
LPSTR str;
|
||||
DWORD len = strlen(toDecode) + strlen(garbage) + 1;
|
||||
|
||||
if (header)
|
||||
len += strlen(header);
|
||||
if (trailer)
|
||||
len += strlen(trailer);
|
||||
str = HeapAlloc(GetProcessHeap(), 0, len);
|
||||
if (str)
|
||||
{
|
||||
LPBYTE buf;
|
||||
DWORD bufLen = 0;
|
||||
BOOL ret;
|
||||
|
||||
if (header)
|
||||
strcpy(str, header);
|
||||
else
|
||||
*str = 0;
|
||||
strcat(str, toDecode);
|
||||
if (trailer)
|
||||
strcat(str, trailer);
|
||||
ret = pCryptStringToBinaryA(str, 0, useFormat, NULL, &bufLen, NULL,
|
||||
NULL);
|
||||
ok(ret, "CryptStringToBinaryA failed: %d\n", GetLastError());
|
||||
buf = HeapAlloc(GetProcessHeap(), 0, bufLen);
|
||||
if (buf)
|
||||
{
|
||||
DWORD skipped, usedFormat;
|
||||
|
||||
/* check as normal, make sure last two parameters are optional */
|
||||
ret = pCryptStringToBinaryA(str, 0, useFormat, buf, &bufLen, NULL,
|
||||
NULL);
|
||||
ok(ret, "CryptStringToBinaryA failed: %d\n", GetLastError());
|
||||
ok(bufLen == expectedLen,
|
||||
"Expected length %d, got %d\n", expectedLen, bufLen);
|
||||
ok(!memcmp(buf, expected, bufLen), "Unexpected value\n");
|
||||
/* check last two params */
|
||||
ret = pCryptStringToBinaryA(str, 0, useFormat, buf, &bufLen,
|
||||
&skipped, &usedFormat);
|
||||
ok(ret, "CryptStringToBinaryA failed: %d\n", GetLastError());
|
||||
ok(skipped == 0, "Expected skipped 0, got %d\n", skipped);
|
||||
ok(usedFormat == expectedFormat, "Expected format %d, got %d\n",
|
||||
expectedFormat, usedFormat);
|
||||
HeapFree(GetProcessHeap(), 0, buf);
|
||||
}
|
||||
|
||||
/* Check again, but with garbage up front */
|
||||
strcpy(str, garbage);
|
||||
if (header)
|
||||
strcat(str, header);
|
||||
strcat(str, toDecode);
|
||||
if (trailer)
|
||||
strcat(str, trailer);
|
||||
ret = pCryptStringToBinaryA(str, 0, useFormat, NULL, &bufLen, NULL,
|
||||
NULL);
|
||||
/* expect failure with no header, and success with one */
|
||||
if (header)
|
||||
ok(ret, "CryptStringToBinaryA failed: %d\n", GetLastError());
|
||||
else
|
||||
ok(!ret && GetLastError() == ERROR_INVALID_DATA,
|
||||
"Expected !ret and last error ERROR_INVALID_DATA, got ret=%d, error=%d\n", ret, GetLastError());
|
||||
if (ret)
|
||||
{
|
||||
buf = HeapAlloc(GetProcessHeap(), 0, bufLen);
|
||||
if (buf)
|
||||
{
|
||||
DWORD skipped, usedFormat;
|
||||
|
||||
ret = pCryptStringToBinaryA(str, 0, useFormat, buf, &bufLen,
|
||||
&skipped, &usedFormat);
|
||||
ok(skipped == strlen(garbage),
|
||||
"Expected %d characters of \"%s\" skipped when trying format %08x, got %d (used format is %08x)\n",
|
||||
lstrlenA(garbage), str, useFormat, skipped, usedFormat);
|
||||
HeapFree(GetProcessHeap(), 0, buf);
|
||||
}
|
||||
}
|
||||
HeapFree(GetProcessHeap(), 0, str);
|
||||
}
|
||||
}
|
||||
|
||||
struct BadString
|
||||
{
|
||||
const char *str;
|
||||
DWORD format;
|
||||
};
|
||||
|
||||
struct BadString badStrings[] = {
|
||||
{ "A\r\nA\r\n=\r\n=\r\n", CRYPT_STRING_BASE64 },
|
||||
{ "AA\r\n=\r\n=\r\n", CRYPT_STRING_BASE64 },
|
||||
{ "AA=\r\n=\r\n", CRYPT_STRING_BASE64 },
|
||||
{ "-----BEGIN X509 CRL-----\r\nAA==\r\n", CRYPT_STRING_BASE64X509CRLHEADER },
|
||||
};
|
||||
|
||||
static void testStringToBinaryA(void)
|
||||
{
|
||||
BOOL ret;
|
||||
DWORD bufLen = 0, i;
|
||||
|
||||
ret = pCryptStringToBinaryA(NULL, 0, 0, NULL, NULL, NULL, NULL);
|
||||
ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
||||
ret = pCryptStringToBinaryA(NULL, 0, 0, NULL, &bufLen, NULL, NULL);
|
||||
ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
||||
/* Bogus format */
|
||||
ret = pCryptStringToBinaryA(tests[0].base64, 0, 0, NULL, &bufLen, NULL,
|
||||
NULL);
|
||||
ok(!ret && GetLastError() == ERROR_INVALID_DATA,
|
||||
"Expected ERROR_INVALID_DATA, got %d\n", GetLastError());
|
||||
/* Decoding doesn't expect the NOCR flag to be specified */
|
||||
ret = pCryptStringToBinaryA(tests[0].base64, 1,
|
||||
CRYPT_STRING_BASE64 | CRYPT_STRING_NOCR, NULL, &bufLen, NULL, NULL);
|
||||
ok(!ret && GetLastError() == ERROR_INVALID_DATA,
|
||||
"Expected ERROR_INVALID_DATA, got %d\n", GetLastError());
|
||||
/* Bad strings */
|
||||
for (i = 0; i < sizeof(badStrings) / sizeof(badStrings[0]); i++)
|
||||
{
|
||||
bufLen = 0;
|
||||
ret = pCryptStringToBinaryA(badStrings[i].str, 0, badStrings[i].format,
|
||||
NULL, &bufLen, NULL, NULL);
|
||||
ok(!ret && GetLastError() == ERROR_INVALID_DATA,
|
||||
"Expected ERROR_INVALID_DATA, got %d\n", GetLastError());
|
||||
}
|
||||
/* Good strings */
|
||||
for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
|
||||
{
|
||||
bufLen = 0;
|
||||
/* Bogus length--oddly enough, that succeeds, even though it's not
|
||||
* properly padded.
|
||||
*/
|
||||
ret = pCryptStringToBinaryA(tests[i].base64, 1, CRYPT_STRING_BASE64,
|
||||
NULL, &bufLen, NULL, NULL);
|
||||
todo_wine ok(ret, "CryptStringToBinaryA failed: %d\n", GetLastError());
|
||||
/* Check with the precise format */
|
||||
decodeAndCompareBase64_A(tests[i].base64, NULL, NULL,
|
||||
CRYPT_STRING_BASE64, CRYPT_STRING_BASE64, tests[i].toEncode,
|
||||
tests[i].toEncodeLen);
|
||||
decodeAndCompareBase64_A(tests[i].base64, CERT_HEADER, CERT_TRAILER,
|
||||
CRYPT_STRING_BASE64HEADER, CRYPT_STRING_BASE64HEADER,
|
||||
tests[i].toEncode, tests[i].toEncodeLen);
|
||||
decodeAndCompareBase64_A(tests[i].base64, CERT_REQUEST_HEADER,
|
||||
CERT_REQUEST_TRAILER, CRYPT_STRING_BASE64REQUESTHEADER,
|
||||
CRYPT_STRING_BASE64REQUESTHEADER, tests[i].toEncode,
|
||||
tests[i].toEncodeLen);
|
||||
decodeAndCompareBase64_A(tests[i].base64, X509_HEADER, X509_TRAILER,
|
||||
CRYPT_STRING_BASE64X509CRLHEADER, CRYPT_STRING_BASE64X509CRLHEADER,
|
||||
tests[i].toEncode, tests[i].toEncodeLen);
|
||||
/* And check with the "any" formats */
|
||||
decodeAndCompareBase64_A(tests[i].base64, NULL, NULL,
|
||||
CRYPT_STRING_BASE64_ANY, CRYPT_STRING_BASE64, tests[i].toEncode,
|
||||
tests[i].toEncodeLen);
|
||||
/* Don't check with no header and the string_any format, that'll
|
||||
* always succeed.
|
||||
*/
|
||||
decodeAndCompareBase64_A(tests[i].base64, CERT_HEADER, CERT_TRAILER,
|
||||
CRYPT_STRING_BASE64_ANY, CRYPT_STRING_BASE64HEADER, tests[i].toEncode,
|
||||
tests[i].toEncodeLen);
|
||||
decodeAndCompareBase64_A(tests[i].base64, CERT_HEADER, CERT_TRAILER,
|
||||
CRYPT_STRING_ANY, CRYPT_STRING_BASE64HEADER, tests[i].toEncode,
|
||||
tests[i].toEncodeLen);
|
||||
/* oddly, these seem to decode using the wrong format
|
||||
decodeAndCompareBase64_A(tests[i].base64, CERT_REQUEST_HEADER,
|
||||
CERT_REQUEST_TRAILER, CRYPT_STRING_BASE64_ANY,
|
||||
CRYPT_STRING_BASE64REQUESTHEADER, tests[i].toEncode,
|
||||
tests[i].toEncodeLen);
|
||||
decodeAndCompareBase64_A(tests[i].base64, CERT_REQUEST_HEADER,
|
||||
CERT_REQUEST_TRAILER, CRYPT_STRING_ANY,
|
||||
CRYPT_STRING_BASE64REQUESTHEADER, tests[i].toEncode,
|
||||
tests[i].toEncodeLen);
|
||||
decodeAndCompareBase64_A(tests[i].base64, X509_HEADER, X509_TRAILER,
|
||||
CRYPT_STRING_BASE64_ANY, CRYPT_STRING_BASE64X509CRLHEADER,
|
||||
tests[i].toEncode, tests[i].toEncodeLen);
|
||||
decodeAndCompareBase64_A(tests[i].base64, X509_HEADER, X509_TRAILER,
|
||||
CRYPT_STRING_ANY, CRYPT_STRING_BASE64X509CRLHEADER, tests[i].toEncode,
|
||||
tests[i].toEncodeLen);
|
||||
*/
|
||||
}
|
||||
/* And again, with no CR--decoding handles this automatically */
|
||||
for (i = 0; i < sizeof(testsNoCR) / sizeof(testsNoCR[0]); i++)
|
||||
{
|
||||
bufLen = 0;
|
||||
/* Bogus length--oddly enough, that succeeds, even though it's not
|
||||
* properly padded.
|
||||
*/
|
||||
ret = pCryptStringToBinaryA(testsNoCR[i].base64, 1, CRYPT_STRING_BASE64,
|
||||
NULL, &bufLen, NULL, NULL);
|
||||
todo_wine ok(ret, "CryptStringToBinaryA failed: %d\n", GetLastError());
|
||||
/* Check with the precise format */
|
||||
decodeAndCompareBase64_A(testsNoCR[i].base64, NULL, NULL,
|
||||
CRYPT_STRING_BASE64, CRYPT_STRING_BASE64, testsNoCR[i].toEncode,
|
||||
testsNoCR[i].toEncodeLen);
|
||||
decodeAndCompareBase64_A(testsNoCR[i].base64, CERT_HEADER, CERT_TRAILER,
|
||||
CRYPT_STRING_BASE64HEADER, CRYPT_STRING_BASE64HEADER,
|
||||
testsNoCR[i].toEncode, testsNoCR[i].toEncodeLen);
|
||||
decodeAndCompareBase64_A(testsNoCR[i].base64, CERT_REQUEST_HEADER,
|
||||
CERT_REQUEST_TRAILER, CRYPT_STRING_BASE64REQUESTHEADER,
|
||||
CRYPT_STRING_BASE64REQUESTHEADER, testsNoCR[i].toEncode,
|
||||
testsNoCR[i].toEncodeLen);
|
||||
decodeAndCompareBase64_A(testsNoCR[i].base64, X509_HEADER, X509_TRAILER,
|
||||
CRYPT_STRING_BASE64X509CRLHEADER, CRYPT_STRING_BASE64X509CRLHEADER,
|
||||
testsNoCR[i].toEncode, testsNoCR[i].toEncodeLen);
|
||||
/* And check with the "any" formats */
|
||||
decodeAndCompareBase64_A(testsNoCR[i].base64, NULL, NULL,
|
||||
CRYPT_STRING_BASE64_ANY, CRYPT_STRING_BASE64, testsNoCR[i].toEncode,
|
||||
testsNoCR[i].toEncodeLen);
|
||||
/* Don't check with no header and the string_any format, that'll
|
||||
* always succeed.
|
||||
*/
|
||||
decodeAndCompareBase64_A(testsNoCR[i].base64, CERT_HEADER, CERT_TRAILER,
|
||||
CRYPT_STRING_BASE64_ANY, CRYPT_STRING_BASE64HEADER,
|
||||
testsNoCR[i].toEncode, testsNoCR[i].toEncodeLen);
|
||||
decodeAndCompareBase64_A(testsNoCR[i].base64, CERT_HEADER, CERT_TRAILER,
|
||||
CRYPT_STRING_ANY, CRYPT_STRING_BASE64HEADER, testsNoCR[i].toEncode,
|
||||
testsNoCR[i].toEncodeLen);
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST(base64)
|
||||
{
|
||||
HMODULE lib = GetModuleHandleA("crypt32");
|
||||
|
||||
pCryptBinaryToStringA = (CryptBinaryToStringAFunc)GetProcAddress(lib,
|
||||
"CryptBinaryToStringA");
|
||||
pCryptStringToBinaryA = (CryptStringToBinaryAFunc)GetProcAddress(lib,
|
||||
"CryptStringToBinaryA");
|
||||
|
||||
if (pCryptBinaryToStringA)
|
||||
testBinaryToStringA();
|
||||
else
|
||||
skip("CryptBinaryToStringA is not available\n");
|
||||
|
||||
if (pCryptStringToBinaryA)
|
||||
testStringToBinaryA();
|
||||
else
|
||||
skip("CryptStringToBinaryA is not available\n");
|
||||
}
|
3166
rostests/winetests/crypt32/cert.c
Normal file
3166
rostests/winetests/crypt32/cert.c
Normal file
File diff suppressed because it is too large
Load diff
1973
rostests/winetests/crypt32/chain.c
Normal file
1973
rostests/winetests/crypt32/chain.c
Normal file
File diff suppressed because it is too large
Load diff
734
rostests/winetests/crypt32/crl.c
Normal file
734
rostests/winetests/crypt32/crl.c
Normal file
|
@ -0,0 +1,734 @@
|
|||
/*
|
||||
* crypt32 CRL functions tests
|
||||
*
|
||||
* Copyright 2005-2006 Juan Lang
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#include <winreg.h>
|
||||
#include <winerror.h>
|
||||
#include <wincrypt.h>
|
||||
|
||||
#include "wine/test.h"
|
||||
|
||||
|
||||
static const BYTE bigCert[] = { 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 };
|
||||
static const BYTE bigCert2[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
|
||||
0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
|
||||
0x0a, 0x41, 0x6c, 0x65, 0x78, 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, 0x41, 0x6c, 0x65, 0x78, 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 };
|
||||
static const BYTE bigCertWithDifferentIssuer[] = { 0x30, 0x7a, 0x02, 0x01,
|
||||
0x01, 0x30, 0x02, 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
|
||||
0x55, 0x04, 0x03, 0x13, 0x0a, 0x41, 0x6c, 0x65, 0x78, 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 };
|
||||
static const BYTE CRL[] = { 0x30, 0x2c, 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, 0x18, 0x0f, 0x31,
|
||||
0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||
0x5a };
|
||||
static const BYTE newerCRL[] = { 0x30, 0x2a, 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, 0x17, 0x0d, 0x30, 0x36,
|
||||
0x30, 0x35, 0x31, 0x36, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
|
||||
static const BYTE signedCRL[] = { 0x30, 0x45, 0x30, 0x2c, 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, 0x18, 0x0f,
|
||||
0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||
0x30, 0x5a, 0x30, 0x02, 0x06, 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c,
|
||||
0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
|
||||
|
||||
static BOOL (WINAPI *pCertFindCertificateInCRL)(PCCERT_CONTEXT,PCCRL_CONTEXT,DWORD,void*,PCRL_ENTRY*);
|
||||
static PCCRL_CONTEXT (WINAPI *pCertFindCRLInStore)(HCERTSTORE,DWORD,DWORD,DWORD,const void*,PCCRL_CONTEXT);
|
||||
static BOOL (WINAPI *pCertIsValidCRLForCertificate)(PCCERT_CONTEXT, PCCRL_CONTEXT, DWORD, void*);
|
||||
|
||||
static void init_function_pointers(void)
|
||||
{
|
||||
HMODULE hdll = GetModuleHandleA("crypt32.dll");
|
||||
pCertFindCertificateInCRL = (void*)GetProcAddress(hdll, "CertFindCertificateInCRL");
|
||||
pCertFindCRLInStore = (void*)GetProcAddress(hdll, "CertFindCRLInStore");
|
||||
pCertIsValidCRLForCertificate = (void*)GetProcAddress(hdll, "CertIsValidCRLForCertificate");
|
||||
}
|
||||
|
||||
static void testCreateCRL(void)
|
||||
{
|
||||
PCCRL_CONTEXT context;
|
||||
DWORD GLE;
|
||||
|
||||
context = CertCreateCRLContext(0, NULL, 0);
|
||||
ok(!context && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
context = CertCreateCRLContext(X509_ASN_ENCODING, NULL, 0);
|
||||
GLE = GetLastError();
|
||||
ok(!context && (GLE == CRYPT_E_ASN1_EOD || GLE == OSS_MORE_INPUT),
|
||||
"Expected CRYPT_E_ASN1_EOD or OSS_MORE_INPUT, got %08x\n", GLE);
|
||||
context = CertCreateCRLContext(X509_ASN_ENCODING, bigCert, sizeof(bigCert));
|
||||
GLE = GetLastError();
|
||||
ok(!context, "Expected failure\n");
|
||||
context = CertCreateCRLContext(X509_ASN_ENCODING, signedCRL,
|
||||
sizeof(signedCRL) - 1);
|
||||
ok(!context, "Expected failure\n");
|
||||
context = CertCreateCRLContext(X509_ASN_ENCODING, signedCRL,
|
||||
sizeof(signedCRL));
|
||||
ok(context != NULL, "CertCreateCRLContext failed: %08x\n", GetLastError());
|
||||
if (context)
|
||||
CertFreeCRLContext(context);
|
||||
context = CertCreateCRLContext(X509_ASN_ENCODING, CRL, sizeof(CRL));
|
||||
ok(context != NULL, "CertCreateCRLContext failed: %08x\n", GetLastError());
|
||||
if (context)
|
||||
CertFreeCRLContext(context);
|
||||
}
|
||||
|
||||
static void testAddCRL(void)
|
||||
{
|
||||
HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
||||
CERT_STORE_CREATE_NEW_FLAG, NULL);
|
||||
PCCRL_CONTEXT context;
|
||||
BOOL ret;
|
||||
DWORD GLE;
|
||||
|
||||
if (!store) return;
|
||||
|
||||
/* Bad CRL encoding type */
|
||||
ret = CertAddEncodedCRLToStore(0, 0, NULL, 0, 0, NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
ret = CertAddEncodedCRLToStore(store, 0, NULL, 0, 0, NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
ret = CertAddEncodedCRLToStore(0, 0, signedCRL, sizeof(signedCRL), 0, NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
ret = CertAddEncodedCRLToStore(store, 0, signedCRL, sizeof(signedCRL), 0,
|
||||
NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
ret = CertAddEncodedCRLToStore(0, 0, signedCRL, sizeof(signedCRL),
|
||||
CERT_STORE_ADD_ALWAYS, NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
ret = CertAddEncodedCRLToStore(store, 0, signedCRL, sizeof(signedCRL),
|
||||
CERT_STORE_ADD_ALWAYS, NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
|
||||
/* No CRL */
|
||||
ret = CertAddEncodedCRLToStore(0, X509_ASN_ENCODING, NULL, 0, 0, NULL);
|
||||
GLE = GetLastError();
|
||||
ok(!ret && (GLE == CRYPT_E_ASN1_EOD || GLE == OSS_MORE_INPUT),
|
||||
"Expected CRYPT_E_ASN1_EOD or OSS_MORE_INPUT, got %08x\n", GLE);
|
||||
ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, NULL, 0, 0, NULL);
|
||||
GLE = GetLastError();
|
||||
ok(!ret && (GLE == CRYPT_E_ASN1_EOD || GLE == OSS_MORE_INPUT),
|
||||
"Expected CRYPT_E_ASN1_EOD or OSS_MORE_INPUT, got %08x\n", GLE);
|
||||
|
||||
/* Weird--bad add disposition leads to an access violation in Windows.
|
||||
* Both tests crash on some win9x boxes.
|
||||
*/
|
||||
if (0)
|
||||
{
|
||||
ret = CertAddEncodedCRLToStore(0, X509_ASN_ENCODING, signedCRL,
|
||||
sizeof(signedCRL), 0, NULL);
|
||||
ok(!ret && (GetLastError() == STATUS_ACCESS_VIOLATION ||
|
||||
GetLastError() == E_INVALIDARG /* Vista */),
|
||||
"Expected STATUS_ACCESS_VIOLATION or E_INVALIDARG, got %08x\n", GetLastError());
|
||||
ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL,
|
||||
sizeof(signedCRL), 0, NULL);
|
||||
ok(!ret && (GetLastError() == STATUS_ACCESS_VIOLATION ||
|
||||
GetLastError() == E_INVALIDARG /* Vista */),
|
||||
"Expected STATUS_ACCESS_VIOLATION or E_INVALIDARG, got %08x\n", GetLastError());
|
||||
}
|
||||
|
||||
/* Weird--can add a CRL to the NULL store (does this have special meaning?)
|
||||
*/
|
||||
context = NULL;
|
||||
ret = CertAddEncodedCRLToStore(0, X509_ASN_ENCODING, signedCRL,
|
||||
sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, &context);
|
||||
ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError());
|
||||
if (context)
|
||||
CertFreeCRLContext(context);
|
||||
|
||||
/* Normal cases: a "signed" CRL is okay.. */
|
||||
ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL,
|
||||
sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
|
||||
/* and an unsigned one is too. */
|
||||
ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, CRL, sizeof(CRL),
|
||||
CERT_STORE_ADD_ALWAYS, NULL);
|
||||
ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError());
|
||||
|
||||
ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, newerCRL,
|
||||
sizeof(newerCRL), CERT_STORE_ADD_NEW, NULL);
|
||||
ok(!ret && GetLastError() == CRYPT_E_EXISTS,
|
||||
"Expected CRYPT_E_EXISTS, got %08x\n", GetLastError());
|
||||
|
||||
/* This should replace (one of) the existing CRL(s). */
|
||||
ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, newerCRL,
|
||||
sizeof(newerCRL), CERT_STORE_ADD_NEWER, NULL);
|
||||
ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError());
|
||||
|
||||
CertCloseStore(store, 0);
|
||||
}
|
||||
|
||||
static void testFindCRL(void)
|
||||
{
|
||||
HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
||||
CERT_STORE_CREATE_NEW_FLAG, NULL);
|
||||
PCCRL_CONTEXT context;
|
||||
PCCERT_CONTEXT cert;
|
||||
BOOL ret;
|
||||
|
||||
if (!store) return;
|
||||
if (!pCertFindCRLInStore)
|
||||
{
|
||||
skip("CertFindCRLInStore() is not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL,
|
||||
sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
|
||||
ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError());
|
||||
|
||||
/* Crashes
|
||||
context = pCertFindCRLInStore(NULL, 0, 0, 0, NULL, NULL);
|
||||
*/
|
||||
|
||||
/* Find any context */
|
||||
context = pCertFindCRLInStore(store, 0, 0, CRL_FIND_ANY, NULL, NULL);
|
||||
ok(context != NULL, "Expected a context\n");
|
||||
if (context)
|
||||
CertFreeCRLContext(context);
|
||||
/* Bogus flags are ignored */
|
||||
context = pCertFindCRLInStore(store, 0, 1234, CRL_FIND_ANY, NULL, NULL);
|
||||
ok(context != NULL, "Expected a context\n");
|
||||
if (context)
|
||||
CertFreeCRLContext(context);
|
||||
/* CRL encoding type is ignored too */
|
||||
context = pCertFindCRLInStore(store, 1234, 0, CRL_FIND_ANY, NULL, NULL);
|
||||
ok(context != NULL, "Expected a context\n");
|
||||
if (context)
|
||||
CertFreeCRLContext(context);
|
||||
|
||||
/* This appears to match any cert */
|
||||
context = pCertFindCRLInStore(store, 0, 0, CRL_FIND_ISSUED_BY, NULL, NULL);
|
||||
ok(context != NULL, "Expected a context\n");
|
||||
if (context)
|
||||
CertFreeCRLContext(context);
|
||||
|
||||
/* Try to match an issuer that isn't in the store */
|
||||
cert = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
|
||||
sizeof(bigCert2));
|
||||
ok(cert != NULL, "CertCreateCertificateContext failed: %08x\n",
|
||||
GetLastError());
|
||||
context = pCertFindCRLInStore(store, 0, 0, CRL_FIND_ISSUED_BY, cert, NULL);
|
||||
ok(context == NULL, "Expected no matching context\n");
|
||||
CertFreeCertificateContext(cert);
|
||||
|
||||
/* Match an issuer that is in the store */
|
||||
cert = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
|
||||
sizeof(bigCert));
|
||||
ok(cert != NULL, "CertCreateCertificateContext failed: %08x\n",
|
||||
GetLastError());
|
||||
context = pCertFindCRLInStore(store, 0, 0, CRL_FIND_ISSUED_BY, cert, NULL);
|
||||
ok(context != NULL, "Expected a context\n");
|
||||
if (context)
|
||||
CertFreeCRLContext(context);
|
||||
CertFreeCertificateContext(cert);
|
||||
|
||||
CertCloseStore(store, 0);
|
||||
}
|
||||
|
||||
static void testGetCRLFromStore(void)
|
||||
{
|
||||
HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
||||
CERT_STORE_CREATE_NEW_FLAG, NULL);
|
||||
PCCRL_CONTEXT context;
|
||||
PCCERT_CONTEXT cert;
|
||||
DWORD flags;
|
||||
BOOL ret;
|
||||
|
||||
if (!store) return;
|
||||
|
||||
/* Crash
|
||||
context = CertGetCRLFromStore(NULL, NULL, NULL, NULL);
|
||||
context = CertGetCRLFromStore(store, NULL, NULL, NULL);
|
||||
*/
|
||||
|
||||
/* Bogus flags */
|
||||
flags = 0xffffffff;
|
||||
context = CertGetCRLFromStore(store, NULL, NULL, &flags);
|
||||
ok(!context && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
|
||||
/* Test an empty store */
|
||||
flags = 0;
|
||||
context = CertGetCRLFromStore(store, NULL, NULL, &flags);
|
||||
ok(context == NULL && GetLastError() == CRYPT_E_NOT_FOUND,
|
||||
"Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
|
||||
|
||||
ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, signedCRL,
|
||||
sizeof(signedCRL), CERT_STORE_ADD_ALWAYS, NULL);
|
||||
ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError());
|
||||
|
||||
/* NULL matches any CRL */
|
||||
flags = 0;
|
||||
context = CertGetCRLFromStore(store, NULL, NULL, &flags);
|
||||
ok(context != NULL, "Expected a context\n");
|
||||
CertFreeCRLContext(context);
|
||||
|
||||
/* This cert's issuer isn't in */
|
||||
cert = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert2,
|
||||
sizeof(bigCert2));
|
||||
ok(cert != NULL, "CertCreateCertificateContext failed: %08x\n",
|
||||
GetLastError());
|
||||
context = CertGetCRLFromStore(store, cert, NULL, &flags);
|
||||
ok(context == NULL && GetLastError() == CRYPT_E_NOT_FOUND,
|
||||
"Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
|
||||
CertFreeCertificateContext(cert);
|
||||
|
||||
/* But this one is */
|
||||
cert = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
|
||||
sizeof(bigCert));
|
||||
ok(cert != NULL, "CertCreateCertificateContext failed: %08x\n",
|
||||
GetLastError());
|
||||
context = CertGetCRLFromStore(store, cert, NULL, &flags);
|
||||
ok(context != NULL, "Expected a context\n");
|
||||
CertFreeCRLContext(context);
|
||||
CertFreeCertificateContext(cert);
|
||||
|
||||
CertCloseStore(store, 0);
|
||||
}
|
||||
|
||||
static void checkCRLHash(const BYTE *data, DWORD dataLen, ALG_ID algID,
|
||||
PCCRL_CONTEXT context, DWORD propID)
|
||||
{
|
||||
BYTE hash[20] = { 0 }, hashProperty[20];
|
||||
BOOL ret;
|
||||
DWORD size;
|
||||
|
||||
memset(hash, 0, sizeof(hash));
|
||||
memset(hashProperty, 0, sizeof(hashProperty));
|
||||
size = sizeof(hash);
|
||||
ret = CryptHashCertificate(0, algID, 0, data, dataLen, hash, &size);
|
||||
ok(ret, "CryptHashCertificate failed: %08x\n", GetLastError());
|
||||
ret = CertGetCRLContextProperty(context, propID, hashProperty, &size);
|
||||
ok(ret, "CertGetCRLContextProperty failed: %08x\n", GetLastError());
|
||||
ok(!memcmp(hash, hashProperty, size), "Unexpected hash for property %d\n",
|
||||
propID);
|
||||
}
|
||||
|
||||
static void testCRLProperties(void)
|
||||
{
|
||||
PCCRL_CONTEXT context = CertCreateCRLContext(X509_ASN_ENCODING,
|
||||
CRL, sizeof(CRL));
|
||||
|
||||
ok(context != NULL, "CertCreateCRLContext failed: %08x\n", GetLastError());
|
||||
if (context)
|
||||
{
|
||||
DWORD propID, numProps, access, size;
|
||||
BOOL ret;
|
||||
BYTE hash[20] = { 0 }, hashProperty[20];
|
||||
CRYPT_DATA_BLOB blob;
|
||||
|
||||
/* This crashes
|
||||
propID = CertEnumCRLContextProperties(NULL, 0);
|
||||
*/
|
||||
|
||||
propID = 0;
|
||||
numProps = 0;
|
||||
do {
|
||||
propID = CertEnumCRLContextProperties(context, propID);
|
||||
if (propID)
|
||||
numProps++;
|
||||
} while (propID != 0);
|
||||
ok(numProps == 0, "Expected 0 properties, got %d\n", numProps);
|
||||
|
||||
/* Tests with a NULL cert context. Prop ID 0 fails.. */
|
||||
ret = CertSetCRLContextProperty(NULL, 0, 0, NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
/* while this just crashes.
|
||||
ret = CertSetCRLContextProperty(NULL, CERT_KEY_PROV_HANDLE_PROP_ID, 0,
|
||||
NULL);
|
||||
*/
|
||||
|
||||
ret = CertSetCRLContextProperty(context, 0, 0, NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
/* Can't set the cert property directly, this crashes.
|
||||
ret = CertSetCRLContextProperty(context, CERT_CRL_PROP_ID, 0, CRL);
|
||||
*/
|
||||
|
||||
/* These all crash.
|
||||
ret = CertGetCRLContextProperty(context, CERT_ACCESS_STATE_PROP_ID, 0,
|
||||
NULL);
|
||||
ret = CertGetCRLContextProperty(context, CERT_HASH_PROP_ID, NULL, NULL);
|
||||
ret = CertGetCRLContextProperty(context, CERT_HASH_PROP_ID,
|
||||
hashProperty, NULL);
|
||||
*/
|
||||
/* A missing prop */
|
||||
size = 0;
|
||||
ret = CertGetCRLContextProperty(context, CERT_KEY_PROV_INFO_PROP_ID,
|
||||
NULL, &size);
|
||||
ok(!ret && GetLastError() == CRYPT_E_NOT_FOUND,
|
||||
"Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
|
||||
/* And, an implicit property */
|
||||
ret = CertGetCRLContextProperty(context, CERT_ACCESS_STATE_PROP_ID,
|
||||
NULL, &size);
|
||||
ok(ret, "CertGetCRLContextProperty failed: %08x\n", GetLastError());
|
||||
ret = CertGetCRLContextProperty(context, CERT_ACCESS_STATE_PROP_ID,
|
||||
&access, &size);
|
||||
ok(ret, "CertGetCRLContextProperty failed: %08x\n", GetLastError());
|
||||
ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
|
||||
"Didn't expect a persisted crl\n");
|
||||
/* Trying to set this "read only" property crashes.
|
||||
access |= CERT_ACCESS_STATE_WRITE_PERSIST_FLAG;
|
||||
ret = CertSetCRLContextProperty(context, CERT_ACCESS_STATE_PROP_ID, 0,
|
||||
&access);
|
||||
*/
|
||||
|
||||
/* Can I set the hash to an invalid hash? */
|
||||
blob.pbData = hash;
|
||||
blob.cbData = sizeof(hash);
|
||||
ret = CertSetCRLContextProperty(context, CERT_HASH_PROP_ID, 0, &blob);
|
||||
ok(ret, "CertSetCRLContextProperty failed: %08x\n",
|
||||
GetLastError());
|
||||
size = sizeof(hashProperty);
|
||||
ret = CertGetCRLContextProperty(context, CERT_HASH_PROP_ID,
|
||||
hashProperty, &size);
|
||||
ok(!memcmp(hashProperty, hash, sizeof(hash)), "Unexpected hash\n");
|
||||
/* Delete the (bogus) hash, and get the real one */
|
||||
ret = CertSetCRLContextProperty(context, CERT_HASH_PROP_ID, 0, NULL);
|
||||
ok(ret, "CertSetCRLContextProperty failed: %08x\n", GetLastError());
|
||||
checkCRLHash(CRL, sizeof(CRL), CALG_SHA1, context, CERT_HASH_PROP_ID);
|
||||
|
||||
/* Now that the hash property is set, we should get one property when
|
||||
* enumerating.
|
||||
*/
|
||||
propID = 0;
|
||||
numProps = 0;
|
||||
do {
|
||||
propID = CertEnumCRLContextProperties(context, propID);
|
||||
if (propID)
|
||||
numProps++;
|
||||
} while (propID != 0);
|
||||
ok(numProps == 1, "Expected 1 properties, got %d\n", numProps);
|
||||
|
||||
/* Check a few other implicit properties */
|
||||
checkCRLHash(CRL, sizeof(CRL), CALG_MD5, context,
|
||||
CERT_MD5_HASH_PROP_ID);
|
||||
|
||||
CertFreeCRLContext(context);
|
||||
}
|
||||
}
|
||||
|
||||
static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 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, 0x18, 0x0f,
|
||||
0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||
0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
|
||||
0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
|
||||
static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,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,0x18,0x0f,0x31,
|
||||
0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,
|
||||
0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
|
||||
0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,
|
||||
0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
|
||||
static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
|
||||
0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
|
||||
0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
|
||||
0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
|
||||
0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
|
||||
0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
|
||||
0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
|
||||
0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
|
||||
0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
|
||||
0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
|
||||
0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
|
||||
0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
|
||||
0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
|
||||
0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
|
||||
0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
|
||||
0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
|
||||
0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
|
||||
0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
|
||||
0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
|
||||
0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
|
||||
0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
|
||||
0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
|
||||
0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
|
||||
0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
|
||||
0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
|
||||
0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
|
||||
0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
|
||||
0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
|
||||
0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
|
||||
0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
|
||||
0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
|
||||
0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
|
||||
0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
|
||||
0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
|
||||
0xcd };
|
||||
|
||||
static void testIsValidCRLForCert(void)
|
||||
{
|
||||
BOOL ret;
|
||||
PCCERT_CONTEXT cert1, cert2;
|
||||
PCCRL_CONTEXT crl;
|
||||
HCERTSTORE store;
|
||||
|
||||
if(!pCertIsValidCRLForCertificate) return;
|
||||
|
||||
crl = CertCreateCRLContext(X509_ASN_ENCODING, v1CRLWithIssuerAndEntry,
|
||||
sizeof(v1CRLWithIssuerAndEntry));
|
||||
ok(crl != NULL, "CertCreateCRLContext failed: %08x\n", GetLastError());
|
||||
cert1 = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
|
||||
sizeof(bigCert));
|
||||
ok(cert1 != NULL, "CertCreateCertificateContext failed: %08x\n",
|
||||
GetLastError());
|
||||
|
||||
/* Crash
|
||||
ret = CertIsValidCRLForCertificate(NULL, NULL, 0, NULL);
|
||||
ret = CertIsValidCRLForCertificate(cert1, NULL, 0, NULL);
|
||||
*/
|
||||
|
||||
/* Curiously, any CRL is valid for the NULL certificate */
|
||||
ret = pCertIsValidCRLForCertificate(NULL, crl, 0, NULL);
|
||||
ok(ret, "CertIsValidCRLForCertificate failed: %08x\n", GetLastError());
|
||||
|
||||
/* Same issuer for both cert and CRL, this CRL is valid for that cert */
|
||||
ret = pCertIsValidCRLForCertificate(cert1, crl, 0, NULL);
|
||||
ok(ret, "CertIsValidCRLForCertificate failed: %08x\n", GetLastError());
|
||||
|
||||
cert2 = CertCreateCertificateContext(X509_ASN_ENCODING,
|
||||
bigCertWithDifferentIssuer, sizeof(bigCertWithDifferentIssuer));
|
||||
ok(cert2 != NULL, "CertCreateCertificateContext failed: %08x\n",
|
||||
GetLastError());
|
||||
|
||||
/* Yet more curious: different issuers for these, yet the CRL is valid for
|
||||
* that cert. According to MSDN, the relevant bit to check is whether the
|
||||
* CRL has a CRL_ISSUING_DIST_POINT extension.
|
||||
*/
|
||||
ret = pCertIsValidCRLForCertificate(cert2, crl, 0, NULL);
|
||||
ok(ret, "CertIsValidCRLForCertificate failed: %08x\n", GetLastError());
|
||||
|
||||
CertFreeCRLContext(crl);
|
||||
|
||||
/* Yet with a CRL_ISSUING_DIST_POINT in the CRL, I still can't get this
|
||||
* to say the CRL is not valid for either cert.
|
||||
*/
|
||||
crl = CertCreateCRLContext(X509_ASN_ENCODING, v2CRLWithIssuingDistPoint,
|
||||
sizeof(v2CRLWithIssuingDistPoint));
|
||||
ok(crl != NULL, "CertCreateCRLContext failed: %08x\n", GetLastError());
|
||||
|
||||
ret = pCertIsValidCRLForCertificate(cert1, crl, 0, NULL);
|
||||
ok(ret, "CertIsValidCRLForCertificate failed: %08x\n", GetLastError());
|
||||
ret = pCertIsValidCRLForCertificate(cert2, crl, 0, NULL);
|
||||
ok(ret, "CertIsValidCRLForCertificate failed: %08x\n", GetLastError());
|
||||
|
||||
CertFreeCRLContext(crl);
|
||||
|
||||
/* And again, with a real CRL, the CRL is valid for both certs. */
|
||||
crl = CertCreateCRLContext(X509_ASN_ENCODING, verisignCRL,
|
||||
sizeof(verisignCRL));
|
||||
ok(crl != NULL, "CertCreateCRLContext failed: %08x\n", GetLastError());
|
||||
|
||||
ret = pCertIsValidCRLForCertificate(cert1, crl, 0, NULL);
|
||||
ok(ret, "CertIsValidCRLForCertificate failed: %08x\n", GetLastError());
|
||||
ret = pCertIsValidCRLForCertificate(cert2, crl, 0, NULL);
|
||||
ok(ret, "CertIsValidCRLForCertificate failed: %08x\n", GetLastError());
|
||||
|
||||
CertFreeCRLContext(crl);
|
||||
|
||||
/* One last test: a CRL in a different store than the cert is also valid
|
||||
* for the cert, so CertIsValidCRLForCertificate must always return TRUE?
|
||||
*/
|
||||
store = CertOpenStore(CERT_STORE_PROV_MEMORY, X509_ASN_ENCODING, 0,
|
||||
CERT_STORE_CREATE_NEW_FLAG, NULL);
|
||||
ok(store != NULL, "CertOpenStore failed: %08x\n", GetLastError());
|
||||
|
||||
ret = CertAddEncodedCRLToStore(store, X509_ASN_ENCODING, verisignCRL,
|
||||
sizeof(verisignCRL), CERT_STORE_ADD_ALWAYS, &crl);
|
||||
ok(ret, "CertAddEncodedCRLToStore failed: %08x\n", GetLastError());
|
||||
|
||||
ret = pCertIsValidCRLForCertificate(cert1, crl, 0, NULL);
|
||||
ok(ret, "CertIsValidCRLForCertificate failed: %08x\n", GetLastError());
|
||||
ret = pCertIsValidCRLForCertificate(cert2, crl, 0, NULL);
|
||||
ok(ret, "CertIsValidCRLForCertificate failed: %08x\n", GetLastError());
|
||||
|
||||
CertFreeCRLContext(crl);
|
||||
|
||||
CertCloseStore(store, 0);
|
||||
|
||||
CertFreeCertificateContext(cert2);
|
||||
CertFreeCertificateContext(cert1);
|
||||
}
|
||||
|
||||
static const BYTE crlWithDifferentIssuer[] = {
|
||||
0x30,0x47,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
|
||||
0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x41,0x6c,0x65,0x78,0x20,0x4c,0x61,0x6e,
|
||||
0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,
|
||||
0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,
|
||||
0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a };
|
||||
|
||||
static void testFindCertInCRL(void)
|
||||
{
|
||||
BOOL ret;
|
||||
PCCERT_CONTEXT cert;
|
||||
PCCRL_CONTEXT crl;
|
||||
PCRL_ENTRY entry;
|
||||
|
||||
if (!pCertFindCertificateInCRL)
|
||||
{
|
||||
skip("CertFindCertificateInCRL() is not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
cert = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
|
||||
sizeof(bigCert));
|
||||
ok(cert != NULL, "CertCreateCertificateContext failed: %08x\n",
|
||||
GetLastError());
|
||||
|
||||
/* Crash
|
||||
ret = pCertFindCertificateInCRL(NULL, NULL, 0, NULL, NULL);
|
||||
ret = pCertFindCertificateInCRL(NULL, crl, 0, NULL, NULL);
|
||||
ret = pCertFindCertificateInCRL(cert, NULL, 0, NULL, NULL);
|
||||
ret = pCertFindCertificateInCRL(cert, crl, 0, NULL, NULL);
|
||||
ret = pCertFindCertificateInCRL(NULL, NULL, 0, NULL, &entry);
|
||||
ret = pCertFindCertificateInCRL(NULL, crl, 0, NULL, &entry);
|
||||
ret = pCertFindCertificateInCRL(cert, NULL, 0, NULL, &entry);
|
||||
*/
|
||||
|
||||
crl = CertCreateCRLContext(X509_ASN_ENCODING, verisignCRL,
|
||||
sizeof(verisignCRL));
|
||||
ret = pCertFindCertificateInCRL(cert, crl, 0, NULL, &entry);
|
||||
ok(ret, "CertFindCertificateInCRL failed: %08x\n", GetLastError());
|
||||
ok(entry == NULL, "Expected not to find an entry in CRL\n");
|
||||
CertFreeCRLContext(crl);
|
||||
|
||||
crl = CertCreateCRLContext(X509_ASN_ENCODING, v1CRLWithIssuerAndEntry,
|
||||
sizeof(v1CRLWithIssuerAndEntry));
|
||||
ret = pCertFindCertificateInCRL(cert, crl, 0, NULL, &entry);
|
||||
ok(ret, "CertFindCertificateInCRL failed: %08x\n", GetLastError());
|
||||
ok(entry != NULL, "Expected to find an entry in CRL\n");
|
||||
CertFreeCRLContext(crl);
|
||||
|
||||
/* Entry found even though CRL issuer doesn't match cert issuer */
|
||||
crl = CertCreateCRLContext(X509_ASN_ENCODING, crlWithDifferentIssuer,
|
||||
sizeof(crlWithDifferentIssuer));
|
||||
ret = pCertFindCertificateInCRL(cert, crl, 0, NULL, &entry);
|
||||
ok(ret, "CertFindCertificateInCRL failed: %08x\n", GetLastError());
|
||||
ok(entry != NULL, "Expected to find an entry in CRL\n");
|
||||
CertFreeCRLContext(crl);
|
||||
|
||||
CertFreeCertificateContext(cert);
|
||||
}
|
||||
|
||||
static void testVerifyCRLRevocation(void)
|
||||
{
|
||||
BOOL ret;
|
||||
PCCERT_CONTEXT cert;
|
||||
PCCRL_CONTEXT crl;
|
||||
|
||||
ret = CertVerifyCRLRevocation(0, NULL, 0, NULL);
|
||||
ok(ret, "CertVerifyCRLRevocation failed: %08x\n", GetLastError());
|
||||
ret = CertVerifyCRLRevocation(X509_ASN_ENCODING, NULL, 0, NULL);
|
||||
ok(ret, "CertVerifyCRLRevocation failed: %08x\n", GetLastError());
|
||||
|
||||
cert = CertCreateCertificateContext(X509_ASN_ENCODING, bigCert,
|
||||
sizeof(bigCert));
|
||||
|
||||
/* Check against no CRL */
|
||||
ret = CertVerifyCRLRevocation(0, cert->pCertInfo, 0, NULL);
|
||||
ok(ret, "CertVerifyCRLRevocation failed: %08x\n", GetLastError());
|
||||
ret = CertVerifyCRLRevocation(X509_ASN_ENCODING, cert->pCertInfo, 0, NULL);
|
||||
ok(ret, "CertVerifyCRLRevocation failed: %08x\n", GetLastError());
|
||||
|
||||
/* Check against CRL with entry for the cert */
|
||||
crl = CertCreateCRLContext(X509_ASN_ENCODING, v1CRLWithIssuerAndEntry,
|
||||
sizeof(v1CRLWithIssuerAndEntry));
|
||||
ret = CertVerifyCRLRevocation(0, cert->pCertInfo, 1,
|
||||
(PCRL_INFO *)&crl->pCrlInfo);
|
||||
ok(!ret, "CertVerifyCRLRevocation should have been revoked\n");
|
||||
ret = CertVerifyCRLRevocation(X509_ASN_ENCODING, cert->pCertInfo, 1,
|
||||
(PCRL_INFO *)&crl->pCrlInfo);
|
||||
ok(!ret, "CertVerifyCRLRevocation should have been revoked\n");
|
||||
CertFreeCRLContext(crl);
|
||||
|
||||
/* Check against CRL with different issuer and entry for the cert */
|
||||
crl = CertCreateCRLContext(X509_ASN_ENCODING, v1CRLWithIssuerAndEntry,
|
||||
sizeof(v1CRLWithIssuerAndEntry));
|
||||
ok(crl != NULL, "CertCreateCRLContext failed: %08x\n", GetLastError());
|
||||
ret = CertVerifyCRLRevocation(X509_ASN_ENCODING, cert->pCertInfo, 1,
|
||||
(PCRL_INFO *)&crl->pCrlInfo);
|
||||
ok(!ret, "CertVerifyCRLRevocation should have been revoked\n");
|
||||
CertFreeCRLContext(crl);
|
||||
|
||||
/* Check against CRL without entry for the cert */
|
||||
crl = CertCreateCRLContext(X509_ASN_ENCODING, verisignCRL,
|
||||
sizeof(verisignCRL));
|
||||
ret = CertVerifyCRLRevocation(0, cert->pCertInfo, 1,
|
||||
(PCRL_INFO *)&crl->pCrlInfo);
|
||||
ok(ret, "CertVerifyCRLRevocation failed: %08x\n", GetLastError());
|
||||
ret = CertVerifyCRLRevocation(X509_ASN_ENCODING, cert->pCertInfo, 1,
|
||||
(PCRL_INFO *)&crl->pCrlInfo);
|
||||
ok(ret, "CertVerifyCRLRevocation failed: %08x\n", GetLastError());
|
||||
CertFreeCRLContext(crl);
|
||||
|
||||
CertFreeCertificateContext(cert);
|
||||
}
|
||||
|
||||
START_TEST(crl)
|
||||
{
|
||||
init_function_pointers();
|
||||
|
||||
testCreateCRL();
|
||||
testAddCRL();
|
||||
testFindCRL();
|
||||
testGetCRLFromStore();
|
||||
|
||||
testCRLProperties();
|
||||
|
||||
testIsValidCRLForCert();
|
||||
testFindCertInCRL();
|
||||
testVerifyCRLRevocation();
|
||||
}
|
29
rostests/winetests/crypt32/crypt32.rbuild
Normal file
29
rostests/winetests/crypt32/crypt32.rbuild
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
|
||||
<group>
|
||||
<module name="crypt32_winetest" type="win32cui" installbase="bin" installname="crypt32_winetest.exe" allowwarnings="true">
|
||||
<compilerflag compiler="cc">-Wno-format</compilerflag>
|
||||
<include base="crypt32_winetest">.</include>
|
||||
<file>base64.c</file>
|
||||
<file>cert.c</file>
|
||||
<file>chain.c</file>
|
||||
<file>crl.c</file>
|
||||
<file>ctl.c</file>
|
||||
<file>encode.c</file>
|
||||
<file>main.c</file>
|
||||
<file>message.c</file>
|
||||
<file>msg.c</file>
|
||||
<file>object.c</file>
|
||||
<file>oid.c</file>
|
||||
<file>protectdata.c</file>
|
||||
<file>sip.c</file>
|
||||
<file>store.c</file>
|
||||
<file>str.c</file>
|
||||
<file>testlist.c</file>
|
||||
<library>wine</library>
|
||||
<library>crypt32</library>
|
||||
<library>advapi32</library>
|
||||
<library>kernel32</library>
|
||||
<library>ntdll</library>
|
||||
</module>
|
||||
</group>
|
429
rostests/winetests/crypt32/ctl.c
Normal file
429
rostests/winetests/crypt32/ctl.c
Normal file
|
@ -0,0 +1,429 @@
|
|||
/*
|
||||
* crypt32 CTL functions tests
|
||||
*
|
||||
* Copyright 2008 Juan Lang
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#include <winerror.h>
|
||||
#include <wincrypt.h>
|
||||
|
||||
#include "wine/test.h"
|
||||
|
||||
static const BYTE emptyCTL[] = {
|
||||
0x30,0x17,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
|
||||
0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
|
||||
static const BYTE ctlWithOneEntry[] = {
|
||||
0x30,0x2a,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
|
||||
0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x11,0x30,0x0f,0x04,
|
||||
0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00 };
|
||||
static const BYTE signedCTL[] = {
|
||||
0x30,0x81,0xc7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
|
||||
0x81,0xb9,0x30,0x81,0xb6,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
|
||||
0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x28,0x06,0x09,0x2a,0x86,
|
||||
0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x1b,0x04,0x19,0x30,0x17,0x30,0x00,
|
||||
0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
|
||||
0x30,0x5a,0x30,0x02,0x06,0x00,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
|
||||
0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
|
||||
0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
|
||||
0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
|
||||
0x00,0x04,0x40,0xca,0xd8,0x32,0xd1,0xbd,0x97,0x61,0x54,0xd6,0x80,0xcf,0x0d,
|
||||
0xbd,0xa2,0x42,0xc7,0xca,0x37,0x91,0x7d,0x9d,0xac,0x8c,0xdf,0x05,0x8a,0x39,
|
||||
0xc6,0x07,0xc1,0x37,0xe6,0xb9,0xd1,0x0d,0x26,0xec,0xa5,0xb0,0x8a,0x51,0x26,
|
||||
0x2b,0x4f,0x73,0x44,0x86,0x83,0x5e,0x2b,0x6e,0xcc,0xf8,0x1b,0x85,0x53,0xe9,
|
||||
0x7a,0x80,0x8f,0x6b,0x42,0x19,0x93 };
|
||||
static const BYTE signedCTLWithSubjectAlgorithm[] = {
|
||||
0x30,0x81,0xd1,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
|
||||
0x81,0xc3,0x30,0x81,0xc0,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
|
||||
0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x32,0x06,0x09,0x2a,0x86,
|
||||
0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x25,0x04,0x23,0x30,0x21,0x30,0x00,
|
||||
0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
|
||||
0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
|
||||
0x00,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,
|
||||
0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
|
||||
0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,
|
||||
0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0xca,0x7a,
|
||||
0xfa,0xbf,0x44,0x36,0xfd,0xb2,0x84,0x70,0x0f,0xf5,0x66,0xcb,0x68,0xdb,0x45,
|
||||
0x74,0xa1,0xed,0xe3,0x30,0x4a,0x11,0xd2,0x7b,0xf5,0xa9,0x68,0x8d,0x36,0xe8,
|
||||
0x79,0xff,0xa2,0xf2,0x4c,0x8a,0xa9,0x65,0x03,0xf8,0x77,0xa5,0x01,0xd3,0x46,
|
||||
0x8a,0xcc,0x93,0x36,0x30,0xe1,0xa4,0x47,0x70,0x3d,0xb3,0x97,0xfc,0x6d,0x24,
|
||||
0xe9,0xf9 };
|
||||
static const BYTE signedCTLWithCTLInnerContent[] = {
|
||||
0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
|
||||
0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
|
||||
0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
|
||||
0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
|
||||
0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
|
||||
0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
|
||||
0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
|
||||
0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
|
||||
0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
|
||||
0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
|
||||
0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
|
||||
0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
|
||||
0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
|
||||
0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
|
||||
0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
|
||||
0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
|
||||
0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
|
||||
0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
|
||||
0x57,0x6c,0x0b,0x47,0xb8 };
|
||||
static const BYTE signedCTLWithCTLInnerContentAndBadSig[] = {
|
||||
0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
|
||||
0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
|
||||
0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
|
||||
0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
|
||||
0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
|
||||
0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
|
||||
0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
|
||||
0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
|
||||
0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
|
||||
0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
|
||||
0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
|
||||
0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
|
||||
0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
|
||||
0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
|
||||
0x40,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0xff,0xff,0xff };
|
||||
|
||||
static void testCreateCTL(void)
|
||||
{
|
||||
PCCTL_CONTEXT ctl;
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ctl = CertCreateCTLContext(0, NULL, 0);
|
||||
ok(!ctl && GetLastError() == E_INVALIDARG,
|
||||
"expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
SetLastError(0xdeadbeef);
|
||||
ctl = CertCreateCTLContext(X509_ASN_ENCODING, NULL, 0);
|
||||
ok(!ctl &&
|
||||
(GetLastError() == ERROR_INVALID_DATA ||
|
||||
GetLastError() == OSS_MORE_INPUT), /* win9x */
|
||||
"expected ERROR_INVALID_DATA, got %d (0x%08x)\n", GetLastError(),
|
||||
GetLastError());
|
||||
/* An empty CTL can't be created.. */
|
||||
SetLastError(0xdeadbeef);
|
||||
ctl = CertCreateCTLContext(X509_ASN_ENCODING, emptyCTL, sizeof(emptyCTL));
|
||||
ok(!ctl &&
|
||||
(GetLastError() == ERROR_INVALID_DATA ||
|
||||
GetLastError() == OSS_DATA_ERROR), /* win9x */
|
||||
"expected ERROR_INVALID_DATA, got %d (0x%08x)\n", GetLastError(),
|
||||
GetLastError());
|
||||
/* Nor can any of these "signed" CTLs whose inner content OID isn't
|
||||
* szOID_CTL.
|
||||
*/
|
||||
SetLastError(0xdeadbeef);
|
||||
ctl = CertCreateCTLContext(X509_ASN_ENCODING, signedCTL, sizeof(signedCTL));
|
||||
ok(!ctl &&
|
||||
(GetLastError() == ERROR_INVALID_DATA ||
|
||||
GetLastError() == CRYPT_E_UNEXPECTED_MSG_TYPE), /* win9x */
|
||||
"expected ERROR_INVALID_DATA, got %d (0x%08x)\n", GetLastError(),
|
||||
GetLastError());
|
||||
SetLastError(0xdeadbeef);
|
||||
ctl = CertCreateCTLContext(X509_ASN_ENCODING, ctlWithOneEntry,
|
||||
sizeof(ctlWithOneEntry));
|
||||
ok(!ctl &&
|
||||
(GetLastError() == ERROR_INVALID_DATA ||
|
||||
GetLastError() == OSS_DATA_ERROR), /* win9x */
|
||||
"expected ERROR_INVALID_DATA, got %d (0x%08x)\n", GetLastError(),
|
||||
GetLastError());
|
||||
SetLastError(0xdeadbeef);
|
||||
ctl = CertCreateCTLContext(X509_ASN_ENCODING,
|
||||
signedCTLWithSubjectAlgorithm, sizeof(signedCTLWithSubjectAlgorithm));
|
||||
ok(!ctl &&
|
||||
(GetLastError() == ERROR_INVALID_DATA ||
|
||||
GetLastError() == CRYPT_E_UNEXPECTED_MSG_TYPE), /* win9x */
|
||||
"expected ERROR_INVALID_DATA, got %d (0x%08x)\n", GetLastError(),
|
||||
GetLastError());
|
||||
/* This signed CTL with the appropriate inner content type can be decoded.
|
||||
*/
|
||||
ctl = CertCreateCTLContext(X509_ASN_ENCODING,
|
||||
signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent));
|
||||
ok(ctl != NULL, "CertCreateCTLContext failed: %08x\n", GetLastError());
|
||||
if (ctl)
|
||||
{
|
||||
/* Even though the CTL was decoded with X509_ASN_ENCODING, the
|
||||
* message encoding type is included in the CTL's encoding type.
|
||||
*/
|
||||
ok(ctl->dwMsgAndCertEncodingType ==
|
||||
(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING),
|
||||
"expected X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, got %08x\n",
|
||||
ctl->dwMsgAndCertEncodingType);
|
||||
CertFreeCTLContext(ctl);
|
||||
}
|
||||
/* This CTL with a bad signature can also be decoded, so the sig isn't
|
||||
* checked when loading the CTL.
|
||||
*/
|
||||
ctl = CertCreateCTLContext(X509_ASN_ENCODING,
|
||||
signedCTLWithCTLInnerContentAndBadSig,
|
||||
sizeof(signedCTLWithCTLInnerContentAndBadSig));
|
||||
ok(ctl != NULL, "CertCreateCTLContext failed: %08x\n", GetLastError());
|
||||
if (ctl)
|
||||
CertFreeCTLContext(ctl);
|
||||
}
|
||||
|
||||
static void checkHash(const BYTE *data, DWORD dataLen, ALG_ID algID,
|
||||
PCCTL_CONTEXT context, DWORD propID)
|
||||
{
|
||||
BYTE hash[20] = { 0 }, hashProperty[20];
|
||||
BOOL ret;
|
||||
DWORD size;
|
||||
|
||||
memset(hash, 0, sizeof(hash));
|
||||
memset(hashProperty, 0, sizeof(hashProperty));
|
||||
size = sizeof(hash);
|
||||
ret = CryptHashCertificate(0, algID, 0, data, dataLen, hash, &size);
|
||||
ret = CertGetCTLContextProperty(context, propID, hashProperty, &size);
|
||||
ok(ret, "CertGetCTLContextProperty failed: %08x\n", GetLastError());
|
||||
if (ret)
|
||||
ok(!memcmp(hash, hashProperty, size),
|
||||
"Unexpected hash for property %d\n", propID);
|
||||
}
|
||||
|
||||
static void testCTLProperties(void)
|
||||
{
|
||||
PCCTL_CONTEXT ctl;
|
||||
BOOL ret;
|
||||
DWORD propID, numProps, access, size;
|
||||
|
||||
ctl = CertCreateCTLContext(X509_ASN_ENCODING,
|
||||
signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent));
|
||||
if (!ctl)
|
||||
{
|
||||
skip("CertCreateCTLContext failed: %08x\n", GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
/* No properties as yet */
|
||||
propID = 0;
|
||||
numProps = 0;
|
||||
do {
|
||||
propID = CertEnumCTLContextProperties(ctl, propID);
|
||||
if (propID)
|
||||
numProps++;
|
||||
} while (propID != 0);
|
||||
ok(numProps == 0, "Expected 0 properties, got %d\n", numProps);
|
||||
|
||||
/* An implicit property */
|
||||
ret = CertGetCTLContextProperty(ctl, CERT_ACCESS_STATE_PROP_ID, NULL,
|
||||
&size);
|
||||
ok(ret, "CertGetCTLContextProperty failed: %08x\n", GetLastError());
|
||||
ret = CertGetCTLContextProperty(ctl, CERT_ACCESS_STATE_PROP_ID, &access,
|
||||
&size);
|
||||
ok(ret, "CertGetCTLContextProperty failed: %08x\n", GetLastError());
|
||||
ok(!(access & CERT_ACCESS_STATE_WRITE_PERSIST_FLAG),
|
||||
"Didn't expect a persisted cert\n");
|
||||
|
||||
checkHash(signedCTLWithCTLInnerContent,
|
||||
sizeof(signedCTLWithCTLInnerContent), CALG_SHA1, ctl, CERT_HASH_PROP_ID);
|
||||
|
||||
/* Now that the hash property is set, we should get one property when
|
||||
* enumerating.
|
||||
*/
|
||||
propID = 0;
|
||||
numProps = 0;
|
||||
do {
|
||||
propID = CertEnumCTLContextProperties(ctl, propID);
|
||||
if (propID)
|
||||
numProps++;
|
||||
} while (propID != 0);
|
||||
ok(numProps == 1, "Expected 1 properties, got %d\n", numProps);
|
||||
|
||||
checkHash(signedCTLWithCTLInnerContent,
|
||||
sizeof(signedCTLWithCTLInnerContent), CALG_MD5, ctl,
|
||||
CERT_MD5_HASH_PROP_ID);
|
||||
|
||||
CertFreeCTLContext(ctl);
|
||||
}
|
||||
|
||||
static const BYTE signedCTLWithUsage[] = {
|
||||
0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
|
||||
0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
|
||||
0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
|
||||
0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x0a,
|
||||
0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x18,0x0f,0x31,0x36,0x30,
|
||||
0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,
|
||||
0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
|
||||
0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
|
||||
0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
|
||||
0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
|
||||
0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
|
||||
0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
|
||||
0x01,0x09,0x04,0x31,0x12,0x04,0x10,0xc4,0x3e,0x7e,0xc8,0xf9,0x85,0xf3,0x27,
|
||||
0x7d,0xc0,0x38,0xb2,0x7f,0xc7,0x76,0x85,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
|
||||
0x40,0x90,0x33,0x1b,0xb4,0x88,0x35,0xe6,0xf7,0x7f,0x93,0x05,0xc9,0x1a,0x0e,
|
||||
0x8f,0x21,0xc0,0xaa,0xb3,0xab,0x3e,0x4a,0xa6,0x63,0x74,0xfd,0xef,0x11,0xbd,
|
||||
0x67,0x3a,0x1b,0x07,0x4b,0x88,0x59,0x31,0xd5,0x08,0xf9,0x09,0x2f,0x0b,0x85,
|
||||
0x62,0x5a,0x67,0x3b,0x62,0x7e,0x81,0x31,0xea,0xa4,0x36,0x5f,0x9a,0x92,0xb6,
|
||||
0x66,0xa5,0x00,0x60,0x96 };
|
||||
static const BYTE signedCTLWithListID1[] = {
|
||||
0x30,0x82,0x01,0x07,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
|
||||
0xa0,0x81,0xf9,0x30,0x81,0xf6,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,
|
||||
0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x29,0x06,0x09,0x2b,
|
||||
0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x1c,0x30,0x1a,0x30,0x00,0x04,
|
||||
0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,
|
||||
0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,
|
||||
0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
|
||||
0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,
|
||||
0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,
|
||||
0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,
|
||||
0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,
|
||||
0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x09,0x04,0x31,0x12,0x04,0x10,0xbc,
|
||||
0x13,0xde,0x17,0xc7,0x7c,0x67,0x5b,0xf9,0xa9,0x7c,0xb0,0xd9,0xf2,0x84,0xd5,
|
||||
0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
|
||||
static const BYTE signedCTLWithListID2[] = {
|
||||
0x30,0x82,0x01,0x07,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
|
||||
0xa0,0x81,0xf9,0x30,0x81,0xf6,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,
|
||||
0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x29,0x06,0x09,0x2b,
|
||||
0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x1c,0x30,0x1a,0x30,0x00,0x04,
|
||||
0x01,0x02,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,
|
||||
0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,
|
||||
0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
|
||||
0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,
|
||||
0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,
|
||||
0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,
|
||||
0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,
|
||||
0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x60,
|
||||
0x6b,0x10,0xb6,0xb8,0x74,0xb8,0xf3,0x79,0xd5,0x42,0x15,0x4a,0x60,0x93,0x1f,
|
||||
0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff };
|
||||
|
||||
static void testAddCTLToStore(void)
|
||||
{
|
||||
HCERTSTORE store;
|
||||
BOOL ret;
|
||||
DWORD numCTLs;
|
||||
PCCTL_CONTEXT ctl;
|
||||
|
||||
store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
||||
CERT_STORE_CREATE_NEW_FLAG, NULL);
|
||||
/* Add two CTLs */
|
||||
ret = CertAddEncodedCTLToStore(store, X509_ASN_ENCODING,
|
||||
signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent),
|
||||
CERT_STORE_ADD_ALWAYS, NULL);
|
||||
ok(ret, "CertAddEncodedCTLToStore failed: %08x\n", GetLastError());
|
||||
ret = CertAddEncodedCTLToStore(store, X509_ASN_ENCODING,
|
||||
signedCTLWithCTLInnerContentAndBadSig,
|
||||
sizeof(signedCTLWithCTLInnerContentAndBadSig), CERT_STORE_ADD_ALWAYS,
|
||||
NULL);
|
||||
ok(ret, "CertAddEncodedCTLToStore failed: %08x\n", GetLastError());
|
||||
/* Check that two exist */
|
||||
numCTLs = 0;
|
||||
ctl = NULL;
|
||||
do {
|
||||
ctl = CertEnumCTLsInStore(store, ctl);
|
||||
if (ctl)
|
||||
numCTLs++;
|
||||
} while (ctl);
|
||||
ok(numCTLs == 2, "expected 2 CTLs, got %d\n", numCTLs);
|
||||
CertCloseStore(store, 0);
|
||||
|
||||
store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
||||
CERT_STORE_CREATE_NEW_FLAG, NULL);
|
||||
/* Add the two CTLs again. They're identical except for the signature.. */
|
||||
ret = CertAddEncodedCTLToStore(store, X509_ASN_ENCODING,
|
||||
signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent),
|
||||
CERT_STORE_ADD_NEW, NULL);
|
||||
ok(ret, "CertAddEncodedCTLToStore failed: %08x\n", GetLastError());
|
||||
/* so adding the second CTL fails. */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CertAddEncodedCTLToStore(store, X509_ASN_ENCODING,
|
||||
signedCTLWithCTLInnerContentAndBadSig,
|
||||
sizeof(signedCTLWithCTLInnerContentAndBadSig), CERT_STORE_ADD_NEW,
|
||||
NULL);
|
||||
if (ret)
|
||||
{
|
||||
/* win9x */
|
||||
ok(GetLastError() == CRYPT_E_NOT_FOUND,
|
||||
"Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
ok(!ret && GetLastError() == CRYPT_E_EXISTS,
|
||||
"expected CRYPT_E_EXISTS, got %d %08x\n", ret, GetLastError());
|
||||
}
|
||||
CertCloseStore(store, 0);
|
||||
|
||||
store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
||||
CERT_STORE_CREATE_NEW_FLAG, NULL);
|
||||
/* Add two CTLs. These two have different usages, so they're considered
|
||||
* different.
|
||||
*/
|
||||
ret = CertAddEncodedCTLToStore(store, X509_ASN_ENCODING,
|
||||
signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent),
|
||||
CERT_STORE_ADD_NEW, NULL);
|
||||
ok(ret, "CertAddEncodedCTLToStore failed: %08x\n", GetLastError());
|
||||
ret = CertAddEncodedCTLToStore(store, X509_ASN_ENCODING,
|
||||
signedCTLWithUsage, sizeof(signedCTLWithUsage), CERT_STORE_ADD_NEW,
|
||||
NULL);
|
||||
ok(ret, "CertAddEncodedCTLToStore failed: %08x\n", GetLastError());
|
||||
/* Check that two exist */
|
||||
numCTLs = 0;
|
||||
ctl = NULL;
|
||||
do {
|
||||
ctl = CertEnumCTLsInStore(store, ctl);
|
||||
if (ctl)
|
||||
numCTLs++;
|
||||
} while (ctl);
|
||||
ok(numCTLs == 2, "expected 2 CTLs, got %d\n", numCTLs);
|
||||
CertCloseStore(store, 0);
|
||||
|
||||
store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
|
||||
CERT_STORE_CREATE_NEW_FLAG, NULL);
|
||||
/* Add two CTLs. Now they have the same (empty) usages and different list
|
||||
* IDs, so they're different.
|
||||
*/
|
||||
ret = CertAddEncodedCTLToStore(store, X509_ASN_ENCODING,
|
||||
signedCTLWithListID1, sizeof(signedCTLWithListID1), CERT_STORE_ADD_NEW,
|
||||
NULL);
|
||||
ok(ret, "CertAddEncodedCTLToStore failed: %08x\n", GetLastError());
|
||||
ret = CertAddEncodedCTLToStore(store, X509_ASN_ENCODING,
|
||||
signedCTLWithListID2, sizeof(signedCTLWithListID2), CERT_STORE_ADD_NEW,
|
||||
NULL);
|
||||
ok(ret, "CertAddEncodedCTLToStore failed: %08x\n", GetLastError());
|
||||
/* Check that two exist */
|
||||
numCTLs = 0;
|
||||
ctl = NULL;
|
||||
do {
|
||||
ctl = CertEnumCTLsInStore(store, ctl);
|
||||
if (ctl)
|
||||
numCTLs++;
|
||||
} while (ctl);
|
||||
ok(numCTLs == 2, "expected 2 CTLs, got %d\n", numCTLs);
|
||||
CertCloseStore(store, 0);
|
||||
}
|
||||
|
||||
START_TEST(ctl)
|
||||
{
|
||||
testCreateCTL();
|
||||
testCTLProperties();
|
||||
testAddCTLToStore();
|
||||
}
|
7589
rostests/winetests/crypt32/encode.c
Normal file
7589
rostests/winetests/crypt32/encode.c
Normal file
File diff suppressed because it is too large
Load diff
498
rostests/winetests/crypt32/main.c
Normal file
498
rostests/winetests/crypt32/main.c
Normal file
|
@ -0,0 +1,498 @@
|
|||
/*
|
||||
* Miscellaneous crypt32 tests
|
||||
*
|
||||
* Copyright 2005 Juan Lang
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#include <winerror.h>
|
||||
#include <wincrypt.h>
|
||||
#include <winreg.h>
|
||||
|
||||
#include "wine/test.h"
|
||||
|
||||
HMODULE hCrypt;
|
||||
|
||||
static void test_findAttribute(void)
|
||||
{
|
||||
PCRYPT_ATTRIBUTE ret;
|
||||
BYTE blobbin[] = {0x02,0x01,0x01};
|
||||
static CHAR oid[] = "1.2.3";
|
||||
CRYPT_ATTR_BLOB blobs[] = { { sizeof blobbin, blobbin }, };
|
||||
CRYPT_ATTRIBUTE attr = { oid, sizeof(blobs) / sizeof(blobs[0]), blobs };
|
||||
|
||||
/* returns NULL, last error not set */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CertFindAttribute(NULL, 0, NULL);
|
||||
ok(ret == NULL, "Expected failure\n");
|
||||
ok(GetLastError() == 0xdeadbeef, "Last error was set to %08x\n",
|
||||
GetLastError());
|
||||
if (0)
|
||||
{
|
||||
/* crashes */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CertFindAttribute(NULL, 1, NULL);
|
||||
/* returns NULL, last error is ERROR_INVALID_PARAMETER
|
||||
* crashes on Vista
|
||||
*/
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CertFindAttribute(NULL, 1, &attr);
|
||||
ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"Expected ERROR_INVALID_PARAMETER, got %d (%08x)\n", GetLastError(),
|
||||
GetLastError());
|
||||
}
|
||||
/* returns NULL, last error not set */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CertFindAttribute("bogus", 1, &attr);
|
||||
ok(ret == NULL, "Expected failure\n");
|
||||
ok(GetLastError() == 0xdeadbeef, "Last error was set to %08x\n",
|
||||
GetLastError());
|
||||
/* returns NULL, last error not set */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CertFindAttribute("1.2.4", 1, &attr);
|
||||
ok(ret == NULL, "Expected failure\n");
|
||||
ok(GetLastError() == 0xdeadbeef, "Last error was set to %08x\n",
|
||||
GetLastError());
|
||||
/* succeeds, last error not set */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CertFindAttribute("1.2.3", 1, &attr);
|
||||
ok(ret != NULL, "CertFindAttribute failed: %08x\n", GetLastError());
|
||||
}
|
||||
|
||||
static void test_findExtension(void)
|
||||
{
|
||||
PCERT_EXTENSION ret;
|
||||
static CHAR oid[] = "1.2.3";
|
||||
BYTE blobbin[] = {0x02,0x01,0x01};
|
||||
CERT_EXTENSION ext = { oid, TRUE, { sizeof blobbin, blobbin } };
|
||||
|
||||
/* returns NULL, last error not set */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CertFindExtension(NULL, 0, NULL);
|
||||
ok(ret == NULL, "Expected failure\n");
|
||||
ok(GetLastError() == 0xdeadbeef, "Last error was set to %08x\n",
|
||||
GetLastError());
|
||||
if (0)
|
||||
{
|
||||
/* crashes */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CertFindExtension(NULL, 1, NULL);
|
||||
/* returns NULL, last error is ERROR_INVALID_PARAMETER
|
||||
* crashes on Vista
|
||||
*/
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CertFindExtension(NULL, 1, &ext);
|
||||
ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"Expected ERROR_INVALID_PARAMETER, got %d (%08x)\n", GetLastError(),
|
||||
GetLastError());
|
||||
}
|
||||
/* returns NULL, last error not set */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CertFindExtension("bogus", 1, &ext);
|
||||
ok(ret == NULL, "Expected failure\n");
|
||||
ok(GetLastError() == 0xdeadbeef, "Last error was set to %08x\n",
|
||||
GetLastError());
|
||||
/* returns NULL, last error not set */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CertFindExtension("1.2.4", 1, &ext);
|
||||
ok(ret == NULL, "Expected failure\n");
|
||||
ok(GetLastError() == 0xdeadbeef, "Last error was set to %08x\n",
|
||||
GetLastError());
|
||||
/* succeeds, last error not set */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CertFindExtension("1.2.3", 1, &ext);
|
||||
ok(ret != NULL, "CertFindExtension failed: %08x\n", GetLastError());
|
||||
}
|
||||
|
||||
static void test_findRDNAttr(void)
|
||||
{
|
||||
PCERT_RDN_ATTR ret;
|
||||
static CHAR oid[] = "1.2.3";
|
||||
BYTE bin[] = { 0x16,0x09,'J','u','a','n',' ','L','a','n','g' };
|
||||
CERT_RDN_ATTR attrs[] = {
|
||||
{ oid, CERT_RDN_IA5_STRING, { sizeof bin, bin } },
|
||||
};
|
||||
CERT_RDN rdns[] = {
|
||||
{ sizeof(attrs) / sizeof(attrs[0]), attrs },
|
||||
};
|
||||
CERT_NAME_INFO nameInfo = { sizeof(rdns) / sizeof(rdns[0]), rdns };
|
||||
|
||||
if (0)
|
||||
{
|
||||
/* crashes */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CertFindRDNAttr(NULL, NULL);
|
||||
/* returns NULL, last error is ERROR_INVALID_PARAMETER
|
||||
* crashes on Vista
|
||||
*/
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CertFindRDNAttr(NULL, &nameInfo);
|
||||
ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"Expected ERROR_INVALID_PARAMETER, got %d (%08x)\n", GetLastError(),
|
||||
GetLastError());
|
||||
}
|
||||
/* returns NULL, last error not set */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CertFindRDNAttr("bogus", &nameInfo);
|
||||
ok(ret == NULL, "Expected failure\n");
|
||||
ok(GetLastError() == 0xdeadbeef, "Last error was set to %08x\n",
|
||||
GetLastError());
|
||||
/* returns NULL, last error not set */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CertFindRDNAttr("1.2.4", &nameInfo);
|
||||
ok(ret == NULL, "Expected failure\n");
|
||||
ok(GetLastError() == 0xdeadbeef, "Last error was set to %08x\n",
|
||||
GetLastError());
|
||||
/* succeeds, last error not set */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CertFindRDNAttr("1.2.3", &nameInfo);
|
||||
ok(ret != NULL, "CertFindRDNAttr failed: %08x\n", GetLastError());
|
||||
}
|
||||
|
||||
static void test_verifyTimeValidity(void)
|
||||
{
|
||||
SYSTEMTIME sysTime;
|
||||
FILETIME fileTime;
|
||||
CERT_INFO info = { 0 };
|
||||
LONG ret;
|
||||
|
||||
GetSystemTime(&sysTime);
|
||||
SystemTimeToFileTime(&sysTime, &fileTime);
|
||||
/* crashes
|
||||
ret = CertVerifyTimeValidity(NULL, NULL);
|
||||
ret = CertVerifyTimeValidity(&fileTime, NULL);
|
||||
*/
|
||||
/* Check with 0 NotBefore and NotAfter */
|
||||
ret = CertVerifyTimeValidity(&fileTime, &info);
|
||||
ok(ret == 1, "Expected 1, got %d\n", ret);
|
||||
memcpy(&info.NotAfter, &fileTime, sizeof(info.NotAfter));
|
||||
/* Check with NotAfter equal to comparison time */
|
||||
ret = CertVerifyTimeValidity(&fileTime, &info);
|
||||
ok(ret == 0, "Expected 0, got %d\n", ret);
|
||||
/* Check with NotBefore after comparison time */
|
||||
memcpy(&info.NotBefore, &fileTime, sizeof(info.NotBefore));
|
||||
info.NotBefore.dwLowDateTime += 5000;
|
||||
ret = CertVerifyTimeValidity(&fileTime, &info);
|
||||
ok(ret == -1, "Expected -1, got %d\n", ret);
|
||||
}
|
||||
|
||||
static void test_cryptAllocate(void)
|
||||
{
|
||||
LPVOID buf;
|
||||
|
||||
buf = CryptMemAlloc(0);
|
||||
ok(buf != NULL, "CryptMemAlloc failed: %08x\n", GetLastError());
|
||||
CryptMemFree(buf);
|
||||
/* CryptMemRealloc(NULL, 0) fails pre-Vista */
|
||||
buf = CryptMemAlloc(0);
|
||||
buf = CryptMemRealloc(buf, 1);
|
||||
ok(buf != NULL, "CryptMemRealloc failed: %08x\n", GetLastError());
|
||||
CryptMemFree(buf);
|
||||
}
|
||||
|
||||
typedef DWORD (WINAPI *I_CryptAllocTlsFunc)(void);
|
||||
typedef LPVOID (WINAPI *I_CryptDetachTlsFunc)(DWORD dwTlsIndex);
|
||||
typedef LPVOID (WINAPI *I_CryptGetTlsFunc)(DWORD dwTlsIndex);
|
||||
typedef BOOL (WINAPI *I_CryptSetTlsFunc)(DWORD dwTlsIndex, LPVOID lpTlsValue);
|
||||
typedef BOOL (WINAPI *I_CryptFreeTlsFunc)(DWORD dwTlsIndex, DWORD unknown);
|
||||
|
||||
static I_CryptAllocTlsFunc pI_CryptAllocTls;
|
||||
static I_CryptDetachTlsFunc pI_CryptDetachTls;
|
||||
static I_CryptGetTlsFunc pI_CryptGetTls;
|
||||
static I_CryptSetTlsFunc pI_CryptSetTls;
|
||||
static I_CryptFreeTlsFunc pI_CryptFreeTls;
|
||||
|
||||
static void test_cryptTls(void)
|
||||
{
|
||||
DWORD index;
|
||||
BOOL ret;
|
||||
|
||||
pI_CryptAllocTls = (I_CryptAllocTlsFunc)GetProcAddress(hCrypt,
|
||||
"I_CryptAllocTls");
|
||||
pI_CryptDetachTls = (I_CryptDetachTlsFunc)GetProcAddress(hCrypt,
|
||||
"I_CryptDetachTls");
|
||||
pI_CryptGetTls = (I_CryptGetTlsFunc)GetProcAddress(hCrypt,
|
||||
"I_CryptGetTls");
|
||||
pI_CryptSetTls = (I_CryptSetTlsFunc)GetProcAddress(hCrypt,
|
||||
"I_CryptSetTls");
|
||||
pI_CryptFreeTls = (I_CryptFreeTlsFunc)GetProcAddress(hCrypt,
|
||||
"I_CryptFreeTls");
|
||||
|
||||
/* One normal pass */
|
||||
index = pI_CryptAllocTls();
|
||||
ok(index, "I_CryptAllocTls failed: %08x\n", GetLastError());
|
||||
if (index)
|
||||
{
|
||||
LPVOID ptr;
|
||||
|
||||
ptr = pI_CryptGetTls(index);
|
||||
ok(!ptr, "Expected NULL\n");
|
||||
ret = pI_CryptSetTls(index, (LPVOID)0xdeadbeef);
|
||||
ok(ret, "I_CryptSetTls failed: %08x\n", GetLastError());
|
||||
ptr = pI_CryptGetTls(index);
|
||||
ok(ptr == (LPVOID)0xdeadbeef, "Expected 0xdeadbeef, got %p\n", ptr);
|
||||
/* This crashes
|
||||
ret = pI_CryptFreeTls(index, 1);
|
||||
*/
|
||||
ret = pI_CryptFreeTls(index, 0);
|
||||
ok(ret, "I_CryptFreeTls failed: %08x\n", GetLastError());
|
||||
ret = pI_CryptFreeTls(index, 0);
|
||||
/* Not sure if this fails because TlsFree should fail, so leave as
|
||||
* todo for now.
|
||||
*/
|
||||
todo_wine ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
}
|
||||
/* Similar pass, check I_CryptDetachTls */
|
||||
index = pI_CryptAllocTls();
|
||||
ok(index, "I_CryptAllocTls failed: %08x\n", GetLastError());
|
||||
if (index)
|
||||
{
|
||||
LPVOID ptr;
|
||||
|
||||
ptr = pI_CryptGetTls(index);
|
||||
ok(!ptr, "Expected NULL\n");
|
||||
ret = pI_CryptSetTls(index, (LPVOID)0xdeadbeef);
|
||||
ok(ret, "I_CryptSetTls failed: %08x\n", GetLastError());
|
||||
ptr = pI_CryptGetTls(index);
|
||||
ok(ptr == (LPVOID)0xdeadbeef, "Expected 0xdeadbeef, got %p\n", ptr);
|
||||
ptr = pI_CryptDetachTls(index);
|
||||
ok(ptr == (LPVOID)0xdeadbeef, "Expected 0xdeadbeef, got %p\n", ptr);
|
||||
ptr = pI_CryptGetTls(index);
|
||||
ok(!ptr, "Expected NULL\n");
|
||||
}
|
||||
}
|
||||
|
||||
typedef BOOL (WINAPI *I_CryptReadTrustedPublisherDWORDValueFromRegistryFunc)
|
||||
(LPCWSTR, DWORD *);
|
||||
|
||||
static void test_readTrustedPublisherDWORD(void)
|
||||
{
|
||||
I_CryptReadTrustedPublisherDWORDValueFromRegistryFunc pReadDWORD;
|
||||
|
||||
pReadDWORD =
|
||||
(I_CryptReadTrustedPublisherDWORDValueFromRegistryFunc)GetProcAddress(
|
||||
hCrypt, "I_CryptReadTrustedPublisherDWORDValueFromRegistry");
|
||||
if (pReadDWORD)
|
||||
{
|
||||
static const WCHAR safer[] = {
|
||||
'S','o','f','t','w','a','r','e','\\',
|
||||
'P','o','l','i','c','i','e','s','\\',
|
||||
'M','i','c','r','o','s','o','f','t','\\','S','y','s','t','e','m',
|
||||
'C','e','r','t','i','f','i','c','a','t','e','s','\\',
|
||||
'T','r','u','s','t','e','d','P','u','b','l','i','s','h','e','r',
|
||||
'\\','S','a','f','e','r',0 };
|
||||
static const WCHAR authenticodeFlags[] = { 'A','u','t','h','e','n',
|
||||
't','i','c','o','d','e','F','l','a','g','s',0 };
|
||||
BOOL ret, exists = FALSE;
|
||||
DWORD size, readFlags = 0, returnedFlags;
|
||||
HKEY key;
|
||||
LONG rc;
|
||||
|
||||
rc = RegOpenKeyW(HKEY_LOCAL_MACHINE, safer, &key);
|
||||
if (rc == ERROR_SUCCESS)
|
||||
{
|
||||
size = sizeof(readFlags);
|
||||
rc = RegQueryValueExW(key, authenticodeFlags, NULL, NULL,
|
||||
(LPBYTE)&readFlags, &size);
|
||||
if (rc == ERROR_SUCCESS)
|
||||
exists = TRUE;
|
||||
}
|
||||
returnedFlags = 0xdeadbeef;
|
||||
ret = pReadDWORD(authenticodeFlags, &returnedFlags);
|
||||
ok(ret == exists, "Unexpected return value\n");
|
||||
ok(readFlags == returnedFlags,
|
||||
"Expected flags %08x, got %08x\n", readFlags, returnedFlags);
|
||||
}
|
||||
}
|
||||
|
||||
typedef HCRYPTPROV (WINAPI *I_CryptGetDefaultCryptProvFunc)(DWORD w);
|
||||
|
||||
static void test_getDefaultCryptProv(void)
|
||||
{
|
||||
I_CryptGetDefaultCryptProvFunc pI_CryptGetDefaultCryptProv;
|
||||
HCRYPTPROV prov;
|
||||
|
||||
pI_CryptGetDefaultCryptProv = (I_CryptGetDefaultCryptProvFunc)
|
||||
GetProcAddress(hCrypt, "I_CryptGetDefaultCryptProv");
|
||||
if (!pI_CryptGetDefaultCryptProv) return;
|
||||
|
||||
prov = pI_CryptGetDefaultCryptProv(0xdeadbeef);
|
||||
ok(prov == 0 && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
prov = pI_CryptGetDefaultCryptProv(PROV_RSA_FULL);
|
||||
ok(prov == 0 && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
prov = pI_CryptGetDefaultCryptProv(1);
|
||||
ok(prov == 0 && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
prov = pI_CryptGetDefaultCryptProv(0);
|
||||
ok(prov != 0, "I_CryptGetDefaultCryptProv failed: %08x\n", GetLastError());
|
||||
CryptReleaseContext(prov, 0);
|
||||
}
|
||||
|
||||
typedef int (WINAPI *I_CryptInstallOssGlobal)(DWORD,DWORD,DWORD);
|
||||
|
||||
static void test_CryptInstallOssGlobal(void)
|
||||
{
|
||||
int ret,i;
|
||||
I_CryptInstallOssGlobal pI_CryptInstallOssGlobal;
|
||||
|
||||
pI_CryptInstallOssGlobal= (I_CryptInstallOssGlobal)GetProcAddress(hCrypt,"I_CryptInstallOssGlobal");
|
||||
/* passing in some random values to I_CryptInstallOssGlobal, it always returns 9 the first time, then 10, 11 etc.*/
|
||||
for(i=0;i<30;i++)
|
||||
{
|
||||
ret = pI_CryptInstallOssGlobal(rand(),rand(),rand());
|
||||
ok((9+i) == ret ||
|
||||
ret == 0, /* Vista */
|
||||
"Expected %d or 0, got %d\n",(9+i),ret);
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL (WINAPI *pCryptFormatObject)(DWORD dwEncoding, DWORD dwFormatType,
|
||||
DWORD dwFormatStrType, void *pFormatStruct, LPCSTR lpszStructType,
|
||||
const BYTE *pbEncoded, DWORD dwEncoded, void *pbFormat, DWORD *pcbFormat);
|
||||
|
||||
static const BYTE encodedInt[] = { 0x02,0x01,0x01 };
|
||||
static const WCHAR encodedIntStr[] = { '0','2',' ','0','1',' ','0','1',0 };
|
||||
static const BYTE encodedBigInt[] = { 0x02,0x1f,0x01,0x02,0x03,0x04,0x05,0x06,
|
||||
0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,
|
||||
0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f };
|
||||
static const WCHAR encodedBigIntStr[] = { '0','2',' ','1','f',' ','0','1',' ',
|
||||
'0','2',' ','0','3',' ','0','4',' ','0','5',' ','0','6',' ','0','7',' ','0',
|
||||
'8',' ','0','9',' ','0','a',' ','0','b',' ','0','c',' ','0','d',' ','0','e',
|
||||
' ','0','f',' ','1','0',' ','1','1',' ','1','2',' ','1','3',' ','1','4',' ',
|
||||
'1','5',' ','1','6',' ','1','7',' ','1','8',' ','1','9',' ','1','a',' ','1',
|
||||
'b',' ','1','c',' ','1','d',' ','1','e',' ','1','f',0 };
|
||||
|
||||
static void test_format_object(void)
|
||||
{
|
||||
BOOL ret;
|
||||
DWORD size;
|
||||
LPWSTR str;
|
||||
|
||||
pCryptFormatObject = (void *)GetProcAddress(hCrypt, "CryptFormatObject");
|
||||
if (!pCryptFormatObject)
|
||||
{
|
||||
skip("No CryptFormatObject\n");
|
||||
return;
|
||||
}
|
||||
/* Crash */
|
||||
if (0)
|
||||
{
|
||||
ret = pCryptFormatObject(0, 0, 0, NULL, NULL, NULL, 0, NULL, NULL);
|
||||
}
|
||||
/* When called with any but the default encoding, it fails to find a
|
||||
* formatting function.
|
||||
*/
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pCryptFormatObject(0, 0, 0, NULL, NULL, NULL, 0, NULL, &size);
|
||||
ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
|
||||
"expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
|
||||
/* When called with the default encoding type for any undefined struct type
|
||||
* (including none), it succeeds: the default encoding is a hex string
|
||||
* encoding.
|
||||
*/
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pCryptFormatObject(X509_ASN_ENCODING, 0, 0, NULL, NULL, NULL, 0,
|
||||
NULL, &size);
|
||||
ok(ret, "CryptFormatObject failed: %d\n", GetLastError());
|
||||
if (ret)
|
||||
{
|
||||
if (size == 0 && GetLastError() == ERROR_FILE_NOT_FOUND)
|
||||
{
|
||||
win_skip("CryptFormatObject has no default implementation\n");
|
||||
return;
|
||||
}
|
||||
ok(size == sizeof(WCHAR), "unexpected size %d\n", size);
|
||||
str = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
SetLastError(0xdeadbeef);
|
||||
size = 0;
|
||||
ret = pCryptFormatObject(X509_ASN_ENCODING, 0, 0, NULL, NULL, NULL, 0,
|
||||
str, &size);
|
||||
ok(!ret && GetLastError() == ERROR_MORE_DATA,
|
||||
"expected ERROR_MORE_DATA, got %d\n", GetLastError());
|
||||
size = sizeof(WCHAR);
|
||||
ret = pCryptFormatObject(X509_ASN_ENCODING, 0, 0, NULL, NULL, NULL, 0,
|
||||
str, &size);
|
||||
ok(ret, "CryptFormatObject failed: %d\n", GetLastError());
|
||||
ok(!str[0], "expected empty string\n");
|
||||
HeapFree(GetProcessHeap(), 0, str);
|
||||
}
|
||||
ret = pCryptFormatObject(X509_ASN_ENCODING, 0, 0, NULL, NULL, encodedInt,
|
||||
sizeof(encodedInt), NULL, &size);
|
||||
ok(ret, "CryptFormatObject failed: %d\n", GetLastError());
|
||||
if (ret)
|
||||
{
|
||||
str = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
ret = pCryptFormatObject(X509_ASN_ENCODING, 0, 0, NULL, NULL,
|
||||
encodedInt, sizeof(encodedInt), str, &size);
|
||||
ok(ret, "CryptFormatObject failed: %d\n", GetLastError());
|
||||
ok(!lstrcmpW(str, encodedIntStr), "unexpected format string\n");
|
||||
HeapFree(GetProcessHeap(), 0, str);
|
||||
}
|
||||
ret = pCryptFormatObject(X509_ASN_ENCODING, 0, 0, NULL, NULL,
|
||||
encodedBigInt, sizeof(encodedBigInt), NULL, &size);
|
||||
ok(ret, "CryptFormatObject failed: %d\n", GetLastError());
|
||||
if (ret)
|
||||
{
|
||||
str = HeapAlloc(GetProcessHeap(), 0, size);
|
||||
ret = pCryptFormatObject(X509_ASN_ENCODING, 0, 0, NULL, NULL,
|
||||
encodedBigInt, sizeof(encodedBigInt), str, &size);
|
||||
ok(ret, "CryptFormatObject failed: %d\n", GetLastError());
|
||||
ok(!lstrcmpiW(str, encodedBigIntStr), "unexpected format string\n");
|
||||
HeapFree(GetProcessHeap(), 0, str);
|
||||
}
|
||||
/* When called with the default encoding type for any undefined struct
|
||||
* type but CRYPT_FORMAT_STR_NO_HEX specified, it fails to find a
|
||||
* formatting function.
|
||||
*/
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pCryptFormatObject(X509_ASN_ENCODING, 0, CRYPT_FORMAT_STR_NO_HEX,
|
||||
NULL, NULL, NULL, 0, NULL, &size);
|
||||
ok(!ret, "CryptFormatObject succeeded\n");
|
||||
ok(GetLastError() == ERROR_FILE_NOT_FOUND ||
|
||||
GetLastError() == 0xdeadbeef, /* Vista, W2K8 */
|
||||
"expected ERROR_FILE_NOT_FOUND or no change, got %d\n", GetLastError());
|
||||
/* When called to format an AUTHORITY_KEY_ID2_INFO, it fails when no
|
||||
* data are given.
|
||||
*/
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pCryptFormatObject(X509_ASN_ENCODING, 0, 0, NULL,
|
||||
szOID_AUTHORITY_KEY_IDENTIFIER2, NULL, 0, NULL, &size);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"expected E_INVALIDARG, got %d\n", GetLastError());
|
||||
}
|
||||
|
||||
START_TEST(main)
|
||||
{
|
||||
hCrypt = GetModuleHandleA("crypt32.dll");
|
||||
|
||||
test_findAttribute();
|
||||
test_findExtension();
|
||||
test_findRDNAttr();
|
||||
test_verifyTimeValidity();
|
||||
test_cryptAllocate();
|
||||
test_cryptTls();
|
||||
test_readTrustedPublisherDWORD();
|
||||
test_getDefaultCryptProv();
|
||||
test_CryptInstallOssGlobal();
|
||||
test_format_object();
|
||||
}
|
721
rostests/winetests/crypt32/message.c
Normal file
721
rostests/winetests/crypt32/message.c
Normal file
|
@ -0,0 +1,721 @@
|
|||
/*
|
||||
* Unit test suite for crypt32.dll's Crypt*Message functions
|
||||
*
|
||||
* Copyright 2007-2008 Juan Lang
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#include <winerror.h>
|
||||
#include <wincrypt.h>
|
||||
|
||||
#include "wine/test.h"
|
||||
|
||||
static const BYTE dataEmptyBareContent[] = { 0x04,0x00 };
|
||||
static const BYTE dataEmptyContent[] = {
|
||||
0x30,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x02,
|
||||
0x04,0x00 };
|
||||
static const BYTE signedEmptyBareContent[] = {
|
||||
0x30,0x50,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
|
||||
0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x31,0x37,0x30,0x35,0x02,
|
||||
0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
|
||||
0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,
|
||||
0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,
|
||||
0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
|
||||
static const BYTE signedEmptyContent[] = {
|
||||
0x30,0x5f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x52,
|
||||
0x30,0x50,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
|
||||
0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0x31,0x37,0x30,0x35,0x02,
|
||||
0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
|
||||
0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,
|
||||
0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,
|
||||
0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
|
||||
|
||||
static void test_msg_get_signer_count(void)
|
||||
{
|
||||
LONG count;
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
count = CryptGetMessageSignerCount(0, NULL, 0);
|
||||
ok(count == -1, "Expected -1, got %d\n", count);
|
||||
ok(GetLastError() == E_INVALIDARG, "Expected E_INVALIDARG, got %08x\n",
|
||||
GetLastError());
|
||||
SetLastError(0xdeadbeef);
|
||||
count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING, NULL, 0);
|
||||
ok(count == -1, "Expected -1, got %d\n", count);
|
||||
ok(GetLastError() == CRYPT_E_ASN1_EOD ||
|
||||
GetLastError() == OSS_BAD_ARG, /* win9x */
|
||||
"Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
|
||||
SetLastError(0xdeadbeef);
|
||||
count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING,
|
||||
dataEmptyBareContent, sizeof(dataEmptyBareContent));
|
||||
ok(count == -1, "Expected -1, got %d\n", count);
|
||||
ok(GetLastError() == CRYPT_E_ASN1_BADTAG ||
|
||||
GetLastError() == OSS_PDU_MISMATCH, /* win9x */
|
||||
"Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
|
||||
SetLastError(0xdeadbeef);
|
||||
count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING,
|
||||
dataEmptyContent, sizeof(dataEmptyContent));
|
||||
ok(count == -1, "Expected -1, got %d\n", count);
|
||||
ok(GetLastError() == CRYPT_E_INVALID_MSG_TYPE,
|
||||
"Expected CRYPT_E_INVALID_MSG_TYPE, got %08x\n", GetLastError());
|
||||
SetLastError(0xdeadbeef);
|
||||
count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING,
|
||||
signedEmptyBareContent, sizeof(signedEmptyBareContent));
|
||||
ok(count == -1, "Expected -1, got %d\n", count);
|
||||
ok(GetLastError() == CRYPT_E_ASN1_BADTAG ||
|
||||
GetLastError() == OSS_DATA_ERROR, /* win9x */
|
||||
"Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
|
||||
count = CryptGetMessageSignerCount(PKCS_7_ASN_ENCODING,
|
||||
signedEmptyContent, sizeof(signedEmptyContent));
|
||||
ok(count == 1 ||
|
||||
broken(count == -1), /* win9x */
|
||||
"Expected 1, got %d\n", count);
|
||||
}
|
||||
|
||||
static BYTE detachedHashContent[] = {
|
||||
0x30,0x3f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x32,
|
||||
0x30,0x30,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
|
||||
0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
|
||||
0x07,0x01,0x04,0x10,0x08,0xd6,0xc0,0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,
|
||||
0x9d,0x2a,0x8f,0x26,0x2f };
|
||||
static const BYTE msgData[] = { 1, 2, 3, 4 };
|
||||
|
||||
static void test_verify_detached_message_hash(void)
|
||||
{
|
||||
BOOL ret;
|
||||
CRYPT_HASH_MESSAGE_PARA para;
|
||||
DWORD size, hashSize;
|
||||
const BYTE *pMsgData = msgData;
|
||||
BYTE hash[16];
|
||||
|
||||
if (0)
|
||||
{
|
||||
ret = CryptVerifyDetachedMessageHash(NULL, NULL, 0, 0, NULL, NULL, NULL,
|
||||
NULL);
|
||||
}
|
||||
memset(¶, 0, sizeof(para));
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptVerifyDetachedMessageHash(¶, NULL, 0, 0, NULL, NULL, NULL,
|
||||
NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
para.cbSize = sizeof(para);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptVerifyDetachedMessageHash(¶, NULL, 0, 0, NULL, NULL, NULL,
|
||||
NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
para.dwMsgEncodingType = PKCS_7_ASN_ENCODING;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptVerifyDetachedMessageHash(¶, NULL, 0, 0, NULL, NULL, NULL,
|
||||
NULL);
|
||||
ok(!ret &&
|
||||
(GetLastError() == CRYPT_E_ASN1_EOD ||
|
||||
GetLastError() == OSS_BAD_ARG), /* win9x */
|
||||
"expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
|
||||
para.dwMsgEncodingType = X509_ASN_ENCODING;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptVerifyDetachedMessageHash(¶, NULL, 0, 0, NULL, NULL, NULL,
|
||||
NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
para.dwMsgEncodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptVerifyDetachedMessageHash(¶, NULL, 0, 0, NULL, NULL, NULL,
|
||||
NULL);
|
||||
ok(!ret &&
|
||||
(GetLastError() == CRYPT_E_ASN1_EOD ||
|
||||
GetLastError() == OSS_BAD_ARG), /* win9x */
|
||||
"expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
|
||||
/* Curiously, passing no data to hash succeeds.. */
|
||||
ret = CryptVerifyDetachedMessageHash(¶, detachedHashContent,
|
||||
sizeof(detachedHashContent), 0, NULL, NULL, NULL, NULL);
|
||||
todo_wine
|
||||
ok(ret, "CryptVerifyDetachedMessageHash failed: %08x\n", GetLastError());
|
||||
/* as does passing the actual content of the message to hash.. */
|
||||
size = sizeof(msgData);
|
||||
pMsgData = msgData;
|
||||
ret = CryptVerifyDetachedMessageHash(¶, detachedHashContent,
|
||||
sizeof(detachedHashContent), 1, &pMsgData, &size, NULL, NULL);
|
||||
ok(ret, "CryptVerifyDetachedMessageHash failed: %08x\n", GetLastError());
|
||||
/* while passing data to hash that isn't the content of the message fails.
|
||||
*/
|
||||
size = sizeof(detachedHashContent);
|
||||
pMsgData = detachedHashContent;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptVerifyDetachedMessageHash(¶, detachedHashContent,
|
||||
sizeof(detachedHashContent), 1, &pMsgData, &size, NULL, NULL);
|
||||
ok(!ret && GetLastError() == CRYPT_E_HASH_VALUE,
|
||||
"expected CRYPT_E_HASH_VALUE, got %08x\n", GetLastError());
|
||||
/* Getting the size of the hash while passing no hash data causes the
|
||||
* hash to be checked (and fail.)
|
||||
*/
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptVerifyDetachedMessageHash(¶, detachedHashContent,
|
||||
sizeof(detachedHashContent), 0, NULL, NULL, NULL, &hashSize);
|
||||
ok(!ret && GetLastError() == CRYPT_E_HASH_VALUE,
|
||||
"expected CRYPT_E_HASH_VALUE, got %08x\n", GetLastError());
|
||||
size = sizeof(msgData);
|
||||
pMsgData = msgData;
|
||||
ret = CryptVerifyDetachedMessageHash(¶, detachedHashContent,
|
||||
sizeof(detachedHashContent), 1, &pMsgData, &size, NULL, &hashSize);
|
||||
ok(ret, "CryptVerifyDetachedMessageHash failed: %08x\n", GetLastError());
|
||||
ok(hashSize == sizeof(hash), "unexpected size %d\n", hashSize);
|
||||
hashSize = 1;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptVerifyDetachedMessageHash(¶, detachedHashContent,
|
||||
sizeof(detachedHashContent), 1, &pMsgData, &size, hash, &hashSize);
|
||||
ok(!ret && GetLastError() == ERROR_MORE_DATA,
|
||||
"expected ERROR_MORE_DATA, got %08x\n", GetLastError());
|
||||
hashSize = sizeof(hash);
|
||||
ret = CryptVerifyDetachedMessageHash(¶, detachedHashContent,
|
||||
sizeof(detachedHashContent), 1, &pMsgData, &size, hash, &hashSize);
|
||||
ok(ret, "CryptVerifyDetachedMessageHash failed: %08x\n", GetLastError());
|
||||
}
|
||||
|
||||
static BYTE hashContent[] = {
|
||||
0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
|
||||
0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
|
||||
0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
|
||||
0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,0x04,0x10,0x08,0xd6,0xc0,
|
||||
0x5a,0x21,0x51,0x2a,0x79,0xa1,0xdf,0xeb,0x9d,0x2a,0x8f,0x26,0x2f };
|
||||
|
||||
static void test_verify_message_hash(void)
|
||||
{
|
||||
BOOL ret;
|
||||
CRYPT_HASH_MESSAGE_PARA para;
|
||||
DWORD size;
|
||||
BYTE *buf = NULL;
|
||||
|
||||
memset(¶, 0, sizeof(para));
|
||||
/* Crash */
|
||||
if (0)
|
||||
ret = CryptVerifyMessageHash(NULL, NULL, 0, NULL, NULL, NULL, NULL);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptVerifyMessageHash(¶, NULL, 0, NULL, NULL, NULL, NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
para.cbSize = sizeof(para);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptVerifyMessageHash(¶, NULL, 0, NULL, NULL, NULL, NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
para.dwMsgEncodingType = PKCS_7_ASN_ENCODING;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptVerifyMessageHash(¶, NULL, 0, NULL, NULL, NULL, NULL);
|
||||
ok(!ret, "Expected 0, got %d\n", ret);
|
||||
ok(GetLastError() == CRYPT_E_ASN1_EOD ||
|
||||
GetLastError() == OSS_BAD_ARG, /* win98 */
|
||||
"Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
|
||||
/* Verifying the hash of a detached message succeeds? */
|
||||
ret = CryptVerifyMessageHash(¶, detachedHashContent,
|
||||
sizeof(detachedHashContent), NULL, NULL, NULL, NULL);
|
||||
todo_wine
|
||||
ok(ret, "CryptVerifyMessageHash failed: %08x\n", GetLastError());
|
||||
/* As does verifying the hash of a regular message. */
|
||||
ret = CryptVerifyMessageHash(¶, hashContent, sizeof(hashContent),
|
||||
NULL, NULL, NULL, NULL);
|
||||
ok(ret, "CryptVerifyMessageHash failed: %08x\n", GetLastError());
|
||||
ret = CryptVerifyMessageHash(¶, hashContent, sizeof(hashContent),
|
||||
NULL, &size, NULL, NULL);
|
||||
ok(ret, "CryptVerifyMessageHash failed: %08x\n", GetLastError());
|
||||
if (ret)
|
||||
buf = CryptMemAlloc(size);
|
||||
if (buf)
|
||||
{
|
||||
size = 1;
|
||||
ret = CryptVerifyMessageHash(¶, hashContent, sizeof(hashContent),
|
||||
buf, &size, NULL, NULL);
|
||||
ok(!ret && GetLastError() == ERROR_MORE_DATA,
|
||||
"expected ERROR_MORE_DATA, got %08x\n", GetLastError());
|
||||
ret = CryptVerifyMessageHash(¶, hashContent, sizeof(hashContent),
|
||||
buf, &size, NULL, NULL);
|
||||
ok(ret, "CryptVerifyMessageHash failed: %08x\n", GetLastError());
|
||||
ok(size == sizeof(msgData), "unexpected size %d\n", size);
|
||||
ok(!memcmp(buf, msgData, size), "unexpected value\n");
|
||||
CryptMemFree(buf);
|
||||
}
|
||||
}
|
||||
|
||||
static const BYTE signedWithCertContent[] = {
|
||||
0x30,0x82,0x01,0x32,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
|
||||
0xa0,0x82,0x01,0x23,0x30,0x82,0x01,0x1f,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,
|
||||
0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,
|
||||
0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,
|
||||
0x02,0x03,0x04,0xa0,0x7c,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,0x31,0x77,0x30,0x75,0x02,0x01,
|
||||
0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,
|
||||
0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,
|
||||
0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,
|
||||
0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,
|
||||
0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,
|
||||
0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,
|
||||
0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,
|
||||
0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
|
||||
static const BYTE signedContent[] = {
|
||||
0x30,0x81,0xb2,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
|
||||
0x81,0xa4,0x30,0x81,0xa1,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
|
||||
0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,
|
||||
0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,0x02,0x03,0x04,
|
||||
0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,
|
||||
0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
|
||||
0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
|
||||
0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x81,0xa6,0x70,
|
||||
0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,
|
||||
0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,
|
||||
0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,
|
||||
0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,
|
||||
0x0d };
|
||||
static const BYTE detachedSignedContent[] = {
|
||||
0x30,0x81,0xaa,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
|
||||
0x81,0x9c,0x30,0x81,0x99,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
|
||||
0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,
|
||||
0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,
|
||||
0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
|
||||
0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,
|
||||
0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,
|
||||
0x05,0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,
|
||||
0x9a,0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,
|
||||
0x1e,0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,
|
||||
0x64,0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,
|
||||
0xe4,0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
|
||||
static const BYTE v1CertWithValidPubKey[] = {
|
||||
0x30,0x81,0xcf,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,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
|
||||
0x01,0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,
|
||||
0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,
|
||||
0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,
|
||||
0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,
|
||||
0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,
|
||||
0x79,0x02,0x03,0x01,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 PCCERT_CONTEXT WINAPI msg_get_signer_callback(void *pvArg,
|
||||
DWORD certEncodingType, PCERT_INFO signerId, HCERTSTORE store)
|
||||
{
|
||||
return CertCreateCertificateContext(X509_ASN_ENCODING,
|
||||
v1CertWithValidPubKey, sizeof(v1CertWithValidPubKey));
|
||||
}
|
||||
|
||||
static void test_verify_detached_message_signature(void)
|
||||
{
|
||||
CRYPT_VERIFY_MESSAGE_PARA para;
|
||||
BOOL ret;
|
||||
const BYTE *pContent;
|
||||
DWORD cbContent;
|
||||
|
||||
memset(¶, 0, sizeof(para));
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptVerifyDetachedMessageSignature(NULL, 0, NULL, 0, 0, NULL,
|
||||
NULL, NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptVerifyDetachedMessageSignature(¶, 0, NULL, 0, 0, NULL,
|
||||
NULL, NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
para.cbSize = sizeof(para);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptVerifyDetachedMessageSignature(¶, 0, NULL, 0, 0, NULL,
|
||||
NULL, NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
para.dwMsgAndCertEncodingType = X509_ASN_ENCODING;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptVerifyDetachedMessageSignature(¶, 0, NULL, 0, 0, NULL,
|
||||
NULL, NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
para.dwMsgAndCertEncodingType = PKCS_7_ASN_ENCODING;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptVerifyDetachedMessageSignature(¶, 0, NULL, 0, 0, NULL,
|
||||
NULL, NULL);
|
||||
ok(!ret, "Expected 0, got %d\n", ret);
|
||||
ok(GetLastError() == CRYPT_E_ASN1_EOD ||
|
||||
GetLastError() == OSS_BAD_ARG, /* win98 */
|
||||
"Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
|
||||
/* None of these messages contains a cert in the message itself, so the
|
||||
* default callback isn't able to verify their signature.
|
||||
*/
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptVerifyDetachedMessageSignature(¶, 0, signedWithCertContent,
|
||||
sizeof(signedWithCertContent), 0, NULL, NULL, NULL);
|
||||
ok(!ret, "Expected 0, got %d\n", ret);
|
||||
todo_wine
|
||||
ok(GetLastError() == CRYPT_E_NOT_FOUND ||
|
||||
GetLastError() == OSS_DATA_ERROR, /* win98 */
|
||||
"Expected CRYPT_E_NOT_FOUND or OSS_DATA_ERROR, got %08x\n", GetLastError());
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptVerifyDetachedMessageSignature(¶, 0, signedContent,
|
||||
sizeof(signedContent), 0, NULL, NULL, NULL);
|
||||
ok(!ret, "Expected 0, got %d\n", ret);
|
||||
ok(GetLastError() == CRYPT_E_NOT_FOUND ||
|
||||
GetLastError() == OSS_DATA_ERROR, /* win98 */
|
||||
"Expected CRYPT_E_NOT_FOUND or OSS_DATA_ERROR, got %08x\n", GetLastError());
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptVerifyDetachedMessageSignature(¶, 0, detachedSignedContent,
|
||||
sizeof(detachedSignedContent), 0, NULL, NULL, NULL);
|
||||
ok(!ret, "Expected 0, got %d\n", ret);
|
||||
ok(GetLastError() == CRYPT_E_NOT_FOUND ||
|
||||
GetLastError() == OSS_DATA_ERROR, /* win98 */
|
||||
"Expected CRYPT_E_NOT_FOUND or OSS_DATA_ERROR, got %08x\n", GetLastError());
|
||||
SetLastError(0xdeadbeef);
|
||||
pContent = msgData;
|
||||
cbContent = sizeof(msgData);
|
||||
ret = CryptVerifyDetachedMessageSignature(¶, 0, detachedSignedContent,
|
||||
sizeof(detachedSignedContent), 1, &pContent, &cbContent, NULL);
|
||||
ok(!ret, "Expected 0, got %d\n", ret);
|
||||
ok(GetLastError() == CRYPT_E_NOT_FOUND ||
|
||||
GetLastError() == OSS_DATA_ERROR, /* win98 */
|
||||
"Expected CRYPT_E_NOT_FOUND or OSS_DATA_ERROR, got %08x\n", GetLastError());
|
||||
/* Passing the correct callback results in success */
|
||||
para.pfnGetSignerCertificate = msg_get_signer_callback;
|
||||
ret = CryptVerifyDetachedMessageSignature(¶, 0, detachedSignedContent,
|
||||
sizeof(detachedSignedContent), 1, &pContent, &cbContent, NULL);
|
||||
ok(ret ||
|
||||
broken(!ret), /* win98 */
|
||||
"CryptVerifyDetachedMessageSignature failed: %08x\n",
|
||||
GetLastError());
|
||||
/* Not passing the correct data to be signed results in the signature not
|
||||
* matching.
|
||||
*/
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptVerifyDetachedMessageSignature(¶, 0, detachedSignedContent,
|
||||
sizeof(detachedSignedContent), 0, NULL, NULL, NULL);
|
||||
ok(!ret, "Expected 0, got %d\n", ret);
|
||||
ok(GetLastError() == NTE_BAD_SIGNATURE ||
|
||||
GetLastError() == OSS_DATA_ERROR, /* win98 */
|
||||
"Expected NTE_BAD_SIGNATURE or OSS_DATA_ERROR, got %08x\n", GetLastError());
|
||||
}
|
||||
|
||||
static const BYTE signedWithCertEmptyContent[] = {
|
||||
0x30,0x81,0xdf,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
|
||||
0x81,0xd1,0x30,0x81,0xce,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
|
||||
0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0xa0,0x7c,
|
||||
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,0x31,0x37,0x30,0x35,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,
|
||||
0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
|
||||
0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,
|
||||
0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
|
||||
0x00 };
|
||||
static const BYTE signedWithCertWithPubKeyContent[] = {
|
||||
0x30,0x81,0xfc,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
|
||||
0x81,0xee,0x30,0x81,0xeb,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
|
||||
0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x02,0x06,0x00,0xa0,0x81,
|
||||
0x98,0x30,0x81,0x95,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,0xa3,0x16,0x30,0x14,0x30,0x12,
|
||||
0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,
|
||||
0x02,0x01,0x01,0x31,0x37,0x30,0x35,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
|
||||
0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
|
||||
0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
|
||||
0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
|
||||
|
||||
static void test_verify_message_signature(void)
|
||||
{
|
||||
BOOL ret;
|
||||
CRYPT_VERIFY_MESSAGE_PARA para = { 0 };
|
||||
PCCERT_CONTEXT cert;
|
||||
DWORD cbDecoded;
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptVerifyMessageSignature(NULL, 0, NULL, 0, NULL, 0, NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptVerifyMessageSignature(¶, 0, NULL, 0, NULL, 0, NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
para.cbSize = sizeof(para);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptVerifyMessageSignature(¶, 0, NULL, 0, NULL, 0, NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
para.cbSize = 0;
|
||||
para.dwMsgAndCertEncodingType = PKCS_7_ASN_ENCODING;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptVerifyMessageSignature(¶, 0, NULL, 0, NULL, 0, NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
para.cbSize = sizeof(para);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptVerifyMessageSignature(¶, 0, NULL, 0, NULL, 0, NULL);
|
||||
ok(!ret &&
|
||||
(GetLastError() == CRYPT_E_ASN1_EOD ||
|
||||
GetLastError() == OSS_BAD_ARG), /* win9x */
|
||||
"Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
|
||||
/* Check whether cert is set on error */
|
||||
cert = (PCCERT_CONTEXT)0xdeadbeef;
|
||||
ret = CryptVerifyMessageSignature(¶, 0, NULL, 0, NULL, 0, &cert);
|
||||
ok(cert == NULL, "Expected NULL cert\n");
|
||||
/* Check whether cbDecoded is set on error */
|
||||
cbDecoded = 0xdeadbeef;
|
||||
ret = CryptVerifyMessageSignature(¶, 0, NULL, 0, NULL, &cbDecoded,
|
||||
NULL);
|
||||
ok(!cbDecoded, "Expected 0\n");
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptVerifyMessageSignature(¶, 0, dataEmptyBareContent,
|
||||
sizeof(dataEmptyBareContent), NULL, 0, NULL);
|
||||
ok(GetLastError() == CRYPT_E_ASN1_BADTAG ||
|
||||
GetLastError() == OSS_PDU_MISMATCH, /* win9x */
|
||||
"Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptVerifyMessageSignature(¶, 0, dataEmptyContent,
|
||||
sizeof(dataEmptyContent), NULL, 0, NULL);
|
||||
ok(!ret && GetLastError() == CRYPT_E_UNEXPECTED_MSG_TYPE,
|
||||
"Expected CRYPT_E_UNEXPECTED_MSG_TYPE, got %08x\n", GetLastError());
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptVerifyMessageSignature(¶, 0, signedEmptyBareContent,
|
||||
sizeof(signedEmptyBareContent), NULL, 0, NULL);
|
||||
ok(!ret &&
|
||||
(GetLastError() == CRYPT_E_ASN1_BADTAG ||
|
||||
GetLastError() == OSS_DATA_ERROR), /* win9x */
|
||||
"Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptVerifyMessageSignature(¶, 0, signedEmptyContent,
|
||||
sizeof(signedEmptyContent), NULL, 0, NULL);
|
||||
ok(!ret &&
|
||||
(GetLastError() == CRYPT_E_NOT_FOUND ||
|
||||
GetLastError() == OSS_DATA_ERROR), /* win9x */
|
||||
"Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptVerifyMessageSignature(¶, 0, signedContent,
|
||||
sizeof(signedContent), NULL, 0, NULL);
|
||||
ok(!ret &&
|
||||
(GetLastError() == CRYPT_E_NOT_FOUND ||
|
||||
GetLastError() == OSS_DATA_ERROR), /* win9x */
|
||||
"Expected CRYPT_E_NOT_FOUND, got %08x\n", GetLastError());
|
||||
/* FIXME: Windows fails with CRYPT_E_NOT_FOUND for these messages, but
|
||||
* their signer certs have invalid public keys that fail to decode. In
|
||||
* Wine therefore the failure is an ASN error. Need some messages with
|
||||
* valid public keys and invalid signatures to check against.
|
||||
*/
|
||||
ret = CryptVerifyMessageSignature(¶, 0, signedWithCertEmptyContent,
|
||||
sizeof(signedWithCertEmptyContent), NULL, 0, NULL);
|
||||
ok(!ret, "Expected failure\n");
|
||||
ret = CryptVerifyMessageSignature(¶, 0, signedWithCertContent,
|
||||
sizeof(signedWithCertContent), NULL, 0, NULL);
|
||||
ok(!ret, "Expected failure\n");
|
||||
ret = CryptVerifyMessageSignature(¶, 0, signedWithCertWithPubKeyContent,
|
||||
sizeof(signedWithCertWithPubKeyContent), NULL, 0, NULL);
|
||||
ok(!ret, "Expected failure\n");
|
||||
}
|
||||
|
||||
static const BYTE detachedHashBlob[] = {
|
||||
0x30,0x3f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x32,
|
||||
0x30,0x30,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
|
||||
0x02,0x05,0x05,0x00,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
|
||||
0x07,0x01,0x04,0x10,0x2d,0x1b,0xbc,0x1f,0xc7,0xab,0x36,0x8d,0xdb,0x95,0xe6,
|
||||
0x24,0xb9,0x66,0x7c,0x21 };
|
||||
static const BYTE hashBlob[] = {
|
||||
0x30,0x47,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x05,0xa0,0x3a,
|
||||
0x30,0x38,0x02,0x01,0x00,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,
|
||||
0x02,0x05,0x05,0x00,0x30,0x13,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
|
||||
0x07,0x01,0xa0,0x06,0x04,0x04,0xde,0xad,0xbe,0xef,0x04,0x10,0x2f,0x24,0x92,
|
||||
0x30,0xa8,0xe7,0xc2,0xbf,0x60,0x05,0xcc,0xd2,0x67,0x92,0x59,0xec };
|
||||
static const BYTE hashVal[] = {
|
||||
0x2d,0x1b,0xbc,0x1f,0xc7,0xab,0x36,0x8d,0xdb,0x95,0xe6,0x24,0xb9,0x66,0x7c,
|
||||
0x21 };
|
||||
|
||||
static void test_hash_message(void)
|
||||
{
|
||||
BOOL ret;
|
||||
CRYPT_HASH_MESSAGE_PARA para;
|
||||
static const BYTE blob1[] = { 0xde, 0xad, 0xbe, 0xef };
|
||||
static const BYTE blob2[] = { 0xba, 0xad, 0xf0, 0x0d };
|
||||
const BYTE *toHash[] = { blob1, blob2 };
|
||||
DWORD hashSize[] = { sizeof(blob1), sizeof(blob2) };
|
||||
DWORD hashedBlobSize, computedHashSize;
|
||||
static char oid_rsa_md5[] = szOID_RSA_MD5;
|
||||
LPBYTE hashedBlob, computedHash;
|
||||
|
||||
/* Crash
|
||||
ret = CryptHashMessage(NULL, FALSE, 0, NULL, 0, NULL, NULL, NULL, NULL);
|
||||
*/
|
||||
memset(¶, 0, sizeof(para));
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptHashMessage(¶, FALSE, 0, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"expected E_INVALIDARG, got 0x%08x\n", GetLastError());
|
||||
para.cbSize = sizeof(para);
|
||||
/* Not quite sure what "success" means in this case, but it does succeed */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptHashMessage(¶, FALSE, 0, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
|
||||
/* With a bogus encoding type it "succeeds" */
|
||||
para.dwMsgEncodingType = 0xdeadbeef;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptHashMessage(¶, FALSE, 0, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
|
||||
/* According to MSDN, the third parameter (cToBeHashed) must be 1 if the
|
||||
* second parameter (fDetached) is FALSE, but again it "succeeds."
|
||||
*/
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptHashMessage(¶, FALSE, 2, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
|
||||
/* Even passing parameters to hash results in "success." */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptHashMessage(¶, FALSE, 2, toHash, hashSize, NULL, NULL, NULL,
|
||||
NULL);
|
||||
/* Try again with a valid encoding type */
|
||||
para.dwMsgEncodingType = PKCS_7_ASN_ENCODING;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptHashMessage(¶, FALSE, 2, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
|
||||
/* And with valid data to hash */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptHashMessage(¶, FALSE, 2, toHash, hashSize, NULL, NULL, NULL,
|
||||
NULL);
|
||||
ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
|
||||
/* But requesting the size of the hashed blob and indicating there's data
|
||||
* to hash results in a crash
|
||||
*/
|
||||
if (0)
|
||||
{
|
||||
ret = CryptHashMessage(¶, FALSE, 2, NULL, NULL, NULL,
|
||||
&hashedBlobSize, NULL, NULL);
|
||||
}
|
||||
/* Passing a valid pointer for the data to hash fails, as the hash
|
||||
* algorithm is finally checked.
|
||||
*/
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptHashMessage(¶, FALSE, 2, toHash, hashSize, NULL,
|
||||
&hashedBlobSize, NULL, NULL);
|
||||
ok(!ret &&
|
||||
(GetLastError() == CRYPT_E_UNKNOWN_ALGO ||
|
||||
GetLastError() == CRYPT_E_OID_FORMAT), /* Vista */
|
||||
"expected CRYPT_E_UNKNOWN_ALGO or CRYPT_E_OID_FORMAT, got 0x%08x (%d)\n",
|
||||
GetLastError(), GetLastError());
|
||||
para.HashAlgorithm.pszObjId = oid_rsa_md5;
|
||||
/* With a valid hash algorithm, this succeeds, even though fDetached is
|
||||
* FALSE.
|
||||
*/
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptHashMessage(¶, FALSE, 2, toHash, hashSize, NULL,
|
||||
&hashedBlobSize, NULL, NULL);
|
||||
todo_wine
|
||||
ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
|
||||
if (ret)
|
||||
{
|
||||
/* Actually attempting to get the hashed data fails, perhaps because
|
||||
* detached is FALSE.
|
||||
*/
|
||||
hashedBlob = HeapAlloc(GetProcessHeap(), 0, hashedBlobSize);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptHashMessage(¶, FALSE, 2, toHash, hashSize, hashedBlob,
|
||||
&hashedBlobSize, NULL, NULL);
|
||||
ok(!ret && GetLastError() == CRYPT_E_MSG_ERROR,
|
||||
"expected CRYPT_E_MSG_ERROR, got 0x%08x (%d)\n", GetLastError(),
|
||||
GetLastError());
|
||||
HeapFree(GetProcessHeap(), 0, hashedBlob);
|
||||
}
|
||||
/* Repeating tests with fDetached = TRUE results in success */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptHashMessage(¶, TRUE, 2, toHash, hashSize, NULL,
|
||||
&hashedBlobSize, NULL, NULL);
|
||||
ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
|
||||
if (ret)
|
||||
{
|
||||
hashedBlob = HeapAlloc(GetProcessHeap(), 0, hashedBlobSize);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptHashMessage(¶, TRUE, 2, toHash, hashSize, hashedBlob,
|
||||
&hashedBlobSize, NULL, NULL);
|
||||
ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
|
||||
ok(hashedBlobSize == sizeof(detachedHashBlob),
|
||||
"unexpected size of detached blob %d\n", hashedBlobSize);
|
||||
ok(!memcmp(hashedBlob, detachedHashBlob, hashedBlobSize),
|
||||
"unexpected detached blob value\n");
|
||||
HeapFree(GetProcessHeap(), 0, hashedBlob);
|
||||
}
|
||||
/* Hashing a single item with fDetached = FALSE also succeeds */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptHashMessage(¶, FALSE, 1, toHash, hashSize, NULL,
|
||||
&hashedBlobSize, NULL, NULL);
|
||||
ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
|
||||
if (ret)
|
||||
{
|
||||
hashedBlob = HeapAlloc(GetProcessHeap(), 0, hashedBlobSize);
|
||||
ret = CryptHashMessage(¶, FALSE, 1, toHash, hashSize, hashedBlob,
|
||||
&hashedBlobSize, NULL, NULL);
|
||||
ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
|
||||
ok(hashedBlobSize == sizeof(hashBlob),
|
||||
"unexpected size of detached blob %d\n", hashedBlobSize);
|
||||
ok(!memcmp(hashedBlob, hashBlob, hashedBlobSize),
|
||||
"unexpected detached blob value\n");
|
||||
HeapFree(GetProcessHeap(), 0, hashedBlob);
|
||||
}
|
||||
/* Check the computed hash value too. You don't need to get the encoded
|
||||
* blob to get it.
|
||||
*/
|
||||
computedHashSize = 0xdeadbeef;
|
||||
ret = CryptHashMessage(¶, TRUE, 2, toHash, hashSize, NULL,
|
||||
&hashedBlobSize, NULL, &computedHashSize);
|
||||
ok(ret, "CryptHashMessage failed: 0x%08x\n", GetLastError());
|
||||
ok(computedHashSize == 16, "expected hash size of 16, got %d\n",
|
||||
computedHashSize);
|
||||
if (ret)
|
||||
{
|
||||
computedHash = HeapAlloc(GetProcessHeap(), 0, computedHashSize);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptHashMessage(¶, TRUE, 2, toHash, hashSize, NULL,
|
||||
&hashedBlobSize, computedHash, &computedHashSize);
|
||||
ok(computedHashSize == sizeof(hashVal),
|
||||
"unexpected size of hash value %d\n", computedHashSize);
|
||||
ok(!memcmp(computedHash, hashVal, computedHashSize),
|
||||
"unexpected value\n");
|
||||
HeapFree(GetProcessHeap(), 0, computedHash);
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST(message)
|
||||
{
|
||||
test_msg_get_signer_count();
|
||||
test_verify_detached_message_hash();
|
||||
test_verify_message_hash();
|
||||
test_verify_detached_message_signature();
|
||||
test_verify_message_signature();
|
||||
test_hash_message();
|
||||
}
|
3060
rostests/winetests/crypt32/msg.c
Normal file
3060
rostests/winetests/crypt32/msg.c
Normal file
File diff suppressed because it is too large
Load diff
222
rostests/winetests/crypt32/object.c
Normal file
222
rostests/winetests/crypt32/object.c
Normal file
|
@ -0,0 +1,222 @@
|
|||
/*
|
||||
* Unit test suite for crypt32.dll's Crypt*Object functions
|
||||
*
|
||||
* Copyright 2008 Juan Lang
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#include <winerror.h>
|
||||
#include <wincrypt.h>
|
||||
|
||||
#include "wine/test.h"
|
||||
|
||||
static BYTE bigCert[] = {
|
||||
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 };
|
||||
static char bigCertBase64[] =
|
||||
"MHoCAQEwAgYAMBUxEzARBgNVBAMTCkp1YW4gTGFuZwAwIhgPMTYwMTAxMDEwMDAw\n"
|
||||
"MDBaGA8xNjAxMDEwMTAwMDAwMFowFTETMBEGA1UEAxMKSnVhbiBMYW5nADAHMAIG\n"
|
||||
"AAMBAKMWMBQwEgYDVR0TAQH/BAgwBgEB/wIBAQ==\n";
|
||||
static WCHAR bigCertBase64W[] = {
|
||||
'M','H','o','C','A','Q','E','w','A','g','Y','A','M','B','U','x','E','z','A',
|
||||
'R','B','g','N','V','B','A','M','T','C','k','p','1','Y','W','4','g','T','G',
|
||||
'F','u','Z','w','A','w','I','h','g','P','M','T','Y','w','M','T','A','x','M',
|
||||
'D','E','w',',','D','A','w','\n',
|
||||
'M','D','B','a','G','A','8','x','N','j','A','x','M','D','E','w','M','T','A',
|
||||
'w','M','D','A','w','M','F','o','w','F','T','E','T','M','B','E','G','A','1',
|
||||
'U','E','A','x','M','K','S','n','V','h','b','i','B','M','Y','W','5','n','A',
|
||||
'D','A','H','M','A','I','G','\n',
|
||||
'A','A','M','B','A','K','M','W','M','B','Q','w','E','g','Y','D','V','R','0',
|
||||
'T','A','Q','H','/','B','A','g','w','B','g','E','B','/','w','I','B','A','Q',
|
||||
'=','=','\n',0 };
|
||||
static BYTE signedWithCertWithValidPubKeyContent[] = {
|
||||
0x30,0x82,0x01,0x89,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
|
||||
0xa0,0x82,0x01,0x7a,0x30,0x82,0x01,0x76,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,
|
||||
0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06,
|
||||
0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01,
|
||||
0x02,0x03,0x04,0xa0,0x81,0xd2,0x30,0x81,0xcf,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,0x5c,0x30,0x0d,0x06,0x09,0x2a,
|
||||
0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,
|
||||
0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,
|
||||
0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,
|
||||
0x65,0x97,0x03,0x86,0x60,0xde,0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,
|
||||
0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,
|
||||
0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,0x02,0x03,0x01,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,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
|
||||
0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
|
||||
0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
|
||||
0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
|
||||
0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a,
|
||||
0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e,
|
||||
0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64,
|
||||
0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4,
|
||||
0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d };
|
||||
static char signedWithCertWithValidPubKeyContentBase64[] =
|
||||
"MIIBiQYJKoZIhvcNAQcCoIIBejCCAXYCAQExDjAMBggqhkiG9w0CBQUAMBMGCSqG"
|
||||
"SIb3DQEHAaAGBAQBAgMEoIHSMIHPAgEBMAIGADAVMRMwEQYDVQQDEwpKdWFuIExh"
|
||||
"bmcAMCIYDzE2MDEwMTAxMDAwMDAwWhgPMTYwMTAxMDEwMDAwMDBaMBUxEzARBgNV"
|
||||
"BAMTCkp1YW4gTGFuZwAwXDANBgkqhkiG9w0BAQEFAANLADBIAkEA4lQ6p4OxJxQ+"
|
||||
"Wbu0U+Yf513xIWithVPbax7rZZcDhmDe82w4deBMYbu8YhepzXk/IU6Wyw7cYZQw"
|
||||
"GBBr0BwQeQIDAQABoxYwFDASBgNVHRMBAf8ECDAGAQH/AgEBMXcwdQIBATAaMBUx"
|
||||
"EzARBgNVBAMTCkp1YW4gTGFuZwACAQEwDAYIKoZIhvcNAgUFADAEBgAFAARAgaZw"
|
||||
"s+9Z0WbRm8CatppebW9tDVmpqm7pLKAe7sJgvFm+P2MGjckRHSNkku8u/FcppK/g"
|
||||
"7pMZOVHkRLgLKPSoDQ==";
|
||||
static WCHAR signedWithCertWithValidPubKeyContentBase64W[] = {
|
||||
'M','I','I','B','i','Q','Y','J','K','o','Z','I','h','v','c','N','A','Q','c','C',
|
||||
'o','I','I','B','e','j','C','C','A','X','Y','C','A','Q','E','x','D','j','A','M',
|
||||
'B','g','g','q','h','k','i','G','9','w','0','C','B','Q','U','A','M','B','M','G',
|
||||
'C','S','q','G','S','I','b','3','D','Q','E','H','A','a','A','G','B','A','Q','B',
|
||||
'A','g','M','E','o','I','H','S','M','I','H','P','A','g','E','B','M','A','I','G',
|
||||
'A','D','A','V','M','R','M','w','E','Q','Y','D','V','Q','Q','D','E','w','p','K',
|
||||
'd','W','F','u','I','E','x','h','b','m','c','A','M','C','I','Y','D','z','E','2',
|
||||
'M','D','E','w','M','T','A','x','M','D','A','w','M','D','A','w','W','h','g','P',
|
||||
'M','T','Y','w','M','T','A','x','M','D','E','w','M','D','A','w','M','D','B','a',
|
||||
'M','B','U','x','E','z','A','R','B','g','N','V','B','A','M','T','C','k','p','1',
|
||||
'Y','W','4','g','T','G','F','u','Z','w','A','w','X','D','A','N','B','g','k','q',
|
||||
'h','k','i','G','9','w','0','B','A','Q','E','F','A','A','N','L','A','D','B','I',
|
||||
'A','k','E','A','4','l','Q','6','p','4','O','x','J','x','Q','+','W','b','u','0',
|
||||
'U','+','Y','f','5','1','3','x','I','W','i','t','h','V','P','b','a','x','7','r',
|
||||
'Z','Z','c','D','h','m','D','e','8','2','w','4','d','e','B','M','Y','b','u','8',
|
||||
'Y','h','e','p','z','X','k','/','I','U','6','W','y','w','7','c','Y','Z','Q','w',
|
||||
'G','B','B','r','0','B','w','Q','e','Q','I','D','A','Q','A','B','o','x','Y','w',
|
||||
'F','D','A','S','B','g','N','V','H','R','M','B','A','f','8','E','C','D','A','G',
|
||||
'A','Q','H','/','A','g','E','B','M','X','c','w','d','Q','I','B','A','T','A','a',
|
||||
'M','B','U','x','E','z','A','R','B','g','N','V','B','A','M','T','C','k','p','1',
|
||||
'Y','W','4','g','T','G','F','u','Z','w','A','C','A','Q','E','w','D','A','Y','I',
|
||||
'K','o','Z','I','h','v','c','N','A','g','U','F','A','D','A','E','B','g','A','F',
|
||||
'A','A','R','A','g','a','Z','w','s','+','9','Z','0','W','b','R','m','8','C','a',
|
||||
't','p','p','e','b','W','9','t','D','V','m','p','q','m','7','p','L','K','A','e',
|
||||
'7','s','J','g','v','F','m','+','P','2','M','G','j','c','k','R','H','S','N','k',
|
||||
'k','u','8','u','/','F','c','p','p','K','/','g','7','p','M','Z','O','V','H','k',
|
||||
'R','L','g','L','K','P','S','o','D','Q','=','=',0 };
|
||||
|
||||
static void test_query_object(void)
|
||||
{
|
||||
BOOL ret;
|
||||
CRYPT_DATA_BLOB blob;
|
||||
|
||||
/* Test the usual invalid arguments */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptQueryObject(0, NULL, 0, 0, 0, NULL, NULL, NULL, NULL, NULL,
|
||||
NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptQueryObject(CERT_QUERY_OBJECT_BLOB, NULL, 0, 0, 0, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
/* Test with a simple cert */
|
||||
blob.pbData = bigCert;
|
||||
blob.cbData = sizeof(bigCert);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob,
|
||||
CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_ALL, 0, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL);
|
||||
ok(ret, "CryptQueryObject failed: %08x\n", GetLastError());
|
||||
/* The same cert, base64-encoded */
|
||||
blob.pbData = (BYTE *)bigCertBase64;
|
||||
blob.cbData = sizeof(bigCertBase64);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob,
|
||||
CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_ALL, 0, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL);
|
||||
ok(ret, "CryptQueryObject failed: %08x\n", GetLastError());
|
||||
/* The same base64-encoded cert, restricting the format types */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob,
|
||||
CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_BINARY, 0, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL);
|
||||
ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
|
||||
"expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob,
|
||||
CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED, 0,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
ok(ret, "CryptQueryObject failed: %08x\n", GetLastError());
|
||||
/* The same cert, base64-encoded but as a wide character string */
|
||||
blob.pbData = (BYTE *)bigCertBase64W;
|
||||
blob.cbData = sizeof(bigCertBase64W);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob,
|
||||
CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_ALL, 0, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL);
|
||||
ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
|
||||
"expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
|
||||
/* For brevity, not tested here, but tested on Windows: same failure
|
||||
* (CRYPT_E_NO_MATCH) when the wide character base64-encoded cert
|
||||
* is written to a file and queried.
|
||||
*/
|
||||
/* Test with a valid signed message */
|
||||
blob.pbData = signedWithCertWithValidPubKeyContent;
|
||||
blob.cbData = sizeof(signedWithCertWithValidPubKeyContent);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob,
|
||||
CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_ALL, 0, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL);
|
||||
ok(ret, "CryptQueryObject failed: %08x\n", GetLastError());
|
||||
blob.pbData = (BYTE *)signedWithCertWithValidPubKeyContentBase64;
|
||||
blob.cbData = sizeof(signedWithCertWithValidPubKeyContentBase64);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob,
|
||||
CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_ALL, 0, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL);
|
||||
ok(ret, "CryptQueryObject failed: %08x\n", GetLastError());
|
||||
/* A valid signed message, encoded as a wide character base64 string, can
|
||||
* be queried successfully.
|
||||
*/
|
||||
blob.pbData = (BYTE *)signedWithCertWithValidPubKeyContentBase64W;
|
||||
blob.cbData = sizeof(signedWithCertWithValidPubKeyContentBase64W);
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob,
|
||||
CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_ALL, 0, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL);
|
||||
ok(ret, "CryptQueryObject failed: %08x\n", GetLastError());
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob,
|
||||
CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_BINARY, 0, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL);
|
||||
ok(!ret && GetLastError() == CRYPT_E_NO_MATCH,
|
||||
"expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError());
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob,
|
||||
CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED, 0,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
ok(ret, "CryptQueryObject failed: %08x\n", GetLastError());
|
||||
}
|
||||
|
||||
START_TEST(object)
|
||||
{
|
||||
test_query_object();
|
||||
}
|
590
rostests/winetests/crypt32/oid.c
Normal file
590
rostests/winetests/crypt32/oid.c
Normal file
|
@ -0,0 +1,590 @@
|
|||
/*
|
||||
* Unit test suite for crypt32.dll's OID support functions.
|
||||
*
|
||||
* Copyright 2005 Juan Lang
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#include <winerror.h>
|
||||
#include <wincrypt.h>
|
||||
#include <winreg.h>
|
||||
|
||||
#include "wine/test.h"
|
||||
|
||||
|
||||
static BOOL (WINAPI *pCryptEnumOIDInfo)(DWORD,DWORD,void*,PFN_CRYPT_ENUM_OID_INFO);
|
||||
|
||||
|
||||
struct OIDToAlgID
|
||||
{
|
||||
LPCSTR oid;
|
||||
DWORD algID;
|
||||
};
|
||||
|
||||
static const struct OIDToAlgID oidToAlgID[] = {
|
||||
{ szOID_RSA_RSA, CALG_RSA_KEYX },
|
||||
{ szOID_RSA_MD2RSA, CALG_MD2 },
|
||||
{ szOID_RSA_MD4RSA, CALG_MD4 },
|
||||
{ szOID_RSA_MD5RSA, CALG_MD5 },
|
||||
{ szOID_RSA_SHA1RSA, CALG_SHA },
|
||||
{ szOID_RSA_DH, CALG_DH_SF },
|
||||
{ szOID_RSA_SMIMEalgESDH, CALG_DH_EPHEM },
|
||||
{ szOID_RSA_SMIMEalgCMS3DESwrap, CALG_3DES },
|
||||
{ szOID_RSA_SMIMEalgCMSRC2wrap, CALG_RC2 },
|
||||
{ szOID_RSA_MD2, CALG_MD2 },
|
||||
{ szOID_RSA_MD4, CALG_MD4 },
|
||||
{ szOID_RSA_MD5, CALG_MD5 },
|
||||
{ szOID_RSA_RC2CBC, CALG_RC2 },
|
||||
{ szOID_RSA_RC4, CALG_RC4 },
|
||||
{ szOID_RSA_DES_EDE3_CBC, CALG_3DES },
|
||||
{ szOID_ANSI_X942_DH, CALG_DH_SF },
|
||||
{ szOID_X957_DSA, CALG_DSS_SIGN },
|
||||
{ szOID_X957_SHA1DSA, CALG_SHA },
|
||||
{ szOID_OIWSEC_md4RSA, CALG_MD4 },
|
||||
{ szOID_OIWSEC_md5RSA, CALG_MD5 },
|
||||
{ szOID_OIWSEC_md4RSA2, CALG_MD4 },
|
||||
{ szOID_OIWSEC_desCBC, CALG_DES },
|
||||
{ szOID_OIWSEC_dsa, CALG_DSS_SIGN },
|
||||
{ szOID_OIWSEC_shaDSA, CALG_SHA },
|
||||
{ szOID_OIWSEC_shaRSA, CALG_SHA },
|
||||
{ szOID_OIWSEC_sha, CALG_SHA },
|
||||
{ szOID_OIWSEC_rsaXchg, CALG_RSA_KEYX },
|
||||
{ szOID_OIWSEC_sha1, CALG_SHA },
|
||||
{ szOID_OIWSEC_dsaSHA1, CALG_SHA },
|
||||
{ szOID_OIWSEC_sha1RSASign, CALG_SHA },
|
||||
{ szOID_OIWDIR_md2RSA, CALG_MD2 },
|
||||
{ szOID_INFOSEC_mosaicUpdatedSig, CALG_SHA },
|
||||
{ szOID_INFOSEC_mosaicKMandUpdSig, CALG_DSS_SIGN },
|
||||
};
|
||||
|
||||
static const struct OIDToAlgID algIDToOID[] = {
|
||||
{ szOID_RSA_RSA, CALG_RSA_KEYX },
|
||||
{ szOID_RSA_SMIMEalgESDH, CALG_DH_EPHEM },
|
||||
{ szOID_RSA_MD2, CALG_MD2 },
|
||||
{ szOID_RSA_MD4, CALG_MD4 },
|
||||
{ szOID_RSA_MD5, CALG_MD5 },
|
||||
{ szOID_RSA_RC2CBC, CALG_RC2 },
|
||||
{ szOID_RSA_RC4, CALG_RC4 },
|
||||
{ szOID_RSA_DES_EDE3_CBC, CALG_3DES },
|
||||
{ szOID_ANSI_X942_DH, CALG_DH_SF },
|
||||
{ szOID_X957_DSA, CALG_DSS_SIGN },
|
||||
{ szOID_OIWSEC_desCBC, CALG_DES },
|
||||
{ szOID_OIWSEC_sha1, CALG_SHA },
|
||||
};
|
||||
|
||||
static const WCHAR bogusDll[] = { 'b','o','g','u','s','.','d','l','l',0 };
|
||||
static const WCHAR bogus2Dll[] = { 'b','o','g','u','s','2','.','d','l','l',0 };
|
||||
|
||||
static void testOIDToAlgID(void)
|
||||
{
|
||||
int i;
|
||||
DWORD alg;
|
||||
|
||||
/* Test with a bogus one */
|
||||
SetLastError(0xdeadbeef);
|
||||
alg = CertOIDToAlgId("1.2.3");
|
||||
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++)
|
||||
{
|
||||
alg = CertOIDToAlgId(oidToAlgID[i].oid);
|
||||
/* Not all Windows installations support all these, so make sure it's
|
||||
* at least not the wrong one.
|
||||
*/
|
||||
ok(alg == 0 || alg == oidToAlgID[i].algID,
|
||||
"Expected %d, got %d\n", oidToAlgID[i].algID, alg);
|
||||
}
|
||||
}
|
||||
|
||||
static void testAlgIDToOID(void)
|
||||
{
|
||||
int i;
|
||||
LPCSTR oid;
|
||||
|
||||
/* Test with a bogus one */
|
||||
SetLastError(0xdeadbeef);
|
||||
oid = CertAlgIdToOID(ALG_CLASS_SIGNATURE | ALG_TYPE_ANY | 80);
|
||||
ok(!oid && GetLastError() == 0xdeadbeef,
|
||||
"Didn't expect last error (%08x) to be set\n", GetLastError());
|
||||
for (i = 0; i < sizeof(algIDToOID) / sizeof(algIDToOID[0]); i++)
|
||||
{
|
||||
oid = CertAlgIdToOID(algIDToOID[i].algID);
|
||||
/* Allow failure, not every version of Windows supports every algo */
|
||||
if (oid)
|
||||
ok(!strcmp(oid, algIDToOID[i].oid),
|
||||
"Expected %s, got %s\n", algIDToOID[i].oid, oid);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_oidFunctionSet(void)
|
||||
{
|
||||
HCRYPTOIDFUNCSET set1, set2;
|
||||
BOOL ret;
|
||||
LPWSTR buf = NULL;
|
||||
DWORD size;
|
||||
|
||||
/* This crashes
|
||||
set = CryptInitOIDFunctionSet(NULL, 0);
|
||||
*/
|
||||
|
||||
/* The name doesn't mean much */
|
||||
set1 = CryptInitOIDFunctionSet("funky", 0);
|
||||
ok(set1 != 0, "CryptInitOIDFunctionSet failed: %08x\n", GetLastError());
|
||||
if (set1)
|
||||
{
|
||||
/* These crash
|
||||
ret = CryptGetDefaultOIDDllList(NULL, 0, NULL, NULL);
|
||||
ret = CryptGetDefaultOIDDllList(NULL, 0, NULL, &size);
|
||||
*/
|
||||
size = 0;
|
||||
ret = CryptGetDefaultOIDDllList(set1, 0, NULL, &size);
|
||||
ok(ret, "CryptGetDefaultOIDDllList failed: %08x\n", GetLastError());
|
||||
if (ret)
|
||||
{
|
||||
buf = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
|
||||
if (buf)
|
||||
{
|
||||
ret = CryptGetDefaultOIDDllList(set1, 0, buf, &size);
|
||||
ok(ret, "CryptGetDefaultOIDDllList failed: %08x\n",
|
||||
GetLastError());
|
||||
ok(!*buf, "Expected empty DLL list\n");
|
||||
HeapFree(GetProcessHeap(), 0, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* MSDN says flags must be 0, but it's not checked */
|
||||
set1 = CryptInitOIDFunctionSet("", 1);
|
||||
ok(set1 != 0, "CryptInitOIDFunctionSet failed: %08x\n", GetLastError());
|
||||
set2 = CryptInitOIDFunctionSet("", 0);
|
||||
ok(set2 != 0, "CryptInitOIDFunctionSet failed: %08x\n", GetLastError());
|
||||
/* There isn't a free function, so there must be only one set per name to
|
||||
* limit leaks. (I guess the sets are freed when crypt32 is unloaded.)
|
||||
*/
|
||||
ok(set1 == set2, "Expected identical sets\n");
|
||||
if (set1)
|
||||
{
|
||||
/* The empty name function set used here seems to correspond to
|
||||
* DEFAULT.
|
||||
*/
|
||||
}
|
||||
|
||||
/* There's no installed function for a built-in encoding. */
|
||||
set1 = CryptInitOIDFunctionSet("CryptDllEncodeObject", 0);
|
||||
ok(set1 != 0, "CryptInitOIDFunctionSet failed: %08x\n", GetLastError());
|
||||
if (set1)
|
||||
{
|
||||
void *funcAddr;
|
||||
HCRYPTOIDFUNCADDR hFuncAddr;
|
||||
|
||||
ret = CryptGetOIDFunctionAddress(set1, X509_ASN_ENCODING, X509_CERT, 0,
|
||||
&funcAddr, &hFuncAddr);
|
||||
ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
|
||||
"Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
typedef int (*funcY)(int);
|
||||
|
||||
static int funky(int x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
static void test_installOIDFunctionAddress(void)
|
||||
{
|
||||
BOOL ret;
|
||||
CRYPT_OID_FUNC_ENTRY entry = { CRYPT_DEFAULT_OID, funky };
|
||||
HCRYPTOIDFUNCSET set;
|
||||
|
||||
/* This crashes
|
||||
ret = CryptInstallOIDFunctionAddress(NULL, 0, NULL, 0, NULL, 0);
|
||||
*/
|
||||
|
||||
/* Installing zero functions should work */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptInstallOIDFunctionAddress(NULL, 0, "CryptDllEncodeObject", 0,
|
||||
NULL, 0);
|
||||
ok(ret && GetLastError() == 0xdeadbeef, "Expected success, got %08x\n",
|
||||
GetLastError());
|
||||
|
||||
/* The function name doesn't much matter */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptInstallOIDFunctionAddress(NULL, 0, "OhSoFunky", 0, NULL, 0);
|
||||
ok(ret && GetLastError() == 0xdeadbeef, "Expected success, got %08x\n",
|
||||
GetLastError());
|
||||
SetLastError(0xdeadbeef);
|
||||
entry.pszOID = X509_CERT;
|
||||
ret = CryptInstallOIDFunctionAddress(NULL, 0, "OhSoFunky", 1, &entry, 0);
|
||||
ok(ret && GetLastError() == 0xdeadbeef, "Expected success, got %08x\n",
|
||||
GetLastError());
|
||||
set = CryptInitOIDFunctionSet("OhSoFunky", 0);
|
||||
ok(set != 0, "CryptInitOIDFunctionSet failed: %08x\n", GetLastError());
|
||||
if (set)
|
||||
{
|
||||
funcY funcAddr = NULL;
|
||||
HCRYPTOIDFUNCADDR hFuncAddr = NULL;
|
||||
|
||||
/* This crashes
|
||||
ret = CryptGetOIDFunctionAddress(set, X509_ASN_ENCODING, 0, 0, NULL,
|
||||
NULL);
|
||||
*/
|
||||
ret = CryptGetOIDFunctionAddress(set, X509_ASN_ENCODING, 0, 0,
|
||||
(void **)&funcAddr, &hFuncAddr);
|
||||
ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
|
||||
"Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
|
||||
ret = CryptGetOIDFunctionAddress(set, X509_ASN_ENCODING, X509_CERT, 0,
|
||||
(void **)&funcAddr, &hFuncAddr);
|
||||
ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
|
||||
"Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
|
||||
ret = CryptGetOIDFunctionAddress(set, 0, X509_CERT, 0,
|
||||
(void **)&funcAddr, &hFuncAddr);
|
||||
ok(ret, "CryptGetOIDFunctionAddress failed: %d\n", GetLastError());
|
||||
if (funcAddr)
|
||||
{
|
||||
int y = funcAddr(0xabadc0da);
|
||||
|
||||
ok(y == 0xabadc0da, "Unexpected return (%d) from function\n", y);
|
||||
CryptFreeOIDFunctionAddress(hFuncAddr, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void test_registerOIDFunction(void)
|
||||
{
|
||||
BOOL ret;
|
||||
|
||||
/* oddly, this succeeds under WinXP; the function name key is merely
|
||||
* omitted. This may be a side effect of the registry code, I don't know.
|
||||
* I don't check it because I doubt anyone would depend on it.
|
||||
ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, NULL,
|
||||
"1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
|
||||
*/
|
||||
/* On windows XP, GetLastError is incorrectly being set with an HRESULT,
|
||||
* E_INVALIDARG
|
||||
*/
|
||||
ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "foo", NULL, bogusDll,
|
||||
NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG: %d\n", GetLastError());
|
||||
/* This has no effect, but "succeeds" on XP */
|
||||
ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "foo",
|
||||
"1.2.3.4.5.6.7.8.9.10", NULL, NULL);
|
||||
ok(ret, "Expected pseudo-success, got %d\n", GetLastError());
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "CryptDllEncodeObject",
|
||||
"1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
|
||||
if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
|
||||
{
|
||||
skip("Need admin rights\n");
|
||||
return;
|
||||
}
|
||||
ok(ret, "CryptRegisterOIDFunction failed: %d\n", GetLastError());
|
||||
ret = CryptUnregisterOIDFunction(X509_ASN_ENCODING, "CryptDllEncodeObject",
|
||||
"1.2.3.4.5.6.7.8.9.10");
|
||||
ok(ret, "CryptUnregisterOIDFunction failed: %d\n", GetLastError());
|
||||
ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "bogus",
|
||||
"1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
|
||||
ok(ret, "CryptRegisterOIDFunction failed: %d\n", GetLastError());
|
||||
ret = CryptUnregisterOIDFunction(X509_ASN_ENCODING, "bogus",
|
||||
"1.2.3.4.5.6.7.8.9.10");
|
||||
ok(ret, "CryptUnregisterOIDFunction failed: %d\n", GetLastError());
|
||||
/* Unwanted Cryptography\OID\EncodingType 1\bogus\ will still be there */
|
||||
ok(!RegDeleteKeyA(HKEY_LOCAL_MACHINE,
|
||||
"SOFTWARE\\Microsoft\\Cryptography\\OID\\EncodingType 1\\bogus"),
|
||||
"Could not delete bogus key\n");
|
||||
/* Shouldn't have effect but registry keys are created */
|
||||
ret = CryptRegisterOIDFunction(PKCS_7_ASN_ENCODING, "CryptDllEncodeObject",
|
||||
"1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
|
||||
ok(ret, "CryptRegisterOIDFunction failed: %d\n", GetLastError());
|
||||
ret = CryptUnregisterOIDFunction(PKCS_7_ASN_ENCODING, "CryptDllEncodeObject",
|
||||
"1.2.3.4.5.6.7.8.9.10");
|
||||
ok(ret, "CryptUnregisterOIDFunction failed: %d\n", GetLastError());
|
||||
/* Check with bogus encoding type. Registry keys are still created */
|
||||
ret = CryptRegisterOIDFunction(0, "CryptDllEncodeObject",
|
||||
"1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
|
||||
ok(ret, "CryptRegisterOIDFunction failed: %d\n", GetLastError());
|
||||
ret = CryptUnregisterOIDFunction(0, "CryptDllEncodeObject",
|
||||
"1.2.3.4.5.6.7.8.9.10");
|
||||
ok(ret, "CryptUnregisterOIDFunction failed: %d\n", GetLastError());
|
||||
/* Unwanted Cryptography\OID\EncodingType 0\CryptDllEncodeObject\
|
||||
* will still be there
|
||||
*/
|
||||
ok(!RegDeleteKeyA(HKEY_LOCAL_MACHINE,
|
||||
"SOFTWARE\\Microsoft\\Cryptography\\OID\\EncodingType 0\\CryptDllEncodeObject"),
|
||||
"Could not delete CryptDllEncodeObject key\n");
|
||||
/* This is written with value 3 verbatim. Thus, the encoding type isn't
|
||||
* (for now) treated as a mask. Registry keys are created.
|
||||
*/
|
||||
ret = CryptRegisterOIDFunction(3, "CryptDllEncodeObject",
|
||||
"1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
|
||||
ok(ret, "CryptRegisterOIDFunction failed: %d\n", GetLastError());
|
||||
ret = CryptUnregisterOIDFunction(3, "CryptDllEncodeObject",
|
||||
"1.2.3.4.5.6.7.8.9.10");
|
||||
ok(ret, "CryptUnregisterOIDFunction failed: %d\n", GetLastError());
|
||||
/* Unwanted Cryptography\OID\EncodingType 3\CryptDllEncodeObject
|
||||
* will still be there.
|
||||
*/
|
||||
ok(!RegDeleteKeyA(HKEY_LOCAL_MACHINE,
|
||||
"SOFTWARE\\Microsoft\\Cryptography\\OID\\EncodingType 3\\CryptDllEncodeObject"),
|
||||
"Could not delete CryptDllEncodeObject key\n");
|
||||
ok(!RegDeleteKeyA(HKEY_LOCAL_MACHINE,
|
||||
"SOFTWARE\\Microsoft\\Cryptography\\OID\\EncodingType 3"),
|
||||
"Could not delete 'EncodingType 3' key\n");
|
||||
}
|
||||
|
||||
static void test_registerDefaultOIDFunction(void)
|
||||
{
|
||||
static const char fmt[] =
|
||||
"Software\\Microsoft\\Cryptography\\OID\\EncodingType %d\\%s\\DEFAULT";
|
||||
static const char func[] = "CertDllOpenStoreProv";
|
||||
char buf[MAX_PATH];
|
||||
BOOL ret;
|
||||
long rc;
|
||||
HKEY key;
|
||||
|
||||
ret = CryptRegisterDefaultOIDFunction(0, NULL, 0, NULL);
|
||||
ok(!ret && GetLastError() == E_INVALIDARG,
|
||||
"Expected E_INVALIDARG, got %08x\n", GetLastError());
|
||||
/* This succeeds on WinXP, although the bogus entry is unusable.
|
||||
ret = CryptRegisterDefaultOIDFunction(0, NULL, 0, bogusDll);
|
||||
*/
|
||||
/* Register one at index 0 */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptRegisterDefaultOIDFunction(0, "CertDllOpenStoreProv", 0,
|
||||
bogusDll);
|
||||
if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
|
||||
{
|
||||
skip("Need admin rights\n");
|
||||
return;
|
||||
}
|
||||
ok(ret, "CryptRegisterDefaultOIDFunction failed: %08x\n", GetLastError());
|
||||
/* Reregistering should fail */
|
||||
ret = CryptRegisterDefaultOIDFunction(0, "CertDllOpenStoreProv", 0,
|
||||
bogusDll);
|
||||
ok(!ret && GetLastError() == ERROR_FILE_EXISTS,
|
||||
"Expected ERROR_FILE_EXISTS, got %08x\n", GetLastError());
|
||||
/* Registering the same one at index 1 should also fail */
|
||||
ret = CryptRegisterDefaultOIDFunction(0, "CertDllOpenStoreProv", 1,
|
||||
bogusDll);
|
||||
ok(!ret && GetLastError() == ERROR_FILE_EXISTS,
|
||||
"Expected ERROR_FILE_EXISTS, got %08x\n", GetLastError());
|
||||
/* Registering a different one at index 1 succeeds */
|
||||
ret = CryptRegisterDefaultOIDFunction(0, "CertDllOpenStoreProv", 1,
|
||||
bogus2Dll);
|
||||
ok(ret, "CryptRegisterDefaultOIDFunction failed: %08x\n", GetLastError());
|
||||
sprintf(buf, fmt, 0, func);
|
||||
rc = RegOpenKeyA(HKEY_LOCAL_MACHINE, buf, &key);
|
||||
ok(rc == 0, "Expected key to exist, RegOpenKeyA failed: %ld\n", rc);
|
||||
if (rc == 0)
|
||||
{
|
||||
static const CHAR dllA[] = "Dll";
|
||||
static const CHAR bogusDll_A[] = "bogus.dll";
|
||||
static const CHAR bogus2Dll_A[] = "bogus2.dll";
|
||||
CHAR dllBuf[MAX_PATH];
|
||||
DWORD type, size;
|
||||
LPSTR ptr;
|
||||
|
||||
size = sizeof(dllBuf) / sizeof(dllBuf[0]);
|
||||
rc = RegQueryValueExA(key, dllA, NULL, &type, (LPBYTE)dllBuf, &size);
|
||||
ok(rc == 0,
|
||||
"Expected Dll value to exist, RegQueryValueExA failed: %ld\n", rc);
|
||||
ok(type == REG_MULTI_SZ, "Expected type REG_MULTI_SZ, got %d\n", type);
|
||||
/* bogusDll was registered first, so that should be first */
|
||||
ptr = dllBuf;
|
||||
ok(!lstrcmpiA(ptr, bogusDll_A), "Unexpected dll\n");
|
||||
ptr += lstrlenA(ptr) + 1;
|
||||
ok(!lstrcmpiA(ptr, bogus2Dll_A), "Unexpected dll\n");
|
||||
RegCloseKey(key);
|
||||
}
|
||||
/* Unregister both of them */
|
||||
ret = CryptUnregisterDefaultOIDFunction(0, "CertDllOpenStoreProv",
|
||||
bogusDll);
|
||||
ok(ret, "CryptUnregisterDefaultOIDFunction failed: %08x\n",
|
||||
GetLastError());
|
||||
ret = CryptUnregisterDefaultOIDFunction(0, "CertDllOpenStoreProv",
|
||||
bogus2Dll);
|
||||
ok(ret, "CryptUnregisterDefaultOIDFunction failed: %08x\n",
|
||||
GetLastError());
|
||||
/* Now that they're both unregistered, unregistering should fail */
|
||||
ret = CryptUnregisterDefaultOIDFunction(0, "CertDllOpenStoreProv",
|
||||
bogusDll);
|
||||
ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
|
||||
"Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
|
||||
|
||||
/* Repeat a few tests on the normal encoding type */
|
||||
ret = CryptRegisterDefaultOIDFunction(X509_ASN_ENCODING,
|
||||
"CertDllOpenStoreProv", 0, bogusDll);
|
||||
ret = CryptUnregisterDefaultOIDFunction(X509_ASN_ENCODING,
|
||||
"CertDllOpenStoreProv", bogusDll);
|
||||
ok(ret, "CryptUnregisterDefaultOIDFunction failed\n");
|
||||
ret = CryptUnregisterDefaultOIDFunction(X509_ASN_ENCODING,
|
||||
"CertDllOpenStoreProv", bogusDll);
|
||||
ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
|
||||
"Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
|
||||
}
|
||||
|
||||
static void test_getDefaultOIDFunctionAddress(void)
|
||||
{
|
||||
BOOL ret;
|
||||
HCRYPTOIDFUNCSET set;
|
||||
void *funcAddr;
|
||||
HCRYPTOIDFUNCADDR hFuncAddr;
|
||||
|
||||
/* Crash
|
||||
ret = CryptGetDefaultOIDFunctionAddress(0, 0, NULL, 0, NULL, NULL);
|
||||
ret = CryptGetDefaultOIDFunctionAddress(0, 0, NULL, 0, &funcAddr, NULL);
|
||||
ret = CryptGetDefaultOIDFunctionAddress(0, 0, NULL, 0, NULL, &hFuncAddr);
|
||||
ret = CryptGetDefaultOIDFunctionAddress(0, 0, NULL, 0, &funcAddr,
|
||||
&hFuncAddr);
|
||||
*/
|
||||
set = CryptInitOIDFunctionSet("CertDllOpenStoreProv", 0);
|
||||
ok(set != 0, "CryptInitOIDFunctionSet failed: %d\n", GetLastError());
|
||||
/* This crashes if hFuncAddr is not 0 to begin with */
|
||||
hFuncAddr = 0;
|
||||
ret = CryptGetDefaultOIDFunctionAddress(set, 0, NULL, 0, &funcAddr,
|
||||
&hFuncAddr);
|
||||
ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
|
||||
"Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
|
||||
/* This fails with the normal encoding too, so built-in functions aren't
|
||||
* returned.
|
||||
*/
|
||||
ret = CryptGetDefaultOIDFunctionAddress(set, X509_ASN_ENCODING, NULL, 0,
|
||||
&funcAddr, &hFuncAddr);
|
||||
ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
|
||||
"Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
|
||||
|
||||
/* Even with a registered dll, this fails (since the dll doesn't exist) */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptRegisterDefaultOIDFunction(0, "CertDllOpenStoreProv", 0,
|
||||
bogusDll);
|
||||
if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
|
||||
skip("Need admin rights\n");
|
||||
else
|
||||
ok(ret, "CryptRegisterDefaultOIDFunction failed: %08x\n", GetLastError());
|
||||
ret = CryptGetDefaultOIDFunctionAddress(set, 0, NULL, 0, &funcAddr,
|
||||
&hFuncAddr);
|
||||
ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
|
||||
"Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
|
||||
CryptUnregisterDefaultOIDFunction(0, "CertDllOpenStoreProv", bogusDll);
|
||||
}
|
||||
|
||||
static BOOL WINAPI countOidInfo(PCCRYPT_OID_INFO pInfo, void *pvArg)
|
||||
{
|
||||
(*(DWORD *)pvArg)++;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL WINAPI noOidInfo(PCCRYPT_OID_INFO pInfo, void *pvArg)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void test_enumOIDInfo(void)
|
||||
{
|
||||
BOOL ret;
|
||||
DWORD count = 0;
|
||||
|
||||
if (!pCryptEnumOIDInfo)
|
||||
{
|
||||
skip("CryptEnumOIDInfo() is not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* This crashes
|
||||
ret = pCryptEnumOIDInfo(7, 0, NULL, NULL);
|
||||
*/
|
||||
|
||||
/* Silly tests, check that more than one thing is enumerated */
|
||||
ret = pCryptEnumOIDInfo(0, 0, &count, countOidInfo);
|
||||
ok(ret && count > 0, "Expected more than item enumerated\n");
|
||||
ret = pCryptEnumOIDInfo(0, 0, NULL, noOidInfo);
|
||||
ok(!ret, "Expected FALSE\n");
|
||||
}
|
||||
|
||||
static void test_findOIDInfo(void)
|
||||
{
|
||||
static WCHAR sha1[] = { 's','h','a','1',0 };
|
||||
static CHAR oid_rsa_md5[] = szOID_RSA_MD5;
|
||||
ALG_ID alg = CALG_SHA1;
|
||||
ALG_ID algs[2] = { CALG_MD5, CALG_RSA_SIGN };
|
||||
PCCRYPT_OID_INFO info;
|
||||
|
||||
info = CryptFindOIDInfo(0, NULL, 0);
|
||||
ok(info == NULL, "Expected NULL\n");
|
||||
info = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, oid_rsa_md5, 0);
|
||||
ok(info != NULL, "Expected to find szOID_RSA_MD5\n");
|
||||
if (info)
|
||||
{
|
||||
ok(!strcmp(info->pszOID, szOID_RSA_MD5), "Expected %s, got %s\n",
|
||||
szOID_RSA_MD5, info->pszOID);
|
||||
ok(U(*info).Algid == CALG_MD5, "Expected CALG_MD5, got %d\n",
|
||||
U(*info).Algid);
|
||||
}
|
||||
info = CryptFindOIDInfo(CRYPT_OID_INFO_NAME_KEY, sha1, 0);
|
||||
ok(info != NULL, "Expected to find sha1\n");
|
||||
if (info)
|
||||
{
|
||||
ok(!strcmp(info->pszOID, szOID_OIWSEC_sha1), "Expected %s, got %s\n",
|
||||
szOID_OIWSEC_sha1, info->pszOID);
|
||||
ok(U(*info).Algid == CALG_SHA1, "Expected CALG_SHA1, got %d\n",
|
||||
U(*info).Algid);
|
||||
}
|
||||
info = CryptFindOIDInfo(CRYPT_OID_INFO_ALGID_KEY, &alg, 0);
|
||||
ok(info != NULL, "Expected to find sha1\n");
|
||||
if (info)
|
||||
{
|
||||
ok(!strcmp(info->pszOID, szOID_OIWSEC_sha1), "Expected %s, got %s\n",
|
||||
szOID_OIWSEC_sha1, info->pszOID);
|
||||
ok(U(*info).Algid == CALG_SHA1, "Expected CALG_SHA1, got %d\n",
|
||||
U(*info).Algid);
|
||||
}
|
||||
info = CryptFindOIDInfo(CRYPT_OID_INFO_SIGN_KEY, algs, 0);
|
||||
ok(info != NULL, "Expected to find md5RSA\n");
|
||||
if (info)
|
||||
{
|
||||
ok(!strcmp(info->pszOID, szOID_RSA_MD5RSA), "Expected %s, got %s\n",
|
||||
szOID_RSA_MD5RSA, info->pszOID);
|
||||
ok(U(*info).Algid == CALG_MD5, "Expected CALG_MD5, got %d\n",
|
||||
U(*info).Algid);
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST(oid)
|
||||
{
|
||||
HMODULE hCrypt32 = GetModuleHandleA("crypt32.dll");
|
||||
pCryptEnumOIDInfo = (void*)GetProcAddress(hCrypt32, "CryptEnumOIDInfo");
|
||||
|
||||
testOIDToAlgID();
|
||||
testAlgIDToOID();
|
||||
test_enumOIDInfo();
|
||||
test_findOIDInfo();
|
||||
test_oidFunctionSet();
|
||||
test_installOIDFunctionAddress();
|
||||
test_registerOIDFunction();
|
||||
test_registerDefaultOIDFunction();
|
||||
test_getDefaultOIDFunctionAddress();
|
||||
}
|
229
rostests/winetests/crypt32/protectdata.c
Normal file
229
rostests/winetests/crypt32/protectdata.c
Normal file
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
* Unit test suite for crypt32.dll's CryptProtectData/CryptUnprotectData
|
||||
*
|
||||
* Copyright 2005 Kees Cook <kees@outflux.net>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#include <winerror.h>
|
||||
#include <wincrypt.h>
|
||||
|
||||
#include "wine/test.h"
|
||||
|
||||
static BOOL (WINAPI *pCryptProtectData)(DATA_BLOB*,LPCWSTR,DATA_BLOB*,PVOID,CRYPTPROTECT_PROMPTSTRUCT*,DWORD,DATA_BLOB*);
|
||||
static BOOL (WINAPI *pCryptUnprotectData)(DATA_BLOB*,LPWSTR*,DATA_BLOB*,PVOID,CRYPTPROTECT_PROMPTSTRUCT*,DWORD,DATA_BLOB*);
|
||||
|
||||
static char secret[] = "I am a super secret string that no one can see!";
|
||||
static char secret2[] = "I am a super secret string indescribable string";
|
||||
static char key[] = "Wibble wibble wibble";
|
||||
static const WCHAR desc[] = {'U','l','t','r','a',' ','s','e','c','r','e','t',' ','t','e','s','t',' ','m','e','s','s','a','g','e',0};
|
||||
static BOOL protected = FALSE; /* if true, the unprotect tests can run */
|
||||
static DATA_BLOB cipher;
|
||||
static DATA_BLOB cipher_entropy;
|
||||
static DATA_BLOB cipher_no_desc;
|
||||
|
||||
static void test_cryptprotectdata(void)
|
||||
{
|
||||
LONG r;
|
||||
DATA_BLOB plain;
|
||||
DATA_BLOB entropy;
|
||||
|
||||
plain.pbData=(void*)secret;
|
||||
plain.cbData=strlen(secret)+1;
|
||||
|
||||
entropy.pbData=(void*)key;
|
||||
entropy.cbData=strlen(key)+1;
|
||||
|
||||
SetLastError(0xDEADBEEF);
|
||||
protected = pCryptProtectData(NULL,desc,NULL,NULL,NULL,0,&cipher);
|
||||
ok(!protected, "Encrypting without plain data source.\n");
|
||||
r = GetLastError();
|
||||
ok(r == ERROR_INVALID_PARAMETER, "Wrong (%u) GetLastError seen\n",r);
|
||||
|
||||
SetLastError(0xDEADBEEF);
|
||||
protected = pCryptProtectData(&plain,desc,NULL,NULL,NULL,0,NULL);
|
||||
ok(!protected, "Encrypting without cipher destination.\n");
|
||||
r = GetLastError();
|
||||
ok(r == ERROR_INVALID_PARAMETER, "Wrong (%u) GetLastError seen\n",r);
|
||||
|
||||
cipher.pbData=NULL;
|
||||
cipher.cbData=0;
|
||||
|
||||
/* without entropy */
|
||||
SetLastError(0xDEADBEEF);
|
||||
protected = pCryptProtectData(&plain,desc,NULL,NULL,NULL,0,&cipher);
|
||||
ok(protected, "Encrypting without entropy.\n");
|
||||
r = GetLastError();
|
||||
ok(r == ERROR_SUCCESS ||
|
||||
r == ERROR_IO_PENDING, /* win2k */
|
||||
"Expected ERROR_SUCCESS or ERROR_IO_PENDING, got %d\n",r);
|
||||
|
||||
cipher_entropy.pbData=NULL;
|
||||
cipher_entropy.cbData=0;
|
||||
|
||||
/* with entropy */
|
||||
SetLastError(0xDEADBEEF);
|
||||
protected = pCryptProtectData(&plain,desc,&entropy,NULL,NULL,0,&cipher_entropy);
|
||||
ok(protected, "Encrypting with entropy.\n");
|
||||
|
||||
cipher_no_desc.pbData=NULL;
|
||||
cipher_no_desc.cbData=0;
|
||||
|
||||
/* with entropy but no description */
|
||||
plain.pbData=(void*)secret2;
|
||||
plain.cbData=strlen(secret2)+1;
|
||||
SetLastError(0xDEADBEEF);
|
||||
protected = pCryptProtectData(&plain,NULL,&entropy,NULL,NULL,0,&cipher_no_desc);
|
||||
if (!protected)
|
||||
{
|
||||
/* fails in win2k */
|
||||
ok(GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"Expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
static void test_cryptunprotectdata(void)
|
||||
{
|
||||
LONG r;
|
||||
DATA_BLOB plain;
|
||||
DATA_BLOB entropy;
|
||||
BOOL okay;
|
||||
WCHAR * data_desc;
|
||||
|
||||
entropy.pbData=(void*)key;
|
||||
entropy.cbData=strlen(key)+1;
|
||||
|
||||
/* fails in win2k */
|
||||
if (!protected)
|
||||
{
|
||||
skip("CryptProtectData failed to run\n");
|
||||
return;
|
||||
}
|
||||
|
||||
plain.pbData=NULL;
|
||||
plain.cbData=0;
|
||||
|
||||
SetLastError(0xDEADBEEF);
|
||||
okay = pCryptUnprotectData(&cipher,NULL,NULL,NULL,NULL,0,NULL);
|
||||
ok(!okay,"Decrypting without destination\n");
|
||||
r = GetLastError();
|
||||
ok(r == ERROR_INVALID_PARAMETER, "Wrong (%u) GetLastError seen\n",r);
|
||||
|
||||
SetLastError(0xDEADBEEF);
|
||||
okay = pCryptUnprotectData(NULL,NULL,NULL,NULL,NULL,0,&plain);
|
||||
ok(!okay,"Decrypting without source\n");
|
||||
r = GetLastError();
|
||||
ok(r == ERROR_INVALID_PARAMETER, "Wrong (%u) GetLastError seen\n",r);
|
||||
|
||||
plain.pbData=NULL;
|
||||
plain.cbData=0;
|
||||
|
||||
SetLastError(0xDEADBEEF);
|
||||
okay = pCryptUnprotectData(&cipher_entropy,NULL,NULL,NULL,NULL,0,&plain);
|
||||
ok(!okay,"Decrypting without needed entropy\n");
|
||||
r = GetLastError();
|
||||
ok(r == ERROR_INVALID_DATA, "Wrong (%u) GetLastError seen\n", r);
|
||||
|
||||
plain.pbData=NULL;
|
||||
plain.cbData=0;
|
||||
data_desc=NULL;
|
||||
|
||||
/* without entropy */
|
||||
SetLastError(0xDEADBEEF);
|
||||
okay = pCryptUnprotectData(&cipher,&data_desc,NULL,NULL,NULL,0,&plain);
|
||||
ok(okay,"Decrypting without entropy\n");
|
||||
|
||||
ok(plain.pbData!=NULL,"Plain DATA_BLOB missing data\n");
|
||||
ok(plain.cbData==strlen(secret)+1,"Plain DATA_BLOB wrong length\n");
|
||||
ok(!strcmp((const char*)plain.pbData,secret),"Plain does not match secret\n");
|
||||
ok(data_desc!=NULL,"Description not allocated\n");
|
||||
ok(!lstrcmpW(data_desc,desc),"Description does not match\n");
|
||||
|
||||
LocalFree(plain.pbData);
|
||||
LocalFree(data_desc);
|
||||
|
||||
plain.pbData=NULL;
|
||||
plain.cbData=0;
|
||||
data_desc=NULL;
|
||||
|
||||
/* with wrong entropy */
|
||||
SetLastError(0xDEADBEEF);
|
||||
okay = pCryptUnprotectData(&cipher_entropy,&data_desc,&cipher_entropy,NULL,NULL,0,&plain);
|
||||
ok(!okay,"Decrypting with wrong entropy\n");
|
||||
r = GetLastError();
|
||||
ok(r == ERROR_INVALID_DATA, "Wrong (%u) GetLastError seen\n",r);
|
||||
|
||||
/* with entropy */
|
||||
SetLastError(0xDEADBEEF);
|
||||
okay = pCryptUnprotectData(&cipher_entropy,&data_desc,&entropy,NULL,NULL,0,&plain);
|
||||
ok(okay,"Decrypting with entropy\n");
|
||||
|
||||
ok(plain.pbData!=NULL,"Plain DATA_BLOB missing data\n");
|
||||
ok(plain.cbData==strlen(secret)+1,"Plain DATA_BLOB wrong length\n");
|
||||
ok(!strcmp((const char*)plain.pbData,secret),"Plain does not match secret\n");
|
||||
ok(data_desc!=NULL,"Description not allocated\n");
|
||||
ok(!lstrcmpW(data_desc,desc),"Description does not match\n");
|
||||
|
||||
LocalFree(plain.pbData);
|
||||
LocalFree(data_desc);
|
||||
|
||||
plain.pbData=NULL;
|
||||
plain.cbData=0;
|
||||
data_desc=NULL;
|
||||
|
||||
/* with entropy but no description */
|
||||
SetLastError(0xDEADBEEF);
|
||||
okay = pCryptUnprotectData(&cipher_no_desc,&data_desc,&entropy,NULL,NULL,0,&plain);
|
||||
ok(okay,"Decrypting with entropy and no description\n");
|
||||
|
||||
ok(plain.pbData!=NULL,"Plain DATA_BLOB missing data\n");
|
||||
ok(plain.cbData==strlen(secret2)+1,"Plain DATA_BLOB wrong length\n");
|
||||
ok(!strcmp((const char*)plain.pbData,secret2),"Plain does not match secret\n");
|
||||
ok(data_desc!=NULL,"Description not allocated\n");
|
||||
ok(data_desc[0]=='\0',"Description not empty\n");
|
||||
|
||||
LocalFree(data_desc);
|
||||
LocalFree(plain.pbData);
|
||||
|
||||
plain.pbData=NULL;
|
||||
plain.cbData=0;
|
||||
}
|
||||
|
||||
START_TEST(protectdata)
|
||||
{
|
||||
HMODULE hCrypt32 = GetModuleHandleA("crypt32.dll");
|
||||
hCrypt32 = GetModuleHandleA("crypt32.dll");
|
||||
pCryptProtectData = (void*)GetProcAddress(hCrypt32, "CryptProtectData");
|
||||
pCryptUnprotectData = (void*)GetProcAddress(hCrypt32, "CryptUnprotectData");
|
||||
if (!pCryptProtectData || !pCryptUnprotectData)
|
||||
{
|
||||
skip("Crypt(Un)ProtectData() is not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
protected=FALSE;
|
||||
test_cryptprotectdata();
|
||||
test_cryptunprotectdata();
|
||||
|
||||
/* deinit globals here */
|
||||
if (cipher.pbData) LocalFree(cipher.pbData);
|
||||
if (cipher_entropy.pbData) LocalFree(cipher_entropy.pbData);
|
||||
if (cipher_no_desc.pbData) LocalFree(cipher_no_desc.pbData);
|
||||
}
|
444
rostests/winetests/crypt32/sip.c
Normal file
444
rostests/winetests/crypt32/sip.c
Normal file
|
@ -0,0 +1,444 @@
|
|||
/*
|
||||
* Subject Interface Package tests
|
||||
*
|
||||
* Copyright 2006 Paul Vriens
|
||||
* Copyright 2008 Juan Lang
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#include <winerror.h>
|
||||
#include <winnls.h>
|
||||
#include <wincrypt.h>
|
||||
#include <mssip.h>
|
||||
|
||||
#include "wine/test.h"
|
||||
|
||||
static BOOL (WINAPI * funcCryptSIPGetSignedDataMsg)(SIP_SUBJECTINFO *,DWORD *,DWORD,DWORD *,BYTE *);
|
||||
static BOOL (WINAPI * funcCryptSIPPutSignedDataMsg)(SIP_SUBJECTINFO *,DWORD,DWORD *,DWORD,BYTE *);
|
||||
static BOOL (WINAPI * funcCryptSIPCreateIndirectData)(SIP_SUBJECTINFO *,DWORD *,SIP_INDIRECT_DATA *);
|
||||
static BOOL (WINAPI * funcCryptSIPVerifyIndirectData)(SIP_SUBJECTINFO *,SIP_INDIRECT_DATA *);
|
||||
static BOOL (WINAPI * funcCryptSIPRemoveSignedDataMsg)(SIP_SUBJECTINFO *,DWORD);
|
||||
|
||||
static char *show_guid(const GUID *guid, char *buf)
|
||||
{
|
||||
sprintf(buf,
|
||||
"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
|
||||
guid->Data1, guid->Data2, guid->Data3,
|
||||
guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
|
||||
guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] );
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void test_AddRemoveProvider(void)
|
||||
{
|
||||
BOOL ret;
|
||||
SIP_ADD_NEWPROVIDER newprov;
|
||||
GUID actionid = { 0xdeadbe, 0xefde, 0xadbe, { 0xef,0xde,0xad,0xbe,0xef,0xde,0xad,0xbe }};
|
||||
static WCHAR dummydll[] = {'d','e','a','d','b','e','e','f','.','d','l','l',0 };
|
||||
static WCHAR dummyfunction[] = {'d','u','m','m','y','f','u','n','c','t','i','o','n',0 };
|
||||
|
||||
/* NULL check */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptSIPRemoveProvider(NULL);
|
||||
ok (!ret, "Expected CryptSIPRemoveProvider to fail.\n");
|
||||
ok (GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"Expected ERROR_INVALID_PARAMETER, got %d.\n", GetLastError());
|
||||
|
||||
/* nonexistent provider should result in a registry error */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptSIPRemoveProvider(&actionid);
|
||||
if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
|
||||
{
|
||||
/* Apparently the needed rights are checked before the existence of the provider */
|
||||
skip("Need admin rights\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
ok (!ret, "Expected CryptSIPRemoveProvider to fail.\n");
|
||||
ok (GetLastError() == ERROR_FILE_NOT_FOUND,
|
||||
"Expected ERROR_FILE_NOT_FOUND, got %d.\n", GetLastError());
|
||||
}
|
||||
|
||||
/* Everything OK, pwszIsFunctionName and pwszIsFunctionNameFmt2 are left NULL
|
||||
* as allowed */
|
||||
|
||||
memset(&newprov, 0, sizeof(SIP_ADD_NEWPROVIDER));
|
||||
newprov.cbStruct = sizeof(SIP_ADD_NEWPROVIDER);
|
||||
newprov.pgSubject = &actionid;
|
||||
newprov.pwszDLLFileName = dummydll;
|
||||
newprov.pwszGetFuncName = dummyfunction;
|
||||
newprov.pwszPutFuncName = dummyfunction;
|
||||
newprov.pwszCreateFuncName = dummyfunction;
|
||||
newprov.pwszVerifyFuncName = dummyfunction;
|
||||
newprov.pwszRemoveFuncName = dummyfunction;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptSIPAddProvider(&newprov);
|
||||
if (!ret && GetLastError() == ERROR_ACCESS_DENIED)
|
||||
{
|
||||
skip("Need admin rights\n");
|
||||
return;
|
||||
}
|
||||
ok ( ret, "CryptSIPAddProvider should have succeeded\n");
|
||||
|
||||
/* Dummy provider will be deleted, but the function still fails because
|
||||
* pwszIsFunctionName and pwszIsFunctionNameFmt2 are not present in the
|
||||
* registry.
|
||||
*/
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptSIPRemoveProvider(&actionid);
|
||||
ok (!ret, "Expected CryptSIPRemoveProvider to fail.\n");
|
||||
ok (GetLastError() == ERROR_FILE_NOT_FOUND,
|
||||
"Expected ERROR_FILE_NOT_FOUND, got %d.\n", GetLastError());
|
||||
|
||||
/* Everything OK */
|
||||
memset(&newprov, 0, sizeof(SIP_ADD_NEWPROVIDER));
|
||||
newprov.cbStruct = sizeof(SIP_ADD_NEWPROVIDER);
|
||||
newprov.pgSubject = &actionid;
|
||||
newprov.pwszDLLFileName = dummydll;
|
||||
newprov.pwszGetFuncName = dummyfunction;
|
||||
newprov.pwszPutFuncName = dummyfunction;
|
||||
newprov.pwszCreateFuncName = dummyfunction;
|
||||
newprov.pwszVerifyFuncName = dummyfunction;
|
||||
newprov.pwszRemoveFuncName = dummyfunction;
|
||||
newprov.pwszIsFunctionNameFmt2 = dummyfunction;
|
||||
newprov.pwszIsFunctionName = dummyfunction;
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptSIPAddProvider(&newprov);
|
||||
ok ( ret, "CryptSIPAddProvider should have succeeded\n");
|
||||
|
||||
/* Dummy provider should be deleted */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptSIPRemoveProvider(&actionid);
|
||||
ok ( ret, "CryptSIPRemoveProvider should have succeeded\n");
|
||||
}
|
||||
|
||||
static const BYTE cabFileData[] = {
|
||||
0x4d,0x53,0x43,0x46,0x00,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||
0x2c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x01,0x01,0x00,0x01,0x00,0x00,0x00,
|
||||
0xef,0xbe,0xff,0xff,0x42,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x06,0x00,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0xf7,0x38,0x4b,0xac,0x00,0x00,0x61,0x2e,0x74,0x78,
|
||||
0x74,0x00,0x6d,0x5a,0x72,0x78,0x06,0x00,0x06,0x00,0x61,0x2e,0x74,0x78,0x74,0x0a,
|
||||
};
|
||||
|
||||
static void test_SIPRetrieveSubjectGUID(void)
|
||||
{
|
||||
BOOL ret;
|
||||
GUID subject;
|
||||
HANDLE file;
|
||||
static const CHAR windir[] = "windir";
|
||||
static const CHAR regeditExe[] = "regedit.exe";
|
||||
static const GUID nullSubject = { 0x0, 0x0, 0x0, { 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 }};
|
||||
static const WCHAR deadbeef[] = { 'c',':','\\','d','e','a','d','b','e','e','f','.','d','b','f',0 };
|
||||
/* Couldn't find a name for this GUID, it's the one used for 95% of the files */
|
||||
static const GUID unknownGUID = { 0xC689AAB8, 0x8E78, 0x11D0, { 0x8C,0x47,0x00,0xC0,0x4F,0xC2,0x95,0xEE }};
|
||||
static const GUID cabGUID = { 0xc689aaba, 0x8e78, 0x11d0, {0x8c,0x47,0x00,0xc0,0x4f,0xc2,0x95,0xee }};
|
||||
static CHAR regeditPath[MAX_PATH];
|
||||
static WCHAR regeditPathW[MAX_PATH];
|
||||
static CHAR path[MAX_PATH];
|
||||
static CHAR tempfile[MAX_PATH];
|
||||
static WCHAR tempfileW[MAX_PATH];
|
||||
static char guid1[39], guid2[39];
|
||||
DWORD written;
|
||||
|
||||
/* NULL check */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptSIPRetrieveSubjectGuid(NULL, NULL, NULL);
|
||||
ok ( !ret, "Expected CryptSIPRetrieveSubjectGuid to fail\n");
|
||||
ok (GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"Expected ERROR_INVALID_PARAMETER, got %d.\n", GetLastError());
|
||||
|
||||
/* Test with a nonexistent file (hopefully) */
|
||||
SetLastError(0xdeadbeef);
|
||||
/* Set subject to something other than zeros */
|
||||
memset(&subject, 1, sizeof(GUID));
|
||||
ret = CryptSIPRetrieveSubjectGuid(deadbeef, NULL, &subject);
|
||||
ok ( !ret, "Expected CryptSIPRetrieveSubjectGuid to fail\n");
|
||||
ok (GetLastError() == ERROR_FILE_NOT_FOUND,
|
||||
"Expected ERROR_FILE_NOT_FOUND, got %d.\n", GetLastError());
|
||||
ok ( !memcmp(&subject, &nullSubject, sizeof(GUID)),
|
||||
"Expected a NULL GUID for c:\\deadbeef.dbf, not %s\n", show_guid(&subject, guid1));
|
||||
|
||||
/* Now with an executable that should exist
|
||||
*
|
||||
* Use A-functions where possible as that should be available on all platforms
|
||||
*/
|
||||
ret = GetEnvironmentVariableA(windir, regeditPath, MAX_PATH);
|
||||
ok (ret > 0, "expected GEVA(windir) to succeed, last error %d\n", GetLastError());
|
||||
strcat(regeditPath, "\\");
|
||||
strcat(regeditPath, regeditExe);
|
||||
MultiByteToWideChar( CP_ACP, 0, regeditPath,
|
||||
strlen(regeditPath)+1, regeditPathW,
|
||||
sizeof(regeditPathW)/sizeof(regeditPathW[0]) );
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
memset(&subject, 1, sizeof(GUID));
|
||||
ret = CryptSIPRetrieveSubjectGuid(regeditPathW, NULL, &subject);
|
||||
ok ( ret, "Expected CryptSIPRetrieveSubjectGuid to succeed\n");
|
||||
ok ( !memcmp(&subject, &unknownGUID, sizeof(GUID)),
|
||||
"Expected (%s), got (%s).\n", show_guid(&unknownGUID, guid1), show_guid(&subject, guid2));
|
||||
|
||||
/* The same thing but now with a handle instead of a filename */
|
||||
file = CreateFileA(regeditPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||
SetLastError(0xdeadbeef);
|
||||
memset(&subject, 1, sizeof(GUID));
|
||||
ret = CryptSIPRetrieveSubjectGuid(NULL, file, &subject);
|
||||
ok ( ret, "Expected CryptSIPRetrieveSubjectGuid to succeed\n");
|
||||
ok ( !memcmp(&subject, &unknownGUID, sizeof(GUID)),
|
||||
"Expected (%s), got (%s).\n", show_guid(&unknownGUID, guid1), show_guid(&subject, guid2));
|
||||
CloseHandle(file);
|
||||
|
||||
/* And both */
|
||||
file = CreateFileA(regeditPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||
SetLastError(0xdeadbeef);
|
||||
memset(&subject, 1, sizeof(GUID));
|
||||
ret = CryptSIPRetrieveSubjectGuid(regeditPathW, file, &subject);
|
||||
ok ( ret, "Expected CryptSIPRetrieveSubjectGuid to succeed\n");
|
||||
ok ( !memcmp(&subject, &unknownGUID, sizeof(GUID)),
|
||||
"Expected (%s), got (%s).\n", show_guid(&unknownGUID, guid1), show_guid(&subject, guid2));
|
||||
CloseHandle(file);
|
||||
|
||||
/* Now with an empty file */
|
||||
GetTempPathA(sizeof(path), path);
|
||||
GetTempFileNameA(path, "sip", 0 , tempfile);
|
||||
MultiByteToWideChar( CP_ACP, 0, tempfile,
|
||||
strlen(tempfile)+1, tempfileW,
|
||||
sizeof(tempfileW)/sizeof(tempfileW[0]) );
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
memset(&subject, 1, sizeof(GUID));
|
||||
ret = CryptSIPRetrieveSubjectGuid(tempfileW, NULL, &subject);
|
||||
ok ( !ret, "Expected CryptSIPRetrieveSubjectGuid to fail\n");
|
||||
ok ( GetLastError() == ERROR_FILE_INVALID ||
|
||||
GetLastError() == ERROR_INVALID_PARAMETER /* Vista */ ||
|
||||
GetLastError() == ERROR_SUCCESS /* Win98 */,
|
||||
"Expected ERROR_FILE_INVALID, ERROR_INVALID_PARAMETER or ERROR_SUCCESS, got 0x%08x\n", GetLastError());
|
||||
ok ( !memcmp(&subject, &nullSubject, sizeof(GUID)),
|
||||
"Expected a NULL GUID for empty file %s, not %s\n", tempfile, show_guid(&subject, guid1));
|
||||
|
||||
/* Use a file with a size of 3 (at least < 4) */
|
||||
file = CreateFileA(tempfile, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||
WriteFile(file, "123", 3, &written, NULL);
|
||||
CloseHandle(file);
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
memset(&subject, 1, sizeof(GUID));
|
||||
ret = CryptSIPRetrieveSubjectGuid(tempfileW, NULL, &subject);
|
||||
ok ( !ret, "Expected CryptSIPRetrieveSubjectGuid to fail\n");
|
||||
ok ( GetLastError() == ERROR_INVALID_PARAMETER ||
|
||||
GetLastError() == ERROR_SUCCESS /* Win98 */,
|
||||
"Expected ERROR_INVALID_PARAMETER or ERROR_SUCCESS, got 0x%08x\n", GetLastError());
|
||||
ok ( !memcmp(&subject, &nullSubject, sizeof(GUID)),
|
||||
"Expected a NULL GUID for empty file %s, not %s\n", tempfile, show_guid(&subject, guid1));
|
||||
|
||||
/* And now >= 4 */
|
||||
file = CreateFileA(tempfile, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||
WriteFile(file, "1234", 4, &written, NULL);
|
||||
CloseHandle(file);
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
memset(&subject, 1, sizeof(GUID));
|
||||
ret = CryptSIPRetrieveSubjectGuid(tempfileW, NULL, &subject);
|
||||
ok ( !ret, "Expected CryptSIPRetrieveSubjectGuid to fail\n");
|
||||
ok ( GetLastError() == TRUST_E_SUBJECT_FORM_UNKNOWN ||
|
||||
GetLastError() == ERROR_SUCCESS /* Win98 */,
|
||||
"Expected TRUST_E_SUBJECT_FORM_UNKNOWN or ERROR_SUCCESS, got 0x%08x\n", GetLastError());
|
||||
ok ( !memcmp(&subject, &nullSubject, sizeof(GUID)),
|
||||
"Expected a NULL GUID for empty file %s, not %s\n", tempfile, show_guid(&subject, guid1));
|
||||
|
||||
/* Clean up */
|
||||
DeleteFileA(tempfile);
|
||||
|
||||
/* Create a file with just the .cab header 'MSCF' */
|
||||
SetLastError(0xdeadbeef);
|
||||
file = CreateFileA(tempfile, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL);
|
||||
ok(file != INVALID_HANDLE_VALUE, "failed with %u\n", GetLastError());
|
||||
WriteFile(file, cabFileData, 4, &written, NULL);
|
||||
CloseHandle(file);
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
memset(&subject, 1, sizeof(GUID));
|
||||
ret = CryptSIPRetrieveSubjectGuid(tempfileW, NULL, &subject);
|
||||
ok( ret, "CryptSIPRetrieveSubjectGuid failed: %d (0x%08x)\n",
|
||||
GetLastError(), GetLastError() );
|
||||
ok ( !memcmp(&subject, &cabGUID, sizeof(GUID)),
|
||||
"Expected GUID %s for cabinet file, not %s\n", show_guid(&cabGUID, guid1), show_guid(&subject, guid2));
|
||||
|
||||
/* Clean up */
|
||||
DeleteFileA(tempfile);
|
||||
|
||||
/* Create a .cab file */
|
||||
SetLastError(0xdeadbeef);
|
||||
file = CreateFileA(tempfile, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL);
|
||||
ok(file != INVALID_HANDLE_VALUE, "failed with %u\n", GetLastError());
|
||||
WriteFile(file, cabFileData, sizeof(cabFileData), &written, NULL);
|
||||
CloseHandle(file);
|
||||
|
||||
SetLastError(0xdeadbeef);
|
||||
memset(&subject, 1, sizeof(GUID));
|
||||
ret = CryptSIPRetrieveSubjectGuid(tempfileW, NULL, &subject);
|
||||
ok( ret, "CryptSIPRetrieveSubjectGuid failed: %d (0x%08x)\n",
|
||||
GetLastError(), GetLastError() );
|
||||
ok ( !memcmp(&subject, &cabGUID, sizeof(GUID)),
|
||||
"Expected GUID %s for cabinet file, not %s\n", show_guid(&cabGUID, guid1), show_guid(&subject, guid2));
|
||||
|
||||
/* Clean up */
|
||||
DeleteFileA(tempfile);
|
||||
}
|
||||
|
||||
static void test_SIPLoad(void)
|
||||
{
|
||||
BOOL ret;
|
||||
GUID subject;
|
||||
static GUID dummySubject = { 0xdeadbeef, 0xdead, 0xbeef, { 0xde,0xad,0xbe,0xef,0xde,0xad,0xbe,0xef }};
|
||||
static GUID unknown = { 0xC689AABA, 0x8E78, 0x11D0, { 0x8C,0x47,0x00,0xC0,0x4F,0xC2,0x95,0xEE }}; /* WINTRUST.DLL */
|
||||
static GUID unknown2 = { 0xDE351A43, 0x8E59, 0x11D0, { 0x8C,0x47,0x00,0xC0,0x4F,0xC2,0x95,0xEE }}; /* WINTRUST.DLL */
|
||||
/* The next SIP is available on Windows and on Wine */
|
||||
static GUID unknown3 = { 0x000C10F1, 0x0000, 0x0000, { 0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46 }}; /* MSISIP.DLL */
|
||||
SIP_DISPATCH_INFO sdi;
|
||||
HMODULE hCrypt;
|
||||
|
||||
/* All NULL */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptSIPLoad(NULL, 0, NULL);
|
||||
ok ( !ret, "Expected CryptSIPLoad to fail\n");
|
||||
ok ( GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"Expected ERROR_INVALID_PARAMETER, got 0x%08x\n", GetLastError());
|
||||
|
||||
/* Only pSipDispatch NULL */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = CryptSIPLoad(&subject, 0, NULL);
|
||||
ok ( !ret, "Expected CryptSIPLoad to fail\n");
|
||||
ok ( GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"Expected ERROR_INVALID_PARAMETER, got 0x%08x\n", GetLastError());
|
||||
|
||||
/* No NULLs, but nonexistent pgSubject */
|
||||
SetLastError(0xdeadbeef);
|
||||
memset(&sdi, 0, sizeof(SIP_DISPATCH_INFO));
|
||||
sdi.cbSize = sizeof(SIP_DISPATCH_INFO);
|
||||
sdi.pfGet = (pCryptSIPGetSignedDataMsg)0xdeadbeef;
|
||||
ret = CryptSIPLoad(&dummySubject, 0, &sdi);
|
||||
ok ( !ret, "Expected CryptSIPLoad to fail\n");
|
||||
ok ( GetLastError() == TRUST_E_SUBJECT_FORM_UNKNOWN,
|
||||
"Expected TRUST_E_SUBJECT_FORM_UNKNOWN, got 0x%08x\n", GetLastError());
|
||||
ok( sdi.pfGet == (pCryptSIPGetSignedDataMsg)0xdeadbeef, "Expected no change to the function pointer\n");
|
||||
|
||||
hCrypt = GetModuleHandleA("crypt32.dll");
|
||||
funcCryptSIPGetSignedDataMsg = (void*)GetProcAddress(hCrypt, "CryptSIPGetSignedDataMsg");
|
||||
funcCryptSIPPutSignedDataMsg = (void*)GetProcAddress(hCrypt, "CryptSIPPutSignedDataMsg");
|
||||
funcCryptSIPCreateIndirectData = (void*)GetProcAddress(hCrypt, "CryptSIPCreateIndirectData");
|
||||
funcCryptSIPVerifyIndirectData = (void*)GetProcAddress(hCrypt, "CryptSIPVerifyIndirectData");
|
||||
funcCryptSIPRemoveSignedDataMsg = (void*)GetProcAddress(hCrypt, "CryptSIPRemoveSignedDataMsg");
|
||||
|
||||
/* All OK */
|
||||
SetLastError(0xdeadbeef);
|
||||
memset(&sdi, 0, sizeof(SIP_DISPATCH_INFO));
|
||||
sdi.cbSize = sizeof(SIP_DISPATCH_INFO);
|
||||
sdi.pfGet = (pCryptSIPGetSignedDataMsg)0xdeadbeef;
|
||||
ret = CryptSIPLoad(&unknown, 0, &sdi);
|
||||
ok ( ret, "Expected CryptSIPLoad to succeed\n");
|
||||
/* On native the last error will always be ERROR_PROC_NOT_FOUND as native searches for the function DllCanUnloadNow
|
||||
* in WINTRUST.DLL (in this case). This function is not available in WINTRUST.DLL.
|
||||
* For now there's no need to implement this is Wine as I doubt any program will rely on
|
||||
* this last error when the call succeeded.
|
||||
*/
|
||||
ok( sdi.pfGet != (pCryptSIPGetSignedDataMsg)0xdeadbeef, "Expected a function pointer to be loaded.\n");
|
||||
|
||||
/* The function addresses returned by CryptSIPLoad are actually the addresses of
|
||||
* crypt32's own functions. A function calling these addresses will end up first
|
||||
* calling crypt32 functions which in its turn call the equivalent in the SIP
|
||||
* as dictated by the given GUID.
|
||||
*/
|
||||
if (funcCryptSIPGetSignedDataMsg && funcCryptSIPPutSignedDataMsg && funcCryptSIPCreateIndirectData &&
|
||||
funcCryptSIPVerifyIndirectData && funcCryptSIPRemoveSignedDataMsg)
|
||||
ok (sdi.pfGet == funcCryptSIPGetSignedDataMsg &&
|
||||
sdi.pfPut == funcCryptSIPPutSignedDataMsg &&
|
||||
sdi.pfCreate == funcCryptSIPCreateIndirectData &&
|
||||
sdi.pfVerify == funcCryptSIPVerifyIndirectData &&
|
||||
sdi.pfRemove == funcCryptSIPRemoveSignedDataMsg,
|
||||
"Expected function addresses to be from crypt32\n");
|
||||
else
|
||||
trace("Couldn't load function pointers\n");
|
||||
|
||||
/* All OK, but different GUID (same SIP though) */
|
||||
SetLastError(0xdeadbeef);
|
||||
memset(&sdi, 0, sizeof(SIP_DISPATCH_INFO));
|
||||
sdi.cbSize = sizeof(SIP_DISPATCH_INFO);
|
||||
sdi.pfGet = (pCryptSIPGetSignedDataMsg)0xdeadbeef;
|
||||
ret = CryptSIPLoad(&unknown2, 0, &sdi);
|
||||
ok ( ret, "Expected CryptSIPLoad to succeed\n");
|
||||
/* This call on its own would have resulted in an ERROR_PROC_NOT_FOUND, but the previous
|
||||
* call to CryptSIPLoad already loaded wintrust.dll. As this information is cached,
|
||||
* CryptSIPLoad will not try to search for the already mentioned DllCanUnloadNow.
|
||||
*/
|
||||
ok( sdi.pfGet != (pCryptSIPGetSignedDataMsg)0xdeadbeef, "Expected a function pointer to be loaded.\n");
|
||||
|
||||
/* All OK, but other SIP */
|
||||
SetLastError(0xdeadbeef);
|
||||
memset(&sdi, 0, sizeof(SIP_DISPATCH_INFO));
|
||||
sdi.cbSize = sizeof(SIP_DISPATCH_INFO);
|
||||
sdi.pfGet = (pCryptSIPGetSignedDataMsg)0xdeadbeef;
|
||||
ret = CryptSIPLoad(&unknown3, 0, &sdi);
|
||||
if (ret)
|
||||
{
|
||||
/* The SIP is known so we can safely assume that the next tests can be done */
|
||||
|
||||
/* As msisip.dll is not checked yet by any of the previous calls, the
|
||||
* function DllCanUnloadNow will be checked again in msisip.dll (it's not present)
|
||||
*/
|
||||
ok( sdi.pfGet != (pCryptSIPGetSignedDataMsg)0xdeadbeef, "Expected a function pointer to be loaded.\n");
|
||||
|
||||
/* This is another SIP but this test proves the function addresses are the same as
|
||||
* in the previous test.
|
||||
*/
|
||||
if (funcCryptSIPGetSignedDataMsg && funcCryptSIPPutSignedDataMsg && funcCryptSIPCreateIndirectData &&
|
||||
funcCryptSIPVerifyIndirectData && funcCryptSIPRemoveSignedDataMsg)
|
||||
ok (sdi.pfGet == funcCryptSIPGetSignedDataMsg &&
|
||||
sdi.pfPut == funcCryptSIPPutSignedDataMsg &&
|
||||
sdi.pfCreate == funcCryptSIPCreateIndirectData &&
|
||||
sdi.pfVerify == funcCryptSIPVerifyIndirectData &&
|
||||
sdi.pfRemove == funcCryptSIPRemoveSignedDataMsg,
|
||||
"Expected function addresses to be from crypt32\n");
|
||||
else
|
||||
trace("Couldn't load function pointers\n");
|
||||
}
|
||||
|
||||
/* Reserved parameter not 0 */
|
||||
SetLastError(0xdeadbeef);
|
||||
memset(&sdi, 0, sizeof(SIP_DISPATCH_INFO));
|
||||
sdi.cbSize = sizeof(SIP_DISPATCH_INFO);
|
||||
sdi.pfGet = (pCryptSIPGetSignedDataMsg)0xdeadbeef;
|
||||
ret = CryptSIPLoad(&unknown, 1, &sdi);
|
||||
ok ( !ret, "Expected CryptSIPLoad to fail\n");
|
||||
ok ( GetLastError() == ERROR_INVALID_PARAMETER,
|
||||
"Expected ERROR_INVALID_PARAMETER, got 0x%08x\n", GetLastError());
|
||||
ok( sdi.pfGet == (pCryptSIPGetSignedDataMsg)0xdeadbeef, "Expected no change to the function pointer\n");
|
||||
}
|
||||
|
||||
START_TEST(sip)
|
||||
{
|
||||
test_AddRemoveProvider();
|
||||
/* It seems that the caching for loaded dlls is shared between CryptSIPRetrieveSubjectGUID
|
||||
* and CryptSIPLoad. The tests have to be in this order to succeed. This is because in the last
|
||||
* test for CryptSIPRetrieveSubjectGUID, several SIPs will be loaded (on Windows).
|
||||
*/
|
||||
test_SIPLoad();
|
||||
test_SIPRetrieveSubjectGUID();
|
||||
}
|
2112
rostests/winetests/crypt32/store.c
Normal file
2112
rostests/winetests/crypt32/store.c
Normal file
File diff suppressed because it is too large
Load diff
654
rostests/winetests/crypt32/str.c
Normal file
654
rostests/winetests/crypt32/str.c
Normal file
|
@ -0,0 +1,654 @@
|
|||
/*
|
||||
* Unit test suite for crypt32.dll's Cert*ToStr and CertStrToName functions.
|
||||
*
|
||||
* Copyright 2006 Juan Lang, Aric Stewart for CodeWeavers
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#include <winerror.h>
|
||||
#include <wincrypt.h>
|
||||
|
||||
#include "wine/test.h"
|
||||
|
||||
/*#define DUMP_STRINGS*/
|
||||
#ifdef DUMP_STRINGS
|
||||
#include "wine/debug.h"
|
||||
#endif
|
||||
|
||||
typedef struct _CertRDNAttrEncoding {
|
||||
LPCSTR pszObjId;
|
||||
DWORD dwValueType;
|
||||
CERT_RDN_VALUE_BLOB Value;
|
||||
LPCSTR str;
|
||||
} CertRDNAttrEncoding, *PCertRDNAttrEncoding;
|
||||
|
||||
typedef struct _CertRDNAttrEncodingW {
|
||||
LPCSTR pszObjId;
|
||||
DWORD dwValueType;
|
||||
CERT_RDN_VALUE_BLOB Value;
|
||||
LPCWSTR str;
|
||||
} CertRDNAttrEncodingW, *PCertRDNAttrEncodingW;
|
||||
|
||||
static BYTE bin1[] = { 0x55, 0x53 };
|
||||
static BYTE bin2[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f, 0x74,
|
||||
0x61 };
|
||||
static BYTE bin3[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70, 0x6f,
|
||||
0x6c, 0x69, 0x73 };
|
||||
static BYTE bin4[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61, 0x76,
|
||||
0x65, 0x72, 0x73 };
|
||||
static BYTE bin5[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
|
||||
0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
|
||||
static BYTE bin6[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73,
|
||||
0x74 };
|
||||
static BYTE bin7[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
|
||||
0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
|
||||
|
||||
static const BYTE cert[] =
|
||||
{0x30,0x82,0x2,0xbb,0x30,0x82,0x2,0x24,0x2,0x9,0x0,0xe3,0x5a,0x10,0xf1,0xfc,
|
||||
0x4b,0xf3,0xa2,0x30,0xd,0x6,0x9,0x2a,0x86,0x48,0x86,0xf7,0xd,0x1,0x1,0x4,0x5,
|
||||
0x0,0x30,0x81,0xa1,0x31,0xb,0x30,0x9,0x6,0x3,0x55,0x4,0x6,0x13,0x2,0x55,0x53,
|
||||
0x31,0x12,0x30,0x10,0x6,0x3,0x55,0x4,0x8,0x13,0x9,0x4d,0x69,0x6e,0x6e,0x65,
|
||||
0x73,0x6f,0x74,0x61,0x31,0x14,0x30,0x12,0x6,0x3,0x55,0x4,0x7,0x13,0xb,0x4d,
|
||||
0x69,0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x31,0x14,0x30,0x12,0x6,0x3,
|
||||
0x55,0x4,0xa,0x13,0xb,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,
|
||||
0x31,0x19,0x30,0x17,0x6,0x3,0x55,0x4,0xb,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,
|
||||
0x44,0x65,0x76,0x65,0x6c,0x6f,0x70,0x6d,0x65,0x6e,0x74,0x31,0x12,0x30,0x10,
|
||||
0x6,0x3,0x55,0x4,0x3,0x13,0x9,0x6c,0x6f,0x63,0x61,0x6c,0x68,0x6f,0x73,0x74,
|
||||
0x31,0x23,0x30,0x21,0x6,0x9,0x2a,0x86,0x48,0x86,0xf7,0xd,0x1,0x9,0x1,0x16,
|
||||
0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,0x61,0x76,0x65,
|
||||
0x72,0x73,0x2e,0x63,0x6f,0x6d,0x30,0x1e,0x17,0xd,0x30,0x36,0x30,0x31,0x32,
|
||||
0x35,0x31,0x33,0x35,0x37,0x32,0x34,0x5a,0x17,0xd,0x30,0x36,0x30,0x32,0x32,
|
||||
0x34,0x31,0x33,0x35,0x37,0x32,0x34,0x5a,0x30,0x81,0xa1,0x31,0xb,0x30,0x9,0x6,
|
||||
0x3,0x55,0x4,0x6,0x13,0x2,0x55,0x53,0x31,0x12,0x30,0x10,0x6,0x3,0x55,0x4,0x8,
|
||||
0x13,0x9,0x4d,0x69,0x6e,0x6e,0x65,0x73,0x6f,0x74,0x61,0x31,0x14,0x30,0x12,0x6,
|
||||
0x3,0x55,0x4,0x7,0x13,0xb,0x4d,0x69,0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,
|
||||
0x73,0x31,0x14,0x30,0x12,0x6,0x3,0x55,0x4,0xa,0x13,0xb,0x43,0x6f,0x64,0x65,
|
||||
0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x31,0x19,0x30,0x17,0x6,0x3,0x55,0x4,0xb,
|
||||
0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,0x6f,0x70,0x6d,
|
||||
0x65,0x6e,0x74,0x31,0x12,0x30,0x10,0x6,0x3,0x55,0x4,0x3,0x13,0x9,0x6c,0x6f,
|
||||
0x63,0x61,0x6c,0x68,0x6f,0x73,0x74,0x31,0x23,0x30,0x21,0x6,0x9,0x2a,0x86,0x48,
|
||||
0x86,0xf7,0xd,0x1,0x9,0x1,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,
|
||||
0x65,0x77,0x65,0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d,0x30,0x81,0x9f,
|
||||
0x30,0xd,0x6,0x9,0x2a,0x86,0x48,0x86,0xf7,0xd,0x1,0x1,0x1,0x5,0x0,0x3,0x81,
|
||||
0x8d,0x0,0x30,0x81,0x89,0x2,0x81,0x81,0x0,0x9b,0xb5,0x8f,0xaf,0xfb,0x9a,0xaf,
|
||||
0xdc,0xa2,0x4d,0xb1,0xc8,0x72,0x44,0xef,0x79,0x7f,0x28,0xb6,0xfe,0x50,0xdc,
|
||||
0x8a,0xf7,0x11,0x2f,0x90,0x70,0xed,0xa4,0xa9,0xd,0xbf,0x82,0x3e,0x56,0xd8,
|
||||
0x36,0xb6,0x9,0x52,0x83,0xab,0x65,0x95,0x0,0xe2,0xea,0x3c,0x4f,0x85,0xb8,0xc,
|
||||
0x41,0x42,0x77,0x5c,0x9d,0x44,0xeb,0xcf,0x7d,0x60,0x64,0x7a,0x6c,0x4c,0xac,
|
||||
0x4a,0x9a,0x23,0x25,0x15,0xd7,0x92,0xb4,0x10,0xe7,0x95,0xad,0x4b,0x93,0xda,
|
||||
0x6a,0x76,0xe0,0xa5,0xd2,0x13,0x8,0x12,0x30,0x68,0xde,0xb9,0x5b,0x6e,0x2a,
|
||||
0x97,0x43,0xaa,0x7b,0x22,0x33,0x34,0xb1,0xca,0x5d,0x19,0xd8,0x42,0x26,0x45,
|
||||
0xc6,0xe9,0x1d,0xee,0x7,0xc2,0x27,0x95,0x87,0xd8,0x12,0xec,0x4b,0x16,0x9f,0x2,
|
||||
0x3,0x1,0x0,0x1,0x30,0xd,0x6,0x9,0x2a,0x86,0x48,0x86,0xf7,0xd,0x1,0x1,0x4,0x5,
|
||||
0x0,0x3,0x81,0x81,0x0,0x96,0xf9,0xf6,0x6a,0x3d,0xd9,0xca,0x6e,0xd5,0x76,0x73,
|
||||
0xab,0x75,0xc1,0xcc,0x98,0x44,0xc3,0xa9,0x90,0x68,0x88,0x76,0xb9,0xeb,0xb6,
|
||||
0xbe,0x60,0x62,0xb9,0x67,0x1e,0xcc,0xf4,0xe1,0xe7,0x6c,0xc8,0x67,0x3f,0x1d,
|
||||
0xf3,0x68,0x86,0x30,0xee,0xaa,0x92,0x61,0x37,0xd7,0x82,0x90,0x28,0xaa,0x7a,
|
||||
0x18,0x88,0x60,0x14,0x88,0x75,0xc0,0x4a,0x4e,0x7d,0x48,0xe7,0x3,0xa6,0xfd,
|
||||
0xd7,0xce,0x3c,0xe5,0x9b,0xaf,0x2f,0xdc,0xbb,0x7c,0xbd,0x20,0x49,0xd9,0x68,
|
||||
0x37,0xeb,0x5d,0xbb,0xe2,0x6d,0x66,0xe3,0x11,0xc1,0xa7,0x88,0x49,0xc6,0x6f,
|
||||
0x65,0xd3,0xce,0xae,0x26,0x19,0x3,0x2e,0x4f,0x78,0xa5,0xa,0x97,0x7e,0x4f,0xc4,
|
||||
0x91,0x8a,0xf8,0x5,0xef,0x5b,0x3b,0x49,0xbf,0x5f,0x2b};
|
||||
|
||||
static char issuerStr[] =
|
||||
"US, Minnesota, Minneapolis, CodeWeavers, Wine Development, localhost, aric@codeweavers.com";
|
||||
static char issuerStrSemicolon[] =
|
||||
"US; Minnesota; Minneapolis; CodeWeavers; Wine Development; localhost; aric@codeweavers.com";
|
||||
static char issuerStrCRLF[] =
|
||||
"US\r\nMinnesota\r\nMinneapolis\r\nCodeWeavers\r\nWine Development\r\nlocalhost\r\naric@codeweavers.com";
|
||||
static char subjectStr[] =
|
||||
"2.5.4.6=US, 2.5.4.8=Minnesota, 2.5.4.7=Minneapolis, 2.5.4.10=CodeWeavers, 2.5.4.11=Wine Development, 2.5.4.3=localhost, 1.2.840.113549.1.9.1=aric@codeweavers.com";
|
||||
static char subjectStrSemicolon[] =
|
||||
"2.5.4.6=US; 2.5.4.8=Minnesota; 2.5.4.7=Minneapolis; 2.5.4.10=CodeWeavers; 2.5.4.11=Wine Development; 2.5.4.3=localhost; 1.2.840.113549.1.9.1=aric@codeweavers.com";
|
||||
static char subjectStrCRLF[] =
|
||||
"2.5.4.6=US\r\n2.5.4.8=Minnesota\r\n2.5.4.7=Minneapolis\r\n2.5.4.10=CodeWeavers\r\n2.5.4.11=Wine Development\r\n2.5.4.3=localhost\r\n1.2.840.113549.1.9.1=aric@codeweavers.com";
|
||||
static char x500SubjectStr[] = "C=US, S=Minnesota, L=Minneapolis, O=CodeWeavers, OU=Wine Development, CN=localhost, E=aric@codeweavers.com";
|
||||
static char x500SubjectStrSemicolonReverse[] = "E=aric@codeweavers.com; CN=localhost; OU=Wine Development; O=CodeWeavers; L=Minneapolis; S=Minnesota; C=US";
|
||||
static WCHAR issuerStrW[] = {
|
||||
'U','S',',',' ','M','i','n','n','e','s','o','t','a',',',' ','M','i','n','n',
|
||||
'e','a','p','o','l','i','s',',',' ','C','o','d','e','W','e','a','v','e','r',
|
||||
's',',',' ','W','i','n','e',' ','D','e','v','e','l','o','p','m','e','n','t',
|
||||
',',' ','l','o','c','a','l','h','o','s','t',',',' ','a','r','i','c','@','c',
|
||||
'o','d','e','w','e','a','v','e','r','s','.','c','o','m',0 };
|
||||
static WCHAR issuerStrSemicolonW[] = {
|
||||
'U','S',';',' ','M','i','n','n','e','s','o','t','a',';',' ','M','i','n','n',
|
||||
'e','a','p','o','l','i','s',';',' ','C','o','d','e','W','e','a','v','e','r',
|
||||
's',';',' ','W','i','n','e',' ','D','e','v','e','l','o','p','m','e','n','t',
|
||||
';',' ','l','o','c','a','l','h','o','s','t',';',' ','a','r','i','c','@','c',
|
||||
'o','d','e','w','e','a','v','e','r','s','.','c','o','m',0 };
|
||||
static WCHAR issuerStrCRLFW[] = {
|
||||
'U','S','\r','\n','M','i','n','n','e','s','o','t','a','\r','\n','M','i','n',
|
||||
'n','e','a','p','o','l','i','s','\r','\n','C','o','d','e','W','e','a','v','e',
|
||||
'r','s','\r','\n','W','i','n','e',' ','D','e','v','e','l','o','p','m','e','n',
|
||||
't','\r','\n','l','o','c','a','l','h','o','s','t','\r','\n','a','r','i','c',
|
||||
'@','c','o','d','e','w','e','a','v','e','r','s','.','c','o','m',0 };
|
||||
static WCHAR subjectStrW[] = {
|
||||
'2','.','5','.','4','.','6','=','U','S',',',' ','2','.','5','.','4','.','8',
|
||||
'=','M','i','n','n','e','s','o','t','a',',',' ','2','.','5','.','4','.','7',
|
||||
'=','M','i','n','n','e','a','p','o','l','i','s',',',' ','2','.','5','.','4',
|
||||
'.','1','0','=','C','o','d','e','W','e','a','v','e','r','s',',',' ','2','.',
|
||||
'5','.','4','.','1','1','=','W','i','n','e',' ','D','e','v','e','l','o','p',
|
||||
'm','e','n','t',',',' ','2','.','5','.','4','.','3','=','l','o','c','a','l',
|
||||
'h','o','s','t',',',' ','1','.','2','.','8','4','0','.','1','1','3','5','4',
|
||||
'9','.','1','.','9','.','1','=','a','r','i','c','@','c','o','d','e','w','e',
|
||||
'a','v','e','r','s','.','c','o','m',0 };
|
||||
static WCHAR subjectStrSemicolonW[] = {
|
||||
'2','.','5','.','4','.','6','=','U','S',';',' ','2','.','5','.','4','.','8',
|
||||
'=','M','i','n','n','e','s','o','t','a',';',' ','2','.','5','.','4','.','7',
|
||||
'=','M','i','n','n','e','a','p','o','l','i','s',';',' ','2','.','5','.','4',
|
||||
'.','1','0','=','C','o','d','e','W','e','a','v','e','r','s',';',' ','2','.',
|
||||
'5','.','4','.','1','1','=','W','i','n','e',' ','D','e','v','e','l','o','p',
|
||||
'm','e','n','t',';',' ','2','.','5','.','4','.','3','=','l','o','c','a','l',
|
||||
'h','o','s','t',';',' ','1','.','2','.','8','4','0','.','1','1','3','5','4',
|
||||
'9','.','1','.','9','.','1','=','a','r','i','c','@','c','o','d','e','w','e',
|
||||
'a','v','e','r','s','.','c','o','m',0 };
|
||||
static WCHAR subjectStrCRLFW[] = {
|
||||
'2','.','5','.','4','.','6','=','U','S','\r','\n','2','.','5','.','4','.','8',
|
||||
'=','M','i','n','n','e','s','o','t','a','\r','\n','2','.','5','.','4','.','7',
|
||||
'=','M','i','n','n','e','a','p','o','l','i','s','\r','\n','2','.','5','.','4',
|
||||
'.','1','0','=','C','o','d','e','W','e','a','v','e','r','s','\r','\n','2','.',
|
||||
'5','.','4','.','1','1','=','W','i','n','e',' ','D','e','v','e','l','o','p',
|
||||
'm','e','n','t','\r','\n','2','.','5','.','4','.','3','=','l','o','c','a','l',
|
||||
'h','o','s','t','\r','\n','1','.','2','.','8','4','0','.','1','1','3','5','4',
|
||||
'9','.','1','.','9','.','1','=','a','r','i','c','@','c','o','d','e','w','e',
|
||||
'a','v','e','r','s','.','c','o','m',0 };
|
||||
static WCHAR x500SubjectStrSemicolonReverseW[] = {
|
||||
'E','=','a','r','i','c','@','c','o','d','e','w','e','a','v','e','r','s','.','c',
|
||||
'o','m',';',' ','C','N','=','l','o','c','a','l','h','o','s','t',';',' ','O','U',
|
||||
'=','W','i','n','e',' ','D','e','v','e','l','o','p','m','e','n','t',';',' ','O',
|
||||
'=','C','o','d','e','W','e','a','v','e','r','s',';',' ','L','=','M','i','n','n',
|
||||
'e','a','p','o','l','i','s',';',' ','S','=','M','i','n','n','e','s','o','t','a',
|
||||
';',' ','C','=','U','S',0 };
|
||||
|
||||
typedef BOOL (WINAPI *CryptDecodeObjectFunc)(DWORD, LPCSTR, const BYTE *,
|
||||
DWORD, DWORD, void *, DWORD *);
|
||||
typedef DWORD (WINAPI *CertNameToStrAFunc)(DWORD,LPVOID,DWORD,LPSTR,DWORD);
|
||||
typedef DWORD (WINAPI *CertNameToStrWFunc)(DWORD,LPVOID,DWORD,LPWSTR,DWORD);
|
||||
typedef DWORD (WINAPI *CertRDNValueToStrAFunc)(DWORD, PCERT_RDN_VALUE_BLOB,
|
||||
LPSTR, DWORD);
|
||||
typedef DWORD (WINAPI *CertRDNValueToStrWFunc)(DWORD, PCERT_RDN_VALUE_BLOB,
|
||||
LPWSTR, DWORD);
|
||||
typedef BOOL (WINAPI *CertStrToNameAFunc)(DWORD dwCertEncodingType,
|
||||
LPCSTR pszX500, DWORD dwStrType, void *pvReserved, BYTE *pbEncoded,
|
||||
DWORD *pcbEncoded, LPCSTR *ppszError);
|
||||
typedef BOOL (WINAPI *CertStrToNameWFunc)(DWORD dwCertEncodingType,
|
||||
LPCWSTR pszX500, DWORD dwStrType, void *pvReserved, BYTE *pbEncoded,
|
||||
DWORD *pcbEncoded, LPCWSTR *ppszError);
|
||||
|
||||
HMODULE dll;
|
||||
static CertNameToStrAFunc pCertNameToStrA;
|
||||
static CertNameToStrWFunc pCertNameToStrW;
|
||||
static CryptDecodeObjectFunc pCryptDecodeObject;
|
||||
static CertRDNValueToStrAFunc pCertRDNValueToStrA;
|
||||
static CertRDNValueToStrWFunc pCertRDNValueToStrW;
|
||||
static CertStrToNameAFunc pCertStrToNameA;
|
||||
static CertStrToNameWFunc pCertStrToNameW;
|
||||
|
||||
static void test_CertRDNValueToStrA(void)
|
||||
{
|
||||
CertRDNAttrEncoding attrs[] = {
|
||||
{ "2.5.4.6", CERT_RDN_PRINTABLE_STRING,
|
||||
{ sizeof(bin1), (PBYTE)bin1 }, "US" },
|
||||
{ "2.5.4.8", CERT_RDN_PRINTABLE_STRING,
|
||||
{ sizeof(bin2), (PBYTE)bin2 }, "Minnesota" },
|
||||
{ "2.5.4.7", CERT_RDN_PRINTABLE_STRING,
|
||||
{ sizeof(bin3), (PBYTE)bin3 }, "Minneapolis" },
|
||||
{ "2.5.4.10", CERT_RDN_PRINTABLE_STRING,
|
||||
{ sizeof(bin4), (PBYTE)bin4 }, "CodeWeavers" },
|
||||
{ "2.5.4.11", CERT_RDN_PRINTABLE_STRING,
|
||||
{ sizeof(bin5), (PBYTE)bin5 }, "Wine Development" },
|
||||
{ "2.5.4.3", CERT_RDN_PRINTABLE_STRING,
|
||||
{ sizeof(bin6), (PBYTE)bin6 }, "localhost" },
|
||||
{ "1.2.840.113549.1.9.1", CERT_RDN_IA5_STRING,
|
||||
{ sizeof(bin7), (PBYTE)bin7 }, "aric@codeweavers.com" },
|
||||
};
|
||||
DWORD i, ret;
|
||||
char buffer[2000];
|
||||
CERT_RDN_VALUE_BLOB blob = { 0, NULL };
|
||||
|
||||
if (!pCertRDNValueToStrA) return;
|
||||
|
||||
/* This crashes
|
||||
ret = pCertRDNValueToStrA(0, NULL, NULL, 0);
|
||||
*/
|
||||
/* With empty input, it generates the empty string */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pCertRDNValueToStrA(0, &blob, NULL, 0);
|
||||
ok(ret == 1 && GetLastError() == 0xdeadbeef, "Expected empty string\n");
|
||||
ret = pCertRDNValueToStrA(0, &blob, buffer, sizeof(buffer));
|
||||
ok(ret == 1 && GetLastError() == 0xdeadbeef, "Expected empty string\n");
|
||||
ok(!buffer[0], "Expected empty string\n");
|
||||
|
||||
for (i = 0; i < sizeof(attrs) / sizeof(attrs[0]); i++)
|
||||
{
|
||||
ret = pCertRDNValueToStrA(attrs[i].dwValueType, &attrs[i].Value,
|
||||
buffer, sizeof(buffer));
|
||||
ok(ret == strlen(attrs[i].str) + 1, "Expected length %d, got %d\n",
|
||||
lstrlenA(attrs[i].str) + 1, ret);
|
||||
ok(!strcmp(buffer, attrs[i].str), "Expected %s, got %s\n", attrs[i].str,
|
||||
buffer);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_CertRDNValueToStrW(void)
|
||||
{
|
||||
static const WCHAR usW[] = { 'U','S',0 };
|
||||
static const WCHAR minnesotaW[] = { 'M','i','n','n','e','s','o','t','a',0 };
|
||||
static const WCHAR minneapolisW[] = { 'M','i','n','n','e','a','p','o','l',
|
||||
'i','s',0 };
|
||||
static const WCHAR codeweaversW[] = { 'C','o','d','e','W','e','a','v','e',
|
||||
'r','s',0 };
|
||||
static const WCHAR wineDevW[] = { 'W','i','n','e',' ','D','e','v','e','l',
|
||||
'o','p','m','e','n','t',0 };
|
||||
static const WCHAR localhostW[] = { 'l','o','c','a','l','h','o','s','t',0 };
|
||||
static const WCHAR aricW[] = { 'a','r','i','c','@','c','o','d','e','w','e',
|
||||
'a','v','e','r','s','.','c','o','m',0 };
|
||||
CertRDNAttrEncodingW attrs[] = {
|
||||
{ "2.5.4.6", CERT_RDN_PRINTABLE_STRING,
|
||||
{ sizeof(bin1), (PBYTE)bin1 }, usW },
|
||||
{ "2.5.4.8", CERT_RDN_PRINTABLE_STRING,
|
||||
{ sizeof(bin2), (PBYTE)bin2 }, minnesotaW },
|
||||
{ "2.5.4.7", CERT_RDN_PRINTABLE_STRING,
|
||||
{ sizeof(bin3), (PBYTE)bin3 }, minneapolisW },
|
||||
{ "2.5.4.10", CERT_RDN_PRINTABLE_STRING,
|
||||
{ sizeof(bin4), (PBYTE)bin4 }, codeweaversW },
|
||||
{ "2.5.4.11", CERT_RDN_PRINTABLE_STRING,
|
||||
{ sizeof(bin5), (PBYTE)bin5 }, wineDevW },
|
||||
{ "2.5.4.3", CERT_RDN_PRINTABLE_STRING,
|
||||
{ sizeof(bin6), (PBYTE)bin6 }, localhostW },
|
||||
{ "1.2.840.113549.1.9.1", CERT_RDN_IA5_STRING,
|
||||
{ sizeof(bin7), (PBYTE)bin7 }, aricW },
|
||||
};
|
||||
DWORD i, ret;
|
||||
WCHAR buffer[2000];
|
||||
CERT_RDN_VALUE_BLOB blob = { 0, NULL };
|
||||
|
||||
if (!pCertRDNValueToStrW)
|
||||
{
|
||||
skip("CertRDNValueToStrW is not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* This crashes
|
||||
ret = pCertRDNValueToStrW(0, NULL, NULL, 0);
|
||||
*/
|
||||
/* With empty input, it generates the empty string */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pCertRDNValueToStrW(0, &blob, NULL, 0);
|
||||
ok(ret == 1 && GetLastError() == 0xdeadbeef, "Expected empty string\n");
|
||||
ret = pCertRDNValueToStrW(0, &blob, buffer,
|
||||
sizeof(buffer) / sizeof(buffer[0]));
|
||||
ok(ret == 1 && GetLastError() == 0xdeadbeef, "Expected empty string\n");
|
||||
ok(!buffer[0], "Expected empty string\n");
|
||||
|
||||
for (i = 0; i < sizeof(attrs) / sizeof(attrs[0]); i++)
|
||||
{
|
||||
ret = pCertRDNValueToStrW(attrs[i].dwValueType, &attrs[i].Value,
|
||||
buffer, sizeof(buffer) / sizeof(buffer[0]));
|
||||
ok(ret == lstrlenW(attrs[i].str) + 1, "Expected length %d, got %d\n",
|
||||
lstrlenW(attrs[i].str) + 1, ret);
|
||||
ok(!lstrcmpW(buffer, attrs[i].str), "Unexpected value\n");
|
||||
#ifdef DUMP_STRINGS
|
||||
trace("Expected %s, got %s\n",
|
||||
wine_dbgstr_w(attrs[i].str), wine_dbgstr_w(buffer));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void test_NameToStrConversionA(PCERT_NAME_BLOB pName, DWORD dwStrType,
|
||||
LPCSTR expected)
|
||||
{
|
||||
char buffer[2000] = { 0 };
|
||||
DWORD i;
|
||||
|
||||
i = pCertNameToStrA(X509_ASN_ENCODING, pName, dwStrType, NULL, 0);
|
||||
ok(i == strlen(expected) + 1, "Expected %d chars, got %d\n",
|
||||
lstrlenA(expected) + 1, i);
|
||||
i = pCertNameToStrA(X509_ASN_ENCODING,pName, dwStrType, buffer,
|
||||
sizeof(buffer));
|
||||
ok(i == strlen(expected) + 1, "Expected %d chars, got %d\n",
|
||||
lstrlenA(expected) + 1, i);
|
||||
ok(!strcmp(buffer, expected), "Expected %s, got %s\n", expected, buffer);
|
||||
}
|
||||
|
||||
static void test_CertNameToStrA(void)
|
||||
{
|
||||
PCCERT_CONTEXT context;
|
||||
|
||||
if (!pCertNameToStrA)
|
||||
{
|
||||
skip("CertNameToStrA is not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
context = CertCreateCertificateContext(X509_ASN_ENCODING, cert,
|
||||
sizeof(cert));
|
||||
ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
|
||||
GetLastError());
|
||||
if (context)
|
||||
{
|
||||
DWORD ret;
|
||||
|
||||
/* This crashes
|
||||
ret = pCertNameToStrA(0, NULL, 0, NULL, 0);
|
||||
*/
|
||||
/* Test with a bogus encoding type */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pCertNameToStrA(0, &context->pCertInfo->Issuer, 0, NULL, 0);
|
||||
ok(ret == 1 && GetLastError() == ERROR_FILE_NOT_FOUND,
|
||||
"Expected retval 1 and ERROR_FILE_NOT_FOUND, got %d - %08x\n",
|
||||
ret, GetLastError());
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pCertNameToStrA(X509_ASN_ENCODING, &context->pCertInfo->Issuer,
|
||||
0, NULL, 0);
|
||||
ok(ret && GetLastError() == ERROR_SUCCESS,
|
||||
"Expected positive return and ERROR_SUCCESS, got %d - %08x\n",
|
||||
ret, GetLastError());
|
||||
|
||||
test_NameToStrConversionA(&context->pCertInfo->Issuer,
|
||||
CERT_SIMPLE_NAME_STR, issuerStr);
|
||||
test_NameToStrConversionA(&context->pCertInfo->Issuer,
|
||||
CERT_SIMPLE_NAME_STR | CERT_NAME_STR_SEMICOLON_FLAG,
|
||||
issuerStrSemicolon);
|
||||
test_NameToStrConversionA(&context->pCertInfo->Issuer,
|
||||
CERT_SIMPLE_NAME_STR | CERT_NAME_STR_CRLF_FLAG,
|
||||
issuerStrCRLF);
|
||||
test_NameToStrConversionA(&context->pCertInfo->Subject,
|
||||
CERT_OID_NAME_STR, subjectStr);
|
||||
test_NameToStrConversionA(&context->pCertInfo->Subject,
|
||||
CERT_OID_NAME_STR | CERT_NAME_STR_SEMICOLON_FLAG,
|
||||
subjectStrSemicolon);
|
||||
test_NameToStrConversionA(&context->pCertInfo->Subject,
|
||||
CERT_OID_NAME_STR | CERT_NAME_STR_CRLF_FLAG,
|
||||
subjectStrCRLF);
|
||||
test_NameToStrConversionA(&context->pCertInfo->Subject,
|
||||
CERT_X500_NAME_STR, x500SubjectStr);
|
||||
test_NameToStrConversionA(&context->pCertInfo->Subject,
|
||||
CERT_X500_NAME_STR | CERT_NAME_STR_SEMICOLON_FLAG | CERT_NAME_STR_REVERSE_FLAG, x500SubjectStrSemicolonReverse);
|
||||
|
||||
CertFreeCertificateContext(context);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_NameToStrConversionW(PCERT_NAME_BLOB pName, DWORD dwStrType,
|
||||
LPCWSTR expected)
|
||||
{
|
||||
WCHAR buffer[2000] = { 0 };
|
||||
DWORD i;
|
||||
|
||||
i = pCertNameToStrW(X509_ASN_ENCODING,pName, dwStrType, NULL, 0);
|
||||
ok(i == lstrlenW(expected) + 1, "Expected %d chars, got %d\n",
|
||||
lstrlenW(expected) + 1, i);
|
||||
i = pCertNameToStrW(X509_ASN_ENCODING,pName, dwStrType, buffer,
|
||||
sizeof(buffer) / sizeof(buffer[0]));
|
||||
ok(i == lstrlenW(expected) + 1, "Expected %d chars, got %d\n",
|
||||
lstrlenW(expected) + 1, i);
|
||||
ok(!lstrcmpW(buffer, expected), "Unexpected value\n");
|
||||
#ifdef DUMP_STRINGS
|
||||
trace("Expected %s, got %s\n",
|
||||
wine_dbgstr_w(expected), wine_dbgstr_w(buffer));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void test_CertNameToStrW(void)
|
||||
{
|
||||
PCCERT_CONTEXT context;
|
||||
|
||||
if (!pCertNameToStrW)
|
||||
{
|
||||
skip("CertNameToStrW is not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
context = CertCreateCertificateContext(X509_ASN_ENCODING, cert,
|
||||
sizeof(cert));
|
||||
ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
|
||||
GetLastError());
|
||||
if (context)
|
||||
{
|
||||
DWORD ret;
|
||||
|
||||
/* This crashes
|
||||
ret = pCertNameToStrW(0, NULL, 0, NULL, 0);
|
||||
*/
|
||||
/* Test with a bogus encoding type */
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pCertNameToStrW(0, &context->pCertInfo->Issuer, 0, NULL, 0);
|
||||
ok(ret == 1 && GetLastError() == ERROR_FILE_NOT_FOUND,
|
||||
"Expected retval 1 and ERROR_FILE_NOT_FOUND, got %d - %08x\n",
|
||||
ret, GetLastError());
|
||||
SetLastError(0xdeadbeef);
|
||||
ret = pCertNameToStrW(X509_ASN_ENCODING, &context->pCertInfo->Issuer,
|
||||
0, NULL, 0);
|
||||
ok(ret && GetLastError() == ERROR_SUCCESS,
|
||||
"Expected positive return and ERROR_SUCCESS, got %d - %08x\n",
|
||||
ret, GetLastError());
|
||||
|
||||
test_NameToStrConversionW(&context->pCertInfo->Issuer,
|
||||
CERT_SIMPLE_NAME_STR, issuerStrW);
|
||||
test_NameToStrConversionW(&context->pCertInfo->Issuer,
|
||||
CERT_SIMPLE_NAME_STR | CERT_NAME_STR_SEMICOLON_FLAG,
|
||||
issuerStrSemicolonW);
|
||||
test_NameToStrConversionW(&context->pCertInfo->Issuer,
|
||||
CERT_SIMPLE_NAME_STR | CERT_NAME_STR_CRLF_FLAG,
|
||||
issuerStrCRLFW);
|
||||
test_NameToStrConversionW(&context->pCertInfo->Subject,
|
||||
CERT_OID_NAME_STR, subjectStrW);
|
||||
test_NameToStrConversionW(&context->pCertInfo->Subject,
|
||||
CERT_OID_NAME_STR | CERT_NAME_STR_SEMICOLON_FLAG,
|
||||
subjectStrSemicolonW);
|
||||
test_NameToStrConversionW(&context->pCertInfo->Subject,
|
||||
CERT_OID_NAME_STR | CERT_NAME_STR_CRLF_FLAG,
|
||||
subjectStrCRLFW);
|
||||
test_NameToStrConversionW(&context->pCertInfo->Subject,
|
||||
CERT_X500_NAME_STR | CERT_NAME_STR_SEMICOLON_FLAG | CERT_NAME_STR_REVERSE_FLAG, x500SubjectStrSemicolonReverseW);
|
||||
|
||||
CertFreeCertificateContext(context);
|
||||
}
|
||||
}
|
||||
|
||||
struct StrToNameA
|
||||
{
|
||||
LPCSTR x500;
|
||||
DWORD encodedSize;
|
||||
const BYTE *encoded;
|
||||
};
|
||||
|
||||
const BYTE encodedSimpleCN[] = {
|
||||
0x30,0x0c,0x31,0x0a,0x30,0x08,0x06,0x03,0x55,0x04,0x03,0x13,0x01,0x31 };
|
||||
static const BYTE encodedSingleQuotedCN[] = { 0x30,0x0e,0x31,0x0c,0x30,0x0a,
|
||||
0x06,0x03,0x55,0x04,0x03,0x13,0x03,0x27,0x31,0x27 };
|
||||
static const BYTE encodedSpacedCN[] = { 0x30,0x0e,0x31,0x0c,0x30,0x0a,0x06,0x03,
|
||||
0x55,0x04,0x03,0x13,0x03,0x20,0x31,0x20 };
|
||||
static const BYTE encodedQuotedCN[] = { 0x30,0x11,0x31,0x0f,0x30,0x0d,0x06,0x03,
|
||||
0x55, 0x04,0x03,0x1e,0x06,0x00,0x22,0x00,0x31,0x00,0x22, };
|
||||
static const BYTE encodedMultipleAttrCN[] = { 0x30,0x0e,0x31,0x0c,0x30,0x0a,
|
||||
0x06,0x03,0x55,0x04,0x03,0x13,0x03,0x31,0x2b,0x32 };
|
||||
|
||||
struct StrToNameA namesA[] = {
|
||||
{ "CN=1", sizeof(encodedSimpleCN), encodedSimpleCN },
|
||||
{ "CN=\"1\"", sizeof(encodedSimpleCN), encodedSimpleCN },
|
||||
{ "CN = \"1\"", sizeof(encodedSimpleCN), encodedSimpleCN },
|
||||
{ "CN='1'", sizeof(encodedSingleQuotedCN), encodedSingleQuotedCN },
|
||||
{ "CN=\" 1 \"", sizeof(encodedSpacedCN), encodedSpacedCN },
|
||||
{ "CN=\"\"\"1\"\"\"", sizeof(encodedQuotedCN), encodedQuotedCN },
|
||||
{ "CN=\"1+2\"", sizeof(encodedMultipleAttrCN), encodedMultipleAttrCN },
|
||||
};
|
||||
|
||||
static void test_CertStrToNameA(void)
|
||||
{
|
||||
BOOL ret;
|
||||
DWORD size, i;
|
||||
BYTE buf[100];
|
||||
|
||||
if (!pCertStrToNameA)
|
||||
{
|
||||
skip("CertStrToNameA is not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Crash
|
||||
ret = pCertStrToNameA(0, NULL, 0, NULL, NULL, NULL, NULL);
|
||||
*/
|
||||
ret = pCertStrToNameA(0, NULL, 0, NULL, NULL, &size, NULL);
|
||||
ok(!ret, "Expected failure\n");
|
||||
ret = pCertStrToNameA(0, "bogus", 0, NULL, NULL, &size, NULL);
|
||||
ok(!ret && GetLastError() == CRYPT_E_INVALID_X500_STRING,
|
||||
"Expected CRYPT_E_INVALID_X500_STRING, got %08x\n", GetLastError());
|
||||
ret = pCertStrToNameA(0, "foo=1", 0, NULL, NULL, &size, NULL);
|
||||
ok(!ret && GetLastError() == CRYPT_E_INVALID_X500_STRING,
|
||||
"Expected CRYPT_E_INVALID_X500_STRING, got %08x\n", GetLastError());
|
||||
ret = pCertStrToNameA(0, "CN=1", 0, NULL, NULL, &size, NULL);
|
||||
ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
|
||||
"Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
|
||||
ret = pCertStrToNameA(X509_ASN_ENCODING, "CN=1", 0, NULL, NULL, &size, NULL);
|
||||
ok(ret, "CertStrToNameA failed: %08x\n", GetLastError());
|
||||
size = sizeof(buf);
|
||||
ret = pCertStrToNameA(X509_ASN_ENCODING, "CN=\"\"1\"\"", 0, NULL, buf, &size,
|
||||
NULL);
|
||||
ok(!ret && GetLastError() == CRYPT_E_INVALID_X500_STRING,
|
||||
"Expected CRYPT_E_INVALID_X500_STRING, got %08x\n", GetLastError());
|
||||
ret = pCertStrToNameA(X509_ASN_ENCODING, "CN=1+2", 0, NULL, buf,
|
||||
&size, NULL);
|
||||
todo_wine ok(!ret && GetLastError() == CRYPT_E_INVALID_X500_STRING,
|
||||
"Expected CRYPT_E_INVALID_X500_STRING, got %08x\n", GetLastError());
|
||||
for (i = 0; i < sizeof(namesA) / sizeof(namesA[0]); i++)
|
||||
{
|
||||
size = sizeof(buf);
|
||||
ret = pCertStrToNameA(X509_ASN_ENCODING, namesA[i].x500, 0, NULL, buf,
|
||||
&size, NULL);
|
||||
ok(ret, "CertStrToNameA failed on string %s: %08x\n", namesA[i].x500,
|
||||
GetLastError());
|
||||
ok(size == namesA[i].encodedSize,
|
||||
"Expected size %d, got %d\n", namesA[i].encodedSize, size);
|
||||
if (ret)
|
||||
ok(!memcmp(buf, namesA[i].encoded, namesA[i].encodedSize),
|
||||
"Unexpected value for string %s\n", namesA[i].x500);
|
||||
}
|
||||
}
|
||||
|
||||
struct StrToNameW
|
||||
{
|
||||
LPCWSTR x500;
|
||||
DWORD encodedSize;
|
||||
const BYTE *encoded;
|
||||
};
|
||||
|
||||
static const WCHAR badlyQuotedCN_W[] = { 'C','N','=','"','"','1','"','"',0 };
|
||||
static const WCHAR simpleCN_W[] = { 'C','N','=','1',0 };
|
||||
static const WCHAR simpleCN2_W[] = { 'C','N','=','"','1','"',0 };
|
||||
static const WCHAR simpleCN3_W[] = { 'C','N',' ','=',' ','"','1','"',0 };
|
||||
static const WCHAR singledQuotedCN_W[] = { 'C','N','=','\'','1','\'',0 };
|
||||
static const WCHAR spacedCN_W[] = { 'C','N','=','"',' ','1',' ','"',0 };
|
||||
static const WCHAR quotedCN_W[] = { 'C','N','=','"','"','"','1','"','"','"',0 };
|
||||
static const WCHAR multipleAttrCN_W[] = { 'C','N','=','"','1','+','2','"',0 };
|
||||
static const WCHAR japaneseCN_W[] = { 'C','N','=',0x226f,0x575b,0 };
|
||||
static const BYTE encodedJapaneseCN[] = { 0x30,0x0f,0x31,0x0d,0x30,0x0b,0x06,
|
||||
0x03,0x55,0x04,0x03,0x1e,0x04,0x22,0x6f,0x57,0x5b };
|
||||
|
||||
struct StrToNameW namesW[] = {
|
||||
{ simpleCN_W, sizeof(encodedSimpleCN), encodedSimpleCN },
|
||||
{ simpleCN2_W, sizeof(encodedSimpleCN), encodedSimpleCN },
|
||||
{ simpleCN3_W, sizeof(encodedSimpleCN), encodedSimpleCN },
|
||||
{ singledQuotedCN_W, sizeof(encodedSingleQuotedCN), encodedSingleQuotedCN },
|
||||
{ spacedCN_W, sizeof(encodedSpacedCN), encodedSpacedCN },
|
||||
{ quotedCN_W, sizeof(encodedQuotedCN), encodedQuotedCN },
|
||||
{ multipleAttrCN_W, sizeof(encodedMultipleAttrCN), encodedMultipleAttrCN },
|
||||
{ japaneseCN_W, sizeof(encodedJapaneseCN), encodedJapaneseCN },
|
||||
};
|
||||
|
||||
static void test_CertStrToNameW(void)
|
||||
{
|
||||
static const WCHAR bogusW[] = { 'b','o','g','u','s',0 };
|
||||
static const WCHAR fooW[] = { 'f','o','o','=','1',0 };
|
||||
BOOL ret;
|
||||
DWORD size, i;
|
||||
LPCWSTR errorPtr;
|
||||
BYTE buf[100];
|
||||
|
||||
if (!pCertStrToNameW)
|
||||
{
|
||||
skip("CertStrToNameW is not available\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Crash
|
||||
ret = pCertStrToNameW(0, NULL, 0, NULL, NULL, NULL, NULL);
|
||||
*/
|
||||
ret = pCertStrToNameW(0, NULL, 0, NULL, NULL, &size, NULL);
|
||||
ok(!ret, "Expected failure\n");
|
||||
ret = pCertStrToNameW(0, bogusW, 0, NULL, NULL, &size, NULL);
|
||||
ok(!ret && GetLastError() == CRYPT_E_INVALID_X500_STRING,
|
||||
"Expected CRYPT_E_INVALID_X500_STRING, got %08x\n", GetLastError());
|
||||
ret = pCertStrToNameW(0, fooW, 0, NULL, NULL, &size, NULL);
|
||||
ok(!ret && GetLastError() == CRYPT_E_INVALID_X500_STRING,
|
||||
"Expected CRYPT_E_INVALID_X500_STRING, got %08x\n", GetLastError());
|
||||
ret = pCertStrToNameW(0, simpleCN_W, 0, NULL, NULL, &size, NULL);
|
||||
ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
|
||||
"Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
|
||||
ret = pCertStrToNameW(X509_ASN_ENCODING, simpleCN_W, 0, NULL, NULL, &size,
|
||||
NULL);
|
||||
ok(ret, "CertStrToNameW failed: %08x\n", GetLastError());
|
||||
size = sizeof(buf);
|
||||
ret = pCertStrToNameW(X509_ASN_ENCODING, badlyQuotedCN_W, 0, NULL, buf,
|
||||
&size, NULL);
|
||||
ok(!ret && GetLastError() == CRYPT_E_INVALID_X500_STRING,
|
||||
"Expected CRYPT_E_INVALID_X500_STRING, got %08x\n", GetLastError());
|
||||
ret = pCertStrToNameW(X509_ASN_ENCODING, badlyQuotedCN_W, 0, NULL, buf,
|
||||
&size, &errorPtr);
|
||||
ok(!ret && GetLastError() == CRYPT_E_INVALID_X500_STRING,
|
||||
"Expected CRYPT_E_INVALID_X500_STRING, got %08x\n", GetLastError());
|
||||
ok(errorPtr && *errorPtr == '1', "Expected first error character was 1\n");
|
||||
for (i = 0; i < sizeof(namesW) / sizeof(namesW[0]); i++)
|
||||
{
|
||||
size = sizeof(buf);
|
||||
ret = pCertStrToNameW(X509_ASN_ENCODING, namesW[i].x500, 0, NULL, buf,
|
||||
&size, NULL);
|
||||
ok(ret, "Index %d: CertStrToNameW failed: %08x\n", i, GetLastError());
|
||||
ok(size == namesW[i].encodedSize,
|
||||
"Index %d: expected size %d, got %d\n", i, namesW[i].encodedSize,
|
||||
size);
|
||||
if (ret)
|
||||
ok(!memcmp(buf, namesW[i].encoded, size),
|
||||
"Index %d: unexpected value\n", i);
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST(str)
|
||||
{
|
||||
dll = GetModuleHandleA("Crypt32.dll");
|
||||
|
||||
pCertNameToStrA = (CertNameToStrAFunc)GetProcAddress(dll,"CertNameToStrA");
|
||||
pCertNameToStrW = (CertNameToStrWFunc)GetProcAddress(dll,"CertNameToStrW");
|
||||
pCertRDNValueToStrA = (CertRDNValueToStrAFunc)GetProcAddress(dll,
|
||||
"CertRDNValueToStrA");
|
||||
pCertRDNValueToStrW = (CertRDNValueToStrWFunc)GetProcAddress(dll,
|
||||
"CertRDNValueToStrW");
|
||||
pCryptDecodeObject = (CryptDecodeObjectFunc)GetProcAddress(dll,
|
||||
"CryptDecodeObject");
|
||||
pCertStrToNameA = (CertStrToNameAFunc)GetProcAddress(dll,"CertStrToNameA");
|
||||
pCertStrToNameW = (CertStrToNameWFunc)GetProcAddress(dll,"CertStrToNameW");
|
||||
|
||||
test_CertRDNValueToStrA();
|
||||
test_CertRDNValueToStrW();
|
||||
test_CertNameToStrA();
|
||||
test_CertNameToStrW();
|
||||
test_CertStrToNameA();
|
||||
test_CertStrToNameW();
|
||||
}
|
43
rostests/winetests/crypt32/testlist.c
Normal file
43
rostests/winetests/crypt32/testlist.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
/* Automatically generated file; DO NOT EDIT!! */
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
#define STANDALONE
|
||||
#include "wine/test.h"
|
||||
|
||||
extern void func_base64(void);
|
||||
extern void func_cert(void);
|
||||
extern void func_chain(void);
|
||||
extern void func_crl(void);
|
||||
extern void func_ctl(void);
|
||||
extern void func_encode(void);
|
||||
extern void func_main(void);
|
||||
extern void func_message(void);
|
||||
extern void func_msg(void);
|
||||
extern void func_object(void);
|
||||
extern void func_oid(void);
|
||||
extern void func_protectdata(void);
|
||||
extern void func_sip(void);
|
||||
extern void func_store(void);
|
||||
extern void func_str(void);
|
||||
|
||||
const struct test winetest_testlist[] =
|
||||
{
|
||||
{ "asn", func_base64 },
|
||||
{ "cert", func_cert },
|
||||
{ "chain", func_chain },
|
||||
{ "crl", func_crl },
|
||||
{ "ctl", func_ctl },
|
||||
{ "encode", func_encode },
|
||||
{ "main", func_main },
|
||||
{ "message", func_message },
|
||||
{ "msg", func_msg },
|
||||
{ "object", func_object },
|
||||
{ "oid", func_oid },
|
||||
{ "protectdata", func_protectdata },
|
||||
{ "sip", func_sip },
|
||||
{ "store", func_store },
|
||||
{ "str", func_str },
|
||||
{ 0, 0 }
|
||||
};
|
|
@ -22,6 +22,9 @@
|
|||
<directory name="comdlg32">
|
||||
<xi:include href="comdlg32/comdlg32.rbuild" />
|
||||
</directory>
|
||||
<directory name="crypt32">
|
||||
<xi:include href="crypt32/crypt32.rbuild" />
|
||||
</directory>
|
||||
<directory name="gdi32">
|
||||
<xi:include href="gdi32/gdi32.rbuild" />
|
||||
</directory>
|
||||
|
|
Loading…
Reference in a new issue