1 /* 2 * Unit test suite for crypt32.dll's Crypt*Object functions 3 * 4 * Copyright 2008 Juan Lang 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include "precomp.h" 22 23 static BOOL (WINAPI * pCryptQueryObject)(DWORD, const void *, DWORD, DWORD, 24 DWORD, DWORD *, DWORD *, DWORD *, HCERTSTORE *, HCRYPTMSG *, const void **); 25 26 static BYTE bigCert[] = { 27 0x30,0x7a,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31, 28 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75, 29 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f, 30 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30, 31 0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30, 32 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13, 33 0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61, 34 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x07,0x30,0x02,0x06, 35 0x00,0x03,0x01,0x00,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03, 36 0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01, 37 0xff,0x02,0x01,0x01 }; 38 static char bigCertBase64[] = 39 "MHoCAQEwAgYAMBUxEzARBgNVBAMTCkp1YW4gTGFuZwAwIhgPMTYwMTAxMDEwMDAw\n" 40 "MDBaGA8xNjAxMDEwMTAwMDAwMFowFTETMBEGA1UEAxMKSnVhbiBMYW5nADAHMAIG\n" 41 "AAMBAKMWMBQwEgYDVR0TAQH/BAgwBgEB/wIBAQ==\n"; 42 static WCHAR bigCertBase64W[] = { 43 'M','H','o','C','A','Q','E','w','A','g','Y','A','M','B','U','x','E','z','A', 44 'R','B','g','N','V','B','A','M','T','C','k','p','1','Y','W','4','g','T','G', 45 'F','u','Z','w','A','w','I','h','g','P','M','T','Y','w','M','T','A','x','M', 46 'D','E','w',',','D','A','w','\n', 47 'M','D','B','a','G','A','8','x','N','j','A','x','M','D','E','w','M','T','A', 48 'w','M','D','A','w','M','F','o','w','F','T','E','T','M','B','E','G','A','1', 49 'U','E','A','x','M','K','S','n','V','h','b','i','B','M','Y','W','5','n','A', 50 'D','A','H','M','A','I','G','\n', 51 'A','A','M','B','A','K','M','W','M','B','Q','w','E','g','Y','D','V','R','0', 52 'T','A','Q','H','/','B','A','g','w','B','g','E','B','/','w','I','B','A','Q', 53 '=','=','\n',0 }; 54 static BYTE signedWithCertWithValidPubKeyContent[] = { 55 0x30,0x82,0x01,0x89,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02, 56 0xa0,0x82,0x01,0x7a,0x30,0x82,0x01,0x76,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c, 57 0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x13,0x06, 58 0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x06,0x04,0x04,0x01, 59 0x02,0x03,0x04,0xa0,0x81,0xd2,0x30,0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06, 60 0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a, 61 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36, 62 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f, 63 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a, 64 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75, 65 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a, 66 0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48, 67 0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4, 68 0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb, 69 0x65,0x97,0x03,0x86,0x60,0xde,0xf3,0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc, 70 0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30, 71 0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30, 72 0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06, 73 0x01,0x01,0xff,0x02,0x01,0x01,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a, 74 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75, 75 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08, 76 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05, 77 0x00,0x04,0x40,0x81,0xa6,0x70,0xb3,0xef,0x59,0xd1,0x66,0xd1,0x9b,0xc0,0x9a, 78 0xb6,0x9a,0x5e,0x6d,0x6f,0x6d,0x0d,0x59,0xa9,0xaa,0x6e,0xe9,0x2c,0xa0,0x1e, 79 0xee,0xc2,0x60,0xbc,0x59,0xbe,0x3f,0x63,0x06,0x8d,0xc9,0x11,0x1d,0x23,0x64, 80 0x92,0xef,0x2e,0xfc,0x57,0x29,0xa4,0xaf,0xe0,0xee,0x93,0x19,0x39,0x51,0xe4, 81 0x44,0xb8,0x0b,0x28,0xf4,0xa8,0x0d }; 82 static char signedWithCertWithValidPubKeyContentBase64[] = 83 "MIIBiQYJKoZIhvcNAQcCoIIBejCCAXYCAQExDjAMBggqhkiG9w0CBQUAMBMGCSqG" 84 "SIb3DQEHAaAGBAQBAgMEoIHSMIHPAgEBMAIGADAVMRMwEQYDVQQDEwpKdWFuIExh" 85 "bmcAMCIYDzE2MDEwMTAxMDAwMDAwWhgPMTYwMTAxMDEwMDAwMDBaMBUxEzARBgNV" 86 "BAMTCkp1YW4gTGFuZwAwXDANBgkqhkiG9w0BAQEFAANLADBIAkEA4lQ6p4OxJxQ+" 87 "Wbu0U+Yf513xIWithVPbax7rZZcDhmDe82w4deBMYbu8YhepzXk/IU6Wyw7cYZQw" 88 "GBBr0BwQeQIDAQABoxYwFDASBgNVHRMBAf8ECDAGAQH/AgEBMXcwdQIBATAaMBUx" 89 "EzARBgNVBAMTCkp1YW4gTGFuZwACAQEwDAYIKoZIhvcNAgUFADAEBgAFAARAgaZw" 90 "s+9Z0WbRm8CatppebW9tDVmpqm7pLKAe7sJgvFm+P2MGjckRHSNkku8u/FcppK/g" 91 "7pMZOVHkRLgLKPSoDQ=="; 92 static WCHAR signedWithCertWithValidPubKeyContentBase64W[] = { 93 'M','I','I','B','i','Q','Y','J','K','o','Z','I','h','v','c','N','A','Q','c','C', 94 'o','I','I','B','e','j','C','C','A','X','Y','C','A','Q','E','x','D','j','A','M', 95 'B','g','g','q','h','k','i','G','9','w','0','C','B','Q','U','A','M','B','M','G', 96 'C','S','q','G','S','I','b','3','D','Q','E','H','A','a','A','G','B','A','Q','B', 97 'A','g','M','E','o','I','H','S','M','I','H','P','A','g','E','B','M','A','I','G', 98 'A','D','A','V','M','R','M','w','E','Q','Y','D','V','Q','Q','D','E','w','p','K', 99 'd','W','F','u','I','E','x','h','b','m','c','A','M','C','I','Y','D','z','E','2', 100 'M','D','E','w','M','T','A','x','M','D','A','w','M','D','A','w','W','h','g','P', 101 'M','T','Y','w','M','T','A','x','M','D','E','w','M','D','A','w','M','D','B','a', 102 'M','B','U','x','E','z','A','R','B','g','N','V','B','A','M','T','C','k','p','1', 103 'Y','W','4','g','T','G','F','u','Z','w','A','w','X','D','A','N','B','g','k','q', 104 'h','k','i','G','9','w','0','B','A','Q','E','F','A','A','N','L','A','D','B','I', 105 'A','k','E','A','4','l','Q','6','p','4','O','x','J','x','Q','+','W','b','u','0', 106 'U','+','Y','f','5','1','3','x','I','W','i','t','h','V','P','b','a','x','7','r', 107 'Z','Z','c','D','h','m','D','e','8','2','w','4','d','e','B','M','Y','b','u','8', 108 'Y','h','e','p','z','X','k','/','I','U','6','W','y','w','7','c','Y','Z','Q','w', 109 'G','B','B','r','0','B','w','Q','e','Q','I','D','A','Q','A','B','o','x','Y','w', 110 'F','D','A','S','B','g','N','V','H','R','M','B','A','f','8','E','C','D','A','G', 111 'A','Q','H','/','A','g','E','B','M','X','c','w','d','Q','I','B','A','T','A','a', 112 'M','B','U','x','E','z','A','R','B','g','N','V','B','A','M','T','C','k','p','1', 113 'Y','W','4','g','T','G','F','u','Z','w','A','C','A','Q','E','w','D','A','Y','I', 114 'K','o','Z','I','h','v','c','N','A','g','U','F','A','D','A','E','B','g','A','F', 115 'A','A','R','A','g','a','Z','w','s','+','9','Z','0','W','b','R','m','8','C','a', 116 't','p','p','e','b','W','9','t','D','V','m','p','q','m','7','p','L','K','A','e', 117 '7','s','J','g','v','F','m','+','P','2','M','G','j','c','k','R','H','S','N','k', 118 'k','u','8','u','/','F','c','p','p','K','/','g','7','p','M','Z','O','V','H','k', 119 'R','L','g','L','K','P','S','o','D','Q','=','=',0 }; 120 121 static void test_query_object(void) 122 { 123 BOOL ret; 124 CRYPT_DATA_BLOB blob; 125 126 /* Test the usual invalid arguments */ 127 SetLastError(0xdeadbeef); 128 ret = pCryptQueryObject(0, NULL, 0, 0, 0, NULL, NULL, NULL, NULL, NULL, 129 NULL); 130 ok(!ret && GetLastError() == E_INVALIDARG, 131 "expected E_INVALIDARG, got %08x\n", GetLastError()); 132 SetLastError(0xdeadbeef); 133 ret = pCryptQueryObject(CERT_QUERY_OBJECT_BLOB, NULL, 0, 0, 0, NULL, NULL, 134 NULL, NULL, NULL, NULL); 135 ok(!ret && GetLastError() == E_INVALIDARG, 136 "expected E_INVALIDARG, got %08x\n", GetLastError()); 137 /* Test with a simple cert */ 138 blob.pbData = bigCert; 139 blob.cbData = sizeof(bigCert); 140 SetLastError(0xdeadbeef); 141 ret = pCryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob, 142 CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_ALL, 0, NULL, NULL, 143 NULL, NULL, NULL, NULL); 144 ok(ret, "CryptQueryObject failed: %08x\n", GetLastError()); 145 /* The same cert, base64-encoded */ 146 blob.pbData = (BYTE *)bigCertBase64; 147 blob.cbData = sizeof(bigCertBase64); 148 SetLastError(0xdeadbeef); 149 ret = pCryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob, 150 CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_ALL, 0, NULL, NULL, 151 NULL, NULL, NULL, NULL); 152 ok(ret, "CryptQueryObject failed: %08x\n", GetLastError()); 153 /* The same base64-encoded cert, restricting the format types */ 154 SetLastError(0xdeadbeef); 155 ret = pCryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob, 156 CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_BINARY, 0, NULL, NULL, 157 NULL, NULL, NULL, NULL); 158 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH, 159 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError()); 160 SetLastError(0xdeadbeef); 161 ret = pCryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob, 162 CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED, 0, 163 NULL, NULL, NULL, NULL, NULL, NULL); 164 ok(ret, "CryptQueryObject failed: %08x\n", GetLastError()); 165 /* The same cert, base64-encoded but as a wide character string */ 166 blob.pbData = (BYTE *)bigCertBase64W; 167 blob.cbData = sizeof(bigCertBase64W); 168 SetLastError(0xdeadbeef); 169 ret = pCryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob, 170 CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_ALL, 0, NULL, NULL, 171 NULL, NULL, NULL, NULL); 172 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH, 173 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError()); 174 /* For brevity, not tested here, but tested on Windows: same failure 175 * (CRYPT_E_NO_MATCH) when the wide character base64-encoded cert 176 * is written to a file and queried. 177 */ 178 /* Test with a valid signed message */ 179 blob.pbData = signedWithCertWithValidPubKeyContent; 180 blob.cbData = sizeof(signedWithCertWithValidPubKeyContent); 181 SetLastError(0xdeadbeef); 182 ret = pCryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob, 183 CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_ALL, 0, NULL, NULL, 184 NULL, NULL, NULL, NULL); 185 ok(ret, "CryptQueryObject failed: %08x\n", GetLastError()); 186 blob.pbData = (BYTE *)signedWithCertWithValidPubKeyContentBase64; 187 blob.cbData = sizeof(signedWithCertWithValidPubKeyContentBase64); 188 SetLastError(0xdeadbeef); 189 ret = pCryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob, 190 CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_ALL, 0, NULL, NULL, 191 NULL, NULL, NULL, NULL); 192 ok(ret, "CryptQueryObject failed: %08x\n", GetLastError()); 193 /* A valid signed message, encoded as a wide character base64 string, can 194 * be queried successfully. 195 */ 196 blob.pbData = (BYTE *)signedWithCertWithValidPubKeyContentBase64W; 197 blob.cbData = sizeof(signedWithCertWithValidPubKeyContentBase64W); 198 SetLastError(0xdeadbeef); 199 ret = pCryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob, 200 CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_ALL, 0, NULL, NULL, 201 NULL, NULL, NULL, NULL); 202 ok(ret, "CryptQueryObject failed: %08x\n", GetLastError()); 203 SetLastError(0xdeadbeef); 204 ret = pCryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob, 205 CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_BINARY, 0, NULL, NULL, 206 NULL, NULL, NULL, NULL); 207 ok(!ret && GetLastError() == CRYPT_E_NO_MATCH, 208 "expected CRYPT_E_NO_MATCH, got %08x\n", GetLastError()); 209 SetLastError(0xdeadbeef); 210 ret = pCryptQueryObject(CERT_QUERY_OBJECT_BLOB, &blob, 211 CERT_QUERY_CONTENT_FLAG_ALL, CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED, 0, 212 NULL, NULL, NULL, NULL, NULL, NULL); 213 ok(ret, "CryptQueryObject failed: %08x\n", GetLastError()); 214 } 215 216 START_TEST(object) 217 { 218 HMODULE mod = GetModuleHandleA("crypt32.dll"); 219 220 pCryptQueryObject = (void *)GetProcAddress(mod, "CryptQueryObject"); 221 222 if (!pCryptQueryObject) 223 { 224 win_skip("CryptQueryObject is not available\n"); 225 return; 226 } 227 228 test_query_object(); 229 } 230