winmm: Rearrange device mapping when a new default device is chosen.
[wine] / dlls / crypt32 / rootstore.c
1 /*
2  * Copyright 2007 Juan Lang
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 #include "config.h"
19 #include <stdarg.h>
20 #include <stdio.h>
21 #include <sys/types.h>
22 #ifdef HAVE_SYS_STAT_H
23 #include <sys/stat.h>
24 #endif
25 #ifdef HAVE_DIRENT_H
26 #include <dirent.h>
27 #endif
28 #include <fcntl.h>
29 #ifdef HAVE_UNISTD_H
30 #include <unistd.h>
31 #endif
32 #include <errno.h>
33 #include <limits.h>
34 #ifdef HAVE_SECURITY_SECURITY_H
35 #include <Security/Security.h>
36 #endif
37 #include "ntstatus.h"
38 #define WIN32_NO_STATUS
39 #include "windef.h"
40 #include "winbase.h"
41 #include "winreg.h"
42 #include "wincrypt.h"
43 #include "winternl.h"
44 #include "wine/debug.h"
45 #include "crypt32_private.h"
46
47 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
48
49 #define INITIAL_CERT_BUFFER 1024
50
51 struct DynamicBuffer
52 {
53     DWORD allocated;
54     DWORD used;
55     BYTE *data;
56 };
57
58 static inline void reset_buffer(struct DynamicBuffer *buffer)
59 {
60     buffer->used = 0;
61     if (buffer->data) buffer->data[0] = 0;
62 }
63
64 static BOOL add_line_to_buffer(struct DynamicBuffer *buffer, LPCSTR line)
65 {
66     BOOL ret;
67
68     if (buffer->used + strlen(line) + 1 > buffer->allocated)
69     {
70         if (!buffer->allocated)
71         {
72             buffer->data = CryptMemAlloc(INITIAL_CERT_BUFFER);
73             if (buffer->data)
74             {
75                 buffer->data[0] = 0;
76                 buffer->allocated = INITIAL_CERT_BUFFER;
77             }
78         }
79         else
80         {
81             DWORD new_size = max(buffer->allocated * 2,
82              buffer->used + strlen(line) + 1);
83
84             buffer->data = CryptMemRealloc(buffer->data, new_size);
85             if (buffer->data)
86                 buffer->allocated = new_size;
87         }
88     }
89     if (buffer->data)
90     {
91         strcpy((char *)buffer->data + strlen((char *)buffer->data), line);
92         /* Not strlen + 1, otherwise we'd count the NULL for every line's
93          * addition (but we overwrite the previous NULL character.)  Not an
94          * overrun, we allocate strlen + 1 bytes above.
95          */
96         buffer->used += strlen(line);
97         ret = TRUE;
98     }
99     else
100         ret = FALSE;
101     return ret;
102 }
103
104 /* Reads any base64-encoded certificates present in fp and adds them to store.
105  * Returns TRUE if any certificates were successfully imported.
106  */
107 static BOOL import_base64_certs_from_fp(FILE *fp, HCERTSTORE store)
108 {
109     char line[1024];
110     BOOL in_cert = FALSE;
111     struct DynamicBuffer saved_cert = { 0, 0, NULL };
112     int num_certs = 0;
113
114     TRACE("\n");
115     while (fgets(line, sizeof(line), fp))
116     {
117         static const char header[] = "-----BEGIN CERTIFICATE-----";
118         static const char trailer[] = "-----END CERTIFICATE-----";
119
120         if (!strncmp(line, header, strlen(header)))
121         {
122             TRACE("begin new certificate\n");
123             in_cert = TRUE;
124             reset_buffer(&saved_cert);
125         }
126         else if (!strncmp(line, trailer, strlen(trailer)))
127         {
128             DWORD size;
129
130             TRACE("end of certificate, adding cert\n");
131             in_cert = FALSE;
132             if (CryptStringToBinaryA((char *)saved_cert.data, saved_cert.used,
133              CRYPT_STRING_BASE64, NULL, &size, NULL, NULL))
134             {
135                 LPBYTE buf = CryptMemAlloc(size);
136
137                 if (buf)
138                 {
139                     CryptStringToBinaryA((char *)saved_cert.data,
140                      saved_cert.used, CRYPT_STRING_BASE64, buf, &size, NULL,
141                      NULL);
142                     if (CertAddEncodedCertificateToStore(store,
143                      X509_ASN_ENCODING, buf, size, CERT_STORE_ADD_NEW, NULL))
144                         num_certs++;
145                     CryptMemFree(buf);
146                 }
147             }
148         }
149         else if (in_cert)
150             add_line_to_buffer(&saved_cert, line);
151     }
152     CryptMemFree(saved_cert.data);
153     TRACE("Read %d certs\n", num_certs);
154     return num_certs > 0;
155 }
156
157 static const char *trust_status_to_str(DWORD status)
158 {
159     static char buf[1024];
160     int pos = 0;
161
162     if (status & CERT_TRUST_IS_NOT_TIME_VALID)
163         pos += snprintf(buf + pos, sizeof(buf) - pos, "\n\texpired");
164     if (status & CERT_TRUST_IS_NOT_TIME_NESTED)
165         pos += snprintf(buf + pos, sizeof(buf) - pos, "\n\tbad time nesting");
166     if (status & CERT_TRUST_IS_REVOKED)
167         pos += snprintf(buf + pos, sizeof(buf) - pos, "\n\trevoked");
168     if (status & CERT_TRUST_IS_NOT_SIGNATURE_VALID)
169         pos += snprintf(buf + pos, sizeof(buf) - pos, "\n\tbad signature");
170     if (status & CERT_TRUST_IS_NOT_VALID_FOR_USAGE)
171         pos += snprintf(buf + pos, sizeof(buf) - pos, "\n\tbad usage");
172     if (status & CERT_TRUST_IS_UNTRUSTED_ROOT)
173         pos += snprintf(buf + pos, sizeof(buf) - pos, "\n\tuntrusted root");
174     if (status & CERT_TRUST_REVOCATION_STATUS_UNKNOWN)
175         pos += snprintf(buf + pos, sizeof(buf) - pos,
176          "\n\tunknown revocation status");
177     if (status & CERT_TRUST_IS_CYCLIC)
178         pos += snprintf(buf + pos, sizeof(buf) - pos, "\n\tcyclic chain");
179     if (status & CERT_TRUST_INVALID_EXTENSION)
180         pos += snprintf(buf + pos, sizeof(buf) - pos,
181          "\n\tunsupported critical extension");
182     if (status & CERT_TRUST_INVALID_POLICY_CONSTRAINTS)
183         pos += snprintf(buf + pos, sizeof(buf) - pos, "\n\tbad policy");
184     if (status & CERT_TRUST_INVALID_BASIC_CONSTRAINTS)
185         pos += snprintf(buf + pos, sizeof(buf) - pos,
186          "\n\tbad basic constraints");
187     if (status & CERT_TRUST_INVALID_NAME_CONSTRAINTS)
188         pos += snprintf(buf + pos, sizeof(buf) - pos,
189          "\n\tbad name constraints");
190     if (status & CERT_TRUST_HAS_NOT_SUPPORTED_NAME_CONSTRAINT)
191         pos += snprintf(buf + pos, sizeof(buf) - pos,
192          "\n\tunsuported name constraint");
193     if (status & CERT_TRUST_HAS_NOT_DEFINED_NAME_CONSTRAINT)
194         pos += snprintf(buf + pos, sizeof(buf) - pos,
195          "\n\tundefined name constraint");
196     if (status & CERT_TRUST_HAS_NOT_PERMITTED_NAME_CONSTRAINT)
197         pos += snprintf(buf + pos, sizeof(buf) - pos,
198          "\n\tdisallowed name constraint");
199     if (status & CERT_TRUST_HAS_EXCLUDED_NAME_CONSTRAINT)
200         pos += snprintf(buf + pos, sizeof(buf) - pos,
201          "\n\texcluded name constraint");
202     if (status & CERT_TRUST_IS_OFFLINE_REVOCATION)
203         pos += snprintf(buf + pos, sizeof(buf) - pos,
204          "\n\trevocation server offline");
205     if (status & CERT_TRUST_NO_ISSUANCE_CHAIN_POLICY)
206         pos += snprintf(buf + pos, sizeof(buf) - pos,
207          "\n\tno issuance policy");
208     return buf;
209 }
210
211 static const char *get_cert_common_name(PCCERT_CONTEXT cert)
212 {
213     static char buf[1024];
214     const char *name = NULL;
215     CERT_NAME_INFO *nameInfo;
216     DWORD size;
217     BOOL ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME,
218      cert->pCertInfo->Subject.pbData, cert->pCertInfo->Subject.cbData,
219      CRYPT_DECODE_NOCOPY_FLAG | CRYPT_DECODE_ALLOC_FLAG, NULL, &nameInfo,
220      &size);
221
222     if (ret)
223     {
224         PCERT_RDN_ATTR commonName = CertFindRDNAttr(szOID_COMMON_NAME,
225          nameInfo);
226
227         if (commonName)
228         {
229             CertRDNValueToStrA(commonName->dwValueType,
230              &commonName->Value, buf, sizeof(buf));
231             name = buf;
232         }
233         LocalFree(nameInfo);
234     }
235     return name;
236 }
237
238 static void check_and_store_certs(HCERTSTORE from, HCERTSTORE to)
239 {
240     DWORD root_count = 0;
241     CERT_CHAIN_ENGINE_CONFIG chainEngineConfig =
242      { sizeof(chainEngineConfig), 0 };
243     HCERTCHAINENGINE engine;
244
245     TRACE("\n");
246
247     CertDuplicateStore(to);
248     engine = CRYPT_CreateChainEngine(to, &chainEngineConfig);
249     if (engine)
250     {
251         PCCERT_CONTEXT cert = NULL;
252
253         do {
254             cert = CertEnumCertificatesInStore(from, cert);
255             if (cert)
256             {
257                 CERT_CHAIN_PARA chainPara = { sizeof(chainPara), { 0 } };
258                 PCCERT_CHAIN_CONTEXT chain;
259                 BOOL ret = CertGetCertificateChain(engine, cert, NULL, from,
260                  &chainPara, 0, NULL, &chain);
261
262                 if (!ret)
263                     TRACE("rejecting %s: %s\n", get_cert_common_name(cert),
264                      "chain creation failed");
265                 else
266                 {
267                     DWORD allowedErrors = CERT_TRUST_IS_UNTRUSTED_ROOT |
268                      CERT_TRUST_IS_NOT_VALID_FOR_USAGE |
269                      CERT_TRUST_INVALID_BASIC_CONSTRAINTS |
270                      CERT_TRUST_IS_NOT_TIME_VALID;
271
272                     /* The certificate chain verification only allows certain
273                      * invalid CA certs if they're installed locally:  CA
274                      * certs missing the key usage extension, and CA certs
275                      * missing the basic constraints extension.  Of course
276                      * there's a chicken and egg problem:  we have to accept
277                      * them here in order for them to be accepted later.
278                      * Expired, locally installed certs are also allowed here,
279                      * because we don't know (yet) what date will be checked
280                      * for an item signed by one of these certs.
281                      * Thus, accept certs with any of the allowed errors.
282                      */
283                     if (chain->TrustStatus.dwErrorStatus & ~allowedErrors)
284                         TRACE("rejecting %s: %s\n", get_cert_common_name(cert),
285                          trust_status_to_str(chain->TrustStatus.dwErrorStatus &
286                          ~CERT_TRUST_IS_UNTRUSTED_ROOT));
287                     else
288                     {
289                         DWORD i, j;
290
291                         for (i = 0; i < chain->cChain; i++)
292                             for (j = 0; j < chain->rgpChain[i]->cElement; j++)
293                                 if (CertAddCertificateContextToStore(to,
294                                  chain->rgpChain[i]->rgpElement[j]->pCertContext,
295                                  CERT_STORE_ADD_NEW, NULL))
296                                     root_count++;
297                     }
298                     CertFreeCertificateChain(chain);
299                 }
300             }
301         } while (cert);
302         CertFreeCertificateChainEngine(engine);
303     }
304     TRACE("Added %d root certificates\n", root_count);
305 }
306
307 /* Reads the file fd, and imports any certificates in it into store.
308  * Returns TRUE if any certificates were successfully imported.
309  */
310 static BOOL import_certs_from_file(int fd, HCERTSTORE store)
311 {
312     BOOL ret = FALSE;
313     FILE *fp;
314
315     TRACE("\n");
316
317     fp = fdopen(fd, "r");
318     if (fp)
319     {
320         ret = import_base64_certs_from_fp(fp, store);
321         fclose(fp);
322     }
323     return ret;
324 }
325
326 static BOOL import_certs_from_path(LPCSTR path, HCERTSTORE store,
327  BOOL allow_dir);
328
329 static BOOL check_buffer_resize(char **ptr_buf, size_t *buf_size, size_t check_size)
330 {
331     if (check_size > *buf_size)
332     {
333         *buf_size = check_size;
334
335         if (*ptr_buf)
336         {
337             char *realloc_buf = CryptMemRealloc(*ptr_buf, *buf_size);
338
339             if (!realloc_buf)
340                 return FALSE;
341
342             *ptr_buf = realloc_buf;
343         }
344         else
345         {
346             *ptr_buf = CryptMemAlloc(*buf_size);
347             if (!*ptr_buf)
348                 return FALSE;
349         }
350     }
351
352     return TRUE;
353 }
354
355 /* Opens path, which must be a directory, and imports certificates from every
356  * file in the directory into store.
357  * Returns TRUE if any certificates were successfully imported.
358  */
359 static BOOL import_certs_from_dir(LPCSTR path, HCERTSTORE store)
360 {
361 #ifdef HAVE_READDIR
362     BOOL ret = FALSE;
363     DIR *dir;
364
365     TRACE("(%s, %p)\n", debugstr_a(path), store);
366
367     dir = opendir(path);
368     if (dir)
369     {
370         size_t path_len = strlen(path), bufsize = 0;
371         char *filebuf = NULL;
372
373         struct dirent *entry;
374         while ((entry = readdir(dir)))
375         {
376             if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, ".."))
377             {
378                 size_t name_len = strlen(entry->d_name);
379
380                 if (!check_buffer_resize(&filebuf, &bufsize, path_len + 1 + name_len + 1))
381                 {
382                     ERR("Path buffer (re)allocation failed with out of memory condition\n");
383                     break;
384                 }
385                 snprintf(filebuf, bufsize, "%s/%s", path, entry->d_name);
386                 if (import_certs_from_path(filebuf, store, FALSE) && !ret)
387                     ret = TRUE;
388             }
389         }
390         CryptMemFree(filebuf);
391         closedir(dir);
392     }
393     return ret;
394 #else
395     FIXME("not implemented without readdir available\n");
396     return FALSE;
397 #endif
398 }
399
400 /* Opens path, which may be a file or a directory, and imports any certificates
401  * it finds into store.
402  * Returns TRUE if any certificates were successfully imported.
403  */
404 static BOOL import_certs_from_path(LPCSTR path, HCERTSTORE store,
405  BOOL allow_dir)
406 {
407     BOOL ret = FALSE;
408     int fd;
409
410     TRACE("(%s, %p, %d)\n", debugstr_a(path), store, allow_dir);
411
412     fd = open(path, O_RDONLY);
413     if (fd != -1)
414     {
415         struct stat st;
416
417         if (fstat(fd, &st) == 0)
418         {
419             if (S_ISREG(st.st_mode))
420                 ret = import_certs_from_file(fd, store);
421             else if (S_ISDIR(st.st_mode))
422             {
423                 if (allow_dir)
424                     ret = import_certs_from_dir(path, store);
425                 else
426                     WARN("%s is a directory and directories are disallowed\n",
427                      debugstr_a(path));
428             }
429             else
430                 ERR("%s: invalid file type\n", path);
431         }
432         close(fd);
433     }
434     return ret;
435 }
436
437 static BOOL WINAPI CRYPT_RootWriteCert(HCERTSTORE hCertStore,
438  PCCERT_CONTEXT cert, DWORD dwFlags)
439 {
440     /* The root store can't have certs added */
441     return FALSE;
442 }
443
444 static BOOL WINAPI CRYPT_RootDeleteCert(HCERTSTORE hCertStore,
445  PCCERT_CONTEXT cert, DWORD dwFlags)
446 {
447     /* The root store can't have certs deleted */
448     return FALSE;
449 }
450
451 static BOOL WINAPI CRYPT_RootWriteCRL(HCERTSTORE hCertStore,
452  PCCRL_CONTEXT crl, DWORD dwFlags)
453 {
454     /* The root store can have CRLs added.  At worst, a malicious application
455      * can DoS itself, as the changes aren't persisted in any way.
456      */
457     return TRUE;
458 }
459
460 static BOOL WINAPI CRYPT_RootDeleteCRL(HCERTSTORE hCertStore,
461  PCCRL_CONTEXT crl, DWORD dwFlags)
462 {
463     /* The root store can't have CRLs deleted */
464     return FALSE;
465 }
466
467 static void *rootProvFuncs[] = {
468     NULL, /* CERT_STORE_PROV_CLOSE_FUNC */
469     NULL, /* CERT_STORE_PROV_READ_CERT_FUNC */
470     CRYPT_RootWriteCert,
471     CRYPT_RootDeleteCert,
472     NULL, /* CERT_STORE_PROV_SET_CERT_PROPERTY_FUNC */
473     NULL, /* CERT_STORE_PROV_READ_CRL_FUNC */
474     CRYPT_RootWriteCRL,
475     CRYPT_RootDeleteCRL,
476     NULL, /* CERT_STORE_PROV_SET_CRL_PROPERTY_FUNC */
477     NULL, /* CERT_STORE_PROV_READ_CTL_FUNC */
478     NULL, /* CERT_STORE_PROV_WRITE_CTL_FUNC */
479     NULL, /* CERT_STORE_PROV_DELETE_CTL_FUNC */
480     NULL, /* CERT_STORE_PROV_SET_CTL_PROPERTY_FUNC */
481     NULL, /* CERT_STORE_PROV_CONTROL_FUNC */
482 };
483
484 static const char * const CRYPT_knownLocations[] = {
485  "/etc/ssl/certs/ca-certificates.crt",
486  "/etc/ssl/certs",
487  "/etc/pki/tls/certs/ca-bundle.crt",
488  "/usr/local/share/certs/",
489  "/etc/sfw/openssl/certs",
490 };
491
492 static const BYTE authenticode[] = {
493 0x30,0x82,0x03,0xd6,0x30,0x82,0x02,0xbe,0xa0,0x03,0x02,0x01,0x02,0x02,0x01,0x01,
494 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,
495 0x50,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,0x31,0x0d,
496 0x30,0x0b,0x06,0x03,0x55,0x04,0x0a,0x13,0x04,0x4d,0x53,0x46,0x54,0x31,0x32,0x30,
497 0x30,0x06,0x03,0x55,0x04,0x03,0x13,0x29,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,
498 0x74,0x20,0x41,0x75,0x74,0x68,0x65,0x6e,0x74,0x69,0x63,0x6f,0x64,0x65,0x28,0x74,
499 0x6d,0x29,0x20,0x52,0x6f,0x6f,0x74,0x20,0x41,0x75,0x74,0x68,0x6f,0x72,0x69,0x74,
500 0x79,0x30,0x1e,0x17,0x0d,0x39,0x35,0x30,0x31,0x30,0x31,0x30,0x38,0x30,0x30,0x30,
501 0x31,0x5a,0x17,0x0d,0x39,0x39,0x31,0x32,0x33,0x31,0x32,0x33,0x35,0x39,0x35,0x39,
502 0x5a,0x30,0x50,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,
503 0x31,0x0d,0x30,0x0b,0x06,0x03,0x55,0x04,0x0a,0x13,0x04,0x4d,0x53,0x46,0x54,0x31,
504 0x32,0x30,0x30,0x06,0x03,0x55,0x04,0x03,0x13,0x29,0x4d,0x69,0x63,0x72,0x6f,0x73,
505 0x6f,0x66,0x74,0x20,0x41,0x75,0x74,0x68,0x65,0x6e,0x74,0x69,0x63,0x6f,0x64,0x65,
506 0x28,0x74,0x6d,0x29,0x20,0x52,0x6f,0x6f,0x74,0x20,0x41,0x75,0x74,0x68,0x6f,0x72,
507 0x69,0x74,0x79,0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
508 0x0d,0x01,0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,
509 0x82,0x01,0x01,0x00,0xdf,0x08,0xba,0xe3,0x3f,0x6e,0x64,0x9b,0xf5,0x89,0xaf,0x28,
510 0x96,0x4a,0x07,0x8f,0x1b,0x2e,0x8b,0x3e,0x1d,0xfc,0xb8,0x80,0x69,0xa3,0xa1,0xce,
511 0xdb,0xdf,0xb0,0x8e,0x6c,0x89,0x76,0x29,0x4f,0xca,0x60,0x35,0x39,0xad,0x72,0x32,
512 0xe0,0x0b,0xae,0x29,0x3d,0x4c,0x16,0xd9,0x4b,0x3c,0x9d,0xda,0xc5,0xd3,0xd1,0x09,
513 0xc9,0x2c,0x6f,0xa6,0xc2,0x60,0x53,0x45,0xdd,0x4b,0xd1,0x55,0xcd,0x03,0x1c,0xd2,
514 0x59,0x56,0x24,0xf3,0xe5,0x78,0xd8,0x07,0xcc,0xd8,0xb3,0x1f,0x90,0x3f,0xc0,0x1a,
515 0x71,0x50,0x1d,0x2d,0xa7,0x12,0x08,0x6d,0x7c,0xb0,0x86,0x6c,0xc7,0xba,0x85,0x32,
516 0x07,0xe1,0x61,0x6f,0xaf,0x03,0xc5,0x6d,0xe5,0xd6,0xa1,0x8f,0x36,0xf6,0xc1,0x0b,
517 0xd1,0x3e,0x69,0x97,0x48,0x72,0xc9,0x7f,0xa4,0xc8,0xc2,0x4a,0x4c,0x7e,0xa1,0xd1,
518 0x94,0xa6,0xd7,0xdc,0xeb,0x05,0x46,0x2e,0xb8,0x18,0xb4,0x57,0x1d,0x86,0x49,0xdb,
519 0x69,0x4a,0x2c,0x21,0xf5,0x5e,0x0f,0x54,0x2d,0x5a,0x43,0xa9,0x7a,0x7e,0x6a,0x8e,
520 0x50,0x4d,0x25,0x57,0xa1,0xbf,0x1b,0x15,0x05,0x43,0x7b,0x2c,0x05,0x8d,0xbd,0x3d,
521 0x03,0x8c,0x93,0x22,0x7d,0x63,0xea,0x0a,0x57,0x05,0x06,0x0a,0xdb,0x61,0x98,0x65,
522 0x2d,0x47,0x49,0xa8,0xe7,0xe6,0x56,0x75,0x5c,0xb8,0x64,0x08,0x63,0xa9,0x30,0x40,
523 0x66,0xb2,0xf9,0xb6,0xe3,0x34,0xe8,0x67,0x30,0xe1,0x43,0x0b,0x87,0xff,0xc9,0xbe,
524 0x72,0x10,0x5e,0x23,0xf0,0x9b,0xa7,0x48,0x65,0xbf,0x09,0x88,0x7b,0xcd,0x72,0xbc,
525 0x2e,0x79,0x9b,0x7b,0x02,0x03,0x01,0x00,0x01,0xa3,0x81,0xba,0x30,0x81,0xb7,0x30,
526 0x0d,0x06,0x03,0x55,0x1d,0x0a,0x04,0x06,0x30,0x04,0x03,0x02,0x07,0x80,0x30,0x32,
527 0x06,0x03,0x55,0x04,0x03,0x04,0x2b,0x13,0x29,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,
528 0x66,0x74,0x20,0x41,0x75,0x74,0x68,0x65,0x6e,0x74,0x69,0x63,0x6f,0x64,0x65,0x28,
529 0x74,0x6d,0x29,0x20,0x52,0x6f,0x6f,0x74,0x20,0x41,0x75,0x74,0x68,0x6f,0x72,0x69,
530 0x74,0x79,0x30,0x72,0x06,0x03,0x55,0x1d,0x01,0x04,0x6b,0x30,0x69,0x80,0x10,0x1a,
531 0x1b,0xe7,0x5b,0x9f,0xfd,0x8c,0x2a,0xc3,0x39,0xae,0x0c,0x62,0x2e,0x53,0x32,0xa1,
532 0x52,0x30,0x50,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,0x53,
533 0x31,0x0d,0x30,0x0b,0x06,0x03,0x55,0x04,0x0a,0x13,0x04,0x4d,0x53,0x46,0x54,0x31,
534 0x32,0x30,0x30,0x06,0x03,0x55,0x04,0x03,0x13,0x29,0x4d,0x69,0x63,0x72,0x6f,0x73,
535 0x6f,0x66,0x74,0x20,0x41,0x75,0x74,0x68,0x65,0x6e,0x74,0x69,0x63,0x6f,0x64,0x65,
536 0x28,0x74,0x6d,0x29,0x20,0x52,0x6f,0x6f,0x74,0x20,0x41,0x75,0x74,0x68,0x6f,0x72,
537 0x69,0x74,0x79,0x82,0x01,0x01,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
538 0x01,0x01,0x04,0x05,0x00,0x03,0x82,0x01,0x01,0x00,0x2d,0xc9,0xe2,0xf6,0x12,0x9e,
539 0x5d,0x56,0x67,0xfa,0xfa,0x4b,0x9a,0x7e,0xdc,0x29,0x56,0x5c,0x80,0x14,0x02,0x28,
540 0x85,0x6e,0x26,0xf3,0xcd,0x58,0xda,0x50,0x80,0xc5,0xf8,0x19,0xb3,0xa6,0x7c,0xe2,
541 0x9d,0x6b,0x5f,0x3b,0x8f,0x22,0x74,0xe6,0x18,0x04,0xfc,0x47,0x40,0xd8,0x7a,0x3f,
542 0x30,0x66,0xf0,0x12,0xa4,0xd1,0xeb,0x1d,0xe7,0xb6,0xf4,0x98,0xab,0x53,0x22,0x86,
543 0x51,0x58,0xee,0x23,0x09,0x76,0xe4,0x1d,0x45,0x5c,0x4b,0xff,0x4c,0xe3,0x02,0x50,
544 0x01,0x13,0xcc,0x41,0xa4,0x52,0x97,0xd4,0x86,0xd5,0xc4,0xfe,0x83,0x83,0x65,0x7d,
545 0xea,0xbe,0xa2,0x68,0x3b,0xc1,0xb1,0x29,0x98,0xbf,0xa2,0xa5,0xfc,0x9d,0xd3,0x84,
546 0xee,0x70,0x17,0x50,0xf3,0x0b,0xfa,0x3c,0xef,0xa9,0x27,0x8b,0x91,0xb4,0x48,0xc8,
547 0x45,0xa0,0xe1,0x01,0x42,0x4b,0x44,0x76,0x04,0x1c,0xc2,0x19,0xa2,0x8e,0x6b,0x20,
548 0x98,0xc4,0xdd,0x02,0xac,0xb4,0xd2,0xa2,0x0e,0x8d,0x5d,0xb9,0x36,0x8e,0x4a,0x1b,
549 0x5d,0x6c,0x1a,0xe2,0xcb,0x00,0x7f,0x10,0xf4,0xb2,0x95,0xef,0xe3,0xe8,0xff,0xa1,
550 0x73,0x58,0xa9,0x75,0x2c,0xa2,0x49,0x95,0x85,0xfe,0xcc,0xda,0x44,0x8a,0xc2,0x12,
551 0x44,0xd2,0x44,0xc8,0xa5,0xa2,0x1f,0xa9,0x5a,0x8e,0x56,0xc2,0xc3,0x7b,0xcf,0x42,
552 0x60,0xdc,0x82,0x1f,0xfb,0xce,0x74,0x06,0x7e,0xd6,0xf1,0xac,0x19,0x6a,0x4f,0x74,
553 0x5c,0xc5,0x15,0x66,0x31,0x6c,0xc1,0x62,0x71,0x91,0x0f,0x59,0x5b,0x7d,0x2a,0x82,
554 0x1a,0xdf,0xb1,0xb4,0xd8,0x1d,0x37,0xde,0x0d,0x0f };
555 static const BYTE rootauthority[] = {
556 0x30,0x82,0x04,0x12,0x30,0x82,0x02,0xfa,0xa0,0x03,0x02,0x01,0x02,0x02,0x0f,0x00,
557 0xc1,0x00,0x8b,0x3c,0x3c,0x88,0x11,0xd1,0x3e,0xf6,0x63,0xec,0xdf,0x40,0x30,0x0d,
558 0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x70,0x31,
559 0x2b,0x30,0x29,0x06,0x03,0x55,0x04,0x0b,0x13,0x22,0x43,0x6f,0x70,0x79,0x72,0x69,
560 0x67,0x68,0x74,0x20,0x28,0x63,0x29,0x20,0x31,0x39,0x39,0x37,0x20,0x4d,0x69,0x63,
561 0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x43,0x6f,0x72,0x70,0x2e,0x31,0x1e,0x30,0x1c,
562 0x06,0x03,0x55,0x04,0x0b,0x13,0x15,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,
563 0x20,0x43,0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x21,0x30,0x1f,
564 0x06,0x03,0x55,0x04,0x03,0x13,0x18,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,
565 0x20,0x52,0x6f,0x6f,0x74,0x20,0x41,0x75,0x74,0x68,0x6f,0x72,0x69,0x74,0x79,0x30,
566 0x1e,0x17,0x0d,0x39,0x37,0x30,0x31,0x31,0x30,0x30,0x37,0x30,0x30,0x30,0x30,0x5a,
567 0x17,0x0d,0x32,0x30,0x31,0x32,0x33,0x31,0x30,0x37,0x30,0x30,0x30,0x30,0x5a,0x30,
568 0x70,0x31,0x2b,0x30,0x29,0x06,0x03,0x55,0x04,0x0b,0x13,0x22,0x43,0x6f,0x70,0x79,
569 0x72,0x69,0x67,0x68,0x74,0x20,0x28,0x63,0x29,0x20,0x31,0x39,0x39,0x37,0x20,0x4d,
570 0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x43,0x6f,0x72,0x70,0x2e,0x31,0x1e,
571 0x30,0x1c,0x06,0x03,0x55,0x04,0x0b,0x13,0x15,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,
572 0x66,0x74,0x20,0x43,0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x21,
573 0x30,0x1f,0x06,0x03,0x55,0x04,0x03,0x13,0x18,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,
574 0x66,0x74,0x20,0x52,0x6f,0x6f,0x74,0x20,0x41,0x75,0x74,0x68,0x6f,0x72,0x69,0x74,
575 0x79,0x30,0x82,0x01,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
576 0x01,0x01,0x05,0x00,0x03,0x82,0x01,0x0f,0x00,0x30,0x82,0x01,0x0a,0x02,0x82,0x01,
577 0x01,0x00,0xa9,0x02,0xbd,0xc1,0x70,0xe6,0x3b,0xf2,0x4e,0x1b,0x28,0x9f,0x97,0x78,
578 0x5e,0x30,0xea,0xa2,0xa9,0x8d,0x25,0x5f,0xf8,0xfe,0x95,0x4c,0xa3,0xb7,0xfe,0x9d,
579 0xa2,0x20,0x3e,0x7c,0x51,0xa2,0x9b,0xa2,0x8f,0x60,0x32,0x6b,0xd1,0x42,0x64,0x79,
580 0xee,0xac,0x76,0xc9,0x54,0xda,0xf2,0xeb,0x9c,0x86,0x1c,0x8f,0x9f,0x84,0x66,0xb3,
581 0xc5,0x6b,0x7a,0x62,0x23,0xd6,0x1d,0x3c,0xde,0x0f,0x01,0x92,0xe8,0x96,0xc4,0xbf,
582 0x2d,0x66,0x9a,0x9a,0x68,0x26,0x99,0xd0,0x3a,0x2c,0xbf,0x0c,0xb5,0x58,0x26,0xc1,
583 0x46,0xe7,0x0a,0x3e,0x38,0x96,0x2c,0xa9,0x28,0x39,0xa8,0xec,0x49,0x83,0x42,0xe3,
584 0x84,0x0f,0xbb,0x9a,0x6c,0x55,0x61,0xac,0x82,0x7c,0xa1,0x60,0x2d,0x77,0x4c,0xe9,
585 0x99,0xb4,0x64,0x3b,0x9a,0x50,0x1c,0x31,0x08,0x24,0x14,0x9f,0xa9,0xe7,0x91,0x2b,
586 0x18,0xe6,0x3d,0x98,0x63,0x14,0x60,0x58,0x05,0x65,0x9f,0x1d,0x37,0x52,0x87,0xf7,
587 0xa7,0xef,0x94,0x02,0xc6,0x1b,0xd3,0xbf,0x55,0x45,0xb3,0x89,0x80,0xbf,0x3a,0xec,
588 0x54,0x94,0x4e,0xae,0xfd,0xa7,0x7a,0x6d,0x74,0x4e,0xaf,0x18,0xcc,0x96,0x09,0x28,
589 0x21,0x00,0x57,0x90,0x60,0x69,0x37,0xbb,0x4b,0x12,0x07,0x3c,0x56,0xff,0x5b,0xfb,
590 0xa4,0x66,0x0a,0x08,0xa6,0xd2,0x81,0x56,0x57,0xef,0xb6,0x3b,0x5e,0x16,0x81,0x77,
591 0x04,0xda,0xf6,0xbe,0xae,0x80,0x95,0xfe,0xb0,0xcd,0x7f,0xd6,0xa7,0x1a,0x72,0x5c,
592 0x3c,0xca,0xbc,0xf0,0x08,0xa3,0x22,0x30,0xb3,0x06,0x85,0xc9,0xb3,0x20,0x77,0x13,
593 0x85,0xdf,0x02,0x03,0x01,0x00,0x01,0xa3,0x81,0xa8,0x30,0x81,0xa5,0x30,0x81,0xa2,
594 0x06,0x03,0x55,0x1d,0x01,0x04,0x81,0x9a,0x30,0x81,0x97,0x80,0x10,0x5b,0xd0,0x70,
595 0xef,0x69,0x72,0x9e,0x23,0x51,0x7e,0x14,0xb2,0x4d,0x8e,0xff,0xcb,0xa1,0x72,0x30,
596 0x70,0x31,0x2b,0x30,0x29,0x06,0x03,0x55,0x04,0x0b,0x13,0x22,0x43,0x6f,0x70,0x79,
597 0x72,0x69,0x67,0x68,0x74,0x20,0x28,0x63,0x29,0x20,0x31,0x39,0x39,0x37,0x20,0x4d,
598 0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x43,0x6f,0x72,0x70,0x2e,0x31,0x1e,
599 0x30,0x1c,0x06,0x03,0x55,0x04,0x0b,0x13,0x15,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,
600 0x66,0x74,0x20,0x43,0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x31,0x21,
601 0x30,0x1f,0x06,0x03,0x55,0x04,0x03,0x13,0x18,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,
602 0x66,0x74,0x20,0x52,0x6f,0x6f,0x74,0x20,0x41,0x75,0x74,0x68,0x6f,0x72,0x69,0x74,
603 0x79,0x82,0x0f,0x00,0xc1,0x00,0x8b,0x3c,0x3c,0x88,0x11,0xd1,0x3e,0xf6,0x63,0xec,
604 0xdf,0x40,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,
605 0x00,0x03,0x82,0x01,0x01,0x00,0x95,0xe8,0x0b,0xc0,0x8d,0xf3,0x97,0x18,0x35,0xed,
606 0xb8,0x01,0x24,0xd8,0x77,0x11,0xf3,0x5c,0x60,0x32,0x9f,0x9e,0x0b,0xcb,0x3e,0x05,
607 0x91,0x88,0x8f,0xc9,0x3a,0xe6,0x21,0xf2,0xf0,0x57,0x93,0x2c,0xb5,0xa0,0x47,0xc8,
608 0x62,0xef,0xfc,0xd7,0xcc,0x3b,0x3b,0x5a,0xa9,0x36,0x54,0x69,0xfe,0x24,0x6d,0x3f,
609 0xc9,0xcc,0xaa,0xde,0x05,0x7c,0xdd,0x31,0x8d,0x3d,0x9f,0x10,0x70,0x6a,0xbb,0xfe,
610 0x12,0x4f,0x18,0x69,0xc0,0xfc,0xd0,0x43,0xe3,0x11,0x5a,0x20,0x4f,0xea,0x62,0x7b,
611 0xaf,0xaa,0x19,0xc8,0x2b,0x37,0x25,0x2d,0xbe,0x65,0xa1,0x12,0x8a,0x25,0x0f,0x63,
612 0xa3,0xf7,0x54,0x1c,0xf9,0x21,0xc9,0xd6,0x15,0xf3,0x52,0xac,0x6e,0x43,0x32,0x07,
613 0xfd,0x82,0x17,0xf8,0xe5,0x67,0x6c,0x0d,0x51,0xf6,0xbd,0xf1,0x52,0xc7,0xbd,0xe7,
614 0xc4,0x30,0xfc,0x20,0x31,0x09,0x88,0x1d,0x95,0x29,0x1a,0x4d,0xd5,0x1d,0x02,0xa5,
615 0xf1,0x80,0xe0,0x03,0xb4,0x5b,0xf4,0xb1,0xdd,0xc8,0x57,0xee,0x65,0x49,0xc7,0x52,
616 0x54,0xb6,0xb4,0x03,0x28,0x12,0xff,0x90,0xd6,0xf0,0x08,0x8f,0x7e,0xb8,0x97,0xc5,
617 0xab,0x37,0x2c,0xe4,0x7a,0xe4,0xa8,0x77,0xe3,0x76,0xa0,0x00,0xd0,0x6a,0x3f,0xc1,
618 0xd2,0x36,0x8a,0xe0,0x41,0x12,0xa8,0x35,0x6a,0x1b,0x6a,0xdb,0x35,0xe1,0xd4,0x1c,
619 0x04,0xe4,0xa8,0x45,0x04,0xc8,0x5a,0x33,0x38,0x6e,0x4d,0x1c,0x0d,0x62,0xb7,0x0a,
620 0xa2,0x8c,0xd3,0xd5,0x54,0x3f,0x46,0xcd,0x1c,0x55,0xa6,0x70,0xdb,0x12,0x3a,0x87,
621 0x93,0x75,0x9f,0xa7,0xd2,0xa0 };
622 static const BYTE rootcertauthority[] = {
623 0x30,0x82,0x05,0x99,0x30,0x82,0x03,0x81,0xa0,0x03,0x02,0x01,0x02,0x02,0x10,0x79,
624 0xad,0x16,0xa1,0x4a,0xa0,0xa5,0xad,0x4c,0x73,0x58,0xf4,0x07,0x13,0x2e,0x65,0x30,
625 0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x30,0x5f,
626 0x31,0x13,0x30,0x11,0x06,0x0a,0x09,0x92,0x26,0x89,0x93,0xf2,0x2c,0x64,0x01,0x19,
627 0x16,0x03,0x63,0x6f,0x6d,0x31,0x19,0x30,0x17,0x06,0x0a,0x09,0x92,0x26,0x89,0x93,
628 0xf2,0x2c,0x64,0x01,0x19,0x16,0x09,0x6d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,
629 0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x13,0x24,0x4d,0x69,0x63,0x72,0x6f,
630 0x73,0x6f,0x66,0x74,0x20,0x52,0x6f,0x6f,0x74,0x20,0x43,0x65,0x72,0x74,0x69,0x66,
631 0x69,0x63,0x61,0x74,0x65,0x20,0x41,0x75,0x74,0x68,0x6f,0x72,0x69,0x74,0x79,0x30,
632 0x1e,0x17,0x0d,0x30,0x31,0x30,0x35,0x30,0x39,0x32,0x33,0x31,0x39,0x32,0x32,0x5a,
633 0x17,0x0d,0x32,0x31,0x30,0x35,0x30,0x39,0x32,0x33,0x32,0x38,0x31,0x33,0x5a,0x30,
634 0x5f,0x31,0x13,0x30,0x11,0x06,0x0a,0x09,0x92,0x26,0x89,0x93,0xf2,0x2c,0x64,0x01,
635 0x19,0x16,0x03,0x63,0x6f,0x6d,0x31,0x19,0x30,0x17,0x06,0x0a,0x09,0x92,0x26,0x89,
636 0x93,0xf2,0x2c,0x64,0x01,0x19,0x16,0x09,0x6d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,
637 0x74,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x13,0x24,0x4d,0x69,0x63,0x72,
638 0x6f,0x73,0x6f,0x66,0x74,0x20,0x52,0x6f,0x6f,0x74,0x20,0x43,0x65,0x72,0x74,0x69,
639 0x66,0x69,0x63,0x61,0x74,0x65,0x20,0x41,0x75,0x74,0x68,0x6f,0x72,0x69,0x74,0x79,
640 0x30,0x82,0x02,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
641 0x01,0x05,0x00,0x03,0x82,0x02,0x0f,0x00,0x30,0x82,0x02,0x0a,0x02,0x82,0x02,0x01,
642 0x00,0xf3,0x5d,0xfa,0x80,0x67,0xd4,0x5a,0xa7,0xa9,0x0c,0x2c,0x90,0x20,0xd0,0x35,
643 0x08,0x3c,0x75,0x84,0xcd,0xb7,0x07,0x89,0x9c,0x89,0xda,0xde,0xce,0xc3,0x60,0xfa,
644 0x91,0x68,0x5a,0x9e,0x94,0x71,0x29,0x18,0x76,0x7c,0xc2,0xe0,0xc8,0x25,0x76,0x94,
645 0x0e,0x58,0xfa,0x04,0x34,0x36,0xe6,0xdf,0xaf,0xf7,0x80,0xba,0xe9,0x58,0x0b,0x2b,
646 0x93,0xe5,0x9d,0x05,0xe3,0x77,0x22,0x91,0xf7,0x34,0x64,0x3c,0x22,0x91,0x1d,0x5e,
647 0xe1,0x09,0x90,0xbc,0x14,0xfe,0xfc,0x75,0x58,0x19,0xe1,0x79,0xb7,0x07,0x92,0xa3,
648 0xae,0x88,0x59,0x08,0xd8,0x9f,0x07,0xca,0x03,0x58,0xfc,0x68,0x29,0x6d,0x32,0xd7,
649 0xd2,0xa8,0xcb,0x4b,0xfc,0xe1,0x0b,0x48,0x32,0x4f,0xe6,0xeb,0xb8,0xad,0x4f,0xe4,
650 0x5c,0x6f,0x13,0x94,0x99,0xdb,0x95,0xd5,0x75,0xdb,0xa8,0x1a,0xb7,0x94,0x91,0xb4,
651 0x77,0x5b,0xf5,0x48,0x0c,0x8f,0x6a,0x79,0x7d,0x14,0x70,0x04,0x7d,0x6d,0xaf,0x90,
652 0xf5,0xda,0x70,0xd8,0x47,0xb7,0xbf,0x9b,0x2f,0x6c,0xe7,0x05,0xb7,0xe1,0x11,0x60,
653 0xac,0x79,0x91,0x14,0x7c,0xc5,0xd6,0xa6,0xe4,0xe1,0x7e,0xd5,0xc3,0x7e,0xe5,0x92,
654 0xd2,0x3c,0x00,0xb5,0x36,0x82,0xde,0x79,0xe1,0x6d,0xf3,0xb5,0x6e,0xf8,0x9f,0x33,
655 0xc9,0xcb,0x52,0x7d,0x73,0x98,0x36,0xdb,0x8b,0xa1,0x6b,0xa2,0x95,0x97,0x9b,0xa3,
656 0xde,0xc2,0x4d,0x26,0xff,0x06,0x96,0x67,0x25,0x06,0xc8,0xe7,0xac,0xe4,0xee,0x12,
657 0x33,0x95,0x31,0x99,0xc8,0x35,0x08,0x4e,0x34,0xca,0x79,0x53,0xd5,0xb5,0xbe,0x63,
658 0x32,0x59,0x40,0x36,0xc0,0xa5,0x4e,0x04,0x4d,0x3d,0xdb,0x5b,0x07,0x33,0xe4,0x58,
659 0xbf,0xef,0x3f,0x53,0x64,0xd8,0x42,0x59,0x35,0x57,0xfd,0x0f,0x45,0x7c,0x24,0x04,
660 0x4d,0x9e,0xd6,0x38,0x74,0x11,0x97,0x22,0x90,0xce,0x68,0x44,0x74,0x92,0x6f,0xd5,
661 0x4b,0x6f,0xb0,0x86,0xe3,0xc7,0x36,0x42,0xa0,0xd0,0xfc,0xc1,0xc0,0x5a,0xf9,0xa3,
662 0x61,0xb9,0x30,0x47,0x71,0x96,0x0a,0x16,0xb0,0x91,0xc0,0x42,0x95,0xef,0x10,0x7f,
663 0x28,0x6a,0xe3,0x2a,0x1f,0xb1,0xe4,0xcd,0x03,0x3f,0x77,0x71,0x04,0xc7,0x20,0xfc,
664 0x49,0x0f,0x1d,0x45,0x88,0xa4,0xd7,0xcb,0x7e,0x88,0xad,0x8e,0x2d,0xec,0x45,0xdb,
665 0xc4,0x51,0x04,0xc9,0x2a,0xfc,0xec,0x86,0x9e,0x9a,0x11,0x97,0x5b,0xde,0xce,0x53,
666 0x88,0xe6,0xe2,0xb7,0xfd,0xac,0x95,0xc2,0x28,0x40,0xdb,0xef,0x04,0x90,0xdf,0x81,
667 0x33,0x39,0xd9,0xb2,0x45,0xa5,0x23,0x87,0x06,0xa5,0x55,0x89,0x31,0xbb,0x06,0x2d,
668 0x60,0x0e,0x41,0x18,0x7d,0x1f,0x2e,0xb5,0x97,0xcb,0x11,0xeb,0x15,0xd5,0x24,0xa5,
669 0x94,0xef,0x15,0x14,0x89,0xfd,0x4b,0x73,0xfa,0x32,0x5b,0xfc,0xd1,0x33,0x00,0xf9,
670 0x59,0x62,0x70,0x07,0x32,0xea,0x2e,0xab,0x40,0x2d,0x7b,0xca,0xdd,0x21,0x67,0x1b,
671 0x30,0x99,0x8f,0x16,0xaa,0x23,0xa8,0x41,0xd1,0xb0,0x6e,0x11,0x9b,0x36,0xc4,0xde,
672 0x40,0x74,0x9c,0xe1,0x58,0x65,0xc1,0x60,0x1e,0x7a,0x5b,0x38,0xc8,0x8f,0xbb,0x04,
673 0x26,0x7c,0xd4,0x16,0x40,0xe5,0xb6,0x6b,0x6c,0xaa,0x86,0xfd,0x00,0xbf,0xce,0xc1,
674 0x35,0x02,0x03,0x01,0x00,0x01,0xa3,0x51,0x30,0x4f,0x30,0x0b,0x06,0x03,0x55,0x1d,
675 0x0f,0x04,0x04,0x03,0x02,0x01,0xc6,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
676 0xff,0x04,0x05,0x30,0x03,0x01,0x01,0xff,0x30,0x1d,0x06,0x03,0x55,0x1d,0x0e,0x04,
677 0x16,0x04,0x14,0x0e,0xac,0x82,0x60,0x40,0x56,0x27,0x97,0xe5,0x25,0x13,0xfc,0x2a,
678 0xe1,0x0a,0x53,0x95,0x59,0xe4,0xa4,0x30,0x10,0x06,0x09,0x2b,0x06,0x01,0x04,0x01,
679 0x82,0x37,0x15,0x01,0x04,0x03,0x02,0x01,0x00,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
680 0x86,0xf7,0x0d,0x01,0x01,0x05,0x05,0x00,0x03,0x82,0x02,0x01,0x00,0xc5,0x11,0x4d,
681 0x03,0x3a,0x60,0xdd,0x5d,0x52,0x11,0x77,0x8f,0xb2,0xbb,0x36,0xc8,0xb2,0x05,0xbf,
682 0xb4,0xb7,0xa8,0xd8,0x20,0x9d,0x5c,0x13,0x03,0xb6,0x1c,0x22,0xfa,0x06,0x13,0x35,
683 0xb6,0xc8,0x63,0xd4,0x9a,0x47,0x6f,0x26,0x57,0xd2,0x55,0xf1,0x04,0xb1,0x26,0x5f,
684 0xd6,0xa9,0x50,0x68,0xa0,0xbc,0xd2,0xb8,0x6e,0xcc,0xc3,0xe9,0xac,0xdf,0x19,0xcd,
685 0x78,0xac,0x59,0x74,0xac,0x66,0x34,0x36,0xc4,0x1b,0x3e,0x6c,0x38,0x4c,0x33,0x0e,
686 0x30,0x12,0x0d,0xa3,0x26,0xfe,0x51,0x53,0x00,0xff,0xaf,0x5a,0x4e,0x84,0x0d,0x0f,
687 0x1f,0xe4,0x6d,0x05,0x2e,0x4e,0x85,0x4b,0x8d,0x6c,0x33,0x6f,0x54,0xd2,0x64,0xab,
688 0xbf,0x50,0xaf,0x7d,0x7a,0x39,0xa0,0x37,0xed,0x63,0x03,0x0f,0xfc,0x13,0x06,0xce,
689 0x16,0x36,0xd4,0x54,0x3b,0x95,0x1b,0x51,0x62,0x3a,0xe5,0x4d,0x17,0xd4,0x05,0x39,
690 0x92,0x9a,0x27,0xa8,0x5b,0xaa,0xbd,0xec,0xbb,0xbe,0xe3,0x20,0x89,0x60,0x71,0x6c,
691 0x56,0xb3,0xa5,0x13,0xd0,0x6d,0x0e,0x23,0x7e,0x95,0x03,0xed,0x68,0x3d,0xf2,0xd8,
692 0x63,0xb8,0x6b,0x4d,0xb6,0xe8,0x30,0xb5,0xe1,0xca,0x94,0x4b,0xf7,0xa2,0xaa,0x5d,
693 0x99,0x30,0xb2,0x3d,0xa7,0xc2,0x51,0x6c,0x28,0x20,0x01,0x24,0x27,0x2b,0x4b,0x00,
694 0xb7,0x9d,0x11,0x6b,0x70,0xbe,0xb2,0x10,0x82,0xbc,0x0c,0x9b,0x68,0xd0,0x8d,0x3b,
695 0x24,0x87,0xaa,0x99,0x28,0x72,0x9d,0x33,0x5f,0x59,0x90,0xbd,0xf5,0xde,0x93,0x9e,
696 0x3a,0x62,0x5a,0x34,0x39,0xe2,0x88,0x55,0x1d,0xb9,0x06,0xb0,0xc1,0x89,0x6b,0x2d,
697 0xd7,0x69,0xc3,0x19,0x12,0x36,0x84,0xd0,0xc9,0xa0,0xda,0xff,0x2f,0x69,0x78,0xb2,
698 0xe5,0x7a,0xda,0xeb,0xd7,0x0c,0xc0,0xf7,0xbd,0x63,0x17,0xb8,0x39,0x13,0x38,0xa2,
699 0x36,0x5b,0x7b,0xf2,0x85,0x56,0x6a,0x1d,0x64,0x62,0xc1,0x38,0xe2,0xaa,0xbf,0x51,
700 0x66,0xa2,0x94,0xf5,0x12,0x9c,0x66,0x22,0x10,0x6b,0xf2,0xb7,0x30,0x92,0x2d,0xf2,
701 0x29,0xf0,0x3d,0x3b,0x14,0x43,0x68,0xa2,0xf1,0x9c,0x29,0x37,0xcb,0xce,0x38,0x20,
702 0x25,0x6d,0x7c,0x67,0xf3,0x7e,0x24,0x12,0x24,0x03,0x08,0x81,0x47,0xec,0xa5,0x9e,
703 0x97,0xf5,0x18,0xd7,0xcf,0xbb,0xd5,0xef,0x76,0x96,0xef,0xfd,0xce,0xdb,0x56,0x9d,
704 0x95,0xa0,0x42,0xf9,0x97,0x58,0xe1,0xd7,0x31,0x22,0xd3,0x5f,0x59,0xe6,0x3e,0x6e,
705 0x22,0x00,0xea,0x43,0x84,0xb6,0x25,0xdb,0xd9,0xf3,0x08,0x56,0x68,0xc0,0x64,0x6b,
706 0x1d,0x7c,0xec,0xb6,0x93,0xa2,0x62,0x57,0x6e,0x2e,0xd8,0xe7,0x58,0x8f,0xc4,0x31,
707 0x49,0x26,0xdd,0xde,0x29,0x35,0x87,0xf5,0x30,0x71,0x70,0x5b,0x14,0x3c,0x69,0xbd,
708 0x89,0x12,0x7d,0xeb,0x2e,0xa3,0xfe,0xd8,0x7f,0x9e,0x82,0x5a,0x52,0x0a,0x2b,0xc1,
709 0x43,0x2b,0xd9,0x30,0x88,0x9f,0xc8,0x10,0xfb,0x89,0x8d,0xe6,0xa1,0x85,0x75,0x33,
710 0x7e,0x6c,0x9e,0xdb,0x73,0x13,0x64,0x62,0x69,0xa5,0x2f,0x7d,0xca,0x96,0x6d,0x9f,
711 0xf8,0x04,0x4d,0x30,0x92,0x3d,0x6e,0x21,0x14,0x21,0xc9,0x3d,0xe0,0xc3,0xfd,0x8a,
712 0x6b,0x9d,0x4a,0xfd,0xd1,0xa1,0x9d,0x99,0x43,0x77,0x3f,0xb0,0xda };
713
714 static const struct CONST_BLOB {
715     const BYTE *pb;
716     DWORD       cb;
717 } msRootCerts[] = {
718     { authenticode, sizeof(authenticode) },
719     { rootauthority, sizeof(rootauthority) },
720     { rootcertauthority, sizeof(rootcertauthority) },
721 };
722
723 static void add_ms_root_certs(HCERTSTORE to)
724 {
725     DWORD i;
726
727     TRACE("\n");
728
729     for (i = 0; i < sizeof(msRootCerts) / sizeof(msRootCerts[0]); i++)
730         if (!CertAddEncodedCertificateToStore(to, X509_ASN_ENCODING,
731          msRootCerts[i].pb, msRootCerts[i].cb, CERT_STORE_ADD_NEW, NULL))
732             WARN("adding root cert %d failed: %08x\n", i, GetLastError());
733 }
734
735 /* Reads certificates from the list of known locations into store.  Stops when
736  * any location contains any certificates, to prevent spending unnecessary time
737  * adding redundant certificates, e.g. when both a certificate bundle and
738  * individual certificates exist in the same directory.
739  */
740 static void read_trusted_roots_from_known_locations(HCERTSTORE store)
741 {
742     HCERTSTORE from = CertOpenStore(CERT_STORE_PROV_MEMORY,
743      X509_ASN_ENCODING, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
744
745     if (from)
746     {
747         DWORD i;
748         BOOL ret = FALSE;
749
750 #ifdef HAVE_SECURITY_SECURITY_H
751         OSStatus status;
752         CFArrayRef rootCerts;
753
754         status = SecTrustCopyAnchorCertificates(&rootCerts);
755         if (status == noErr)
756         {
757             int i;
758             for (i = 0; i < CFArrayGetCount(rootCerts); i++)
759             {
760                 SecCertificateRef cert = (SecCertificateRef)CFArrayGetValueAtIndex(rootCerts, i);
761                 CFDataRef certData;
762                 if ((status = SecKeychainItemExport(cert, kSecFormatX509Cert, 0, NULL, &certData)) == noErr)
763                 {
764                     if (CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING,
765                             CFDataGetBytePtr(certData), CFDataGetLength(certData),
766                             CERT_STORE_ADD_NEW, NULL))
767                         ret = TRUE;
768                     else
769                         WARN("adding root cert %d failed: %08x\n", i, GetLastError());
770                     CFRelease(certData);
771                 }
772                 else
773                     WARN("could not export certificate %d to X509 format: 0x%08x\n", i, (unsigned int)status);
774             }
775             CFRelease(rootCerts);
776         }
777 #endif
778
779         for (i = 0; !ret &&
780          i < sizeof(CRYPT_knownLocations) / sizeof(CRYPT_knownLocations[0]);
781          i++)
782             ret = import_certs_from_path(CRYPT_knownLocations[i], from, TRUE);
783         check_and_store_certs(from, store);
784     }
785     CertCloseStore(from, 0);
786 }
787
788 static HCERTSTORE create_root_store(void)
789 {
790     HCERTSTORE root = NULL;
791     HCERTSTORE memStore = CertOpenStore(CERT_STORE_PROV_MEMORY,
792      X509_ASN_ENCODING, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
793
794     if (memStore)
795     {
796         CERT_STORE_PROV_INFO provInfo = {
797          sizeof(CERT_STORE_PROV_INFO),
798          sizeof(rootProvFuncs) / sizeof(rootProvFuncs[0]),
799          rootProvFuncs,
800          NULL,
801          0,
802          NULL
803         };
804
805         read_trusted_roots_from_known_locations(memStore);
806         add_ms_root_certs(memStore);
807         root = CRYPT_ProvCreateStore(0, memStore, &provInfo);
808     }
809     TRACE("returning %p\n", root);
810     return root;
811 }
812
813 static PWINECRYPT_CERTSTORE CRYPT_rootStore;
814
815 PWINECRYPT_CERTSTORE CRYPT_RootOpenStore(HCRYPTPROV hCryptProv, DWORD dwFlags)
816 {
817     TRACE("(%ld, %08x)\n", hCryptProv, dwFlags);
818
819     if (dwFlags & CERT_STORE_DELETE_FLAG)
820     {
821         WARN("root store can't be deleted\n");
822         SetLastError(ERROR_ACCESS_DENIED);
823         return NULL;
824     }
825     if (!CRYPT_rootStore)
826     {
827         HCERTSTORE root = create_root_store();
828
829         InterlockedCompareExchangePointer((PVOID *)&CRYPT_rootStore, root,
830          NULL);
831         if (CRYPT_rootStore != root)
832             CertCloseStore(root, 0);
833     }
834     CertDuplicateStore(CRYPT_rootStore);
835     return CRYPT_rootStore;
836 }
837
838 void root_store_free(void)
839 {
840     CertCloseStore(CRYPT_rootStore, 0);
841 }