wine/dlls/cryptxml/tests/cryptxml.c
2025-08-18 13:10:21 +02:00

168 lines
7.5 KiB
C

/* 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\">"
"<ds:Signature xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">"
"<ds:SignedInfo>"
"<ds:CanonicalizationMethod Algorithm=\"http://www.w3.org/TR/2001/REC-xml-c14n-20010315\"/>"
"<ds:SignatureMethod Algorithm=\"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256\"/>"
"<ds:Reference URI=\"\">"
"<ds:Transforms>"
"<ds:Transform Algorithm=\"http://www.w3.org/2000/09/xmldsig#enveloped-signature\"/>"
"<ds:Transform Algorithm=\"http://www.w3.org/TR/2001/REC-xml-c14n-20010315\"/>"
"</ds:Transforms>"
"<ds:DigestMethod Algorithm=\"http://www.w3.org/2001/04/xmlenc#sha256\"/>"
"<ds:DigestValue>/juoQ4bDxElf1M+KJauO20euW+QAvvPP0nDCruCQooM=</ds:DigestValue>"
"</ds:Reference>"
"</ds:SignedInfo>"
"<ds:SignatureValue>N0e0G9nH8CKLZPoUii3W2/lZWnu/eFl1mX5kVMLb1VCBdkcDlbIldw44HbHSY9WQruLjsm7YNyR4RjSYJSwk6RqcbaPt5LfzBJCgh3K+Hd/2TLlnN/xRpHzpnP86+11owwz6i475dRARDGRBUBWFcDkXXjdmWQ1nXbz1Pu4fIdBmpUtkPWnKtYitcq+YANnJez55PxShaZMQUZGnBipMJDajfyXTQr106TBrGic39+UJ+wfni6AE2GSeALsliiop9loBa0yekUcMSIUM8fjhBYRqfdg8vls26pacyEpBjDYUool0YA76o2iGHOXchFzndlm5KbQQyekea4ohmtVq2w==</ds:SignatureValue>"
"<ds:KeyInfo>"
"<ds:KeyValue>"
"<ds:RSAKeyValue>"
"<ds:Modulus>smBoZK3x0L164lUyh0iM8tTfHbR6Mk9yuoHryzryfe1bplF/Vj+mKCKPVXyCPrUvvHMZsDvdoE50EbILeSA3CGDSghDscKMJnWJZv19qNBZSzCi7UlE3PfmivL6NX8VwYuixHR7YbUJDq/gGnMW687gC8+b4JWPEgiBB71tw8OFluMa5hlIMuAfYMXYjr2QqTKuu4rgwRo3uei83HF3np2mglqFwRCVr6vADX+tRsA5YR6cDtVYqMOahF6YOhHbfYl9x2r+aFv82oBo+SussqdE2lthqowrWLTjHMy3htQoVhEJ0jiJULr/Da5isXDWzXENXH6F5jGIb7v86ZsgMQQ==</ds:Modulus>"
"<ds:Exponent>AQAB</ds:Exponent>"
"</ds:RSAKeyValue>"
"</ds:KeyValue>"
"</ds:KeyInfo>"
"</ds: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();
}