From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- configure.ac | 1 + dlls/cryptxml/Makefile.in | 3 +- dlls/cryptxml/tests/Makefile.in | 5 + dlls/cryptxml/tests/cryptxml.c | 171 ++++++++++++++++++++++++++++++++ 4 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 dlls/cryptxml/tests/Makefile.in create mode 100644 dlls/cryptxml/tests/cryptxml.c
diff --git a/configure.ac b/configure.ac index 83778c2882a..ed5097e245a 100644 --- a/configure.ac +++ b/configure.ac @@ -2530,6 +2530,7 @@ WINE_CONFIG_MAKEFILE(dlls/cryptsp) WINE_CONFIG_MAKEFILE(dlls/cryptui) WINE_CONFIG_MAKEFILE(dlls/cryptui/tests) WINE_CONFIG_MAKEFILE(dlls/cryptxml) +WINE_CONFIG_MAKEFILE(dlls/cryptxml/tests) WINE_CONFIG_MAKEFILE(dlls/ctapi32) WINE_CONFIG_MAKEFILE(dlls/ctl3d.dll16) WINE_CONFIG_MAKEFILE(dlls/ctl3d32) diff --git a/dlls/cryptxml/Makefile.in b/dlls/cryptxml/Makefile.in index 1fe91fe7019..49414e3cfd8 100644 --- a/dlls/cryptxml/Makefile.in +++ b/dlls/cryptxml/Makefile.in @@ -1,4 +1,5 @@ -MODULE = cryptxml.dll +MODULE = cryptxml.dll +IMPORTLIB = cryptxml
SOURCES = \ cryptxml.c diff --git a/dlls/cryptxml/tests/Makefile.in b/dlls/cryptxml/tests/Makefile.in new file mode 100644 index 00000000000..82a24b26f4d --- /dev/null +++ b/dlls/cryptxml/tests/Makefile.in @@ -0,0 +1,5 @@ +TESTDLL = cryptxml.dll +IMPORTS = cryptxml + +SOURCES = \ + cryptxml.c diff --git a/dlls/cryptxml/tests/cryptxml.c b/dlls/cryptxml/tests/cryptxml.c new file mode 100644 index 00000000000..cb93e6a2e5c --- /dev/null +++ b/dlls/cryptxml/tests/cryptxml.c @@ -0,0 +1,171 @@ +/* CryptXML Tests + * + * Copyright (C) 2025 Mohamad Al-Jaf + * + * 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 <stdarg.h> + +#include "windef.h" +#include "winbase.h" +#include "cryptxml.h" + +#include "wine/test.h" + +#define check_status( handle, expected_size, expected_error, expected_info, todo ) check_status_( __LINE__, handle, expected_size, expected_error, expected_info, todo ) +static void check_status_( unsigned int line, HCRYPTXML handle, ULONG expected_size, DWORD expected_error, DWORD expected_info, BOOL todo ) +{ + CRYPT_XML_STATUS status; + HRESULT hr; + + status.cbSize = 0xdeadbeef; + status.dwErrorStatus = 0xdeadbeef; + status.dwInfoStatus = 0xdeadbeef; + + hr = CryptXmlGetStatus( handle, &status ); + ok_(__FILE__, line)( hr == S_OK, "got CryptXmlGetStatus hr %#lx\n", hr ); + ok_(__FILE__, line)( status.cbSize == expected_size, "got status.cbSize = %lu\n", status.cbSize ); + todo_wine_if( todo ) ok_(__FILE__, line)( status.dwErrorStatus == expected_error, "got status.dwErrorStatus = %ld\n", status.dwErrorStatus ); + ok_(__FILE__, line)( status.dwInfoStatus == expected_info, "got status.dwInfoStatus = %ld\n", status.dwInfoStatus ); +} + +static void test_verify_signature(void) +{ + static const BYTE signature[] = + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<Envelope xmlns="urn:envelope">" + "<Signature xmlns="http://www.w3.org/2000/09/xmldsig#%5C%22%3E" + "<SignedInfo>" + "<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments%5C%22/%3E" + "<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1%5C%22/%3E" + "<Reference URI="">" + "<Transforms>" + "<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature%5C%22/%3E" + "</Transforms>" + "<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1%5C%22/%3E" + "<DigestValue>uooqbWYa5VCqcJCbuymBKqm17vY=</DigestValue>" + "</Reference>" + "</SignedInfo>" + "<SignatureValue>" + "KedJuTob5gtvYx9qM3k3gm7kbLBwVbEQRl26S2tmXjqNND7MRGtoew==" + "</SignatureValue>" + "<KeyInfo>" + "<KeyValue>" + "<DSAKeyValue>" + "<P>/KaCzo4Syrom78z3EQ5SbbB4sF7ey80etKII864WF64B81uRpH5t9jQTxeEu0ImbzRMqzVDZkVG9xD7nN1kuFw==</P>" + "<Q>li7dzDacuo67Jg7mtqEm2TRuOMU=</Q>" + "<G>Z4Rxsnqc9E7pGknFFH2xqaryRPBaQ01khpMdLRQnG541Awtx/XPaF5Bpsy4pNWMOHCBiNU0NogpsQW5QvnlMpA==</G>" + "<Y>qV38IqrWJG0V/mZQvRVi1OHw9Zj84nDC4jO8P0axi1gb6d+475yhMjSc/BrIVC58W3ydbkK+Ri4OKbaRZlYeRA==</Y>" + "</DSAKeyValue>" + "</KeyValue>" + "</KeyInfo>" + "</Signature>" + "</Envelope>"; + const CRYPT_XML_SIGNATURE *sig; + const CRYPT_XML_DOC_CTXT *ctx; + HCRYPTXML handle = NULL; + CRYPT_XML_STATUS status; + CRYPT_XML_BLOB blob; + HRESULT hr; + + hr = CryptXmlOpenToDecode( NULL, 0, NULL, 0, NULL, NULL ); + ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); + + handle = (HCRYPTXML)0xdeadbeef; + hr = CryptXmlOpenToDecode( NULL, 0, NULL, 0, NULL, &handle ); + ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); + ok( handle == (HCRYPTXML)0xdeadbeef, "got handle %p.\n", handle ); + + blob.dwCharset = CRYPT_XML_CHARSET_UTF8; + blob.cbData = strlen((const char *)signature) - 1; + blob.pbData = (BYTE *)signature; + hr = CryptXmlOpenToDecode( NULL, 0, NULL, 0, &blob, &handle ); + todo_wine + ok( hr == WS_E_INVALID_FORMAT, "got hr %#lx.\n", hr ); + todo_wine + ok( handle == NULL, "got handle %p.\n", handle ); + + hr = CryptXmlClose( NULL ); + ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); + + blob.dwCharset = CRYPT_XML_CHARSET_UTF8; + blob.cbData = strlen( (const char *)signature ); + blob.pbData = (BYTE *)signature; + hr = CryptXmlOpenToDecode( NULL, 0, NULL, 0, &blob, &handle ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + + hr = CryptXmlGetStatus( handle, NULL ); + ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); + hr = CryptXmlGetStatus( NULL, &status ); + ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); + + ctx = (CRYPT_XML_DOC_CTXT *)0xdeadbeef; + hr = CryptXmlGetDocContext( NULL, &ctx ); + ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); + ok( ctx == (CRYPT_XML_DOC_CTXT *)0xdeadbeef, "got ctx %p\n", ctx ); + hr = CryptXmlGetDocContext( handle, NULL ); + ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); + + hr = CryptXmlGetDocContext( handle, &ctx ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( ctx->cSignature == 1, "got signature count %lu\n", ctx->cSignature ); + ok( ctx->rgpSignature != NULL, "got NULL rgpSignature\n" ); + + sig = (CRYPT_XML_SIGNATURE *)0xdeadbeef; + hr = CryptXmlGetSignature( NULL, &sig ); + ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); + ok( sig == (CRYPT_XML_SIGNATURE *)0xdeadbeef, "got sig %p\n", sig ); + hr = CryptXmlGetSignature( handle, NULL ); + ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); + hr = CryptXmlGetSignature( handle, &sig ); + ok( hr == CRYPT_XML_E_HANDLE, "got hr %#lx.\n", hr ); + ok( sig == NULL, "got sig %p\n", sig ); + + hr = CryptXmlGetSignature( ctx->rgpSignature[0]->hSignature, &sig ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( sig != NULL, "failed to get signature\n" ); + ok( sig->cbSize == sizeof( CRYPT_XML_SIGNATURE ), "got sig->cbSize = %lu\n", sig->cbSize ); + + check_status( handle, sizeof( CRYPT_XML_STATUS ), CRYPT_XML_STATUS_ERROR_NOT_RESOLVED, 0, FALSE ); + + hr = CryptXmlVerifySignature( NULL, NULL, 0 ); + ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); + hr = CryptXmlVerifySignature( handle, NULL, 0 ); + ok( hr == CRYPT_XML_E_HANDLE, "got hr %#lx.\n", hr ); + hr = CryptXmlVerifySignature( handle, sig->pKeyInfo->hVerifyKey, 0 ); + ok( hr == CRYPT_XML_E_HANDLE, "got hr %#lx.\n", hr ); + + hr = CryptXmlVerifySignature( sig->hSignature, sig->pKeyInfo->hVerifyKey, 0 ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + + check_status( handle, sizeof( CRYPT_XML_STATUS ), CRYPT_XML_STATUS_ERROR_DIGEST_INVALID, CRYPT_XML_STATUS_SIGNATURE_VALID, TRUE ); + check_status( sig->hSignature, sizeof( CRYPT_XML_STATUS ), CRYPT_XML_STATUS_ERROR_DIGEST_INVALID, CRYPT_XML_STATUS_SIGNATURE_VALID, TRUE ); + + ctx = (CRYPT_XML_DOC_CTXT *)0xdeadbeef; + hr = CryptXmlGetDocContext( sig->hSignature, &ctx ); + ok( hr == CRYPT_XML_E_HANDLE, "got hr %#lx.\n", hr ); + ok( ctx == NULL, "got ctx %p\n", ctx ); + + hr = CryptXmlClose( sig->hSignature ); + ok( hr == S_FALSE, "got hr %#lx.\n", hr ); + hr = CryptXmlClose( handle ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); +} + +START_TEST(cryptxml) +{ + test_verify_signature(); +}