- add some tests for OID functions

- implement encoding integers
This commit is contained in:
Juan Lang 2005-06-02 10:34:03 +00:00 committed by Alexandre Julliard
parent 719187f190
commit 46185a9f8e
5 changed files with 242 additions and 5 deletions

View File

@ -22,6 +22,7 @@
#include "winbase.h"
#include "wincrypt.h"
#include "winreg.h"
#include "snmp.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(crypt);
@ -77,15 +78,18 @@ BOOL WINAPI CryptRegisterOIDFunction(DWORD dwEncodingType, LPCSTR pszFuncName,
if (!GET_CERT_ENCODING_TYPE(dwEncodingType))
return TRUE;
/* Native does nothing pwszDll is NULL */
if (!pwszDll)
return TRUE;
/* I'm not matching MS bug for bug here, because I doubt any app depends on
* it:
* - native does nothing if pwszDll is NULL
* - native "succeeds" if pszFuncName is NULL, but the nonsensical entry
* it creates would never be used
* - native returns an HRESULT rather than a Win32 error if pszOID is NULL.
* Instead I disallow all of these with ERROR_INVALID_PARAMETER.
* Instead I disallow both of these with ERROR_INVALID_PARAMETER.
*/
if (!pszFuncName || !pszOID || !pwszDll)
if (!pszFuncName || !pszOID)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
@ -309,6 +313,89 @@ BOOL WINAPI CryptEncodeObject(DWORD dwCertEncodingType, LPCSTR lpszStructType,
return ret;
}
static BOOL CRYPT_EncodeInt(DWORD dwCertEncodingType, const void *pvStructInfo,
DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
DWORD *pcbEncoded)
{
INT val, i;
BYTE significantBytes, padByte = 0, bytesNeeded;
BOOL neg = FALSE, pad = FALSE;
if ((dwCertEncodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING &&
(dwCertEncodingType & CMSG_ENCODING_TYPE_MASK) != PKCS_7_ASN_ENCODING)
{
SetLastError(ERROR_FILE_NOT_FOUND);
return FALSE;
}
if (!pvStructInfo)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
memcpy(&val, pvStructInfo, sizeof(val));
/* Count the number of significant bytes. Temporarily swap sign for
* negatives so I count the minimum number of bytes.
*/
if (val < 0)
{
neg = TRUE;
val = -val;
}
for (significantBytes = sizeof(val); !(val & 0xff000000);
val <<= 8, significantBytes--)
;
if (neg)
{
val = -val;
if ((val & 0xff000000) < 0x80000000)
{
padByte = 0xff;
pad = TRUE;
}
}
else if ((val & 0xff000000) > 0x7f000000)
{
padByte = 0;
pad = TRUE;
}
bytesNeeded = 2 + significantBytes;
if (pad)
bytesNeeded++;
if (!pbEncoded || bytesNeeded > *pcbEncoded)
{
*pcbEncoded = bytesNeeded;
SetLastError(ERROR_MORE_DATA);
return FALSE;
}
if (!pbEncoded)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
{
if (pEncodePara && pEncodePara->pfnAlloc)
*(BYTE **)pbEncoded = pEncodePara->pfnAlloc(bytesNeeded);
else
*(BYTE **)pbEncoded = LocalAlloc(0, bytesNeeded);
if (!*(BYTE **)pbEncoded)
return FALSE;
pbEncoded = *(BYTE **)pbEncoded;
}
*pbEncoded++ = ASN_INTEGER;
if (pad)
{
*pbEncoded++ = significantBytes + 1;
*pbEncoded++ = padByte;
}
else
*pbEncoded++ = significantBytes;
for (i = 0; i < significantBytes; i++, val <<= 8)
*(pbEncoded + i) = (BYTE)((val & 0xff000000) >> 24);
return TRUE;
}
typedef BOOL (WINAPI *CryptEncodeObjectExFunc)(DWORD, LPCSTR, const void *,
DWORD, PCRYPT_ENCODE_PARA, BYTE *, DWORD *);
@ -318,7 +405,7 @@ BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
{
BOOL ret = FALSE, encoded = FALSE;
FIXME("(0x%08lx, %s, %p, 0x%08lx, %p, %p, %p): stub\n",
TRACE("(0x%08lx, %s, %p, 0x%08lx, %p, %p, %p): semi-stub\n",
dwCertEncodingType, HIWORD(lpszStructType) ? debugstr_a(lpszStructType) :
"(integer value)", pvStructInfo, dwFlags, pEncodePara, pbEncoded,
pcbEncoded);
@ -333,6 +420,10 @@ BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
{
switch (LOWORD(lpszStructType))
{
case (WORD)X509_INTEGER:
ret = CRYPT_EncodeInt(dwCertEncodingType, pvStructInfo, dwFlags,
pEncodePara, pbEncoded, pcbEncoded);
break;
default:
FIXME("%d: unimplemented\n", LOWORD(lpszStructType));
}

View File

@ -1,3 +1,4 @@
Makefile
encode.ok
protectdata.ok
testlist.c

View File

@ -6,6 +6,7 @@ TESTDLL = crypt32.dll
IMPORTS = crypt32
CTESTS = \
encode.c \
protectdata.c
@MAKE_TEST_RULES@

144
dlls/crypt32/tests/encode.c Normal file
View File

@ -0,0 +1,144 @@
/*
* Unit test suite for crypt32.dll's CryptEncodeObjectEx
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include <stdarg.h>
#include <windef.h>
#include <winbase.h>
#include <winerror.h>
#include <wincrypt.h>
#include "wine/test.h"
struct encodedInt
{
int val;
BYTE encoded[6];
};
static void test_encodeint(void)
{
static const struct encodedInt ints[] = {
{ 1, { 2, 1, 1 } },
{ 127, { 2, 1, 0x7f } },
{ 128, { 2, 2, 0x00, 0x80 } },
{ 256, { 2, 2, 0x01, 0x00 } },
{ -128, { 2, 1, 0x80 } },
{ -129, { 2, 2, 0xff, 0x7f } },
{ 0xbaddf00d, { 2, 4, 0xba, 0xdd, 0xf0, 0x0d } },
};
DWORD bufSize = 0;
int i;
BOOL ret;
/* CryptEncodeObjectEx with NULL bufSize crashes..
ret = CryptEncodeObjectEx(3, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
NULL);
*/
/* check bogus encoding */
ret = CryptEncodeObjectEx(0, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
&bufSize);
ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
"Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
/* check with NULL integer buffer. Windows XP incorrectly returns an
* NTSTATUS.
*/
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_INTEGER, NULL, 0, NULL,
NULL, &bufSize);
ok(!ret && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() ==
STATUS_ACCESS_VIOLATION), "Unexpected error code %ld\n", GetLastError());
for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
{
BYTE *buf = NULL;
ret = CryptEncodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
X509_INTEGER, &ints[i].val, 0, NULL, NULL, &bufSize);
ok(ret || GetLastError() == ERROR_MORE_DATA,
"Expected success or ERROR_MORE_DATA, got %ld\n", GetLastError());
ret = CryptEncodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
X509_INTEGER, &ints[i].val, CRYPT_ENCODE_ALLOC_FLAG, NULL,
(BYTE *)&buf, &bufSize);
ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
buf[0]);
ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
"Encoded value of 0x%08x didn't match expected\n", ints[i].val);
LocalFree(buf);
}
}
static void test_registerOIDFunction(void)
{
static const WCHAR bogusDll[] = { 'b','o','g','u','s','.','d','l','l',0 };
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,
* HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)
*/
ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "foo", NULL, bogusDll,
NULL);
ok(!ret && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() ==
HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)),
"Expected ERROR_INVALID_PARAMETER: %ld\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 %ld\n", GetLastError());
ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "CryptDllEncodeObject",
"1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
ok(ret, "CryptRegisterOIDFunction failed: %ld\n", GetLastError());
ret = CryptUnregisterOIDFunction(X509_ASN_ENCODING, "CryptDllEncodeObject",
"1.2.3.4.5.6.7.8.9.10");
ok(ret, "CryptUnregisterOIDFunction failed: %ld\n", GetLastError());
ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "bogus",
"1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
ok(ret, "CryptRegisterOIDFunction failed: %ld\n", GetLastError());
ret = CryptUnregisterOIDFunction(X509_ASN_ENCODING, "bogus",
"1.2.3.4.5.6.7.8.9.10");
ok(ret, "CryptUnregisterOIDFunction failed: %ld\n", GetLastError());
/* This has no effect */
ret = CryptRegisterOIDFunction(PKCS_7_ASN_ENCODING, "CryptDllEncodeObject",
"1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
ok(ret, "CryptRegisterOIDFunction failed: %ld\n", GetLastError());
/* Check with bogus encoding type: */
ret = CryptRegisterOIDFunction(0, "CryptDllEncodeObject",
"1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
ok(ret, "CryptRegisterOIDFunction failed: %ld\n", GetLastError());
/* This is written with value 3 verbatim. Thus, the encoding type isn't
* (for now) treated as a mask.
*/
ret = CryptRegisterOIDFunction(3, "CryptDllEncodeObject",
"1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
ok(ret, "CryptRegisterOIDFunction failed: %ld\n", GetLastError());
ret = CryptUnregisterOIDFunction(3, "CryptDllEncodeObject",
"1.2.3.4.5.6.7.8.9.10");
ok(ret, "CryptUnregisterOIDFunction failed: %ld\n", GetLastError());
}
START_TEST(encode)
{
test_encodeint();
test_registerOIDFunction();
}

View File

@ -1437,7 +1437,6 @@ BOOL WINAPI CryptHashSessionKey (HCRYPTHASH hHash, HCRYPTKEY hKey, DWORD dwFlags
BOOL WINAPI CryptImportKey (HCRYPTPROV hProv, BYTE *pbData, DWORD dwDataLen,
HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey);
BOOL WINAPI CryptRegisterOIDFunction(DWORD,LPCSTR,LPCSTR,LPCWSTR,LPCSTR);
BOOL WINAPI CryptReleaseContext (HCRYPTPROV hProv, DWORD dwFlags);
BOOL WINAPI CryptSignHashA (HCRYPTHASH hHash, DWORD dwKeySpec, LPCSTR sDescription,
DWORD dwFlags, BYTE *pbSignature, DWORD *pdwSigLen);
@ -1453,6 +1452,7 @@ BOOL WINAPI CryptSetProviderExA (LPCSTR pszProvName, DWORD dwProvType, DWORD *pd
BOOL WINAPI CryptSetProviderExW (LPCWSTR pszProvName, DWORD dwProvType, DWORD *pdwReserved, DWORD dwFlags);
#define CryptSetProviderEx WINELIB_NAME_AW(CryptSetProviderEx)
BOOL WINAPI CryptSetProvParam (HCRYPTPROV hProv, DWORD dwParam, BYTE *pbData, DWORD dwFlags);
BOOL WINAPI CryptUnregisterOIDFunction(DWORD,LPCSTR,LPCSTR);
BOOL WINAPI CryptVerifySignatureA (HCRYPTHASH hHash, BYTE *pbSignature, DWORD dwSigLen,
HCRYPTKEY hPubKey, LPCSTR sDescription, DWORD dwFlags);
BOOL WINAPI CryptVerifySignatureW (HCRYPTHASH hHash, BYTE *pbSignature, DWORD dwSigLen,